From 77dc2c01beb0694ea58f8c0d67ce442f85c41f44 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 3 May 2022 10:03:58 +0200 Subject: [PATCH 01/56] fix: update metadata for 3.0 --- .../TestBundle/Entity/AbsoluteUrlDummy.php | 8 +-- .../Entity/AbsoluteUrlRelationDummy.php | 7 +-- .../TestBundle/Entity/AbstractDummy.php | 21 ++++---- .../TestBundle/Entity/AbstractUser.php | 15 ++---- tests/Fixtures/TestBundle/Entity/Address.php | 5 +- tests/Fixtures/TestBundle/Entity/Answer.php | 21 ++++---- .../Entity/ArrayFilterValidator.php | 10 +--- tests/Fixtures/TestBundle/Entity/Book.php | 11 ++-- .../TestBundle/Entity/CircularReference.php | 7 +-- .../TestBundle/Entity/CompositeItem.php | 6 +-- .../TestBundle/Entity/CompositeLabel.php | 5 +- .../Entity/CompositePrimitiveItem.php | 6 +-- .../TestBundle/Entity/CompositeRelation.php | 6 +-- .../TestBundle/Entity/ConcreteDummy.php | 5 +- .../TestBundle/Entity/ContainNonResource.php | 14 +---- tests/Fixtures/TestBundle/Entity/Content.php | 21 ++------ .../TestBundle/Entity/ConvertedBoolean.php | 7 ++- .../TestBundle/Entity/ConvertedDate.php | 7 ++- .../TestBundle/Entity/ConvertedInteger.php | 11 ++-- .../TestBundle/Entity/ConvertedOwner.php | 7 ++- .../TestBundle/Entity/ConvertedRelated.php | 5 +- .../TestBundle/Entity/ConvertedString.php | 7 ++- .../TestBundle/Entity/CustomActionDummy.php | 19 ++----- .../Entity/CustomGeneratedIdentifier.php | 4 +- .../Entity/CustomIdentifierDummy.php | 5 +- .../Entity/CustomMultipleIdentifierDummy.php | 7 ++- .../Entity/CustomNormalizedDummy.php | 10 +--- .../Entity/CustomWritableIdentifierDummy.php | 5 +- tests/Fixtures/TestBundle/Entity/Customer.php | 6 +-- .../TestBundle/Entity/DeprecatedResource.php | 5 +- .../Entity/DisableItemOperation.php | 18 ++----- tests/Fixtures/TestBundle/Entity/Dummy.php | 43 +++------------ .../TestBundle/Entity/DummyAggregateOffer.php | 19 +++---- .../TestBundle/Entity/DummyBoolean.php | 5 +- tests/Fixtures/TestBundle/Entity/DummyCar.php | 34 +++++------- .../TestBundle/Entity/DummyCarColor.php | 6 +-- .../TestBundle/Entity/DummyCustomFormat.php | 5 +- .../TestBundle/Entity/DummyCustomMutation.php | 42 ++------------- .../TestBundle/Entity/DummyCustomQuery.php | 53 ++----------------- .../Fixtures/TestBundle/Entity/DummyDate.php | 17 ++---- ...ummyDifferentGraphQlSerializationGroup.php | 14 ++--- .../TestBundle/Entity/DummyDtoCustom.php | 15 +++--- .../TestBundle/Entity/DummyDtoInputOutput.php | 9 +--- .../TestBundle/Entity/DummyDtoNoInput.php | 35 +++--------- .../TestBundle/Entity/DummyDtoNoOutput.php | 13 +---- .../DummyDtoOutputFallbackToSameClass.php | 7 +-- .../Entity/DummyDtoOutputSameClass.php | 7 +-- .../Entity/DummyEntityWithConstructor.php | 19 +++---- .../Entity/DummyForAdditionalFields.php | 4 +- .../Entity/DummyForAdditionalFieldsInput.php | 7 +-- .../TestBundle/Entity/DummyFriend.php | 7 ++- .../Fixtures/TestBundle/Entity/DummyGroup.php | 33 ++---------- .../TestBundle/Entity/DummyImmutableDate.php | 8 ++- .../TestBundle/Entity/DummyMercure.php | 7 +-- .../TestBundle/Entity/DummyNoGetOperation.php | 12 ++--- .../Fixtures/TestBundle/Entity/DummyOffer.php | 13 +++-- .../TestBundle/Entity/DummyPassenger.php | 5 +- .../Fixtures/TestBundle/Entity/DummyPhp8.php | 17 +++--- .../TestBundle/Entity/DummyProduct.php | 22 +++----- .../TestBundle/Entity/DummyProperty.php | 34 ++---------- .../Entity/DummyPropertyWithDefaultValue.php | 10 +--- .../Entity/DummyTableInheritance.php | 12 ++--- .../Entity/DummyTableInheritanceChild.php | 4 +- .../DummyTableInheritanceDifferentChild.php | 4 +- .../Entity/DummyTableInheritanceRelated.php | 10 +--- .../TestBundle/Entity/DummyTravel.php | 6 +-- .../TestBundle/Entity/DummyValidation.php | 20 +++---- .../TestBundle/Entity/EmbeddedDummy.php | 17 +++--- .../TestBundle/Entity/ExternalUser.php | 4 +- .../TestBundle/Entity/FilterValidator.php | 17 +----- tests/Fixtures/TestBundle/Entity/Foo.php | 30 ++++------- tests/Fixtures/TestBundle/Entity/FooDummy.php | 15 ++---- .../TestBundle/Entity/FourthLevel.php | 15 ++++-- tests/Fixtures/TestBundle/Entity/Greeting.php | 10 ++-- .../TestBundle/Entity/InitializeInput.php | 6 +-- .../TestBundle/Entity/IriOnlyDummy.php | 11 +--- .../TestBundle/Entity/JsonldContextDummy.php | 5 +- .../TestBundle/Entity/LegacySecuredDummy.php | 30 +++-------- .../TestBundle/Entity/MaxDepthDummy.php | 13 ++--- .../TestBundle/Entity/MaxDepthEagerDummy.php | 13 ++--- .../TestBundle/Entity/MessengerWithInput.php | 7 ++- .../Entity/MessengerWithResponse.php | 6 +-- .../TestBundle/Entity/NetworkPathDummy.php | 8 +-- .../Entity/NetworkPathRelationDummy.php | 7 +-- .../TestBundle/Entity/NoCollectionDummy.php | 8 ++- .../TestBundle/Entity/NonRelationResource.php | 5 +- tests/Fixtures/TestBundle/Entity/Order.php | 11 ++-- .../Entity/OverriddenOperationDummy.php | 43 +++------------ .../Fixtures/TestBundle/Entity/PatchDummy.php | 15 +++--- .../TestBundle/Entity/PatchDummyRelation.php | 19 +++---- tests/Fixtures/TestBundle/Entity/Payment.php | 21 ++------ tests/Fixtures/TestBundle/Entity/Person.php | 10 +--- tests/Fixtures/TestBundle/Entity/Pet.php | 7 +-- .../TestBundle/Entity/PlainObjectDummy.php | 7 +-- tests/Fixtures/TestBundle/Entity/Question.php | 13 ++--- tests/Fixtures/TestBundle/Entity/RPC.php | 12 ++--- .../TestBundle/Entity/RamseyUuidDummy.php | 5 +- .../Entity/ReadableOnlyProperty.php | 5 +- .../TestBundle/Entity/RelatedDummy.php | 28 +++++----- .../Entity/RelatedNormalizedDummy.php | 10 +--- .../TestBundle/Entity/RelatedOwnedDummy.php | 13 ++--- .../TestBundle/Entity/RelatedOwningDummy.php | 14 ++--- .../TestBundle/Entity/RelatedSecuredDummy.php | 20 +++---- .../Entity/RelatedToDummyFriend.php | 14 +++-- .../Fixtures/TestBundle/Entity/Relation1.php | 5 +- .../Fixtures/TestBundle/Entity/Relation2.php | 5 +- .../Fixtures/TestBundle/Entity/Relation3.php | 5 +- .../TestBundle/Entity/RelationEmbedder.php | 28 +++------- .../TestBundle/Entity/ResourceWithBoolean.php | 5 +- .../TestBundle/Entity/ResourceWithFloat.php | 5 +- .../TestBundle/Entity/ResourceWithInteger.php | 5 +- .../TestBundle/Entity/ResourceWithString.php | 5 +- .../TestBundle/Entity/SecuredDummy.php | 45 ++++------------ tests/Fixtures/TestBundle/Entity/Site.php | 4 +- .../TestBundle/Entity/SlugChildDummy.php | 13 +++-- .../TestBundle/Entity/SlugParentDummy.php | 15 +++--- tests/Fixtures/TestBundle/Entity/SoMany.php | 15 ++---- .../TestBundle/Entity/SymfonyUuidDummy.php | 5 +- .../Fixtures/TestBundle/Entity/ThirdLevel.php | 18 +++---- .../TestBundle/Entity/TruncatedDummy.php | 6 +-- .../Entity/UpperCaseIdentifierDummy.php | 6 +-- .../TestBundle/Entity/UrlEncodedId.php | 16 ++---- tests/Fixtures/TestBundle/Entity/User.php | 41 +++----------- .../TestBundle/Entity/UserResource.php | 16 ++---- .../TestBundle/Entity/UuidIdentifierDummy.php | 5 +- .../Fixtures/TestBundle/Entity/VoDummyCar.php | 18 ++----- .../TestBundle/Entity/VoDummyDriver.php | 6 +-- .../TestBundle/Entity/VoDummyInspection.php | 14 +---- .../Entity/VoDummyInsuranceCompany.php | 5 +- .../TestBundle/Entity/VoidPayment.php | 6 +-- .../TestBundle/Entity/WithJsonDummy.php | 5 +- .../Fixtures/TestBundle/Entity/WritableId.php | 6 +-- .../Fixtures/TestBundle/Model/MediaObject.php | 23 ++------ .../TestBundle/Model/ProductInterface.php | 15 +----- .../TestBundle/Model/SerializableResource.php | 7 +-- .../TestBundle/Model/TaxonInterface.php | 15 +----- 136 files changed, 532 insertions(+), 1219 deletions(-) diff --git a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php index a4c2bc4e166..8104f04be7a 100644 --- a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php @@ -14,13 +14,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::ABS_URL) * @ORM\Entity */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] +#[ApiResource(uriTemplate: '/absolute_url_relation_dummies/{id}/absolute_url_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\AbsoluteUrlRelationDummy::class, identifiers: ['id'], toProperty: 'absoluteUrlRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::ABS_URL, operations: [new GetCollection()])] class AbsoluteUrlDummy { /** @@ -29,7 +32,6 @@ class AbsoluteUrlDummy * @ORM\Column(type="integer") */ private $id; - /** * @ORM\ManyToOne(targetEntity="AbsoluteUrlRelationDummy", inversedBy="absoluteUrlDummies") */ diff --git a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php index e689c5efd39..b9a6447317c 100644 --- a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php @@ -14,15 +14,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::ABS_URL) * @ORM\Entity */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] class AbsoluteUrlRelationDummy { /** @@ -31,10 +30,8 @@ class AbsoluteUrlRelationDummy * @ORM\Column(type="integer") */ private $id; - /** * @ORM\OneToMany(targetEntity="AbsoluteUrlDummy", mappedBy="absoluteUrlRelationDummy") - * @ApiSubresource */ public $absoluteUrlDummies; diff --git a/tests/Fixtures/TestBundle/Entity/AbstractDummy.php b/tests/Fixtures/TestBundle/Entity/AbstractDummy.php index 5bd9d03f0e5..9fe16ed35a3 100644 --- a/tests/Fixtures/TestBundle/Entity/AbstractDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbstractDummy.php @@ -14,7 +14,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -22,17 +27,12 @@ * Abstract Dummy. * * @author Jérémy Derussé - * - * @ApiResource( - * collectionOperations={"get", "post"}, - * itemOperations={"get", "put", "delete"}, - * attributes={"filters"={"my_dummy.search", "my_dummy.order", "my_dummy.date"}} - * ) * @ORM\Entity - * @ORM\InheritanceType("SINGLE_TABLE") - * @ORM\DiscriminatorColumn(name="discr", type="string", length=16) - * @ORM\DiscriminatorMap({"concrete"="ConcreteDummy"}) + * @ORM\InheritanceType ("SINGLE_TABLE") + * @ORM\DiscriminatorColumn (name="discr", type="string", length=16) + * @ORM\DiscriminatorMap ({"concrete"="ConcreteDummy"}) */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new GetCollection(), new Post()], filters: ['my_dummy.search', 'my_dummy.order', 'my_dummy.date'])] abstract class AbstractDummy { /** @@ -43,7 +43,6 @@ abstract class AbstractDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Entity/AbstractUser.php b/tests/Fixtures/TestBundle/Entity/AbstractUser.php index d454c320fd6..76ed5795795 100644 --- a/tests/Fixtures/TestBundle/Entity/AbstractUser.php +++ b/tests/Fixtures/TestBundle/Entity/AbstractUser.php @@ -13,21 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * @ORM\InheritanceType("JOINED") - * @ApiResource( - * collectionOperations={ - * "get"={"path"="/custom_users"} - * }, - * itemOperations={ - * "get"={"path"="/custom_users/{id}"} - * } - * ) + * @ORM\InheritanceType ("JOINED") */ +#[ApiResource(operations: [new Get(uriTemplate: '/custom_users/{id}'), new GetCollection(uriTemplate: '/custom_users')])] abstract class AbstractUser { /** diff --git a/tests/Fixtures/TestBundle/Entity/Address.php b/tests/Fixtures/TestBundle/Entity/Address.php index 2086b7ae979..6638c8f97e8 100644 --- a/tests/Fixtures/TestBundle/Entity/Address.php +++ b/tests/Fixtures/TestBundle/Entity/Address.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class Address { /** @@ -32,7 +32,6 @@ class Address * @Groups({"order_read"}) */ private $id; - /** * @ORM\Column(type="string") * @Groups({"order_read"}) diff --git a/tests/Fixtures/TestBundle/Entity/Answer.php b/tests/Fixtures/TestBundle/Entity/Answer.php index 68425c5f247..9903f6abb9f 100644 --- a/tests/Fixtures/TestBundle/Entity/Answer.php +++ b/tests/Fixtures/TestBundle/Entity/Answer.php @@ -13,8 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -24,10 +29,10 @@ * Answer. * * @ORM\Entity - * @ApiResource(collectionOperations={ - * "get_subresource_answer"={"method"="GET", "normalization_context"={"groups"={"foobar"}}} - * }) */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(normalizationContext: ['groups' => ['foobar']])])] +#[ApiResource(uriTemplate: '/answers/{id}/related_questions/{relatedQuestions}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], toProperty: 'answer'), 'relatedQuestions' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/questions/{id}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] class Answer { /** @@ -37,24 +42,20 @@ class Answer * @Serializer\Groups({"foobar"}) */ private $id; - /** * @ORM\Column(nullable=false) * @Serializer\Groups({"foobar"}) */ private $content; - /** * @ORM\OneToOne(targetEntity="Question", mappedBy="answer") * @Serializer\Groups({"foobar"}) */ private $question; - /** - * @var Collection + * @var \Collection * @ORM\OneToMany(targetEntity="Question", mappedBy="answer") * @Serializer\Groups({"foobar"}) - * @ApiSubresource */ private $relatedQuestions; diff --git a/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php b/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php index a78a881f78e..3e576798ec4 100644 --- a/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php +++ b/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayRequiredFilter; use Doctrine\ORM\Mapping as ORM; @@ -22,14 +22,9 @@ * Filter Validator entity. * * @author Julien Deniau - * - * @ApiResource(attributes={ - * "filters"={ - * ArrayRequiredFilter::class - * } - * }) * @ORM\Entity */ +#[ApiResource(filters: [ArrayRequiredFilter::class])] class ArrayFilterValidator { /** @@ -40,7 +35,6 @@ class ArrayFilterValidator * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string A name * diff --git a/tests/Fixtures/TestBundle/Entity/Book.php b/tests/Fixtures/TestBundle/Entity/Book.php index 9ba7911a638..dcce5c39915 100644 --- a/tests/Fixtures/TestBundle/Entity/Book.php +++ b/tests/Fixtures/TestBundle/Entity/Book.php @@ -13,20 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Book. * * @author Antoine Bluchet - * - * @ApiResource(collectionOperations={}, itemOperations={ - * "get", - * "get_by_isbn"={"method"="GET", "path"="/books/by_isbn/{isbn}.{_format}", "requirements"={"isbn"=".+"}, "identifiers"="isbn"} - * }) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Get(uriTemplate: '/books/by_isbn/{isbn}.{_format}', requirements: ['isbn' => '.+'], uriVariables: 'isbn')])] class Book { /** @@ -35,12 +32,10 @@ class Book * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @ORM\Column */ public $name; - /** * @ORM\Column(unique=true) */ diff --git a/tests/Fixtures/TestBundle/Entity/CircularReference.php b/tests/Fixtures/TestBundle/Entity/CircularReference.php index 244d65a9afa..75374e97114 100644 --- a/tests/Fixtures/TestBundle/Entity/CircularReference.php +++ b/tests/Fixtures/TestBundle/Entity/CircularReference.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,10 +22,9 @@ * Circular Reference. * * @author Kévin Dunglas - * - * @ApiResource(attributes={"normalization_context"={"groups"={"circular"}}}) * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['circular']])] class CircularReference { /** @@ -34,14 +33,12 @@ class CircularReference * @ORM\GeneratedValue(strategy="AUTO") */ public $id; - /** * @ORM\ManyToOne(targetEntity="CircularReference", inversedBy="children") * * @Groups({"circular"}) */ public $parent; - /** * @ORM\OneToMany(targetEntity="CircularReference", mappedBy="parent") * diff --git a/tests/Fixtures/TestBundle/Entity/CompositeItem.php b/tests/Fixtures/TestBundle/Entity/CompositeItem.php index 6e35171bee7..f20fc8b4849 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeItem.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeItem.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,9 +21,9 @@ /** * Composite Item. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class CompositeItem { /** @@ -32,13 +32,11 @@ class CompositeItem * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @ORM\Column(type="string", nullable=true) * @Groups({"default"}) */ private $field1; - /** * @ORM\OneToMany(targetEntity="CompositeRelation", mappedBy="compositeItem", fetch="EAGER") * @Groups({"default"}) diff --git a/tests/Fixtures/TestBundle/Entity/CompositeLabel.php b/tests/Fixtures/TestBundle/Entity/CompositeLabel.php index 681c6edfb2f..d4f55e7d5b0 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeLabel.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeLabel.php @@ -13,16 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Label. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class CompositeLabel { /** @@ -31,7 +31,6 @@ class CompositeLabel * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @ORM\Column(type="string", nullable=true) * @Groups({"default"}) diff --git a/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php b/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php index e3cce5ba0e1..56cea9e5271 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php +++ b/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Composite Primitive Item. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class CompositePrimitiveItem { /** @@ -29,13 +29,11 @@ class CompositePrimitiveItem * @ORM\Column(type="string") */ private $name; - /** * @ORM\Id * @ORM\Column(type="integer") */ private $year; - /** * @ORM\Column(type="text") */ diff --git a/tests/Fixtures/TestBundle/Entity/CompositeRelation.php b/tests/Fixtures/TestBundle/Entity/CompositeRelation.php index c768bdcbc1b..170e168fc6c 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeRelation.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeRelation.php @@ -13,16 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Relation. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class CompositeRelation { /** @@ -30,7 +30,6 @@ class CompositeRelation * @Groups({"default"}) */ private $value; - /** * @ORM\Id * @ORM\ManyToOne(targetEntity="CompositeItem", inversedBy="compositeValues") @@ -38,7 +37,6 @@ class CompositeRelation * @Groups({"default"}) */ private $compositeItem; - /** * @ORM\Id * @ORM\ManyToOne(targetEntity="CompositeLabel") diff --git a/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php b/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php index e37ccc48d58..2ea8695b5ed 100644 --- a/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php +++ b/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -21,10 +21,9 @@ * Concrete Dummy. * * @author Jérémy Derusse - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class ConcreteDummy extends AbstractDummy { /** diff --git a/tests/Fixtures/TestBundle/Entity/ContainNonResource.php b/tests/Fixtures/TestBundle/Entity/ContainNonResource.php index a6c2dd5198a..6f6e8421ed3 100644 --- a/tests/Fixtures/TestBundle/Entity/ContainNonResource.php +++ b/tests/Fixtures/TestBundle/Entity/ContainNonResource.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\NotAResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -23,17 +23,9 @@ * * @ORM\Entity * - * @ApiResource( - * attributes={ - * "filters"={"my_dummy.property"} - * }, - * normalizationContext={ - * "groups"={"contain_non_resource"} - * } - * ) - * * @author Kévin Dunglas */ +#[ApiResource(filters: ['my_dummy.property'], normalizationContext: ['groups' => ['contain_non_resource']])] class ContainNonResource { /** @@ -44,14 +36,12 @@ class ContainNonResource * @Groups("contain_non_resource") */ public $id; - /** * @var ContainNonResource * * @Groups("contain_non_resource") */ public $nested; - /** * @var NotAResource * diff --git a/tests/Fixtures/TestBundle/Entity/Content.php b/tests/Fixtures/TestBundle/Entity/Content.php index 5edf39c6623..d385f5035c5 100644 --- a/tests/Fixtures/TestBundle/Entity/Content.php +++ b/tests/Fixtures/TestBundle/Entity/Content.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use ApiPlatform\Tests\Fixtures\TestBundle\Enum\ContentStatus; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -21,14 +22,9 @@ use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource( - * normalizationContext={ - * "groups"={"get_content"}, - * }, - * ) - * * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['get_content']])] class Content implements \JsonSerializable { /** @@ -39,14 +35,12 @@ class Content implements \JsonSerializable * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * * @ORM\Column(type="string") */ private $contentType; - /** * @var Collection * @@ -60,7 +54,6 @@ class Content implements \JsonSerializable * @ORM\OrderBy({"id"="ASC"}) */ private $fields; - /** * @var string * @@ -113,7 +106,6 @@ public function addField(Field $field): void if ($this->hasField($field->getName())) { throw new \InvalidArgumentException(sprintf("Content already has '%s' field", $field->getName())); } - $this->fields[$field->getName()] = $field; $field->setContent($this); } @@ -121,7 +113,6 @@ public function addField(Field $field): void public function removeField(Field $field): void { unset($this->fields[$field->getName()]); - // set the owning side to null (unless already changed) if ($field->getContent() === $this) { $field->setContent(null); @@ -157,10 +148,6 @@ public function getStatus(): ContentStatus #[\ReturnTypeWillChange] public function jsonSerialize() { - return [ - 'id' => $this->id, - 'contentType' => $this->contentType, - 'fields' => $this->fields, - ]; + return ['id' => $this->id, 'contentType' => $this->contentType, 'fields' => $this->fields]; } } diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php index 82a162ab7fa..1668c0562e8 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity - * @ApiFilter(BooleanFilter::class) + * @ApiFilter (BooleanFilter::class) */ +#[ApiResource] class ConvertedBoolean { /** @@ -33,7 +33,6 @@ class ConvertedBoolean * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var bool * diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedDate.php b/tests/Fixtures/TestBundle/Entity/ConvertedDate.php index 2ac10c4bae8..fb889fd4d07 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedDate.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity - * @ApiFilter(DateFilter::class) + * @ApiFilter (DateFilter::class) */ +#[ApiResource] class ConvertedDate { /** @@ -33,7 +33,6 @@ class ConvertedDate * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var \DateTime * diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php b/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php index fea4365608b..4ce32e42672 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php @@ -14,19 +14,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\NumericFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity - * @ApiFilter(NumericFilter::class, properties={"nameConverted"}) - * @ApiFilter(RangeFilter::class, properties={"nameConverted"}) - * @ApiFilter(OrderFilter::class, properties={"nameConverted"}) + * @ApiFilter (NumericFilter::class, properties={"nameConverted"}) + * @ApiFilter (RangeFilter::class, properties={"nameConverted"}) + * @ApiFilter (OrderFilter::class, properties={"nameConverted"}) */ +#[ApiResource] class ConvertedInteger { /** @@ -37,7 +37,6 @@ class ConvertedInteger * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var int * diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php index bc48be22175..aa00a2bff82 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity - * @ApiFilter(SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) + * @ApiFilter (SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) */ +#[ApiResource] class ConvertedOwner { /** @@ -33,7 +33,6 @@ class ConvertedOwner * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var ConvertedRelated|null * diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php b/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php index c8adbc83e6c..feb36f8c6e2 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class ConvertedRelated { /** @@ -30,7 +30,6 @@ class ConvertedRelated * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedString.php b/tests/Fixtures/TestBundle/Entity/ConvertedString.php index 5cc47430d48..b47bb947a5a 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedString.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\ExistsFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity - * @ApiFilter(ExistsFilter::class, properties={"nameConverted"}) + * @ApiFilter (ExistsFilter::class, properties={"nameConverted"}) */ +#[ApiResource] class ConvertedString { /** @@ -33,7 +33,6 @@ class ConvertedString * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php b/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php index 4b82412cad5..af48d57ecc7 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php @@ -13,26 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * @ApiResource(itemOperations={ - * "get", - * "get_custom"={"method"="GET", "path"="custom_action_collection_dummies/{id}"}, - * "custom_normalization"={"route_name"="custom_normalization", "method"="GET"}, - * "short_custom_normalization"={"route_name"="short_custom_normalization", "method"="GET"}, - * }, - * collectionOperations={ - * "get", - * "get_custom"={"method"="GET", "path"="custom_action_collection_dummies"}, - * "custom_denormalization"={"route_name"="custom_denormalization", "method"="POST"}, - * "short_custom_denormalization"={"route_name"="short_custom_denormalization", "method"="GET"}, - * }) * * @author Kévin Dunglas */ +#[ApiResource(operations: [new Get(), new Get(uriTemplate: 'custom_action_collection_dummies/{id}'), new Get(routeName: 'custom_normalization'), new Get(routeName: 'short_custom_normalization'), new GetCollection(), new GetCollection(uriTemplate: 'custom_action_collection_dummies'), new Post(routeName: 'custom_denormalization'), new GetCollection(routeName: 'short_custom_denormalization')])] class CustomActionDummy { /** @@ -43,7 +35,6 @@ class CustomActionDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php b/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php index 58cbe190cd0..8fef0bef6d4 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php +++ b/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Custom identifier. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class CustomGeneratedIdentifier { /** diff --git a/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php index 7f47550d7cc..d0c03433049 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Custom Identifier Dummy. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class CustomIdentifierDummy { /** @@ -32,7 +32,6 @@ class CustomIdentifierDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $customId; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php index 6ef2c1b9e18..ff01f25fac7 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php @@ -13,15 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** * Custom Identifier Dummy. * - * @ApiResource(compositeIdentifier=false) * @ORM\Entity */ +#[ApiResource(uriVariables: ['firstId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['firstId']), 'secondId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['secondId'])])] class CustomMultipleIdentifierDummy { /** @@ -31,7 +32,6 @@ class CustomMultipleIdentifierDummy * @ORM\Id */ private $firstId; - /** * @var int The custom identifier * @@ -39,7 +39,6 @@ class CustomMultipleIdentifierDummy * @ORM\Id */ private $secondId; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php b/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php index edb7685fccf..e078bae5528 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,13 +23,9 @@ * Custom Normalized Dummy. * * @author Mikaël Labrut - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"output"}}, - * "denormalization_context"={"groups"={"input"}} - * }) * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['output']], denormalizationContext: ['groups' => ['input']])] class CustomNormalizedDummy { /** @@ -41,7 +37,6 @@ class CustomNormalizedDummy * @Groups({"input", "output"}) */ private $id; - /** * @var string The dummy name * @@ -51,7 +46,6 @@ class CustomNormalizedDummy * @Groups({"input", "output"}) */ private $name; - /** * @var string|null The dummy name alias * diff --git a/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php index 5df74ba433b..b01f9f122ce 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Custom Writable Identifier Dummy. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class CustomWritableIdentifierDummy { /** @@ -31,7 +31,6 @@ class CustomWritableIdentifierDummy * @ORM\Id */ private $slug; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Entity/Customer.php b/tests/Fixtures/TestBundle/Entity/Customer.php index fdac6244361..c598476479b 100644 --- a/tests/Fixtures/TestBundle/Entity/Customer.php +++ b/tests/Fixtures/TestBundle/Entity/Customer.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class Customer { /** @@ -33,13 +33,11 @@ class Customer * @Groups({"order_read"}) */ private $id; - /** * @ORM\Column(type="string") * @Groups({"order_read"}) */ public $name; - /** * @ORM\ManyToMany(targetEntity="Address") * @ORM\JoinColumn(nullable=false) diff --git a/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php b/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php index 501d11af9b4..80dc1b717ac 100644 --- a/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php +++ b/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource(deprecationReason="This resource is deprecated") * @ORM\Entity * * @author Kévin Dunglas */ +#[ApiResource(deprecationReason: 'This resource is deprecated')] class DeprecatedResource { /** @@ -30,7 +30,6 @@ class DeprecatedResource * @ORM\Column */ public $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php b/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php index e2636a48db2..4a4ad4ce141 100644 --- a/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php +++ b/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php @@ -14,24 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Action\NotFoundAction; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource( - * collectionOperations={ - * "get", - * }, - * itemOperations={ - * "get"={ - * "controller"=NotFoundAction::class, - * "read"=false, - * "output"=false, - * }, - * }, - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(controller: NotFoundAction::class, read: false, output: false), new GetCollection()])] class DisableItemOperation { /** @@ -42,7 +33,6 @@ class DisableItemOperation * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index 00e44f10566..0b208cb8715 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -14,10 +14,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -25,21 +25,11 @@ * Dummy. * * @author Kévin Dunglas - * - * @ApiResource(attributes={ - * "filters"={ - * "my_dummy.boolean", - * "my_dummy.date", - * "my_dummy.exists", - * "my_dummy.numeric", - * "my_dummy.order", - * "my_dummy.range", - * "my_dummy.search", - * "my_dummy.property" - * } - * }) * @ORM\Entity */ +#[ApiResource(filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy')], status: 200, filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy')], status: 200, filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'], operations: [new Get()])] class Dummy { /** @@ -50,7 +40,6 @@ class Dummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The dummy name * @@ -59,7 +48,6 @@ class Dummy * @ApiProperty(iri="http://schema.org/name") */ private $name; - /** * @var string|null The dummy name alias * @@ -67,12 +55,10 @@ class Dummy * @ApiProperty(iri="https://schema.org/alternateName") */ private $alias; - /** * @var array foo */ private $foo; - /** * @var string|null A short description of the item * @@ -80,21 +66,18 @@ class Dummy * @ApiProperty(iri="https://schema.org/description") */ public $description; - /** * @var string|null A dummy * * @ORM\Column(nullable=true) */ public $dummy; - /** * @var bool|null A dummy boolean * * @ORM\Column(type="boolean", nullable=true) */ public $dummyBoolean; - /** * @var \DateTime|null A dummy date * @@ -102,21 +85,18 @@ class Dummy * @ApiProperty(iri="http://schema.org/DateTime") */ public $dummyDate; - /** * @var float|null A dummy float * * @ORM\Column(type="float", nullable=true) */ public $dummyFloat; - /** * @var string|null A dummy price * * @ORM\Column(type="decimal", precision=10, scale=2, nullable=true) */ public $dummyPrice; - /** * @var RelatedDummy|null A related dummy * @@ -124,43 +104,35 @@ class Dummy * @ApiProperty(push=true) */ public $relatedDummy; - /** - * @var Collection Several dummies - * + * @var \Collection Several dummies * @ORM\ManyToMany(targetEntity="RelatedDummy") - * @ApiSubresource */ public $relatedDummies; - /** * @var array|null serialize data * * @ORM\Column(type="json", nullable=true) */ public $jsonData; - /** * @var array|null * * @ORM\Column(type="simple_array", nullable=true) */ public $arrayData; - /** * @var string|null * * @ORM\Column(nullable=true) */ public $nameConverted; - /** * @var RelatedOwnedDummy|null * * @ORM\OneToOne(targetEntity="RelatedOwnedDummy", cascade={"persist"}, mappedBy="owningDummy") */ public $relatedOwnedDummy; - /** * @var RelatedOwningDummy|null * @@ -298,7 +270,6 @@ public function getRelatedOwnedDummy() public function setRelatedOwnedDummy(RelatedOwnedDummy $relatedOwnedDummy) { $this->relatedOwnedDummy = $relatedOwnedDummy; - if ($this !== $this->relatedOwnedDummy->getOwningDummy()) { $this->relatedOwnedDummy->setOwningDummy($this); } diff --git a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php index 7bda8e1f077..d3908219379 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php @@ -13,21 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; /** * Dummy Aggregate Offer. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_products/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] class DummyAggregateOffer { /** @@ -38,22 +40,17 @@ class DummyAggregateOffer * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** - * @var Collection - * - * @ApiSubresource + * @var \Collection * @ORM\OneToMany(targetEntity="DummyOffer", mappedBy="aggregate", cascade={"persist"}) */ private $offers; - /** * @var DummyProduct|null The dummy product * * @ORM\ManyToOne(targetEntity="DummyProduct", inversedBy="offers") */ private $product; - /** * @var int The dummy aggregate offer value * diff --git a/tests/Fixtures/TestBundle/Entity/DummyBoolean.php b/tests/Fixtures/TestBundle/Entity/DummyBoolean.php index ba37166cadc..4e5103f93b9 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/DummyBoolean.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class DummyBoolean { /** @@ -30,7 +30,6 @@ class DummyBoolean * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var bool|null * diff --git a/tests/Fixtures/TestBundle/Entity/DummyCar.php b/tests/Fixtures/TestBundle/Entity/DummyCar.php index cd1385b2db0..b952db1b104 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCar.php @@ -14,10 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Serializer\Filter\GroupFilter; use ApiPlatform\Serializer\Filter\PropertyFilter; use Doctrine\Common\Collections\ArrayCollection; @@ -25,20 +30,14 @@ use Symfony\Component\Serializer\Annotation as Serializer; /** - * @ApiResource( - * itemOperations={"get"={"swagger_context"={"tags"={}}, "openapi_context"={"tags"={}}}, "put", "delete"}, - * attributes={ - * "sunset"="2050-01-01", - * "normalization_context"={"groups"={"colors"}} - * } - * ) * @ORM\Entity - * @ApiFilter(DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) - * @ApiFilter(BooleanFilter::class) - * @ApiFilter(PropertyFilter::class, arguments={"parameterName"="foobar"}) - * @ApiFilter(GroupFilter::class, arguments={"parameterName"="foobargroups"}) - * @ApiFilter(GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") + * @ApiFilter (DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) + * @ApiFilter (BooleanFilter::class) + * @ApiFilter (PropertyFilter::class, arguments={"parameterName"="foobar"}) + * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups"}) + * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") */ +#[ApiResource(operations: [new Get(openapiContext: ['tags' => []]), new Put(), new Delete(), new Post(), new GetCollection()], sunset: '2050-01-01', normalizationContext: ['groups' => ['colors']])] class DummyCar { /** @@ -48,7 +47,6 @@ class DummyCar * @ORM\OneToOne(targetEntity="DummyCarIdentifier", cascade={"persist"}) */ private $id; - /** * @var mixed Something else * @@ -58,7 +56,6 @@ class DummyCar * @ApiFilter(SearchFilter::class, properties={"colors.prop"="ipartial", "colors"="exact"}) */ private $colors; - /** * @var mixed Something else * @@ -68,7 +65,6 @@ class DummyCar * @ApiFilter(SearchFilter::class, strategy="exact") */ private $secondColors; - /** * @var mixed Something else * @@ -78,7 +74,6 @@ class DummyCar * @ApiFilter(SearchFilter::class, strategy="exact") */ private $thirdColors; - /** * @var mixed Something else * @@ -91,7 +86,6 @@ class DummyCar * @ApiFilter(SearchFilter::class, strategy="exact") */ private $uuid; - /** * @var string * @@ -99,21 +93,18 @@ class DummyCar * @ApiFilter(SearchFilter::class, strategy="partial") */ private $name; - /** * @var bool * * @ORM\Column(type="boolean") */ private $canSell; - /** * @var \DateTime * * @ORM\Column(type="datetime") */ private $availableAt; - /** * @var string * @@ -123,7 +114,6 @@ class DummyCar * @ORM\Column */ private $brand = 'DummyBrand'; - /** * @var DummyCarInfo * diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php index 08468c15058..21dc53f7614 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php @@ -14,16 +14,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class DummyCarColor { /** @@ -34,7 +34,6 @@ class DummyCarColor * @ORM\Column(type="integer") */ private $id; - /** * @var DummyCar * @@ -43,7 +42,6 @@ class DummyCarColor * @Assert\NotBlank */ private $car; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php b/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php index e8bb542f332..a1af67d71d1 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** - * @ApiResource(attributes={"formats"={"xml", "jsonld", "csv"={"text/csv"}, "pdf"="application/pdf"}}) * @ORM\Entity */ +#[ApiResource(formats: ['xml', 'jsonld', 'csv' => ['text/csv'], 'pdf' => 'application/pdf'])] class DummyCustomFormat { /** @@ -31,7 +31,6 @@ class DummyCustomFormat * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php index 5a2ca212103..fa9dcd0639d 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,44 +23,10 @@ * Dummy with a custom GraphQL mutation resolver. * * @ORM\Entity - * @ApiResource(graphql={ - * "sum"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNotPersisted"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNoWriteCustomResult"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "write"=false - * }, - * "sumOnlyPersist"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "read"=false, - * "deserialize"=false, - * "validate"=false, - * "serialize"=false - * }, - * "testCustomArguments"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "args"={"operandC"={"type"="Int!"}} - * }, - * "testOutput"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "output"=OutputDto::class - * } - * }) * * @author Raoul Clais */ +#[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']]), new Mutation(name: 'testOutput', resolver: 'app.graphql.mutation_resolver.dummy_custom', output: OutputDto::class)])] class DummyCustomMutation { /** @@ -70,14 +37,12 @@ class DummyCustomMutation * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var int|null * * @ORM\Column(type="integer", nullable=true) */ private $operandA; - /** * @var int|null * @@ -85,7 +50,6 @@ class DummyCustomMutation * @ORM\Column(type="integer", nullable=true) */ private $operandB; - /** * @var int|null * diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php index 5c920aac3c7..d702a2822d2 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use Doctrine\ORM\Mapping as ORM; @@ -21,54 +23,9 @@ * Dummy with custom GraphQL query resolvers. * * @author Lukas Lücke - * - * @ApiResource(graphql={ - * "testItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item" - * }, - * "testNotRetrievedItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item", - * "args"={} - * }, - * "testNoReadAndSerializeItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testItemCustomArguments"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item", - * "args"={ - * "id"={"type"="ID"}, - * "customArgumentNullableBool"={"type"="Boolean"}, - * "customArgumentBool"={"type"="Boolean!"}, - * "customArgumentInt"={"type"="Int!"}, - * "customArgumentString"={"type"="String!"}, - * "customArgumentFloat"={"type"="Float!"}, - * "customArgumentIntArray"={"type"="[Int!]!"}, - * "customArgumentCustomType"={"type"="DateTime!"} - * } - * }, - * "testItemOutput"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item", - * "output"=OutputDto::class - * }, - * "testCollection"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection" - * }, - * "testCollectionNoReadAndSerialize"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testCollectionCustomArguments"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection", - * "args"={ - * "customArgumentString"={"type"="String!"} - * } - * } - * }) * @ORM\Entity */ +#[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new Query(name: 'testItemOutput', resolver: 'app.graphql.query_resolver.dummy_custom_item', output: OutputDto::class), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])] class DummyCustomQuery { /** @@ -79,12 +36,10 @@ class DummyCustomQuery * @ORM\Column(type="integer") */ public $id; - /** * @var string */ public $message; - /** * @var array */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyDate.php b/tests/Fixtures/TestBundle/Entity/DummyDate.php index ff34bbed65c..60d0ea723bb 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDate.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDate.php @@ -14,28 +14,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Dummy Date. * * @author Antoine Bluchet - * - * @ApiResource(attributes={ - * "filters"={"my_dummy_date.date"} - * }) - * @ApiFilter(SearchFilter::class, properties={"dummyDate"}) - * @ApiFilter(DateFilter::class, properties={ + * @ApiFilter (SearchFilter::class, properties={"dummyDate"}) + * @ApiFilter (DateFilter::class, properties={ * "dateIncludeNullAfter"=DateFilter::INCLUDE_NULL_AFTER, * "dateIncludeNullBefore"=DateFilter::INCLUDE_NULL_BEFORE, * "dateIncludeNullBeforeAndAfter"=DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER * }) - * * @ORM\Entity */ +#[ApiResource(filters: ['my_dummy_date.date'])] class DummyDate { /** @@ -46,28 +43,24 @@ class DummyDate * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var \DateTime The dummy date * * @ORM\Column(type="date") */ public $dummyDate; - /** * @var \DateTime|null * * @ORM\Column(type="date", nullable=true) */ public $dateIncludeNullAfter; - /** * @var \DateTime|null * * @ORM\Column(type="date", nullable=true) */ public $dateIncludeNullBefore; - /** * @var \DateTime|null * diff --git a/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php b/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php index 71470f01e32..114bbf7d42e 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,15 +23,9 @@ * Dummy with different serialization groups for item_query and collection_query. * * @author Mahmood Bazdar - * - * @ApiResource( - * graphql={ - * "item_query"={"normalization_context"={"groups"={"item_query"}}}, - * "collection_query"={"normalization_context"={"groups"={"collection_query"}}} - * } - * ) * @ORM\Entity */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['item_query']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['collection_query']])])] class DummyDifferentGraphQlSerializationGroup { /** @@ -41,7 +37,6 @@ class DummyDifferentGraphQlSerializationGroup * @Groups({"item_query", "collection_query"}) */ private $id; - /** * @var string The dummy name * @@ -49,7 +44,6 @@ class DummyDifferentGraphQlSerializationGroup * @Groups({"item_query", "collection_query"}) */ private $name; - /** * @var string|null The dummy title * diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php index acf177fb630..f9960ebcf36 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomInputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomOutputDto; use Doctrine\ORM\Mapping as ORM; @@ -22,12 +27,8 @@ * DummyDtoCustom. * * @ORM\Entity - * - * @ApiResource( - * collectionOperations={"post"={"input"=CustomInputDto::class}, "get", "custom_output"={"output"=CustomOutputDto::class, "path"="dummy_dto_custom_output", "method"="GET"}, "post_without_output"={"output"=false, "method"="POST", "path"="dummy_dto_custom_post_without_output"}}, - * itemOperations={"get", "custom_output"={"output"=CustomOutputDto::class, "method"="GET", "path"="dummy_dto_custom_output/{id}"}, "put", "delete"} - * ) */ +#[ApiResource(operations: [new Get(), new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), new Put(), new Delete(), new Post(input: CustomInputDto::class), new GetCollection(), new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output')])] class DummyDtoCustom { /** @@ -38,14 +39,12 @@ class DummyDtoCustom * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * * @ORM\Column */ public $lorem; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php index 51c35321713..5890a676cad 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use Doctrine\Common\Collections\ArrayCollection; @@ -24,17 +24,15 @@ * Dummy InputOutput. * * @author Kévin Dunglas - * - * @ApiResource(attributes={"input"=InputDto::class, "output"=OutputDto::class}) * @ORM\Entity */ +#[ApiResource(input: InputDto::class, output: OutputDto::class)] class DummyDtoInputOutput { public function __construct() { $this->relatedDummies = new ArrayCollection(); } - /** * @var int The id * @ORM\Column(type="integer") @@ -42,19 +40,16 @@ public function __construct() * @ORM\GeneratedValue(strategy="AUTO") */ public $id; - /** * @var string * @ORM\Column(type="string") */ public $str; - /** * @var float * @ORM\Column(type="float") */ public $num; - /** * @var Collection * @ORM\ManyToMany(targetEntity="RelatedDummy") diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php index 937223861ac..08b9137ec72 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php @@ -13,7 +13,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\CreateItemAction; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\DoubleBatAction; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; @@ -23,34 +27,9 @@ * DummyDtoNoInput. * * @author Vincent Chalamon - * * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "input"=false, - * "output"=OutputDto::class - * }, - * collectionOperations={ - * "post"={ - * "method"="POST", - * "path"="/dummy_dto_no_inputs", - * "controller"=CreateItemAction::class, - * }, - * "get", - * }, - * itemOperations={ - * "get", - * "delete", - * "post_double_bat"={ - * "method"="POST", - * "path"="/dummy_dto_no_inputs/{id}/double_bat", - * "controller"=DoubleBatAction::class, - * "status"=200, - * }, - * }, - * ) */ +#[ApiResource(operations: [new Get(), new Delete(), new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200), new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class), new GetCollection()], input: false, output: OutputDto::class)] class DummyDtoNoInput { /** @@ -61,14 +40,12 @@ class DummyDtoNoInput * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * * @ORM\Column */ public $lorem; - /** * @var float * diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php index 79e4b46cb1f..d1d1b1a034d 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use Doctrine\ORM\Mapping as ORM; @@ -21,16 +21,9 @@ * DummyDtoNoOutput. * * @author Vincent Chalamon - * * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "input"=InputDto::class, - * "output"=false - * } - * ) */ +#[ApiResource(input: InputDto::class, output: false)] class DummyDtoNoOutput { /** @@ -41,14 +34,12 @@ class DummyDtoNoOutput * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * * @ORM\Column */ public $lorem; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php index 28cc949d384..8cce1b5b478 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDtoDummy; use Doctrine\ORM\Mapping as ORM; @@ -21,10 +21,9 @@ * Dummy InputOutput. * * @author Daniel West - * - * @ApiResource(attributes={"output"=OutputDtoDummy::class}) * @ORM\Entity */ +#[ApiResource(output: OutputDtoDummy::class)] class DummyDtoOutputFallbackToSameClass { /** @@ -35,14 +34,12 @@ class DummyDtoOutputFallbackToSameClass * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * * @ORM\Column */ public $lorem; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php index 6545480f116..fa88497f8b0 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php @@ -13,17 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Dummy InputOutput. * * @author Daniel West - * - * @ApiResource(attributes={"output"=DummyDtoOutputSameClass::class}) * @ORM\Entity */ +#[ApiResource(output: DummyDtoOutputSameClass::class)] class DummyDtoOutputSameClass { /** @@ -34,14 +33,12 @@ class DummyDtoOutputSameClass * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * * @ORM\Column */ public $lorem; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php b/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php index 9acbdee4ac1..a6f2d3a41b3 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php +++ b/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php @@ -13,25 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\DummyObjectWithoutConstructor; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy entity built with constructor. + * * https://github.com/api-platform/core/issues/1747. * * @author Maxime Veber - * - * @ApiResource( - * itemOperations={ - * "get", - * "put"={"denormalization_context"={"groups"={"put"}}} - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(denormalizationContext: ['groups' => ['put']]), new Post(), new GetCollection()])] class DummyEntityWithConstructor { /** @@ -42,21 +41,18 @@ class DummyEntityWithConstructor * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * * @ORM\Column */ private $foo; - /** * @var string * * @ORM\Column */ private $bar; - /** * @var string|null * @@ -64,7 +60,6 @@ class DummyEntityWithConstructor * @Groups({"put"}) */ private $baz; - /** * @var DummyObjectWithoutConstructor[] */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php index 6156b3afeeb..311fa7ab95a 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php +++ b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class DummyForAdditionalFields { /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php index d0be5c4941e..b546afa4415 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php @@ -14,18 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; -/** - * @ApiResource - */ +#[ApiResource] final class DummyForAdditionalFieldsInput { /** * @ApiProperty(identifier=true) */ public $id; - private $dummyName; public function __construct(string $dummyName) diff --git a/tests/Fixtures/TestBundle/Entity/DummyFriend.php b/tests/Fixtures/TestBundle/Entity/DummyFriend.php index 8bc22120760..ee144c9ece9 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyFriend.php +++ b/tests/Fixtures/TestBundle/Entity/DummyFriend.php @@ -14,7 +14,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,10 +24,9 @@ * Dummy Friend. * * @author Kévin Dunglas - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class DummyFriend { /** @@ -37,7 +37,6 @@ class DummyFriend * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Entity/DummyGroup.php b/tests/Fixtures/TestBundle/Entity/DummyGroup.php index 4089de74bdd..d6f2c60fea7 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyGroup.php +++ b/tests/Fixtures/TestBundle/Entity/DummyGroup.php @@ -13,7 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,31 +24,9 @@ * DummyGroup. * * @author Baptiste Meyer - * * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}}, - * "filters"={ - * "dummy_group.group", - * "dummy_group.override_group", - * "dummy_group.whitelist_group", - * "dummy_group.override_whitelist_group" - * } - * }, - * graphql={ - * "item_query"={"normalization_context"={"groups"={"dummy_foo"}}}, - * "collection_query"={"normalization_context"={"groups"={"dummy_foo"}}}, - * "delete", - * "create"={ - * "normalization_context"={"groups"={"dummy_bar"}}, - * "denormalization_context"={"groups"={"dummy_bar", "dummy_baz"}} - * } - * } - * ) */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['dummy_foo']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['dummy_foo']]), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_bar']], denormalizationContext: ['groups' => ['dummy_bar', 'dummy_baz']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_group.group', 'dummy_group.override_group', 'dummy_group.whitelist_group', 'dummy_group.override_whitelist_group'])] class DummyGroup { /** @@ -58,7 +39,6 @@ class DummyGroup * @Groups({"dummy", "dummy_read", "dummy_id"}) */ private $id; - /** * @var string|null * @@ -67,7 +47,6 @@ class DummyGroup * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_foo"}) */ public $foo; - /** * @var string|null * @@ -76,7 +55,6 @@ class DummyGroup * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_bar"}) */ public $bar; - /** * @var string|null * @@ -85,7 +63,6 @@ class DummyGroup * @Groups({"dummy", "dummy_read", "dummy_baz"}) */ public $baz; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php b/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php index 138003fe91a..3680e06f758 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php +++ b/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php @@ -13,17 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Dummy Immutable Date. * - * @ApiResource(attributes={ - * "filters"={"my_dummy_immutable_date.date"} - * }) * @ORM\Entity */ +#[ApiResource(filters: ['my_dummy_immutable_date.date'])] class DummyImmutableDate { /** @@ -34,7 +33,6 @@ class DummyImmutableDate * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var \DateTimeImmutable The dummy date * diff --git a/tests/Fixtures/TestBundle/Entity/DummyMercure.php b/tests/Fixtures/TestBundle/Entity/DummyMercure.php index 5b6cba7fdd7..b20669366fe 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyMercure.php +++ b/tests/Fixtures/TestBundle/Entity/DummyMercure.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * @ApiResource(mercure=true) * * @author Kévin Dunglas */ +#[ApiResource(mercure: true)] class DummyMercure { /** @@ -30,17 +30,14 @@ class DummyMercure * @ORM\GeneratedValue(strategy="AUTO") */ public $id; - /** * @ORM\Column */ public $name; - /** * @ORM\Column */ public $description; - /** * @ORM\ManyToOne(targetEntity="RelatedDummy") */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php b/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php index 6561346bfb9..4085bc8d1c5 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php @@ -13,21 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; /** * DummyNoGetOperation. * * @author Grégoire Hébert gregoire@les-tilleuls.coop - * * @ORM\Entity - * - * @ApiResource( - * collectionOperations={"post"}, - * itemOperations={"put"} - * ) */ +#[ApiResource(operations: [new Put(), new Post()])] class DummyNoGetOperation { /** @@ -38,7 +35,6 @@ class DummyNoGetOperation * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/DummyOffer.php b/tests/Fixtures/TestBundle/Entity/DummyOffer.php index f8cd95f67c8..15b18d2332c 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyOffer.php @@ -13,18 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** * Dummy Offer. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_aggregate_offers/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] class DummyOffer { /** @@ -35,14 +40,12 @@ class DummyOffer * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var int The dummy aggregate offer value * * @ORM\Column(type="integer") */ private $value; - /** * @var DummyAggregateOffer|null The dummy aggregate offer value * diff --git a/tests/Fixtures/TestBundle/Entity/DummyPassenger.php b/tests/Fixtures/TestBundle/Entity/DummyPassenger.php index 5f6da5bd642..e1499af768d 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPassenger.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPassenger.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class DummyPassenger { /** @@ -30,7 +30,6 @@ class DummyPassenger * @ORM\Column(type="integer") */ private $id; - /** * @ORM\Column(type="string") */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php index 1e0514f82ce..23cd381535f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php @@ -9,20 +9,25 @@ * file that was distributed with this source code. */ -declare(strict_types=1); +declare (strict_types=1); namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use Doctrine\ORM\Mapping as ORM; - /** * @ORM\Entity */ -#[ApiResource(description: "Hey PHP 8")] +#[ApiResource(description: 'Hey PHP 8')] class DummyPhp8 { /** @@ -31,15 +36,13 @@ class DummyPhp8 */ #[ApiProperty(identifier: true, description: 'the identifier')] public $id; - /** * @ORM\Column */ #[ApiFilter(SearchFilter::class)] public $filtered; - #[ApiProperty(description: 'a foo')] - public function getFoo(): int + public function getFoo() : int { return 0; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyProduct.php b/tests/Fixtures/TestBundle/Entity/DummyProduct.php index 3930d62aa14..d4c154090e0 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Entity/DummyProduct.php @@ -13,21 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; /** * Dummy Product. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, operations: [new GetCollection()])] class DummyProduct { /** @@ -38,30 +40,22 @@ class DummyProduct * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** - * @var Collection - * - * @ApiSubresource + * @var \Collection * @ORM\OneToMany(targetEntity="DummyAggregateOffer", mappedBy="product", cascade={"persist"}) */ private $offers; - /** * @var string The tour name * * @ORM\Column */ private $name; - /** - * @var Collection - * - * @ApiSubresource + * @var \Collection * @ORM\OneToMany(targetEntity="DummyProduct", mappedBy="parent") */ private $relatedProducts; - /** * @ORM\ManyToOne(targetEntity="DummyProduct", inversedBy="relatedProducts") */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyProperty.php b/tests/Fixtures/TestBundle/Entity/DummyProperty.php index 5251bea16bb..3f8338113f1 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyProperty.php +++ b/tests/Fixtures/TestBundle/Entity/DummyProperty.php @@ -13,7 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,30 +25,9 @@ * DummyProperty. * * @author Baptiste Meyer - * * @ORM\Entity - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}}, - * "filters"={ - * "dummy_property.property", - * "dummy_property.whitelist_property", - * "dummy_property.whitelisted_properties" - * } - * }, - * graphql={ - * "item_query", - * "collection_query", - * "update", - * "delete", - * "create"={ - * "normalization_context"={"groups"={"dummy_graphql_read"}}, - * } - * } - * ) */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query'), new Mutation(name: 'update'), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_graphql_read']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_property.property', 'dummy_property.whitelist_property', 'dummy_property.whitelisted_properties'])] class DummyProperty { /** @@ -58,7 +40,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read"}) */ private $id; - /** * @var string|null * @@ -67,7 +48,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_write"}) */ public $foo; - /** * @var string|null * @@ -76,7 +56,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ public $bar; - /** * @var string|null * @@ -85,7 +64,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ public $baz; - /** * @var DummyGroup|null * @@ -94,7 +72,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ public $group; - /** * @var Collection * @@ -102,7 +79,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ public $groups; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php b/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php index 755893931c7..bc8a5b29dee 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,12 +21,8 @@ * DummyPropertyWithDefaultValue. * * @ORM\Entity - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}} - * }) */ +#[ApiResource(normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']])] class DummyPropertyWithDefaultValue { /** @@ -39,7 +35,6 @@ class DummyPropertyWithDefaultValue * @Groups("dummy_read") */ private $id; - /** * @var string|null * @@ -48,7 +43,6 @@ class DummyPropertyWithDefaultValue * @Groups({"dummy_read", "dummy_write"}) */ public $foo = 'foo'; - /** * @var string A dummy with a Doctrine default options * diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php index e6ee7fb9b03..9ac1af3a3de 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php @@ -13,22 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * @ORM\Entity - * @ORM\InheritanceType("JOINED") - * @ORM\DiscriminatorColumn(name="discr", type="string") - * @ORM\DiscriminatorMap({ + * @ORM\InheritanceType ("JOINED") + * @ORM\DiscriminatorColumn (name="discr", type="string") + * @ORM\DiscriminatorMap ({ * "dummyTableInheritance"="DummyTableInheritance", * "dummyTableInheritanceChild"="DummyTableInheritanceChild", * "dummyTableInheritanceDifferentChild"="DummyTableInheritanceDifferentChild", * "dummyTableInheritanceNotApiResourceChild"="DummyTableInheritanceNotApiResourceChild" * }) - * @ApiResource */ +#[ApiResource] class DummyTableInheritance { /** @@ -41,7 +41,6 @@ class DummyTableInheritance * @Groups({"default"}) */ private $id; - /** * @var string The dummy name * @@ -50,7 +49,6 @@ class DummyTableInheritance * @Groups({"default"}) */ private $name; - /** * @var DummyTableInheritanceRelated|null * diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php index 385c90f2cc4..f78a24aa3b4 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * @ORM\Entity - * @ApiResource */ +#[ApiResource] class DummyTableInheritanceChild extends DummyTableInheritance { /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php index d0d940405a7..a3afcdf0cbf 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * @ORM\Entity - * @ApiResource */ +#[ApiResource] class DummyTableInheritanceDifferentChild extends DummyTableInheritance { /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php index 60a57d5dc4e..dc5886e194c 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -21,13 +21,8 @@ /** * @ORM\Entity - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"default"}}, - * "denormalization_context"={"groups"={"default"}} - * } - * ) */ +#[ApiResource(normalizationContext: ['groups' => ['default']], denormalizationContext: ['groups' => ['default']])] class DummyTableInheritanceRelated { /** @@ -40,7 +35,6 @@ class DummyTableInheritanceRelated * @Groups({"default"}) */ private $id; - /** * @var Collection Related children * diff --git a/tests/Fixtures/TestBundle/Entity/DummyTravel.php b/tests/Fixtures/TestBundle/Entity/DummyTravel.php index fbf3285b764..869704a0333 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTravel.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTravel.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource(filters={"dummy_travel.property"}) * @ORM\Entity */ +#[ApiResource(filters: ['dummy_travel.property'])] class DummyTravel { /** @@ -28,13 +28,11 @@ class DummyTravel * @ORM\Column(type="integer") */ private $id; - /** * @ORM\ManyToOne(targetEntity="DummyCar") * @ORM\JoinColumn(name="car_id", referencedColumnName="id_id") */ public $car; - /** * @ORM\Column(type="boolean") */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyValidation.php b/tests/Fixtures/TestBundle/Entity/DummyValidation.php index a8721e2e9dd..9b6b071c6f4 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyValidation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyValidation.php @@ -13,21 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * @ORM\Entity - * @ApiResource( - * collectionOperations={ - * "get"={"method"="GET"}, - * "post"={"path"="dummy_validation.{_format}", "method"="POST"}, - * "post_validation_groups"={"route_name"="post_validation_groups", "validation_groups"={"a"}, "method"="GET"}, - * "post_validation_sequence"={"route_name"="post_validation_sequence", "validation_groups"="app.dummy_validation.group_generator", "method"="GET"} - * } - * ) */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new Post(uriTemplate: 'dummy_validation.{_format}'), new GetCollection(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]), new GetCollection(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator'])])] class DummyValidation { /** @@ -38,7 +37,6 @@ class DummyValidation * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string|null The dummy name * @@ -46,7 +44,6 @@ class DummyValidation * @Assert\NotNull(groups={"a"}) */ private $name; - /** * @var string|null The dummy title * @@ -54,7 +51,6 @@ class DummyValidation * @Assert\NotNull(groups={"b"}) */ private $title; - /** * @var string The dummy code * @ORM\Column diff --git a/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php b/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php index 1900edf2ad3..e739543b2e3 100644 --- a/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -22,13 +27,9 @@ * Embedded Dummy. * * @author Jordan Samouh - * - * @ApiResource( - * attributes={"filters"={"my_dummy.search", "my_dummy.order", "my_dummy.date", "my_dummy.range", "my_dummy.boolean", "my_dummy.numeric"}}, - * itemOperations={"get", "put", "delete", "groups"={"method"="GET", "path"="/embedded_dummies_groups/{id}", "normalization_context"={"groups"={"embed"}}}} - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(uriTemplate: '/embedded_dummies_groups/{id}', normalizationContext: ['groups' => ['embed']]), new Post(), new GetCollection()], filters: ['my_dummy.search', 'my_dummy.order', 'my_dummy.date', 'my_dummy.range', 'my_dummy.boolean', 'my_dummy.numeric'])] class EmbeddedDummy { /** @@ -39,7 +40,6 @@ class EmbeddedDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string|null The dummy name * @@ -47,7 +47,6 @@ class EmbeddedDummy * @Groups({"embed"}) */ private $name; - /** * @var \DateTime|null A dummy date * @@ -55,7 +54,6 @@ class EmbeddedDummy * @Assert\DateTime */ public $dummyDate; - /** * @var EmbeddableDummy * @@ -63,7 +61,6 @@ class EmbeddedDummy * @Groups({"embed"}) */ public $embeddedDummy; - /** * @var RelatedDummy|null A related dummy * diff --git a/tests/Fixtures/TestBundle/Entity/ExternalUser.php b/tests/Fixtures/TestBundle/Entity/ExternalUser.php index 5346b2e6399..15534783054 100644 --- a/tests/Fixtures/TestBundle/Entity/ExternalUser.php +++ b/tests/Fixtures/TestBundle/Entity/ExternalUser.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * @ApiResource */ +#[ApiResource] class ExternalUser extends AbstractUser { /** diff --git a/tests/Fixtures/TestBundle/Entity/FilterValidator.php b/tests/Fixtures/TestBundle/Entity/FilterValidator.php index 8b0c48593bb..19c4df9d3f8 100644 --- a/tests/Fixtures/TestBundle/Entity/FilterValidator.php +++ b/tests/Fixtures/TestBundle/Entity/FilterValidator.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayItemsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\BoundsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\EnumFilter; @@ -29,21 +29,9 @@ * Filter Validator entity. * * @author Julien Deniau - * - * @ApiResource(attributes={ - * "filters"={ - * ArrayItemsFilter::class, - * BoundsFilter::class, - * EnumFilter::class, - * LengthFilter::class, - * MultipleOfFilter::class, - * PatternFilter::class, - * RequiredFilter::class, - * RequiredAllowEmptyFilter::class - * } - * }) * @ORM\Entity */ +#[ApiResource(filters: [ArrayItemsFilter::class, BoundsFilter::class, EnumFilter::class, LengthFilter::class, MultipleOfFilter::class, PatternFilter::class, RequiredFilter::class, RequiredAllowEmptyFilter::class])] class FilterValidator { /** @@ -54,7 +42,6 @@ class FilterValidator * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string A name * diff --git a/tests/Fixtures/TestBundle/Entity/Foo.php b/tests/Fixtures/TestBundle/Entity/Foo.php index 2c0d3348fb3..a05d8231630 100644 --- a/tests/Fixtures/TestBundle/Entity/Foo.php +++ b/tests/Fixtures/TestBundle/Entity/Foo.php @@ -13,32 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; /** * Foo. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={ - * "order"={"bar", "name"="DESC"} - * }, - * graphql={ - * "item_query", - * "collection_query"={"pagination_enabled"=false}, - * "create", - * "delete" - * }, - * collectionOperations={ - * "get", - * "get_desc_custom"={"method"="GET", "path"="custom_collection_desc_foos", "order"={"name"="DESC"}}, - * "get_asc_custom"={"method"="GET", "path"="custom_collection_asc_foos", "order"={ "name"="ASC"}}, - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new GetCollection(uriTemplate: 'custom_collection_desc_foos', order: ['name' => 'DESC']), new GetCollection(uriTemplate: 'custom_collection_asc_foos', order: ['name' => 'ASC'])], graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query', paginationEnabled: false), new Mutation(name: 'create'), new Mutation(name: 'delete')], order: ['bar', 'name' => 'DESC'])] class Foo { /** @@ -49,14 +41,12 @@ class Foo * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The foo name * * @ORM\Column */ private $name; - /** * @var string The foo bar * diff --git a/tests/Fixtures/TestBundle/Entity/FooDummy.php b/tests/Fixtures/TestBundle/Entity/FooDummy.php index 672d4bea900..dc552de8858 100644 --- a/tests/Fixtures/TestBundle/Entity/FooDummy.php +++ b/tests/Fixtures/TestBundle/Entity/FooDummy.php @@ -13,24 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; /** * FooDummy. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={ - * "order"={"dummy.name"} - * }, - * graphql={ - * "collection_query"={"pagination_type"="page"} - * } - * ) * @ORM\Entity */ +#[ApiResource(graphQlOperations: [new QueryCollection(name: 'collection_query', paginationType: 'page')], order: ['dummy.name'])] class FooDummy { /** @@ -41,14 +34,12 @@ class FooDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The foo name * * @ORM\Column */ private $name; - /** * @var Dummy|null The foo dummy * diff --git a/tests/Fixtures/TestBundle/Entity/FourthLevel.php b/tests/Fixtures/TestBundle/Entity/FourthLevel.php index a00cef25524..025483000cb 100644 --- a/tests/Fixtures/TestBundle/Entity/FourthLevel.php +++ b/tests/Fixtures/TestBundle/Entity/FourthLevel.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,10 +23,15 @@ * Fourth Level. * * @author Alan Poulain - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/third_levels/{id}/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: ['id'], fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] class FourthLevel { /** @@ -35,7 +42,6 @@ class FourthLevel * @ORM\GeneratedValue */ private $id; - /** * @var int * @@ -43,7 +49,6 @@ class FourthLevel * @Groups({"barcelona", "chicago"}) */ private $level = 4; - /** * @ORM\OneToMany(targetEntity=ThirdLevel::class, cascade={"persist"}, mappedBy="badFourthLevel") */ diff --git a/tests/Fixtures/TestBundle/Entity/Greeting.php b/tests/Fixtures/TestBundle/Entity/Greeting.php index 84eb5936e64..43ee83c3c84 100644 --- a/tests/Fixtures/TestBundle/Entity/Greeting.php +++ b/tests/Fixtures/TestBundle/Entity/Greeting.php @@ -13,13 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/people/{id}/sent_greetings.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Person::class, identifiers: ['id'], toProperty: 'sender')], status: 200, operations: [new GetCollection()])] class Greeting { /** @@ -28,18 +31,15 @@ class Greeting * @ORM\Column(type="integer") */ private $id; - /** * @ORM\Column */ public $message = ''; - /** * @ORM\ManyToOne(targetEntity="Person", inversedBy="sentGreetings") * @ORM\JoinColumn(name="sender_id") */ public $sender; - /** * @ORM\ManyToOne(targetEntity="Person") * @ORM\JoinColumn(name="recipient_id", nullable=true) diff --git a/tests/Fixtures/TestBundle/Entity/InitializeInput.php b/tests/Fixtures/TestBundle/Entity/InitializeInput.php index 8059a8eb2ed..1390c990f90 100644 --- a/tests/Fixtures/TestBundle/Entity/InitializeInput.php +++ b/tests/Fixtures/TestBundle/Entity/InitializeInput.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource(input=InitializeInputDto::class) * @ORM\Entity */ +#[ApiResource(input: InitializeInputDto::class)] class InitializeInput { /** @@ -28,12 +28,10 @@ class InitializeInput * @ORM\Column(type="integer") */ public $id; - /** * @ORM\Column */ public $manager; - /** * @ORM\Column */ diff --git a/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php b/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php index 9aceb5f7b8f..a1daec613d4 100644 --- a/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php +++ b/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php @@ -13,22 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Dummy with iri_only. * * @author Pierre Thibaudeau - * - * @ApiResource( - * normalizationContext={ - * "iri_only"=true, - * "jsonld_embed_context"=true - * } - * ) * @ORM\Entity */ +#[ApiResource(normalizationContext: ['iri_only' => true, 'jsonld_embed_context' => true])] class IriOnlyDummy { /** @@ -39,7 +33,6 @@ class IriOnlyDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php b/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php index 8550e066d8c..b1fc55f356b 100644 --- a/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php +++ b/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Jsonld Context Dummy. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class JsonldContextDummy { /** @@ -34,7 +34,6 @@ class JsonldContextDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The dummy person * diff --git a/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php b/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php index f9530a6384f..634d8cf2324 100644 --- a/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php @@ -13,7 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -21,26 +27,9 @@ * Secured resource with legacy access_control attribute. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={"access_control"="is_granted('ROLE_USER')"}, - * collectionOperations={ - * "get", - * "post"={"access_control"="is_granted('ROLE_ADMIN')"} - * }, - * itemOperations={ - * "get"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "put"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * }, - * graphql={ - * "item_query"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "delete"={}, - * "update"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * "create"={"access_control"="is_granted('ROLE_ADMIN')", "access_control_message"="Only admins can create a secured dummy."} - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Mutation(name: 'delete'), new Mutation(name: 'update', security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] class LegacySecuredDummy { /** @@ -51,7 +40,6 @@ class LegacySecuredDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The title * @@ -59,14 +47,12 @@ class LegacySecuredDummy * @Assert\NotBlank */ private $title; - /** * @var string The description * * @ORM\Column */ private $description = ''; - /** * @var string The owner * diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php index 58c7a1fe0f5..d3fdda9dabf 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php @@ -14,20 +14,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; -/** * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"default"}, "enable_max_depth"=true}, - * "denormalization_context"={"groups"={"default"}, "enable_max_depth"=true} - * }) +/** + * * + * * @ORM\Entity * * @author Brian Fox */ +#[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] class MaxDepthDummy { /** @@ -37,13 +36,11 @@ class MaxDepthDummy * @Groups({"default"}) */ private $id; - /** * @ORM\Column(name="name", type="string", length=30) * @Groups({"default"}) */ public $name; - /** * @ORM\ManyToOne(targetEntity="MaxDepthDummy", cascade={"persist"}) * @ApiProperty(attributes={"fetch_eager"=false}) diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php index 082c4e90e1b..4b53f92f044 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php @@ -13,20 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; -/** * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"default"}, "enable_max_depth"=true}, - * "denormalization_context"={"groups"={"default"}, "enable_max_depth"=true} - * }) +/** + * * + * * @ORM\Entity * * @author Brian Fox */ +#[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] class MaxDepthEagerDummy { /** @@ -36,13 +35,11 @@ class MaxDepthEagerDummy * @Groups({"default"}) */ private $id; - /** * @ORM\Column(name="name", type="string", length=30) * @Groups({"default"}) */ public $name; - /** * @ORM\ManyToOne(targetEntity="MaxDepthEagerDummy", cascade={"persist"}) * @Groups({"default"}) diff --git a/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php b/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php index ed1db8c4c5b..fd620196e76 100644 --- a/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php +++ b/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php @@ -14,12 +14,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerInput; -/** - * @ApiResource(messenger="input", input=MessengerInput::class, graphql={"create"={"input"=MessengerInput::class, "messenger"="input"}}) - */ +#[ApiResource(graphQlOperations: [new Mutation(name: 'create', input: MessengerInput::class, messenger: 'input')], messenger: 'input', input: MessengerInput::class)] class MessengerWithInput { /** diff --git a/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php b/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php index 9a5b3ab3192..ad646783331 100644 --- a/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php +++ b/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php @@ -14,12 +14,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerResponseInput; -/** - * @ApiResource(messenger="input", input=MessengerResponseInput::class) - */ +#[ApiResource(messenger: 'input', input: MessengerResponseInput::class)] class MessengerWithResponse { /** diff --git a/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php b/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php index 50e1ff91dec..ff50defbe9c 100644 --- a/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php @@ -14,13 +14,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::NET_PATH) * @ORM\Entity */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] +#[ApiResource(uriTemplate: '/network_path_relation_dummies/{id}/network_path_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\NetworkPathRelationDummy::class, identifiers: ['id'], toProperty: 'networkPathRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::NET_PATH, operations: [new GetCollection()])] class NetworkPathDummy { /** @@ -29,7 +32,6 @@ class NetworkPathDummy * @ORM\Column(type="integer") */ private $id; - /** * @ORM\ManyToOne(targetEntity="NetworkPathRelationDummy", inversedBy="networkPathDummies") */ diff --git a/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php b/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php index 2b3a973abe5..18beb3cb3da 100644 --- a/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php @@ -14,15 +14,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::NET_PATH) * @ORM\Entity */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] class NetworkPathRelationDummy { /** @@ -31,10 +30,8 @@ class NetworkPathRelationDummy * @ORM\Column(type="integer") */ private $id; - /** * @ORM\OneToMany(targetEntity="NetworkPathDummy", mappedBy="networkPathRelationDummy") - * @ApiSubresource */ public $networkPathDummies; diff --git a/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php b/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php index 9050019e2de..41a31d1a036 100644 --- a/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php @@ -13,15 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; /** * No Collection Dummy. * - * @ApiResource(collectionOperations={}) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete()])] class NoCollectionDummy { /** diff --git a/tests/Fixtures/TestBundle/Entity/NonRelationResource.php b/tests/Fixtures/TestBundle/Entity/NonRelationResource.php index c48f6bf4268..c2660b9cb74 100644 --- a/tests/Fixtures/TestBundle/Entity/NonRelationResource.php +++ b/tests/Fixtures/TestBundle/Entity/NonRelationResource.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\NonResourceClass; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class NonRelationResource { /** @@ -29,7 +29,6 @@ class NonRelationResource * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var NonResourceClass */ diff --git a/tests/Fixtures/TestBundle/Entity/Order.php b/tests/Fixtures/TestBundle/Entity/Order.php index 1d9b4f3e2a5..14ab8e8095d 100644 --- a/tests/Fixtures/TestBundle/Entity/Order.php +++ b/tests/Fixtures/TestBundle/Entity/Order.php @@ -13,19 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; /** - * @ApiResource( - * attributes={"normalization_context"={"groups"={"order_read"}}}, - * forceEager=false - * ) * @ORM\Entity - * @ORM\Table(name="`order`") + * @ORM\Table (name="`order`") */ +#[ApiResource(normalizationContext: ['groups' => ['order_read']], forceEager: false)] class Order { /** @@ -37,14 +34,12 @@ class Order * @Groups({"order_read"}) */ private $id; - /** * @ORM\ManyToOne(targetEntity="Customer") * @ORM\JoinColumn(nullable=false) * @Groups({"order_read"}) */ public $customer; - /** * @ORM\ManyToOne(targetEntity="Customer") * @ORM\JoinColumn(nullable=false) diff --git a/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php b/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php index f91ece8bed6..56cb3521d79 100644 --- a/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php @@ -14,7 +14,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,39 +28,9 @@ * Overridden Operation Dummy. * * @author Amrouche Hamza - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"overridden_operation_dummy_read"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_write"}} - * }, - * collectionOperations={ - * "get"={"method"="GET"}, - * "post"={"method"="POST"}, - * "swagger"={ - * "path"="/override/swagger", - * "method"="GET", - * } - * }, - * itemOperations={ - * "swagger"={ - * "method"="GET", - * }, - * "get"={ - * "method"="GET", - * "normalization_context"={"groups"={"overridden_operation_dummy_get"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_get"}} - * }, - * "put"={ - * "method"="PUT", - * "normalization_context"={"groups"={"overridden_operation_dummy_put"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_put"}} - * }, - * "delete"={"method"="DELETE"} - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Get(normalizationContext: ['groups' => ['overridden_operation_dummy_get']], denormalizationContext: ['groups' => ['overridden_operation_dummy_get']]), new Put(normalizationContext: ['groups' => ['overridden_operation_dummy_put']], denormalizationContext: ['groups' => ['overridden_operation_dummy_put']]), new Delete(), new GetCollection(), new Post(), new GetCollection(uriTemplate: '/override/swagger')], normalizationContext: ['groups' => ['overridden_operation_dummy_read']], denormalizationContext: ['groups' => ['overridden_operation_dummy_write']])] class OverriddenOperationDummy { /** @@ -66,7 +41,6 @@ class OverriddenOperationDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The dummy name * @@ -76,7 +50,6 @@ class OverriddenOperationDummy * @ApiProperty(iri="http://schema.org/name") */ private $name; - /** * @var string|null The dummy name alias * @@ -85,7 +58,6 @@ class OverriddenOperationDummy * @ApiProperty(iri="https://schema.org/alternateName") */ private $alias; - /** * @var string|null A short description of the item * @@ -94,7 +66,6 @@ class OverriddenOperationDummy * @ApiProperty(iri="https://schema.org/description") */ public $description; - /** * @ORM\Column(nullable=true) * @Groups({"overridden_operation_dummy_write"}) diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummy.php b/tests/Fixtures/TestBundle/Entity/PatchDummy.php index 1a842597c29..b2adbd69c95 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummy.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummy.php @@ -13,20 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; /** * @author Kévin Dunglas - * - * @ApiResource( - * itemOperations={ - * "get", - * "patch"={"input_formats"={"json"={"application/merge-patch+json"}, "jsonapi"}} - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()])] class PatchDummy { /** @@ -35,7 +33,6 @@ class PatchDummy * @ORM\GeneratedValue(strategy="AUTO") */ public $id; - /** * @ORM\Column(nullable=true) */ diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php index 0100c0854d9..1f0d8c2f103 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php @@ -13,25 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * @author Kévin Dunglas - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"chicago"}}, - * "denormalization_context"={"groups"={"chicago"}}, - * }, - * itemOperations={ - * "get", - * "patch"={"input_formats"={"json"={"application/merge-patch+json"}, "jsonapi"}} - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] class PatchDummyRelation { /** @@ -40,7 +34,6 @@ class PatchDummyRelation * @ORM\GeneratedValue(strategy="AUTO") */ public $id; - /** * @ORM\ManyToOne(targetEntity="RelatedDummy") * @Groups({"chicago"}) diff --git a/tests/Fixtures/TestBundle/Entity/Payment.php b/tests/Fixtures/TestBundle/Entity/Payment.php index 6351fb11dea..e800ac595e1 100644 --- a/tests/Fixtures/TestBundle/Entity/Payment.php +++ b/tests/Fixtures/TestBundle/Entity/Payment.php @@ -13,25 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\Payment\VoidPaymentAction; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * - * @ApiResource( - * itemOperations={ - * "get", - * "post_void"={ - * "method"="POST", - * "path"="/payments/{id}/void", - * "controller"=VoidPaymentAction::class, - * "deserialize"=false, - * }, - * }, - * ) */ +#[ApiResource(operations: [new Get(), new Post(uriTemplate: '/payments/{id}/void', controller: VoidPaymentAction::class, deserialize: false), new Post(), new GetCollection()])] class Payment { /** @@ -42,14 +34,12 @@ class Payment * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * * @ORM\Column(type="decimal", precision=6, scale=2) */ private $amount; - /** * @ORM\OneToOne(targetEntity=VoidPayment::class, mappedBy="payment") */ @@ -75,7 +65,6 @@ public function void(): void if (null !== $this->voidPayment) { return; } - $this->voidPayment = new VoidPayment($this); } diff --git a/tests/Fixtures/TestBundle/Entity/Person.php b/tests/Fixtures/TestBundle/Entity/Person.php index d21a6ea4415..cde3eafc1c0 100644 --- a/tests/Fixtures/TestBundle/Entity/Person.php +++ b/tests/Fixtures/TestBundle/Entity/Person.php @@ -13,8 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -24,10 +23,9 @@ * Person. * * @author Antoine Bluchet - * - * @ApiResource(attributes={"normalization_context"={"groups"={"people.pets"}}}) * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['people.pets']])] class Person { /** @@ -36,13 +34,11 @@ class Person * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @ORM\Column(type="string") * @Groups({"people.pets"}) */ public $name; - /** * @ORM\OneToMany(targetEntity="PersonToPet", mappedBy="person") * @Groups({"people.pets"}) @@ -50,9 +46,7 @@ class Person * @var Collection */ public $pets; - /** - * @ApiSubresource * @ORM\OneToMany(targetEntity="Greeting", mappedBy="sender") */ public $sentGreetings; diff --git a/tests/Fixtures/TestBundle/Entity/Pet.php b/tests/Fixtures/TestBundle/Entity/Pet.php index 159a67353eb..6f3da59de4c 100644 --- a/tests/Fixtures/TestBundle/Entity/Pet.php +++ b/tests/Fixtures/TestBundle/Entity/Pet.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -23,10 +23,9 @@ * Pet. * * @author Antoine Bluchet - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class Pet { /** @@ -35,13 +34,11 @@ class Pet * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @ORM\Column(type="string") * @Groups({"people.pets"}) */ public $name; - /** * @ORM\OneToMany(targetEntity="PersonToPet", mappedBy="pet") * diff --git a/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php b/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php index c40d98a67b5..aa117fc2746 100644 --- a/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php +++ b/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php @@ -13,17 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Regression test for https://github.com/api-platform/api-platform/issues/1085. * * @author Antoine Bluchet - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class PlainObjectDummy { /** @@ -32,12 +31,10 @@ class PlainObjectDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string */ private $content; - /** * @var array */ diff --git a/tests/Fixtures/TestBundle/Entity/Question.php b/tests/Fixtures/TestBundle/Entity/Question.php index 3943ca0a00a..50f6ac0f549 100644 --- a/tests/Fixtures/TestBundle/Entity/Question.php +++ b/tests/Fixtures/TestBundle/Entity/Question.php @@ -13,14 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * @ApiResource */ +#[ApiResource] +#[ApiResource(uriTemplate: '/answers/{id}/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer::class, identifiers: ['id'], toProperty: 'answer')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/questions/{id}/answer/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], fromProperty: 'answer'), 'answer' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer::class, identifiers: [], expandedValue: 'answer', toProperty: 'answer')], status: 200, operations: [new GetCollection()])] class Question { /** @@ -29,16 +33,13 @@ class Question * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @ORM\Column(nullable=true) */ private $content; - /** * @ORM\OneToOne(targetEntity="Answer", inversedBy="question") * @ORM\JoinColumn(name="answer_id", referencedColumnName="id", unique=true) - * @ApiSubresource */ private $answer; diff --git a/tests/Fixtures/TestBundle/Entity/RPC.php b/tests/Fixtures/TestBundle/Entity/RPC.php index 0647a570f91..2f3fac9d713 100644 --- a/tests/Fixtures/TestBundle/Entity/RPC.php +++ b/tests/Fixtures/TestBundle/Entity/RPC.php @@ -13,20 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RPCOutput; /** * RPC-like resource. - * - * @ApiResource( - * itemOperations={}, - * collectionOperations={ - * "post"={"status"=202, "messenger"=true, "path"="rpc", "output"=false}, - * "post_output"={"method"="POST", "status"=200, "path"="rpc_output", "output"=RPCOutput::class} - * }, - * ) */ +#[ApiResource(operations: [new Post(status: 202, messenger: true, uriTemplate: 'rpc', output: false), new Post(status: 200, uriTemplate: 'rpc_output', output: RPCOutput::class)])] class RPC { /** diff --git a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php index 87472305a71..d19baeadecb 100644 --- a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; /** * @ORM\Entity - * @ApiResource */ +#[ApiResource] class RamseyUuidDummy { /** @@ -31,7 +31,6 @@ class RamseyUuidDummy * @ORM\Column(type="uuid", unique=true) */ private $id; - /** * @var \Ramsey\Uuid\UuidInterface|null * diff --git a/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php b/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php index 40e44dcf4d5..f6fe92e3676 100644 --- a/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php +++ b/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php @@ -14,13 +14,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class ReadableOnlyProperty { /** @@ -31,7 +31,6 @@ class ReadableOnlyProperty * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The foo name * diff --git a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php index f9b15024a2e..42b742ed381 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php @@ -14,8 +14,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -26,22 +30,26 @@ * Related Dummy. * * @author Kévin Dunglas - * - * @ApiResource(graphql={"item_query", "update"={"normalization_context"={"groups"={"chicago", "fakemanytomany"}}, "denormalization_context"={"groups"={"friends"}}}}, iri="https://schema.org/Product", attributes={"normalization_context"={"groups"={"friends"}}, "filters"={"related_dummy.friends", "related_dummy.complex_sub_query"}}) * @ORM\Entity */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] class RelatedDummy extends ParentDummy { /** * @ApiProperty(writable=false) - * @ApiSubresource * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") * @Groups({"chicago", "friends"}) */ private $id; - /** * @var string|null A name * @@ -49,13 +57,11 @@ class RelatedDummy extends ParentDummy * @Groups({"friends"}) */ public $name; - /** * @ORM\Column * @Groups({"barcelona", "chicago", "friends"}) */ protected $symfony = 'symfony'; - /** * @var \DateTime|null A dummy date * @@ -64,21 +70,16 @@ class RelatedDummy extends ParentDummy * @Groups({"friends"}) */ public $dummyDate; - /** - * @ApiSubresource * @ORM\ManyToOne(targetEntity="ThirdLevel", cascade={"persist"}) * @Groups({"barcelona", "chicago", "friends"}) */ public $thirdLevel; - /** - * @ApiSubresource * @ORM\OneToMany(targetEntity="RelatedToDummyFriend", cascade={"persist"}, mappedBy="relatedDummy") * @Groups({"fakemanytomany", "friends"}) */ public $relatedToDummyFriend; - /** * @var bool|null A dummy bool * @@ -86,7 +87,6 @@ class RelatedDummy extends ParentDummy * @Groups({"friends"}) */ public $dummyBoolean; - /** * @var EmbeddableDummy * diff --git a/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php index 3d79617e3df..4582a2a3da6 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -25,13 +25,9 @@ * Related to Normalized Dummy. * * @author Amrouche Hamza - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"related_output", "output"}}, - * "denormalization_context"={"groups"={"related_input", "input"}} - * }) * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['related_output', 'output']], denormalizationContext: ['groups' => ['related_input', 'input']])] class RelatedNormalizedDummy { /** @@ -43,7 +39,6 @@ class RelatedNormalizedDummy * @Groups({"related_output", "related_input"}) */ private $id; - /** * @var string The dummy name * @@ -53,7 +48,6 @@ class RelatedNormalizedDummy * @Groups({"related_output", "related_input"}) */ private $name; - /** * @var Collection Several Normalized dummies * diff --git a/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php index ceace5fb9ab..f2ebf4bfc81 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php @@ -13,18 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Related Owned Dummy. * * @author Sergey V. Ryabov - * - * @ApiResource(iri="https://schema.org/Product") * @ORM\Entity */ +#[ApiResource(types: ['https://schema.org/Product'])] class RelatedOwnedDummy { /** @@ -33,20 +32,16 @@ class RelatedOwnedDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string|null A name * * @ORM\Column(nullable=true) */ public $name; - /** - * @var Dummy - * + * @var \Dummy * @ORM\OneToOne(targetEntity="Dummy", cascade={"persist"}, inversedBy="relatedOwnedDummy") * @ORM\JoinColumn(nullable=false) - * @ApiSubresource */ public $owningDummy; diff --git a/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php index 0a8fc0589c8..13c7aa45f51 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php @@ -13,18 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * Related Owning Dummy. * * @author Sergey V. Ryabov - * - * @ApiResource(iri="https://schema.org/Product") * @ORM\Entity */ +#[ApiResource(types: ['https://schema.org/Product'])] class RelatedOwningDummy { /** @@ -33,19 +32,15 @@ class RelatedOwningDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string|null A name * * @ORM\Column(nullable=true) */ public $name; - /** - * @var Dummy|null - * + * @var \Dummy|null * @ORM\OneToOne(targetEntity="Dummy", cascade={"persist"}, mappedBy="relatedOwningDummy") - * @ApiSubresource */ public $ownedDummy; @@ -85,7 +80,6 @@ public function getOwnedDummy(): Dummy public function setOwnedDummy(Dummy $ownedDummy) { $this->ownedDummy = $ownedDummy; - if ($this !== $this->ownedDummy->getRelatedOwningDummy()) { $this->ownedDummy->setRelatedOwningDummy($this); } diff --git a/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php index 063a2bc5383..07c8ec01f1c 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php @@ -13,25 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource( - * attributes={"security"="is_granted('ROLE_ADMIN')"}, - * collectionOperations={ - * "get"={"security"="is_granted('ROLE_ADMIN')"}, - * }, - * itemOperations={ - * "get"={"security"="is_granted('ROLE_ADMIN')"}, - * }, - * graphql={ - * "item_query"={"security"="is_granted('ROLE_ADMIN')"}, - * "collection_query"={"security"="is_granted('ROLE_ADMIN')"}, - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_ADMIN\')'), new GetCollection(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\')'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')')], security: 'is_granted(\'ROLE_ADMIN\')')] class RelatedSecuredDummy { /** diff --git a/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php b/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php index bee990b00a1..df9155b59f1 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php @@ -14,7 +14,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -22,9 +24,14 @@ /** * Related To Dummy Friend represent an association table for a manytomany relation. * - * @ApiResource(attributes={"normalization_context"={"groups"={"fakemanytomany"}}, "filters"={"related_to_dummy_friend.name"}}) * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['fakemanytomany']], filters: ['related_to_dummy_friend.name'])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] class RelatedToDummyFriend { /** @@ -36,7 +43,6 @@ class RelatedToDummyFriend * @Groups({"fakemanytomany", "friends"}) */ private $name; - /** * @var string|null The dummy description * @@ -44,7 +50,6 @@ class RelatedToDummyFriend * @Groups({"fakemanytomany", "friends"}) */ private $description; - /** * @ORM\Id * @ORM\ManyToOne(targetEntity="DummyFriend") @@ -53,7 +58,6 @@ class RelatedToDummyFriend * @Assert\NotNull */ private $dummyFriend; - /** * @ORM\Id * @ORM\ManyToOne(targetEntity="RelatedDummy", inversedBy="relatedToDummyFriend") diff --git a/tests/Fixtures/TestBundle/Entity/Relation1.php b/tests/Fixtures/TestBundle/Entity/Relation1.php index cadf4f9cf28..91a7ca1025f 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation1.php +++ b/tests/Fixtures/TestBundle/Entity/Relation1.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity * * @author Kévin Dunglas */ +#[ApiResource] class Relation1 { /** @@ -30,7 +30,6 @@ class Relation1 * @ORM\GeneratedValue */ public $id; - /** * @ORM\ManyToOne(targetEntity="Relation2", inversedBy="relation1s") */ diff --git a/tests/Fixtures/TestBundle/Entity/Relation2.php b/tests/Fixtures/TestBundle/Entity/Relation2.php index 784ceb6dd86..61eba9f2c37 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation2.php +++ b/tests/Fixtures/TestBundle/Entity/Relation2.php @@ -13,16 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity * * @author Kévin Dunglas */ +#[ApiResource] class Relation2 { /** @@ -31,7 +31,6 @@ class Relation2 * @ORM\GeneratedValue */ public $id; - /** * @ORM\OneToMany(targetEntity="Relation1", mappedBy="relation2") */ diff --git a/tests/Fixtures/TestBundle/Entity/Relation3.php b/tests/Fixtures/TestBundle/Entity/Relation3.php index fcc5e6aebd7..dd73e75f8ac 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation3.php +++ b/tests/Fixtures/TestBundle/Entity/Relation3.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class Relation3 { /** @@ -30,7 +30,6 @@ class Relation3 * @ORM\GeneratedValue */ public $id; - /** * @var Collection * @ORM\ManyToMany(targetEntity="Relation2", orphanRemoval=true) diff --git a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php index 6a5784b5dc2..050719faf69 100644 --- a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,24 +26,9 @@ * Relation Embedder. * * @author Kévin Dunglas - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"barcelona"}}, - * "denormalization_context"={"groups"={"chicago"}}, - * "hydra_context"={"@type"="hydra:Operation", "hydra:title"="A custom operation", "returns"="xmls:string"} - * }, - * itemOperations={ - * "get", - * "put"={}, - * "delete", - * "custom_get"={"route_name"="relation_embedded.custom_get", "method"="GET"}, - * "custom1"={"path"="/api/custom-call/{id}", "method"="GET"}, - * "custom2"={"path"="/api/custom-call/{id}", "method"="PUT"}, - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(routeName: 'relation_embedded.custom_get'), new Get(uriTemplate: '/api/custom-call/{id}'), new Put(uriTemplate: '/api/custom-call/{id}'), new Post(), new GetCollection()], normalizationContext: ['groups' => ['barcelona']], denormalizationContext: ['groups' => ['chicago']], hydraContext: ['@type' => 'hydra:Operation', 'hydra:title' => 'A custom operation', 'returns' => 'xmls:string'])] class RelationEmbedder { /** @@ -47,25 +37,21 @@ class RelationEmbedder * @ORM\GeneratedValue(strategy="AUTO") */ public $id; - /** * @ORM\Column * @Groups({"chicago"}) */ public $paris = 'Paris'; - /** * @ORM\Column * @Groups({"barcelona", "chicago"}) */ public $krondstadt = 'Krondstadt'; - /** * @ORM\ManyToOne(targetEntity="RelatedDummy", cascade={"persist"}) * @Groups({"chicago", "barcelona"}) */ public $anotherRelated; - /** * @ORM\ManyToOne(targetEntity="RelatedDummy") * @Groups({"barcelona", "chicago"}) diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php b/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php index 93a6bcc8f45..9de3fa686f6 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class ResourceWithBoolean { /** @@ -30,7 +30,6 @@ class ResourceWithBoolean * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var bool * diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php b/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php index 41407e74951..1d7233deab2 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class ResourceWithFloat { /** @@ -30,7 +30,6 @@ class ResourceWithFloat * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var float * diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php b/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php index be76f2571f8..bdb495bbd62 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class ResourceWithInteger { /** @@ -30,7 +30,6 @@ class ResourceWithInteger * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var int * diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithString.php b/tests/Fixtures/TestBundle/Entity/ResourceWithString.php index 07020e1a4f1..0bd096ed0de 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithString.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithString.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class ResourceWithString { /** @@ -30,7 +30,6 @@ class ResourceWithString * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/SecuredDummy.php b/tests/Fixtures/TestBundle/Entity/SecuredDummy.php index 198d8f39c35..19010291638 100644 --- a/tests/Fixtures/TestBundle/Entity/SecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SecuredDummy.php @@ -14,7 +14,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -24,32 +31,9 @@ * Secured resource. * * @author Kévin Dunglas - * - * @ApiResource( - * attributes={"security"="is_granted('ROLE_USER')"}, - * collectionOperations={ - * "get"={"security"="is_granted('ROLE_USER') or is_granted('ROLE_ADMIN')"}, - * "get_from_data_provider_generator"={ - * "method"="GET", - * "path"="custom_data_provider_generator", - * "security"="is_granted('ROLE_USER')" - * }, - * "post"={"security"="is_granted('ROLE_ADMIN')"} - * }, - * itemOperations={ - * "get"={"security"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "put"={"security_post_denormalize"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * }, - * graphql={ - * "item_query"={"security"="is_granted('ROLE_ADMIN') or (is_granted('ROLE_USER') and object.getOwner() == user)"}, - * "collection_query"={"security"="is_granted('ROLE_ADMIN')"}, - * "delete"={}, - * "update"={"security_post_denormalize"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * "create"={"security"="is_granted('ROLE_ADMIN')", "security_message"="Only admins can create a secured dummy."} - * } - * ) * @ORM\Entity */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(security: 'is_granted(\'ROLE_USER\') or is_granted(\'ROLE_ADMIN\')'), new GetCollection(uriTemplate: 'custom_data_provider_generator', security: 'is_granted(\'ROLE_USER\')'), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\') or (is_granted(\'ROLE_USER\') and object.getOwner() == user)'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')'), new Mutation(name: 'delete'), new Mutation(name: 'update', securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] class SecuredDummy { /** @@ -60,7 +44,6 @@ class SecuredDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The title * @@ -68,14 +51,12 @@ class SecuredDummy * @Assert\NotBlank */ private $title; - /** * @var string The description * * @ORM\Column */ private $description = ''; - /** * @var string The dummy secret property, only readable/writable by specific users * @@ -83,7 +64,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ private $adminOnlyProperty = ''; - /** * @var string Secret property, only readable/writable by owners * @@ -94,7 +74,6 @@ class SecuredDummy * ) */ private $ownerOnlyProperty = ''; - /** * @var string The owner * @@ -102,7 +81,6 @@ class SecuredDummy * @Assert\NotBlank */ private $owner; - /** * A collection of dummies that only admins can access. * @@ -113,7 +91,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ public $relatedDummies; - /** * A dummy that only admins can access. * @@ -124,7 +101,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ protected $relatedDummy; - /** * A collection of dummies that only users can access. The security on RelatedSecuredDummy shouldn't be run. * @@ -135,7 +111,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_USER')") */ public $relatedSecuredDummies; - /** * A dummy that only users can access. The security on RelatedSecuredDummy shouldn't be run. * @@ -146,7 +121,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_USER')") */ protected $relatedSecuredDummy; - /** * Collection of dummies that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * @@ -156,7 +130,6 @@ class SecuredDummy * @ORM\JoinTable(name="secured_dummy_public_related_secured_dummy") */ public $publicRelatedSecuredDummies; - /** * A dummy that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * diff --git a/tests/Fixtures/TestBundle/Entity/Site.php b/tests/Fixtures/TestBundle/Entity/Site.php index 15e4aa6a3d1..40963c1edf7 100644 --- a/tests/Fixtures/TestBundle/Entity/Site.php +++ b/tests/Fixtures/TestBundle/Entity/Site.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class Site { /** diff --git a/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php b/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php index d8870357047..4578916b183 100644 --- a/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php @@ -14,14 +14,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy::class, identifiers: ['slug'], toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], fromProperty: 'parentDummy'), 'parentDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy::class, identifiers: [], expandedValue: 'parent_dummy', toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] class SlugChildDummy { /** @@ -34,7 +37,6 @@ class SlugChildDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The slug used as API identifier * @@ -43,12 +45,9 @@ class SlugChildDummy * @ORM\Column(type="string", length=255, unique=true) */ private $slug; - /** * @ORM\ManyToOne(targetEntity="ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy", inversedBy="childDummies") * @ORM\JoinColumn(name="parent_dummy_id", referencedColumnName="id") - * - * @ApiSubresource */ private $parentDummy; diff --git a/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php b/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php index 6b60db60dc6..c7a220a4861 100644 --- a/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php @@ -14,8 +14,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -23,9 +24,11 @@ /** * Custom Identifier Dummy With Subresource. * - * @ApiResource(attributes={"identifiers"="slug"}) * @ORM\Entity */ +#[ApiResource(uriVariables: 'slug')] +#[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies/{childDummies}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], toProperty: 'parentDummy'), 'childDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] class SlugParentDummy { /** @@ -38,7 +41,6 @@ class SlugParentDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string The slug used a API identifier * @@ -47,12 +49,9 @@ class SlugParentDummy * @ORM\Column(type="string", length=255, unique=true) */ private $slug; - /** - * @var Collection + * @var \Collection * @ORM\OneToMany(targetEntity="ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy", mappedBy="parentDummy") - * - * @ApiSubresource */ private $childDummies; diff --git a/tests/Fixtures/TestBundle/Entity/SoMany.php b/tests/Fixtures/TestBundle/Entity/SoMany.php index b2404392ea7..4c0c37f5c03 100644 --- a/tests/Fixtures/TestBundle/Entity/SoMany.php +++ b/tests/Fixtures/TestBundle/Entity/SoMany.php @@ -14,23 +14,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * @ApiResource(attributes={ - * "pagination_partial"=true, - * "pagination_via_cursor"={ - * {"field"="id", "direction"="DESC"} - * } - * }) - * - * @ApiFilter(RangeFilter::class, properties={"id"}) - * @ApiFilter(OrderFilter::class, properties={"id"="DESC"}) + * @ApiFilter (RangeFilter::class, properties={"id"}) + * @ApiFilter (OrderFilter::class, properties={"id"="DESC"}) */ +#[ApiResource(paginationPartial: true, paginationViaCursor: [['field' => 'id', 'direction' => 'DESC']])] class SoMany { /** @@ -39,7 +33,6 @@ class SoMany * @ORM\GeneratedValue(strategy="AUTO") */ public $id; - /** * @ORM\Column(nullable=true) */ diff --git a/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php b/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php index f6e4c4cbc66..531f9a2ed3c 100644 --- a/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Component\Uid\Uuid; @@ -22,10 +22,10 @@ if (\PHP_VERSION_ID >= 70200 && class_exists(Uuid::class) && class_exists(UuidType::class)) { /** * @ORM\Entity - * @ApiResource * * @author Vincent Chalamon */ + #[ApiResource] class SymfonyUuidDummy { /** @@ -34,7 +34,6 @@ class SymfonyUuidDummy * @ORM\GeneratedValue(strategy="NONE") */ private $id; - /** * @ORM\Column(nullable=true) */ diff --git a/tests/Fixtures/TestBundle/Entity/ThirdLevel.php b/tests/Fixtures/TestBundle/Entity/ThirdLevel.php index 12f2d6fe66f..1b20b32d95d 100644 --- a/tests/Fixtures/TestBundle/Entity/ThirdLevel.php +++ b/tests/Fixtures/TestBundle/Entity/ThirdLevel.php @@ -13,8 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,10 +23,14 @@ * Third Level. * * @author Kévin Dunglas - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] class ThirdLevel { /** @@ -36,7 +41,6 @@ class ThirdLevel * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var int * @@ -44,21 +48,17 @@ class ThirdLevel * @Groups({"barcelona", "chicago"}) */ private $level = 3; - /** * @var bool * * @ORM\Column(type="boolean") */ private $test = true; - /** - * @ApiSubresource * @ORM\ManyToOne(targetEntity="FourthLevel", cascade={"persist"}) * @Groups({"barcelona", "chicago", "friends"}) */ public $fourthLevel; - /** * @ORM\ManyToOne(targetEntity=FourthLevel::class, cascade={"persist"}) */ diff --git a/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php b/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php index c25bdea09eb..c18027b75f8 100644 --- a/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php @@ -13,13 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * @ApiResource */ +#[ApiResource] class TruncatedDummy { /** @@ -28,7 +29,6 @@ class TruncatedDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @ORM\Column(type="decimal", precision=4, scale=1, nullable=false) */ diff --git a/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php index 0e4f1b11947..863376fd762 100644 --- a/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php @@ -13,17 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * UpperCaseIdentifier dummy. * * @author Exploit.cz - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class UpperCaseIdentifierDummy { /** @@ -33,7 +32,6 @@ class UpperCaseIdentifierDummy * @ORM\Id */ private $Uuid; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php b/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php index 652eae1a1f2..d4dfb52a051 100644 --- a/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php +++ b/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php @@ -13,25 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; /** * @author Daniel West * * Resource with an ID that will be URL encoded - * * @ORM\Entity - * - * @ApiResource( - * itemOperations={ - * "get"={ - * "method"="GET", - * "requirements"={"id"=".+"} - * } - * } - * ) */ +#[ApiResource(operations: [new Get(requirements: ['id' => '.+']), new Post(), new GetCollection()])] class UrlEncodedId { /** diff --git a/tests/Fixtures/TestBundle/Entity/User.php b/tests/Fixtures/TestBundle/Entity/User.php index 5c237dfa812..4fc45f1af3a 100644 --- a/tests/Fixtures/TestBundle/Entity/User.php +++ b/tests/Fixtures/TestBundle/Entity/User.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\PasswordResetRequest; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\PasswordResetRequestResult; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; @@ -26,39 +31,12 @@ * A User. * * @ORM\Entity - * @ORM\Table(name="user_test") - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"user", "user-read"}}, - * "denormalization_context"={"groups"={"user", "user-write"}} - * }, - * collectionOperations={ - * "post", - * "get", - * "post_password_reset_request"={ - * "method"="POST", - * "path"="/users/password_reset_request", - * "messenger"="input", - * "input"=PasswordResetRequest::class, - * "output"=PasswordResetRequestResult::class, - * "normalization_context"={ - * "groups"={"user_password_reset_request"}, - * }, - * "denormalization_context"={ - * "groups"={"user_password_reset_request"}, - * }, - * }, - * }, - * itemOperations={"get", "put", "delete", - * "recover_password"={ - * "input"=RecoverPasswordInput::class, "output"=RecoverPasswordOutput::class, "method"="PUT", "path"="users/recover/{id}" - * } - * } - * ) + * @ORM\Table (name="user_test") * * @author Théo FIDRY * @author Kévin Dunglas */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Put(input: RecoverPasswordInput::class, output: RecoverPasswordOutput::class, uriTemplate: 'users/recover/{id}'), new Post(), new GetCollection(), new Post(uriTemplate: '/users/password_reset_request', messenger: 'input', input: PasswordResetRequest::class, output: PasswordResetRequestResult::class, normalizationContext: ['groups' => ['user_password_reset_request']], denormalizationContext: ['groups' => ['user_password_reset_request']])], normalizationContext: ['groups' => ['user', 'user-read']], denormalizationContext: ['groups' => ['user', 'user-write']])] class User extends AbstractSecurityUser { /** @@ -69,14 +47,12 @@ class User extends AbstractSecurityUser * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var string|null * * @Groups({"user"}) */ private $email; - /** * @var string|null * @@ -84,7 +60,6 @@ class User extends AbstractSecurityUser * @Groups({"user"}) */ private $fullname; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Entity/UserResource.php b/tests/Fixtures/TestBundle/Entity/UserResource.php index 919eb688b26..cee2bc9c954 100644 --- a/tests/Fixtures/TestBundle/Entity/UserResource.php +++ b/tests/Fixtures/TestBundle/Entity/UserResource.php @@ -13,22 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\UserResetPasswordDto; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource( - * collectionOperations={ - * "post"={ - * "method"="POST", - * "path"="/user-reset-password", - * "input"=UserResetPasswordDto::class - * } - * }, - * itemOperations={} - * ) - */ +#[ApiResource(operations: [new Post(uriTemplate: '/user-reset-password', input: UserResetPasswordDto::class)])] final class UserResource { /** diff --git a/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php index ca55c118c21..2f90db78aff 100644 --- a/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Custom identifier dummy. * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class UuidIdentifierDummy { /** @@ -31,7 +31,6 @@ class UuidIdentifierDummy * @ORM\Id */ private $uuid; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php index 363c3358fe1..c8f84f4ba20 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php @@ -13,19 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"car_read"}}, - * "denormalization_context"={"groups"={"car_write"}} - * }) * @ORM\Entity */ +#[ApiResource(normalizationContext: ['groups' => ['car_read']], denormalizationContext: ['groups' => ['car_write']])] class VoDummyCar extends VoDummyVehicle { /** @@ -35,7 +32,6 @@ class VoDummyCar extends VoDummyVehicle * @Groups({"car_read", "car_write"}) */ private $mileage; - /** * @var string * @@ -43,7 +39,6 @@ class VoDummyCar extends VoDummyVehicle * @Groups({"car_read", "car_write"}) */ private $bodyType; - /** * @var VoDummyInspection[]|Collection * @@ -52,13 +47,8 @@ class VoDummyCar extends VoDummyVehicle */ private $inspections; - public function __construct( - string $make, - VoDummyInsuranceCompany $insuranceCompany, - array $drivers, - int $mileage, - string $bodyType = 'coupe' - ) { + public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, int $mileage, string $bodyType = 'coupe') + { parent::__construct($make, $insuranceCompany, $drivers); $this->mileage = $mileage; $this->bodyType = $bodyType; diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php b/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php index a0b0569291b..88b7347a524 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php @@ -13,18 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class VoDummyDriver { use VoDummyIdAwareTrait; - /** * @var string * @@ -32,7 +31,6 @@ class VoDummyDriver * @Groups({"car_read", "car_write"}) */ private $firstName; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php index d4d8ee89385..bedd0aa3f25 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php @@ -13,25 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use DateTime; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"inspection_read"}}, - * "denormalization_context"={"groups"={"inspection_write"}} - * }, - * graphql={} - * ) * @ORM\Entity */ +#[ApiResource(graphQlOperations: [], normalizationContext: ['groups' => ['inspection_read']], denormalizationContext: ['groups' => ['inspection_write']])] class VoDummyInspection { use VoDummyIdAwareTrait; - /** * @var bool * @@ -39,7 +32,6 @@ class VoDummyInspection * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) */ private $accepted; - /** * @var VoDummyCar|null * @@ -47,7 +39,6 @@ class VoDummyInspection * @Groups({"inspection_read", "inspection_write"}) */ private $car; - /** * @var DateTime * @@ -55,7 +46,6 @@ class VoDummyInspection * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) */ private $performed; - private $attributeWithoutConstructorEquivalent; public function __construct(bool $accepted, VoDummyCar $car, DateTime $performed = null, string $parameterWhichIsNotClassAttribute = '') diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php b/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php index 0795a0ad55d..eb639f5e7fa 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php @@ -13,18 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class VoDummyInsuranceCompany { use VoDummyIdAwareTrait; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Entity/VoidPayment.php b/tests/Fixtures/TestBundle/Entity/VoidPayment.php index 09bcc880681..089da723146 100644 --- a/tests/Fixtures/TestBundle/Entity/VoidPayment.php +++ b/tests/Fixtures/TestBundle/Entity/VoidPayment.php @@ -13,14 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity - * - * @ApiResource */ +#[ApiResource] class VoidPayment { /** @@ -31,7 +30,6 @@ class VoidPayment * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @ORM\OneToOne(targetEntity=Payment::class, inversedBy="voidPayment") * @ORM\JoinColumn(nullable=false) diff --git a/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php index e9553d1cf0c..a1d926b5ff0 100644 --- a/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php +++ b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ApiResource * @ORM\Entity */ +#[ApiResource] class WithJsonDummy { /** @@ -30,7 +30,6 @@ class WithJsonDummy * @ORM\GeneratedValue(strategy="AUTO") */ private $id; - /** * @var array|null * diff --git a/tests/Fixtures/TestBundle/Entity/WritableId.php b/tests/Fixtures/TestBundle/Entity/WritableId.php index 0d465adab31..53c7b167653 100644 --- a/tests/Fixtures/TestBundle/Entity/WritableId.php +++ b/tests/Fixtures/TestBundle/Entity/WritableId.php @@ -13,16 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * @author Kévin Dunglas - * - * @ApiResource * @ORM\Entity */ +#[ApiResource] class WritableId { /** @@ -31,7 +30,6 @@ class WritableId * @ORM\Column(type="guid") */ public $id; - /** * @ORM\Column */ diff --git a/tests/Fixtures/TestBundle/Model/MediaObject.php b/tests/Fixtures/TestBundle/Model/MediaObject.php index 18cda6d2a96..53c3aa557d0 100644 --- a/tests/Fixtures/TestBundle/Model/MediaObject.php +++ b/tests/Fixtures/TestBundle/Model/MediaObject.php @@ -14,36 +14,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; /** - * @ApiResource( - * iri="http://schema.org/MediaObject", - * graphql={ - * "upload"={ - * "mutation"="app.graphql.mutation_resolver.upload_media_object", - * "args"={ - * "file"={"type"="Upload!", "description"="Upload a file"} - * } - * }, - * "uploadMultiple"={ - * "mutation"="app.graphql.mutation_resolver.upload_multiple_media_object", - * "args"={ - * "files"={"type"="[Upload!]!", "description"="Upload multiple files"} - * } - * } - * } - * ) - * * @author Mahmood Bazdar */ +#[ApiResource(graphQlOperations: [new Mutation(name: 'upload', resolver: 'app.graphql.mutation_resolver.upload_media_object', args: ['file' => ['type' => 'Upload!', 'description' => 'Upload a file']]), new Mutation(name: 'uploadMultiple', resolver: 'app.graphql.mutation_resolver.upload_multiple_media_object', args: ['files' => ['type' => '[Upload!]!', 'description' => 'Upload multiple files']])], types: ['http://schema.org/MediaObject'])] class MediaObject { /** * @ApiProperty(identifier=true) */ public $id; - /** * @var string */ diff --git a/tests/Fixtures/TestBundle/Model/ProductInterface.php b/tests/Fixtures/TestBundle/Model/ProductInterface.php index a2780efbcd8..70b2451c6e8 100644 --- a/tests/Fixtures/TestBundle/Model/ProductInterface.php +++ b/tests/Fixtures/TestBundle/Model/ProductInterface.php @@ -14,23 +14,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource( - * shortName="Product", - * attributes={"identifiers"="code", "provider"=ProductProvider::class}, - * normalizationContext={ - * "groups"={"product_read"}, - * }, - * denormalizationContext={ - * "groups"={"product_write"}, - * }, - * ) - */ +#[ApiResource(shortName: 'Product', uriVariables: 'code', provider: ProductProvider::class, normalizationContext: ['groups' => ['product_read']], denormalizationContext: ['groups' => ['product_write']])] interface ProductInterface { public function getId(); diff --git a/tests/Fixtures/TestBundle/Model/SerializableResource.php b/tests/Fixtures/TestBundle/Model/SerializableResource.php index 1a7cb80c30b..5c2e2639979 100644 --- a/tests/Fixtures/TestBundle/Model/SerializableResource.php +++ b/tests/Fixtures/TestBundle/Model/SerializableResource.php @@ -14,15 +14,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; /** * Resource linked to an external API. * - * @ApiResource - * * @author Vincent Chalamon */ +#[ApiResource] class SerializableResource { /** @@ -31,12 +30,10 @@ class SerializableResource * @ApiProperty(identifier=true) */ public $id; - /** * @var string */ public $foo; - /** * @var string */ diff --git a/tests/Fixtures/TestBundle/Model/TaxonInterface.php b/tests/Fixtures/TestBundle/Model/TaxonInterface.php index 80d29146736..a13531eb99d 100644 --- a/tests/Fixtures/TestBundle/Model/TaxonInterface.php +++ b/tests/Fixtures/TestBundle/Model/TaxonInterface.php @@ -14,22 +14,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ApiResource( - * attributes={"identifiers"="code"}, - * shortName="Taxon", - * normalizationContext={ - * "groups"={"taxon_read"}, - * }, - * denormalizationContext={ - * "groups"={"taxon_write"}, - * }, - * ) - */ +#[ApiResource(shortName: 'Taxon', uriVariables: 'code', normalizationContext: ['groups' => ['taxon_read']], denormalizationContext: ['groups' => ['taxon_write']])] interface TaxonInterface { public function getId(); From 7437a843393ac979d040c79d3e41d3681fd830fd Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 3 May 2022 10:29:01 +0200 Subject: [PATCH 02/56] feat: remove core tests --- src/Core/Action/EntrypointAction.php | 22 - src/Core/Action/ExceptionAction.php | 22 - src/Core/Action/NotFoundAction.php | 22 - src/Core/Action/PlaceholderAction.php | 22 - src/Core/Annotation/ApiFilter.php | 96 - src/Core/Annotation/ApiProperty.php | 165 - src/Core/Annotation/ApiResource.php | 251 -- src/Core/Annotation/ApiSubresource.php | 48 - .../Annotation/AttributesHydratorTrait.php | 99 - src/Core/Annotation/TemporaryApiResource.php | 21 - src/Core/Api/CachedIdentifiersExtractor.php | 132 - src/Core/Api/Entrypoint.php | 22 - src/Core/Api/FilterCollection.php | 33 - src/Core/Api/FilterCollectionFactory.php | 54 - src/Core/Api/FilterLocatorTrait.php | 23 - src/Core/Api/FormatMatcher.php | 22 - src/Core/Api/FormatsProvider.php | 109 - src/Core/Api/FormatsProviderInterface.php | 29 - src/Core/Api/IdentifiersExtractor.php | 121 - .../Api/IdentifiersExtractorInterface.php | 38 - src/Core/Api/IriConverterInterface.php | 68 - ...OperationAwareFormatsProviderInterface.php | 29 - .../Api/OperationMethodResolverInterface.php | 40 - src/Core/Api/OperationType.php | 22 - .../Api/OperationTypeDeprecationHelper.php | 44 - src/Core/Api/ResourceClassResolver.php | 22 - .../Bridge/Doctrine/Common/DataPersister.php | 105 - .../Common/Filter/BooleanFilterTrait.php | 23 - .../Common/Filter/DateFilterTrait.php | 23 - .../Common/Filter/ExistsFilterTrait.php | 23 - .../Common/Filter/NumericFilterTrait.php | 23 - .../Common/Filter/OrderFilterTrait.php | 23 - .../Common/Filter/RangeFilterTrait.php | 23 - .../Common/Filter/SearchFilterTrait.php | 23 - .../Doctrine/Common/PropertyHelperTrait.php | 23 - .../Common/Util/IdentifierManagerTrait.php | 113 - .../PublishMercureUpdatesListener.php | 285 -- .../EventListener/PurgeHttpCacheListener.php | 22 - .../Doctrine/EventListener/WriteListener.php | 22 - .../MongoDbOdm/CollectionDataProvider.php | 108 - .../MongoDbOdm/Extension/FilterExtension.php | 22 - .../MongoDbOdm/Extension/OrderExtension.php | 22 - .../Extension/PaginationExtension.php | 22 - .../MongoDbOdm/Filter/AbstractFilter.php | 22 - .../MongoDbOdm/Filter/BooleanFilter.php | 22 - .../Doctrine/MongoDbOdm/Filter/DateFilter.php | 22 - .../MongoDbOdm/Filter/ExistsFilter.php | 22 - .../MongoDbOdm/Filter/NumericFilter.php | 22 - .../MongoDbOdm/Filter/OrderFilter.php | 22 - .../MongoDbOdm/Filter/RangeFilter.php | 22 - .../MongoDbOdm/Filter/SearchFilter.php | 223 -- .../Doctrine/MongoDbOdm/ItemDataProvider.php | 131 - ...trineMongoDbOdmPropertyMetadataFactory.php | 79 - .../Bridge/Doctrine/MongoDbOdm/Paginator.php | 22 - .../MongoDbOdm/PropertyHelperTrait.php | 23 - .../PropertyInfo/DoctrineExtractor.php | 22 - .../MongoDbOdm/SubresourceDataProvider.php | 213 - .../Bridge/Doctrine/Orm/AbstractPaginator.php | 22 - .../Doctrine/Orm/CollectionDataProvider.php | 78 - .../Orm/Extension/EagerLoadingExtension.php | 22 - .../Extension/FilterEagerLoadingExtension.php | 22 - .../Orm/Extension/FilterExtension.php | 22 - .../Doctrine/Orm/Extension/OrderExtension.php | 22 - .../Orm/Extension/PaginationExtension.php | 22 - .../Orm/Filter/AbstractContextAwareFilter.php | 22 - .../Doctrine/Orm/Filter/AbstractFilter.php | 22 - .../Doctrine/Orm/Filter/BooleanFilter.php | 22 - .../Bridge/Doctrine/Orm/Filter/DateFilter.php | 22 - .../Doctrine/Orm/Filter/ExistsFilter.php | 22 - .../Doctrine/Orm/Filter/NumericFilter.php | 22 - .../Doctrine/Orm/Filter/OrderFilter.php | 22 - .../Doctrine/Orm/Filter/RangeFilter.php | 22 - .../Doctrine/Orm/Filter/SearchFilter.php | 275 -- .../Bridge/Doctrine/Orm/ItemDataProvider.php | 136 - .../DoctrineOrmPropertyMetadataFactory.php | 87 - src/Core/Bridge/Doctrine/Orm/Paginator.php | 22 - .../Doctrine/Orm/PropertyHelperTrait.php | 23 - .../Doctrine/Orm/SubresourceDataProvider.php | 240 -- .../Doctrine/Orm/Util/EagerLoadingTrait.php | 23 - .../Doctrine/Orm/Util/QueryBuilderHelper.php | 22 - .../Bridge/Doctrine/Orm/Util/QueryChecker.php | 22 - .../Doctrine/Orm/Util/QueryJoinParser.php | 22 - .../Doctrine/Orm/Util/QueryNameGenerator.php | 22 - .../Elasticsearch/Api/IdentifierExtractor.php | 52 - .../Api/IdentifierExtractorInterface.php | 33 - .../DataProvider/CollectionDataProvider.php | 152 - .../Extension/AbstractFilterExtension.php | 22 - .../ConstantScoreFilterExtension.php | 22 - .../DataProvider/Extension/SortExtension.php | 22 - .../Extension/SortFilterExtension.php | 22 - .../DataProvider/Filter/AbstractFilter.php | 145 - .../Filter/AbstractSearchFilter.php | 187 - .../DataProvider/Filter/MatchFilter.php | 46 - .../DataProvider/Filter/OrderFilter.php | 111 - .../DataProvider/Filter/TermFilter.php | 45 - .../DataProvider/ItemDataProvider.php | 117 - .../Elasticsearch/DataProvider/Paginator.php | 22 - .../Exception/IndexNotFoundException.php | 22 - .../NonUniqueIdentifierException.php | 22 - .../Metadata/Document/DocumentMetadata.php | 22 - .../AttributeDocumentMetadataFactory.php | 22 - .../Factory/CachedDocumentMetadataFactory.php | 22 - .../Factory/CatDocumentMetadataFactory.php | 22 - .../ConfiguredDocumentMetadataFactory.php | 22 - ...searchOperationResourceMetadataFactory.php | 52 - .../Serializer/DocumentNormalizer.php | 22 - .../Serializer/ItemNormalizer.php | 22 - .../InnerFieldsNameConverter.php | 22 - .../Elasticsearch/Util/FieldDatatypeTrait.php | 23 - src/Core/Bridge/FosUser/EventListener.php | 58 - .../ApiPlatformProvider.php | 215 - .../NelmioApiDoc/Parser/ApiPlatformParser.php | 280 -- .../Identifier/Normalizer/UuidNormalizer.php | 56 - .../Serializer/UuidDenormalizer.php | 22 - .../Symfony/Bundle/Action/SwaggerUiAction.php | 229 -- .../Symfony/Bundle/ApiPlatformBundle.php | 22 - .../PayloadArgumentResolver.php | 22 - .../CachePoolClearerCacheWarmer.php | 22 - .../Bundle/Command/GraphQlExportCommand.php | 22 - .../Symfony/Bundle/Command/OpenApiCommand.php | 22 - .../Symfony/Bundle/Command/SwaggerCommand.php | 118 - .../Command/UpgradeApiResourceCommand.php | 218 -- .../DataCollector/RequestDataCollector.php | 194 - .../TraceableChainDataPersister.php | 84 - .../TraceableChainCollectionDataProvider.php | 77 - .../TraceableChainItemDataProvider.php | 87 - .../TraceableChainSubresourceDataProvider.php | 77 - .../ApiPlatformExtension.php | 22 - .../Compiler/AnnotationFilterPass.php | 22 - .../Compiler/AuthenticatorManagerPass.php | 22 - .../Compiler/DataProviderPass.php | 22 - .../DeprecateMercurePublisherPass.php | 22 - .../Compiler/ElasticsearchClientPass.php | 22 - .../Compiler/FilterPass.php | 22 - .../Compiler/GraphQlMutationResolverPass.php | 22 - .../Compiler/GraphQlQueryResolverPass.php | 22 - .../Compiler/GraphQlTypePass.php | 22 - .../MetadataAwareNameConverterPass.php | 22 - .../Compiler/TestClientPass.php | 22 - .../DependencyInjection/Configuration.php | 22 - .../EventListener/SwaggerUiListener.php | 22 - .../Bundle/SwaggerUi/SwaggerUiAction.php | 22 - .../Bundle/SwaggerUi/SwaggerUiContext.php | 22 - .../Bundle/Test/ApiTestAssertionsTrait.php | 23 - .../Symfony/Bundle/Test/ApiTestCase.php | 22 - .../Bridge/Symfony/Bundle/Test/Client.php | 22 - .../Bundle/Test/Constraint/ArraySubset.php | 31 - .../Test/Constraint/ArraySubsetLegacy.php | 34 - .../Test/Constraint/ArraySubsetTrait.php | 98 - .../Bundle/Test/Constraint/ArraySubsetV9.php | 34 - .../Test/Constraint/MatchesJsonSchema.php | 116 - .../Bridge/Symfony/Bundle/Test/Response.php | 22 - .../Identifier/Normalizer/UlidNormalizer.php | 46 - .../Identifier/Normalizer/UuidNormalizer.php | 46 - .../Symfony/Maker/MakeDataPersister.php | 116 - .../Bridge/Symfony/Maker/MakeDataProvider.php | 122 - .../Resources/help/MakeDataPersister.txt | 5 - .../Maker/Resources/help/MakeDataProvider.txt | 5 - .../Resources/skeleton/DataPersister.tpl.php | 57 - .../Resources/skeleton/DataProvider.tpl.php | 64 - .../Bridge/Symfony/Messenger/ContextStamp.php | 22 - .../Symfony/Messenger/DataPersister.php | 122 - .../Symfony/Messenger/DataTransformer.php | 98 - .../Symfony/Messenger/DispatchTrait.php | 23 - .../Bridge/Symfony/Messenger/RemoveStamp.php | 22 - .../PropertyInfoPropertyMetadataFactory.php | 89 - ...pertyInfoPropertyNameCollectionFactory.php | 22 - src/Core/Bridge/Symfony/Routing/ApiLoader.php | 22 - .../Routing/CachedRouteNameResolver.php | 50 - .../Bridge/Symfony/Routing/IriConverter.php | 186 - .../Routing/OperationMethodResolver.php | 153 - .../OperationMethodResolverInterface.php | 38 - .../Symfony/Routing/RouteNameGenerator.php | 77 - .../Symfony/Routing/RouteNameResolver.php | 76 - .../Routing/RouteNameResolverInterface.php | 33 - src/Core/Bridge/Symfony/Routing/Router.php | 22 - .../Routing/RouterOperationPathResolver.php | 72 - .../EventListener/ValidateListener.php | 90 - .../ValidationExceptionListener.php | 22 - .../Exception/ValidationException.php | 22 - .../PropertySchemaChoiceRestriction.php | 78 - .../PropertySchemaCollectionRestriction.php | 96 - .../PropertySchemaCountRestriction.php | 52 - .../Restriction/PropertySchemaFormat.php | 67 - ...rtySchemaGreaterThanOrEqualRestriction.php | 45 - .../PropertySchemaGreaterThanRestriction.php | 46 - .../PropertySchemaLengthRestriction.php | 53 - ...opertySchemaLessThanOrEqualRestriction.php | 45 - .../PropertySchemaLessThanRestriction.php | 46 - .../PropertySchemaOneOfRestriction.php | 70 - .../PropertySchemaRangeRestriction.php | 51 - .../PropertySchemaRegexRestriction.php | 42 - ...ertySchemaRestrictionMetadataInterface.php | 43 - .../PropertySchemaUniqueRestriction.php | 40 - .../ValidatorPropertyMetadataFactory.php | 199 - .../Bridge/Symfony/Validator/Validator.php | 22 - src/Core/Cache/CachedTrait.php | 23 - src/Core/DataPersister/ChainDataPersister.php | 87 - .../ContextAwareDataPersisterInterface.php | 37 - .../DataPersister/DataPersisterInterface.php | 45 - .../ResumableDataPersisterInterface.php | 26 - src/Core/DataProvider/ArrayPaginator.php | 22 - .../ChainCollectionDataProvider.php | 56 - .../DataProvider/ChainItemDataProvider.php | 66 - .../ChainSubresourceDataProvider.php | 60 - .../CollectionDataProviderInterface.php | 33 - ...xtAwareCollectionDataProviderInterface.php | 27 - ...ntifiersAwareItemDataProviderInterface.php | 27 - .../ItemDataProviderInterface.php | 35 - .../OperationDataProviderTrait.php | 132 - src/Core/DataProvider/Pagination.php | 271 -- src/Core/DataProvider/PaginationOptions.php | 22 - .../RestrictDataProviderTrait.php | 32 - .../RestrictedDataProviderInterface.php | 22 - .../SerializerAwareDataProviderInterface.php | 26 - .../SerializerAwareDataProviderTrait.php | 43 - .../SubresourceDataProviderInterface.php | 38 - .../DataProvider/TraversablePaginator.php | 22 - .../DataTransformerInitializerInterface.php | 26 - .../DataTransformerInterface.php | 39 - .../Action/DocumentationAction.php | 22 - src/Core/Documentation/Documentation.php | 22 - src/Core/EventListener/AddFormatListener.php | 22 - .../EventListener/DeserializeListener.php | 22 - src/Core/EventListener/EventPriorities.php | 22 - src/Core/EventListener/ExceptionListener.php | 22 - .../QueryParameterValidateListener.php | 22 - src/Core/EventListener/ReadListener.php | 143 - src/Core/EventListener/RespondListener.php | 22 - src/Core/EventListener/SerializeListener.php | 22 - src/Core/EventListener/WriteListener.php | 134 - .../Exception/DeserializationException.php | 22 - .../Exception/FilterValidationException.php | 22 - .../Exception/InvalidArgumentException.php | 22 - .../Exception/InvalidIdentifierException.php | 22 - .../Exception/InvalidResourceException.php | 22 - src/Core/Exception/InvalidValueException.php | 22 - src/Core/Exception/ItemNotFoundException.php | 22 - .../Exception/PropertyNotFoundException.php | 22 - .../ResourceClassNotFoundException.php | 22 - .../ResourceClassNotSupportedException.php | 22 - src/Core/Exception/RuntimeException.php | 22 - src/Core/Filter/QueryParameterValidator.php | 22 - src/Core/Filter/Validator/ArrayItems.php | 22 - src/Core/Filter/Validator/Bounds.php | 22 - src/Core/Filter/Validator/Enum.php | 22 - src/Core/Filter/Validator/Length.php | 22 - src/Core/Filter/Validator/MultipleOf.php | 22 - src/Core/Filter/Validator/Pattern.php | 22 - src/Core/Filter/Validator/Required.php | 22 - src/Core/GraphQl/Action/EntrypointAction.php | 22 - .../Action/GraphQlPlaygroundAction.php | 22 - src/Core/GraphQl/Action/GraphiQlAction.php | 22 - src/Core/GraphQl/Error/ErrorHandler.php | 22 - src/Core/GraphQl/Executor.php | 22 - .../Factory/CollectionResolverFactory.php | 105 - .../Factory/ItemMutationResolverFactory.php | 128 - .../Resolver/Factory/ItemResolverFactory.php | 128 - .../ItemSubscriptionResolverFactory.php | 92 - .../Factory/ResolverFactoryInterface.php | 26 - .../Resolver/ResourceFieldResolver.php | 56 - .../Resolver/Stage/DeserializeStage.php | 65 - .../Stage/DeserializeStageInterface.php | 31 - src/Core/GraphQl/Resolver/Stage/ReadStage.php | 188 - .../Resolver/Stage/ReadStageInterface.php | 29 - .../Stage/SecurityPostDenormalizeStage.php | 65 - .../SecurityPostDenormalizeStageInterface.php | 31 - .../GraphQl/Resolver/Stage/SecurityStage.php | 57 - .../Resolver/Stage/SecurityStageInterface.php | 32 - .../GraphQl/Resolver/Stage/SerializeStage.php | 223 -- .../Stage/SerializeStageInterface.php | 29 - .../GraphQl/Resolver/Stage/ValidateStage.php | 50 - .../Resolver/Stage/ValidateStageInterface.php | 33 - .../GraphQl/Resolver/Stage/WriteStage.php | 68 - .../Resolver/Stage/WriteStageInterface.php | 31 - .../GraphQl/Resolver/Util/IdentifierTrait.php | 23 - .../Serializer/Exception/ErrorNormalizer.php | 44 - .../Exception/HttpExceptionNormalizer.php | 52 - .../Exception/RuntimeExceptionNormalizer.php | 49 - .../ValidationExceptionNormalizer.php | 82 - .../GraphQl/Serializer/ItemNormalizer.php | 133 - .../GraphQl/Serializer/ObjectNormalizer.php | 97 - .../Serializer/SerializerContextBuilder.php | 124 - .../SerializerContextBuilderInterface.php | 26 - .../MercureSubscriptionIriGenerator.php | 60 - ...rcureSubscriptionIriGeneratorInterface.php | 28 - .../SubscriptionIdentifierGenerator.php | 31 - ...bscriptionIdentifierGeneratorInterface.php | 26 - .../Subscription/SubscriptionManager.php | 124 - .../SubscriptionManagerInterface.php | 28 - .../GraphQl/Type/Definition/IterableType.php | 22 - .../GraphQl/Type/Definition/UploadType.php | 22 - src/Core/GraphQl/Type/FieldsBuilder.php | 530 --- .../GraphQl/Type/FieldsBuilderInterface.php | 59 - src/Core/GraphQl/Type/SchemaBuilder.php | 132 - .../GraphQl/Type/SchemaBuilderInterface.php | 26 - src/Core/GraphQl/Type/TypeBuilder.php | 287 -- .../GraphQl/Type/TypeBuilderInterface.php | 51 - src/Core/GraphQl/Type/TypeConverter.php | 205 - .../GraphQl/Type/TypeConverterInterface.php | 38 - .../GraphQl/Type/TypeNotFoundException.php | 22 - src/Core/GraphQl/Type/TypesContainer.php | 22 - src/Core/GraphQl/Type/TypesFactory.php | 22 - src/Core/Hal/JsonSchema/SchemaFactory.php | 137 - .../Hal/Serializer/CollectionNormalizer.php | 22 - .../Hal/Serializer/EntrypointNormalizer.php | 22 - src/Core/Hal/Serializer/ItemNormalizer.php | 22 - src/Core/Hal/Serializer/ObjectNormalizer.php | 22 - .../EventListener/AddHeadersListener.php | 22 - .../EventListener/AddTagsListener.php | 22 - src/Core/HttpCache/PurgerInterface.php | 31 - src/Core/HttpCache/VarnishPurger.php | 22 - src/Core/HttpCache/VarnishXKeyPurger.php | 22 - .../EventListener/AddLinkHeaderListener.php | 22 - src/Core/Hydra/JsonSchema/SchemaFactory.php | 189 - .../CollectionFiltersNormalizer.php | 22 - .../Hydra/Serializer/CollectionNormalizer.php | 22 - .../ConstraintViolationListNormalizer.php | 22 - .../Serializer/DocumentationNormalizer.php | 22 - .../Hydra/Serializer/EntrypointNormalizer.php | 22 - src/Core/Hydra/Serializer/ErrorNormalizer.php | 22 - .../PartialCollectionViewNormalizer.php | 22 - .../Identifier/CompositeIdentifierParser.php | 63 - ...ntextAwareIdentifierConverterInterface.php | 27 - src/Core/Identifier/IdentifierConverter.php | 91 - .../IdentifierConverterInterface.php | 41 - .../DateTimeIdentifierDenormalizer.php | 43 - .../Normalizer/IntegerDenormalizer.php | 45 - .../TransformFieldsetsParametersListener.php | 22 - .../TransformFilteringParametersListener.php | 22 - .../TransformPaginationParametersListener.php | 22 - .../TransformSortingParametersListener.php | 22 - .../Serializer/CollectionNormalizer.php | 22 - .../ConstraintViolationListNormalizer.php | 22 - .../Serializer/EntrypointNormalizer.php | 22 - .../JsonApi/Serializer/ErrorNormalizer.php | 22 - .../JsonApi/Serializer/ItemNormalizer.php | 22 - .../JsonApi/Serializer/ObjectNormalizer.php | 22 - .../ReservedAttributeNameConverter.php | 22 - src/Core/JsonLd/Action/ContextAction.php | 22 - src/Core/JsonLd/ContextBuilder.php | 22 - src/Core/JsonLd/Serializer/ItemNormalizer.php | 22 - .../JsonLd/Serializer/JsonLdContextTrait.php | 23 - .../JsonLd/Serializer/ObjectNormalizer.php | 22 - .../Command/JsonSchemaGenerateCommand.php | 22 - src/Core/JsonSchema/Schema.php | 22 - src/Core/JsonSchema/SchemaFactory.php | 447 --- src/Core/JsonSchema/TypeFactory.php | 22 - .../EventListener/AddLinkHeaderListener.php | 22 - src/Core/Metadata/Extractor/XmlExtractor.php | 212 - src/Core/Metadata/Extractor/YamlExtractor.php | 183 - .../AnnotationPropertyMetadataFactory.php | 154 - ...nnotationPropertyNameCollectionFactory.php | 109 - .../AnnotationSubresourceMetadataFactory.php | 118 - .../Factory/CachedPropertyMetadataFactory.php | 50 - .../CachedPropertyNameCollectionFactory.php | 22 - .../DefaultPropertyMetadataFactory.php | 57 - .../ExtractorPropertyMetadataFactory.php | 164 - ...ExtractorPropertyNameCollectionFactory.php | 22 - .../InheritedPropertyMetadataFactory.php | 58 - ...InheritedPropertyNameCollectionFactory.php | 65 - .../PropertyMetadataFactoryInterface.php | 32 - .../SerializerPropertyMetadataFactory.php | 233 -- .../Metadata/Property/PropertyMetadata.php | 435 -- .../Property/PropertyNameCollection.php | 22 - .../Metadata/Property/SubresourceMetadata.php | 64 - ...iResourceToLegacyResourceMetadataTrait.php | 126 - ...nnotationResourceFilterMetadataFactory.php | 94 - .../AnnotationResourceMetadataFactory.php | 145 - ...nnotationResourceNameCollectionFactory.php | 67 - .../Factory/CachedResourceMetadataFactory.php | 50 - .../ExtractorResourceMetadataFactory.php | 104 - .../FormatsResourceMetadataFactory.php | 127 - .../InputOutputResourceMetadataFactory.php | 109 - .../OperationResourceMetadataFactory.php | 153 - .../Factory/PhpDocResourceMetadataFactory.php | 61 - .../ResourceMetadataFactoryInterface.php | 32 - .../ShortNameResourceMetadataFactory.php | 49 - .../Metadata/Resource/ResourceMetadata.php | 311 -- .../ToggleableOperationAttributeTrait.php | 44 - src/Core/Metadata/schema/metadata.xsd | 123 - src/Core/OpenApi/Factory/OpenApiFactory.php | 539 --- src/Core/OpenApi/Model/Components.php | 22 - src/Core/OpenApi/Model/Contact.php | 22 - src/Core/OpenApi/Model/Encoding.php | 22 - src/Core/OpenApi/Model/ExtensionTrait.php | 23 - .../OpenApi/Model/ExternalDocumentation.php | 22 - src/Core/OpenApi/Model/Info.php | 22 - src/Core/OpenApi/Model/License.php | 22 - src/Core/OpenApi/Model/Link.php | 22 - src/Core/OpenApi/Model/MediaType.php | 22 - src/Core/OpenApi/Model/OAuthFlow.php | 22 - src/Core/OpenApi/Model/OAuthFlows.php | 22 - src/Core/OpenApi/Model/Operation.php | 22 - src/Core/OpenApi/Model/Parameter.php | 22 - src/Core/OpenApi/Model/PathItem.php | 22 - src/Core/OpenApi/Model/Paths.php | 22 - src/Core/OpenApi/Model/RequestBody.php | 22 - src/Core/OpenApi/Model/Response.php | 22 - src/Core/OpenApi/Model/Schema.php | 22 - src/Core/OpenApi/Model/SecurityScheme.php | 22 - src/Core/OpenApi/Model/Server.php | 22 - src/Core/OpenApi/OpenApi.php | 22 - src/Core/OpenApi/Options.php | 22 - .../OpenApi/Serializer/OpenApiNormalizer.php | 22 - .../DashPathSegmentNameGenerator.php | 22 - .../CachedSubresourceOperationFactory.php | 47 - .../Factory/SubresourceOperationFactory.php | 214 - .../SubresourceOperationFactoryInterface.php | 27 - .../UnderscorePathSegmentNameGenerator.php | 22 - .../CustomOperationPathResolver.php | 22 - .../DashOperationPathResolver.php | 46 - .../PathResolver/OperationPathResolver.php | 22 - .../UnderscoreOperationPathResolver.php | 46 - .../ConstraintViolationListNormalizer.php | 22 - .../Problem/Serializer/ErrorNormalizer.php | 22 - .../Serializer/ErrorNormalizerTrait.php | 23 - .../ExpressionLanguageProvider.php | 22 - .../EventListener/DenyAccessListener.php | 22 - src/Core/Security/ExpressionLanguage.php | 22 - src/Core/Security/ResourceAccessChecker.php | 22 - .../AbstractCollectionNormalizer.php | 22 - ...tractConstraintViolationListNormalizer.php | 22 - .../Serializer/AbstractItemNormalizer.php | 22 - src/Core/Serializer/CacheKeyTrait.php | 23 - src/Core/Serializer/ContextTrait.php | 23 - src/Core/Serializer/Filter/GroupFilter.php | 22 - src/Core/Serializer/Filter/PropertyFilter.php | 22 - .../Serializer/InputOutputMetadataTrait.php | 23 - src/Core/Serializer/ItemNormalizer.php | 22 - src/Core/Serializer/JsonEncoder.php | 22 - .../Mapping/Factory/ClassMetadataFactory.php | 22 - src/Core/Serializer/ResourceList.php | 22 - .../Serializer/SerializerContextBuilder.php | 22 - .../SerializerFilterContextBuilder.php | 22 - .../Serializer/ApiGatewayNormalizer.php | 22 - .../Serializer/DocumentationNormalizer.php | 955 ----- .../Test/DoctrineMongoDbOdmFilterTestCase.php | 22 - src/Core/Test/DoctrineMongoDbOdmSetup.php | 22 - src/Core/Test/DoctrineMongoDbOdmTestCase.php | 22 - src/Core/Test/DoctrineOrmFilterTestCase.php | 22 - .../Upgrade/ColorConsoleDiffFormatter.php | 119 - src/Core/Upgrade/RemoveAnnotationTrait.php | 34 - src/Core/Upgrade/SubresourceTransformer.php | 112 - .../Upgrade/UpgradeApiResourceVisitor.php | 444 --- .../Upgrade/UpgradeApiSubresourceVisitor.php | 301 -- .../Util/AnnotationFilterExtractorTrait.php | 23 - src/Core/Util/ArrayTrait.php | 23 - src/Core/Util/AttributesExtractor.php | 22 - src/Core/Util/ClassInfoTrait.php | 23 - src/Core/Util/ClientTrait.php | 23 - src/Core/Util/CloneTrait.php | 23 - src/Core/Util/CorsTrait.php | 23 - src/Core/Util/ErrorFormatGuesser.php | 22 - src/Core/Util/Inflector.php | 22 - src/Core/Util/IriHelper.php | 22 - src/Core/Util/Reflection.php | 22 - .../Util/ReflectionClassRecursiveIterator.php | 22 - src/Core/Util/RequestAttributesExtractor.php | 22 - src/Core/Util/RequestParser.php | 22 - src/Core/Util/ResourceClassInfoTrait.php | 23 - src/Core/Util/ResponseTrait.php | 23 - src/Core/Util/SortTrait.php | 23 - .../EventListener/ValidateListener.php | 22 - .../Exception/ValidationException.php | 22 - tests/Action/EntrypointActionTest.php | 2 +- tests/Action/ExceptionActionTest.php | 2 +- tests/Api/IdentifiersExtractorTest.php | 2 +- .../QueryParameterValidatorTest.php | 2 +- tests/{Core => }/Behat/CommandContext.php | 2 +- tests/{Core => }/Behat/CoverageContext.php | 2 +- tests/{Core => }/Behat/DoctrineContext.php | 2 +- .../{Core => }/Behat/ElasticsearchContext.php | 2 +- tests/{Core => }/Behat/GraphqlContext.php | 2 +- tests/{Core => }/Behat/HttpCacheContext.php | 2 +- tests/{Core => }/Behat/HydraContext.php | 2 +- tests/{Core => }/Behat/JsonApiContext.php | 2 +- tests/{Core => }/Behat/JsonContext.php | 2 +- tests/{Core => }/Behat/JsonHalContext.php | 2 +- tests/{Core => }/Behat/MercureContext.php | 2 +- tests/{Core => }/Behat/OpenApiContext.php | 2 +- tests/{Core => }/Behat/XmlContext.php | 2 +- tests/Core/Annotation/ApiFilterTest.php | 75 - tests/Core/Annotation/ApiPropertyTest.php | 107 - tests/Core/Annotation/ApiResourceTest.php | 297 -- tests/Core/Annotation/ApiSubresourceTest.php | 53 - .../Api/CachedIdentifiersExtractorTest.php | 244 -- tests/Core/Api/EntrypointTest.php | 32 - .../Core/Api/FilterCollectionFactoryTest.php | 50 - tests/Core/Api/FilterCollectionTest.php | 33 - tests/Core/Api/FilterLocatorTraitTest.php | 161 - tests/Core/Api/FormatsProviderTest.php | 189 - tests/Core/Api/IdentifiersExtractorTest.php | 276 -- tests/Core/Api/ResourceClassResolverTest.php | 209 - .../Doctrine/Common/DataPersisterTest.php | 162 - .../Util/IdentifierManagerTraitTest.php | 245 -- .../MongoDbOdm/CollectionDataProviderTest.php | 166 - .../MongoDbOdm/ItemDataProviderTest.php | 307 -- .../SubresourceDataProviderTest.php | 541 --- .../Orm/CollectionDataProviderTest.php | 114 - .../Doctrine/Orm/ItemDataProviderTest.php | 305 -- .../Orm/SubresourceDataProviderTest.php | 615 --- .../Api/IdentifierExtractorTest.php | 70 - .../CollectionDataProviderTest.php | 186 - .../DataProvider/ItemDataProviderTest.php | 149 - ...chOperationResourceMetadataFactoryTest.php | 64 - .../ApiPlatformProviderTest.php | 569 --- .../Parser/ApiPlatformParserTest.php | 540 --- .../Normalizer/UuidNormalizerTest.php | 54 - .../Bundle/Command/SwaggerCommandTest.php | 137 - .../Bundle/Command/SwaggerCommandUnitTest.php | 75 - .../Command/UpgradeApiResourceCommandTest.php | 106 - .../TraceableChainDataPersisterTest.php | 185 - ...ceableChainCollectionDataCollectorTest.php | 149 - .../TraceableChainItemDataCollectorTest.php | 150 - ...eableChainSubresourceDataCollectorTest.php | 149 - .../Twig/ApiPlatformProfilerPanelTest.php | 299 -- .../Normalizer/UlidNormalizerTest.php | 62 - .../Normalizer/UuidNormalizerTest.php | 62 - .../Symfony/Maker/MakeDataPersisterTest.php | 187 - .../Symfony/Maker/MakeDataProviderTest.php | 332 -- .../Symfony/Messenger/DataPersisterTest.php | 107 - .../Symfony/Messenger/DataTransformerTest.php | 101 - .../Bridge/Symfony/Routing/ApiLoaderTest.php | 361 -- .../Routing/CachedRouteNameResolverTest.php | 178 - .../Symfony/Routing/IriConverterTest.php | 453 --- .../Routing/RouteNameGeneratorTest.php | 48 - .../Symfony/Routing/RouteNameResolverTest.php | 195 - .../RouterOperationPathResolverTest.php | 98 - .../EventListener/ValidateListenerTest.php | 212 - .../ValidatorPropertyMetadataFactoryTest.php | 398 -- .../DataPersister/ChainDataPersisterTest.php | 122 - .../ChainCollectionDataProviderTest.php | 126 - .../ChainItemDataProviderTest.php | 158 - .../ChainSubresourcedataProviderTest.php | 122 - tests/Core/EventListener/ReadListenerTest.php | 409 -- .../Core/EventListener/WriteListenerTest.php | 400 -- .../CompositeIdentifierParserTest.php | 67 - .../Identifier/IdentifierConverterTest.php | 147 - .../DateTimeIdentifierNormalizerTest.php | 36 - .../Normalizer/IntegerDenormalizerTest.php | 37 - .../Metadata/Extractor/ExtractorTestCase.php | 614 --- .../Metadata/Extractor/XmlExtractorTest.php | 63 - .../Metadata/Extractor/YamlExtractorTest.php | 121 - .../AnnotationPropertyMetadataFactoryTest.php | 163 - ...ationPropertyNameCollectionFactoryTest.php | 126 - ...notationSubresourceMetadataFactoryTest.php | 86 - .../ExtractorPropertyMetadataFactoryTest.php | 259 -- ...leConfigurationMetadataFactoryProvider.php | 79 - .../InheritedPropertyMetadataFactoryTest.php | 50 - ...ritedPropertyNameCollectionFactoryTest.php | 62 - .../SerializerPropertyMetadataFactoryTest.php | 187 - .../Property/PropertyMetadataTest.php | 115 - ...ationResourceFilterMetadataFactoryTest.php | 55 - .../AnnotationResourceMetadataFactoryTest.php | 156 - ...ationResourceNameCollectionFactoryTest.php | 52 - .../CachedResourceMetadataFactoryTest.php | 96 - ...achedResourceNameCollectionFactoryTest.php | 92 - .../ExtractorResourceMetadataFactoryTest.php | 361 -- ...actorResourceNameCollectionFactoryTest.php | 79 - ...leConfigurationMetadataFactoryProvider.php | 114 - .../FormatsResourceMetadataFactoryTest.php | 193 - ...InputOutputResourceMetadataFactoryTest.php | 77 - .../OperationResourceMetadataFactoryTest.php | 79 - .../PhpDocResourceMetadataFactoryTest.php | 62 - .../Resource/ResourceMetadataTest.php | 111 - .../Resource/ResourceNameCollectionTest.php | 32 - tests/Core/Metadata/schema/XmlSchemaTest.php | 38 - .../OpenApi/Factory/OpenApiFactoryTest.php | 818 ---- .../DashedPathSegmentNameGeneratorTest.php | 27 - .../CachedSubresourceOperationFactoryTest.php | 92 - .../SubresourceOperationFactoryTest.php | 988 ----- .../DashOperationPathResolverTest.php | 71 - .../UnderscoreOperationPathResolverTest.php | 71 - tests/Core/ProphecyTrait.php | 135 - .../DocumentationNormalizerV2Test.php | 3483 ----------------- .../DocumentationNormalizerV3Test.php | 3280 ---------------- tests/Core/Test/BookTestDeprecatedClient.php | 37 - .../Upgrade/SubresourceTransformerTest.php | 337 -- .../EventListener/ValidateListenerTest.php | 189 - .../Common/State/PersistProcessorTest.php | 2 +- .../Common/State/RemoveProcessorTest.php | 2 +- .../PublishMercureUpdatesListenerTest.php | 2 +- .../PurgeHttpCacheListenerTest.php | 2 +- .../EventListener/WriteListenerTest.php | 2 +- .../Odm/Extension/FilterExtensionTest.php | 2 +- .../Odm/Extension/OrderExtensionTest.php | 2 +- .../Odm/Extension/PaginationExtensionTest.php | 2 +- .../Doctrine/Odm/Filter/SearchFilterTest.php | 2 +- ...eMongoDbOdmPropertyMetadataFactoryTest.php | 2 +- ...mResourceCollectionMetadataFactoryTest.php | 2 +- tests/Doctrine/Odm/PaginatorTest.php | 2 +- .../Odm/State/CollectionProviderTest.php | 2 +- tests/Doctrine/Odm/State/ItemProviderTest.php | 2 +- .../Extension/EagerLoadingExtensionTest.php | 2 +- .../FilterEagerLoadingExtensionTest.php | 2 +- .../Orm/Extension/FilterExtensionTest.php | 2 +- .../Orm/Extension/OrderExtensionTest.php | 2 +- .../Orm/Extension/PaginationExtensionTest.php | 2 +- .../Doctrine/Orm/Filter/CommonFilterTest.php | 2 +- .../Doctrine/Orm/Filter/SearchFilterTest.php | 2 +- ...DoctrineOrmPropertyMetadataFactoryTest.php | 2 +- ...mResourceCollectionMetadataFactoryTest.php | 2 +- tests/Doctrine/Orm/PaginatorTest.php | 2 +- .../Orm/State/CollectionProviderTest.php | 2 +- tests/Doctrine/Orm/State/ItemProviderTest.php | 2 +- .../Orm/Util/QueryBuilderHelperTest.php | 2 +- tests/Doctrine/Orm/Util/QueryCheckerTest.php | 2 +- .../Doctrine/Orm/Util/QueryJoinParserTest.php | 2 +- .../Action/DocumentationActionTest.php | 2 +- .../ConstantScoreFilterExtensionTest.php | 2 +- .../Extension/SortExtensionTest.php | 2 +- .../Extension/SortFilterExtensionTest.php | 2 +- .../Elasticsearch/Filter/MatchFilterTest.php | 2 +- .../Elasticsearch/Filter/OrderFilterTest.php | 2 +- tests/Elasticsearch/Filter/TermFilterTest.php | 2 +- .../AttributeDocumentMetadataFactoryTest.php | 2 +- .../CachedDocumentMetadataFactoryTest.php | 2 +- .../CatDocumentMetadataFactoryTest.php | 2 +- .../ConfiguredDocumentMetadataFactoryTest.php | 2 +- tests/Elasticsearch/PaginatorTest.php | 2 +- .../Serializer/DocumentNormalizerTest.php | 2 +- .../Serializer/ItemNormalizerTest.php | 2 +- .../InnerFieldsNameConverterTest.php | 2 +- .../State/CollectionProviderTest.php | 2 +- .../Elasticsearch/State/ItemProviderTest.php | 2 +- .../Util/FieldDatatypeTraitTest.php | 2 +- tests/GraphQl/Action/EntrypointActionTest.php | 2 +- .../Action/GraphQlPlaygroundActionTest.php | 2 +- tests/GraphQl/Action/GraphiQlActionTest.php | 2 +- .../Factory/CollectionResolverFactoryTest.php | 2 +- .../ItemMutationResolverFactoryTest.php | 2 +- .../Factory/ItemResolverFactoryTest.php | 2 +- .../ItemSubscriptionResolverFactoryTest.php | 2 +- .../Resolver/ResourceFieldResolverTest.php | 2 +- .../Resolver/Stage/DeserializeStageTest.php | 2 +- .../GraphQl/Resolver/Stage/ReadStageTest.php | 2 +- .../SecurityPostDenormalizeStageTest.php | 2 +- .../Stage/SecurityPostValidationStageTest.php | 2 +- .../Resolver/Stage/SecurityStageTest.php | 2 +- .../Resolver/Stage/SerializeStageTest.php | 2 +- .../Resolver/Stage/ValidateStageTest.php | 2 +- .../GraphQl/Resolver/Stage/WriteStageTest.php | 2 +- .../GraphQl/Serializer/ItemNormalizerTest.php | 2 +- .../SerializerContextBuilderTest.php | 2 +- .../Subscription/SubscriptionManagerTest.php | 2 +- tests/GraphQl/Type/FieldsBuilderTest.php | 2 +- tests/GraphQl/Type/SchemaBuilderTest.php | 2 +- tests/GraphQl/Type/TypeBuilderTest.php | 2 +- tests/GraphQl/Type/TypeConverterTest.php | 2 +- tests/GraphQl/Type/TypesContainerTest.php | 2 +- tests/GraphQl/Type/TypesFactoryTest.php | 2 +- tests/Hal/JsonSchema/SchemaFactoryTest.php | 2 +- .../Serializer/CollectionNormalizerTest.php | 2 +- .../Serializer/EntrypointNormalizerTest.php | 2 +- tests/Hal/Serializer/ItemNormalizerTest.php | 2 +- tests/Hal/Serializer/ObjectNormalizerTest.php | 2 +- .../EventListener/AddHeadersListenerTest.php | 2 +- .../EventListener/AddTagsListenerTest.php | 2 +- tests/HttpCache/VarnishPurgerTest.php | 2 +- tests/HttpCache/VarnishXKeyPurgerTest.php | 2 +- .../AddLinkHeaderListenerTest.php | 2 +- tests/Hydra/JsonSchema/SchemaFactoryTest.php | 2 +- .../CollectionFiltersNormalizerTest.php | 2 +- .../Serializer/CollectionNormalizerTest.php | 2 +- .../ConstraintViolationNormalizerTest.php | 2 +- .../DocumentationNormalizerTest.php | 2 +- .../Serializer/EntrypointNormalizerTest.php | 2 +- .../Hydra/Serializer/ErrorNormalizerTest.php | 2 +- .../PartialCollectionViewNormalizerTest.php | 2 +- .../Serializer/CollectionNormalizerTest.php | 2 +- .../ConstraintViolationNormalizerTest.php | 2 +- .../Serializer/EntrypointNormalizerTest.php | 2 +- .../Serializer/ErrorNormalizerTest.php | 2 +- .../JsonApi/Serializer/ItemNormalizerTest.php | 2 +- tests/JsonLd/Action/ContextActionTest.php | 2 +- tests/JsonLd/ContextBuilderTest.php | 2 +- .../JsonLd/Serializer/ItemNormalizerTest.php | 2 +- .../Serializer/ObjectNormalizerTest.php | 2 +- tests/JsonSchema/SchemaFactoryTest.php | 2 +- tests/JsonSchema/TypeFactoryTest.php | 2 +- .../AttributePropertyMetadataFactoryTest.php | 2 +- .../CachedPropertyMetadataFactoryTest.php | 2 +- ...achedPropertyNameCollectionFactoryTest.php | 2 +- .../DefaultPropertyMetadataFactoryTest.php | 2 +- ...actorPropertyNameCollectionFactoryTest.php | 2 +- .../SerializerPropertyMetadataFactoryTest.php | 2 +- ...sResourceMetadataCollectionFactoryTest.php | 2 +- ...sResourceMetadataCollectionFactoryTest.php | 2 +- ...tResourceMetadataCollectionFactoryTest.php | 2 +- .../Resource/Factory/LinkFactoryTest.php | 2 +- ...kResourceMetadataCollectionFactoryTest.php | 2 +- ...cResourceMetadataCollectionFactoryTest.php | 2 +- ...eResourceMetadataCollectionFactoryTest.php | 2 +- .../ResourceMetadataCollectionTest.php | 2 +- .../Mock/Exception/ErrorCodeSerializable.php | 2 +- tests/OpenApi/Factory/OpenApiFactoryTest.php | 2 +- .../Serializer/ApiGatewayNormalizerTest.php | 2 +- .../Serializer/OpenApiNormalizerTest.php | 2 +- .../CustomOperationPathResolverTest.php | 2 +- .../ConstraintViolationNormalizerTest.php | 2 +- .../Serializer/AbstractItemNormalizerTest.php | 2 +- tests/Serializer/ItemNormalizerTest.php | 2 +- .../LegacySerializerContextBuilderTest.php | 2 +- .../SerializerContextBuilderTest.php | 2 +- .../SerializerFilterContextBuilderTest.php | 2 +- .../Bundle/Action/SwaggerUiActionTest.php | 2 +- .../Symfony/Bundle/ApiPlatformBundleTest.php | 2 +- .../PayloadArgumentResolverTest.php | 2 +- .../Command/DebugResourceCommandTest.php | 2 +- .../RequestDataCollectorTest.php | 2 +- .../ApiPlatformExtensionTest.php | 2 +- .../Compiler/AnnotationFilterPassTest.php | 2 +- .../Compiler/AuthenticatorManagerPassTest.php | 2 +- .../DeprecateMercurePublisherPassTest.php | 2 +- .../Compiler/ElasticsearchClientPassTest.php | 2 +- .../Compiler/FilterPassTest.php | 2 +- .../GraphQlMutationResolverPassTest.php | 2 +- .../Compiler/GraphQlQueryResolverPassTest.php | 2 +- .../Compiler/GraphQlTypePassTest.php | 2 +- .../MetadataAwareNameConverterPassTest.php | 2 +- .../Compiler/TestClientPassTest.php | 2 +- .../EventListener/SwaggerUiListenerTest.php | 2 +- .../Bundle/SwaggerUi/SwaggerUiActionTest.php | 2 +- .../EventListener/AddFormatListenerTest.php | 2 +- .../AddLinkHeaderListenerTest.php | 2 +- .../EventListener/DenyAccessListenerTest.php | 2 +- .../EventListener/DeserializeListenerTest.php | 2 +- .../EventListener/ExceptionListenerTest.php | 2 +- ...ansformFieldsetsParametersListenerTest.php | 2 +- ...ansformFilteringParametersListenerTest.php | 2 +- ...nsformPaginationParametersListenerTest.php | 2 +- ...TransformSortingParametersListenerTest.php | 2 +- .../QueryParameterValidateListenerTest.php | 2 +- .../EventListener/ReadListenerTest.php | 2 +- .../EventListener/RespondListenerTest.php | 2 +- .../EventListener/SerializeListenerTest.php | 2 +- .../EventListener/WriteListenerTest.php | 2 +- tests/Symfony/Messenger/ProcessorTest.php | 2 +- tests/Symfony/Routing/ApiLoaderTest.php | 2 +- tests/Symfony/Routing/IriConverterTest.php | 2 +- tests/Symfony/Routing/RouterTest.php | 2 +- .../Security/ResourceAccessCheckerTest.php | 2 +- .../PropertySchemaChoiceRestrictionTest.php | 2 +- ...ropertySchemaCollectionRestrictionTest.php | 2 +- .../PropertySchemaCountRestrictionTest.php | 2 +- .../Restriction/PropertySchemaFormatTest.php | 2 +- ...chemaGreaterThanOrEqualRestrictionTest.php | 2 +- ...opertySchemaGreaterThanRestrictionTest.php | 2 +- ...tySchemaLessThanOrEqualRestrictionTest.php | 2 +- .../PropertySchemaLessThanRestrictionTest.php | 2 +- .../PropertySchemaOneOfRestrictionTest.php | 2 +- .../PropertySchemaRangeRestrictionTest.php | 2 +- .../PropertySchemaRegexRestrictionTest.php | 2 +- .../PropertySchemaUniqueRestrictionTest.php | 2 +- .../ValidatorPropertyMetadataFactoryTest.php | 2 +- .../ValidationExceptionListenerTest.php | 2 +- .../Validator/Metadata/ValidatorTest.php | 2 +- 758 files changed, 195 insertions(+), 51979 deletions(-) delete mode 100644 src/Core/Action/EntrypointAction.php delete mode 100644 src/Core/Action/ExceptionAction.php delete mode 100644 src/Core/Action/NotFoundAction.php delete mode 100644 src/Core/Action/PlaceholderAction.php delete mode 100644 src/Core/Annotation/ApiFilter.php delete mode 100644 src/Core/Annotation/ApiProperty.php delete mode 100644 src/Core/Annotation/ApiResource.php delete mode 100644 src/Core/Annotation/ApiSubresource.php delete mode 100644 src/Core/Annotation/AttributesHydratorTrait.php delete mode 100644 src/Core/Annotation/TemporaryApiResource.php delete mode 100644 src/Core/Api/CachedIdentifiersExtractor.php delete mode 100644 src/Core/Api/Entrypoint.php delete mode 100644 src/Core/Api/FilterCollection.php delete mode 100644 src/Core/Api/FilterCollectionFactory.php delete mode 100644 src/Core/Api/FilterLocatorTrait.php delete mode 100644 src/Core/Api/FormatMatcher.php delete mode 100644 src/Core/Api/FormatsProvider.php delete mode 100644 src/Core/Api/FormatsProviderInterface.php delete mode 100644 src/Core/Api/IdentifiersExtractor.php delete mode 100644 src/Core/Api/IdentifiersExtractorInterface.php delete mode 100644 src/Core/Api/IriConverterInterface.php delete mode 100644 src/Core/Api/OperationAwareFormatsProviderInterface.php delete mode 100644 src/Core/Api/OperationMethodResolverInterface.php delete mode 100644 src/Core/Api/OperationType.php delete mode 100644 src/Core/Api/OperationTypeDeprecationHelper.php delete mode 100644 src/Core/Api/ResourceClassResolver.php delete mode 100644 src/Core/Bridge/Doctrine/Common/DataPersister.php delete mode 100644 src/Core/Bridge/Doctrine/Common/Filter/BooleanFilterTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Common/Filter/DateFilterTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Common/Filter/ExistsFilterTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Common/Filter/NumericFilterTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Common/Filter/OrderFilterTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Common/Filter/RangeFilterTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Common/Filter/SearchFilterTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Common/PropertyHelperTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTrait.php delete mode 100644 src/Core/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php delete mode 100644 src/Core/Bridge/Doctrine/EventListener/PurgeHttpCacheListener.php delete mode 100644 src/Core/Bridge/Doctrine/EventListener/WriteListener.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtension.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Filter/AbstractFilter.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Filter/BooleanFilter.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Filter/DateFilter.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Filter/ExistsFilter.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Filter/NumericFilter.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Filter/OrderFilter.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Filter/RangeFilter.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/Paginator.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/PropertyHelperTrait.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractor.php delete mode 100644 src/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/AbstractPaginator.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/CollectionDataProvider.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/AbstractContextAwareFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/ExistsFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/NumericFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/OrderFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/RangeFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Filter/SearchFilter.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/ItemDataProvider.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Paginator.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/PropertyHelperTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/SubresourceDataProvider.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Util/EagerLoadingTrait.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Util/QueryJoinParser.php delete mode 100644 src/Core/Bridge/Doctrine/Orm/Util/QueryNameGenerator.php delete mode 100644 src/Core/Bridge/Elasticsearch/Api/IdentifierExtractor.php delete mode 100644 src/Core/Bridge/Elasticsearch/Api/IdentifierExtractorInterface.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProvider.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Extension/AbstractFilterExtension.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtension.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortExtension.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtension.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractFilter.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractSearchFilter.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Filter/MatchFilter.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Filter/OrderFilter.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Filter/TermFilter.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/ItemDataProvider.php delete mode 100644 src/Core/Bridge/Elasticsearch/DataProvider/Paginator.php delete mode 100644 src/Core/Bridge/Elasticsearch/Exception/IndexNotFoundException.php delete mode 100644 src/Core/Bridge/Elasticsearch/Exception/NonUniqueIdentifierException.php delete mode 100644 src/Core/Bridge/Elasticsearch/Metadata/Document/DocumentMetadata.php delete mode 100644 src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php delete mode 100644 src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php delete mode 100644 src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php delete mode 100644 src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php delete mode 100644 src/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php delete mode 100644 src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php delete mode 100644 src/Core/Bridge/Elasticsearch/Serializer/ItemNormalizer.php delete mode 100644 src/Core/Bridge/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php delete mode 100644 src/Core/Bridge/Elasticsearch/Util/FieldDatatypeTrait.php delete mode 100644 src/Core/Bridge/FosUser/EventListener.php delete mode 100644 src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php delete mode 100644 src/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParser.php delete mode 100644 src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php delete mode 100644 src/Core/Bridge/RamseyUuid/Serializer/UuidDenormalizer.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/ApiPlatformBundle.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Command/GraphQlExportCommand.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Command/OpenApiCommand.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersister.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataProvider.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataProvider.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataProvider.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/ApiTestCase.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/Client.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php delete mode 100644 src/Core/Bridge/Symfony/Bundle/Test/Response.php delete mode 100644 src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php delete mode 100644 src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php delete mode 100644 src/Core/Bridge/Symfony/Maker/MakeDataPersister.php delete mode 100644 src/Core/Bridge/Symfony/Maker/MakeDataProvider.php delete mode 100644 src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataPersister.txt delete mode 100644 src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataProvider.txt delete mode 100644 src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataPersister.tpl.php delete mode 100644 src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataProvider.tpl.php delete mode 100644 src/Core/Bridge/Symfony/Messenger/ContextStamp.php delete mode 100644 src/Core/Bridge/Symfony/Messenger/DataPersister.php delete mode 100644 src/Core/Bridge/Symfony/Messenger/DataTransformer.php delete mode 100644 src/Core/Bridge/Symfony/Messenger/DispatchTrait.php delete mode 100644 src/Core/Bridge/Symfony/Messenger/RemoveStamp.php delete mode 100644 src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php delete mode 100644 src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php delete mode 100644 src/Core/Bridge/Symfony/Routing/ApiLoader.php delete mode 100644 src/Core/Bridge/Symfony/Routing/CachedRouteNameResolver.php delete mode 100644 src/Core/Bridge/Symfony/Routing/IriConverter.php delete mode 100644 src/Core/Bridge/Symfony/Routing/OperationMethodResolver.php delete mode 100644 src/Core/Bridge/Symfony/Routing/OperationMethodResolverInterface.php delete mode 100644 src/Core/Bridge/Symfony/Routing/RouteNameGenerator.php delete mode 100644 src/Core/Bridge/Symfony/Routing/RouteNameResolver.php delete mode 100644 src/Core/Bridge/Symfony/Routing/RouteNameResolverInterface.php delete mode 100644 src/Core/Bridge/Symfony/Routing/Router.php delete mode 100644 src/Core/Bridge/Symfony/Routing/RouterOperationPathResolver.php delete mode 100644 src/Core/Bridge/Symfony/Validator/EventListener/ValidateListener.php delete mode 100644 src/Core/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Exception/ValidationException.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormat.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLengthRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRestrictionMetadataInterface.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestriction.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php delete mode 100644 src/Core/Bridge/Symfony/Validator/Validator.php delete mode 100644 src/Core/Cache/CachedTrait.php delete mode 100644 src/Core/DataPersister/ChainDataPersister.php delete mode 100644 src/Core/DataPersister/ContextAwareDataPersisterInterface.php delete mode 100644 src/Core/DataPersister/DataPersisterInterface.php delete mode 100644 src/Core/DataPersister/ResumableDataPersisterInterface.php delete mode 100644 src/Core/DataProvider/ArrayPaginator.php delete mode 100644 src/Core/DataProvider/ChainCollectionDataProvider.php delete mode 100644 src/Core/DataProvider/ChainItemDataProvider.php delete mode 100644 src/Core/DataProvider/ChainSubresourceDataProvider.php delete mode 100644 src/Core/DataProvider/CollectionDataProviderInterface.php delete mode 100644 src/Core/DataProvider/ContextAwareCollectionDataProviderInterface.php delete mode 100644 src/Core/DataProvider/DenormalizedIdentifiersAwareItemDataProviderInterface.php delete mode 100644 src/Core/DataProvider/ItemDataProviderInterface.php delete mode 100644 src/Core/DataProvider/OperationDataProviderTrait.php delete mode 100644 src/Core/DataProvider/Pagination.php delete mode 100644 src/Core/DataProvider/PaginationOptions.php delete mode 100644 src/Core/DataProvider/RestrictDataProviderTrait.php delete mode 100644 src/Core/DataProvider/RestrictedDataProviderInterface.php delete mode 100644 src/Core/DataProvider/SerializerAwareDataProviderInterface.php delete mode 100644 src/Core/DataProvider/SerializerAwareDataProviderTrait.php delete mode 100644 src/Core/DataProvider/SubresourceDataProviderInterface.php delete mode 100644 src/Core/DataProvider/TraversablePaginator.php delete mode 100644 src/Core/DataTransformer/DataTransformerInitializerInterface.php delete mode 100644 src/Core/DataTransformer/DataTransformerInterface.php delete mode 100644 src/Core/Documentation/Action/DocumentationAction.php delete mode 100644 src/Core/Documentation/Documentation.php delete mode 100644 src/Core/EventListener/AddFormatListener.php delete mode 100644 src/Core/EventListener/DeserializeListener.php delete mode 100644 src/Core/EventListener/EventPriorities.php delete mode 100644 src/Core/EventListener/ExceptionListener.php delete mode 100644 src/Core/EventListener/QueryParameterValidateListener.php delete mode 100644 src/Core/EventListener/ReadListener.php delete mode 100644 src/Core/EventListener/RespondListener.php delete mode 100644 src/Core/EventListener/SerializeListener.php delete mode 100644 src/Core/EventListener/WriteListener.php delete mode 100644 src/Core/Exception/DeserializationException.php delete mode 100644 src/Core/Exception/FilterValidationException.php delete mode 100644 src/Core/Exception/InvalidArgumentException.php delete mode 100644 src/Core/Exception/InvalidIdentifierException.php delete mode 100644 src/Core/Exception/InvalidResourceException.php delete mode 100644 src/Core/Exception/InvalidValueException.php delete mode 100644 src/Core/Exception/ItemNotFoundException.php delete mode 100644 src/Core/Exception/PropertyNotFoundException.php delete mode 100644 src/Core/Exception/ResourceClassNotFoundException.php delete mode 100644 src/Core/Exception/ResourceClassNotSupportedException.php delete mode 100644 src/Core/Exception/RuntimeException.php delete mode 100644 src/Core/Filter/QueryParameterValidator.php delete mode 100644 src/Core/Filter/Validator/ArrayItems.php delete mode 100644 src/Core/Filter/Validator/Bounds.php delete mode 100644 src/Core/Filter/Validator/Enum.php delete mode 100644 src/Core/Filter/Validator/Length.php delete mode 100644 src/Core/Filter/Validator/MultipleOf.php delete mode 100644 src/Core/Filter/Validator/Pattern.php delete mode 100644 src/Core/Filter/Validator/Required.php delete mode 100644 src/Core/GraphQl/Action/EntrypointAction.php delete mode 100644 src/Core/GraphQl/Action/GraphQlPlaygroundAction.php delete mode 100644 src/Core/GraphQl/Action/GraphiQlAction.php delete mode 100644 src/Core/GraphQl/Error/ErrorHandler.php delete mode 100644 src/Core/GraphQl/Executor.php delete mode 100644 src/Core/GraphQl/Resolver/Factory/CollectionResolverFactory.php delete mode 100644 src/Core/GraphQl/Resolver/Factory/ItemMutationResolverFactory.php delete mode 100644 src/Core/GraphQl/Resolver/Factory/ItemResolverFactory.php delete mode 100644 src/Core/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactory.php delete mode 100644 src/Core/GraphQl/Resolver/Factory/ResolverFactoryInterface.php delete mode 100644 src/Core/GraphQl/Resolver/ResourceFieldResolver.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/DeserializeStage.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/DeserializeStageInterface.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/ReadStage.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/ReadStageInterface.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageInterface.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/SecurityStage.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/SecurityStageInterface.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/SerializeStage.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/SerializeStageInterface.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/ValidateStage.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/ValidateStageInterface.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/WriteStage.php delete mode 100644 src/Core/GraphQl/Resolver/Stage/WriteStageInterface.php delete mode 100644 src/Core/GraphQl/Resolver/Util/IdentifierTrait.php delete mode 100644 src/Core/GraphQl/Serializer/Exception/ErrorNormalizer.php delete mode 100644 src/Core/GraphQl/Serializer/Exception/HttpExceptionNormalizer.php delete mode 100644 src/Core/GraphQl/Serializer/Exception/RuntimeExceptionNormalizer.php delete mode 100644 src/Core/GraphQl/Serializer/Exception/ValidationExceptionNormalizer.php delete mode 100644 src/Core/GraphQl/Serializer/ItemNormalizer.php delete mode 100644 src/Core/GraphQl/Serializer/ObjectNormalizer.php delete mode 100644 src/Core/GraphQl/Serializer/SerializerContextBuilder.php delete mode 100644 src/Core/GraphQl/Serializer/SerializerContextBuilderInterface.php delete mode 100644 src/Core/GraphQl/Subscription/MercureSubscriptionIriGenerator.php delete mode 100644 src/Core/GraphQl/Subscription/MercureSubscriptionIriGeneratorInterface.php delete mode 100644 src/Core/GraphQl/Subscription/SubscriptionIdentifierGenerator.php delete mode 100644 src/Core/GraphQl/Subscription/SubscriptionIdentifierGeneratorInterface.php delete mode 100644 src/Core/GraphQl/Subscription/SubscriptionManager.php delete mode 100644 src/Core/GraphQl/Subscription/SubscriptionManagerInterface.php delete mode 100644 src/Core/GraphQl/Type/Definition/IterableType.php delete mode 100644 src/Core/GraphQl/Type/Definition/UploadType.php delete mode 100644 src/Core/GraphQl/Type/FieldsBuilder.php delete mode 100644 src/Core/GraphQl/Type/FieldsBuilderInterface.php delete mode 100644 src/Core/GraphQl/Type/SchemaBuilder.php delete mode 100644 src/Core/GraphQl/Type/SchemaBuilderInterface.php delete mode 100644 src/Core/GraphQl/Type/TypeBuilder.php delete mode 100644 src/Core/GraphQl/Type/TypeBuilderInterface.php delete mode 100644 src/Core/GraphQl/Type/TypeConverter.php delete mode 100644 src/Core/GraphQl/Type/TypeConverterInterface.php delete mode 100644 src/Core/GraphQl/Type/TypeNotFoundException.php delete mode 100644 src/Core/GraphQl/Type/TypesContainer.php delete mode 100644 src/Core/GraphQl/Type/TypesFactory.php delete mode 100644 src/Core/Hal/JsonSchema/SchemaFactory.php delete mode 100644 src/Core/Hal/Serializer/CollectionNormalizer.php delete mode 100644 src/Core/Hal/Serializer/EntrypointNormalizer.php delete mode 100644 src/Core/Hal/Serializer/ItemNormalizer.php delete mode 100644 src/Core/Hal/Serializer/ObjectNormalizer.php delete mode 100644 src/Core/HttpCache/EventListener/AddHeadersListener.php delete mode 100644 src/Core/HttpCache/EventListener/AddTagsListener.php delete mode 100644 src/Core/HttpCache/PurgerInterface.php delete mode 100644 src/Core/HttpCache/VarnishPurger.php delete mode 100644 src/Core/HttpCache/VarnishXKeyPurger.php delete mode 100644 src/Core/Hydra/EventListener/AddLinkHeaderListener.php delete mode 100644 src/Core/Hydra/JsonSchema/SchemaFactory.php delete mode 100644 src/Core/Hydra/Serializer/CollectionFiltersNormalizer.php delete mode 100644 src/Core/Hydra/Serializer/CollectionNormalizer.php delete mode 100644 src/Core/Hydra/Serializer/ConstraintViolationListNormalizer.php delete mode 100644 src/Core/Hydra/Serializer/DocumentationNormalizer.php delete mode 100644 src/Core/Hydra/Serializer/EntrypointNormalizer.php delete mode 100644 src/Core/Hydra/Serializer/ErrorNormalizer.php delete mode 100644 src/Core/Hydra/Serializer/PartialCollectionViewNormalizer.php delete mode 100644 src/Core/Identifier/CompositeIdentifierParser.php delete mode 100644 src/Core/Identifier/ContextAwareIdentifierConverterInterface.php delete mode 100644 src/Core/Identifier/IdentifierConverter.php delete mode 100644 src/Core/Identifier/IdentifierConverterInterface.php delete mode 100644 src/Core/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php delete mode 100644 src/Core/Identifier/Normalizer/IntegerDenormalizer.php delete mode 100644 src/Core/JsonApi/EventListener/TransformFieldsetsParametersListener.php delete mode 100644 src/Core/JsonApi/EventListener/TransformFilteringParametersListener.php delete mode 100644 src/Core/JsonApi/EventListener/TransformPaginationParametersListener.php delete mode 100644 src/Core/JsonApi/EventListener/TransformSortingParametersListener.php delete mode 100644 src/Core/JsonApi/Serializer/CollectionNormalizer.php delete mode 100644 src/Core/JsonApi/Serializer/ConstraintViolationListNormalizer.php delete mode 100644 src/Core/JsonApi/Serializer/EntrypointNormalizer.php delete mode 100644 src/Core/JsonApi/Serializer/ErrorNormalizer.php delete mode 100644 src/Core/JsonApi/Serializer/ItemNormalizer.php delete mode 100644 src/Core/JsonApi/Serializer/ObjectNormalizer.php delete mode 100644 src/Core/JsonApi/Serializer/ReservedAttributeNameConverter.php delete mode 100644 src/Core/JsonLd/Action/ContextAction.php delete mode 100644 src/Core/JsonLd/ContextBuilder.php delete mode 100644 src/Core/JsonLd/Serializer/ItemNormalizer.php delete mode 100644 src/Core/JsonLd/Serializer/JsonLdContextTrait.php delete mode 100644 src/Core/JsonLd/Serializer/ObjectNormalizer.php delete mode 100644 src/Core/JsonSchema/Command/JsonSchemaGenerateCommand.php delete mode 100644 src/Core/JsonSchema/Schema.php delete mode 100644 src/Core/JsonSchema/SchemaFactory.php delete mode 100644 src/Core/JsonSchema/TypeFactory.php delete mode 100644 src/Core/Mercure/EventListener/AddLinkHeaderListener.php delete mode 100644 src/Core/Metadata/Extractor/XmlExtractor.php delete mode 100644 src/Core/Metadata/Extractor/YamlExtractor.php delete mode 100644 src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php delete mode 100644 src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php delete mode 100644 src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php delete mode 100644 src/Core/Metadata/Property/PropertyMetadata.php delete mode 100644 src/Core/Metadata/Property/PropertyNameCollection.php delete mode 100644 src/Core/Metadata/Property/SubresourceMetadata.php delete mode 100644 src/Core/Metadata/Resource/ApiResourceToLegacyResourceMetadataTrait.php delete mode 100644 src/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/CachedResourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/OperationResourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/Factory/ResourceMetadataFactoryInterface.php delete mode 100644 src/Core/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php delete mode 100644 src/Core/Metadata/Resource/ResourceMetadata.php delete mode 100644 src/Core/Metadata/Resource/ToggleableOperationAttributeTrait.php delete mode 100644 src/Core/Metadata/schema/metadata.xsd delete mode 100644 src/Core/OpenApi/Factory/OpenApiFactory.php delete mode 100644 src/Core/OpenApi/Model/Components.php delete mode 100644 src/Core/OpenApi/Model/Contact.php delete mode 100644 src/Core/OpenApi/Model/Encoding.php delete mode 100644 src/Core/OpenApi/Model/ExtensionTrait.php delete mode 100644 src/Core/OpenApi/Model/ExternalDocumentation.php delete mode 100644 src/Core/OpenApi/Model/Info.php delete mode 100644 src/Core/OpenApi/Model/License.php delete mode 100644 src/Core/OpenApi/Model/Link.php delete mode 100644 src/Core/OpenApi/Model/MediaType.php delete mode 100644 src/Core/OpenApi/Model/OAuthFlow.php delete mode 100644 src/Core/OpenApi/Model/OAuthFlows.php delete mode 100644 src/Core/OpenApi/Model/Operation.php delete mode 100644 src/Core/OpenApi/Model/Parameter.php delete mode 100644 src/Core/OpenApi/Model/PathItem.php delete mode 100644 src/Core/OpenApi/Model/Paths.php delete mode 100644 src/Core/OpenApi/Model/RequestBody.php delete mode 100644 src/Core/OpenApi/Model/Response.php delete mode 100644 src/Core/OpenApi/Model/Schema.php delete mode 100644 src/Core/OpenApi/Model/SecurityScheme.php delete mode 100644 src/Core/OpenApi/Model/Server.php delete mode 100644 src/Core/OpenApi/OpenApi.php delete mode 100644 src/Core/OpenApi/Options.php delete mode 100644 src/Core/OpenApi/Serializer/OpenApiNormalizer.php delete mode 100644 src/Core/Operation/DashPathSegmentNameGenerator.php delete mode 100644 src/Core/Operation/Factory/CachedSubresourceOperationFactory.php delete mode 100644 src/Core/Operation/Factory/SubresourceOperationFactory.php delete mode 100644 src/Core/Operation/Factory/SubresourceOperationFactoryInterface.php delete mode 100644 src/Core/Operation/UnderscorePathSegmentNameGenerator.php delete mode 100644 src/Core/PathResolver/CustomOperationPathResolver.php delete mode 100644 src/Core/PathResolver/DashOperationPathResolver.php delete mode 100644 src/Core/PathResolver/OperationPathResolver.php delete mode 100644 src/Core/PathResolver/UnderscoreOperationPathResolver.php delete mode 100644 src/Core/Problem/Serializer/ConstraintViolationListNormalizer.php delete mode 100644 src/Core/Problem/Serializer/ErrorNormalizer.php delete mode 100644 src/Core/Problem/Serializer/ErrorNormalizerTrait.php delete mode 100644 src/Core/Security/Core/Authorization/ExpressionLanguageProvider.php delete mode 100644 src/Core/Security/EventListener/DenyAccessListener.php delete mode 100644 src/Core/Security/ExpressionLanguage.php delete mode 100644 src/Core/Security/ResourceAccessChecker.php delete mode 100644 src/Core/Serializer/AbstractCollectionNormalizer.php delete mode 100644 src/Core/Serializer/AbstractConstraintViolationListNormalizer.php delete mode 100644 src/Core/Serializer/AbstractItemNormalizer.php delete mode 100644 src/Core/Serializer/CacheKeyTrait.php delete mode 100644 src/Core/Serializer/ContextTrait.php delete mode 100644 src/Core/Serializer/Filter/GroupFilter.php delete mode 100644 src/Core/Serializer/Filter/PropertyFilter.php delete mode 100644 src/Core/Serializer/InputOutputMetadataTrait.php delete mode 100644 src/Core/Serializer/ItemNormalizer.php delete mode 100644 src/Core/Serializer/JsonEncoder.php delete mode 100644 src/Core/Serializer/Mapping/Factory/ClassMetadataFactory.php delete mode 100644 src/Core/Serializer/ResourceList.php delete mode 100644 src/Core/Serializer/SerializerContextBuilder.php delete mode 100644 src/Core/Serializer/SerializerFilterContextBuilder.php delete mode 100644 src/Core/Swagger/Serializer/ApiGatewayNormalizer.php delete mode 100644 src/Core/Swagger/Serializer/DocumentationNormalizer.php delete mode 100644 src/Core/Test/DoctrineMongoDbOdmFilterTestCase.php delete mode 100644 src/Core/Test/DoctrineMongoDbOdmSetup.php delete mode 100644 src/Core/Test/DoctrineMongoDbOdmTestCase.php delete mode 100644 src/Core/Test/DoctrineOrmFilterTestCase.php delete mode 100644 src/Core/Upgrade/ColorConsoleDiffFormatter.php delete mode 100644 src/Core/Upgrade/RemoveAnnotationTrait.php delete mode 100644 src/Core/Upgrade/SubresourceTransformer.php delete mode 100644 src/Core/Upgrade/UpgradeApiResourceVisitor.php delete mode 100644 src/Core/Upgrade/UpgradeApiSubresourceVisitor.php delete mode 100644 src/Core/Util/AnnotationFilterExtractorTrait.php delete mode 100644 src/Core/Util/ArrayTrait.php delete mode 100644 src/Core/Util/AttributesExtractor.php delete mode 100644 src/Core/Util/ClassInfoTrait.php delete mode 100644 src/Core/Util/ClientTrait.php delete mode 100644 src/Core/Util/CloneTrait.php delete mode 100644 src/Core/Util/CorsTrait.php delete mode 100644 src/Core/Util/ErrorFormatGuesser.php delete mode 100644 src/Core/Util/Inflector.php delete mode 100644 src/Core/Util/IriHelper.php delete mode 100644 src/Core/Util/Reflection.php delete mode 100644 src/Core/Util/ReflectionClassRecursiveIterator.php delete mode 100644 src/Core/Util/RequestAttributesExtractor.php delete mode 100644 src/Core/Util/RequestParser.php delete mode 100644 src/Core/Util/ResourceClassInfoTrait.php delete mode 100644 src/Core/Util/ResponseTrait.php delete mode 100644 src/Core/Util/SortTrait.php delete mode 100644 src/Core/Validator/EventListener/ValidateListener.php delete mode 100644 src/Core/Validator/Exception/ValidationException.php rename tests/{Core => }/Behat/CommandContext.php (98%) rename tests/{Core => }/Behat/CoverageContext.php (97%) rename tests/{Core => }/Behat/DoctrineContext.php (99%) rename tests/{Core => }/Behat/ElasticsearchContext.php (98%) rename tests/{Core => }/Behat/GraphqlContext.php (99%) rename tests/{Core => }/Behat/HttpCacheContext.php (96%) rename tests/{Core => }/Behat/HydraContext.php (99%) rename tests/{Core => }/Behat/JsonApiContext.php (99%) rename tests/{Core => }/Behat/JsonContext.php (98%) rename tests/{Core => }/Behat/JsonHalContext.php (98%) rename tests/{Core => }/Behat/MercureContext.php (97%) rename tests/{Core => }/Behat/OpenApiContext.php (99%) rename tests/{Core => }/Behat/XmlContext.php (96%) delete mode 100644 tests/Core/Annotation/ApiFilterTest.php delete mode 100644 tests/Core/Annotation/ApiPropertyTest.php delete mode 100644 tests/Core/Annotation/ApiResourceTest.php delete mode 100644 tests/Core/Annotation/ApiSubresourceTest.php delete mode 100644 tests/Core/Api/CachedIdentifiersExtractorTest.php delete mode 100644 tests/Core/Api/EntrypointTest.php delete mode 100644 tests/Core/Api/FilterCollectionFactoryTest.php delete mode 100644 tests/Core/Api/FilterCollectionTest.php delete mode 100644 tests/Core/Api/FilterLocatorTraitTest.php delete mode 100644 tests/Core/Api/FormatsProviderTest.php delete mode 100644 tests/Core/Api/IdentifiersExtractorTest.php delete mode 100644 tests/Core/Api/ResourceClassResolverTest.php delete mode 100644 tests/Core/Bridge/Doctrine/Common/DataPersisterTest.php delete mode 100644 tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php delete mode 100644 tests/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php delete mode 100644 tests/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php delete mode 100644 tests/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php delete mode 100644 tests/Core/Bridge/Doctrine/Orm/CollectionDataProviderTest.php delete mode 100644 tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php delete mode 100644 tests/Core/Bridge/Doctrine/Orm/SubresourceDataProviderTest.php delete mode 100644 tests/Core/Bridge/Elasticsearch/Api/IdentifierExtractorTest.php delete mode 100644 tests/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php delete mode 100644 tests/Core/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php delete mode 100644 tests/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php delete mode 100644 tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php delete mode 100644 tests/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php delete mode 100644 tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php delete mode 100644 tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandTest.php delete mode 100644 tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php delete mode 100644 tests/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommandTest.php delete mode 100644 tests/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php delete mode 100644 tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php delete mode 100644 tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php delete mode 100644 tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php delete mode 100644 tests/Core/Bridge/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php delete mode 100644 tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php delete mode 100644 tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php delete mode 100644 tests/Core/Bridge/Symfony/Maker/MakeDataPersisterTest.php delete mode 100644 tests/Core/Bridge/Symfony/Maker/MakeDataProviderTest.php delete mode 100644 tests/Core/Bridge/Symfony/Messenger/DataPersisterTest.php delete mode 100644 tests/Core/Bridge/Symfony/Messenger/DataTransformerTest.php delete mode 100644 tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php delete mode 100644 tests/Core/Bridge/Symfony/Routing/CachedRouteNameResolverTest.php delete mode 100644 tests/Core/Bridge/Symfony/Routing/IriConverterTest.php delete mode 100644 tests/Core/Bridge/Symfony/Routing/RouteNameGeneratorTest.php delete mode 100644 tests/Core/Bridge/Symfony/Routing/RouteNameResolverTest.php delete mode 100644 tests/Core/Bridge/Symfony/Routing/RouterOperationPathResolverTest.php delete mode 100644 tests/Core/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php delete mode 100644 tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php delete mode 100644 tests/Core/DataPersister/ChainDataPersisterTest.php delete mode 100644 tests/Core/DataProvider/ChainCollectionDataProviderTest.php delete mode 100644 tests/Core/DataProvider/ChainItemDataProviderTest.php delete mode 100644 tests/Core/DataProvider/ChainSubresourcedataProviderTest.php delete mode 100644 tests/Core/EventListener/ReadListenerTest.php delete mode 100644 tests/Core/EventListener/WriteListenerTest.php delete mode 100644 tests/Core/Identifier/CompositeIdentifierParserTest.php delete mode 100644 tests/Core/Identifier/IdentifierConverterTest.php delete mode 100644 tests/Core/Identifier/Normalizer/DateTimeIdentifierNormalizerTest.php delete mode 100644 tests/Core/Identifier/Normalizer/IntegerDenormalizerTest.php delete mode 100644 tests/Core/Metadata/Extractor/ExtractorTestCase.php delete mode 100644 tests/Core/Metadata/Extractor/XmlExtractorTest.php delete mode 100644 tests/Core/Metadata/Extractor/YamlExtractorTest.php delete mode 100644 tests/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactoryTest.php delete mode 100644 tests/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Property/Factory/FileConfigurationMetadataFactoryProvider.php delete mode 100644 tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php delete mode 100644 tests/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Property/PropertyMetadataTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php delete mode 100644 tests/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php delete mode 100644 tests/Core/Metadata/Resource/ResourceMetadataTest.php delete mode 100644 tests/Core/Metadata/Resource/ResourceNameCollectionTest.php delete mode 100644 tests/Core/Metadata/schema/XmlSchemaTest.php delete mode 100644 tests/Core/OpenApi/Factory/OpenApiFactoryTest.php delete mode 100644 tests/Core/Operation/DashedPathSegmentNameGeneratorTest.php delete mode 100644 tests/Core/Operation/Factory/CachedSubresourceOperationFactoryTest.php delete mode 100644 tests/Core/Operation/Factory/SubresourceOperationFactoryTest.php delete mode 100644 tests/Core/PathResolver/DashOperationPathResolverTest.php delete mode 100644 tests/Core/PathResolver/UnderscoreOperationPathResolverTest.php delete mode 100644 tests/Core/ProphecyTrait.php delete mode 100644 tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php delete mode 100644 tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php delete mode 100644 tests/Core/Test/BookTestDeprecatedClient.php delete mode 100644 tests/Core/Upgrade/SubresourceTransformerTest.php delete mode 100644 tests/Core/Validator/EventListener/ValidateListenerTest.php rename tests/{Core => }/Mock/Exception/ErrorCodeSerializable.php (91%) diff --git a/src/Core/Action/EntrypointAction.php b/src/Core/Action/EntrypointAction.php deleted file mode 100644 index 7a82b6cfc98..00000000000 --- a/src/Core/Action/EntrypointAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Action; - -class_exists(\ApiPlatform\Action\EntrypointAction::class); - -if (false) { - final class EntrypointAction extends \ApiPlatform\Action\EntrypointAction - { - } -} diff --git a/src/Core/Action/ExceptionAction.php b/src/Core/Action/ExceptionAction.php deleted file mode 100644 index 7272c7d1cb2..00000000000 --- a/src/Core/Action/ExceptionAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Action; - -class_exists(\ApiPlatform\Action\ExceptionAction::class); - -if (false) { - final class ExceptionAction extends \ApiPlatform\Action\ExceptionAction - { - } -} diff --git a/src/Core/Action/NotFoundAction.php b/src/Core/Action/NotFoundAction.php deleted file mode 100644 index cb413a942b9..00000000000 --- a/src/Core/Action/NotFoundAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Action; - -class_exists(\ApiPlatform\Action\NotFoundAction::class); - -if (false) { - final class NotFoundAction extends \ApiPlatform\Action\NotFoundAction - { - } -} diff --git a/src/Core/Action/PlaceholderAction.php b/src/Core/Action/PlaceholderAction.php deleted file mode 100644 index 830ad04323d..00000000000 --- a/src/Core/Action/PlaceholderAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Action; - -class_exists(\ApiPlatform\Action\PlaceholderAction::class); - -if (false) { - final class PlaceholderAction extends \ApiPlatform\Action\PlaceholderAction - { - } -} diff --git a/src/Core/Annotation/ApiFilter.php b/src/Core/Annotation/ApiFilter.php deleted file mode 100644 index c759e8e0526..00000000000 --- a/src/Core/Annotation/ApiFilter.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * 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\Annotation; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * Filter annotation. - * - * @author Antoine Bluchet - * - * @Annotation - * @Target({"PROPERTY", "CLASS"}) - */ -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] -final class ApiFilter -{ - /** - * @var string - */ - public $id; - - /** - * @var string - */ - public $strategy; - - /** - * @var string|FilterInterface - */ - public $filterClass; - - /** - * @var array - */ - public $properties = []; - - /** - * @var array raw arguments for the filter - */ - public $arguments = []; - - /** - * @param string $filterClass - * @param string $id - * @param string $strategy - */ - public function __construct( - $filterClass, - ?string $id = null, - ?string $strategy = null, - array $properties = [], - array $arguments = [] - ) { - if (\is_array($filterClass)) { /** @phpstan-ignore-line Doctrine annotations */ - $options = $filterClass; - $this->filterClass = $options['value'] ?? null; /* @phpstan-ignore-line Doctrine annotations */ - unset($options['value']); - - foreach ($options as $key => $value) { - if (!property_exists($this, $key)) { - throw new InvalidArgumentException(sprintf('Property "%s" does not exist on the ApiFilter annotation.', $key)); - } - - $this->{$key} = $value; - } - } else { - // PHP attribute - $this->filterClass = $filterClass; - $this->id = $id; - $this->strategy = $strategy; - $this->properties = $properties; - $this->arguments = $arguments; - } - - if (!\is_string($this->filterClass)) { - throw new InvalidArgumentException('This annotation needs a value representing the filter class.'); - } - - if (!is_a($this->filterClass, FilterInterface::class, true)) { - throw new InvalidArgumentException(sprintf('The filter class "%s" does not implement "%s". Did you forget a use statement?', $this->filterClass, FilterInterface::class)); - } - } -} diff --git a/src/Core/Annotation/ApiProperty.php b/src/Core/Annotation/ApiProperty.php deleted file mode 100644 index 7070b81a175..00000000000 --- a/src/Core/Annotation/ApiProperty.php +++ /dev/null @@ -1,165 +0,0 @@ - - * - * 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\Annotation; - -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * ApiProperty annotation. - * - * @author Kévin Dunglas - * - * @Annotation - * @Target({"METHOD", "PROPERTY"}) - * @Attributes( - * @Attribute("deprecationReason", type="string"), - * @Attribute("fetchable", type="bool"), - * @Attribute("fetchEager", type="bool"), - * @Attribute("openapiContext", type="array"), - * @Attribute("jsonldContext", type="array"), - * @Attribute("push", type="bool"), - * @Attribute("security", type="string"), - * @Attribute("securityPostDenormalize", type="string"), - * @Attribute("swaggerContext", type="array") - * ) - */ -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::TARGET_PARAMETER)] -final class ApiProperty -{ - use AttributesHydratorTrait; - - /** - * @var array - */ - private static $deprecatedAttributes = []; - - /** - * @var string - */ - public $description; - - /** - * @var bool - */ - public $readable; - - /** - * @var bool - */ - public $writable; - - /** - * @var bool - */ - public $readableLink; - - /** - * @var bool - */ - public $writableLink; - - /** - * @var bool - */ - public $required; - - /** - * @var string - */ - public $iri; - - /** - * @var bool - */ - public $identifier; - - /** - * @var string|int|float|bool|array|null - */ - public $default; - - /** - * @var string|int|float|bool|array|null - */ - public $example; - - public $types; - public $builtinTypes; - - /** - * @param string $description - * @param bool $readable - * @param bool $writable - * @param bool $readableLink - * @param bool $writableLink - * @param bool $required - * @param string $iri - * @param bool $identifier - * @param string|int|float|bool|array $default - * @param string|int|float|bool|array|null $example - * @param string $deprecationReason - * @param bool $fetchable - * @param bool $fetchEager - * @param array $jsonldContext - * @param array $openapiContext - * @param bool $push - * @param string $security - * @param array $swaggerContext - * @param string $securityPostDenormalize - * - * @throws InvalidArgumentException - */ - public function __construct( - $description = null, - ?bool $readable = null, - ?bool $writable = null, - ?bool $readableLink = null, - ?bool $writableLink = null, - ?bool $required = null, - ?string $iri = null, - ?bool $identifier = null, - $default = null, - $example = null, - - // attributes - ?array $attributes = null, - ?string $deprecationReason = null, - ?bool $fetchable = null, - ?bool $fetchEager = null, - ?array $jsonldContext = null, - ?array $openapiContext = null, - ?bool $push = null, - ?string $security = null, - ?array $swaggerContext = null, - ?string $securityPostDenormalize = null, - - ?array $types = [], - ?array $builtinTypes = [] - ) { - if (!\is_array($description)) { // @phpstan-ignore-line Doctrine annotations support - [$publicProperties, $configurableAttributes] = self::getConfigMetadata(); - - foreach ($publicProperties as $prop => $_) { - $this->{$prop} = ${$prop}; - } - - $description = []; - foreach ($configurableAttributes as $attribute => $_) { - $description[$attribute] = ${$attribute}; - } - } - - $this->hydrateAttributes($description); - } -} diff --git a/src/Core/Annotation/ApiResource.php b/src/Core/Annotation/ApiResource.php deleted file mode 100644 index 8f3a9c69887..00000000000 --- a/src/Core/Annotation/ApiResource.php +++ /dev/null @@ -1,251 +0,0 @@ - - * - * 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\Annotation; - -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * ApiResource annotation. - * - * @author Kévin Dunglas - * - * @Annotation - * @Target({"CLASS"}) - * @Attributes( - * @Attribute("accessControl", type="string"), - * @Attribute("accessControlMessage", type="string"), - * @Attribute("attributes", type="array"), - * @Attribute("cacheHeaders", type="array"), - * @Attribute("collectionOperations", type="array"), - * @Attribute("compositeIdentifier", type="bool"), - * @Attribute("denormalizationContext", type="array"), - * @Attribute("deprecationReason", type="string"), - * @Attribute("description", type="string"), - * @Attribute("elasticsearch", type="bool"), - * @Attribute("fetchPartial", type="bool"), - * @Attribute("forceEager", type="bool"), - * @Attribute("formats", type="array"), - * @Attribute("filters", type="string[]"), - * @Attribute("graphql", type="array"), - * @Attribute("hydraContext", type="array"), - * @Attribute("input", type="mixed"), - * @Attribute("iri", type="string"), - * @Attribute("itemOperations", type="array"), - * @Attribute("mercure", type="mixed"), - * @Attribute("messenger", type="mixed"), - * @Attribute("normalizationContext", type="array"), - * @Attribute("openapiContext", type="array"), - * @Attribute("order", type="array"), - * @Attribute("output", type="mixed"), - * @Attribute("paginationClientEnabled", type="bool"), - * @Attribute("paginationClientItemsPerPage", type="bool"), - * @Attribute("paginationClientPartial", type="bool"), - * @Attribute("paginationEnabled", type="bool"), - * @Attribute("paginationFetchJoinCollection", type="bool"), - * @Attribute("paginationItemsPerPage", type="int"), - * @Attribute("maximumItemsPerPage", type="int"), - * @Attribute("paginationMaximumItemsPerPage", type="int"), - * @Attribute("paginationPartial", type="bool"), - * @Attribute("paginationViaCursor", type="array"), - * @Attribute("routePrefix", type="string"), - * @Attribute("security", type="string"), - * @Attribute("securityMessage", type="string"), - * @Attribute("securityPostDenormalize", type="string"), - * @Attribute("securityPostDenormalizeMessage", type="string"), - * @Attribute("securityPostValidation", type="string"), - * @Attribute("securityPostValidationMessage", type="string"), - * @Attribute("shortName", type="string"), - * @Attribute("stateless", type="bool"), - * @Attribute("subresourceOperations", type="array"), - * @Attribute("sunset", type="string"), - * @Attribute("swaggerContext", type="array"), - * @Attribute("urlGenerationStrategy", type="int"), - * @Attribute("validationGroups", type="mixed"), - * @Attribute("exceptionToStatus", type="array"), - * @Attribute("queryParameterValidationEnabled", type="bool") - * ) - */ -#[\Attribute(\Attribute::TARGET_CLASS)] -final class ApiResource -{ - use AttributesHydratorTrait; - - /** - * @var array - */ - private static $deprecatedAttributes = [ - 'accessControl' => ['security', '2.5'], - 'accessControlMessage' => ['securityMessage', '2.5'], - 'maximumItemsPerPage' => ['paginationMaximumItemsPerPage', '2.6'], - ]; - - /** - * @see https://api-platform.com/docs/core/operations - * - * @var array - */ - public $collectionOperations; - - /** - * @var string - */ - public $description; - - /** - * @see https://api-platform.com/docs/core/graphql - * - * @var array - */ - public $graphql; - - /** - * @var string - */ - public $iri; - - /** - * @see https://api-platform.com/docs/core/operations - * - * @var array - */ - public $itemOperations; - - /** - * @var string - */ - public $shortName; - - /** - * @see https://api-platform.com/docs/core/subresources - * - * @var array - */ - public $subresourceOperations; - - /** - * @param string $description - * @param array $collectionOperations https://api-platform.com/docs/core/operations - * @param array $graphql https://api-platform.com/docs/core/graphql - * @param array $itemOperations https://api-platform.com/docs/core/operations - * @param array $subresourceOperations https://api-platform.com/docs/core/subresources - * @param array $cacheHeaders https://api-platform.com/docs/core/performance/#setting-custom-http-cache-headers - * @param array $denormalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups - * @param string $deprecationReason https://api-platform.com/docs/core/deprecations/#deprecating-resource-classes-operations-and-properties - * @param bool $elasticsearch https://api-platform.com/docs/core/elasticsearch/ - * @param bool $fetchPartial https://api-platform.com/docs/core/performance/#fetch-partial - * @param bool $forceEager https://api-platform.com/docs/core/performance/#force-eager - * @param array $formats https://api-platform.com/docs/core/content-negotiation/#configuring-formats-for-a-specific-resource-or-operation - * @param string[] $filters https://api-platform.com/docs/core/filters/#doctrine-orm-and-mongodb-odm-filters - * @param string[] $hydraContext https://api-platform.com/docs/core/extending-jsonld-context/#hydra - * @param string|false $input https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation - * @param bool|array $mercure https://api-platform.com/docs/core/mercure - * @param bool $messenger https://api-platform.com/docs/core/messenger/#dispatching-a-resource-through-the-message-bus - * @param array $normalizationContext https://api-platform.com/docs/core/serialization/#using-serialization-groups - * @param array $openapiContext https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts - * @param array $order https://api-platform.com/docs/core/default-order/#overriding-default-order - * @param string|false $output https://api-platform.com/docs/core/dto/#specifying-an-input-or-an-output-data-representation - * @param bool $paginationClientEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource-1 - * @param bool $paginationClientItemsPerPage https://api-platform.com/docs/core/pagination/#for-a-specific-resource-3 - * @param bool $paginationClientPartial https://api-platform.com/docs/core/pagination/#for-a-specific-resource-6 - * @param array $paginationViaCursor https://api-platform.com/docs/core/pagination/#cursor-based-pagination - * @param bool $paginationEnabled https://api-platform.com/docs/core/pagination/#for-a-specific-resource - * @param bool $paginationFetchJoinCollection https://api-platform.com/docs/core/pagination/#controlling-the-behavior-of-the-doctrine-orm-paginator - * @param int $paginationItemsPerPage https://api-platform.com/docs/core/pagination/#changing-the-number-of-items-per-page - * @param int $paginationMaximumItemsPerPage https://api-platform.com/docs/core/pagination/#changing-maximum-items-per-page - * @param bool $paginationPartial https://api-platform.com/docs/core/performance/#partial-pagination - * @param string $routePrefix https://api-platform.com/docs/core/operations/#prefixing-all-routes-of-all-operations - * @param string $security https://api-platform.com/docs/core/security - * @param string $securityMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param string $securityPostDenormalize https://api-platform.com/docs/core/security/#executing-access-control-rules-after-denormalization - * @param string $securityPostDenormalizeMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param string $securityPostValidation https://api-platform.com/docs/core/security/#executing-access-control-rules-after-validation - * @param string $securityPostValidationMessage https://api-platform.com/docs/core/security/#configuring-the-access-control-error-message - * @param bool $stateless - * @param string $sunset https://api-platform.com/docs/core/deprecations/#setting-the-sunset-http-header-to-indicate-when-a-resource-or-an-operation-will-be-removed - * @param array $swaggerContext https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts - * @param array $validationGroups https://api-platform.com/docs/core/validation/#using-validation-groups - * @param int $urlGenerationStrategy - * @param array $exceptionToStatus https://api-platform.com/docs/core/errors/#fine-grained-configuration - * @param bool $queryParameterValidationEnabled - * - * @throws InvalidArgumentException - */ - public function __construct( - $description = null, - ?array $collectionOperations = null, - ?array $graphql = null, - ?string $iri = null, - ?array $itemOperations = null, - ?string $shortName = null, - ?array $subresourceOperations = null, - - // attributes - ?array $attributes = null, - ?array $cacheHeaders = null, - ?array $denormalizationContext = null, - ?string $deprecationReason = null, - ?bool $elasticsearch = null, - ?bool $fetchPartial = null, - ?bool $forceEager = null, - ?array $formats = null, - ?array $filters = null, - ?array $hydraContext = null, - $input = null, - $mercure = null, - $messenger = null, - ?array $normalizationContext = null, - ?array $openapiContext = null, - ?array $order = null, - $output = null, - ?bool $paginationClientEnabled = null, - ?bool $paginationClientItemsPerPage = null, - ?bool $paginationClientPartial = null, - ?array $paginationViaCursor = null, - ?bool $paginationEnabled = null, - ?bool $paginationFetchJoinCollection = null, - ?int $paginationItemsPerPage = null, - ?int $paginationMaximumItemsPerPage = null, - ?bool $paginationPartial = null, - ?string $routePrefix = null, - ?string $security = null, - ?string $securityMessage = null, - ?string $securityPostDenormalize = null, - ?string $securityPostDenormalizeMessage = null, - ?string $securityPostValidation = null, - ?string $securityPostValidationMessage = null, - ?bool $stateless = null, - ?string $sunset = null, - ?array $swaggerContext = null, - ?array $validationGroups = null, - ?int $urlGenerationStrategy = null, - ?bool $compositeIdentifier = null, - ?array $exceptionToStatus = null, - ?bool $queryParameterValidationEnabled = null - ) { - if (!\is_array($description)) { // @phpstan-ignore-line Doctrine annotations support - [$publicProperties, $configurableAttributes] = self::getConfigMetadata(); - - foreach ($publicProperties as $prop => $_) { - $this->{$prop} = ${$prop}; - } - - $description = []; - foreach ($configurableAttributes as $attribute => $_) { - $description[$attribute] = ${$attribute}; - } - } - - $this->hydrateAttributes($description ?? []); // @phpstan-ignore-line - } -} diff --git a/src/Core/Annotation/ApiSubresource.php b/src/Core/Annotation/ApiSubresource.php deleted file mode 100644 index 27e321505f6..00000000000 --- a/src/Core/Annotation/ApiSubresource.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * 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\Annotation; - -/** - * ApiSubresource annotation. - * - * @author Antoine Bluchet - * - * @Annotation - * @Target({"METHOD", "PROPERTY"}) - * @Attributes( - * @Attribute("maxDepth", type="int"), - * ) - */ -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD)] -final class ApiSubresource -{ - /** - * @var int - */ - public $maxDepth; - - /** - * @param int $maxDepth - */ - public function __construct($maxDepth = null) - { - if (\is_array($maxDepth)) { // @phpstan-ignore-line - $this->maxDepth = $maxDepth['maxDepth'] ?? null; // @phpstan-ignore-line - - return; - } - - $this->maxDepth = $maxDepth; - } -} diff --git a/src/Core/Annotation/AttributesHydratorTrait.php b/src/Core/Annotation/AttributesHydratorTrait.php deleted file mode 100644 index 00fe7481994..00000000000 --- a/src/Core/Annotation/AttributesHydratorTrait.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * 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\Annotation; - -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Util\Inflector; - -/** - * Hydrates attributes from annotation's parameters. - * - * @internal - * - * @author Baptiste Meyer - * @author Kévin Dunglas - */ -trait AttributesHydratorTrait -{ - private static $configMetadata; - - /** - * @internal - */ - public static function getConfigMetadata(): array - { - if (null !== self::$configMetadata) { - return self::$configMetadata; - } - - $rc = new \ReflectionClass(self::class); - - $publicProperties = []; - foreach ($rc->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflectionProperty) { - $publicProperties[$reflectionProperty->getName()] = true; - } - - $configurableAttributes = []; - foreach ($rc->getConstructor()->getParameters() as $param) { - if (!isset($publicProperties[$name = $param->getName()])) { - $configurableAttributes[$name] = true; - } - } - - return [$publicProperties, $configurableAttributes]; - } - - /** - * @var array - */ - public $attributes = null; - - /** - * @throws InvalidArgumentException - */ - private function hydrateAttributes(array $values): void - { - if (isset($values['attributes'])) { - $this->attributes = $values['attributes']; - unset($values['attributes']); - } - - foreach (self::$deprecatedAttributes as $deprecatedAttribute => $options) { - if (\array_key_exists($deprecatedAttribute, $values)) { - $values[$options[0]] = $values[$deprecatedAttribute]; - @trigger_error(sprintf('Attribute "%s" is deprecated in annotation since API Platform %s, prefer using "%s" attribute instead', $deprecatedAttribute, $options[1], $options[0]), \E_USER_DEPRECATED); - unset($values[$deprecatedAttribute]); - } - } - - [$publicProperties, $configurableAttributes] = self::getConfigMetadata(); - foreach ($values as $key => $value) { - $key = (string) $key; - if (!isset($publicProperties[$key]) && !isset($configurableAttributes[$key]) && !isset(self::$deprecatedAttributes[$key])) { - throw new InvalidArgumentException(sprintf('Unknown property "%s" on annotation "%s".', $key, self::class)); - } - - if (isset($publicProperties[$key])) { - $this->{$key} = $value; - continue; - } - - if (!\is_array($this->attributes)) { - $this->attributes = []; - } - - $this->attributes += [Inflector::tableize($key) => $value]; - } - } -} diff --git a/src/Core/Annotation/TemporaryApiResource.php b/src/Core/Annotation/TemporaryApiResource.php deleted file mode 100644 index e54a5442888..00000000000 --- a/src/Core/Annotation/TemporaryApiResource.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * 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\Annotation; - -final class TemporaryApiResource -{ - public function __construct() - { - } -} diff --git a/src/Core/Api/CachedIdentifiersExtractor.php b/src/Core/Api/CachedIdentifiersExtractor.php deleted file mode 100644 index 13d772a4c25..00000000000 --- a/src/Core/Api/CachedIdentifiersExtractor.php +++ /dev/null @@ -1,132 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Util\ResourceClassInfoTrait; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; - -/** - * {@inheritdoc} - * - * @author Antoine Bluchet - */ -final class CachedIdentifiersExtractor implements IdentifiersExtractorInterface -{ - use ResourceClassInfoTrait; - - public const CACHE_KEY_PREFIX = 'iri_identifiers'; - - private $cacheItemPool; - private $propertyAccessor; - private $decorated; - private $localCache = []; - private $localResourceCache = []; - - public function __construct(CacheItemPoolInterface $cacheItemPool, IdentifiersExtractorInterface $decorated, PropertyAccessorInterface $propertyAccessor = null, ResourceClassResolverInterface $resourceClassResolver = null) - { - $this->cacheItemPool = $cacheItemPool; - $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor(); - $this->decorated = $decorated; - $this->resourceClassResolver = $resourceClassResolver; - - if (null === $this->resourceClassResolver) { - @trigger_error(sprintf('Not injecting %s in the CachedIdentifiersExtractor might introduce cache issues with object identifiers.', ResourceClassResolverInterface::class), \E_USER_DEPRECATED); - } - } - - /** - * {@inheritdoc} - */ - public function getIdentifiersFromResourceClass(string $resourceClass): array - { - if (isset($this->localResourceCache[$resourceClass])) { - return $this->localResourceCache[$resourceClass]; - } - - return $this->localResourceCache[$resourceClass] = $this->decorated->getIdentifiersFromResourceClass($resourceClass); - } - - /** - * {@inheritdoc} - */ - public function getIdentifiersFromItem($item): array - { - $keys = $this->getKeys($item, function ($item) use (&$identifiers) { - return $identifiers = $this->decorated->getIdentifiersFromItem($item); - }); - - if (null !== $identifiers) { - return $identifiers; - } - - $identifiers = []; - foreach ($keys as $propertyName) { - $identifiers[$propertyName] = $this->propertyAccessor->getValue($item, $propertyName); - - if (!\is_object($identifiers[$propertyName])) { - continue; - } - - if (null === $relatedResourceClass = $this->getResourceClass($identifiers[$propertyName])) { - continue; - } - - if (!$relatedIdentifiers = $this->localCache[$relatedResourceClass] ?? false) { - $relatedCacheKey = self::CACHE_KEY_PREFIX.md5($relatedResourceClass); - try { - $relatedCacheItem = $this->cacheItemPool->getItem($relatedCacheKey); - if (!$relatedCacheItem->isHit()) { - return $this->decorated->getIdentifiersFromItem($item); - } - } catch (CacheException $e) { - return $this->decorated->getIdentifiersFromItem($item); - } - - $relatedIdentifiers = $relatedCacheItem->get(); - } - - $identifiers[$propertyName] = $this->propertyAccessor->getValue($identifiers[$propertyName], $relatedIdentifiers[0]); - } - - return $identifiers; - } - - private function getKeys($item, callable $retriever): array - { - $resourceClass = $this->getObjectClass($item); - if (isset($this->localCache[$resourceClass])) { - return $this->localCache[$resourceClass]; - } - - try { - $cacheItem = $this->cacheItemPool->getItem(self::CACHE_KEY_PREFIX.md5($resourceClass)); - } catch (CacheException $e) { - return $this->localCache[$resourceClass] = array_keys($retriever($item)); - } - - if ($cacheItem->isHit()) { - return $this->localCache[$resourceClass] = $cacheItem->get(); - } - - $keys = array_keys($retriever($item)); - - $cacheItem->set($keys); - $this->cacheItemPool->save($cacheItem); - - return $this->localCache[$resourceClass] = $keys; - } -} diff --git a/src/Core/Api/Entrypoint.php b/src/Core/Api/Entrypoint.php deleted file mode 100644 index af2588bfb28..00000000000 --- a/src/Core/Api/Entrypoint.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Api; - -class_exists(\ApiPlatform\Api\Entrypoint::class); - -if (false) { - final class Entrypoint extends \ApiPlatform\Api\Entrypoint - { - } -} diff --git a/src/Core/Api/FilterCollection.php b/src/Core/Api/FilterCollection.php deleted file mode 100644 index b1bcc1c3584..00000000000 --- a/src/Core/Api/FilterCollection.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * 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\Api; - -use Psr\Container\ContainerInterface; - -/** - * A list of filters. - * - * @author Kévin Dunglas - * - * @deprecated since version 2.1, to be removed in 3.0. Use a service locator {@see \Psr\Container\ContainerInterface}. - */ -final class FilterCollection extends \ArrayObject -{ - public function __construct($input = [], $flags = 0, $iterator_class = 'ArrayIterator') - { - @trigger_error(sprintf('The %s class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of %s instead.', self::class, ContainerInterface::class), \E_USER_DEPRECATED); - - parent::__construct($input, $flags, $iterator_class); - } -} diff --git a/src/Core/Api/FilterCollectionFactory.php b/src/Core/Api/FilterCollectionFactory.php deleted file mode 100644 index 20da8ee17cf..00000000000 --- a/src/Core/Api/FilterCollectionFactory.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * 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\Api; - -use Psr\Container\ContainerInterface; - -/** - * Filter collection factory. - * - * @author Baptiste Meyer - * - * @deprecated see FilterCollection - * - * @internal - */ -class FilterCollectionFactory -{ - private $filtersIds; - - /** - * @param string[] $filtersIds - */ - public function __construct(array $filtersIds) - { - $this->filtersIds = $filtersIds; - } - - /** - * Creates a filter collection from a filter locator. - */ - public function createFilterCollectionFromLocator(ContainerInterface $filterLocator): FilterCollection - { - $filters = []; - - foreach ($this->filtersIds as $filterId) { - if ($filterLocator->has($filterId)) { - $filters[$filterId] = $filterLocator->get($filterId); - } - } - - return new FilterCollection($filters); - } -} diff --git a/src/Core/Api/FilterLocatorTrait.php b/src/Core/Api/FilterLocatorTrait.php deleted file mode 100644 index b11504fbe15..00000000000 --- a/src/Core/Api/FilterLocatorTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Api; - -class_exists(\ApiPlatform\Api\FilterLocatorTrait::class); - -if (false) { - trait FilterLocatorTrait - { - use \ApiPlatform\Api\FilterLocatorTrait; - } -} diff --git a/src/Core/Api/FormatMatcher.php b/src/Core/Api/FormatMatcher.php deleted file mode 100644 index 38cc12cf6df..00000000000 --- a/src/Core/Api/FormatMatcher.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Api; - -class_exists(\ApiPlatform\Api\FormatMatcher::class); - -if (false) { - final class FormatMatcher extends \ApiPlatform\Api\FormatMatcher - { - } -} diff --git a/src/Core/Api/FormatsProvider.php b/src/Core/Api/FormatsProvider.php deleted file mode 100644 index 2c6ae254c73..00000000000 --- a/src/Core/Api/FormatsProvider.php +++ /dev/null @@ -1,109 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * {@inheritdoc} - * - * @author Anthony GRASSIOT - * - * @deprecated since API Platform 2.5, use the "formats" attribute instead - */ -final class FormatsProvider implements FormatsProviderInterface, OperationAwareFormatsProviderInterface -{ - private $configuredFormats; - private $resourceMetadataFactory; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, array $configuredFormats) - { - @trigger_error(sprintf('The "%s" class is deprecated since API Platform 2.5, use the "formats" attribute instead.', __CLASS__), \E_USER_DEPRECATED); - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->configuredFormats = $configuredFormats; - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException - */ - public function getFormatsFromAttributes(array $attributes): array - { - if (!$attributes || !isset($attributes['resource_class'])) { - return $this->configuredFormats; - } - - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - - if (!$formats = $resourceMetadata->getOperationAttribute($attributes, 'formats', [], true)) { - return $this->configuredFormats; - } - - if (!\is_array($formats)) { - throw new InvalidArgumentException(sprintf("The 'formats' attributes must be an array, %s given for resource class '%s'.", \gettype($formats), $attributes['resource_class'])); - } - - return $this->getOperationFormats($formats); - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException - */ - public function getFormatsFromOperation(string $resourceClass, string $operationName, string $operationType): array - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if (!$formats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'formats', [], true)) { - return $this->configuredFormats; - } - - if (!\is_array($formats)) { - throw new InvalidArgumentException(sprintf("The 'formats' attributes must be an array, %s given for resource class '%s'.", \gettype($formats), $resourceClass)); - } - - return $this->getOperationFormats($formats); - } - - /** - * Filter and populate the acceptable formats. - * - * @throws InvalidArgumentException - */ - private function getOperationFormats(array $annotationFormats): array - { - $resourceFormats = []; - foreach ($annotationFormats as $format => $value) { - if (!is_numeric($format)) { - $resourceFormats[$format] = (array) $value; - continue; - } - if (!\is_string($value)) { - throw new InvalidArgumentException(sprintf("The 'formats' attributes value must be a string when trying to include an already configured format, %s given.", \gettype($value))); - } - if (\array_key_exists($value, $this->configuredFormats)) { - $resourceFormats[$value] = $this->configuredFormats[$value]; - continue; - } - - throw new InvalidArgumentException(sprintf("You either need to add the format '%s' to your project configuration or declare a mime type for it in your annotation.", $value)); - } - - return $resourceFormats; - } -} diff --git a/src/Core/Api/FormatsProviderInterface.php b/src/Core/Api/FormatsProviderInterface.php deleted file mode 100644 index ea979141a28..00000000000 --- a/src/Core/Api/FormatsProviderInterface.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * 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\Api; - -/** - * Extracts formats for a given operation according to the retrieved Metadata. - * - * @author Anthony GRASSIOT - * - * @deprecated since API Platform 2.5, use the "formats" attribute instead - */ -interface FormatsProviderInterface -{ - /** - * Finds formats for an operation. - */ - public function getFormatsFromAttributes(array $attributes): array; -} diff --git a/src/Core/Api/IdentifiersExtractor.php b/src/Core/Api/IdentifiersExtractor.php deleted file mode 100644 index f6bbf3f43fb..00000000000 --- a/src/Core/Api/IdentifiersExtractor.php +++ /dev/null @@ -1,121 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Api\IdentifiersExtractor as NewIdentifiersExtractor; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; - -/** - * {@inheritdoc} - * - * @author Antoine Bluchet - */ -final class IdentifiersExtractor implements IdentifiersExtractorInterface -{ - use ResourceClassInfoTrait; - - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $propertyAccessor; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, PropertyAccessorInterface $propertyAccessor = null, ResourceClassResolverInterface $resourceClassResolver = null, bool $metadataBackwardCompatibilityLayer = null) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor(); - $this->resourceClassResolver = $resourceClassResolver; - - if (null === $this->resourceClassResolver) { - @trigger_error(sprintf('Not injecting %s in the IdentifiersExtractor might introduce cache issues with object identifiers.', ResourceClassResolverInterface::class), \E_USER_DEPRECATED); - } - - if ($metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The service "%s" is deprecated, use %s instead.', self::class, NewIdentifiersExtractor::class)); - } - } - - /** - * {@inheritdoc} - */ - public function getIdentifiersFromResourceClass(string $resourceClass): array - { - $identifiers = []; - foreach ($properties = $this->propertyNameCollectionFactory->create($resourceClass) as $property) { - if ($this->propertyMetadataFactory->create($resourceClass, $property)->isIdentifier() ?? false) { - $identifiers[] = $property; - } - } - - if (!$identifiers) { - if (\in_array('id', iterator_to_array($properties), true)) { - return ['id']; - } - - throw new RuntimeException(sprintf('No identifier defined in "%s". You should add #[\ApiPlatform\Core\Annotation\ApiProperty(identifier: true)]" on the property identifying the resource."', $resourceClass)); - } - - return $identifiers; - } - - /** - * {@inheritdoc} - */ - public function getIdentifiersFromItem($item): array - { - $identifiers = []; - $resourceClass = $this->getResourceClass($item, true); - $identifierProperties = $this->getIdentifiersFromResourceClass($resourceClass); - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - if (!\in_array($propertyName, $identifierProperties, true)) { - continue; - } - - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - $identifier = $identifiers[$propertyName] = $this->propertyAccessor->getValue($item, $propertyName); - - if (!\is_object($identifier)) { - continue; - } - - if (null === $relatedResourceClass = $this->getResourceClass($identifier)) { - continue; - } - - $relatedItem = $identifier; - unset($identifiers[$propertyName]); - foreach ($this->propertyNameCollectionFactory->create($relatedResourceClass) as $relatedPropertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($relatedResourceClass, $relatedPropertyName); - if ($propertyMetadata->isIdentifier()) { - if (isset($identifiers[$propertyName])) { - throw new RuntimeException(sprintf('Composite identifiers not supported in "%s" through relation "%s" of "%s" used as identifier', $relatedResourceClass, $propertyName, $resourceClass)); - } - - $identifiers[$propertyName] = $this->propertyAccessor->getValue($relatedItem, $relatedPropertyName); - } - } - - if (!isset($identifiers[$propertyName])) { - throw new RuntimeException(sprintf('No identifier found in "%s" through relation "%s" of "%s" used as identifier', $relatedResourceClass, $propertyName, $resourceClass)); - } - } - - return $identifiers; - } -} diff --git a/src/Core/Api/IdentifiersExtractorInterface.php b/src/Core/Api/IdentifiersExtractorInterface.php deleted file mode 100644 index 2a964d489ad..00000000000 --- a/src/Core/Api/IdentifiersExtractorInterface.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Exception\RuntimeException; - -/** - * Extracts identifiers for a given Resource according to the retrieved Metadata. - * - * @author Antoine Bluchet - */ -interface IdentifiersExtractorInterface -{ - /** - * Finds identifiers from a Resource class. - */ - public function getIdentifiersFromResourceClass(string $resourceClass): array; - - /** - * Finds identifiers from an Item (object). - * - * @param object $item - * - * @throws RuntimeException - */ - public function getIdentifiersFromItem($item): array; -} diff --git a/src/Core/Api/IriConverterInterface.php b/src/Core/Api/IriConverterInterface.php deleted file mode 100644 index 85af6b3024f..00000000000 --- a/src/Core/Api/IriConverterInterface.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ItemNotFoundException; -use ApiPlatform\Exception\RuntimeException; - -/** - * Converts item and resources to IRI and vice versa. - * - * @author Kévin Dunglas - */ -interface IriConverterInterface -{ - /** - * Retrieves an item from its IRI. - * - * @throws InvalidArgumentException - * @throws ItemNotFoundException - * - * @return object - */ - public function getItemFromIri(string $iri, array $context = []); - - /** - * Gets the IRI associated with the given item. - * - * @param object $item - * - * @throws InvalidArgumentException - * @throws RuntimeException - */ - public function getIriFromItem($item, int $referenceType = UrlGeneratorInterface::ABS_PATH): string; - - /** - * Gets the IRI associated with the given resource collection. - * - * @throws InvalidArgumentException - */ - public function getIriFromResourceClass(string $resourceClass, int $referenceType = UrlGeneratorInterface::ABS_PATH): string; - - /** - * Gets the item IRI associated with the given resource. - * - * @throws InvalidArgumentException - */ - public function getItemIriFromResourceClass(string $resourceClass, array $identifiers, int $referenceType = UrlGeneratorInterface::ABS_PATH): string; - - /** - * Gets the IRI associated with the given resource subresource. - * - * @throws InvalidArgumentException - */ - public function getSubresourceIriFromResourceClass(string $resourceClass, array $identifiers, int $referenceType = UrlGeneratorInterface::ABS_PATH): string; -} diff --git a/src/Core/Api/OperationAwareFormatsProviderInterface.php b/src/Core/Api/OperationAwareFormatsProviderInterface.php deleted file mode 100644 index 7860aa1ff0f..00000000000 --- a/src/Core/Api/OperationAwareFormatsProviderInterface.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * 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\Api; - -/** - * Extracts formats for a given operation according to the retrieved Metadata. - * - * @author Anthony GRASSIOT - * - * @deprecated since API Platform 2.5, use the "formats" attribute instead - */ -interface OperationAwareFormatsProviderInterface extends FormatsProviderInterface -{ - /** - * Finds formats for an operation. - */ - public function getFormatsFromOperation(string $resourceClass, string $operationName, string $operationType): array; -} diff --git a/src/Core/Api/OperationMethodResolverInterface.php b/src/Core/Api/OperationMethodResolverInterface.php deleted file mode 100644 index a9f95c9706e..00000000000 --- a/src/Core/Api/OperationMethodResolverInterface.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Exception\RuntimeException; - -/** - * Resolves the uppercased HTTP method associated with an operation. - * - * @author Kévin Dunglas - * - * @deprecated since API Platform 2.5, use the "method" attribute instead - */ -interface OperationMethodResolverInterface -{ - /** - * Resolves the uppercased HTTP method associated with a collection operation. - * - * @throws RuntimeException - */ - public function getCollectionOperationMethod(string $resourceClass, string $operationName): string; - - /** - * Resolves the uppercased HTTP method associated with an item operation. - * - * @throws RuntimeException - */ - public function getItemOperationMethod(string $resourceClass, string $operationName): string; -} diff --git a/src/Core/Api/OperationType.php b/src/Core/Api/OperationType.php deleted file mode 100644 index f1daa8b016b..00000000000 --- a/src/Core/Api/OperationType.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Api; - -final class OperationType -{ - public const ITEM = 'item'; - public const COLLECTION = 'collection'; - public const SUBRESOURCE = 'subresource'; - public const TYPES = [self::ITEM, self::COLLECTION, self::SUBRESOURCE]; -} diff --git a/src/Core/Api/OperationTypeDeprecationHelper.php b/src/Core/Api/OperationTypeDeprecationHelper.php deleted file mode 100644 index 4d8c35e873e..00000000000 --- a/src/Core/Api/OperationTypeDeprecationHelper.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * 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\Api; - -/** - * Class OperationTypeDeprecationHelper - * Before API Platform 2.1, the operation type was one of: - * - "collection" (true) - * - "item" (false). - * - * Because we introduced a third type in API Platform 2.1, we're using a string with OperationType constants: - * - OperationType::ITEM - * - OperationType::COLLECTION - * - OperationType::SUBRESOURCE - * - * @internal - */ -final class OperationTypeDeprecationHelper -{ - /** - * @param string|bool $operationType - */ - public static function getOperationType($operationType): string - { - if (\is_bool($operationType)) { - @trigger_error('Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3', \E_USER_DEPRECATED); - - $operationType = $operationType ? OperationType::COLLECTION : OperationType::ITEM; - } - - return $operationType; - } -} diff --git a/src/Core/Api/ResourceClassResolver.php b/src/Core/Api/ResourceClassResolver.php deleted file mode 100644 index 9eff13927b7..00000000000 --- a/src/Core/Api/ResourceClassResolver.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Api; - -class_exists(\ApiPlatform\Api\ResourceClassResolver::class); - -if (false) { - final class ResourceClassResolver extends \ApiPlatform\Api\ResourceClassResolver - { - } -} diff --git a/src/Core/Bridge/Doctrine/Common/DataPersister.php b/src/Core/Bridge/Doctrine/Common/DataPersister.php deleted file mode 100644 index a13d92fc5f7..00000000000 --- a/src/Core/Bridge/Doctrine/Common/DataPersister.php +++ /dev/null @@ -1,105 +0,0 @@ - - * - * 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\Doctrine\Common; - -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Util\ClassInfoTrait; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager as DoctrineObjectManager; - -/** - * Data persister for Doctrine. - * - * @author Baptiste Meyer - * - * @deprecated - */ -final class DataPersister implements ContextAwareDataPersisterInterface -{ - use ClassInfoTrait; - - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry) - { - $this->managerRegistry = $managerRegistry; - } - - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - return null !== $this->getManager($data); - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []) - { - if (!$manager = $this->getManager($data)) { - return $data; - } - - if (!$manager->contains($data) || $this->isDeferredExplicit($manager, $data)) { - $manager->persist($data); - } - - $manager->flush(); - $manager->refresh($data); - - return $data; - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []) - { - if (!$manager = $this->getManager($data)) { - return; - } - - $manager->remove($data); - $manager->flush(); - } - - /** - * Gets the Doctrine object manager associated with given data. - * - * @param mixed $data - */ - private function getManager($data): ?DoctrineObjectManager - { - return \is_object($data) ? $this->managerRegistry->getManagerForClass($this->getObjectClass($data)) : null; - } - - /** - * Checks if doctrine does not manage data automatically. - * - * @param mixed $data - */ - private function isDeferredExplicit(DoctrineObjectManager $manager, $data): bool - { - $classMetadata = $manager->getClassMetadata($this->getObjectClass($data)); - if (($classMetadata instanceof ClassMetadataInfo || $classMetadata instanceof ClassMetadata) && method_exists($classMetadata, 'isChangeTrackingDeferredExplicit')) { - return $classMetadata->isChangeTrackingDeferredExplicit(); - } - - return false; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/BooleanFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/BooleanFilterTrait.php deleted file mode 100644 index a010295a6ca..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/BooleanFilterTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\BooleanFilterTrait::class); - -if (false) { - trait BooleanFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\BooleanFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/DateFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/DateFilterTrait.php deleted file mode 100644 index e3af076d8b2..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/DateFilterTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\DateFilterTrait::class); - -if (false) { - trait DateFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\DateFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/ExistsFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/ExistsFilterTrait.php deleted file mode 100644 index 6fb083c5238..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/ExistsFilterTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\ExistsFilterTrait::class); - -if (false) { - trait ExistsFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\ExistsFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/NumericFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/NumericFilterTrait.php deleted file mode 100644 index bdb714063d2..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/NumericFilterTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\NumericFilterTrait::class); - -if (false) { - trait NumericFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\NumericFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/OrderFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/OrderFilterTrait.php deleted file mode 100644 index 96a3664ffdb..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/OrderFilterTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait::class); - -if (false) { - trait OrderFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/RangeFilterTrait.php deleted file mode 100644 index 32d985d341d..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/RangeFilterTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\RangeFilterTrait::class); - -if (false) { - trait RangeFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\RangeFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Filter/SearchFilterTrait.php b/src/Core/Bridge/Doctrine/Common/Filter/SearchFilterTrait.php deleted file mode 100644 index 9a37121ceed..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Filter/SearchFilterTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Common\Filter; - -class_exists(\ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait::class); - -if (false) { - trait SearchFilterTrait - { - use \ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/PropertyHelperTrait.php b/src/Core/Bridge/Doctrine/Common/PropertyHelperTrait.php deleted file mode 100644 index 3695281abe2..00000000000 --- a/src/Core/Bridge/Doctrine/Common/PropertyHelperTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Common; - -class_exists(\ApiPlatform\Doctrine\Common\PropertyHelperTrait::class); - -if (false) { - trait PropertyHelperTrait - { - use \ApiPlatform\Doctrine\Common\PropertyHelperTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTrait.php b/src/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTrait.php deleted file mode 100644 index 3ecb1f9dfff..00000000000 --- a/src/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTrait.php +++ /dev/null @@ -1,113 +0,0 @@ - - * - * 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\Doctrine\Common\Util; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\PropertyNotFoundException; -use Doctrine\DBAL\Types\ConversionException; -use Doctrine\DBAL\Types\Type as DBALType; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\ObjectManager; - -/** - * @internal - */ -trait IdentifierManagerTrait -{ - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $resourceMetadataFactory; - - /** - * Transform and check the identifier, composite or not. - * - * @param int|string $id - * - * @throws PropertyNotFoundException - * @throws InvalidIdentifierException - */ - private function normalizeIdentifiers($id, ObjectManager $manager, string $resourceClass): array - { - $identifierValues = [$id]; - $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); - $doctrineIdentifierFields = $doctrineClassMetadata->getIdentifier(); - $isOrm = $manager instanceof EntityManagerInterface; - $isOdm = $manager instanceof DocumentManager; - $platform = $isOrm ? $manager->getConnection()->getDatabasePlatform() : null; - $identifiersMap = null; - - if (\count($doctrineIdentifierFields) > 1) { - $identifiersMap = []; - - // first transform identifiers to a proper key/value array - foreach (explode(';', (string) $id) as $identifier) { - if (!$identifier) { - continue; - } - - $identifierPair = explode('=', $identifier); - $identifiersMap[$identifierPair[0]] = $identifierPair[1]; - } - } - - $identifiers = []; - $i = 0; - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - - if (!$propertyMetadata->isIdentifier()) { - continue; - } - - $identifier = null === $identifiersMap ? $identifierValues[$i] ?? null : $identifiersMap[$propertyName] ?? null; - if (null === $identifier) { - $exceptionMessage = sprintf('Invalid identifier "%s", "%s" was not found', $id, $propertyName); - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $exceptionMessage .= sprintf(' for resource "%s"', $resourceMetadata->getShortName()); - } - - throw new PropertyNotFoundException($exceptionMessage.'.'); - } - - $doctrineTypeName = $doctrineClassMetadata->getTypeOfField($propertyName); - - try { - if ($isOrm && null !== $doctrineTypeName && DBALType::hasType($doctrineTypeName)) { - $identifier = DBALType::getType($doctrineTypeName)->convertToPHPValue($identifier, $platform); - } - if ($isOdm && null !== $doctrineTypeName && MongoDbType::hasType($doctrineTypeName)) { - $identifier = MongoDbType::getType($doctrineTypeName)->convertToPHPValue($identifier); - } - } catch (ConversionException $e) { - $exceptionMessage = sprintf('Invalid value "%s" provided for an identifier', $propertyName); - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $exceptionMessage .= sprintf(' for resource "%s"', $resourceMetadata->getShortName()); - } - - throw new InvalidIdentifierException($exceptionMessage.'.', $e->getCode(), $e); - } - - $identifiers[$propertyName] = $identifier; - ++$i; - } - - return $identifiers; - } -} diff --git a/src/Core/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php b/src/Core/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php deleted file mode 100644 index 2cf6b56b204..00000000000 --- a/src/Core/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php +++ /dev/null @@ -1,285 +0,0 @@ - - * - * 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\Doctrine\EventListener; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Bridge\Symfony\Messenger\DispatchTrait; -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface as GraphQlMercureSubscriptionIriGeneratorInterface; -use ApiPlatform\Core\GraphQl\Subscription\SubscriptionManagerInterface as GraphQlSubscriptionManagerInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ResourceClassInfoTrait; -use Doctrine\Common\EventArgs; -use Doctrine\ODM\MongoDB\Event\OnFlushEventArgs as MongoDbOdmOnFlushEventArgs; -use Doctrine\ORM\Event\OnFlushEventArgs as OrmOnFlushEventArgs; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\Mercure\HubRegistry; -use Symfony\Component\Mercure\Update; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * Publishes resources updates to the Mercure hub. - * - * @author Kévin Dunglas - * - * @experimental - */ -final class PublishMercureUpdatesListener -{ - use DispatchTrait; - use ResourceClassInfoTrait; - - private const ALLOWED_KEYS = [ - 'topics' => true, - 'data' => true, - 'private' => true, - 'id' => true, - 'type' => true, - 'retry' => true, - 'normalization_context' => true, - 'hub' => true, - 'enable_async_update' => true, - ]; - - private $iriConverter; - private $serializer; - private $hubRegistry; - private $expressionLanguage; - private $createdObjects; - private $updatedObjects; - private $deletedObjects; - private $formats; - private $graphQlSubscriptionManager; - private $graphQlMercureSubscriptionIriGenerator; - - /** - * @param array $formats - * @param HubRegistry|callable $hubRegistry - */ - public function __construct(ResourceClassResolverInterface $resourceClassResolver, IriConverterInterface $iriConverter, ResourceMetadataFactoryInterface $resourceMetadataFactory, SerializerInterface $serializer, array $formats, MessageBusInterface $messageBus = null, $hubRegistry = null, ?GraphQlSubscriptionManagerInterface $graphQlSubscriptionManager = null, ?GraphQlMercureSubscriptionIriGeneratorInterface $graphQlMercureSubscriptionIriGenerator = null, ExpressionLanguage $expressionLanguage = null) - { - if (null === $messageBus && null === $hubRegistry) { - throw new InvalidArgumentException('A message bus or a hub registry must be provided.'); - } - - $this->resourceClassResolver = $resourceClassResolver; - $this->iriConverter = $iriConverter; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->serializer = $serializer; - $this->formats = $formats; - $this->messageBus = $messageBus; - $this->hubRegistry = $hubRegistry; - $this->expressionLanguage = $expressionLanguage ?? (class_exists(ExpressionLanguage::class) ? new ExpressionLanguage() : null); - $this->graphQlSubscriptionManager = $graphQlSubscriptionManager; - $this->graphQlMercureSubscriptionIriGenerator = $graphQlMercureSubscriptionIriGenerator; - $this->reset(); - } - - /** - * Collects created, updated and deleted objects. - */ - public function onFlush(EventArgs $eventArgs): void - { - if ($eventArgs instanceof OrmOnFlushEventArgs) { - $uow = $eventArgs->getEntityManager()->getUnitOfWork(); - } elseif ($eventArgs instanceof MongoDbOdmOnFlushEventArgs) { - $uow = $eventArgs->getDocumentManager()->getUnitOfWork(); - } else { - return; - } - - $methodName = $eventArgs instanceof OrmOnFlushEventArgs ? 'getScheduledEntityInsertions' : 'getScheduledDocumentInsertions'; - foreach ($uow->{$methodName}() as $object) { - $this->storeObjectToPublish($object, 'createdObjects'); - } - - $methodName = $eventArgs instanceof OrmOnFlushEventArgs ? 'getScheduledEntityUpdates' : 'getScheduledDocumentUpdates'; - foreach ($uow->{$methodName}() as $object) { - $this->storeObjectToPublish($object, 'updatedObjects'); - } - - $methodName = $eventArgs instanceof OrmOnFlushEventArgs ? 'getScheduledEntityDeletions' : 'getScheduledDocumentDeletions'; - foreach ($uow->{$methodName}() as $object) { - $this->storeObjectToPublish($object, 'deletedObjects'); - } - } - - /** - * Publishes updates for changes collected on flush, and resets the store. - */ - public function postFlush(): void - { - try { - foreach ($this->createdObjects as $object) { - $this->publishUpdate($object, $this->createdObjects[$object], 'create'); - } - - foreach ($this->updatedObjects as $object) { - $this->publishUpdate($object, $this->updatedObjects[$object], 'update'); - } - - foreach ($this->deletedObjects as $object) { - $this->publishUpdate($object, $this->deletedObjects[$object], 'delete'); - } - } finally { - $this->reset(); - } - } - - private function reset(): void - { - $this->createdObjects = new \SplObjectStorage(); - $this->updatedObjects = new \SplObjectStorage(); - $this->deletedObjects = new \SplObjectStorage(); - } - - /** - * @param object $object - */ - private function storeObjectToPublish($object, string $property): void - { - if (null === $resourceClass = $this->getResourceClass($object)) { - return; - } - - $options = $this->resourceMetadataFactory->create($resourceClass)->getAttribute('mercure', false); - - if (\is_string($options)) { - if (null === $this->expressionLanguage) { - throw new RuntimeException('The Expression Language component is not installed. Try running "composer require symfony/expression-language".'); - } - - $options = $this->expressionLanguage->evaluate($options, ['object' => $object]); - } - - if (false === $options) { - return; - } - - if (true === $options) { - $options = []; - } - - if (!\is_array($options)) { - throw new InvalidArgumentException(sprintf('The value of the "mercure" attribute of the "%s" resource class must be a boolean, an array of options or an expression returning this array, "%s" given.', $resourceClass, \gettype($options))); - } - - foreach ($options as $key => $value) { - if (0 === $key) { - if (method_exists(Update::class, 'isPrivate')) { - throw new \InvalidArgumentException('Targets do not exist anymore since Mercure 0.10. Mark the update as private instead or downgrade the Mercure Component to version 0.3'); - } - - @trigger_error('Targets do not exist anymore since Mercure 0.10. Mark the update as private instead.', \E_USER_DEPRECATED); - break; - } - - if (!isset(self::ALLOWED_KEYS[$key])) { - throw new InvalidArgumentException(sprintf('The option "%s" set in the "mercure" attribute of the "%s" resource does not exist. Existing options: "%s"', $key, $resourceClass, implode('", "', self::ALLOWED_KEYS))); - } - - if ('hub' === $key && !$this->hubRegistry instanceof HubRegistry) { - throw new InvalidArgumentException(sprintf('The option "hub" of the "mercure" attribute cannot be set on the "%s" resource . Try running "composer require symfony/mercure:^0.5".', $resourceClass)); - } - } - - $options['enable_async_update'] = $options['enable_async_update'] ?? true; - - if ('deletedObjects' === $property) { - $this->deletedObjects[(object) [ - 'id' => $this->iriConverter->getIriFromItem($object), - 'iri' => $this->iriConverter->getIriFromItem($object, UrlGeneratorInterface::ABS_URL), - ]] = $options; - - return; - } - - $this->{$property}[$object] = $options; - } - - /** - * @param object $object - */ - private function publishUpdate($object, array $options, string $type): void - { - if ($object instanceof \stdClass) { - // By convention, if the object has been deleted, we send only its IRI. - // This may change in the feature, because it's not JSON Merge Patch compliant, - // and I'm not a fond of this approach. - $iri = $options['topics'] ?? $object->iri; - /** @var string $data */ - $data = json_encode(['@id' => $object->id]); - } else { - $resourceClass = $this->getObjectClass($object); - $context = $options['normalization_context'] ?? $this->resourceMetadataFactory->create($resourceClass)->getAttribute('normalization_context', []); - - $iri = $options['topics'] ?? $this->iriConverter->getIriFromItem($object, UrlGeneratorInterface::ABS_URL); - $data = $options['data'] ?? $this->serializer->serialize($object, key($this->formats), $context); - } - - $updates = array_merge([$this->buildUpdate($iri, $data, $options)], $this->getGraphQlSubscriptionUpdates($object, $options, $type)); - - foreach ($updates as $update) { - if ($options['enable_async_update'] && $this->messageBus) { - $this->dispatch($update); - continue; - } - - $this->hubRegistry instanceof HubRegistry ? $this->hubRegistry->getHub($options['hub'] ?? null)->publish($update) : ($this->hubRegistry)($update); - } - } - - /** - * @param object $object - * - * @return Update[] - */ - private function getGraphQlSubscriptionUpdates($object, array $options, string $type): array - { - if ('update' !== $type || !$this->graphQlSubscriptionManager || !$this->graphQlMercureSubscriptionIriGenerator) { - return []; - } - - $payloads = $this->graphQlSubscriptionManager->getPushPayloads($object); - - $updates = []; - foreach ($payloads as [$subscriptionId, $data]) { - $updates[] = $this->buildUpdate( - $this->graphQlMercureSubscriptionIriGenerator->generateTopicIri($subscriptionId), - (string) (new JsonResponse($data))->getContent(), - $options - ); - } - - return $updates; - } - - /** - * @param string|string[] $iri - */ - private function buildUpdate($iri, string $data, array $options): Update - { - if (method_exists(Update::class, 'isPrivate')) { - return new Update($iri, $data, $options['private'] ?? false, $options['id'] ?? null, $options['type'] ?? null, $options['retry'] ?? null); - } - - // Mercure Component < 0.4. - return new Update($iri, $data, $options); // @phpstan-ignore-line - } -} diff --git a/src/Core/Bridge/Doctrine/EventListener/PurgeHttpCacheListener.php b/src/Core/Bridge/Doctrine/EventListener/PurgeHttpCacheListener.php deleted file mode 100644 index 32c6875e788..00000000000 --- a/src/Core/Bridge/Doctrine/EventListener/PurgeHttpCacheListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\EventListener; - -class_exists(\ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener::class); - -if (false) { - final class PurgeHttpCacheListener extends \ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener - { - } -} diff --git a/src/Core/Bridge/Doctrine/EventListener/WriteListener.php b/src/Core/Bridge/Doctrine/EventListener/WriteListener.php deleted file mode 100644 index 68ac5b04e9f..00000000000 --- a/src/Core/Bridge/Doctrine/EventListener/WriteListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\EventListener; - -class_exists(\ApiPlatform\Doctrine\EventListener\WriteListener::class); - -if (false) { - final class WriteListener extends \ApiPlatform\Doctrine\EventListener\WriteListener - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php b/src/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php deleted file mode 100644 index a2693cdc9d9..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProvider.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; - -/** - * Collection data provider for the Doctrine MongoDB ODM. - * - * @experimental - * - * @author Alan Poulain - */ -final class CollectionDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface -{ - private $managerRegistry; - private $resourceMetadataFactory; - private $collectionExtensions; - - /** - * @param AggregationCollectionExtensionInterface[] $collectionExtensions - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - */ - public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataFactory, iterable $collectionExtensions = []) - { - $this->managerRegistry = $managerRegistry; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->collectionExtensions = $collectionExtensions; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return $this->managerRegistry->getManagerForClass($resourceClass) instanceof DocumentManager; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - /** @var DocumentManager $manager */ - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - - /** @var ObjectRepository $repository */ - $repository = $manager->getRepository($resourceClass); - if (!$repository instanceof DocumentRepository) { - throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class)); - } - - $aggregationBuilder = $repository->createAggregationBuilder(); - foreach ($this->collectionExtensions as $extension) { - $extension->applyToCollection($aggregationBuilder, $resourceClass, $operationName, $context); - - if ($extension instanceof AggregationResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context); - } - } - - $attribute = []; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName); - $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; - } catch (OperationNotFoundException $e) { - $attribute = $resourceMetadata->getOperation()->getExtraProperties()['doctrine_mongodb'] ?? []; - } - } else { - /** @var ResourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $attribute = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'doctrine_mongodb', [], true); - } - - $executeOptions = $attribute['execute_options'] ?? []; - $builder = $aggregationBuilder->hydrate($resourceClass); - - if (method_exists($builder, 'getAggregation')) { - return $builder->getAggregation($executeOptions)->getIterator(); - } - - return $builder->execute($executeOptions); - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php deleted file mode 100644 index 64831aa4452..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Extension; - -class_exists(\ApiPlatform\Doctrine\Odm\Extension\FilterExtension::class); - -if (false) { - final class FilterExtension extends \ApiPlatform\Doctrine\Odm\Extension\FilterExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtension.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtension.php deleted file mode 100644 index 959ecee541f..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\OrderExtension::class); - -if (false) { - final class OrderExtension extends \ApiPlatform\Doctrine\Orm\Extension\OrderExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php deleted file mode 100644 index 0d784d22a4c..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\PaginationExtension::class); - -if (false) { - final class PaginationExtension extends \ApiPlatform\Doctrine\Orm\Extension\PaginationExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/AbstractFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/AbstractFilter.php deleted file mode 100644 index 50a21cda197..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/AbstractFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\AbstractFilter::class); - -if (false) { - class AbstractFilter extends \ApiPlatform\Doctrine\Odm\Filter\AbstractFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/BooleanFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/BooleanFilter.php deleted file mode 100644 index 3c9e06559f4..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/BooleanFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\BooleanFilter::class); - -if (false) { - final class BooleanFilter extends \ApiPlatform\Doctrine\Odm\Filter\BooleanFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/DateFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/DateFilter.php deleted file mode 100644 index 8a4da83c350..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/DateFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\DateFilter::class); - -if (false) { - class DateFilter extends \ApiPlatform\Doctrine\Odm\Filter\DateFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/ExistsFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/ExistsFilter.php deleted file mode 100644 index c03ca561946..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/ExistsFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\ExistsFilter::class); - -if (false) { - final class ExistsFilter extends \ApiPlatform\Doctrine\Odm\Filter\ExistsFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/NumericFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/NumericFilter.php deleted file mode 100644 index 8b190ea6e5f..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/NumericFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\NumericFilter::class); - -if (false) { - final class NumericFilter extends \ApiPlatform\Doctrine\Odm\Filter\NumericFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/OrderFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/OrderFilter.php deleted file mode 100644 index 9c050013229..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/OrderFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\OrderFilter::class); - -if (false) { - final class OrderFilter extends \ApiPlatform\Doctrine\Odm\Filter\OrderFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/RangeFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/RangeFilter.php deleted file mode 100644 index 2846094e7df..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/RangeFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Filter; - -class_exists(\ApiPlatform\Doctrine\Odm\Filter\RangeFilter::class); - -if (false) { - final class RangeFilter extends \ApiPlatform\Doctrine\Odm\Filter\RangeFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php deleted file mode 100644 index 5e1e323ea4e..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php +++ /dev/null @@ -1,223 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Filter; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface; -use ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait; -use ApiPlatform\Doctrine\Odm\Filter\AbstractFilter; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MongoDBClassMetadata; -use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\Mapping\ClassMetadata; -use MongoDB\BSON\Regex; -use Psr\Log\LoggerInterface; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Filter the collection by given properties. - * - * @experimental - * - * @author Kévin Dunglas - * @author Alan Poulain - */ -final class SearchFilter extends AbstractFilter implements SearchFilterInterface -{ - use SearchFilterTrait; - - public const DOCTRINE_INTEGER_TYPE = [MongoDbType::INTEGER, MongoDbType::INT]; - - public function __construct(ManagerRegistry $managerRegistry, IriConverterInterface $iriConverter, IdentifiersExtractorInterface $identifiersExtractor, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null) - { - parent::__construct($managerRegistry, $logger, $properties, $nameConverter); - - $this->iriConverter = $iriConverter; - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - $this->identifiersExtractor = $identifiersExtractor; - } - - protected function getIriConverter(): IriConverterInterface - { - return $this->iriConverter; - } - - protected function getPropertyAccessor(): PropertyAccessorInterface - { - return $this->propertyAccessor; - } - - /** - * {@inheritdoc} - */ - protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) - { - if ( - null === $value || - !$this->isPropertyEnabled($property, $resourceClass) || - !$this->isPropertyMapped($property, $resourceClass, true) - ) { - return; - } - - $matchField = $field = $property; - - $values = $this->normalizeValues((array) $value, $property); - if (null === $values) { - return; - } - - $associations = []; - if ($this->isPropertyNested($property, $resourceClass)) { - [$matchField, $field, $associations] = $this->addLookupsForNestedProperty($property, $aggregationBuilder, $resourceClass); - } - - $caseSensitive = true; - $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; - - // prefixing the strategy with i makes it case insensitive - if (0 === strpos($strategy, 'i')) { - $strategy = substr($strategy, 1); - $caseSensitive = false; - } - - /** @var MongoDBClassMetadata */ - $metadata = $this->getNestedMetadata($resourceClass, $associations); - - if ($metadata->hasField($field) && !$metadata->hasAssociation($field)) { - if ('id' === $field) { - $values = array_map([$this, 'getIdFromValue'], $values); - } - - if (!$this->hasValidValues($values, $this->getDoctrineFieldType($property, $resourceClass))) { - $this->logger->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $field)), - ]); - - return; - } - - $this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata); - - return; - } - - // metadata doesn't have the field, nor an association on the field - if (!$metadata->hasAssociation($field)) { - return; - } - - $values = array_map([$this, 'getIdFromValue'], $values); - $doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass); - - if (null !== $this->identifiersExtractor) { - $associationResourceClass = $metadata->getAssociationTargetClass($field); - $associationFieldIdentifier = $this->identifiersExtractor->getIdentifiersFromResourceClass($associationResourceClass)[0]; - $doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass); - } - - if (!$this->hasValidValues($values, $doctrineTypeField)) { - $this->logger->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $property)), - ]); - - return; - } - - $this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata); - } - - /** - * Add equality match stage according to the strategy. - * - * @param mixed $values - */ - private function addEqualityMatchStrategy(string $strategy, Builder $aggregationBuilder, string $field, string $matchField, $values, bool $caseSensitive, ClassMetadata $metadata): void - { - $inValues = []; - foreach ($values as $inValue) { - $inValues[] = $this->getEqualityMatchStrategyValue($strategy, $field, $inValue, $caseSensitive, $metadata); - } - - $aggregationBuilder - ->match() - ->field($matchField) - ->in($inValues); - } - - /** - * Get equality match value according to the strategy. - * - * @param mixed $value - * - * @throws InvalidArgumentException If strategy does not exist - * - * @return Regex|string - */ - private function getEqualityMatchStrategyValue(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata) - { - $type = $metadata->getTypeOfField($field); - - if (!MongoDbType::hasType($type)) { - return $value; - } - if (MongoDbType::STRING !== $type) { - return MongoDbType::getType($type)->convertToDatabaseValue($value); - } - - $quotedValue = preg_quote($value); - - switch ($strategy) { - case null: - case self::STRATEGY_EXACT: - return $caseSensitive ? $value : new Regex("^$quotedValue$", 'i'); - case self::STRATEGY_PARTIAL: - return new Regex($quotedValue, $caseSensitive ? '' : 'i'); - case self::STRATEGY_START: - return new Regex("^$quotedValue", $caseSensitive ? '' : 'i'); - case self::STRATEGY_END: - return new Regex("$quotedValue$", $caseSensitive ? '' : 'i'); - case self::STRATEGY_WORD_START: - return new Regex("(^$quotedValue.*|.*\s$quotedValue.*)", $caseSensitive ? '' : 'i'); - default: - throw new InvalidArgumentException(sprintf('strategy %s does not exist.', $strategy)); - } - } - - /** - * {@inheritdoc} - */ - protected function getType(string $doctrineType): string - { - switch ($doctrineType) { - case MongoDbType::INT: - case MongoDbType::INTEGER: - return 'int'; - case MongoDbType::BOOL: - case MongoDbType::BOOLEAN: - return 'bool'; - case MongoDbType::DATE: - return \DateTimeInterface::class; - case MongoDbType::FLOAT: - return 'float'; - } - - return 'string'; - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php b/src/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php deleted file mode 100644 index 75e7050339d..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProvider.php +++ /dev/null @@ -1,131 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; - -/** - * Item data provider for the Doctrine MongoDB ODM. - * - * @experimental - * - * @author Alan Poulain - */ -final class ItemDataProvider implements DenormalizedIdentifiersAwareItemDataProviderInterface, RestrictedDataProviderInterface -{ - use IdentifierManagerTrait; - - private $managerRegistry; - private $resourceMetadataFactory; - private $itemExtensions; - - /** - * @param AggregationItemExtensionInterface[] $itemExtensions - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - */ - public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $itemExtensions = []) - { - $this->managerRegistry = $managerRegistry; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->itemExtensions = $itemExtensions; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return $this->managerRegistry->getManagerForClass($resourceClass) instanceof DocumentManager; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - /** @var DocumentManager $manager */ - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - - if (!\is_array($id) && !($context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] ?? false)) { - $id = $this->normalizeIdentifiers($id, $manager, $resourceClass); - } - - $id = (array) $id; - - if (!($context['fetch_data'] ?? true)) { - return $manager->getReference($resourceClass, reset($id)); - } - - $repository = $manager->getRepository($resourceClass); - /** @var ObjectRepository $repository */ - if (!$repository instanceof DocumentRepository) { - throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class)); - } - - $aggregationBuilder = $repository->createAggregationBuilder(); - - foreach ($id as $propertyName => $value) { - $aggregationBuilder->match()->field($propertyName)->equals($value); - } - - foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($aggregationBuilder, $resourceClass, $id, $operationName, $context); - - if ($extension instanceof AggregationResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context); - } - } - - $attribute = []; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName); - $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; - } catch (OperationNotFoundException $e) { - $attribute = $resourceMetadata->getOperation()->getExtraProperties()['doctrine_mongodb'] ?? []; - } - } else { - /** @var ResourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $attribute = $resourceMetadata->getItemOperationAttribute($operationName, 'doctrine_mongodb', [], true); - } - - $executeOptions = $attribute['execute_options'] ?? []; - - return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions)->current() ?: null; - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php deleted file mode 100644 index 24b0c1cc081..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php +++ /dev/null @@ -1,79 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\Metadata\Property; - -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\Persistence\ManagerRegistry; - -/** - * Use Doctrine metadata to populate the identifier property. - * - * @experimental - * - * @author Kévin Dunglas - * @author Alan Poulain - */ -final class DoctrineMongoDbOdmPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $decorated; - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry, PropertyMetadataFactoryInterface $decorated) - { - $this->managerRegistry = $managerRegistry; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - if (null !== $propertyMetadata->isIdentifier()) { - return $propertyMetadata; - } - - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - if (!$manager instanceof DocumentManager) { - return $propertyMetadata; - } - - $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); - $identifiers = $doctrineClassMetadata->getIdentifier(); - - foreach ($identifiers as $identifier) { - if ($identifier === $property) { - $propertyMetadata = $propertyMetadata->withIdentifier(true); - - if (null !== $propertyMetadata->isWritable()) { - break; - } - - $propertyMetadata = $propertyMetadata->withWritable(false); - - break; - } - } - - if (null === $propertyMetadata->isIdentifier()) { - $propertyMetadata = $propertyMetadata->withIdentifier(false); - } - - return $propertyMetadata; - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/Paginator.php b/src/Core/Bridge/Doctrine/MongoDbOdm/Paginator.php deleted file mode 100644 index b963af12c6f..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/Paginator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm; - -class_exists(\ApiPlatform\Doctrine\Odm\Paginator::class); - -if (false) { - final class Paginator extends \ApiPlatform\Doctrine\Odm\Paginator - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyHelperTrait.php b/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyHelperTrait.php deleted file mode 100644 index b8d78a8e27d..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyHelperTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm; - -class_exists(\ApiPlatform\Doctrine\Odm\PropertyHelperTrait::class); - -if (false) { - trait PropertyHelperTrait - { - use \ApiPlatform\Doctrine\Odm\PropertyHelperTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractor.php b/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractor.php deleted file mode 100644 index f216aa2b1a8..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractor.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm\PropertyInfo; - -class_exists(\ApiPlatform\Doctrine\Odm\PropertyInfo\DoctrineExtractor::class); - -if (false) { - final class DoctrineExtractor extends \ApiPlatform\Doctrine\Odm\PropertyInfo\DoctrineExtractor - { - } -} diff --git a/src/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php b/src/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php deleted file mode 100644 index 1934400b210..00000000000 --- a/src/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProvider.php +++ /dev/null @@ -1,213 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; - -/** - * Subresource data provider for the Doctrine MongoDB ODM. - * - * @experimental - * - * @author Antoine Bluchet - * @author Alan Poulain - */ -final class SubresourceDataProvider implements SubresourceDataProviderInterface -{ - use IdentifierManagerTrait; - - private $managerRegistry; - private $resourceMetadataFactory; - private $collectionExtensions; - private $itemExtensions; - - /** - * @param AggregationCollectionExtensionInterface[] $collectionExtensions - * @param AggregationItemExtensionInterface[] $itemExtensions - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - */ - public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $collectionExtensions = [], iterable $itemExtensions = []) - { - $this->managerRegistry = $managerRegistry; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->collectionExtensions = $collectionExtensions; - $this->itemExtensions = $itemExtensions; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - if (!$manager instanceof DocumentManager) { - throw new ResourceClassNotSupportedException(sprintf('The manager for "%s" must be an instance of "%s".', $resourceClass, DocumentManager::class)); - } - - $repository = $manager->getRepository($resourceClass); - /** @var ObjectRepository $repository */ - if (!$repository instanceof DocumentRepository) { - throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class)); - } - - if (isset($context['identifiers'], $context['operation']) && !isset($context['property'])) { - $context['property'] = $context['operation']->getExtraProperties()['legacy_subresource_property'] ?? null; - $context['collection'] = $context['operation']->isCollection(); - } - - if (!isset($context['identifiers'], $context['property'])) { - throw new ResourceClassNotSupportedException('The given resource class is not a subresource.'); - } - - $attribute = []; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName); - $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; - } catch (OperationNotFoundException $e) { - $attribute = $resourceMetadata->getOperation()->getExtraProperties()['doctrine_mongodb'] ?? []; - } - } else { - /** @var ResourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $attribute = $resourceMetadata->getSubresourceOperationAttribute($operationName, 'doctrine_mongodb', [], true); - } - - $executeOptions = $attribute['execute_options'] ?? []; - - $aggregationBuilder = $this->buildAggregation($identifiers, $context, $executeOptions, $repository->createAggregationBuilder(), \count($context['identifiers'])); - - if (true === $context['collection']) { - foreach ($this->collectionExtensions as $extension) { - $extension->applyToCollection($aggregationBuilder, $resourceClass, $operationName, $context); - if ($extension instanceof AggregationResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context); - } - } - } else { - foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($aggregationBuilder, $resourceClass, $identifiers, $operationName, $context); - if ($extension instanceof AggregationResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operationName, $context); - } - } - } - - $iterator = $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions); - - return $context['collection'] ? $iterator->toArray() : ($iterator->current() ?: null); - } - - /** - * @throws RuntimeException - */ - private function buildAggregation(array $identifiers, array $context, array $executeOptions, Builder $previousAggregationBuilder, int $remainingIdentifiers, Builder $topAggregationBuilder = null): Builder - { - if ($remainingIdentifiers <= 0) { - return $previousAggregationBuilder; - } - - $topAggregationBuilder = $topAggregationBuilder ?? $previousAggregationBuilder; - - if (\is_string(key($context['identifiers']))) { - $contextIdentifiers = array_keys($context['identifiers']); - $identifier = $contextIdentifiers[$remainingIdentifiers - 1]; - $identifierResourceClass = $context['identifiers'][$identifier][0]; - $previousAssociationProperty = $contextIdentifiers[$remainingIdentifiers] ?? $context['property']; - } else { - @trigger_error('Identifiers should match the convention introduced in ADR 0001-resource-identifiers, this behavior will be removed in 3.0.', \E_USER_DEPRECATED); - [$identifier, $identifierResourceClass] = $context['identifiers'][$remainingIdentifiers - 1]; - $previousAssociationProperty = $context['identifiers'][$remainingIdentifiers][0] ?? $context['property']; - } - - $manager = $this->managerRegistry->getManagerForClass($identifierResourceClass); - if (!$manager instanceof DocumentManager) { - throw new RuntimeException(sprintf('The manager for "%s" must be an instance of "%s".', $identifierResourceClass, DocumentManager::class)); - } - - $classMetadata = $manager->getClassMetadata($identifierResourceClass); - - if (!$classMetadata instanceof ClassMetadata) { - throw new RuntimeException(sprintf('The class metadata for "%s" must be an instance of "%s".', $identifierResourceClass, ClassMetadata::class)); - } - - $aggregation = $manager->createAggregationBuilder($identifierResourceClass); - $normalizedIdentifiers = []; - - if (isset($identifiers[$identifier])) { - // if it's an array it's already normalized, the IdentifierManagerTrait is deprecated - if ($context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] ?? false) { - $normalizedIdentifiers = $identifiers[$identifier]; - } else { - $normalizedIdentifiers = $this->normalizeIdentifiers($identifiers[$identifier], $manager, $identifierResourceClass); - } - } - - if ($classMetadata->hasAssociation($previousAssociationProperty)) { - $aggregation->lookup($previousAssociationProperty)->alias($previousAssociationProperty); - foreach ($normalizedIdentifiers as $key => $value) { - $aggregation->match()->field($key)->equals($value); - } - } elseif ($classMetadata->isIdentifier($previousAssociationProperty)) { - foreach ($normalizedIdentifiers as $key => $value) { - $aggregation->match()->field($key)->equals($value); - } - - return $aggregation; - } - - // Recurse aggregations - $aggregation = $this->buildAggregation($identifiers, $context, $executeOptions, $aggregation, --$remainingIdentifiers, $topAggregationBuilder); - - $results = $aggregation->execute($executeOptions)->toArray(); - $in = array_reduce($results, static function ($in, $result) use ($previousAssociationProperty) { - return $in + array_map(static function ($result) { - return $result['_id']; - }, $result[$previousAssociationProperty] ?? []); - }, []); - $previousAggregationBuilder->match()->field('_id')->in($in); - - return $previousAggregationBuilder; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/AbstractPaginator.php b/src/Core/Bridge/Doctrine/Orm/AbstractPaginator.php deleted file mode 100644 index 28ceb260039..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/AbstractPaginator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm; - -class_exists(\ApiPlatform\Doctrine\Orm\AbstractPaginator::class); - -if (false) { - class AbstractPaginator extends \ApiPlatform\Doctrine\Orm\AbstractPaginator - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/CollectionDataProvider.php b/src/Core/Bridge/Doctrine/Orm/CollectionDataProvider.php deleted file mode 100644 index 380d104f50e..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/CollectionDataProvider.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * 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\Doctrine\Orm; - -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; -use ApiPlatform\Exception\RuntimeException; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\ManagerRegistry; - -/** - * Collection data provider for the Doctrine ORM. - * - * @author Kévin Dunglas - * @author Samuel ROZE - * @final - */ -class CollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - private $managerRegistry; - private $collectionExtensions; - - /** - * @param QueryCollectionExtensionInterface[] $collectionExtensions - */ - public function __construct(ManagerRegistry $managerRegistry, iterable $collectionExtensions = []) - { - $this->managerRegistry = $managerRegistry; - $this->collectionExtensions = $collectionExtensions; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return $this->managerRegistry->getManagerForClass($resourceClass) instanceof EntityManagerInterface; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - /** @var EntityManagerInterface $manager */ - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - - $repository = $manager->getRepository($resourceClass); - if (!method_exists($repository, 'createQueryBuilder')) { - throw new RuntimeException('The repository class must have a "createQueryBuilder" method.'); - } - - $queryBuilder = $repository->createQueryBuilder('o'); - $queryNameGenerator = new QueryNameGenerator(); - foreach ($this->collectionExtensions as $extension) { - $extension->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); - - if ($extension instanceof QueryResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); - } - } - - return $queryBuilder->getQuery()->getResult(); - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php deleted file mode 100644 index fc71aa77885..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension::class); - -if (false) { - final class EagerLoadingExtension extends \ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php deleted file mode 100644 index 779e8186012..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension::class); - -if (false) { - final class FilterEagerLoadingExtension extends \ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php deleted file mode 100644 index 1f2effff3cb..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\FilterExtension::class); - -if (false) { - final class FilterExtension extends \ApiPlatform\Doctrine\Orm\Extension\FilterExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php deleted file mode 100644 index d1452c1421c..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\OrderExtension::class); - -if (false) { - final class OrderExtension extends \ApiPlatform\Doctrine\Orm\Extension\OrderExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php b/src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php deleted file mode 100644 index 5e5f4e1d6fe..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Extension; - -class_exists(\ApiPlatform\Doctrine\Orm\Extension\PaginationExtension::class); - -if (false) { - final class PaginationExtension extends \ApiPlatform\Doctrine\Orm\Extension\PaginationExtension - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/AbstractContextAwareFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/AbstractContextAwareFilter.php deleted file mode 100644 index de3227b34d4..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/AbstractContextAwareFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter::class); - -if (false) { - class AbstractContextAwareFilter extends \ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php deleted file mode 100644 index e67cd6f7456..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\AbstractFilter::class); - -if (false) { - class AbstractFilter extends \ApiPlatform\Doctrine\Orm\Filter\AbstractFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php deleted file mode 100644 index 043582d79b0..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\BooleanFilter::class); - -if (false) { - class BooleanFilter extends \ApiPlatform\Doctrine\Orm\Filter\BooleanFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php deleted file mode 100644 index 5c2ebf78f2d..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\DateFilter::class); - -if (false) { - class DateFilter extends \ApiPlatform\Doctrine\Orm\Filter\DateFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/ExistsFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/ExistsFilter.php deleted file mode 100644 index c9adf3d9a11..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/ExistsFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\ExistsFilter::class); - -if (false) { - class ExistsFilter extends \ApiPlatform\Doctrine\Orm\Filter\ExistsFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/NumericFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/NumericFilter.php deleted file mode 100644 index 2a66623c1c5..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/NumericFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\NumericFilter::class); - -if (false) { - class NumericFilter extends \ApiPlatform\Doctrine\Orm\Filter\NumericFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/OrderFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/OrderFilter.php deleted file mode 100644 index 5b3cf9af579..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/OrderFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\OrderFilter::class); - -if (false) { - class OrderFilter extends \ApiPlatform\Doctrine\Orm\Filter\OrderFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/RangeFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/RangeFilter.php deleted file mode 100644 index a696863c5d4..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/RangeFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -class_exists(\ApiPlatform\Doctrine\Orm\Filter\RangeFilter::class); - -if (false) { - class RangeFilter extends \ApiPlatform\Doctrine\Orm\Filter\RangeFilter - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Filter/SearchFilter.php b/src/Core/Bridge/Doctrine/Orm/Filter/SearchFilter.php deleted file mode 100644 index 21081029653..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Filter/SearchFilter.php +++ /dev/null @@ -1,275 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterInterface; -use ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterTrait; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryBuilderHelper; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter; -use Doctrine\DBAL\Types\Types; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Filter the collection by given properties. - * - * @author Kévin Dunglas - */ -class SearchFilter extends AbstractContextAwareFilter implements SearchFilterInterface -{ - use SearchFilterTrait; - - public const DOCTRINE_INTEGER_TYPE = Types::INTEGER; - - public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $requestStack, IriConverterInterface $iriConverter, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, IdentifiersExtractorInterface $identifiersExtractor = null, NameConverterInterface $nameConverter = null) - { - parent::__construct($managerRegistry, $requestStack, $logger, $properties, $nameConverter); - - if (null === $identifiersExtractor) { - @trigger_error('Not injecting ItemIdentifiersExtractor is deprecated since API Platform 2.5 and can lead to unexpected behaviors, it will not be possible anymore in API Platform 3.0.', \E_USER_DEPRECATED); - } - - $this->iriConverter = $iriConverter; - $this->identifiersExtractor = $identifiersExtractor; - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - } - - protected function getIriConverter(): IriConverterInterface - { - return $this->iriConverter; - } - - protected function getPropertyAccessor(): PropertyAccessorInterface - { - return $this->propertyAccessor; - } - - /** - * {@inheritdoc} - */ - protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) - { - if ( - null === $value || - !$this->isPropertyEnabled($property, $resourceClass) || - !$this->isPropertyMapped($property, $resourceClass, true) - ) { - return; - } - - $alias = $queryBuilder->getRootAliases()[0]; - $field = $property; - - $values = $this->normalizeValues((array) $value, $property); - if (null === $values) { - return; - } - - $associations = []; - if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); - } - - $caseSensitive = true; - $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; - - // prefixing the strategy with i makes it case insensitive - if (0 === strpos($strategy, 'i')) { - $strategy = substr($strategy, 1); - $caseSensitive = false; - } - - $metadata = $this->getNestedMetadata($resourceClass, $associations); - - if ($metadata->hasField($field)) { - if ('id' === $field) { - $values = array_map([$this, 'getIdFromValue'], $values); - } - - if (!$this->hasValidValues($values, $this->getDoctrineFieldType($property, $resourceClass))) { - $this->logger->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $field)), - ]); - - return; - } - - $this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $alias, $field, $values, $caseSensitive); - - return; - } - - // metadata doesn't have the field, nor an association on the field - if (!$metadata->hasAssociation($field)) { - return; - } - - $values = array_map([$this, 'getIdFromValue'], $values); - $associationFieldIdentifier = 'id'; - $doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass); - - if (null !== $this->identifiersExtractor) { - $associationResourceClass = $metadata->getAssociationTargetClass($field); - $associationFieldIdentifier = $this->identifiersExtractor->getIdentifiersFromResourceClass($associationResourceClass)[0]; - $doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass); - } - - if (!$this->hasValidValues($values, $doctrineTypeField)) { - $this->logger->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Values for field "%s" are not valid according to the doctrine type.', $field)), - ]); - - return; - } - - $associationAlias = $alias; - $associationField = $field; - if ($metadata->isCollectionValuedAssociation($associationField) || $metadata->isAssociationInverseSide($field)) { - $associationAlias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $alias, $associationField); - $associationField = $associationFieldIdentifier; - } - - $this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $associationAlias, $associationField, $values, $caseSensitive); - } - - /** - * Adds where clause according to the strategy. - * - * @param mixed $values - * - * @throws InvalidArgumentException If strategy does not exist - */ - protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, $values, bool $caseSensitive) - { - if (!\is_array($values)) { - $values = [$values]; - } - - $wrapCase = $this->createWrapCase($caseSensitive); - $valueParameter = ':'.$queryNameGenerator->generateParameterName($field); - $aliasedField = sprintf('%s.%s', $alias, $field); - - if (!$strategy || self::STRATEGY_EXACT === $strategy) { - if (1 === \count($values)) { - $queryBuilder - ->andWhere($queryBuilder->expr()->eq($wrapCase($aliasedField), $wrapCase($valueParameter))) - ->setParameter($valueParameter, $values[0]); - - return; - } - - $queryBuilder - ->andWhere($queryBuilder->expr()->in($wrapCase($aliasedField), $valueParameter)) - ->setParameter($valueParameter, $caseSensitive ? $values : array_map('strtolower', $values)); - - return; - } - - $ors = []; - $parameters = []; - foreach ($values as $key => $value) { - $keyValueParameter = sprintf('%s_%s', $valueParameter, $key); - $parameters[$caseSensitive ? $value : strtolower($value)] = $keyValueParameter; - - switch ($strategy) { - case self::STRATEGY_PARTIAL: - $ors[] = $queryBuilder->expr()->like( - $wrapCase($aliasedField), - $wrapCase((string) $queryBuilder->expr()->concat("'%'", $keyValueParameter, "'%'")) - ); - break; - case self::STRATEGY_START: - $ors[] = $queryBuilder->expr()->like( - $wrapCase($aliasedField), - $wrapCase((string) $queryBuilder->expr()->concat($keyValueParameter, "'%'")) - ); - break; - case self::STRATEGY_END: - $ors[] = $queryBuilder->expr()->like( - $wrapCase($aliasedField), - $wrapCase((string) $queryBuilder->expr()->concat("'%'", $keyValueParameter)) - ); - break; - case self::STRATEGY_WORD_START: - $ors[] = $queryBuilder->expr()->orX( - $queryBuilder->expr()->like($wrapCase($aliasedField), $wrapCase((string) $queryBuilder->expr()->concat($keyValueParameter, "'%'"))), - $queryBuilder->expr()->like($wrapCase($aliasedField), $wrapCase((string) $queryBuilder->expr()->concat("'% '", $keyValueParameter, "'%'"))) - ); - break; - default: - throw new InvalidArgumentException(sprintf('strategy %s does not exist.', $strategy)); - } - } - - $queryBuilder->andWhere($queryBuilder->expr()->orX(...$ors)); - array_walk($parameters, [$queryBuilder, 'setParameter']); - } - - /** - * Creates a function that will wrap a Doctrine expression according to the - * specified case sensitivity. - * - * For example, "o.name" will get wrapped into "LOWER(o.name)" when $caseSensitive - * is false. - */ - protected function createWrapCase(bool $caseSensitive): \Closure - { - return static function (string $expr) use ($caseSensitive): string { - if ($caseSensitive) { - return $expr; - } - - return sprintf('LOWER(%s)', $expr); - }; - } - - /** - * {@inheritdoc} - */ - protected function getType(string $doctrineType): string - { - switch ($doctrineType) { - case Types::ARRAY: - return 'array'; - case Types::BIGINT: - case Types::INTEGER: - case Types::SMALLINT: - return 'int'; - case Types::BOOLEAN: - return 'bool'; - case Types::DATE_MUTABLE: - case Types::TIME_MUTABLE: - case Types::DATETIME_MUTABLE: - case Types::DATETIMETZ_MUTABLE: - case Types::DATE_IMMUTABLE: - case Types::TIME_IMMUTABLE: - case Types::DATETIME_IMMUTABLE: - case Types::DATETIMETZ_IMMUTABLE: - return \DateTimeInterface::class; - case Types::FLOAT: - return 'float'; - } - - return 'string'; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/ItemDataProvider.php b/src/Core/Bridge/Doctrine/Orm/ItemDataProvider.php deleted file mode 100644 index dd91a1984fd..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/ItemDataProvider.php +++ /dev/null @@ -1,136 +0,0 @@ - - * - * 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\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\Mapping\ClassMetadata; - -/** - * Item data provider for the Doctrine ORM. - * - * @author Kévin Dunglas - * @author Samuel ROZE - * @final - */ -class ItemDataProvider implements DenormalizedIdentifiersAwareItemDataProviderInterface, RestrictedDataProviderInterface -{ - use IdentifierManagerTrait; - - private $managerRegistry; - private $itemExtensions; - - /** - * @param QueryItemExtensionInterface[] $itemExtensions - * @param ResourceMetadataCollectionFactoryInterface|null $resourceMetadataFactory - */ - public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $itemExtensions = [], $resourceMetadataFactory = null) - { - $this->managerRegistry = $managerRegistry; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->itemExtensions = $itemExtensions; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return $this->managerRegistry->getManagerForClass($resourceClass) instanceof EntityManagerInterface; - } - - /** - * {@inheritdoc} - * - * The context may contain a `fetch_data` key representing whether the value should be fetched by Doctrine or if we should return a reference. - * - * @throws RuntimeException - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - /** @var EntityManagerInterface $manager */ - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - - if ((\is_int($id) || \is_string($id)) && !($context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] ?? false)) { - $id = $this->normalizeIdentifiers($id, $manager, $resourceClass); - } - if (!\is_array($id)) { - throw new \InvalidArgumentException(sprintf('$id must be array when "%s" key is set to true in the $context', IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER)); - } - $identifiers = $id; - - $fetchData = $context['fetch_data'] ?? true; - if (!$fetchData) { - return $manager->getReference($resourceClass, $identifiers); - } - - $repository = $manager->getRepository($resourceClass); - if (!method_exists($repository, 'createQueryBuilder')) { - throw new RuntimeException('The repository class must have a "createQueryBuilder" method.'); - } - - $queryBuilder = $repository->createQueryBuilder('o'); - $queryNameGenerator = new QueryNameGenerator(); - $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); - - $this->addWhereForIdentifiers($identifiers, $queryBuilder, $doctrineClassMetadata, $queryNameGenerator); - - foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($queryBuilder, $queryNameGenerator, $resourceClass, $identifiers, $operationName, $context); - - if ($extension instanceof QueryResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); - } - } - - return $queryBuilder->getQuery()->getOneOrNullResult(); - } - - /** - * Add WHERE conditions to the query for one or more identifiers (simple or composite). - * - * @param mixed $queryNameGenerator - */ - private function addWhereForIdentifiers(array $identifiers, QueryBuilder $queryBuilder, ClassMetadata $classMetadata, $queryNameGenerator) - { - $alias = $queryBuilder->getRootAliases()[0]; - foreach ($identifiers as $identifier => $value) { - $placeholder = $queryNameGenerator->generateParameterName($identifier); - $expression = $queryBuilder->expr()->eq( - "{$alias}.{$identifier}", - ':'.$placeholder - ); - - $queryBuilder->andWhere($expression); - $queryBuilder->setParameter($placeholder, $value, $classMetadata->getTypeOfField($identifier)); - } - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php b/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php deleted file mode 100644 index 986c86ecf8e..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * 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\Doctrine\Orm\Metadata\Property; - -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\Persistence\ManagerRegistry; - -/** - * Use Doctrine metadata to populate the identifier property. - * - * @author Kévin Dunglas - */ -final class DoctrineOrmPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $decorated; - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry, PropertyMetadataFactoryInterface $decorated) - { - $this->managerRegistry = $managerRegistry; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - if (null !== $propertyMetadata->isIdentifier()) { - return $propertyMetadata; - } - - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - if (!$manager) { - return $propertyMetadata; - } - $doctrineClassMetadata = $manager->getClassMetadata($resourceClass); - - $identifiers = $doctrineClassMetadata->getIdentifier(); - foreach ($identifiers as $identifier) { - if ($identifier === $property) { - $propertyMetadata = $propertyMetadata->withIdentifier(true); - - if (null !== $propertyMetadata->isWritable()) { - break; - } - - if ($doctrineClassMetadata instanceof ClassMetadataInfo) { - $writable = $doctrineClassMetadata->isIdentifierNatural(); - } else { - $writable = false; - } - - $propertyMetadata = $propertyMetadata->withWritable($writable); - - break; - } - } - - if (null === $propertyMetadata->isIdentifier()) { - $propertyMetadata = $propertyMetadata->withIdentifier(false); - } - - if ($doctrineClassMetadata instanceof ClassMetadataInfo && \in_array($property, $doctrineClassMetadata->getFieldNames(), true)) { - /** @var mixed[] */ - $fieldMapping = $doctrineClassMetadata->getFieldMapping($property); - $propertyMetadata = $propertyMetadata->withDefault($fieldMapping['options']['default'] ?? $propertyMetadata->getDefault()); - } - - return $propertyMetadata; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Paginator.php b/src/Core/Bridge/Doctrine/Orm/Paginator.php deleted file mode 100644 index 2777ef9c1ee..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Paginator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm; - -class_exists(\ApiPlatform\Doctrine\Orm\Paginator::class); - -if (false) { - final class Paginator extends \ApiPlatform\Doctrine\Orm\Paginator - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/PropertyHelperTrait.php b/src/Core/Bridge/Doctrine/Orm/PropertyHelperTrait.php deleted file mode 100644 index e33a8b10e5c..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/PropertyHelperTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Orm; - -class_exists(\ApiPlatform\Doctrine\Orm\PropertyHelperTrait::class); - -if (false) { - trait PropertyHelperTrait - { - use \ApiPlatform\Doctrine\Orm\PropertyHelperTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/SubresourceDataProvider.php b/src/Core/Bridge/Doctrine/Orm/SubresourceDataProvider.php deleted file mode 100644 index 2d2a9d8c209..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/SubresourceDataProvider.php +++ /dev/null @@ -1,240 +0,0 @@ - - * - * 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\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension; -use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Exception\RuntimeException; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; - -/** - * Subresource data provider for the Doctrine ORM. - * - * @author Antoine Bluchet - */ -final class SubresourceDataProvider implements SubresourceDataProviderInterface -{ - use IdentifierManagerTrait; - - private $managerRegistry; - private $collectionExtensions; - private $itemExtensions; - - /** - * @param QueryCollectionExtensionInterface[] $collectionExtensions - * @param QueryItemExtensionInterface[] $itemExtensions - */ - public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $collectionExtensions = [], iterable $itemExtensions = []) - { - $this->managerRegistry = $managerRegistry; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->collectionExtensions = $collectionExtensions; - $this->itemExtensions = $itemExtensions; - } - - /** - * {@inheritdoc} - * - * @throws RuntimeException - */ - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - $manager = $this->managerRegistry->getManagerForClass($resourceClass); - if (null === $manager) { - throw new ResourceClassNotSupportedException(sprintf('The object manager associated with the "%s" resource class cannot be retrieved.', $resourceClass)); - } - - $repository = $manager->getRepository($resourceClass); - if (!method_exists($repository, 'createQueryBuilder')) { - throw new RuntimeException('The repository class must have a "createQueryBuilder" method.'); - } - - if (!isset($context['identifiers'], $context['property'])) { - throw new ResourceClassNotSupportedException('The given resource class is not a subresource.'); - } - - $queryNameGenerator = new QueryNameGenerator(); - - /* - * The following recursively translates to this pseudo-dql: - * - * SELECT thirdLevel WHERE thirdLevel IN ( - * SELECT thirdLevel FROM relatedDummies WHERE relatedDummies = ? AND relatedDummies IN ( - * SELECT relatedDummies FROM Dummy WHERE Dummy = ? - * ) - * ) - * - * By using subqueries, we're forcing the SQL execution plan to go through indexes on doctrine identifiers. - */ - $queryBuilder = $this->buildQuery($identifiers, $context, $queryNameGenerator, $repository->createQueryBuilder($alias = 'o'), $alias, \count($context['identifiers'])); - - if (true === $context['collection']) { - foreach ($this->collectionExtensions as $extension) { - // We don't need this anymore because we already made sub queries to ensure correct results - if ($extension instanceof FilterEagerLoadingExtension) { - continue; - } - - $extension->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); - if ($extension instanceof QueryResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); - } - } - } else { - foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($queryBuilder, $queryNameGenerator, $resourceClass, $identifiers, $operationName, $context); - if ($extension instanceof QueryResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); - } - } - } - - $query = $queryBuilder->getQuery(); - - return $context['collection'] ? $query->getResult() : $query->getOneOrNullResult(); - } - - /** - * @throws RuntimeException - */ - private function buildQuery(array $identifiers, array $context, QueryNameGenerator $queryNameGenerator, QueryBuilder $previousQueryBuilder, string $previousAlias, int $remainingIdentifiers, QueryBuilder $topQueryBuilder = null): QueryBuilder - { - if ($remainingIdentifiers <= 0) { - return $previousQueryBuilder; - } - - $topQueryBuilder = $topQueryBuilder ?? $previousQueryBuilder; - - if (\is_string(key($context['identifiers']))) { - $contextIdentifiers = array_keys($context['identifiers']); - $identifier = $contextIdentifiers[$remainingIdentifiers - 1]; - $identifierResourceClass = $context['identifiers'][$identifier][0]; - $previousAssociationProperty = $contextIdentifiers[$remainingIdentifiers] ?? $context['property']; - } else { - @trigger_error('Identifiers should match the convention introduced in ADR 0001-resource-identifiers, this behavior will be removed in 3.0.', \E_USER_DEPRECATED); - [$identifier, $identifierResourceClass] = $context['identifiers'][$remainingIdentifiers - 1]; - $previousAssociationProperty = $context['identifiers'][$remainingIdentifiers][0] ?? $context['property']; - } - - $manager = $this->managerRegistry->getManagerForClass($identifierResourceClass); - - if (!$manager instanceof EntityManagerInterface) { - throw new RuntimeException("The manager for $identifierResourceClass must be an EntityManager."); - } - - $classMetadata = $manager->getClassMetadata($identifierResourceClass); - - if (!$classMetadata instanceof ClassMetadataInfo) { - throw new RuntimeException("The class metadata for $identifierResourceClass must be an instance of ClassMetadataInfo."); - } - - $qb = $manager->createQueryBuilder(); - $alias = $queryNameGenerator->generateJoinAlias($identifier); - $normalizedIdentifiers = []; - - if (isset($identifiers[$identifier])) { - // if it's an array it's already normalized, the IdentifierManagerTrait is deprecated - if ($context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] ?? false) { - $normalizedIdentifiers = $identifiers[$identifier]; - } else { - $normalizedIdentifiers = $this->normalizeIdentifiers($identifiers[$identifier], $manager, $identifierResourceClass); - } - } - - if ($classMetadata->hasAssociation($previousAssociationProperty)) { - $relationType = $classMetadata->getAssociationMapping($previousAssociationProperty)['type']; - switch ($relationType) { - // MANY_TO_MANY relations need an explicit join so that the identifier part can be retrieved - case ClassMetadataInfo::MANY_TO_MANY: - $joinAlias = $queryNameGenerator->generateJoinAlias($previousAssociationProperty); - - $qb->select($joinAlias) - ->from($identifierResourceClass, $alias) - ->innerJoin("$alias.$previousAssociationProperty", $joinAlias); - break; - case ClassMetadataInfo::ONE_TO_MANY: - $mappedBy = $classMetadata->getAssociationMapping($previousAssociationProperty)['mappedBy']; - $previousAlias = "$previousAlias.$mappedBy"; - - $qb->select($alias) - ->from($identifierResourceClass, $alias); - break; - case ClassMetadataInfo::ONE_TO_ONE: - $association = $classMetadata->getAssociationMapping($previousAssociationProperty); - if (!isset($association['mappedBy'])) { - $qb->select("IDENTITY($alias.$previousAssociationProperty)") - ->from($identifierResourceClass, $alias); - break; - } - $mappedBy = $association['mappedBy']; - $previousAlias = "$previousAlias.$mappedBy"; - - $qb->select($alias) - ->from($identifierResourceClass, $alias); - break; - default: - $qb->select("IDENTITY($alias.$previousAssociationProperty)") - ->from($identifierResourceClass, $alias); - } - } elseif ($classMetadata->isIdentifier($previousAssociationProperty)) { - $qb->select($alias) - ->from($identifierResourceClass, $alias); - } - - $isLeaf = 1 === $remainingIdentifiers; - - // Add where clause for identifiers - foreach ($normalizedIdentifiers as $key => $value) { - $placeholder = $queryNameGenerator->generateParameterName($key); - $topQueryBuilder->setParameter($placeholder, $value, (string) $classMetadata->getTypeOfField($key)); - - // Optimization: add where clause for identifiers, but not via a WHERE ... IN ( ...subquery... ). - // Instead we use a direct identifier equality clause, to speed things up when dealing with large tables. - // We may do so if there is no more recursion levels from here, and if relation allows it. - $association = $classMetadata->hasAssociation($previousAssociationProperty) ? $classMetadata->getAssociationMapping($previousAssociationProperty) : []; - $oneToOneBidirectional = isset($association['inversedBy']) && ClassMetadataInfo::ONE_TO_ONE === $association['type']; - $oneToManyBidirectional = isset($association['mappedBy']) && ClassMetadataInfo::ONE_TO_MANY === $association['type']; - if ($isLeaf && $oneToOneBidirectional) { - $joinAlias = $queryNameGenerator->generateJoinAlias($association['inversedBy']); - - return $previousQueryBuilder->innerJoin("$previousAlias.{$association['inversedBy']}", $joinAlias) - ->andWhere("$joinAlias.$key = :$placeholder"); - } - if ($isLeaf && $oneToManyBidirectional && \in_array($key, $classMetadata->getIdentifier(), true)) { - return $previousQueryBuilder->andWhere("IDENTITY($previousAlias) = :$placeholder"); - } - - $qb->andWhere("$alias.$key = :$placeholder"); - } - - // Recurse queries - $qb = $this->buildQuery($identifiers, $context, $queryNameGenerator, $qb, $alias, --$remainingIdentifiers, $topQueryBuilder); - - return $previousQueryBuilder->andWhere($qb->expr()->in($previousAlias, $qb->getDQL())); - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/EagerLoadingTrait.php b/src/Core/Bridge/Doctrine/Orm/Util/EagerLoadingTrait.php deleted file mode 100644 index 38b07cc1006..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/EagerLoadingTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait::class); - -if (false) { - trait EagerLoadingTrait - { - use \ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait; - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php deleted file mode 100644 index 5f244f5398c..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper::class); - -if (false) { - final class QueryBuilderHelper extends \ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php deleted file mode 100644 index dc257831403..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\QueryChecker::class); - -if (false) { - final class QueryChecker extends \ApiPlatform\Doctrine\Orm\Util\QueryChecker - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryJoinParser.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryJoinParser.php deleted file mode 100644 index 923aeaad669..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryJoinParser.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\QueryJoinParser::class); - -if (false) { - final class QueryJoinParser extends \ApiPlatform\Doctrine\Orm\Util\QueryJoinParser - { - } -} diff --git a/src/Core/Bridge/Doctrine/Orm/Util/QueryNameGenerator.php b/src/Core/Bridge/Doctrine/Orm/Util/QueryNameGenerator.php deleted file mode 100644 index 9939dc4f7cb..00000000000 --- a/src/Core/Bridge/Doctrine/Orm/Util/QueryNameGenerator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Doctrine\Orm\Util; - -class_exists(\ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator::class); - -if (false) { - final class QueryNameGenerator extends \ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractor.php b/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractor.php deleted file mode 100644 index 137709bd584..00000000000 --- a/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractor.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * 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\Elasticsearch\Api; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; - -/** - * {@inheritdoc} - * - * @experimental - * - * @author Baptiste Meyer - */ -final class IdentifierExtractor implements IdentifierExtractorInterface -{ - private $identifiersExtractor; - - public function __construct(IdentifiersExtractorInterface $identifiersExtractor) - { - $this->identifiersExtractor = $identifiersExtractor; - } - - /** - * {@inheritdoc} - */ - public function getIdentifierFromResourceClass(string $resourceClass): string - { - $identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass); - - if (0 >= $totalIdentifiers = \count($identifiers)) { - throw new NonUniqueIdentifierException(sprintf('Resource "%s" has no identifiers.', $resourceClass)); - } - - if (1 < $totalIdentifiers) { - throw new NonUniqueIdentifierException('Composite identifiers not supported.'); - } - - return reset($identifiers); - } -} diff --git a/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractorInterface.php b/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractorInterface.php deleted file mode 100644 index da0dd931fb9..00000000000 --- a/src/Core/Bridge/Elasticsearch/Api/IdentifierExtractorInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * 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\Elasticsearch\Api; - -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; - -/** - * Extracts identifier for a given resource. - * - * @experimental - * - * @author Baptiste Meyer - */ -interface IdentifierExtractorInterface -{ - /** - * Finds identifier from a resource class. - * - * @throws NonUniqueIdentifierException - */ - public function getIdentifierFromResourceClass(string $resourceClass): string; -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProvider.php b/src/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProvider.php deleted file mode 100644 index 669eae33a7c..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProvider.php +++ /dev/null @@ -1,152 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider; - -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\Pagination as LegacyPagination; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; -use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Util\ElasticsearchVersion; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\State\Pagination\Pagination; -use Elasticsearch\Client; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Collection data provider for Elasticsearch. - * - * @experimental - * - * @author Baptiste Meyer - */ -final class CollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - private $client; - private $documentMetadataFactory; - private $identifierExtractor; - private $denormalizer; - private $pagination; - private $resourceMetadataFactory; - - /** - * @param RequestBodySearchCollectionExtensionInterface[] $collectionExtensions - * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory - * @param Pagination|LegacyPagination $pagination - */ - public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, IdentifierExtractorInterface $identifierExtractor = null, DenormalizerInterface $denormalizer, $pagination, $resourceMetadataFactory, iterable $collectionExtensions = []) - { - $this->client = $client; - $this->documentMetadataFactory = $documentMetadataFactory; - - if ($this->identifierExtractor) { - trigger_deprecation('api-platform', '2.7', sprintf('Passing an instance of "%s" is deprecated and will not be supported in 3.0.', IdentifierExtractorInterface::class)); - } - - $this->identifierExtractor = $identifierExtractor; - $this->denormalizer = $denormalizer; - $this->pagination = $pagination; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->collectionExtensions = $collectionExtensions; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, ?string $operationName = null, array $context = []): bool - { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (false === $resourceMetadata->getCollectionOperationAttribute($operationName, 'elasticsearch', true, true)) { - return false; - } - } catch (ResourceClassNotFoundException $e) { - return false; - } - - try { - $this->documentMetadataFactory->create($resourceClass); - } catch (IndexNotFoundException $e) { - return false; - } - - if ($this->identifierExtractor) { - try { - $this->identifierExtractor->getIdentifierFromResourceClass($resourceClass); - } catch (NonUniqueIdentifierException $e) { - return false; - } - } else { - $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation($operationName); - - if (\count($operation->getIdentifiers()) > 1) { - return false; - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, ?string $operationName = null, array $context = []): iterable - { - $documentMetadata = $this->documentMetadataFactory->create($resourceClass); - $body = []; - - foreach ($this->collectionExtensions as $collectionExtension) { - $body = $collectionExtension->applyToCollection($body, $resourceClass, $operationName, $context); - } - - if (!isset($body['query']) && !isset($body['aggs'])) { - $body['query'] = ['match_all' => new \stdClass()]; - } - - $limit = $body['size'] = $body['size'] ?? $this->pagination->getLimit($resourceClass, $operationName, $context); - $offset = $body['from'] = $body['from'] ?? $this->pagination->getOffset($resourceClass, $operationName, $context); - - $params = [ - 'index' => $documentMetadata->getIndex(), - 'body' => $body, - ]; - - if (ElasticsearchVersion::supportsMappingType()) { - $params['type'] = $documentMetadata->getType(); - } - - $documents = $this->client->search($params); - - return new Paginator( - $this->denormalizer, - $documents, - $resourceClass, - $limit, - $offset, - $context - ); - } - - private $collectionExtensions; -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/AbstractFilterExtension.php b/src/Core/Bridge/Elasticsearch/DataProvider/Extension/AbstractFilterExtension.php deleted file mode 100644 index 4db73e50a48..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/AbstractFilterExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Extension; - -class_exists(\ApiPlatform\Elasticsearch\Extension\AbstractFilterExtension::class); - -if (false) { - class AbstractFilterExtension extends \ApiPlatform\Elasticsearch\Extension\AbstractFilterExtension - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtension.php b/src/Core/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtension.php deleted file mode 100644 index 34c17757c37..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Extension; - -class_exists(\ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension::class); - -if (false) { - final class ConstantScoreFilterExtension extends \ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortExtension.php b/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortExtension.php deleted file mode 100644 index efaac85fe8f..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Extension; - -class_exists(\ApiPlatform\Elasticsearch\Extension\SortExtension::class); - -if (false) { - final class SortExtension extends \ApiPlatform\Elasticsearch\Extension\SortExtension - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtension.php b/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtension.php deleted file mode 100644 index 41d41d46eee..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Extension; - -class_exists(\ApiPlatform\Elasticsearch\Extension\SortFilterExtension::class); - -if (false) { - final class SortFilterExtension extends \ApiPlatform\Elasticsearch\Extension\SortFilterExtension - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractFilter.php deleted file mode 100644 index 4be367ca6e0..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractFilter.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Filter; - -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Util\FieldDatatypeTrait; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Exception\ResourceClassNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Abstract class with helpers for easing the implementation of a filter. - * - * @experimental - * - * @author Baptiste Meyer - */ -abstract class AbstractFilter implements FilterInterface -{ - use FieldDatatypeTrait { getNestedFieldPath as protected; } - - protected $properties; - protected $propertyNameCollectionFactory; - protected $nameConverter; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, ?array $properties = null) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->resourceClassResolver = $resourceClassResolver; - $this->nameConverter = $nameConverter; - $this->properties = $properties; - } - - /** - * Gets all enabled properties for the given resource class. - */ - protected function getProperties(string $resourceClass): \Traversable - { - if (null !== $this->properties) { - return yield from array_keys($this->properties); - } - - try { - yield from $this->propertyNameCollectionFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - } - } - - /** - * Is the given property enabled? - */ - protected function hasProperty(string $resourceClass, string $property): bool - { - return \in_array($property, iterator_to_array($this->getProperties($resourceClass)), true); - } - - /** - * Gets info about the decomposed given property for the given resource class. - * - * Returns an array with the following info as values: - * - the {@see Type} of the decomposed given property - * - is the decomposed given property an association? - * - the resource class of the decomposed given property - * - the property name of the decomposed given property - */ - protected function getMetadata(string $resourceClass, string $property): array - { - $noop = [null, null, null, null]; - - if (!$this->hasProperty($resourceClass, $property)) { - return $noop; - } - - $properties = explode('.', $property); - $totalProperties = \count($properties); - $currentResourceClass = $resourceClass; - $hasAssociation = false; - $currentProperty = null; - $type = null; - - foreach ($properties as $index => $currentProperty) { - try { - $propertyMetadata = $this->propertyMetadataFactory->create($currentResourceClass, $currentProperty); - } catch (PropertyNotFoundException $e) { - return $noop; - } - - if (null === $type = $propertyMetadata->getType()) { - return $noop; - } - - ++$index; - $builtinType = $type->getBuiltinType(); - - if (Type::BUILTIN_TYPE_OBJECT !== $builtinType && Type::BUILTIN_TYPE_ARRAY !== $builtinType) { - if ($totalProperties === $index) { - break; - } - - return $noop; - } - - if ($type->isCollection() && null === $type = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType()) { - return $noop; - } - - if (Type::BUILTIN_TYPE_ARRAY === $builtinType && Type::BUILTIN_TYPE_OBJECT !== $type->getBuiltinType()) { - if ($totalProperties === $index) { - break; - } - - return $noop; - } - - if (null === $className = $type->getClassName()) { - return $noop; - } - - if ($isResourceClass = $this->resourceClassResolver->isResourceClass($className)) { - $currentResourceClass = $className; - } elseif ($totalProperties !== $index) { - return $noop; - } - - $hasAssociation = $totalProperties === $index && $isResourceClass; - } - - return [$type, $hasAssociation, $currentResourceClass, $currentProperty]; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractSearchFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractSearchFilter.php deleted file mode 100644 index 6596dd6eeba..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/AbstractSearchFilter.php +++ /dev/null @@ -1,187 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Filter; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Abstract class with helpers for easing the implementation of a search filter like a term filter or a match filter. - * - * @experimental - * - * @internal - * - * @author Baptiste Meyer - */ -abstract class AbstractSearchFilter extends AbstractFilter implements ConstantScoreFilterInterface -{ - protected $identifierExtractor; - protected $iriConverter; - protected $propertyAccessor; - - /** - * {@inheritdoc} - */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, IdentifierExtractorInterface $identifierExtractor, IriConverterInterface $iriConverter, PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter = null, ?array $properties = null) - { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceClassResolver, $nameConverter, $properties); - - $this->identifierExtractor = $identifierExtractor; - $this->iriConverter = $iriConverter; - $this->propertyAccessor = $propertyAccessor; - } - - /** - * {@inheritdoc} - */ - public function apply(array $clauseBody, string $resourceClass, ?string $operationName = null, array $context = []): array - { - $searches = []; - - foreach ($context['filters'] ?? [] as $property => $values) { - [$type, $hasAssociation, $nestedResourceClass, $nestedProperty] = $this->getMetadata($resourceClass, $property); - - if (!$type || !$values = (array) $values) { - continue; - } - - if ($hasAssociation || $this->isIdentifier($nestedResourceClass, $nestedProperty)) { - $values = array_map([$this, 'getIdentifierValue'], $values, array_fill(0, \count($values), $nestedProperty)); - } - - if (!$this->hasValidValues($values, $type)) { - continue; - } - - $property = null === $this->nameConverter ? $property : $this->nameConverter->normalize($property, $resourceClass, null, $context); - $nestedPath = $this->getNestedFieldPath($resourceClass, $property); - $nestedPath = null === $nestedPath || null === $this->nameConverter ? $nestedPath : $this->nameConverter->normalize($nestedPath, $resourceClass, null, $context); - - $searches[] = $this->getQuery($property, $values, $nestedPath); - } - - if (!$searches) { - return $clauseBody; - } - - return array_merge_recursive($clauseBody, [ - 'bool' => [ - 'must' => $searches, - ], - ]); - } - - /** - * {@inheritdoc} - */ - public function getDescription(string $resourceClass): array - { - $description = []; - - foreach ($this->getProperties($resourceClass) as $property) { - [$type, $hasAssociation] = $this->getMetadata($resourceClass, $property); - - if (!$type) { - continue; - } - - foreach ([$property, "${property}[]"] as $filterParameterName) { - $description[$filterParameterName] = [ - 'property' => $property, - 'type' => $hasAssociation ? 'string' : $this->getPhpType($type), - 'required' => false, - ]; - } - } - - return $description; - } - - /** - * Gets the Elasticsearch query corresponding to the current search filter. - */ - abstract protected function getQuery(string $property, array $values, ?string $nestedPath): array; - - /** - * Converts the given {@see Type} in PHP type. - */ - protected function getPhpType(Type $type): string - { - switch ($builtinType = $type->getBuiltinType()) { - case Type::BUILTIN_TYPE_ARRAY: - case Type::BUILTIN_TYPE_INT: - case Type::BUILTIN_TYPE_FLOAT: - case Type::BUILTIN_TYPE_BOOL: - case Type::BUILTIN_TYPE_STRING: - return $builtinType; - case Type::BUILTIN_TYPE_OBJECT: - if (null !== ($className = $type->getClassName()) && is_a($className, \DateTimeInterface::class, true)) { - return \DateTimeInterface::class; - } - - // no break - default: - return 'string'; - } - } - - /** - * Is the given property of the given resource class an identifier? - */ - protected function isIdentifier(string $resourceClass, string $property): bool - { - return $property === $this->identifierExtractor->getIdentifierFromResourceClass($resourceClass); - } - - /** - * Gets the ID from an IRI or a raw ID. - */ - protected function getIdentifierValue(string $iri, string $property) - { - try { - if ($item = $this->iriConverter->getItemFromIri($iri, ['fetch_data' => false])) { - return $this->propertyAccessor->getValue($item, $property); - } - } catch (InvalidArgumentException $e) { - } - - return $iri; - } - - /** - * Are the given values valid according to the given {@see Type}? - */ - protected function hasValidValues(array $values, Type $type): bool - { - foreach ($values as $value) { - if ( - null !== $value - && Type::BUILTIN_TYPE_INT === $type->getBuiltinType() - && false === filter_var($value, \FILTER_VALIDATE_INT) - ) { - return false; - } - } - - return true; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/MatchFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/MatchFilter.php deleted file mode 100644 index c3d9f9a82d1..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/MatchFilter.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Filter; - -/** - * Filter the collection by given properties using a full text query. - * - * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html - * - * @experimental - * - * @author Baptiste Meyer - */ -final class MatchFilter extends AbstractSearchFilter -{ - /** - * {@inheritdoc} - */ - protected function getQuery(string $property, array $values, ?string $nestedPath): array - { - $matches = []; - - foreach ($values as $value) { - $matches[] = ['match' => [$property => $value]]; - } - - $matchQuery = isset($matches[1]) ? ['bool' => ['should' => $matches]] : $matches[0]; - - if (null !== $nestedPath) { - $matchQuery = ['nested' => ['path' => $nestedPath, 'query' => $matchQuery]]; - } - - return $matchQuery; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/OrderFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/OrderFilter.php deleted file mode 100644 index a1c78f3f06d..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/OrderFilter.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Filter; - -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Order the collection by given properties. - * - * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html - * - * @experimental - * - * @author Baptiste Meyer - */ -final class OrderFilter extends AbstractFilter implements SortFilterInterface -{ - private $orderParameterName; - - /** - * {@inheritdoc} - */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, string $orderParameterName = 'order', ?array $properties = null) - { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceClassResolver, $nameConverter, $properties); - - $this->orderParameterName = $orderParameterName; - } - - /** - * {@inheritdoc} - */ - public function apply(array $clauseBody, string $resourceClass, ?string $operationName = null, array $context = []): array - { - if (!\is_array($properties = $context['filters'][$this->orderParameterName] ?? [])) { - return $clauseBody; - } - - $orders = []; - - foreach ($properties as $property => $direction) { - [$type] = $this->getMetadata($resourceClass, $property); - - if (!$type) { - continue; - } - - if (empty($direction) && null !== $defaultDirection = $this->properties[$property] ?? null) { - $direction = $defaultDirection; - } - - if (!\in_array($direction = strtolower($direction), ['asc', 'desc'], true)) { - continue; - } - - $order = ['order' => $direction]; - - if (null !== $nestedPath = $this->getNestedFieldPath($resourceClass, $property)) { - $nestedPath = null === $this->nameConverter ? $nestedPath : $this->nameConverter->normalize($nestedPath, $resourceClass, null, $context); - $order['nested'] = ['path' => $nestedPath]; - } - - $property = null === $this->nameConverter ? $property : $this->nameConverter->normalize($property, $resourceClass, null, $context); - $orders[] = [$property => $order]; - } - - if (!$orders) { - return $clauseBody; - } - - return array_merge_recursive($clauseBody, $orders); - } - - /** - * {@inheritdoc} - */ - public function getDescription(string $resourceClass): array - { - $description = []; - - foreach ($this->getProperties($resourceClass) as $property) { - [$type] = $this->getMetadata($resourceClass, $property); - - if (!$type) { - continue; - } - - $description["$this->orderParameterName[$property]"] = [ - 'property' => $property, - 'type' => 'string', - 'required' => false, - ]; - } - - return $description; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/TermFilter.php b/src/Core/Bridge/Elasticsearch/DataProvider/Filter/TermFilter.php deleted file mode 100644 index 3afc8e357dd..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Filter/TermFilter.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider\Filter; - -/** - * Filter the collection by given properties using a term level query. - * - * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html - * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html - * - * @experimental - * - * @author Baptiste Meyer - */ -final class TermFilter extends AbstractSearchFilter -{ - /** - * {@inheritdoc} - */ - protected function getQuery(string $property, array $values, ?string $nestedPath): array - { - if (1 === \count($values)) { - $termQuery = ['term' => [$property => reset($values)]]; - } else { - $termQuery = ['terms' => [$property => $values]]; - } - - if (null !== $nestedPath) { - $termQuery = ['nested' => ['path' => $nestedPath, 'query' => $termQuery]]; - } - - return $termQuery; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/ItemDataProvider.php b/src/Core/Bridge/Elasticsearch/DataProvider/ItemDataProvider.php deleted file mode 100644 index 1a47a480720..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/ItemDataProvider.php +++ /dev/null @@ -1,117 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider; - -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; -use ApiPlatform\Elasticsearch\Util\ElasticsearchVersion; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use Elasticsearch\Client; -use Elasticsearch\Common\Exceptions\Missing404Exception; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Item data provider for Elasticsearch. - * - * @experimental - * - * @author Baptiste Meyer - */ -final class ItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - private $client; - private $documentMetadataFactory; - private $identifierExtractor; - private $denormalizer; - private $resourceMetadataFactory; - - public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, IdentifierExtractorInterface $identifierExtractor, DenormalizerInterface $denormalizer, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - $this->client = $client; - $this->documentMetadataFactory = $documentMetadataFactory; - $this->identifierExtractor = $identifierExtractor; - $this->denormalizer = $denormalizer; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, ?string $operationName = null, array $context = []): bool - { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (false === $resourceMetadata->getItemOperationAttribute($operationName, 'elasticsearch', true, true)) { - return false; - } - } catch (ResourceClassNotFoundException $e) { - return false; - } - - try { - $this->documentMetadataFactory->create($resourceClass); - } catch (IndexNotFoundException $e) { - return false; - } - - try { - $this->identifierExtractor->getIdentifierFromResourceClass($resourceClass); - } catch (NonUniqueIdentifierException $e) { - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, ?string $operationName = null, array $context = []) - { - if (\is_array($id)) { - $id = $id[$this->identifierExtractor->getIdentifierFromResourceClass($resourceClass)]; - } - - $documentMetadata = $this->documentMetadataFactory->create($resourceClass); - - try { - $params = [ - 'index' => $documentMetadata->getIndex(), - 'id' => (string) $id, - ]; - - if (ElasticsearchVersion::supportsMappingType()) { - $params['type'] = $documentMetadata->getType(); - } - - $document = $this->client->get($params); - } catch (Missing404Exception $e) { - return null; - } - - $item = $this->denormalizer->denormalize($document, $resourceClass, DocumentNormalizer::FORMAT, [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true]); - if (!\is_object($item) && null !== $item) { - throw new \UnexpectedValueException('Expected item to be an object or null.'); - } - - return $item; - } -} diff --git a/src/Core/Bridge/Elasticsearch/DataProvider/Paginator.php b/src/Core/Bridge/Elasticsearch/DataProvider/Paginator.php deleted file mode 100644 index 4e0fb589221..00000000000 --- a/src/Core/Bridge/Elasticsearch/DataProvider/Paginator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider; - -class_exists(\ApiPlatform\Elasticsearch\Paginator::class); - -if (false) { - final class Paginator extends \ApiPlatform\Elasticsearch\Paginator - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Exception/IndexNotFoundException.php b/src/Core/Bridge/Elasticsearch/Exception/IndexNotFoundException.php deleted file mode 100644 index e0763c4c81a..00000000000 --- a/src/Core/Bridge/Elasticsearch/Exception/IndexNotFoundException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Exception; - -class_exists(\ApiPlatform\Elasticsearch\Exception\IndexNotFoundException::class); - -if (false) { - final class IndexNotFoundException extends \ApiPlatform\Elasticsearch\Exception\IndexNotFoundException - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Exception/NonUniqueIdentifierException.php b/src/Core/Bridge/Elasticsearch/Exception/NonUniqueIdentifierException.php deleted file mode 100644 index 9ea219a8237..00000000000 --- a/src/Core/Bridge/Elasticsearch/Exception/NonUniqueIdentifierException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Exception; - -class_exists(\ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException::class); - -if (false) { - final class NonUniqueIdentifierException extends \ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/DocumentMetadata.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/DocumentMetadata.php deleted file mode 100644 index ec74aea8ca2..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/DocumentMetadata.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Metadata\Document; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata::class); - -if (false) { - final class DocumentMetadata extends \ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php deleted file mode 100644 index 57e6ab8689c..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Metadata\Document\Factory; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory::class); - -if (false) { - final class AttributeDocumentMetadataFactory extends \ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php deleted file mode 100644 index 904c2b63bc8..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Metadata\Document\Factory; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory::class); - -if (false) { - final class CachedDocumentMetadataFactory extends \ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php deleted file mode 100644 index 09c9e6500aa..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Metadata\Document\Factory; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory::class); - -if (false) { - final class CatDocumentMetadataFactory extends \ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php deleted file mode 100644 index 2f126d745fa..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Metadata\Document\Factory; - -class_exists(\ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory::class); - -if (false) { - final class ConfiguredDocumentMetadataFactory extends \ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php b/src/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php deleted file mode 100644 index d7cf855da08..00000000000 --- a/src/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * 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\Elasticsearch\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Creates read-only operations for Elasticsearch. - * - * @experimental - * - * @author Baptiste Meyer - */ -final class ElasticsearchOperationResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - - public function __construct(ResourceMetadataFactoryInterface $decorated) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - - if (null === $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations(['get' => ['method' => 'GET']]); - } - - if (null === $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations(['get' => ['method' => 'GET']]); - } - - return $resourceMetadata; - } -} diff --git a/src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php b/src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php deleted file mode 100644 index eb59f592f40..00000000000 --- a/src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Serializer; - -class_exists(\ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer::class); - -if (false) { - final class DocumentNormalizer extends \ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Serializer/ItemNormalizer.php b/src/Core/Bridge/Elasticsearch/Serializer/ItemNormalizer.php deleted file mode 100644 index d263305ffe6..00000000000 --- a/src/Core/Bridge/Elasticsearch/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Serializer; - -class_exists(\ApiPlatform\Elasticsearch\Serializer\ItemNormalizer::class); - -if (false) { - final class ItemNormalizer extends \ApiPlatform\Elasticsearch\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php b/src/Core/Bridge/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php deleted file mode 100644 index ee7a3d14880..00000000000 --- a/src/Core/Bridge/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Elasticsearch\Serializer\NameConverter; - -class_exists(\ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter::class); - -if (false) { - final class InnerFieldsNameConverter extends \ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter - { - } -} diff --git a/src/Core/Bridge/Elasticsearch/Util/FieldDatatypeTrait.php b/src/Core/Bridge/Elasticsearch/Util/FieldDatatypeTrait.php deleted file mode 100644 index 71dd32bd3fb..00000000000 --- a/src/Core/Bridge/Elasticsearch/Util/FieldDatatypeTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Elasticsearch\Util; - -class_exists(\ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait::class); - -if (false) { - trait FieldDatatypeTrait - { - use \ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait; - } -} diff --git a/src/Core/Bridge/FosUser/EventListener.php b/src/Core/Bridge/FosUser/EventListener.php deleted file mode 100644 index 41b77dd78a4..00000000000 --- a/src/Core/Bridge/FosUser/EventListener.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * 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\FosUser; - -use ApiPlatform\Util\RequestAttributesExtractor; -use FOS\UserBundle\Model\UserInterface; -use FOS\UserBundle\Model\UserManagerInterface; -use Symfony\Component\HttpKernel\Event\ViewEvent; - -/** - * Bridges between FOSUserBundle and API Platform Core. - * - * @author Kévin Dunglas - * @author Théo FIDRY - */ -final class EventListener -{ - private $userManager; - - public function __construct(UserManagerInterface $userManager) - { - $this->userManager = $userManager; - } - - /** - * Persists, updates or delete data return by the controller if applicable. - */ - public function onKernelView(ViewEvent $event): void - { - $request = $event->getRequest(); - if (!RequestAttributesExtractor::extractAttributes($request)) { - return; - } - - $user = $event->getControllerResult(); - if (!$user instanceof UserInterface || $request->isMethodSafe()) { - return; - } - - if ('DELETE' === $request->getMethod()) { - $this->userManager->deleteUser($user); - $event->setControllerResult(null); - } else { - $this->userManager->updateUser($user); - } - } -} diff --git a/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php b/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php deleted file mode 100644 index 7fec3d40f61..00000000000 --- a/src/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php +++ /dev/null @@ -1,215 +0,0 @@ - - * - * 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\NelmioApiDoc\Extractor\AnnotationsProvider; - -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\FilterLocatorTrait; -use ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser; -use ApiPlatform\Core\Bridge\Symfony\Routing\OperationMethodResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use Nelmio\ApiDocBundle\Annotation\ApiDoc; -use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface; -use Psr\Container\ContainerInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -if (interface_exists(AnnotationsProviderInterface::class)) { - /** - * Creates Nelmio ApiDoc annotations for the api platform. - * - * @author Kévin Dunglas - * @author Teoh Han Hui - * - * @deprecated since version 2.2, to be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - final class ApiPlatformProvider implements AnnotationsProviderInterface - { - use FilterLocatorTrait; - - private $resourceNameCollectionFactory; - private $documentationNormalizer; - private $resourceMetadataFactory; - private $operationMethodResolver; - - /** - * @param ContainerInterface|FilterCollection $filterLocator The new filter locator or the deprecated filter collection - */ - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, NormalizerInterface $documentationNormalizer, ResourceMetadataFactoryInterface $resourceMetadataFactory, $filterLocator, OperationMethodResolverInterface $operationMethodResolver) - { - @trigger_error('The '.__CLASS__.' class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.', \E_USER_DEPRECATED); - - $this->setFilterLocator($filterLocator); - - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->documentationNormalizer = $documentationNormalizer; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->operationMethodResolver = $operationMethodResolver; - } - - /** - * {@inheritdoc} - */ - public function getAnnotations(): array - { - $resourceNameCollection = $this->resourceNameCollectionFactory->create(); - - $hydraDoc = $this->documentationNormalizer->normalize(new Documentation($resourceNameCollection)); - if (!\is_array($hydraDoc)) { - throw new \UnexpectedValueException('Expected data to be an array'); - } - - if (empty($hydraDoc)) { - return []; - } - - $entrypointHydraDoc = $this->getResourceHydraDoc($hydraDoc, '#Entrypoint'); - if (null === $entrypointHydraDoc) { - return []; - } - - $annotations = []; - foreach ($resourceNameCollection as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $prefixedShortName = ($iri = $resourceMetadata->getIri()) ? $iri : '#'.$resourceMetadata->getShortName(); - $resourceHydraDoc = $this->getResourceHydraDoc($hydraDoc, $prefixedShortName); - if (null === $resourceHydraDoc) { - continue; - } - - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - foreach ($collectionOperations as $operationName => $operation) { - $annotations[] = $this->getApiDoc(true, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc, $entrypointHydraDoc); - } - } - - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - foreach ($itemOperations as $operationName => $operation) { - $annotations[] = $this->getApiDoc(false, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc); - } - } - } - - return $annotations; - } - - /** - * Builds ApiDoc annotation from ApiPlatform data. - */ - private function getApiDoc(bool $collection, string $resourceClass, ResourceMetadata $resourceMetadata, string $operationName, array $resourceHydraDoc, array $entrypointHydraDoc = []): ApiDoc - { - if ($collection) { - $method = $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); - $route = $this->operationMethodResolver->getCollectionOperationRoute($resourceClass, $operationName); - $operationHydraDoc = $this->getCollectionOperationHydraDoc($resourceMetadata->getShortName(), $method, $entrypointHydraDoc); - } else { - $method = $this->operationMethodResolver->getItemOperationMethod($resourceClass, $operationName); - $route = $this->operationMethodResolver->getItemOperationRoute($resourceClass, $operationName); - $operationHydraDoc = $this->getOperationHydraDoc($method, $resourceHydraDoc); - } - - $data = [ - 'resource' => $route->getPath(), - 'description' => $operationHydraDoc['hydra:title'] ?? '', - 'resourceDescription' => $resourceHydraDoc['hydra:title'] ?? '', - 'section' => $resourceHydraDoc['hydra:title'] ?? '', - ]; - - if (isset($operationHydraDoc['expects']) && 'owl:Nothing' !== $operationHydraDoc['expects']) { - $data['input'] = sprintf('%s:%s:%s', ApiPlatformParser::IN_PREFIX, $resourceClass, $operationName); - } - - if (isset($operationHydraDoc['returns']) && 'owl:Nothing' !== $operationHydraDoc['returns']) { - $data['output'] = sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, $resourceClass, $operationName); - } - - if ($collection && 'GET' === $method) { - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); - - $data['filters'] = []; - foreach ($resourceFilters as $filterId) { - if ($filter = $this->getFilter($filterId)) { - foreach ($filter->getDescription($resourceClass) as $name => $definition) { - $data['filters'][] = ['name' => $name] + $definition; - } - } - } - } - - $apiDoc = new ApiDoc($data); - $apiDoc->setRoute($route); - - return $apiDoc; - } - - /** - * Gets Hydra documentation for the given resource. - */ - private function getResourceHydraDoc(array $hydraApiDoc, string $prefixedShortName): ?array - { - if (!isset($hydraApiDoc['hydra:supportedClass']) || !\is_array($hydraApiDoc['hydra:supportedClass'])) { - return null; - } - - foreach ($hydraApiDoc['hydra:supportedClass'] as $supportedClass) { - if (isset($supportedClass['@id']) && $supportedClass['@id'] === $prefixedShortName) { - return $supportedClass; - } - } - - return null; - } - - /** - * Gets the Hydra documentation of a given operation. - */ - private function getOperationHydraDoc(string $method, array $hydraDoc): array - { - if (!isset($hydraDoc['hydra:supportedOperation']) || !\is_array($hydraDoc['hydra:supportedOperation'])) { - return []; - } - - foreach ($hydraDoc['hydra:supportedOperation'] as $supportedOperation) { - if ($supportedOperation['hydra:method'] === $method) { - return $supportedOperation; - } - } - - return []; - } - - /** - * Gets the Hydra documentation for the collection operation. - */ - private function getCollectionOperationHydraDoc(string $shortName, string $method, array $hydraEntrypointDoc): array - { - if (!isset($hydraEntrypointDoc['hydra:supportedProperty']) || !\is_array($hydraEntrypointDoc['hydra:supportedProperty'])) { - return []; - } - - $propertyName = '#Entrypoint/'.lcfirst($shortName); - - foreach ($hydraEntrypointDoc['hydra:supportedProperty'] as $supportedProperty) { - if (isset($supportedProperty['hydra:property']['@id']) - && $supportedProperty['hydra:property']['@id'] === $propertyName) { - return $this->getOperationHydraDoc($method, $supportedProperty['hydra:property']); - } - } - - return []; - } - } -} diff --git a/src/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParser.php b/src/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParser.php deleted file mode 100644 index fc591363d64..00000000000 --- a/src/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParser.php +++ /dev/null @@ -1,280 +0,0 @@ - - * - * 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\NelmioApiDoc\Parser; - -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\ApiProperty; -use Nelmio\ApiDocBundle\DataTypes; -use Nelmio\ApiDocBundle\Parser\ParserInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -if (interface_exists(ParserInterface::class)) { - /** - * Extract input and output information for the NelmioApiDocBundle. - * - * @author Kévin Dunglas - * @author Teoh Han Hui - * - * @deprecated since version 2.2, to be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - final class ApiPlatformParser implements ParserInterface - { - public const IN_PREFIX = 'api_platform_in'; - public const OUT_PREFIX = 'api_platform_out'; - public const TYPE_IRI = 'IRI'; - public const TYPE_MAP = [ - Type::BUILTIN_TYPE_BOOL => DataTypes::BOOLEAN, - Type::BUILTIN_TYPE_FLOAT => DataTypes::FLOAT, - Type::BUILTIN_TYPE_INT => DataTypes::INTEGER, - Type::BUILTIN_TYPE_STRING => DataTypes::STRING, - ]; - - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $nameConverter; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, NameConverterInterface $nameConverter = null) - { - @trigger_error('The '.__CLASS__.' class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.', \E_USER_DEPRECATED); - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->nameConverter = $nameConverter; - } - - /** - * {@inheritdoc} - */ - public function supports(array $item) - { - $data = explode(':', $item['class'], 3); - if (!\in_array($data[0], [self::IN_PREFIX, self::OUT_PREFIX], true)) { - return false; - } - if (!isset($data[1])) { - return false; - } - - try { - $this->resourceMetadataFactory->create($data[1]); - - return true; - } catch (ResourceClassNotFoundException $e) { - // return false - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function parse(array $item): array - { - [$io, $resourceClass, $operationName] = explode(':', $item['class'], 3); - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $classOperations = $this->getGroupsForItemAndCollectionOperation($resourceMetadata, $operationName, $io); - - if (!empty($classOperations['serializer_groups'])) { - return $this->getPropertyMetadata($resourceMetadata, $resourceClass, $io, [], $classOperations); - } - - return $this->parseResource($resourceMetadata, $resourceClass, $io); - } - - /** - * Parses a class. - * - * @param string[] $visited - */ - private function parseResource(ResourceMetadata $resourceMetadata, string $resourceClass, string $io, array $visited = []): array - { - $visited[] = $resourceClass; - - $options = []; - $attributes = $resourceMetadata->getAttributes(); - - if (isset($attributes['normalization_context'][AbstractNormalizer::GROUPS])) { - $options['serializer_groups'] = (array) $attributes['normalization_context'][AbstractNormalizer::GROUPS]; - } - - if (isset($attributes['denormalization_context'][AbstractNormalizer::GROUPS])) { - if (isset($options['serializer_groups'])) { - $options['serializer_groups'] += $attributes['denormalization_context'][AbstractNormalizer::GROUPS]; - } else { - $options['serializer_groups'] = (array) $attributes['denormalization_context'][AbstractNormalizer::GROUPS]; - } - } - - return $this->getPropertyMetadata($resourceMetadata, $resourceClass, $io, $visited, $options); - } - - private function getGroupsContext(ResourceMetadata $resourceMetadata, string $operationName, bool $isNormalization): array - { - $groupsContext = $isNormalization ? 'normalization_context' : 'denormalization_context'; - $itemOperationAttribute = $resourceMetadata->getItemOperationAttribute($operationName, $groupsContext, [AbstractNormalizer::GROUPS => []], true)[AbstractNormalizer::GROUPS]; - $collectionOperationAttribute = $resourceMetadata->getCollectionOperationAttribute($operationName, $groupsContext, [AbstractNormalizer::GROUPS => []], true)[AbstractNormalizer::GROUPS]; - - return [ - $groupsContext => [ - AbstractNormalizer::GROUPS => array_merge((array) ($itemOperationAttribute ?? []), (array) ($collectionOperationAttribute ?? [])), - ], - ]; - } - - /** - * Returns groups of item & collection. - */ - private function getGroupsForItemAndCollectionOperation(ResourceMetadata $resourceMetadata, string $operationName, string $io): array - { - $operation = $this->getGroupsContext($resourceMetadata, $operationName, true); - $operation += $this->getGroupsContext($resourceMetadata, $operationName, false); - - if (self::OUT_PREFIX === $io) { - return [ - 'serializer_groups' => !empty($operation['normalization_context']) ? $operation['normalization_context'][AbstractNormalizer::GROUPS] : [], - ]; - } - - if (self::IN_PREFIX === $io) { - return [ - 'serializer_groups' => !empty($operation['denormalization_context']) ? $operation['denormalization_context'][AbstractNormalizer::GROUPS] : [], - ]; - } - - return []; - } - - /** - * Returns a property metadata. - * - * @param string[] $visited - * @param string[] $options - */ - private function getPropertyMetadata(ResourceMetadata $resourceMetadata, string $resourceClass, string $io, array $visited, array $options): array - { - $data = []; - - foreach ($this->propertyNameCollectionFactory->create($resourceClass, $options) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - if ( - ($propertyMetadata->isReadable() && self::OUT_PREFIX === $io) || - ($propertyMetadata->isWritable() && self::IN_PREFIX === $io) - ) { - $normalizedPropertyName = $this->nameConverter ? $this->nameConverter->normalize($propertyName, $resourceClass) : $propertyName; - $data[$normalizedPropertyName] = $this->parseProperty($resourceMetadata, $propertyMetadata, $io, null, $visited); - } - } - - return $data; - } - - /** - * Parses a property. - * - * @param string $io - * @param string[] $visited - * @param ApiProperty|PropertyMetadata $propertyMetadata - */ - private function parseProperty(ResourceMetadata $resourceMetadata, $propertyMetadata, $io, Type $type = null, array $visited = []): array - { - $data = [ - 'dataType' => null, - 'required' => $propertyMetadata->isRequired(), - 'description' => $propertyMetadata->getDescription(), - 'readonly' => !$propertyMetadata->isWritable(), - ]; - - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; - if (null === $type && null === $type) { - // Default to string - $data['dataType'] = DataTypes::STRING; - - return $data; - } - - if ($type->isCollection()) { - $data['actualType'] = DataTypes::COLLECTION; - - if ($collectionType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType()) { - $subProperty = $this->parseProperty($resourceMetadata, $propertyMetadata, $io, $collectionType, $visited); - if (self::TYPE_IRI === $subProperty['dataType']) { - $data['dataType'] = 'array of IRIs'; - $data['subType'] = DataTypes::STRING; - - return $data; - } - - $data['subType'] = $subProperty['subType'] ?? null; - if (isset($subProperty['children'])) { - $data['children'] = $subProperty['children']; - } - } - - return $data; - } - - $builtinType = $type->getBuiltinType(); - if ('object' === $builtinType) { - $className = $type->getClassName(); - - if (is_a($className, \DateTimeInterface::class, true)) { - $data['dataType'] = DataTypes::DATETIME; - $data['format'] = sprintf('{DateTime %s}', \DateTime::RFC3339); - - return $data; - } - - try { - $this->resourceMetadataFactory->create($className); - } catch (ResourceClassNotFoundException $e) { - $data['actualType'] = DataTypes::MODEL; - $data['subType'] = $className; - - return $data; - } - - if ( - (self::OUT_PREFIX === $io && true !== $propertyMetadata->isReadableLink()) || - (self::IN_PREFIX === $io && true !== $propertyMetadata->isWritableLink()) - ) { - $data['dataType'] = self::TYPE_IRI; - $data['actualType'] = DataTypes::STRING; - - return $data; - } - - $data['actualType'] = DataTypes::MODEL; - $data['subType'] = $className; - $data['children'] = \in_array($className, $visited, true) ? [] : $this->parseResource($resourceMetadata, $className, $io, $visited); - - return $data; - } - - $data['dataType'] = self::TYPE_MAP[$builtinType] ?? DataTypes::STRING; - - return $data; - } - } -} diff --git a/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php b/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php deleted file mode 100644 index 10c0743f0c3..00000000000 --- a/src/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizer.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * 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\RamseyUuid\Identifier\Normalizer; - -use ApiPlatform\Exception\InvalidIdentifierException; -use Ramsey\Uuid\Exception\InvalidUuidStringException; -use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\UuidInterface; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Denormalizes an UUID string to an instance of Ramsey\Uuid. - * - * @author Antoine Bluchet - */ -final class UuidNormalizer implements DenormalizerInterface -{ - /** - * {@inheritdoc} - * - * @param mixed $data - * @param string $class - * @param null $format - * - * @throws InvalidIdentifierException - * - * @return mixed - */ - public function denormalize($data, $class, $format = null, array $context = []) - { - try { - return Uuid::fromString($data); - } catch (InvalidUuidStringException $e) { - throw new InvalidIdentifierException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return \is_string($data) && is_a($type, UuidInterface::class, true); - } -} diff --git a/src/Core/Bridge/RamseyUuid/Serializer/UuidDenormalizer.php b/src/Core/Bridge/RamseyUuid/Serializer/UuidDenormalizer.php deleted file mode 100644 index f9e8ece6a91..00000000000 --- a/src/Core/Bridge/RamseyUuid/Serializer/UuidDenormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\RamseyUuid\Serializer; - -class_exists(\ApiPlatform\RamseyUuid\Serializer\UuidDenormalizer::class); - -if (false) { - final class UuidDenormalizer extends \ApiPlatform\RamseyUuid\Serializer\UuidDenormalizer - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php b/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php deleted file mode 100644 index d0865adb0b5..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php +++ /dev/null @@ -1,229 +0,0 @@ - - * - * 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\Bundle\Action; - -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction as OpenApiSwaggerUiAction; -use ApiPlatform\Util\RequestAttributesExtractor; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Twig\Environment as TwigEnvironment; - -/** - * Displays the documentation. - * - * @deprecated please refer to ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction for further changes - * - * @author Kévin Dunglas - */ -final class SwaggerUiAction -{ - private $resourceNameCollectionFactory; - /** @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface */ - private $resourceMetadataFactory; - private $normalizer; - private $twig; - private $urlGenerator; - private $title; - private $description; - private $version; - private $showWebby; - private $formats; - private $oauthEnabled; - private $oauthClientId; - private $oauthClientSecret; - private $oauthType; - private $oauthFlow; - private $oauthTokenUrl; - private $oauthAuthorizationUrl; - private $oauthScopes; - private $oauthPkce; - private $formatsProvider; - private $swaggerUiEnabled; - private $reDocEnabled; - private $graphqlEnabled; - private $graphiQlEnabled; - private $graphQlPlaygroundEnabled; - private $swaggerVersions; - private $swaggerUiAction; - private $assetPackage; - private $swaggerUiExtraConfiguration; - - /** - * @param int[] $swaggerVersions - * @param mixed|null $assetPackage - * @param mixed $formats - * @param mixed $oauthEnabled - * @param mixed $oauthClientId - * @param mixed $oauthClientSecret - * @param mixed $oauthType - * @param mixed $oauthFlow - * @param mixed $oauthTokenUrl - * @param mixed $oauthAuthorizationUrl - * @param mixed $oauthScopes - * @param mixed $resourceMetadataFactory - */ - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, $resourceMetadataFactory, NormalizerInterface $normalizer, ?TwigEnvironment $twig, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '', string $version = '', $formats = [], $oauthEnabled = false, $oauthClientId = '', $oauthClientSecret = '', $oauthType = '', $oauthFlow = '', $oauthTokenUrl = '', $oauthAuthorizationUrl = '', $oauthScopes = [], bool $showWebby = true, bool $swaggerUiEnabled = false, bool $reDocEnabled = false, bool $graphqlEnabled = false, bool $graphiQlEnabled = false, bool $graphQlPlaygroundEnabled = false, array $swaggerVersions = [2, 3], OpenApiSwaggerUiAction $swaggerUiAction = null, $assetPackage = null, array $swaggerUiExtraConfiguration = [], bool $oauthPkce = false) - { - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->normalizer = $normalizer; - $this->twig = $twig; - $this->urlGenerator = $urlGenerator; - $this->title = $title; - $this->showWebby = $showWebby; - $this->description = $description; - $this->version = $version; - $this->oauthEnabled = $oauthEnabled; - $this->oauthClientId = $oauthClientId; - $this->oauthClientSecret = $oauthClientSecret; - $this->oauthType = $oauthType; - $this->oauthFlow = $oauthFlow; - $this->oauthTokenUrl = $oauthTokenUrl; - $this->oauthAuthorizationUrl = $oauthAuthorizationUrl; - $this->oauthScopes = $oauthScopes; - $this->swaggerUiEnabled = $swaggerUiEnabled; - $this->reDocEnabled = $reDocEnabled; - $this->graphqlEnabled = $graphqlEnabled; - $this->graphiQlEnabled = $graphiQlEnabled; - $this->graphQlPlaygroundEnabled = $graphQlPlaygroundEnabled; - $this->swaggerVersions = $swaggerVersions; - $this->swaggerUiAction = $swaggerUiAction; - $this->swaggerUiExtraConfiguration = $swaggerUiExtraConfiguration; - $this->assetPackage = $assetPackage; - $this->oauthPkce = $oauthPkce; - - if (null === $this->twig) { - throw new \RuntimeException('The documentation cannot be displayed since the Twig bundle is not installed. Try running "composer require symfony/twig-bundle".'); - } - - if (null === $this->swaggerUiAction) { - @trigger_error(sprintf('The use of "%s" is deprecated since API Platform 2.6, use "%s" instead.', __CLASS__, OpenApiSwaggerUiAction::class), \E_USER_DEPRECATED); - } - - if (\is_array($formats)) { - $this->formats = $formats; - - return; - } - - @trigger_error(sprintf('Passing an array or an instance of "%s" as 5th parameter of the constructor of "%s" is deprecated since API Platform 2.5, pass an array instead', FormatsProviderInterface::class, __CLASS__), \E_USER_DEPRECATED); - $this->formatsProvider = $formats; - } - - public function __invoke(Request $request) - { - if ($this->swaggerUiAction) { - return $this->swaggerUiAction->__invoke($request); - } - - $attributes = RequestAttributesExtractor::extractAttributes($request); - - // BC check to be removed in 3.0 - if (null === $this->formatsProvider) { - $formats = $attributes ? $this - ->resourceMetadataFactory - ->create($attributes['resource_class']) - ->getOperationAttribute($attributes, 'output_formats', [], true) : $this->formats; - } else { - $formats = $this->formatsProvider->getFormatsFromAttributes($attributes); - } - - $documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version); - - return new Response($this->twig->render('@ApiPlatform/SwaggerUi/index.html.twig', $this->getContext($request, $documentation) + ['formats' => $formats])); - } - - /** - * Gets the base Twig context. - */ - private function getContext(Request $request, Documentation $documentation): array - { - $context = [ - 'title' => $this->title, - 'description' => $this->description, - 'showWebby' => $this->showWebby, - 'swaggerUiEnabled' => $this->swaggerUiEnabled, - 'reDocEnabled' => $this->reDocEnabled, - 'graphqlEnabled' => $this->graphqlEnabled, - 'graphiQlEnabled' => $this->graphiQlEnabled, - 'graphQlPlaygroundEnabled' => $this->graphQlPlaygroundEnabled, - 'assetPackage' => $this->assetPackage, - ]; - - $swaggerContext = ['spec_version' => $request->query->getInt('spec_version', $this->swaggerVersions[0] ?? 2)]; - if ('' !== $baseUrl = $request->getBaseUrl()) { - $swaggerContext['base_url'] = $baseUrl; - } - - $swaggerData = [ - 'url' => $this->urlGenerator->generate('api_doc', ['format' => 'json']), - 'spec' => $this->normalizer->normalize($documentation, 'json', $swaggerContext), - 'extraConfiguration' => $this->swaggerUiExtraConfiguration, - ]; - - $swaggerData['oauth'] = [ - 'enabled' => $this->oauthEnabled, - 'clientId' => $this->oauthClientId, - 'clientSecret' => $this->oauthClientSecret, - 'pkce' => $this->oauthPkce, - 'type' => $this->oauthType, - 'flow' => $this->oauthFlow, - 'tokenUrl' => $this->oauthTokenUrl, - 'authorizationUrl' => $this->oauthAuthorizationUrl, - 'scopes' => $this->oauthScopes, - ]; - - if ($request->isMethodSafe() && null !== $resourceClass = $request->attributes->get('_api_resource_class')) { - $swaggerData['id'] = $request->attributes->get('id'); - $swaggerData['queryParameters'] = $request->query->all(); - - $metadata = $this->resourceMetadataFactory->create($resourceClass); - $swaggerData['shortName'] = $metadata instanceof ResourceMetadata ? $metadata->getShortName() : $metadata[0]->getShortName(); - - if (null !== $collectionOperationName = $request->attributes->get('_api_collection_operation_name')) { - $swaggerData['operationId'] = sprintf('%s%sCollection', $collectionOperationName, ucfirst($swaggerData['shortName'])); - } elseif (null !== $itemOperationName = $request->attributes->get('_api_item_operation_name')) { - $swaggerData['operationId'] = sprintf('%s%sItem', $itemOperationName, ucfirst($swaggerData['shortName'])); - } elseif (null !== $subresourceOperationContext = $request->attributes->get('_api_subresource_context')) { - $swaggerData['operationId'] = $subresourceOperationContext['operationId']; - } - - [$swaggerData['path'], $swaggerData['method']] = $this->getPathAndMethod($swaggerData); - } - - return $context + ['swagger_data' => $swaggerData]; - } - - private function getPathAndMethod(array $swaggerData): array - { - foreach ($swaggerData['spec']['paths'] as $path => $operations) { - foreach ($operations as $method => $operation) { - if ($operation['operationId'] === $swaggerData['operationId']) { - return [$path, $method]; - } - } - } - - throw new RuntimeException(sprintf('The operation "%s" cannot be found in the Swagger specification.', $swaggerData['operationId'])); - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/ApiPlatformBundle.php b/src/Core/Bridge/Symfony/Bundle/ApiPlatformBundle.php deleted file mode 100644 index f766d5ca6ac..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/ApiPlatformBundle.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle; - -class_exists(\ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class); - -if (false) { - final class ApiPlatformBundle extends \ApiPlatform\Symfony\Bundle\ApiPlatformBundle - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php b/src/Core/Bridge/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php deleted file mode 100644 index 8b8eedc7b3b..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\ArgumentResolver; - -class_exists(\ApiPlatform\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver::class); - -if (false) { - final class PayloadArgumentResolver extends \ApiPlatform\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php b/src/Core/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php deleted file mode 100644 index 5cc4c49cb6d..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\CacheWarmer; - -class_exists(\ApiPlatform\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer::class); - -if (false) { - final class CachePoolClearerCacheWarmer extends \ApiPlatform\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Command/GraphQlExportCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/GraphQlExportCommand.php deleted file mode 100644 index 3cbf77c8e19..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Command/GraphQlExportCommand.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\Command; - -class_exists(\ApiPlatform\Symfony\Bundle\Command\GraphQlExportCommand::class); - -if (false) { - class GraphQlExportCommand extends \ApiPlatform\Symfony\Bundle\Command\GraphQlExportCommand - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Command/OpenApiCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/OpenApiCommand.php deleted file mode 100644 index d35c3c7216f..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Command/OpenApiCommand.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\Command; - -class_exists(\ApiPlatform\Symfony\Bundle\Command\OpenApiCommand::class); - -if (false) { - final class OpenApiCommand extends \ApiPlatform\Symfony\Bundle\Command\OpenApiCommand - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php deleted file mode 100644 index 9666b5fa5b2..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Command/SwaggerCommand.php +++ /dev/null @@ -1,118 +0,0 @@ - - * - * 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\Bundle\Command; - -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidOptionException; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Yaml\Yaml; - -/** - * Console command to dump Swagger API documentations. - * - * @author Amrouche Hamza - */ -final class SwaggerCommand extends Command -{ - protected static $defaultName = 'api:swagger:export'; - - private $normalizer; - private $resourceNameCollectionFactory; - private $apiTitle; - private $apiDescription; - private $apiVersion; - private $apiFormats; - private $swaggerVersions; - private $legacyMode; - - /** - * @param int[] $swaggerVersions - */ - public function __construct(NormalizerInterface $normalizer, ResourceNameCollectionFactoryInterface $resourceNameCollection, string $apiTitle, string $apiDescription, string $apiVersion, array $apiFormats = null, array $swaggerVersions = [2, 3], bool $legacyMode = false) - { - $this->normalizer = $normalizer; - $this->resourceNameCollectionFactory = $resourceNameCollection; - $this->apiTitle = $apiTitle; - $this->apiDescription = $apiDescription; - $this->apiVersion = $apiVersion; - $this->apiFormats = $apiFormats; - $this->swaggerVersions = $swaggerVersions; - $this->legacyMode = $legacyMode; - - if (null !== $apiFormats) { - @trigger_error(sprintf('Passing a 6th parameter to the constructor of "%s" is deprecated since API Platform 2.5', __CLASS__), \E_USER_DEPRECATED); - } - - parent::__construct(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('Dump the Swagger v2 documentation') - ->addOption('yaml', 'y', InputOption::VALUE_NONE, 'Dump the documentation in YAML') - ->addOption('spec-version', null, InputOption::VALUE_OPTIONAL, sprintf('OpenAPI version to use (%s)', implode(' or ', $this->swaggerVersions)), (string) ($this->swaggerVersions[0] ?? 2)) - ->addOption('output', 'o', InputOption::VALUE_OPTIONAL, 'Write output to file') - ->addOption('api-gateway', null, InputOption::VALUE_NONE, 'API Gateway compatibility'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - /** @var string $version */ - $version = $input->getOption('spec-version'); - - if (!\in_array((int) $version, $this->swaggerVersions, true)) { - throw new InvalidOptionException(sprintf('This tool only supports versions %s of the OpenAPI specification ("%s" given).', implode(', ', $this->swaggerVersions), $version)); - } - - if (3 === (int) $version) { - @trigger_error('The command "api:swagger:export" is deprecated for the spec version 3 use "api:openapi:export".', \E_USER_DEPRECATED); - } - - if (!$this->legacyMode) { - @trigger_error('The command "api:swagger:export" is using pre-2.7 metadata, new metadata will not appear, use "api:openapi:export" instead.', \E_USER_DEPRECATED); - } - - $documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->apiTitle, $this->apiDescription, $this->apiVersion, $this->apiFormats); - $data = $this->normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['spec_version' => (int) $version, ApiGatewayNormalizer::API_GATEWAY => $input->getOption('api-gateway')]); - $content = $input->getOption('yaml') - ? Yaml::dump($data, 10, 2, Yaml::DUMP_OBJECT_AS_MAP | Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK) - : (json_encode($data, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES) ?: ''); - - if (!empty($filename = $input->getOption('output')) && \is_string($filename)) { - file_put_contents($filename, $content); - $io->success(sprintf('Data written to %s (specification version %s).', $filename, $version)); - } else { - $output->writeln($content); - } - - return 0; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php b/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php deleted file mode 100644 index 6df0eacea29..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommand.php +++ /dev/null @@ -1,218 +0,0 @@ - - * - * 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\Bundle\Command; - -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Upgrade\ColorConsoleDiffFormatter; -use ApiPlatform\Core\Upgrade\SubresourceTransformer; -use ApiPlatform\Core\Upgrade\UpgradeApiResourceVisitor; -use ApiPlatform\Core\Upgrade\UpgradeApiSubresourceVisitor; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use Doctrine\Common\Annotations\AnnotationReader; -use PhpParser\Lexer\Emulative; -use PhpParser\NodeTraverser; -use PhpParser\Parser\Php7; -use PhpParser\PrettyPrinter\Standard; -use SebastianBergmann\Diff\Differ; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -final class UpgradeApiResourceCommand extends Command -{ - protected static $defaultName = 'api:upgrade-resource'; - - private $resourceNameCollectionFactory; - private $resourceMetadataFactory; - private $subresourceOperationFactory; - private $subresourceTransformer; - private $reader; - private $identifiersExtractor; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, SubresourceOperationFactoryInterface $subresourceOperationFactory, SubresourceTransformer $subresourceTransformer, IdentifiersExtractorInterface $identifiersExtractor, AnnotationReader $reader = null) - { - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->subresourceOperationFactory = $subresourceOperationFactory; - $this->subresourceTransformer = $subresourceTransformer; - $this->identifiersExtractor = $identifiersExtractor; - $this->reader = $reader; - - parent::__construct(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('The "api:upgrade-resource" command upgrades your API Platform metadata from versions below 2.6 to the new metadata from versions above 2.7. -Once you executed this script, make sure that the "metadata_backward_compatibility_layer" flag is set to "false" in the API Platform configuration. -This will remove "ApiPlatform\Core\Annotation\ApiResource" annotation/attribute and use the "ApiPlatform\Metadata\ApiResource" attribute instead.') - ->addOption('dry-run', '-d', InputOption::VALUE_NEGATABLE, 'Dry mode outputs a diff instead of writing files.', true) - ->addOption('silent', '-s', InputOption::VALUE_NONE, 'Silent output.') - ->addOption('force', '-f', InputOption::VALUE_NONE, 'Writes the files in place and skips PHP version check.'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - if (!$input->getOption('force') && \PHP_VERSION_ID < 80100) { - $output->write('The new metadata system only works with PHP 8.1 and above.'); - - return Command::INVALID; - } - - $subresources = $this->getSubresources(); - - $prettyPrinter = new Standard(); - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - continue; - } - - $lexer = new Emulative([ - 'usedAttributes' => [ - 'comments', - 'startLine', - 'endLine', - 'startTokenPos', - 'endTokenPos', - ], - ]); - $parser = new Php7($lexer); - $fileName = (new \ReflectionClass($resourceClass))->getFilename(); - - $traverser = new NodeTraverser(); - [$attribute, $isAnnotation] = $this->readApiResource($resourceClass); - - if (!$attribute) { - continue; - } - - $traverser->addVisitor(new UpgradeApiResourceVisitor($attribute, $isAnnotation, $this->identifiersExtractor, $resourceClass)); - - if (isset($subresources[$resourceClass])) { - $referenceType = $resourceMetadata->getAttribute('url_generation_strategy'); - foreach ($subresources[$resourceClass] as $subresourceMetadata) { - $traverser->addVisitor(new UpgradeApiSubresourceVisitor($subresourceMetadata, $referenceType)); - } - } - - $oldCode = file_get_contents($fileName); - $oldStmts = $parser->parse($oldCode); - $oldTokens = $lexer->getTokens(); - - $newStmts = $traverser->traverse($oldStmts); - $newCode = $prettyPrinter->printFormatPreserving($newStmts, $oldStmts, $oldTokens); - - if (!$input->getOption('force') && $input->getOption('dry-run')) { - if ($input->getOption('silent')) { - continue; - } - - $this->printDiff($oldCode, $newCode, $output); - continue; - } - - file_put_contents($fileName, $newCode); - } - - return Command::SUCCESS; - } - - /** - * This computes a local cache with resource classes having subresources. - * We first loop over all the classes and re-map the metadata on the correct Resource class. - * Then we transform the ApiSubresource to an ApiResource class. - */ - private function getSubresources(): array - { - $localCache = []; - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - try { - new \ReflectionClass($resourceClass); - } catch (\Exception $e) { - continue; - } - - if (!isset($localCache[$resourceClass])) { - $localCache[$resourceClass] = []; - } - - foreach ($this->subresourceOperationFactory->create($resourceClass) as $subresourceMetadata) { - if (!isset($localCache[$subresourceMetadata['resource_class']])) { - $localCache[$subresourceMetadata['resource_class']] = []; - } - - foreach ($localCache[$subresourceMetadata['resource_class']] as $currentSubresourceMetadata) { - if ($currentSubresourceMetadata['path'] === $subresourceMetadata['path']) { - continue 2; - } - } - $localCache[$subresourceMetadata['resource_class']][] = $subresourceMetadata; - } - } - - // Compute URI variables - foreach ($localCache as $class => $subresources) { - if (!$subresources) { - unset($localCache[$class]); - continue; - } - - foreach ($subresources as $i => $subresourceMetadata) { - $localCache[$class][$i]['uri_variables'] = $this->subresourceTransformer->toUriVariables($subresourceMetadata); - } - } - - return $localCache; - } - - private function printDiff(string $oldCode, string $newCode, OutputInterface $output): void - { - $consoleFormatter = new ColorConsoleDiffFormatter(); - $differ = new Differ(); - $diff = $differ->diff($oldCode, $newCode); - $output->write($consoleFormatter->format($diff)); - } - - /** - * @return array[ApiResource, bool] - */ - private function readApiResource(string $resourceClass): array - { - $reflectionClass = new \ReflectionClass($resourceClass); - - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionClass->getAttributes(ApiResource::class)) { - return [$attributes[0]->newInstance(), false]; - } - - if (null === $this->reader) { - throw new \RuntimeException(sprintf('Resource "%s" not found.', $resourceClass)); - } - - return [$this->reader->getClassAnnotation($reflectionClass, ApiResource::class), true]; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php b/src/Core/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php deleted file mode 100644 index 2b7c993cf5d..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php +++ /dev/null @@ -1,194 +0,0 @@ - - * - * 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\Bundle\DataCollector; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister\TraceableChainDataPersister; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainCollectionDataProvider; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainItemDataProvider; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainSubresourceDataProvider; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\RequestAttributesExtractor; -use PackageVersions\Versions; -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollector; - -/** - * @author Julien DENIAU - * @author Anthony GRASSIOT - */ -final class RequestDataCollector extends DataCollector -{ - private $metadataFactory; - private $filterLocator; - private $collectionDataProvider; - private $itemDataProvider; - private $subresourceDataProvider; - private $dataPersister; - - public function __construct(ResourceMetadataFactoryInterface $metadataFactory, ContainerInterface $filterLocator, CollectionDataProviderInterface $collectionDataProvider = null, ItemDataProviderInterface $itemDataProvider = null, SubresourceDataProviderInterface $subresourceDataProvider = null, DataPersisterInterface $dataPersister = null) - { - $this->metadataFactory = $metadataFactory; - $this->filterLocator = $filterLocator; - $this->collectionDataProvider = $collectionDataProvider; - $this->itemDataProvider = $itemDataProvider; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->dataPersister = $dataPersister; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $counters = ['ignored_filters' => 0]; - $resourceClass = $request->attributes->get('_api_resource_class'); - $resourceMetadata = $resourceClass ? $this->metadataFactory->create($resourceClass) : null; - - $filters = []; - foreach ($resourceMetadata ? $resourceMetadata->getAttribute('filters', []) : [] as $id) { - if ($this->filterLocator->has($id)) { - $filters[$id] = \get_class($this->filterLocator->get($id)); - continue; - } - - $filters[$id] = null; - ++$counters['ignored_filters']; - } - - $requestAttributes = RequestAttributesExtractor::extractAttributes($request); - if (isset($requestAttributes['previous_data'])) { - $requestAttributes['previous_data'] = $this->cloneVar($requestAttributes['previous_data']); - } - - $this->data = [ - 'resource_class' => $resourceClass, - 'resource_metadata' => $resourceMetadata ? $this->cloneVar($resourceMetadata) : null, - 'acceptable_content_types' => $request->getAcceptableContentTypes(), - 'filters' => $filters, - 'counters' => $counters, - 'dataProviders' => [], - 'dataPersisters' => ['responses' => []], - 'request_attributes' => $requestAttributes, - ]; - - if ($this->collectionDataProvider instanceof TraceableChainCollectionDataProvider) { - $this->data['dataProviders']['collection'] = [ - 'context' => $this->cloneVar($this->collectionDataProvider->getContext()), - 'responses' => $this->collectionDataProvider->getProvidersResponse(), - ]; - } - - if ($this->itemDataProvider instanceof TraceableChainItemDataProvider) { - $this->data['dataProviders']['item'] = [ - 'context' => $this->cloneVar($this->itemDataProvider->getContext()), - 'responses' => $this->itemDataProvider->getProvidersResponse(), - ]; - } - - if ($this->subresourceDataProvider instanceof TraceableChainSubresourceDataProvider) { - $this->data['dataProviders']['subresource'] = [ - 'context' => $this->cloneVar($this->subresourceDataProvider->getContext()), - 'responses' => $this->subresourceDataProvider->getProvidersResponse(), - ]; - } - - if ($this->dataPersister instanceof TraceableChainDataPersister) { - $this->data['dataPersisters']['responses'] = $this->dataPersister->getPersistersResponse(); - } - } - - public function getAcceptableContentTypes(): array - { - return $this->data['acceptable_content_types'] ?? []; - } - - public function getResourceClass() - { - return $this->data['resource_class'] ?? null; - } - - public function getResourceMetadata() - { - return $this->data['resource_metadata'] ?? null; - } - - public function getRequestAttributes(): array - { - return $this->data['request_attributes'] ?? []; - } - - public function getFilters(): array - { - return $this->data['filters'] ?? []; - } - - public function getCounters(): array - { - return $this->data['counters'] ?? []; - } - - public function getCollectionDataProviders(): array - { - return $this->data['dataProviders']['collection'] ?? ['context' => [], 'responses' => []]; - } - - public function getItemDataProviders(): array - { - return $this->data['dataProviders']['item'] ?? ['context' => [], 'responses' => []]; - } - - public function getSubresourceDataProviders(): array - { - return $this->data['dataProviders']['subresource'] ?? ['context' => [], 'responses' => []]; - } - - public function getDataPersisters(): array - { - return $this->data['dataPersisters'] ?? ['responses' => []]; - } - - public function getVersion(): ?string - { - if (!class_exists(Versions::class)) { - return null; - } - - $version = Versions::getVersion('api-platform/core'); - preg_match('/^v(.*?)@/', $version, $output); - - return $output[1] ?? strtok($version, '@'); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'api_platform.data_collector.request'; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = []; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersister.php b/src/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersister.php deleted file mode 100644 index a85a79f2219..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersister.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * 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\Bundle\DataPersister; - -use ApiPlatform\Core\DataPersister\ChainDataPersister; -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataPersister\ResumableDataPersisterInterface; - -/** - * @author Anthony GRASSIOT - */ -final class TraceableChainDataPersister implements ContextAwareDataPersisterInterface -{ - private $persisters = []; - private $persistersResponse = []; - private $decorated; - - public function __construct(DataPersisterInterface $dataPersister) - { - if ($dataPersister instanceof ChainDataPersister) { - $this->decorated = $dataPersister; - $this->persisters = $dataPersister->persisters; - } - } - - public function getPersistersResponse(): array - { - return $this->persistersResponse; - } - - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - return $this->decorated->supports($data, $context); - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []) - { - $this->tracePersisters($data, $context); - - return $this->decorated->persist($data, $context); - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []) - { - $this->tracePersisters($data, $context); - - return $this->decorated->remove($data, $context); - } - - private function tracePersisters($data, array $context = []) - { - $found = false; - foreach ($this->persisters as $persister) { - if ( - ($this->persistersResponse[\get_class($persister)] = $found ? false : $persister->supports($data, $context)) - && - !($persister instanceof ResumableDataPersisterInterface && $persister->resumable()) && !$found - ) { - $found = true; - } - } - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataProvider.php b/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataProvider.php deleted file mode 100644 index 836270f040f..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataProvider.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * 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\Bundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainCollectionDataProvider; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictDataProviderTrait; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * @author Anthony GRASSIOT - */ -final class TraceableChainCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - use RestrictDataProviderTrait; - - private $context = []; - private $providersResponse = []; - - public function __construct(CollectionDataProviderInterface $collectionDataProvider) - { - if ($collectionDataProvider instanceof ChainCollectionDataProvider) { - $this->dataProviders = $collectionDataProvider->dataProviders; - } - } - - public function getProvidersResponse(): array - { - return $this->providersResponse; - } - - public function getContext(): array - { - return $this->context; - } - - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - $this->context = $context; - $results = null; - $match = false; - - foreach ($this->dataProviders as $dataProvider) { - $this->providersResponse[\get_class($dataProvider)] = $match ? null : false; - if ($match) { - continue; - } - try { - if ($dataProvider instanceof RestrictedDataProviderInterface - && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - $results = $dataProvider->getCollection($resourceClass, $operationName, $context); - $this->providersResponse[\get_class($dataProvider)] = $match = true; - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return $results ?? []; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataProvider.php b/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataProvider.php deleted file mode 100644 index a3116cf882e..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataProvider.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * 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\Bundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainItemDataProvider; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictDataProviderTrait; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * @author Anthony GRASSIOT - */ -final class TraceableChainItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - use RestrictDataProviderTrait; - - private $context = []; - private $providersResponse = []; - - public function __construct(ItemDataProviderInterface $itemDataProvider) - { - if ($itemDataProvider instanceof ChainItemDataProvider) { - $this->dataProviders = $itemDataProvider->dataProviders; - } - } - - public function getProvidersResponse(): array - { - return $this->providersResponse; - } - - public function getContext(): array - { - return $this->context; - } - - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - $this->context = $context; - $match = false; - $result = null; - - foreach ($this->dataProviders as $dataProvider) { - $this->providersResponse[\get_class($dataProvider)] = $match ? null : false; - if ($match) { - continue; - } - try { - if ($dataProvider instanceof RestrictedDataProviderInterface - && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - $identifier = $id; - if (!$dataProvider instanceof DenormalizedIdentifiersAwareItemDataProviderInterface && $identifier && \is_array($identifier)) { - if (\count($identifier) > 1) { - @trigger_error(sprintf('Receiving "$id" as non-array in an item data provider is deprecated in 2.3 in favor of implementing "%s".', DenormalizedIdentifiersAwareItemDataProviderInterface::class), \E_USER_DEPRECATED); - $identifier = http_build_query($identifier, '', ';'); - } else { - $identifier = current($identifier); - } - } - - $result = $dataProvider->getItem($resourceClass, $identifier, $operationName, $context); - $this->providersResponse[\get_class($dataProvider)] = $match = true; - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" is deprecated in favor of implementing "%s"', \get_class($e), RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return $result; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataProvider.php b/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataProvider.php deleted file mode 100644 index 867375b4785..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataProvider.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * 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\Bundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainSubresourceDataProvider; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * @author Anthony GRASSIOT - */ -final class TraceableChainSubresourceDataProvider implements SubresourceDataProviderInterface -{ - private $dataProviders = []; - private $context = []; - private $providersResponse = []; - - public function __construct(SubresourceDataProviderInterface $subresourceDataProvider) - { - if ($subresourceDataProvider instanceof ChainSubresourceDataProvider) { - $this->dataProviders = $subresourceDataProvider->dataProviders; - } - } - - public function getProvidersResponse(): array - { - return $this->providersResponse; - } - - public function getContext(): array - { - return $this->context; - } - - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - $this->context = $context; - $match = false; - $result = null; - - foreach ($this->dataProviders as $dataProvider) { - $this->providersResponse[\get_class($dataProvider)] = $match ? null : false; - if ($match) { - continue; - } - try { - if ($dataProvider instanceof RestrictedDataProviderInterface && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - $result = $dataProvider->getSubresource($resourceClass, $identifiers, $context, $operationName); - $this->providersResponse[\get_class($dataProvider)] = $match = true; - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - if ($match) { - return $result; - } - - return ($context['collection'] ?? false) ? [] : null; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php deleted file mode 100644 index 3f87256cfa1..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class); - -if (false) { - final class ApiPlatformExtension extends \ApiPlatform\Symfony\Bundle\DependencyInjection\ApiPlatformExtension - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php deleted file mode 100644 index 155f4b25721..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass::class); - -if (false) { - final class AnnotationFilterPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php deleted file mode 100644 index 1ade44a2bb3..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass::class); - -if (false) { - final class AuthenticatorManagerPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php deleted file mode 100644 index 0eb98670e35..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass::class); - -if (false) { - final class DataProviderPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php deleted file mode 100644 index 0a416411a9c..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass::class); - -if (false) { - final class DeprecateMercurePublisherPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php deleted file mode 100644 index 21403760cdf..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass::class); - -if (false) { - final class ElasticsearchClientPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php deleted file mode 100644 index d38e09b6b88..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass::class); - -if (false) { - final class FilterPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php deleted file mode 100644 index aa64933292b..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass::class); - -if (false) { - final class GraphQlMutationResolverPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php deleted file mode 100644 index 69f3eda55ba..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass::class); - -if (false) { - final class GraphQlQueryResolverPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php deleted file mode 100644 index fa6edee6809..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass::class); - -if (false) { - final class GraphQlTypePass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php deleted file mode 100644 index ae891b50bff..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass::class); - -if (false) { - final class MetadataAwareNameConverterPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php deleted file mode 100644 index ada12cd16c4..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection\Compiler; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass::class); - -if (false) { - final class TestClientPass extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php deleted file mode 100644 index 39a8c39c4b2..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\DependencyInjection; - -class_exists(\ApiPlatform\Symfony\Bundle\DependencyInjection\Configuration::class); - -if (false) { - final class Configuration extends \ApiPlatform\Symfony\Bundle\DependencyInjection\Configuration - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php b/src/Core/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php deleted file mode 100644 index 934dad77e94..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\EventListener; - -class_exists(\ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener::class); - -if (false) { - final class SwaggerUiListener extends \ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php b/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php deleted file mode 100644 index 2fb7f4ace0c..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\SwaggerUi; - -class_exists(\ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction::class); - -if (false) { - final class SwaggerUiAction extends \ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php b/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php deleted file mode 100644 index 729a84e3298..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\SwaggerUi; - -class_exists(\ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiContext::class); - -if (false) { - final class SwaggerUiContext extends \ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiContext - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php b/src/Core/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php deleted file mode 100644 index a616e27ec37..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Bundle\Test; - -class_exists(\ApiPlatform\Symfony\Bundle\Test\ApiTestAssertionsTrait::class); - -if (false) { - trait ApiTestAssertionsTrait - { - use \ApiPlatform\Symfony\Bundle\Test\ApiTestAssertionsTrait; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/ApiTestCase.php b/src/Core/Bridge/Symfony/Bundle/Test/ApiTestCase.php deleted file mode 100644 index d2835b4fe54..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/ApiTestCase.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\Test; - -class_exists(\ApiPlatform\Symfony\Bundle\Test\ApiTestCase::class); - -if (false) { - class ApiTestCase extends \ApiPlatform\Symfony\Bundle\Test\ApiTestCase - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Client.php b/src/Core/Bridge/Symfony/Bundle/Test/Client.php deleted file mode 100644 index 4399df64840..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Client.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\Test; - -class_exists(\ApiPlatform\Symfony\Bundle\Test\Client::class); - -if (false) { - final class Client extends \ApiPlatform\Symfony\Bundle\Test\Client - { - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php deleted file mode 100644 index a55455514fb..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * 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\Bundle\Test\Constraint; - -use PHPUnit\Runner\Version; -use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure; -use SebastianBergmann\Comparator\ComparisonFailure as LegacyComparisonFailure; - -if (!class_exists(ComparisonFailure::class)) { - class_alias(LegacyComparisonFailure::class, 'PHPUnit\SebastianBergmann\Comparator\ComparisonFailure'); -} - -trigger_deprecation('api-platform/core', '2.7', sprintf('The class %s is deprecated, use %s instead.', 'ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset', 'ApiPlatform\Symfony\Bundle\Test\Constraint')); - -// Aliases as string to avoid loading the class -if (\PHP_VERSION_ID >= 80000 || (float) Version::series() >= 9) { - class_alias('ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetV9', 'ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset'); -} else { - class_alias('ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetLegacy', 'ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset'); -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php deleted file mode 100644 index 0911672ce01..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\Bundle\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; - -/** - * Is used for phpunit < 8. - * - * @internal - */ -final class ArraySubsetLegacy extends Constraint -{ - use ArraySubsetTrait; - - /** - * {@inheritdoc} - */ - public function evaluate($other, $description = '', $returnResult = false) - { - return $this->_evaluate($other, $description, $returnResult); - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php deleted file mode 100644 index cebb2217c31..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * 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\Bundle\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure; - -/** - * Constraint that asserts that the array it is evaluated for has a specified subset. - * - * Uses array_replace_recursive() to check if a key value subset is part of the - * subject array. - * - * Imported from dms/phpunit-arraysubset-asserts, because the original constraint has been deprecated. - * - * @copyright Sebastian Bergmann - * @copyright Rafael Dohms - * - * @see https://github.com/sebastianbergmann/phpunit/issues/3494 - */ -trait ArraySubsetTrait -{ - private $subset; - private $strict; - - public function __construct(iterable $subset, bool $strict = false) - { - $this->strict = $strict; - $this->subset = $subset; - } - - private function _evaluate($other, string $description = '', bool $returnResult = false): ?bool - { - // type cast $other & $this->subset as an array to allow - // support in standard array functions. - $other = $this->toArray($other); - $this->subset = $this->toArray($this->subset); - $patched = array_replace_recursive($other, $this->subset); - if ($this->strict) { - $result = $other === $patched; - } else { - $result = $other == $patched; - } - if ($returnResult) { - return $result; - } - if ($result) { - return null; - } - - $f = new ComparisonFailure( - $patched, - $other, - var_export($patched, true), - var_export($other, true) - ); - $this->fail($other, $description, $f); - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'has the subset '.$this->exporter()->export($this->subset); - } - - /** - * {@inheritdoc} - */ - protected function failureDescription($other): string - { - return 'an array '.$this->toString(); - } - - private function toArray(iterable $other): array - { - if (\is_array($other)) { - return $other; - } - if ($other instanceof \ArrayObject) { - return $other->getArrayCopy(); - } - - return iterator_to_array($other); - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php deleted file mode 100644 index ccb16def0e6..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\Bundle\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; - -/** - * Is used for phpunit >= 9. - * - * @internal - */ -final class ArraySubsetV9 extends Constraint -{ - use ArraySubsetTrait; - - /** - * {@inheritdoc} - */ - public function evaluate($other, string $description = '', bool $returnResult = false): ?bool - { - return $this->_evaluate($other, $description, $returnResult); - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php b/src/Core/Bridge/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php deleted file mode 100644 index 910d3990a87..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Constraint/MatchesJsonSchema.php +++ /dev/null @@ -1,116 +0,0 @@ - - * - * 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\Bundle\Test\Constraint; - -use JsonSchema\Validator; -use PHPUnit\Framework\Constraint\Constraint; - -/** - * Asserts that a JSON document matches a given JSON Schema. - * - * @author Kévin Dunglas - * - * @experimental - */ -final class MatchesJsonSchema extends Constraint -{ - /** - * @var object|array - */ - private $schema; - private $checkMode; - - /** - * @param object|array|string $schema - */ - public function __construct($schema, ?int $checkMode = null) - { - $this->schema = \is_string($schema) ? json_decode($schema) : $schema; - $this->checkMode = $checkMode; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'matches the provided JSON Schema'; - } - - /** - * {@inheritdoc} - */ - protected function matches($other): bool - { - if (!class_exists(Validator::class)) { - throw new \LogicException('The "justinrainbow/json-schema" library must be installed to use "assertMatchesJsonSchema()". Try running "composer require --dev justinrainbow/json-schema".'); - } - - $other = $this->normalizeJson($other); - - $validator = new Validator(); - $validator->validate($other, $this->schema, $this->checkMode); - - return $validator->isValid(); - } - - /** - * {@inheritdoc} - */ - protected function additionalFailureDescription($other): string - { - $other = $this->normalizeJson($other); - - $validator = new Validator(); - $validator->validate($other, $this->schema, $this->checkMode); - - $errors = []; - foreach ($validator->getErrors() as $error) { - $property = $error['property'] ? $error['property'].': ' : ''; - $errors[] = $property.$error['message']; - } - - return implode("\n", $errors); - } - - /** - * Normalizes a JSON document. - * - * Specifically, we should ensure that: - * 1. a JSON object is represented as a PHP object, not as an associative array. - * - * @param mixed $document - */ - private function normalizeJson($document) - { - if (\is_scalar($document) || \is_object($document)) { - return $document; - } - - if (!\is_array($document)) { - throw new \InvalidArgumentException('Document must be scalar, array or object.'); - } - - $document = json_encode($document); - if (!\is_string($document)) { - throw new \UnexpectedValueException('JSON encode failed.'); - } - $document = json_decode($document); - if (!\is_array($document) && !\is_object($document)) { - throw new \UnexpectedValueException('JSON decode failed.'); - } - - return $document; - } -} diff --git a/src/Core/Bridge/Symfony/Bundle/Test/Response.php b/src/Core/Bridge/Symfony/Bundle/Test/Response.php deleted file mode 100644 index d1b77770bdf..00000000000 --- a/src/Core/Bridge/Symfony/Bundle/Test/Response.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Bundle\Test; - -class_exists(\ApiPlatform\Symfony\Bundle\Test\Response::class); - -if (false) { - final class Response extends \ApiPlatform\Symfony\Bundle\Test\Response - { - } -} diff --git a/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php b/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php deleted file mode 100644 index c1675e87d94..00000000000 --- a/src/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizer.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * 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\Identifier\Normalizer; - -use ApiPlatform\Exception\InvalidIdentifierException; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Uid\Ulid; - -/** - * Denormalizes an ULID string to an instance of Symfony\Component\Uid\Ulid. - */ -final class UlidNormalizer implements DenormalizerInterface -{ - /** - * {@inheritdoc} - * - * @return mixed - */ - public function denormalize($data, $class, $format = null, array $context = []) - { - try { - return Ulid::fromString($data); - } catch (\InvalidArgumentException $e) { - throw new InvalidIdentifierException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return \is_string($data) && is_a($type, Ulid::class, true); - } -} diff --git a/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php b/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php deleted file mode 100644 index a51f074a316..00000000000 --- a/src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * 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\Identifier\Normalizer; - -use ApiPlatform\Exception\InvalidIdentifierException; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Uid\Uuid; - -/** - * Denormalizes an UUID string to an instance of Symfony\Component\Uid\Uuid. - */ -final class UuidNormalizer implements DenormalizerInterface -{ - /** - * {@inheritdoc} - * - * @return mixed - */ - public function denormalize($data, $class, $format = null, array $context = []) - { - try { - return Uuid::fromString($data); - } catch (\InvalidArgumentException|\ValueError $e) { // catching ValueError will not be necessary anymore when https://github.com/symfony/symfony/pull/39636 will be released - throw new InvalidIdentifierException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return \is_string($data) && is_a($type, Uuid::class, true); - } -} diff --git a/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php b/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php deleted file mode 100644 index 13daf7d6a74..00000000000 --- a/src/Core/Bridge/Symfony/Maker/MakeDataPersister.php +++ /dev/null @@ -1,116 +0,0 @@ - - * - * 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\Maker; - -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use Symfony\Bundle\MakerBundle\ConsoleStyle; -use Symfony\Bundle\MakerBundle\DependencyBuilder; -use Symfony\Bundle\MakerBundle\Generator; -use Symfony\Bundle\MakerBundle\InputConfiguration; -use Symfony\Bundle\MakerBundle\Maker\AbstractMaker; -use Symfony\Bundle\MakerBundle\Str; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Question\Question; - -final class MakeDataPersister extends AbstractMaker -{ - private $resourceNameCollection; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollection) - { - $this->resourceNameCollection = $resourceNameCollection; - } - - /** - * {@inheritdoc} - */ - public static function getCommandName(): string - { - return 'make:data-persister'; - } - - /** - * {@inheritdoc} - */ - public static function getCommandDescription(): string - { - return 'Creates an API Platform data persister'; - } - - /** - * {@inheritdoc} - */ - public function configureCommand(Command $command, InputConfiguration $inputConfig) - { - $command - ->addArgument('name', InputArgument::OPTIONAL, 'Choose a class name for your data persister (e.g. AwesomeDataPersister)') - ->addArgument('resource-class', InputArgument::OPTIONAL, 'Choose a Resource class') - ->setHelp(file_get_contents(__DIR__.'/Resources/help/MakeDataPersister.txt')); - - $inputConfig->setArgumentAsNonInteractive('resource-class'); - } - - /** - * {@inheritdoc} - */ - public function configureDependencies(DependencyBuilder $dependencies) - { - } - - public function interact(InputInterface $input, ConsoleStyle $io, Command $command) - { - if (null === $input->getArgument('resource-class')) { - $argument = $command->getDefinition()->getArgument('resource-class'); - - $resourceClasses = $this->resourceNameCollection->create(); - - $question = new Question($argument->getDescription()); - $question->setAutocompleterValues($resourceClasses); - - $value = $io->askQuestion($question); - - $input->setArgument('resource-class', $value); - } - } - - /** - * {@inheritdoc} - */ - public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator) - { - $dataPersisterClassNameDetails = $generator->createClassNameDetails( - $input->getArgument('name'), - 'DataPersister\\' - ); - $resourceClass = $input->getArgument('resource-class'); - - $generator->generateClass( - $dataPersisterClassNameDetails->getFullName(), - __DIR__.'/Resources/skeleton/DataPersister.tpl.php', - [ - 'resource_class' => null !== $resourceClass ? Str::getShortClassName($resourceClass) : null, - 'resource_full_class_name' => $resourceClass, - ] - ); - $generator->writeChanges(); - - $this->writeSuccessMessage($io); - $io->text([ - 'Next: Open your new data persister class and start customizing it.', - 'Find the documentation at https://api-platform.com/docs/core/data-persisters/', - ]); - } -} diff --git a/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php b/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php deleted file mode 100644 index 9db71ced56f..00000000000 --- a/src/Core/Bridge/Symfony/Maker/MakeDataProvider.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * 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\Maker; - -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use Symfony\Bundle\MakerBundle\ConsoleStyle; -use Symfony\Bundle\MakerBundle\DependencyBuilder; -use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; -use Symfony\Bundle\MakerBundle\Generator; -use Symfony\Bundle\MakerBundle\InputConfiguration; -use Symfony\Bundle\MakerBundle\Maker\AbstractMaker; -use Symfony\Bundle\MakerBundle\Str; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Question\Question; - -class MakeDataProvider extends AbstractMaker -{ - private $resourceNameCollection; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollection) - { - $this->resourceNameCollection = $resourceNameCollection; - } - - /** - * {@inheritdoc} - */ - public static function getCommandName(): string - { - return 'make:data-provider'; - } - - /** - * {@inheritdoc} - */ - public static function getCommandDescription(): string - { - return 'Creates an API Platform data provider'; - } - - /** - * {@inheritdoc} - */ - public function configureCommand(Command $command, InputConfiguration $inputConfig) - { - $command - ->addArgument('name', InputArgument::OPTIONAL, 'Choose a class name for your data provider (e.g. AwesomeDataProvider)') - ->addArgument('resource-class', InputArgument::OPTIONAL, 'Choose a Resource class') - ->addOption('item-only', null, InputOption::VALUE_NONE, 'Generate only an item data provider') - ->addOption('collection-only', null, InputOption::VALUE_NONE, 'Generate only a collection data provider') - ->setHelp(file_get_contents(__DIR__.'/Resources/help/MakeDataProvider.txt')); - - $inputConfig->setArgumentAsNonInteractive('resource-class'); - } - - /** - * {@inheritdoc} - */ - public function configureDependencies(DependencyBuilder $dependencies) - { - } - - public function interact(InputInterface $input, ConsoleStyle $io, Command $command) - { - if ($input->getOption('item-only') && $input->getOption('collection-only')) { - throw new RuntimeCommandException('You should at least generate an item or a collection data provider'); - } - - if (null === $input->getArgument('resource-class')) { - $argument = $command->getDefinition()->getArgument('resource-class'); - - $question = new Question($argument->getDescription()); - $question->setAutocompleterValues($this->resourceNameCollection->create()); - - $input->setArgument('resource-class', $io->askQuestion($question)); - } - } - - /** - * {@inheritdoc} - */ - public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator) - { - $dataProviderClassNameDetails = $generator->createClassNameDetails( - $input->getArgument('name'), - 'DataProvider\\' - ); - $resourceClass = $input->getArgument('resource-class'); - - $generator->generateClass( - $dataProviderClassNameDetails->getFullName(), - __DIR__.'/Resources/skeleton/DataProvider.tpl.php', - [ - 'resource_class' => null !== $resourceClass ? Str::getShortClassName($resourceClass) : null, - 'resource_full_class_name' => $resourceClass, - 'generate_collection' => !$input->getOption('item-only'), - 'generate_item' => !$input->getOption('collection-only'), - ] - ); - $generator->writeChanges(); - - $this->writeSuccessMessage($io); - $io->text([ - 'Next: Open your new data provider class and start customizing it.', - 'Find the documentation at https://api-platform.com/docs/core/data-providers/', - ]); - } -} diff --git a/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataPersister.txt b/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataPersister.txt deleted file mode 100644 index 7afe500d462..00000000000 --- a/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataPersister.txt +++ /dev/null @@ -1,5 +0,0 @@ -The %command.name% command generates a new API Platform data persister class. - -php %command.full_name% AwesomeDataPersister - -If the argument is missing, the command will ask for the class name interactively. diff --git a/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataProvider.txt b/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataProvider.txt deleted file mode 100644 index 73064481560..00000000000 --- a/src/Core/Bridge/Symfony/Maker/Resources/help/MakeDataProvider.txt +++ /dev/null @@ -1,5 +0,0 @@ -The %command.name% command generates a new API Platform data provider class. - -php %command.full_name% AwesomeDataProvider - -If the argument is missing, the command will ask for the class name interactively. diff --git a/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataPersister.tpl.php b/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataPersister.tpl.php deleted file mode 100644 index 5ed85510a77..00000000000 --- a/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataPersister.tpl.php +++ /dev/null @@ -1,57 +0,0 @@ - - -namespace ; - -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Core\DataPersister\ResumableDataPersisterInterface; - -use ; - - -final class implements ContextAwareDataPersisterInterface, ResumableDataPersisterInterface -{ - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - - return $data instanceof ::class; // Add your custom conditions here - - return false; // Add your custom conditions here - - } - - /** - * {@inheritdoc} - */ - public function resumable(array $context = []): bool - { - return false; // Set it to true if you want to call the other data persisters - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = [])= 70200) { - echo ': object'; - }?> - - { - // Call your persistence layer to save $data - - return $data; - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []): void - { - // Call your persistence layer to delete $data - } -} diff --git a/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataProvider.tpl.php b/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataProvider.tpl.php deleted file mode 100644 index 0d8160c8589..00000000000 --- a/src/Core/Bridge/Symfony/Maker/Resources/skeleton/DataProvider.tpl.php +++ /dev/null @@ -1,64 +0,0 @@ - - -namespace ; - - -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; - - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; - -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; - -use ; - - -final class implements RestrictedDataProviderInterface -{ - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - - return ::class === $resourceClass; // Add your custom conditions here - - return false; // Add your custom conditions here - - } - - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - // Retrieve the collection from somewhere - } - - - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])= 70200) { - echo ': ?object'; - }?> - - { - // Retrieve the item from somewhere then return it or null if not found - } - -} diff --git a/src/Core/Bridge/Symfony/Messenger/ContextStamp.php b/src/Core/Bridge/Symfony/Messenger/ContextStamp.php deleted file mode 100644 index a127b3dd06f..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/ContextStamp.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Messenger; - -class_exists(\ApiPlatform\Symfony\Messenger\ContextStamp::class); - -if (false) { - final class ContextStamp extends \ApiPlatform\Symfony\Messenger\ContextStamp - { - } -} diff --git a/src/Core/Bridge/Symfony/Messenger/DataPersister.php b/src/Core/Bridge/Symfony/Messenger/DataPersister.php deleted file mode 100644 index f2b13d85a74..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/DataPersister.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * 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\Messenger; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Symfony\Messenger\DispatchTrait; -use ApiPlatform\Util\ClassInfoTrait; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Messenger\Stamp\HandledStamp; - -/** - * Dispatches the given resource using the message bus of Symfony Messenger. - * - * @experimental - * - * @author Kévin Dunglas - */ -final class DataPersister implements ContextAwareDataPersisterInterface -{ - use ClassInfoTrait; - use DispatchTrait; - - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface - */ - private $resourceMetadataFactory; - - public function __construct($resourceMetadataFactory, MessageBusInterface $messageBus) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->messageBus = $messageBus; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - } - - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - try { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($context['resource_class'] ?? $this->getObjectClass($data)); - $operation = $resourceMetadataCollection->getOperation($context['operation_name'] ?? null); - - return false !== ($operation->getMessenger() ?? false); - } catch (OperationNotFoundException $e) { - return false; - } - } - - try { - $resourceMetadata = $this->resourceMetadataFactory->create($context['resource_class'] ?? $this->getObjectClass($data)); - } catch (ResourceClassNotFoundException $e) { - return false; - } - - if (null !== $operationName = $context['collection_operation_name'] ?? $context['item_operation_name'] ?? null) { - return false !== $resourceMetadata->getTypedOperationAttribute( - $context['collection_operation_name'] ?? false ? OperationType::COLLECTION : OperationType::ITEM, - $operationName, - 'messenger', - false, - true - ); - } - - if (isset($context['graphql_operation_name'])) { - return false !== $resourceMetadata->getGraphqlAttribute($context['graphql_operation_name'], 'messenger', false, true); - } - - return false !== $resourceMetadata->getAttribute('messenger', false); - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []) - { - $envelope = $this->dispatch( - (new Envelope($data)) - ->with(new ContextStamp($context)) - ); - - $handledStamp = $envelope->last(HandledStamp::class); - if (!$handledStamp instanceof HandledStamp) { - return $data; - } - - return $handledStamp->getResult(); - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []) - { - $this->dispatch( - (new Envelope($data)) - ->with(new RemoveStamp()) - ); - } -} diff --git a/src/Core/Bridge/Symfony/Messenger/DataTransformer.php b/src/Core/Bridge/Symfony/Messenger/DataTransformer.php deleted file mode 100644 index d940788fbf9..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/DataTransformer.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * 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\Messenger; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Util\ClassInfoTrait; - -/** - * Transforms an Input to itself. This gives the ability to send the Input to a - * message handler and process it asynchronously. - * - * @author Antoine Bluchet - */ -final class DataTransformer implements DataTransformerInterface -{ - use ClassInfoTrait; - - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface - */ - private $resourceMetadataFactory; - - public function __construct($resourceMetadataFactory) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - } - - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - return $object; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - if ( - \is_object($data) // data is not normalized yet, it should be an array - || - null === ($context['input']['class'] ?? null) - ) { - return false; - } - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - try { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($context['resource_class'] ?? $to); - $operation = $resourceMetadataCollection->getOperation($context['operation_name'] ?? null); - - return 'input' === $operation->getMessenger(); - } catch (OperationNotFoundException $e) { - return false; - } - } - - $metadata = $this->resourceMetadataFactory->create($context['resource_class'] ?? $to); - - if (isset($context['graphql_operation_name'])) { - return 'input' === $metadata->getGraphqlAttribute($context['graphql_operation_name'], 'messenger', null, true); - } - - if (!isset($context['operation_type'])) { - return 'input' === $metadata->getAttribute('messenger'); - } - - return 'input' === $metadata->getTypedOperationAttribute( - $context['operation_type'], - $context[$context['operation_type'].'_operation_name'] ?? '', - 'messenger', - null, - true - ); - } -} diff --git a/src/Core/Bridge/Symfony/Messenger/DispatchTrait.php b/src/Core/Bridge/Symfony/Messenger/DispatchTrait.php deleted file mode 100644 index 7ae211cd77f..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/DispatchTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Messenger; - -class_exists(\ApiPlatform\Symfony\Messenger\DispatchTrait::class); - -if (false) { - trait DispatchTrait - { - use \ApiPlatform\Symfony\Messenger\DispatchTrait; - } -} diff --git a/src/Core/Bridge/Symfony/Messenger/RemoveStamp.php b/src/Core/Bridge/Symfony/Messenger/RemoveStamp.php deleted file mode 100644 index e5f1dc898ad..00000000000 --- a/src/Core/Bridge/Symfony/Messenger/RemoveStamp.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Messenger; - -class_exists(\ApiPlatform\Symfony\Messenger\RemoveStamp::class); - -if (false) { - final class RemoveStamp extends \ApiPlatform\Symfony\Messenger\RemoveStamp - { - } -} diff --git a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php b/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php deleted file mode 100644 index 26d7a76b657..00000000000 --- a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyMetadataFactory.php +++ /dev/null @@ -1,89 +0,0 @@ - - * - * 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\PropertyInfo\Metadata\Property; - -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; - -/** - * PropertyInfo metadata loader decorator. - * - * @author Kévin Dunglas - */ -final class PropertyInfoPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $propertyInfo; - private $decorated; - - public function __construct(PropertyInfoExtractorInterface $propertyInfo, PropertyMetadataFactoryInterface $decorated = null) - { - $this->propertyInfo = $propertyInfo; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - if (null === $this->decorated) { - $propertyMetadata = new PropertyMetadata(); - } else { - try { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - $propertyMetadata = new PropertyMetadata(); - } - } - - if (null === $propertyMetadata->getType()) { - $types = $this->propertyInfo->getTypes($resourceClass, $property, $options); - if (isset($types[0])) { - $propertyMetadata = $propertyMetadata->withType($types[0]); - } - } - - if (null === $propertyMetadata->getDescription() && null !== $description = $this->propertyInfo->getShortDescription($resourceClass, $property, $options)) { - $propertyMetadata = $propertyMetadata->withDescription($description); - } - - if (null === $propertyMetadata->isReadable() && null !== $readable = $this->propertyInfo->isReadable($resourceClass, $property, $options)) { - $propertyMetadata = $propertyMetadata->withReadable($readable); - } - - if (null === $propertyMetadata->isWritable() && null !== $writable = $this->propertyInfo->isWritable($resourceClass, $property, $options)) { - $propertyMetadata = $propertyMetadata->withWritable($writable); - } - - if (method_exists($this->propertyInfo, 'isInitializable')) { - if (null === $propertyMetadata->isInitializable() && null !== $initializable = $this->propertyInfo->isInitializable($resourceClass, $property, $options)) { - $propertyMetadata = $propertyMetadata->withInitializable($initializable); - } - } else { - // BC layer for Symfony < 4.2 - $ref = new \ReflectionClass($resourceClass); - if ($ref->isInstantiable() && $constructor = $ref->getConstructor()) { - foreach ($constructor->getParameters() as $constructorParameter) { - if ($constructorParameter->name === $property && null === $propertyMetadata->isInitializable()) { - $propertyMetadata = $propertyMetadata->withInitializable(true); - } - } - } - } - - return $propertyMetadata; - } -} diff --git a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php b/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php deleted file mode 100644 index 6e1839aa845..00000000000 --- a/src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\PropertyInfo\Metadata\Property; - -class_exists(\ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory::class); - -if (false) { - final class PropertyInfoPropertyNameCollectionFactory extends \ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory - { - } -} diff --git a/src/Core/Bridge/Symfony/Routing/ApiLoader.php b/src/Core/Bridge/Symfony/Routing/ApiLoader.php deleted file mode 100644 index 5265467c555..00000000000 --- a/src/Core/Bridge/Symfony/Routing/ApiLoader.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Routing; - -class_exists(\ApiPlatform\Symfony\Routing\ApiLoader::class); - -if (false) { - final class ApiLoader extends \ApiPlatform\Symfony\Routing\ApiLoader - { - } -} diff --git a/src/Core/Bridge/Symfony/Routing/CachedRouteNameResolver.php b/src/Core/Bridge/Symfony/Routing/CachedRouteNameResolver.php deleted file mode 100644 index 7cdcf4461c5..00000000000 --- a/src/Core/Bridge/Symfony/Routing/CachedRouteNameResolver.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Util\CachedTrait; -use Psr\Cache\CacheItemPoolInterface; - -/** - * {@inheritdoc} - * - * @author Teoh Han Hui - */ -final class CachedRouteNameResolver implements RouteNameResolverInterface -{ - use CachedTrait; - - public const CACHE_KEY_PREFIX = 'route_name_'; - - private $decorated; - - public function __construct(CacheItemPoolInterface $cacheItemPool, RouteNameResolverInterface $decorated) - { - $this->cacheItemPool = $cacheItemPool; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function getRouteName(string $resourceClass, $operationType /* , array $context = [] */): string - { - $context = \func_num_args() > 2 ? func_get_arg(2) : []; - $cacheKey = self::CACHE_KEY_PREFIX.md5(serialize([$resourceClass, $operationType, $context['subresource_resources'] ?? null])); - - return $this->getCached($cacheKey, function () use ($resourceClass, $operationType, $context) { - return $this->decorated->getRouteName($resourceClass, $operationType, $context); - }); - } -} diff --git a/src/Core/Bridge/Symfony/Routing/IriConverter.php b/src/Core/Bridge/Symfony/Routing/IriConverter.php deleted file mode 100644 index a3c0bfc3533..00000000000 --- a/src/Core/Bridge/Symfony/Routing/IriConverter.php +++ /dev/null @@ -1,186 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\IdentifiersExtractor; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\UrlGeneratorInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\OperationDataProviderTrait; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\CompositeIdentifierParser; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\ItemNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Symfony\Routing\IriConverter as NewIriConverter; -use ApiPlatform\Util\AttributesExtractor; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\PropertyAccess\PropertyAccess; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Routing\Exception\ExceptionInterface as RoutingExceptionInterface; -use Symfony\Component\Routing\RouterInterface; - -/** - * {@inheritdoc} - * - * @author Kévin Dunglas - */ -final class IriConverter implements IriConverterInterface -{ - use OperationDataProviderTrait; - use ResourceClassInfoTrait; - - private $routeNameResolver; - private $router; - private $identifiersExtractor; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ItemDataProviderInterface $itemDataProvider, RouteNameResolverInterface $routeNameResolver, RouterInterface $router, PropertyAccessorInterface $propertyAccessor = null, IdentifiersExtractorInterface $identifiersExtractor = null, SubresourceDataProviderInterface $subresourceDataProvider = null, IdentifierConverterInterface $identifierConverter = null, ResourceClassResolverInterface $resourceClassResolver = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null) - { - $this->itemDataProvider = $itemDataProvider; - $this->routeNameResolver = $routeNameResolver; - $this->router = $router; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->identifierConverter = $identifierConverter; - $this->resourceClassResolver = $resourceClassResolver; - $this->identifiersExtractor = $identifiersExtractor ?: new IdentifiersExtractor($propertyNameCollectionFactory, $propertyMetadataFactory, $propertyAccessor ?? PropertyAccess::createPropertyAccessor()); - $this->resourceMetadataFactory = $resourceMetadataFactory; - - trigger_deprecation('api-platform/core', '2.7', sprintf('The service "%s" is deprecated, use %s instead.', self::class, NewIriConverter::class)); - } - - /** - * {@inheritdoc} - * - * @return object - */ - public function getItemFromIri(string $iri, array $context = []) - { - try { - $parameters = $this->router->match($iri); - } catch (RoutingExceptionInterface $e) { - throw new InvalidArgumentException(sprintf('No route matches "%s".', $iri), $e->getCode(), $e); - } - - if (!isset($parameters['_api_resource_class'])) { - throw new InvalidArgumentException(sprintf('No resource associated to "%s".', $iri)); - } - - if (isset($parameters['_api_collection_operation_name'])) { - throw new InvalidArgumentException(sprintf('The iri "%s" references a collection not an item.', $iri)); - } - - $attributes = AttributesExtractor::extractAttributes($parameters); - - try { - $identifiers = $this->extractIdentifiers($parameters, $attributes); - } catch (InvalidIdentifierException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - - if ($this->identifierConverter) { - $context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] = true; - } - - if (isset($attributes['subresource_operation_name'])) { - if (($item = $this->getSubresourceData($identifiers, $attributes, $context)) && !\is_array($item)) { - return $item; - } - - throw new ItemNotFoundException(sprintf('Item not found for "%s".', $iri)); - } - - if ($item = $this->getItemData($identifiers, $attributes, $context)) { - return $item; - } - - throw new ItemNotFoundException(sprintf('Item not found for "%s".', $iri)); - } - - /** - * {@inheritdoc} - */ - public function getIriFromItem($item, int $referenceType = null): string - { - $resourceClass = $this->getResourceClass($item, true); - - try { - $identifiers = $this->identifiersExtractor->getIdentifiersFromItem($item); - } catch (RuntimeException $e) { - throw new InvalidArgumentException(sprintf('Unable to generate an IRI for the item of type "%s"', $resourceClass), $e->getCode(), $e); - } - - return $this->getItemIriFromResourceClass($resourceClass, $identifiers, $this->getReferenceType($resourceClass, $referenceType)); - } - - /** - * {@inheritdoc} - */ - public function getIriFromResourceClass(string $resourceClass, int $referenceType = null): string - { - try { - return $this->router->generate($this->routeNameResolver->getRouteName($resourceClass, OperationType::COLLECTION), [], $this->getReferenceType($resourceClass, $referenceType)); - } catch (RoutingExceptionInterface $e) { - throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".', $resourceClass), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function getItemIriFromResourceClass(string $resourceClass, array $identifiers, int $referenceType = null): string - { - $routeName = $this->routeNameResolver->getRouteName($resourceClass, OperationType::ITEM); - $metadata = $this->resourceMetadataFactory->create($resourceClass); - - if (\count($identifiers) > 1 && true === $metadata->getAttribute('composite_identifier', true)) { - $identifiers = ['id' => CompositeIdentifierParser::stringify($identifiers)]; - } - - try { - return $this->router->generate($routeName, $identifiers, $this->getReferenceType($resourceClass, $referenceType)); - } catch (RoutingExceptionInterface $e) { - throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".', $resourceClass), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function getSubresourceIriFromResourceClass(string $resourceClass, array $context, int $referenceType = null): string - { - try { - return $this->router->generate($this->routeNameResolver->getRouteName($resourceClass, OperationType::SUBRESOURCE, $context), $context['subresource_identifiers'], $this->getReferenceType($resourceClass, $referenceType)); - } catch (RoutingExceptionInterface $e) { - throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".', $resourceClass), $e->getCode(), $e); - } - } - - private function getReferenceType(string $resourceClass, ?int $referenceType): ?int - { - if (null === $referenceType && null !== $this->resourceMetadataFactory) { - $metadata = $this->resourceMetadataFactory->create($resourceClass); - $referenceType = $metadata->getAttribute('url_generation_strategy'); - } - - return $referenceType ?? UrlGeneratorInterface::ABS_PATH; - } -} diff --git a/src/Core/Bridge/Symfony/Routing/OperationMethodResolver.php b/src/Core/Bridge/Symfony/Routing/OperationMethodResolver.php deleted file mode 100644 index d236b4534c0..00000000000 --- a/src/Core/Bridge/Symfony/Routing/OperationMethodResolver.php +++ /dev/null @@ -1,153 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\RuntimeException; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouterInterface; - -/** - * Resolves the HTTP method associated with an operation, extended for Symfony routing. - * - * @author Kévin Dunglas - * @author Teoh Han Hui - * - * @deprecated since API Platform 2.5, use the "method" attribute instead - */ -final class OperationMethodResolver implements OperationMethodResolverInterface -{ - private $router; - private $resourceMetadataFactory; - - public function __construct(RouterInterface $router, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - @trigger_error(sprintf('The "%s" class is deprecated since API Platform 2.5, use the "method" attribute instead.', __CLASS__), \E_USER_DEPRECATED); - - $this->router = $router; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - /** - * {@inheritdoc} - */ - public function getCollectionOperationMethod(string $resourceClass, string $operationName): string - { - return $this->getOperationMethod($resourceClass, $operationName, OperationType::COLLECTION); - } - - /** - * {@inheritdoc} - */ - public function getItemOperationMethod(string $resourceClass, string $operationName): string - { - return $this->getOperationMethod($resourceClass, $operationName, OperationType::ITEM); - } - - /** - * {@inheritdoc} - */ - public function getCollectionOperationRoute(string $resourceClass, string $operationName): Route - { - return $this->getOperationRoute($resourceClass, $operationName, OperationType::COLLECTION); - } - - /** - * {@inheritdoc} - */ - public function getItemOperationRoute(string $resourceClass, string $operationName): Route - { - return $this->getOperationRoute($resourceClass, $operationName, OperationType::ITEM); - } - - /** - * @throws RuntimeException - */ - private function getOperationMethod(string $resourceClass, string $operationName, string $operationType): string - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if (OperationType::ITEM === $operationType) { - $method = $resourceMetadata->getItemOperationAttribute($operationName, 'method'); - } else { - $method = $resourceMetadata->getCollectionOperationAttribute($operationName, 'method'); - } - - if (null !== $method) { - return strtoupper($method); - } - - if (null === $routeName = $this->getRouteName($resourceMetadata, $operationName, $operationType)) { - throw new RuntimeException(sprintf('Either a "route_name" or a "method" operation attribute must exist for the operation "%s" of the resource "%s".', $operationName, $resourceClass)); - } - - return $this->getRoute($routeName)->getMethods()[0] ?? 'GET'; - } - - /** - * Gets the route related to the given operation. - * - * @throws RuntimeException - */ - private function getOperationRoute(string $resourceClass, string $operationName, string $operationType): Route - { - $routeName = $this->getRouteName($this->resourceMetadataFactory->create($resourceClass), $operationName, $operationType); - if (null !== $routeName) { - return $this->getRoute($routeName); - } - - $operationNameKey = sprintf('_api_%s_operation_name', $operationType); - - foreach ($this->router->getRouteCollection()->all() as $routeName => $route) { - $currentResourceClass = $route->getDefault('_api_resource_class'); - $currentOperationName = $route->getDefault($operationNameKey); - - if ($resourceClass === $currentResourceClass && $operationName === $currentOperationName) { - return $route; - } - } - - throw new RuntimeException(sprintf('No route found for operation "%s" for type "%s".', $operationName, $resourceClass)); - } - - /** - * Gets the route name or null if not defined. - */ - private function getRouteName(ResourceMetadata $resourceMetadata, string $operationName, string $operationType): ?string - { - if (OperationType::ITEM === $operationType) { - return $resourceMetadata->getItemOperationAttribute($operationName, 'route_name'); - } - - return $resourceMetadata->getCollectionOperationAttribute($operationName, 'route_name'); - } - - /** - * Gets the route with the given name. - * - * @throws RuntimeException - */ - private function getRoute(string $routeName): Route - { - foreach ($this->router->getRouteCollection() as $name => $route) { - if ($routeName === $name) { - return $route; - } - } - - throw new RuntimeException(sprintf('The route "%s" does not exist.', $routeName)); - } -} diff --git a/src/Core/Bridge/Symfony/Routing/OperationMethodResolverInterface.php b/src/Core/Bridge/Symfony/Routing/OperationMethodResolverInterface.php deleted file mode 100644 index 1b17511229c..00000000000 --- a/src/Core/Bridge/Symfony/Routing/OperationMethodResolverInterface.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationMethodResolverInterface as BaseOperationMethodResolverInterface; -use ApiPlatform\Exception\RuntimeException; -use Symfony\Component\Routing\Route; - -/** - * Resolves the HTTP method associated with an operation, extended for Symfony routing. - * - * @author Teoh Han Hui - * - * @deprecated since API Platform 2.5, use the "method" attribute instead - */ -interface OperationMethodResolverInterface extends BaseOperationMethodResolverInterface -{ - /** - * @throws RuntimeException - */ - public function getCollectionOperationRoute(string $resourceClass, string $operationName): Route; - - /** - * @throws RuntimeException - */ - public function getItemOperationRoute(string $resourceClass, string $operationName): Route; -} diff --git a/src/Core/Bridge/Symfony/Routing/RouteNameGenerator.php b/src/Core/Bridge/Symfony/Routing/RouteNameGenerator.php deleted file mode 100644 index 4fce8174b38..00000000000 --- a/src/Core/Bridge/Symfony/Routing/RouteNameGenerator.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Util\Inflector; - -/** - * Generates the Symfony route name associated with an operation name and a resource short name. - * - * @internal - * - * @author Baptiste Meyer - */ -final class RouteNameGenerator -{ - public const ROUTE_NAME_PREFIX = 'api_'; - - private function __construct() - { - } - - /** - * Generates a Symfony route name. - * - * @param string|bool $operationType - * - * @throws InvalidArgumentException - */ - public static function generate(string $operationName, string $resourceShortName, $operationType): string - { - if (OperationType::SUBRESOURCE === $operationType = OperationTypeDeprecationHelper::getOperationType($operationType)) { - throw new InvalidArgumentException('Subresource operations are not supported by the RouteNameGenerator.'); - } - - $operationName = sprintf( - '%s%s_%s', - static::ROUTE_NAME_PREFIX, - self::inflector($resourceShortName), - $operationName - ); - - // prevent api_foo_get_collection_collection - if ("_$operationType" !== substr($operationName, -\strlen("_$operationType"))) { - $operationName .= "_$operationType"; - } - - return $operationName; - } - - /** - * Transforms a given string to a tableized, pluralized string. - * - * @param string $name usually a ResourceMetadata shortname - * - * @return string A string that is a part of the route name - */ - public static function inflector(string $name, bool $pluralize = true): string - { - $name = Inflector::tableize($name); - - return $pluralize ? Inflector::pluralize($name) : $name; - } -} diff --git a/src/Core/Bridge/Symfony/Routing/RouteNameResolver.php b/src/Core/Bridge/Symfony/Routing/RouteNameResolver.php deleted file mode 100644 index 5034f959556..00000000000 --- a/src/Core/Bridge/Symfony/Routing/RouteNameResolver.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; -use ApiPlatform\Exception\InvalidArgumentException; -use Symfony\Component\Routing\RouterInterface; - -/** - * {@inheritdoc} - * - * @author Kévin Dunglas - */ -final class RouteNameResolver implements RouteNameResolverInterface -{ - private $router; - - public function __construct(RouterInterface $router) - { - $this->router = $router; - } - - /** - * {@inheritdoc} - */ - public function getRouteName(string $resourceClass, $operationType /* , array $context = [] */): string - { - if (\func_num_args() > 2) { - $context = func_get_arg(2); - } else { - $context = []; - } - - $operationType = OperationTypeDeprecationHelper::getOperationType($operationType); - - foreach ($this->router->getRouteCollection()->all() as $routeName => $route) { - $currentResourceClass = $route->getDefault('_api_resource_class'); - $operation = $route->getDefault(sprintf('_api_%s_operation_name', $operationType)); - $methods = $route->getMethods(); - - if ($resourceClass === $currentResourceClass && null !== $operation && (empty($methods) || \in_array('GET', $methods, true))) { - if (OperationType::SUBRESOURCE === $operationType && false === $this->isSameSubresource($context, $route->getDefault('_api_subresource_context'))) { - continue; - } - - return $routeName; - } - } - - throw new InvalidArgumentException(sprintf('No %s route associated with the type "%s".', $operationType, $resourceClass)); - } - - private function isSameSubresource(array $context, array $currentContext): bool - { - $subresources = array_keys($context['subresource_resources']); - $currentSubresources = []; - - foreach ($currentContext['identifiers'] as [$class]) { - $currentSubresources[] = $class; - } - - return $currentSubresources === $subresources; - } -} diff --git a/src/Core/Bridge/Symfony/Routing/RouteNameResolverInterface.php b/src/Core/Bridge/Symfony/Routing/RouteNameResolverInterface.php deleted file mode 100644 index 91078b25cc8..00000000000 --- a/src/Core/Bridge/Symfony/Routing/RouteNameResolverInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Exception\InvalidArgumentException; - -/** - * Resolves the Symfony route name associated with a resource. - * - * @author Teoh Han Hui - */ -interface RouteNameResolverInterface -{ - /** - * Finds the route name for a resource. - * - * @param bool|string $operationType - * - * @throws InvalidArgumentException - */ - public function getRouteName(string $resourceClass, $operationType /* , array $context = [] */): string; -} diff --git a/src/Core/Bridge/Symfony/Routing/Router.php b/src/Core/Bridge/Symfony/Routing/Router.php deleted file mode 100644 index 52326c81c3f..00000000000 --- a/src/Core/Bridge/Symfony/Routing/Router.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Routing; - -class_exists(\ApiPlatform\Symfony\Routing\Router::class); - -if (false) { - final class Router extends \ApiPlatform\Symfony\Routing\Router - { - } -} diff --git a/src/Core/Bridge/Symfony/Routing/RouterOperationPathResolver.php b/src/Core/Bridge/Symfony/Routing/RouterOperationPathResolver.php deleted file mode 100644 index dd2d9c95399..00000000000 --- a/src/Core/Bridge/Symfony/Routing/RouterOperationPathResolver.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use Symfony\Component\Routing\RouterInterface; - -/** - * Resolves the operations path using a Symfony route. - * TODO: remove this in 3.0. - * - * @author Guilhem N. - */ -final class RouterOperationPathResolver implements OperationPathResolverInterface -{ - private $router; - private $deferred; - - public function __construct(RouterInterface $router, OperationPathResolverInterface $deferred) - { - $this->router = $router; - $this->deferred = $deferred; - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() >= 4) { - $operationName = (string) func_get_arg(3); - } else { - @trigger_error(sprintf('Method %s() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1.', __METHOD__), \E_USER_DEPRECATED); - - $operationName = null; - } - - if (isset($operation['route_name'])) { - $routeName = $operation['route_name']; - } elseif (OperationType::SUBRESOURCE === $operationType) { - throw new InvalidArgumentException('Subresource operations are not supported by the RouterOperationPathResolver without a route name.'); - } elseif (null === $operationName) { - return $this->deferred->resolveOperationPath($resourceShortName, $operation, OperationTypeDeprecationHelper::getOperationType($operationType), $operationName); - } elseif (isset($operation['uri_template'])) { - return $operation['uri_template']; - } else { - $routeName = RouteNameGenerator::generate($operationName, $resourceShortName, $operationType); - } - - if (!$route = $this->router->getRouteCollection()->get($routeName)) { - throw new InvalidArgumentException(sprintf('The route "%s" of the resource "%s" was not found.', $routeName, $resourceShortName)); - } - - return $route->getPath(); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/EventListener/ValidateListener.php b/src/Core/Bridge/Symfony/Validator/EventListener/ValidateListener.php deleted file mode 100644 index 7cb7f162fee..00000000000 --- a/src/Core/Bridge/Symfony/Validator/EventListener/ValidateListener.php +++ /dev/null @@ -1,90 +0,0 @@ - - * - * 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\EventListener; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Symfony\EventListener\ValidateListener as MainValidateListener; -use ApiPlatform\Symfony\Validator\Exception\ValidationException; -use ApiPlatform\Util\RequestAttributesExtractor; -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\Validator\Validator\ValidatorInterface; - -/** - * Validates data. - * - * @deprecated - * - * @author Kévin Dunglas - */ -final class ValidateListener -{ - private $validator; - private $resourceMetadataFactory; - private $container; - - public function __construct(ValidatorInterface $validator, ResourceMetadataFactoryInterface $resourceMetadataFactory, ContainerInterface $container = null) - { - @trigger_error(sprintf('Using "%s" is deprecated since API Platform 2.2 and will not be possible anymore in API Platform 3. Use "%s" instead.', __CLASS__, MainValidateListener::class), \E_USER_DEPRECATED); - - $this->validator = $validator; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->container = $container; - } - - /** - * Validates data returned by the controller if applicable. - * - * @throws ValidationException - */ - public function onKernelView(ViewEvent $event): void - { - $request = $event->getRequest(); - if ( - $request->isMethodSafe() - || $request->isMethod('DELETE') - || !($attributes = RequestAttributesExtractor::extractAttributes($request)) - || !$attributes['receive'] - ) { - return; - } - - $data = $event->getControllerResult(); - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - - $validationGroups = $resourceMetadata->getOperationAttribute($attributes, 'validation_groups'); - - if (!$validationGroups) { - // Fallback to the resource - $validationGroups = $resourceMetadata->getAttributes()['validation_groups'] ?? null; - } - - if ( - $this->container && - \is_string($validationGroups) && - $this->container->has($validationGroups) && - ($service = $this->container->get($validationGroups)) && - \is_callable($service) - ) { - $validationGroups = $service($data); - } elseif (\is_callable($validationGroups)) { - $validationGroups = $validationGroups($data); - } - - $violations = $this->validator->validate($data, null, (array) $validationGroups); - if (0 !== \count($violations)) { - throw new ValidationException($violations); - } - } -} diff --git a/src/Core/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php b/src/Core/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php deleted file mode 100644 index a78906ea488..00000000000 --- a/src/Core/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\EventListener; - -class_exists(\ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener::class); - -if (false) { - final class ValidationExceptionListener extends \ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener - { - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Exception/ValidationException.php b/src/Core/Bridge/Symfony/Validator/Exception/ValidationException.php deleted file mode 100644 index 7893d93d87b..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Exception/ValidationException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Symfony\Validator\Exception\ValidationException::class); - -if (false) { - final class ValidationException extends \ApiPlatform\Symfony\Validator\Exception\ValidationException - { - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestriction.php deleted file mode 100644 index 527f0efb1c8..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestriction.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * 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\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Choice; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaChoiceRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param Choice $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $choices = []; - - if (\is_callable($constraint->callback)) { - $choices = ($constraint->callback)(); - } elseif (\is_array($constraint->choices)) { - $choices = $constraint->choices; - } - - if (!$choices) { - return []; - } - - $restriction = []; - - if (!$constraint->multiple) { - $restriction['enum'] = $choices; - - return $restriction; - } - - $restriction['type'] = 'array'; - - $type = $propertyMetadata->getType() ?? null; - if ($type) { - $restriction['items'] = ['type' => Type::BUILTIN_TYPE_STRING === $type->getBuiltinType() ? 'string' : 'number', 'enum' => $choices]; - } - - if (null !== $constraint->min) { - $restriction['minItems'] = $constraint->min; - } - - if (null !== $constraint->max) { - $restriction['maxItems'] = $constraint->max; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Choice && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_STRING, Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestriction.php deleted file mode 100644 index eecad4e891a..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestriction.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * 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\Collection; -use Symfony\Component\Validator\Constraints\Optional; -use Symfony\Component\Validator\Constraints\Required; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaCollectionRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * @var iterable - */ - private $restrictionsMetadata; - - /** - * @param iterable $restrictionsMetadata - */ - public function __construct(iterable $restrictionsMetadata = []) - { - $this->restrictionsMetadata = $restrictionsMetadata; - } - - /** - * {@inheritdoc} - * - * @param Collection $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $restriction = [ - 'type' => 'object', - 'properties' => [], - 'additionalProperties' => $constraint->allowExtraFields, - ]; - $required = []; - - foreach ($constraint->fields as $field => $baseConstraint) { - /** @var Required|Optional $baseConstraint */ - if ($baseConstraint instanceof Required && !$constraint->allowMissingFields) { - $required[] = $field; - } - - $restriction['properties'][$field] = $this->mergeConstraintRestrictions($baseConstraint, $propertyMetadata); - } - - if ($required) { - $restriction['required'] = $required; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Collection; - } - - /** - * @param Required|Optional $constraint - */ - private function mergeConstraintRestrictions(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $propertyRestrictions = []; - $nestedConstraints = method_exists($constraint, 'getNestedContraints') ? $constraint->getNestedContraints() : $constraint->constraints; - - foreach ($nestedConstraints as $nestedConstraint) { - foreach ($this->restrictionsMetadata as $restrictionMetadata) { - if ($restrictionMetadata->supports($nestedConstraint, $propertyMetadata) && !empty($nestedConstraintRestriction = $restrictionMetadata->create($nestedConstraint, $propertyMetadata))) { - $propertyRestrictions[] = $nestedConstraintRestriction; - } - } - } - - return array_merge([], ...$propertyRestrictions); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestriction.php deleted file mode 100644 index d09f5835b0b..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestriction.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * 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\Count; - -/** - * @author Tomas Norkūnas - */ -class PropertySchemaCountRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param Count $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $restriction = []; - - if (null !== $constraint->min) { - $restriction['minItems'] = $constraint->min; - } - - if (null !== $constraint->max) { - $restriction['maxItems'] = $constraint->max; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Count; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormat.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormat.php deleted file mode 100644 index c6cec232b6f..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormat.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * 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\Email; -use Symfony\Component\Validator\Constraints\Ip; -use Symfony\Component\Validator\Constraints\Ulid; -use Symfony\Component\Validator\Constraints\Uuid; - -/** - * Class PropertySchemaFormat. - * - * @author Andrii Penchuk penja7@gmail.com - */ -class PropertySchemaFormat implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - if ($constraint instanceof Email) { - return ['format' => 'email']; - } - - if ($constraint instanceof Uuid) { - return ['format' => 'uuid']; - } - - if ($constraint instanceof Ulid) { - return ['format' => 'ulid']; - } - - if ($constraint instanceof Ip) { - if ($constraint->version === $constraint::V4) { - return ['format' => 'ipv4']; - } - - return ['format' => 'ipv6']; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - $schema = $propertyMetadata->getSchema(); - - return empty($schema['format']) && ($constraint instanceof Email || $constraint instanceof Uuid || $constraint instanceof Ulid || $constraint instanceof Ip); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestriction.php deleted file mode 100644 index c3d63b5a9e0..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestriction.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * 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\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaGreaterThanOrEqualRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param GreaterThanOrEqual $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return [ - 'minimum' => $constraint->value, - ]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof GreaterThanOrEqual && is_numeric($constraint->value) && ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestriction.php deleted file mode 100644 index edde8500593..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestriction.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * 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\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\GreaterThan; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaGreaterThanRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param GreaterThan $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return [ - 'minimum' => $constraint->value, - 'exclusiveMinimum' => true, - ]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof GreaterThan && is_numeric($constraint->value) && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLengthRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLengthRestriction.php deleted file mode 100644 index 47acf0d8f9e..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLengthRestriction.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * 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\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Length; - -/** - * Class PropertySchemaLengthRestrictions. - * - * @author Andrii Penchuk penja7@gmail.com - */ -class PropertySchemaLengthRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $restriction = []; - - if (isset($constraint->min)) { - $restriction['minLength'] = (int) $constraint->min; - } - - if (isset($constraint->max)) { - $restriction['maxLength'] = (int) $constraint->max; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Length && null !== ($type = $propertyMetadata->getType()) && Type::BUILTIN_TYPE_STRING === $type->getBuiltinType(); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestriction.php deleted file mode 100644 index 1cb0cbfe99d..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestriction.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * 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\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\LessThanOrEqual; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaLessThanOrEqualRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param LessThanOrEqual $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return [ - 'maximum' => $constraint->value, - ]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof LessThanOrEqual && is_numeric($constraint->value) && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestriction.php deleted file mode 100644 index ee1aee51580..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestriction.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * 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\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\LessThan; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaLessThanRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - * - * @param LessThan $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return [ - 'maximum' => $constraint->value, - 'exclusiveMaximum' => true, - ]; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof LessThan && is_numeric($constraint->value) && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestriction.php deleted file mode 100644 index badbbcf7a25..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestriction.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * 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\AtLeastOneOf; - -/** - * @author Alan Poulain - */ -final class PropertySchemaOneOfRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * @var iterable - */ - private $restrictionsMetadata; - - /** - * @param iterable $restrictionsMetadata - */ - public function __construct(iterable $restrictionsMetadata = []) - { - $this->restrictionsMetadata = $restrictionsMetadata; - } - - /** - * {@inheritdoc} - * - * @param AtLeastOneOf $constraint - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $oneOfConstraints = method_exists($constraint, 'getNestedContraints') ? $constraint->getNestedContraints() : $constraint->constraints; - $oneOfRestrictions = []; - - foreach ($oneOfConstraints as $oneOfConstraint) { - foreach ($this->restrictionsMetadata as $restrictionMetadata) { - if ($restrictionMetadata->supports($oneOfConstraint, $propertyMetadata) && !empty($oneOfRestriction = $restrictionMetadata->create($oneOfConstraint, $propertyMetadata))) { - $oneOfRestrictions[] = $oneOfRestriction; - } - } - } - - if (!empty($oneOfRestrictions)) { - return ['oneOf' => $oneOfRestrictions]; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof AtLeastOneOf; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestriction.php deleted file mode 100644 index 51f78cf3e36..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestriction.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * 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\PropertyInfo\Type; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Range; - -/** - * @author Tomas Norkūnas - */ -final class PropertySchemaRangeRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - $restriction = []; - - if (isset($constraint->min) && is_numeric($constraint->min)) { - $restriction['minimum'] = $constraint->min; - } - - if (isset($constraint->max) && is_numeric($constraint->max)) { - $restriction['maximum'] = $constraint->max; - } - - return $restriction; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Range && null !== ($type = $propertyMetadata->getType() ?? null) && \in_array($type->getBuiltinType(), [Type::BUILTIN_TYPE_INT, Type::BUILTIN_TYPE_FLOAT], true); - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestriction.php deleted file mode 100644 index 5a075b9398e..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestriction.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * 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\Regex; - -/** - * Class PropertySchemaRegexRestriction. - * - * @author Andrii Penchuk penja7@gmail.com - */ -class PropertySchemaRegexRestriction implements PropertySchemaRestrictionMetadataInterface -{ - /** - * {@inheritdoc} - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array - { - return $constraint instanceof Regex && $constraint->getHtmlPattern() ? ['pattern' => '^('.$constraint->getHtmlPattern().')$'] : []; - } - - /** - * {@inheritdoc} - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool - { - return $constraint instanceof Regex && $constraint->match; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRestrictionMetadataInterface.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRestrictionMetadataInterface.php deleted file mode 100644 index 2486342de40..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRestrictionMetadataInterface.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * 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; - -/** - * Interface PropertySchemaRestrictionsInterface. - * - * @author Andrii Penchuk penja7@gmail.com - */ -interface PropertySchemaRestrictionMetadataInterface -{ - /** - * Creates json schema restrictions based on the validation constraints. - * - * @param Constraint $constraint The validation constraint - * @param PropertyMetadata $propertyMetadata The property metadata - * - * @return array The array of restrictions - */ - public function create(Constraint $constraint, PropertyMetadata $propertyMetadata): array; - - /** - * Is the constraint supported by the schema restriction? - * - * @param Constraint $constraint The validation constraint - * @param PropertyMetadata $propertyMetadata The property metadata - */ - public function supports(Constraint $constraint, PropertyMetadata $propertyMetadata): bool; -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestriction.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestriction.php deleted file mode 100644 index 8a7a0359669..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestriction.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * 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 - */ -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; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php b/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php deleted file mode 100644 index b5953ace1bf..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php +++ /dev/null @@ -1,199 +0,0 @@ - - * - * 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; - -use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Constraints\Bic; -use Symfony\Component\Validator\Constraints\CardScheme; -use Symfony\Component\Validator\Constraints\Compound; -use Symfony\Component\Validator\Constraints\Currency; -use Symfony\Component\Validator\Constraints\Date; -use Symfony\Component\Validator\Constraints\DateTime; -use Symfony\Component\Validator\Constraints\Email; -use Symfony\Component\Validator\Constraints\File; -use Symfony\Component\Validator\Constraints\Iban; -use Symfony\Component\Validator\Constraints\Image; -use Symfony\Component\Validator\Constraints\Isbn; -use Symfony\Component\Validator\Constraints\Issn; -use Symfony\Component\Validator\Constraints\NotBlank; -use Symfony\Component\Validator\Constraints\NotNull; -use Symfony\Component\Validator\Constraints\Sequentially; -use Symfony\Component\Validator\Constraints\Time; -use Symfony\Component\Validator\Constraints\Url; -use Symfony\Component\Validator\Constraints\Uuid; -use Symfony\Component\Validator\Mapping\ClassMetadataInterface as ValidatorClassMetadataInterface; -use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface as ValidatorMetadataFactoryInterface; -use Symfony\Component\Validator\Mapping\PropertyMetadataInterface as ValidatorPropertyMetadataInterface; - -/** - * Decorates a metadata loader using the validator. - * - * @author Kévin Dunglas - */ -final class ValidatorPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - /** - * @var string[] A list of constraint classes making the entity required - */ - public const REQUIRED_CONSTRAINTS = [NotBlank::class, NotNull::class]; - - public const SCHEMA_MAPPED_CONSTRAINTS = [ - Url::class => 'http://schema.org/url', - Email::class => 'http://schema.org/email', - Uuid::class => 'http://schema.org/identifier', - CardScheme::class => 'http://schema.org/identifier', - Bic::class => 'http://schema.org/identifier', - Iban::class => 'http://schema.org/identifier', - Date::class => 'http://schema.org/Date', - DateTime::class => 'http://schema.org/DateTime', - Time::class => 'http://schema.org/Time', - Image::class => 'http://schema.org/image', - File::class => 'http://schema.org/MediaObject', - Currency::class => 'http://schema.org/priceCurrency', - Isbn::class => 'http://schema.org/isbn', - Issn::class => 'http://schema.org/issn', - ]; - - private $decorated; - private $validatorMetadataFactory; - /** - * @var iterable - */ - private $restrictionsMetadata; - - /** - * @param PropertySchemaRestrictionMetadataInterface[] $restrictionsMetadata - */ - public function __construct(ValidatorMetadataFactoryInterface $validatorMetadataFactory, PropertyMetadataFactoryInterface $decorated, iterable $restrictionsMetadata = []) - { - $this->validatorMetadataFactory = $validatorMetadataFactory; - $this->decorated = $decorated; - $this->restrictionsMetadata = $restrictionsMetadata; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - $required = $propertyMetadata->isRequired(); - $iri = $propertyMetadata->getIri(); - $schema = $propertyMetadata->getSchema(); - - if (null !== $required && null !== $iri && null !== $schema) { - return $propertyMetadata; - } - - $validatorClassMetadata = $this->validatorMetadataFactory->getMetadataFor($resourceClass); - - if (!$validatorClassMetadata instanceof ValidatorClassMetadataInterface) { - throw new \UnexpectedValueException(sprintf('Validator class metadata expected to be of type "%s".', ValidatorClassMetadataInterface::class)); - } - - $validationGroups = $this->getValidationGroups($validatorClassMetadata, $options); - $restrictions = []; - - foreach ($validatorClassMetadata->getPropertyMetadata($property) as $validatorPropertyMetadata) { - foreach ($this->getPropertyConstraints($validatorPropertyMetadata, $validationGroups) as $constraint) { - if (null === $required && $this->isRequired($constraint)) { - $required = true; - } - - if (null === $iri) { - $iri = self::SCHEMA_MAPPED_CONSTRAINTS[\get_class($constraint)] ?? null; - } - - foreach ($this->restrictionsMetadata as $restrictionMetadata) { - if ($restrictionMetadata->supports($constraint, $propertyMetadata)) { - $restrictions[] = $restrictionMetadata->create($constraint, $propertyMetadata); - } - } - } - } - - $propertyMetadata = $propertyMetadata->withIri($iri)->withRequired($required ?? false); - - if (!empty($restrictions)) { - if (null === $schema) { - $schema = []; - } - - $schema += array_merge(...$restrictions); - $propertyMetadata = $propertyMetadata->withSchema($schema); - } - - return $propertyMetadata; - } - - /** - * Returns the list of validation groups. - */ - private function getValidationGroups(ValidatorClassMetadataInterface $classMetadata, array $options): array - { - if (isset($options['validation_groups'])) { - return $options['validation_groups']; - } - - if (!method_exists($classMetadata, 'getDefaultGroup')) { - throw new \UnexpectedValueException(sprintf('Validator class metadata expected to have method "%s".', 'getDefaultGroup')); - } - - return [$classMetadata->getDefaultGroup()]; - } - - /** - * Tests if the property is required because of its validation groups. - */ - private function getPropertyConstraints( - ValidatorPropertyMetadataInterface $validatorPropertyMetadata, - array $groups - ): array { - $constraints = []; - - foreach ($groups as $validationGroup) { - if (!\is_string($validationGroup)) { - continue; - } - - foreach ($validatorPropertyMetadata->findConstraints($validationGroup) as $propertyConstraint) { - if ($propertyConstraint instanceof Sequentially || $propertyConstraint instanceof Compound) { - $constraints[] = method_exists($propertyConstraint, 'getNestedContraints') ? $propertyConstraint->getNestedContraints() : $propertyConstraint->getNestedConstraints(); - } else { - $constraints[] = [$propertyConstraint]; - } - } - } - - return array_merge([], ...$constraints); - } - - /** - * Is this constraint making the related property required? - */ - private function isRequired(Constraint $constraint): bool - { - foreach (self::REQUIRED_CONSTRAINTS as $requiredConstraint) { - if ($constraint instanceof $requiredConstraint) { - return true; - } - } - - return false; - } -} diff --git a/src/Core/Bridge/Symfony/Validator/Validator.php b/src/Core/Bridge/Symfony/Validator/Validator.php deleted file mode 100644 index 2fb61bd0647..00000000000 --- a/src/Core/Bridge/Symfony/Validator/Validator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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; - -class_exists(\ApiPlatform\Symfony\Validator\Validator::class); - -if (false) { - class Validator extends \ApiPlatform\Symfony\Validator\Validator - { - } -} diff --git a/src/Core/Cache/CachedTrait.php b/src/Core/Cache/CachedTrait.php deleted file mode 100644 index 3f6ec41f861..00000000000 --- a/src/Core/Cache/CachedTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Cache; - -class_exists(\ApiPlatform\Util\CachedTrait::class); - -if (false) { - trait CachedTrait - { - use \ApiPlatform\Util\CachedTrait; - } -} diff --git a/src/Core/DataPersister/ChainDataPersister.php b/src/Core/DataPersister/ChainDataPersister.php deleted file mode 100644 index 85e44bb4949..00000000000 --- a/src/Core/DataPersister/ChainDataPersister.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * 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\DataPersister; - -/** - * Chained data persisters. - * - * @author Baptiste Meyer - */ -final class ChainDataPersister implements ContextAwareDataPersisterInterface -{ - /** - * @var iterable - * - * @internal - */ - public $persisters; - - /** - * @param DataPersisterInterface[] $persisters - */ - public function __construct(iterable $persisters) - { - $this->persisters = $persisters; - } - - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool - { - foreach ($this->persisters as $persister) { - if ($persister->supports($data, $context)) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []) - { - foreach ($this->persisters as $persister) { - if ($persister->supports($data, $context)) { - $data = $persister->persist($data, $context); - if ($persister instanceof ResumableDataPersisterInterface && $persister->resumable($context)) { - continue; - } - - return $data; - } - } - - return $data; - } - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []) - { - foreach ($this->persisters as $persister) { - if ($persister->supports($data, $context)) { - $persister->remove($data, $context); - if ($persister instanceof ResumableDataPersisterInterface && $persister->resumable($context)) { - continue; - } - - return; - } - } - } -} diff --git a/src/Core/DataPersister/ContextAwareDataPersisterInterface.php b/src/Core/DataPersister/ContextAwareDataPersisterInterface.php deleted file mode 100644 index a581418710b..00000000000 --- a/src/Core/DataPersister/ContextAwareDataPersisterInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * 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\DataPersister; - -/** - * Manages data persistence. - * - * @author Antoine Bluchet - */ -interface ContextAwareDataPersisterInterface extends DataPersisterInterface -{ - /** - * {@inheritdoc} - */ - public function supports($data, array $context = []): bool; - - /** - * {@inheritdoc} - */ - public function persist($data, array $context = []); - - /** - * {@inheritdoc} - */ - public function remove($data, array $context = []); -} diff --git a/src/Core/DataPersister/DataPersisterInterface.php b/src/Core/DataPersister/DataPersisterInterface.php deleted file mode 100644 index dc2cee68362..00000000000 --- a/src/Core/DataPersister/DataPersisterInterface.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * 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\DataPersister; - -/** - * Manages data persistence. - * - * @author Baptiste Meyer - */ -interface DataPersisterInterface -{ - /** - * Is the data supported by the persister? - * - * @param mixed $data - */ - public function supports($data): bool; - - /** - * Persists the data. - * - * @param mixed $data - * - * @return object|void Void will not be supported in API Platform 3, an object should always be returned - */ - public function persist($data); - - /** - * Removes the data. - * - * @param mixed $data - */ - public function remove($data); -} diff --git a/src/Core/DataPersister/ResumableDataPersisterInterface.php b/src/Core/DataPersister/ResumableDataPersisterInterface.php deleted file mode 100644 index abfc39c1f84..00000000000 --- a/src/Core/DataPersister/ResumableDataPersisterInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * 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\DataPersister; - -/** - * Control the resumability of the data persister chain. - */ -interface ResumableDataPersisterInterface -{ - /** - * Should we continue calling the next DataPersister or stop after this one? - * Defaults to stop the ChainDatapersister if this interface is not implemented. - */ - public function resumable(array $context = []): bool; -} diff --git a/src/Core/DataProvider/ArrayPaginator.php b/src/Core/DataProvider/ArrayPaginator.php deleted file mode 100644 index c80512b2e21..00000000000 --- a/src/Core/DataProvider/ArrayPaginator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\DataProvider; - -class_exists(\ApiPlatform\State\Pagination\ArrayPaginator::class); - -if (false) { - final class ArrayPaginator extends \ApiPlatform\State\Pagination\ArrayPaginator - { - } -} diff --git a/src/Core/DataProvider/ChainCollectionDataProvider.php b/src/Core/DataProvider/ChainCollectionDataProvider.php deleted file mode 100644 index 0f0d402a267..00000000000 --- a/src/Core/DataProvider/ChainCollectionDataProvider.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Tries each configured data provider and returns the result of the first able to handle the resource class. - * - * @author Kévin Dunglas - */ -final class ChainCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - use RestrictDataProviderTrait; - - /** - * @param CollectionDataProviderInterface[] $dataProviders - */ - public function __construct(iterable $dataProviders) - { - $this->dataProviders = $dataProviders; - } - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable - { - foreach ($this->dataProviders as $dataProvider) { - try { - if ($dataProvider instanceof RestrictedDataProviderInterface - && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - return $dataProvider->getCollection($resourceClass, $operationName, $context); - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return []; - } -} diff --git a/src/Core/DataProvider/ChainItemDataProvider.php b/src/Core/DataProvider/ChainItemDataProvider.php deleted file mode 100644 index 5be72883a41..00000000000 --- a/src/Core/DataProvider/ChainItemDataProvider.php +++ /dev/null @@ -1,66 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Tries each configured data provider and returns the result of the first able to handle the resource class. - * - * @author Kévin Dunglas - */ -final class ChainItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - use RestrictDataProviderTrait; - - /** - * @param ItemDataProviderInterface[] $dataProviders - */ - public function __construct(iterable $dataProviders) - { - $this->dataProviders = $dataProviders; - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - foreach ($this->dataProviders as $dataProvider) { - try { - if ($dataProvider instanceof RestrictedDataProviderInterface - && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - $identifier = $id; - if (!$dataProvider instanceof DenormalizedIdentifiersAwareItemDataProviderInterface && $identifier && \is_array($identifier)) { - if (\count($identifier) > 1) { - @trigger_error(sprintf('Receiving "$id" as non-array in an item data provider is deprecated in 2.3 in favor of implementing "%s".', DenormalizedIdentifiersAwareItemDataProviderInterface::class), \E_USER_DEPRECATED); - $identifier = http_build_query($identifier, '', ';'); - } else { - $identifier = current($identifier); - } - } - - return $dataProvider->getItem($resourceClass, $identifier, $operationName, $context); - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" is deprecated in favor of implementing "%s"', \get_class($e), RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return null; - } -} diff --git a/src/Core/DataProvider/ChainSubresourceDataProvider.php b/src/Core/DataProvider/ChainSubresourceDataProvider.php deleted file mode 100644 index 2a44219b459..00000000000 --- a/src/Core/DataProvider/ChainSubresourceDataProvider.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Tries each configured data provider and returns the result of the first able to handle the resource class. - * - * @author Antoine Bluchet - */ -final class ChainSubresourceDataProvider implements SubresourceDataProviderInterface -{ - /** - * @var iterable - * - * @internal - */ - public $dataProviders; - - /** - * @param SubresourceDataProviderInterface[] $dataProviders - */ - public function __construct(iterable $dataProviders) - { - $this->dataProviders = $dataProviders; - } - - /** - * {@inheritdoc} - */ - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - foreach ($this->dataProviders as $dataProvider) { - try { - if ($dataProvider instanceof RestrictedDataProviderInterface && !$dataProvider->supports($resourceClass, $operationName, $context)) { - continue; - } - - return $dataProvider->getSubresource($resourceClass, $identifiers, $context, $operationName); - } catch (ResourceClassNotSupportedException $e) { - @trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), \E_USER_DEPRECATED); - continue; - } - } - - return ($context['collection'] ?? false) ? [] : null; - } -} diff --git a/src/Core/DataProvider/CollectionDataProviderInterface.php b/src/Core/DataProvider/CollectionDataProviderInterface.php deleted file mode 100644 index abd765cf758..00000000000 --- a/src/Core/DataProvider/CollectionDataProviderInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Retrieves items from a persistence layer. - * - * @author Kévin Dunglas - */ -interface CollectionDataProviderInterface -{ - /** - * Retrieves a collection. - * - * @throws ResourceClassNotSupportedException - * - * @return iterable - */ - public function getCollection(string $resourceClass, string $operationName = null); -} diff --git a/src/Core/DataProvider/ContextAwareCollectionDataProviderInterface.php b/src/Core/DataProvider/ContextAwareCollectionDataProviderInterface.php deleted file mode 100644 index 5389ec9bf5d..00000000000 --- a/src/Core/DataProvider/ContextAwareCollectionDataProviderInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * 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\DataProvider; - -/** - * Retrieves items from a persistence layer and allow to pass a context to it. - * - * @author Kévin Dunglas - */ -interface ContextAwareCollectionDataProviderInterface extends CollectionDataProviderInterface -{ - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []); -} diff --git a/src/Core/DataProvider/DenormalizedIdentifiersAwareItemDataProviderInterface.php b/src/Core/DataProvider/DenormalizedIdentifiersAwareItemDataProviderInterface.php deleted file mode 100644 index 07067dc0b25..00000000000 --- a/src/Core/DataProvider/DenormalizedIdentifiersAwareItemDataProviderInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * 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\DataProvider; - -/** - * Marks data providers able to deal with complex identifiers denormalized as an array. - * - * @author Anthony GRASSIOT - */ -interface DenormalizedIdentifiersAwareItemDataProviderInterface extends ItemDataProviderInterface -{ - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, /* array */ $id, string $operationName = null, array $context = []); -} diff --git a/src/Core/DataProvider/ItemDataProviderInterface.php b/src/Core/DataProvider/ItemDataProviderInterface.php deleted file mode 100644 index 5fde5bfbe55..00000000000 --- a/src/Core/DataProvider/ItemDataProviderInterface.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Retrieves items from a persistence layer. - * - * @author Kévin Dunglas - */ -interface ItemDataProviderInterface -{ - /** - * Retrieves an item. - * - * @param array|int|object|string $id - * - * @throws ResourceClassNotSupportedException - * - * @return object|null - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []); -} diff --git a/src/Core/DataProvider/OperationDataProviderTrait.php b/src/Core/DataProvider/OperationDataProviderTrait.php deleted file mode 100644 index 32ad28166d8..00000000000 --- a/src/Core/DataProvider/OperationDataProviderTrait.php +++ /dev/null @@ -1,132 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Core\Identifier\CompositeIdentifierParser; -use ApiPlatform\Core\Identifier\ContextAwareIdentifierConverterInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\RuntimeException; - -/** - * @internal - */ -trait OperationDataProviderTrait -{ - /** - * @var CollectionDataProviderInterface - */ - private $collectionDataProvider; - - /** - * @var ItemDataProviderInterface - */ - private $itemDataProvider; - - /** - * @var SubresourceDataProviderInterface|null - */ - private $subresourceDataProvider; - - /** - * @var IdentifierConverterInterface|null - */ - private $identifierConverter; - - /** - * Retrieves data for a collection operation. - */ - private function getCollectionData(array $attributes, array $context): iterable - { - return $this->collectionDataProvider->getCollection($attributes['resource_class'], $attributes['collection_operation_name'], $context); - } - - /** - * Gets data for an item operation. - * - * @param mixed $identifiers - * - * @return object|null - */ - private function getItemData($identifiers, array $attributes, array $context) - { - return $this->itemDataProvider->getItem($attributes['resource_class'], $identifiers, $attributes['item_operation_name'], $context); - } - - /** - * Gets data for a nested operation. - * - * @param mixed $identifiers - * - * @throws RuntimeException - * - * @return array|object|null - */ - private function getSubresourceData($identifiers, array $attributes, array $context) - { - if (null === $this->subresourceDataProvider) { - throw new RuntimeException('Subresources not supported'); - } - - // TODO: SubresourceDataProvider wants: ['id' => ['id' => 1], 'relatedDummies' => ['id' => 2]], identifiers is ['id' => 1, 'relatedDummies' => 2] - $subresourceIdentifiers = []; - foreach ($attributes['identifiers'] as $parameterName => [$class, $property]) { - if (false !== ($attributes['identifiers'][$parameterName][2] ?? null)) { - $subresourceIdentifiers[$parameterName] = [$property => $identifiers[$parameterName]]; - } - } - - return $this->subresourceDataProvider->getSubresource($attributes['resource_class'], $subresourceIdentifiers, $attributes['subresource_context'] + $context, $attributes['subresource_operation_name']); - } - - /** - * @param array $parameters - usually comes from $request->attributes->all() - * - * @throws InvalidIdentifierException - */ - private function extractIdentifiers(array $parameters, array $attributes) - { - $identifiersKeys = $attributes['identifiers'] ?? ['id' => [$attributes['resource_class'], 'id']]; - $identifiers = []; - - $identifiersNumber = \count($identifiersKeys); - foreach ($identifiersKeys as $parameterName => $identifiedBy) { - if (!isset($parameters[$parameterName])) { - if ($attributes['has_composite_identifier']) { - $identifiers = CompositeIdentifierParser::parse($parameters['id']); - if (($currentIdentifiersNumber = \count($identifiers)) !== $identifiersNumber) { - throw new InvalidIdentifierException(sprintf('Expected %d identifiers, got %d', $identifiersNumber, $currentIdentifiersNumber)); - } - - return $this->identifierConverter->convert($identifiers, $identifiedBy[0]); - } - - // TODO: Subresources tuple may have a third item representing if it is a "collection", this behavior will be removed in 3.0 - if (false === ($identifiedBy[2] ?? null)) { - continue; - } - - throw new InvalidIdentifierException(sprintf('Parameter "%s" not found', $parameterName)); - } - - $identifiers[$parameterName] = $parameters[$parameterName]; - } - - if ($this->identifierConverter instanceof ContextAwareIdentifierConverterInterface) { - return $this->identifierConverter->convert($identifiers, $attributes['resource_class'], ['identifiers' => $identifiersKeys]); - } - - return $this->identifierConverter->convert($identifiers, $attributes['resource_class']); - } -} diff --git a/src/Core/DataProvider/Pagination.php b/src/Core/DataProvider/Pagination.php deleted file mode 100644 index f80907cf548..00000000000 --- a/src/Core/DataProvider/Pagination.php +++ /dev/null @@ -1,271 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Core\Exception\ResourceClassNotFoundException; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; - -/** - * Pagination configuration. - * - * @author Baptiste Meyer - */ -final class Pagination -{ - private $options; - private $graphQlOptions; - private $resourceMetadataFactory; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, array $options = [], array $graphQlOptions = []) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->options = array_merge([ - 'enabled' => true, - 'client_enabled' => false, - 'client_items_per_page' => false, - 'items_per_page' => 30, - 'page_default' => 1, - 'page_parameter_name' => 'page', - 'enabled_parameter_name' => 'pagination', - 'items_per_page_parameter_name' => 'itemsPerPage', - 'maximum_items_per_page' => null, - 'partial' => false, - 'client_partial' => false, - 'partial_parameter_name' => 'partial', - ], $options); - $this->graphQlOptions = array_merge([ - 'enabled' => true, - ], $graphQlOptions); - } - - /** - * Gets the current page. - * - * @throws InvalidArgumentException - */ - public function getPage(array $context = []): int - { - $page = (int) $this->getParameterFromContext( - $context, - $this->options['page_parameter_name'], - $this->options['page_default'] - ); - - if (1 > $page) { - throw new InvalidArgumentException('Page should not be less than 1'); - } - - return $page; - } - - /** - * Gets the current offset. - */ - public function getOffset(string $resourceClass = null, string $operationName = null, array $context = []): int - { - $graphql = (bool) ($context['graphql_operation_name'] ?? false); - - $limit = $this->getLimit($resourceClass, $operationName, $context); - - if ($graphql && null !== ($after = $this->getParameterFromContext($context, 'after'))) { - return false === ($after = base64_decode($after, true)) ? 0 : (int) $after + 1; - } - - if ($graphql && null !== ($before = $this->getParameterFromContext($context, 'before'))) { - return ($offset = (false === ($before = base64_decode($before, true)) ? 0 : (int) $before - $limit)) < 0 ? 0 : $offset; - } - - if ($graphql && null !== ($last = $this->getParameterFromContext($context, 'last'))) { - return ($offset = ($context['count'] ?? 0) - $last) < 0 ? 0 : $offset; - } - - $offset = ($this->getPage($context) - 1) * $limit; - - if (!\is_int($offset)) { - throw new InvalidArgumentException('Page parameter is too large.'); - } - - return $offset; - } - - /** - * Gets the current limit. - * - * @throws InvalidArgumentException - */ - public function getLimit(string $resourceClass = null, string $operationName = null, array $context = []): int - { - $graphql = (bool) ($context['graphql_operation_name'] ?? false); - - $limit = $this->options['items_per_page']; - $clientLimit = $this->options['client_items_per_page']; - - if (null !== $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $limit = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', $limit, true); - $clientLimit = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $clientLimit, true); - } - - if ($graphql && null !== ($first = $this->getParameterFromContext($context, 'first'))) { - $limit = $first; - } - - if ($graphql && null !== ($last = $this->getParameterFromContext($context, 'last'))) { - $limit = $last; - } - - if ($graphql && null !== ($before = $this->getParameterFromContext($context, 'before')) - && (false === ($before = base64_decode($before, true)) ? 0 : (int) $before - $limit) < 0) { - $limit = (int) $before; - } - - if ($clientLimit) { - $limit = (int) $this->getParameterFromContext($context, $this->options['items_per_page_parameter_name'], $limit); - $maxItemsPerPage = null; - - if (null !== $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'maximum_items_per_page', null, true); - if (null !== $maxItemsPerPage) { - @trigger_error('The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3.', \E_USER_DEPRECATED); - } - $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage ?? $this->options['maximum_items_per_page'], true); - } - - if (null !== $maxItemsPerPage && $limit > $maxItemsPerPage) { - $limit = $maxItemsPerPage; - } - } - - if (0 > $limit) { - throw new InvalidArgumentException('Limit should not be less than 0'); - } - - return $limit; - } - - /** - * Gets info about the pagination. - * - * Returns an array with the following info as values: - * - the page {@see Pagination::getPage()} - * - the offset {@see Pagination::getOffset()} - * - the limit {@see Pagination::getLimit()} - * - * @throws InvalidArgumentException - */ - public function getPagination(string $resourceClass = null, string $operationName = null, array $context = []): array - { - $page = $this->getPage($context); - $limit = $this->getLimit($resourceClass, $operationName, $context); - - if (0 === $limit && 1 < $page) { - throw new InvalidArgumentException('Page should not be greater than 1 if limit is equal to 0'); - } - - return [$page, $this->getOffset($resourceClass, $operationName, $context), $limit]; - } - - /** - * Is the pagination enabled? - */ - public function isEnabled(string $resourceClass = null, string $operationName = null, array $context = []): bool - { - return $this->getEnabled($context, $resourceClass, $operationName); - } - - /** - * Is the pagination enabled for GraphQL? - */ - public function isGraphQlEnabled(?string $resourceClass = null, ?string $operationName = null, array $context = []): bool - { - return $this->getGraphQlEnabled($resourceClass, $operationName); - } - - /** - * Is the partial pagination enabled? - */ - public function isPartialEnabled(string $resourceClass = null, string $operationName = null, array $context = []): bool - { - return $this->getEnabled($context, $resourceClass, $operationName, true); - } - - public function getOptions(): array - { - return $this->options; - } - - public function getGraphQlPaginationType(string $resourceClass, string $operationName): string - { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - return 'cursor'; - } - - return (string) $resourceMetadata->getGraphqlAttribute($operationName, 'pagination_type', 'cursor', true); - } - - /** - * Is the classic or partial pagination enabled? - */ - private function getEnabled(array $context, string $resourceClass = null, string $operationName = null, bool $partial = false): bool - { - $enabled = $this->options[$partial ? 'partial' : 'enabled']; - $clientEnabled = $this->options[$partial ? 'client_partial' : 'client_enabled']; - - if (null !== $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $enabled = $resourceMetadata->getCollectionOperationAttribute($operationName, $partial ? 'pagination_partial' : 'pagination_enabled', $enabled, true); - - $clientEnabled = $resourceMetadata->getCollectionOperationAttribute($operationName, $partial ? 'pagination_client_partial' : 'pagination_client_enabled', $clientEnabled, true); - } - - if ($clientEnabled) { - return filter_var($this->getParameterFromContext($context, $this->options[$partial ? 'partial_parameter_name' : 'enabled_parameter_name'], $enabled), \FILTER_VALIDATE_BOOLEAN); - } - - return (bool) $enabled; - } - - private function getGraphQlEnabled(?string $resourceClass, ?string $operationName): bool - { - $enabled = $this->graphQlOptions['enabled']; - - if (null !== $resourceClass) { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - return $enabled; - } - - return (bool) $resourceMetadata->getGraphqlAttribute($operationName, 'pagination_enabled', $enabled, true); - } - - return $enabled; - } - - /** - * Gets the given pagination parameter name from the given context. - * - * @param mixed|null $default - */ - private function getParameterFromContext(array $context, string $parameterName, $default = null) - { - $filters = $context['filters'] ?? []; - - return \array_key_exists($parameterName, $filters) ? $filters[$parameterName] : $default; - } -} diff --git a/src/Core/DataProvider/PaginationOptions.php b/src/Core/DataProvider/PaginationOptions.php deleted file mode 100644 index 504ef049c8a..00000000000 --- a/src/Core/DataProvider/PaginationOptions.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\DataProvider; - -class_exists(\ApiPlatform\State\Pagination\PaginationOptions::class); - -if (false) { - final class PaginationOptions extends \ApiPlatform\State\Pagination\PaginationOptions - { - } -} diff --git a/src/Core/DataProvider/RestrictDataProviderTrait.php b/src/Core/DataProvider/RestrictDataProviderTrait.php deleted file mode 100644 index 4e2570b16f4..00000000000 --- a/src/Core/DataProvider/RestrictDataProviderTrait.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * 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\DataProvider; - -trait RestrictDataProviderTrait -{ - /** @internal */ - public $dataProviders = []; - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - foreach ($this->dataProviders as $dataProvider) { - if ($dataProvider instanceof RestrictedDataProviderInterface - && $dataProvider->supports($resourceClass, $operationName, $context)) { - return true; - } - } - - return false; - } -} diff --git a/src/Core/DataProvider/RestrictedDataProviderInterface.php b/src/Core/DataProvider/RestrictedDataProviderInterface.php deleted file mode 100644 index 5eb5a560540..00000000000 --- a/src/Core/DataProvider/RestrictedDataProviderInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\DataProvider; - -/** - * Restricts a data provider based on a condition. - */ -interface RestrictedDataProviderInterface -{ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool; -} diff --git a/src/Core/DataProvider/SerializerAwareDataProviderInterface.php b/src/Core/DataProvider/SerializerAwareDataProviderInterface.php deleted file mode 100644 index b3989c5d52d..00000000000 --- a/src/Core/DataProvider/SerializerAwareDataProviderInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * 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\DataProvider; - -use Psr\Container\ContainerInterface; - -/** - * Injects serializer in data providers. - * - * @author Vincent Chalamon - */ -interface SerializerAwareDataProviderInterface -{ - public function setSerializerLocator(ContainerInterface $serializerLocator); -} diff --git a/src/Core/DataProvider/SerializerAwareDataProviderTrait.php b/src/Core/DataProvider/SerializerAwareDataProviderTrait.php deleted file mode 100644 index 275df97d172..00000000000 --- a/src/Core/DataProvider/SerializerAwareDataProviderTrait.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * 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\DataProvider; - -use Psr\Container\ContainerInterface; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * Injects serializer in data providers. - * - * @author Vincent Chalamon - */ -trait SerializerAwareDataProviderTrait -{ - /** - * @internal - * - * @var ContainerInterface - */ - private $serializerLocator; - - public function setSerializerLocator(ContainerInterface $serializerLocator): void - { - $this->serializerLocator = $serializerLocator; - } - - private function getSerializer(): SerializerInterface - { - /* @var SerializerInterface */ - return $this->serializerLocator->get('serializer'); - } -} diff --git a/src/Core/DataProvider/SubresourceDataProviderInterface.php b/src/Core/DataProvider/SubresourceDataProviderInterface.php deleted file mode 100644 index 1b569c0bded..00000000000 --- a/src/Core/DataProvider/SubresourceDataProviderInterface.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Exception\ResourceClassNotSupportedException; - -/** - * Retrieves subresources from a persistence layer. - * - * @author Antoine Bluchet - */ -interface SubresourceDataProviderInterface -{ - /** - * Retrieves a subresource of an item. - * - * @param string $resourceClass The root resource class - * @param array $identifiers Identifiers and their values - * @param array $context The context indicates the conjunction between collection properties (identifiers) and their class - * @param string $operationName - * - * @throws ResourceClassNotSupportedException - * - * @return iterable|object|null - */ - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null); -} diff --git a/src/Core/DataProvider/TraversablePaginator.php b/src/Core/DataProvider/TraversablePaginator.php deleted file mode 100644 index 0a0cd9c791c..00000000000 --- a/src/Core/DataProvider/TraversablePaginator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\DataProvider; - -class_exists(\ApiPlatform\State\Pagination\TraversablePaginator::class); - -if (false) { - final class TraversablePaginator extends \ApiPlatform\State\Pagination\TraversablePaginator - { - } -} diff --git a/src/Core/DataTransformer/DataTransformerInitializerInterface.php b/src/Core/DataTransformer/DataTransformerInitializerInterface.php deleted file mode 100644 index 85007c818e1..00000000000 --- a/src/Core/DataTransformer/DataTransformerInitializerInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * 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\DataTransformer; - -interface DataTransformerInitializerInterface extends DataTransformerInterface -{ - /** - * Creates a new DTO object that the data will then be serialized into (using object_to_populate). - * - * This is useful to "initialize" the DTO object based on the current resource's data. - * - * @return object|null - */ - public function initialize(string $inputClass, array $context = []); -} diff --git a/src/Core/DataTransformer/DataTransformerInterface.php b/src/Core/DataTransformer/DataTransformerInterface.php deleted file mode 100644 index 156c0ffe437..00000000000 --- a/src/Core/DataTransformer/DataTransformerInterface.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * 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\DataTransformer; - -/** - * Transforms a DTO or an Anonymous class to a Resource object. - * - * @author Antoine Bluchet - */ -interface DataTransformerInterface -{ - /** - * Transforms the given object to something else, usually another object. - * This must return the original object if no transformations have been done. - * - * @param object $object - * - * @return object - */ - public function transform($object, string $to, array $context = []); - - /** - * Checks whether the transformation is supported for a given data and context. - * - * @param object|array $data object on normalize / array on denormalize - */ - public function supportsTransformation($data, string $to, array $context = []): bool; -} diff --git a/src/Core/Documentation/Action/DocumentationAction.php b/src/Core/Documentation/Action/DocumentationAction.php deleted file mode 100644 index e8993c4c910..00000000000 --- a/src/Core/Documentation/Action/DocumentationAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Documentation\Action; - -class_exists(\ApiPlatform\Documentation\Action\DocumentationAction::class); - -if (false) { - final class DocumentationAction extends \ApiPlatform\Documentation\Action\DocumentationAction - { - } -} diff --git a/src/Core/Documentation/Documentation.php b/src/Core/Documentation/Documentation.php deleted file mode 100644 index 190348f24bc..00000000000 --- a/src/Core/Documentation/Documentation.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Documentation; - -class_exists(\ApiPlatform\Documentation\Documentation::class); - -if (false) { - final class Documentation extends \ApiPlatform\Documentation\Documentation - { - } -} diff --git a/src/Core/EventListener/AddFormatListener.php b/src/Core/EventListener/AddFormatListener.php deleted file mode 100644 index c7f8a0849f6..00000000000 --- a/src/Core/EventListener/AddFormatListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\AddFormatListener::class); - -if (false) { - final class AddFormatListener extends \ApiPlatform\Symfony\EventListener\AddFormatListener - { - } -} diff --git a/src/Core/EventListener/DeserializeListener.php b/src/Core/EventListener/DeserializeListener.php deleted file mode 100644 index 82b852022aa..00000000000 --- a/src/Core/EventListener/DeserializeListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\DeserializeListener::class); - -if (false) { - final class DeserializeListener extends \ApiPlatform\Symfony\EventListener\DeserializeListener - { - } -} diff --git a/src/Core/EventListener/EventPriorities.php b/src/Core/EventListener/EventPriorities.php deleted file mode 100644 index 48b44ea76e6..00000000000 --- a/src/Core/EventListener/EventPriorities.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\EventPriorities::class); - -if (false) { - final class EventPriorities extends \ApiPlatform\Symfony\EventListener\EventPriorities - { - } -} diff --git a/src/Core/EventListener/ExceptionListener.php b/src/Core/EventListener/ExceptionListener.php deleted file mode 100644 index 1e5a20e9413..00000000000 --- a/src/Core/EventListener/ExceptionListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\ExceptionListener::class); - -if (false) { - final class ExceptionListener extends \ApiPlatform\Symfony\EventListener\ExceptionListener - { - } -} diff --git a/src/Core/EventListener/QueryParameterValidateListener.php b/src/Core/EventListener/QueryParameterValidateListener.php deleted file mode 100644 index 9db39bd2db2..00000000000 --- a/src/Core/EventListener/QueryParameterValidateListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\QueryParameterValidateListener::class); - -if (false) { - final class QueryParameterValidateListener extends \ApiPlatform\Symfony\EventListener\QueryParameterValidateListener - { - } -} diff --git a/src/Core/EventListener/ReadListener.php b/src/Core/EventListener/ReadListener.php deleted file mode 100644 index b795c81ea03..00000000000 --- a/src/Core/EventListener/ReadListener.php +++ /dev/null @@ -1,143 +0,0 @@ - - * - * 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\EventListener; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\OperationDataProviderTrait; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Symfony\EventListener\ReadListener as SymfonyReadListener; -use ApiPlatform\Util\CloneTrait; -use ApiPlatform\Util\OperationRequestInitiatorTrait; -use ApiPlatform\Util\RequestAttributesExtractor; -use ApiPlatform\Util\RequestParser; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -/** - * Retrieves data from the applicable data provider and sets it as a request parameter called data. - * - * @author Kévin Dunglas - * - * @deprecated - */ -final class ReadListener -{ - use CloneTrait; - use OperationDataProviderTrait; - use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; - - public const OPERATION_ATTRIBUTE_KEY = 'read'; - - private $serializerContextBuilder; - private $metadataBackwardCompatibilityLayer; - - public function __construct(CollectionDataProviderInterface $collectionDataProvider, ItemDataProviderInterface $itemDataProvider, SubresourceDataProviderInterface $subresourceDataProvider = null, SerializerContextBuilderInterface $serializerContextBuilder = null, IdentifierConverterInterface $identifierConverter = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, bool $metadataBackwardCompatibilityLayer = null) - { - $this->collectionDataProvider = $collectionDataProvider; - $this->itemDataProvider = $itemDataProvider; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->serializerContextBuilder = $serializerContextBuilder; - $this->identifierConverter = $identifierConverter; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; - $this->metadataBackwardCompatibilityLayer = $metadataBackwardCompatibilityLayer; - - if ($metadataBackwardCompatibilityLayer || null === $metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The listener "%s" is deprecated and will be replaced by "%s" in 3.0.', __CLASS__, SymfonyReadListener::class)); - } - } - - /** - * Calls the data provider and sets the data attribute. - * - * @throws NotFoundHttpException - */ - public function onKernelRequest(RequestEvent $event): void - { - $request = $event->getRequest(); - $operation = $this->initializeOperation($request); - - if ( - !($attributes = RequestAttributesExtractor::extractAttributes($request)) - || !$attributes['receive'] - || ($request->isMethod('POST') && isset($attributes['collection_operation_name'])) - || ($operation && !($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) && !($operation->getExtraProperties()['is_legacy_subresource'] ?? false)) - || ($operation && false === $operation->canRead()) - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) - ) { - return; - } - - if (false === $this->metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', 'The operation you requested uses legacy metadata, switch to #[ApiPlatform\Metadata\ApiResource].'); - } - - if (null === $filters = $request->attributes->get('_api_filters')) { - $queryString = RequestParser::getQueryString($request); - $filters = $queryString ? RequestParser::parseRequestParams($queryString) : null; - } - - $context = null === $filters ? [] : ['filters' => $filters]; - if ($this->serializerContextBuilder) { - // Builtin data providers are able to use the serialization context to automatically add join clauses - $context += $normalizationContext = $this->serializerContextBuilder->createFromRequest($request, true, $attributes); - $request->attributes->set('_api_normalization_context', $normalizationContext); - } - - if (isset($attributes['collection_operation_name'])) { - $request->attributes->set('data', $this->getCollectionData($attributes, $context)); - - return; - } - - $data = []; - - if ($this->identifierConverter) { - $context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] = true; - } - - try { - $identifiers = $this->extractIdentifiers($request->attributes->all(), $attributes); - - if (isset($attributes['item_operation_name'])) { - $data = $this->getItemData($identifiers, $attributes, $context); - } elseif (isset($attributes['subresource_operation_name'])) { - // Legacy - if (null === $this->subresourceDataProvider) { - throw new RuntimeException('No subresource data provider.'); - } - - $data = $this->getSubresourceData($identifiers, $attributes, $context); - } - } catch (InvalidIdentifierException $e) { - throw new NotFoundHttpException('Invalid identifier value or configuration.', $e); - } - - if (null === $data) { - throw new NotFoundHttpException('Not Found'); - } - - $request->attributes->set('data', $data); - $request->attributes->set('previous_data', $this->clone($data)); - } -} diff --git a/src/Core/EventListener/RespondListener.php b/src/Core/EventListener/RespondListener.php deleted file mode 100644 index 26530c66564..00000000000 --- a/src/Core/EventListener/RespondListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\RespondListener::class); - -if (false) { - final class RespondListener extends \ApiPlatform\Symfony\EventListener\RespondListener - { - } -} diff --git a/src/Core/EventListener/SerializeListener.php b/src/Core/EventListener/SerializeListener.php deleted file mode 100644 index 470982b00c1..00000000000 --- a/src/Core/EventListener/SerializeListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\SerializeListener::class); - -if (false) { - final class SerializeListener extends \ApiPlatform\Symfony\EventListener\SerializeListener - { - } -} diff --git a/src/Core/EventListener/WriteListener.php b/src/Core/EventListener/WriteListener.php deleted file mode 100644 index 870687bfd1e..00000000000 --- a/src/Core/EventListener/WriteListener.php +++ /dev/null @@ -1,134 +0,0 @@ - - * - * 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\EventListener; - -use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Util\OperationRequestInitiatorTrait; -use ApiPlatform\Util\RequestAttributesExtractor; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ViewEvent; - -/** - * Bridges persistence and the API system. - * - * @author Kévin Dunglas - * @author Baptiste Meyer - * - * @deprecated - */ -final class WriteListener -{ - use OperationRequestInitiatorTrait; - use ResourceClassInfoTrait; - use ToggleableOperationAttributeTrait; - - public const OPERATION_ATTRIBUTE_KEY = 'write'; - - private $dataPersister; - /** @var LegacyIriConverterInterface|IriConverterInterface|null */ - private $iriConverter; - private $metadataBackwardCompatibilityLayer; - - public function __construct(DataPersisterInterface $dataPersister, $iriConverter = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null, ResourceClassResolverInterface $resourceClassResolver = null, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ?bool $metadataBackwardCompatibilityLayer = null) - { - $this->dataPersister = $dataPersister; - $this->iriConverter = $iriConverter; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->resourceClassResolver = $resourceClassResolver; - $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; - $this->metadataBackwardCompatibilityLayer = $metadataBackwardCompatibilityLayer; - - if ($metadataBackwardCompatibilityLayer || null === $metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The listener "%s" is deprecated and will be removed in 3.0, use "%s" instead', __CLASS__, \ApiPlatform\Symfony\EventListener\WriteListener::class)); - } - } - - /** - * Persists, updates or delete data return by the controller if applicable. - */ - public function onKernelView(ViewEvent $event): void - { - $controllerResult = $event->getControllerResult(); - $request = $event->getRequest(); - $operation = $this->initializeOperation($request); - - if ( - $controllerResult instanceof Response - || $request->isMethodSafe() - || !($attributes = RequestAttributesExtractor::extractAttributes($request)) - || !$attributes['persist'] - || ($operation && !($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false)) - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) - ) { - return; - } - - if (false === $this->metadataBackwardCompatibilityLayer) { - trigger_deprecation('api-platform/core', '2.7', 'The operation you requested uses legacy metadata, switch to #[ApiPlatform\Metadata\ApiResource].'); - } - - if (!$this->dataPersister->supports($controllerResult, $attributes)) { - return; - } - - switch ($request->getMethod()) { - case 'PUT': - case 'PATCH': - case 'POST': - $persistResult = $this->dataPersister->persist($controllerResult, $attributes); - - if (!\is_object($persistResult)) { - @trigger_error(sprintf('Not returning an object from %s::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3.', DataPersisterInterface::class), \E_USER_DEPRECATED); - } else { - $controllerResult = $persistResult; - $event->setControllerResult($controllerResult); - } - - if ($controllerResult instanceof Response) { - break; - } - - $hasOutput = true; - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - $outputMetadata = $resourceMetadata->getOperationAttribute($attributes, 'output', [ - 'class' => $attributes['resource_class'], - ], true); - - $hasOutput = \array_key_exists('class', $outputMetadata) && null !== $outputMetadata['class']; - } - - if (!$hasOutput) { - break; - } - - if ($this->isResourceClass($this->getObjectClass($controllerResult))) { - $request->attributes->set('_api_write_item_iri', $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($controllerResult) : $this->iriConverter->getIriFromResource($controllerResult)); - } - - break; - case 'DELETE': - $this->dataPersister->remove($controllerResult, $attributes); - $event->setControllerResult(null); - break; - } - } -} diff --git a/src/Core/Exception/DeserializationException.php b/src/Core/Exception/DeserializationException.php deleted file mode 100644 index eb4ba833f02..00000000000 --- a/src/Core/Exception/DeserializationException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\DeserializationException::class); - -if (false) { - class DeserializationException extends \ApiPlatform\Exception\DeserializationException - { - } -} diff --git a/src/Core/Exception/FilterValidationException.php b/src/Core/Exception/FilterValidationException.php deleted file mode 100644 index 3fe044a9f10..00000000000 --- a/src/Core/Exception/FilterValidationException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\FilterValidationException::class); - -if (false) { - final class FilterValidationException extends \ApiPlatform\Exception\FilterValidationException - { - } -} diff --git a/src/Core/Exception/InvalidArgumentException.php b/src/Core/Exception/InvalidArgumentException.php deleted file mode 100644 index 6b2be87d603..00000000000 --- a/src/Core/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\InvalidArgumentException::class); - -if (false) { - class InvalidArgumentException extends \ApiPlatform\Exception\InvalidArgumentException - { - } -} diff --git a/src/Core/Exception/InvalidIdentifierException.php b/src/Core/Exception/InvalidIdentifierException.php deleted file mode 100644 index 2ab797b1b3b..00000000000 --- a/src/Core/Exception/InvalidIdentifierException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\InvalidIdentifierException::class); - -if (false) { - final class InvalidIdentifierException extends \ApiPlatform\Exception\InvalidIdentifierException - { - } -} diff --git a/src/Core/Exception/InvalidResourceException.php b/src/Core/Exception/InvalidResourceException.php deleted file mode 100644 index dafb4df9a64..00000000000 --- a/src/Core/Exception/InvalidResourceException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\InvalidResourceException::class); - -if (false) { - class InvalidResourceException extends \ApiPlatform\Exception\InvalidResourceException - { - } -} diff --git a/src/Core/Exception/InvalidValueException.php b/src/Core/Exception/InvalidValueException.php deleted file mode 100644 index a0fc7cc2bc3..00000000000 --- a/src/Core/Exception/InvalidValueException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\InvalidValueException::class); - -if (false) { - class InvalidValueException extends \ApiPlatform\Exception\InvalidValueException - { - } -} diff --git a/src/Core/Exception/ItemNotFoundException.php b/src/Core/Exception/ItemNotFoundException.php deleted file mode 100644 index d6d83fb3d7c..00000000000 --- a/src/Core/Exception/ItemNotFoundException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\ItemNotFoundException::class); - -if (false) { - class ItemNotFoundException extends \ApiPlatform\Exception\ItemNotFoundException - { - } -} diff --git a/src/Core/Exception/PropertyNotFoundException.php b/src/Core/Exception/PropertyNotFoundException.php deleted file mode 100644 index 1bc4ac9c520..00000000000 --- a/src/Core/Exception/PropertyNotFoundException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\PropertyNotFoundException::class); - -if (false) { - class PropertyNotFoundException extends \ApiPlatform\Exception\PropertyNotFoundException - { - } -} diff --git a/src/Core/Exception/ResourceClassNotFoundException.php b/src/Core/Exception/ResourceClassNotFoundException.php deleted file mode 100644 index 1becbf78554..00000000000 --- a/src/Core/Exception/ResourceClassNotFoundException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\ResourceClassNotFoundException::class); - -if (false) { - class ResourceClassNotFoundException extends \ApiPlatform\Exception\ResourceClassNotFoundException - { - } -} diff --git a/src/Core/Exception/ResourceClassNotSupportedException.php b/src/Core/Exception/ResourceClassNotSupportedException.php deleted file mode 100644 index a30cdcf38e4..00000000000 --- a/src/Core/Exception/ResourceClassNotSupportedException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\ResourceClassNotSupportedException::class); - -if (false) { - class ResourceClassNotSupportedException extends \ApiPlatform\Exception\ResourceClassNotSupportedException - { - } -} diff --git a/src/Core/Exception/RuntimeException.php b/src/Core/Exception/RuntimeException.php deleted file mode 100644 index 3fc53363342..00000000000 --- a/src/Core/Exception/RuntimeException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Exception; - -class_exists(\ApiPlatform\Exception\RuntimeException::class); - -if (false) { - class RuntimeException extends \ApiPlatform\Exception\RuntimeException - { - } -} diff --git a/src/Core/Filter/QueryParameterValidator.php b/src/Core/Filter/QueryParameterValidator.php deleted file mode 100644 index 0d080b6be1b..00000000000 --- a/src/Core/Filter/QueryParameterValidator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Filter; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator::class); - -if (false) { - class QueryParameterValidator extends \ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator - { - } -} diff --git a/src/Core/Filter/Validator/ArrayItems.php b/src/Core/Filter/Validator/ArrayItems.php deleted file mode 100644 index 99e914f9ec9..00000000000 --- a/src/Core/Filter/Validator/ArrayItems.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\ArrayItems::class); - -if (false) { - final class ArrayItems extends \ApiPlatform\Api\QueryParameterValidator\Validator\ArrayItems - { - } -} diff --git a/src/Core/Filter/Validator/Bounds.php b/src/Core/Filter/Validator/Bounds.php deleted file mode 100644 index 6b27ba69bda..00000000000 --- a/src/Core/Filter/Validator/Bounds.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Bounds::class); - -if (false) { - final class Bounds extends \ApiPlatform\Api\QueryParameterValidator\Validator\Bounds - { - } -} diff --git a/src/Core/Filter/Validator/Enum.php b/src/Core/Filter/Validator/Enum.php deleted file mode 100644 index ad3ee478608..00000000000 --- a/src/Core/Filter/Validator/Enum.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Enum::class); - -if (false) { - final class Enum extends \ApiPlatform\Api\QueryParameterValidator\Validator\Enum - { - } -} diff --git a/src/Core/Filter/Validator/Length.php b/src/Core/Filter/Validator/Length.php deleted file mode 100644 index 6c743c0a997..00000000000 --- a/src/Core/Filter/Validator/Length.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Length::class); - -if (false) { - final class Length extends \ApiPlatform\Api\QueryParameterValidator\Validator\Length - { - } -} diff --git a/src/Core/Filter/Validator/MultipleOf.php b/src/Core/Filter/Validator/MultipleOf.php deleted file mode 100644 index fa4f3180cc6..00000000000 --- a/src/Core/Filter/Validator/MultipleOf.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\MultipleOf::class); - -if (false) { - final class MultipleOf extends \ApiPlatform\Api\QueryParameterValidator\Validator\MultipleOf - { - } -} diff --git a/src/Core/Filter/Validator/Pattern.php b/src/Core/Filter/Validator/Pattern.php deleted file mode 100644 index bbb0aaa1cdd..00000000000 --- a/src/Core/Filter/Validator/Pattern.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Pattern::class); - -if (false) { - final class Pattern extends \ApiPlatform\Api\QueryParameterValidator\Validator\Pattern - { - } -} diff --git a/src/Core/Filter/Validator/Required.php b/src/Core/Filter/Validator/Required.php deleted file mode 100644 index 71f13283d90..00000000000 --- a/src/Core/Filter/Validator/Required.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Filter\Validator; - -class_exists(\ApiPlatform\Api\QueryParameterValidator\Validator\Required::class); - -if (false) { - final class Required extends \ApiPlatform\Api\QueryParameterValidator\Validator\Required - { - } -} diff --git a/src/Core/GraphQl/Action/EntrypointAction.php b/src/Core/GraphQl/Action/EntrypointAction.php deleted file mode 100644 index 771447e1ef9..00000000000 --- a/src/Core/GraphQl/Action/EntrypointAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Action; - -class_exists(\ApiPlatform\GraphQl\Action\EntrypointAction::class); - -if (false) { - final class EntrypointAction extends \ApiPlatform\GraphQl\Action\EntrypointAction - { - } -} diff --git a/src/Core/GraphQl/Action/GraphQlPlaygroundAction.php b/src/Core/GraphQl/Action/GraphQlPlaygroundAction.php deleted file mode 100644 index ff553d7aa31..00000000000 --- a/src/Core/GraphQl/Action/GraphQlPlaygroundAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Action; - -class_exists(\ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction::class); - -if (false) { - final class GraphQlPlaygroundAction extends \ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction - { - } -} diff --git a/src/Core/GraphQl/Action/GraphiQlAction.php b/src/Core/GraphQl/Action/GraphiQlAction.php deleted file mode 100644 index ee069ed2b08..00000000000 --- a/src/Core/GraphQl/Action/GraphiQlAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Action; - -class_exists(\ApiPlatform\GraphQl\Action\GraphiQlAction::class); - -if (false) { - final class GraphiQlAction extends \ApiPlatform\GraphQl\Action\GraphiQlAction - { - } -} diff --git a/src/Core/GraphQl/Error/ErrorHandler.php b/src/Core/GraphQl/Error/ErrorHandler.php deleted file mode 100644 index 1061371edeb..00000000000 --- a/src/Core/GraphQl/Error/ErrorHandler.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Error; - -class_exists(\ApiPlatform\GraphQl\Error\ErrorHandler::class); - -if (false) { - final class ErrorHandler extends \ApiPlatform\GraphQl\Error\ErrorHandler - { - } -} diff --git a/src/Core/GraphQl/Executor.php b/src/Core/GraphQl/Executor.php deleted file mode 100644 index f0cc9948085..00000000000 --- a/src/Core/GraphQl/Executor.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl; - -class_exists(\ApiPlatform\GraphQl\Executor::class); - -if (false) { - final class Executor extends \ApiPlatform\GraphQl\Executor - { - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/CollectionResolverFactory.php b/src/Core/GraphQl/Resolver/Factory/CollectionResolverFactory.php deleted file mode 100644 index 8fff34f5643..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/CollectionResolverFactory.php +++ /dev/null @@ -1,105 +0,0 @@ - - * - * 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\GraphQl\Resolver\Factory; - -use ApiPlatform\Core\GraphQl\Resolver\QueryCollectionResolverInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\CloneTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\RequestStack; - -/** - * Creates a function retrieving a collection to resolve a GraphQL query or a field returned by a mutation. - * - * @experimental - * - * @author Alan Poulain - * @author Kévin Dunglas - * @author Vincent Chalamon - */ -final class CollectionResolverFactory implements ResolverFactoryInterface -{ - use CloneTrait; - - private $readStage; - private $securityStage; - private $securityPostDenormalizeStage; - private $serializeStage; - private $queryResolverLocator; - private $requestStack; - private $resourceMetadataFactory; - - public function __construct(ReadStageInterface $readStage, SecurityStageInterface $securityStage, SecurityPostDenormalizeStageInterface $securityPostDenormalizeStage, SerializeStageInterface $serializeStage, ContainerInterface $queryResolverLocator, ResourceMetadataFactoryInterface $resourceMetadataFactory, RequestStack $requestStack = null) - { - $this->readStage = $readStage; - $this->securityStage = $securityStage; - $this->securityPostDenormalizeStage = $securityPostDenormalizeStage; - $this->serializeStage = $serializeStage; - $this->queryResolverLocator = $queryResolverLocator; - $this->requestStack = $requestStack; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable - { - return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { - if (null === $resourceClass || null === $rootClass) { - return null; - } - - if ($this->requestStack && null !== $request = $this->requestStack->getCurrentRequest()) { - $request->attributes->set( - '_graphql_collections_args', - [$resourceClass => $args] + $request->attributes->get('_graphql_collections_args', []) - ); - } - - $operationName = $operationName ?? 'collection_query'; - $resolverContext = ['source' => $source, 'args' => $args, 'info' => $info, 'is_collection' => true, 'is_mutation' => false, 'is_subscription' => false]; - - $collection = ($this->readStage)($resourceClass, $rootClass, $operationName, $resolverContext); - if (!is_iterable($collection)) { - throw new \LogicException('Collection from read stage should be iterable.'); - } - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $queryResolverId = $resourceMetadata->getGraphqlAttribute($operationName, 'collection_query'); - if (null !== $queryResolverId) { - /** @var QueryCollectionResolverInterface $queryResolver */ - $queryResolver = $this->queryResolverLocator->get($queryResolverId); - $collection = $queryResolver($collection, $resolverContext); - } - - ($this->securityStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $collection, - ], - ]); - ($this->securityPostDenormalizeStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $collection, - 'previous_object' => $this->clone($collection), - ], - ]); - - return ($this->serializeStage)($collection, $resourceClass, $operationName, $resolverContext); - }; - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/ItemMutationResolverFactory.php b/src/Core/GraphQl/Resolver/Factory/ItemMutationResolverFactory.php deleted file mode 100644 index 45fc233f00a..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/ItemMutationResolverFactory.php +++ /dev/null @@ -1,128 +0,0 @@ - - * - * 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\GraphQl\Resolver\Factory; - -use ApiPlatform\Core\GraphQl\Resolver\MutationResolverInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\DeserializeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\ValidateStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\WriteStageInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ClassInfoTrait; -use ApiPlatform\Core\Util\CloneTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Psr\Container\ContainerInterface; - -/** - * Creates a function resolving a GraphQL mutation of an item. - * - * @experimental - * - * @author Alan Poulain - * @author Vincent Chalamon - */ -final class ItemMutationResolverFactory implements ResolverFactoryInterface -{ - use ClassInfoTrait; - use CloneTrait; - - private $readStage; - private $securityStage; - private $securityPostDenormalizeStage; - private $serializeStage; - private $deserializeStage; - private $writeStage; - private $validateStage; - private $mutationResolverLocator; - private $resourceMetadataFactory; - - public function __construct(ReadStageInterface $readStage, SecurityStageInterface $securityStage, SecurityPostDenormalizeStageInterface $securityPostDenormalizeStage, SerializeStageInterface $serializeStage, DeserializeStageInterface $deserializeStage, WriteStageInterface $writeStage, ValidateStageInterface $validateStage, ContainerInterface $mutationResolverLocator, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - $this->readStage = $readStage; - $this->securityStage = $securityStage; - $this->securityPostDenormalizeStage = $securityPostDenormalizeStage; - $this->serializeStage = $serializeStage; - $this->deserializeStage = $deserializeStage; - $this->writeStage = $writeStage; - $this->validateStage = $validateStage; - $this->mutationResolverLocator = $mutationResolverLocator; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable - { - return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { - if (null === $resourceClass || null === $operationName) { - return null; - } - - $resolverContext = ['source' => $source, 'args' => $args, 'info' => $info, 'is_collection' => false, 'is_mutation' => true, 'is_subscription' => false]; - - $item = ($this->readStage)($resourceClass, $rootClass, $operationName, $resolverContext); - if (null !== $item && !\is_object($item)) { - throw new \LogicException('Item from read stage should be a nullable object.'); - } - ($this->securityStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - ], - ]); - $previousItem = $this->clone($item); - - if ('delete' === $operationName) { - ($this->securityPostDenormalizeStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - 'previous_object' => $previousItem, - ], - ]); - $item = ($this->writeStage)($item, $resourceClass, $operationName, $resolverContext); - - return ($this->serializeStage)($item, $resourceClass, $operationName, $resolverContext); - } - - $item = ($this->deserializeStage)($item, $resourceClass, $operationName, $resolverContext); - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $mutationResolverId = $resourceMetadata->getGraphqlAttribute($operationName, 'mutation'); - if (null !== $mutationResolverId) { - /** @var MutationResolverInterface $mutationResolver */ - $mutationResolver = $this->mutationResolverLocator->get($mutationResolverId); - $item = $mutationResolver($item, $resolverContext); - if (null !== $item && $resourceClass !== $itemClass = $this->getObjectClass($item)) { - throw new \LogicException(sprintf('Custom mutation resolver "%s" has to return an item of class %s but returned an item of class %s.', $mutationResolverId, $resourceMetadata->getShortName(), (new \ReflectionClass($itemClass))->getShortName())); - } - } - - ($this->securityPostDenormalizeStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - 'previous_object' => $previousItem, - ], - ]); - - if (null !== $item) { - ($this->validateStage)($item, $resourceClass, $operationName, $resolverContext); - - $persistResult = ($this->writeStage)($item, $resourceClass, $operationName, $resolverContext); - } - - return ($this->serializeStage)($persistResult ?? $item, $resourceClass, $operationName, $resolverContext); - }; - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/ItemResolverFactory.php b/src/Core/GraphQl/Resolver/Factory/ItemResolverFactory.php deleted file mode 100644 index f96794dd964..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/ItemResolverFactory.php +++ /dev/null @@ -1,128 +0,0 @@ - - * - * 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\GraphQl\Resolver\Factory; - -use ApiPlatform\Core\GraphQl\Resolver\QueryItemResolverInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ClassInfoTrait; -use ApiPlatform\Core\Util\CloneTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Psr\Container\ContainerInterface; - -/** - * Creates a function retrieving an item to resolve a GraphQL query. - * - * @experimental - * - * @author Alan Poulain - * @author Kévin Dunglas - * @author Vincent Chalamon - */ -final class ItemResolverFactory implements ResolverFactoryInterface -{ - use ClassInfoTrait; - use CloneTrait; - - private $readStage; - private $securityStage; - private $securityPostDenormalizeStage; - private $serializeStage; - private $queryResolverLocator; - private $resourceMetadataFactory; - - public function __construct(ReadStageInterface $readStage, SecurityStageInterface $securityStage, SecurityPostDenormalizeStageInterface $securityPostDenormalizeStage, SerializeStageInterface $serializeStage, ContainerInterface $queryResolverLocator, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - $this->readStage = $readStage; - $this->securityStage = $securityStage; - $this->securityPostDenormalizeStage = $securityPostDenormalizeStage; - $this->serializeStage = $serializeStage; - $this->queryResolverLocator = $queryResolverLocator; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable - { - return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { - // Data already fetched and normalized (field or nested resource) - if ($source && \array_key_exists($info->fieldName, $source)) { - return $source[$info->fieldName]; - } - - $operationName = $operationName ?? 'item_query'; - $resolverContext = ['source' => $source, 'args' => $args, 'info' => $info, 'is_collection' => false, 'is_mutation' => false, 'is_subscription' => false]; - - $item = ($this->readStage)($resourceClass, $rootClass, $operationName, $resolverContext); - if (null !== $item && !\is_object($item)) { - throw new \LogicException('Item from read stage should be a nullable object.'); - } - - $resourceClass = $this->getResourceClass($item, $resourceClass); - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $queryResolverId = $resourceMetadata->getGraphqlAttribute($operationName, 'item_query'); - if (null !== $queryResolverId) { - /** @var QueryItemResolverInterface $queryResolver */ - $queryResolver = $this->queryResolverLocator->get($queryResolverId); - $item = $queryResolver($item, $resolverContext); - $resourceClass = $this->getResourceClass($item, $resourceClass, sprintf('Custom query resolver "%s"', $queryResolverId).' has to return an item of class %s but returned an item of class %s.'); - } - - ($this->securityStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - ], - ]); - ($this->securityPostDenormalizeStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - 'previous_object' => $this->clone($item), - ], - ]); - - return ($this->serializeStage)($item, $resourceClass, $operationName, $resolverContext); - }; - } - - /** - * @param object|null $item - * - * @throws \UnexpectedValueException - */ - private function getResourceClass($item, ?string $resourceClass, string $errorMessage = 'Resolver only handles items of class %s but retrieved item is of class %s.'): string - { - if (null === $item) { - if (null === $resourceClass) { - throw new \UnexpectedValueException('Resource class cannot be determined.'); - } - - return $resourceClass; - } - - $itemClass = $this->getObjectClass($item); - - if (null === $resourceClass) { - return $itemClass; - } - - if ($resourceClass !== $itemClass) { - throw new \UnexpectedValueException(sprintf($errorMessage, (new \ReflectionClass($resourceClass))->getShortName(), (new \ReflectionClass($itemClass))->getShortName())); - } - - return $resourceClass; - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactory.php b/src/Core/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactory.php deleted file mode 100644 index 33b86c409ec..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactory.php +++ /dev/null @@ -1,92 +0,0 @@ - - * - * 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\GraphQl\Resolver\Factory; - -use ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface; -use ApiPlatform\Core\GraphQl\Subscription\SubscriptionManagerInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ClassInfoTrait; -use ApiPlatform\Core\Util\CloneTrait; -use GraphQL\Type\Definition\ResolveInfo; - -/** - * Creates a function resolving a GraphQL subscription of an item. - * - * @experimental - * - * @author Alan Poulain - */ -final class ItemSubscriptionResolverFactory implements ResolverFactoryInterface -{ - use ClassInfoTrait; - use CloneTrait; - - private $readStage; - private $securityStage; - private $serializeStage; - private $resourceMetadataFactory; - private $subscriptionManager; - private $mercureSubscriptionIriGenerator; - - public function __construct(ReadStageInterface $readStage, SecurityStageInterface $securityStage, SerializeStageInterface $serializeStage, ResourceMetadataFactoryInterface $resourceMetadataFactory, SubscriptionManagerInterface $subscriptionManager, ?MercureSubscriptionIriGeneratorInterface $mercureSubscriptionIriGenerator) - { - $this->readStage = $readStage; - $this->securityStage = $securityStage; - $this->serializeStage = $serializeStage; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->subscriptionManager = $subscriptionManager; - $this->mercureSubscriptionIriGenerator = $mercureSubscriptionIriGenerator; - } - - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable - { - return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { - if (null === $resourceClass || null === $operationName) { - return null; - } - - $resolverContext = ['source' => $source, 'args' => $args, 'info' => $info, 'is_collection' => false, 'is_mutation' => false, 'is_subscription' => true]; - - $item = ($this->readStage)($resourceClass, $rootClass, $operationName, $resolverContext); - if (null !== $item && !\is_object($item)) { - throw new \LogicException('Item from read stage should be a nullable object.'); - } - ($this->securityStage)($resourceClass, $operationName, $resolverContext + [ - 'extra_variables' => [ - 'object' => $item, - ], - ]); - - $result = ($this->serializeStage)($item, $resourceClass, $operationName, $resolverContext); - - $subscriptionId = $this->subscriptionManager->retrieveSubscriptionId($resolverContext, $result); - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($subscriptionId && ($mercure = $resourceMetadata->getAttribute('mercure', false))) { - if (!$this->mercureSubscriptionIriGenerator) { - throw new \LogicException('Cannot use Mercure for subscriptions when MercureBundle is not installed. Try running "composer require mercure".'); - } - - $hub = \is_array($mercure) ? ($mercure['hub'] ?? null) : null; - $result['mercureUrl'] = $this->mercureSubscriptionIriGenerator->generateMercureUrl($subscriptionId, $hub); - } - - return $result; - }; - } -} diff --git a/src/Core/GraphQl/Resolver/Factory/ResolverFactoryInterface.php b/src/Core/GraphQl/Resolver/Factory/ResolverFactoryInterface.php deleted file mode 100644 index f406bc7a3b2..00000000000 --- a/src/Core/GraphQl/Resolver/Factory/ResolverFactoryInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * 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\GraphQl\Resolver\Factory; - -/** - * Builds a GraphQL resolver. - * - * @experimental - * - * @author Kévin Dunglas - */ -interface ResolverFactoryInterface -{ - public function __invoke(?string $resourceClass = null, ?string $rootClass = null, ?string $operationName = null): callable; -} diff --git a/src/Core/GraphQl/Resolver/ResourceFieldResolver.php b/src/Core/GraphQl/Resolver/ResourceFieldResolver.php deleted file mode 100644 index 1e1f846e705..00000000000 --- a/src/Core/GraphQl/Resolver/ResourceFieldResolver.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * 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\GraphQl\Resolver; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\Core\Util\ClassInfoTrait; -use GraphQL\Type\Definition\ResolveInfo; - -/** - * A field resolver that resolves IDs to IRIs and allow to access to the raw ID using the "#id" field. - * - * @experimental - * - * @author Kévin Dunglas - */ -final class ResourceFieldResolver -{ - use ClassInfoTrait; - - private $iriConverter; - - public function __construct(IriConverterInterface $iriConverter) - { - $this->iriConverter = $iriConverter; - } - - public function __invoke(?array $source, array $args, $context, ResolveInfo $info) - { - $property = null; - if ('id' === $info->fieldName && !isset($source['_id']) && isset($source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY], $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY])) { - return $this->iriConverter->getItemIriFromResourceClass($source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY], $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY]); - } - - if ('_id' === $info->fieldName && !isset($source['_id']) && isset($source['id'])) { - $property = $source['id']; - } elseif (\is_array($source) && isset($source[$info->fieldName])) { - $property = $source[$info->fieldName]; - } elseif (isset($source->{$info->fieldName})) { - $property = $source->{$info->fieldName}; - } - - return $property instanceof \Closure ? $property($source, $args, $context) : $property; - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/DeserializeStage.php b/src/Core/GraphQl/Resolver/Stage/DeserializeStage.php deleted file mode 100644 index 6786a03f191..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/DeserializeStage.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Deserialize stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class DeserializeStage implements DeserializeStageInterface -{ - private $resourceMetadataFactory; - private $denormalizer; - private $serializerContextBuilder; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, DenormalizerInterface $denormalizer, SerializerContextBuilderInterface $serializerContextBuilder) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->denormalizer = $denormalizer; - $this->serializerContextBuilder = $serializerContextBuilder; - } - - /** - * {@inheritdoc} - */ - public function __invoke($objectToPopulate, string $resourceClass, string $operationName, array $context) - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (!$resourceMetadata->getGraphqlAttribute($operationName, 'deserialize', true, true)) { - return $objectToPopulate; - } - - $denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, false); - if (null !== $objectToPopulate) { - $denormalizationContext[AbstractNormalizer::OBJECT_TO_POPULATE] = $objectToPopulate; - } - - $item = $this->denormalizer->denormalize($context['args']['input'], $resourceClass, ItemNormalizer::FORMAT, $denormalizationContext); - - if (!\is_object($item)) { - throw new \UnexpectedValueException('Expected item to be an object.'); - } - - return $item; - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/DeserializeStageInterface.php b/src/Core/GraphQl/Resolver/Stage/DeserializeStageInterface.php deleted file mode 100644 index be57bbe4126..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/DeserializeStageInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -/** - * Deserialize stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface DeserializeStageInterface -{ - /** - * @param object|null $objectToPopulate - * - * @return object|null - */ - public function __invoke($objectToPopulate, string $resourceClass, string $operationName, array $context); -} diff --git a/src/Core/GraphQl/Resolver/Stage/ReadStage.php b/src/Core/GraphQl/Resolver/Stage/ReadStage.php deleted file mode 100644 index 344b2f49df0..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/ReadStage.php +++ /dev/null @@ -1,188 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Exception\ItemNotFoundException; -use ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait; -use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Util\ArrayTrait; -use ApiPlatform\Core\Util\ClassInfoTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -/** - * Read stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class ReadStage implements ReadStageInterface -{ - use ArrayTrait; - use ClassInfoTrait; - use IdentifierTrait; - - private $resourceMetadataFactory; - private $iriConverter; - private $collectionDataProvider; - private $subresourceDataProvider; - private $serializerContextBuilder; - private $nestingSeparator; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, IriConverterInterface $iriConverter, ContextAwareCollectionDataProviderInterface $collectionDataProvider, SubresourceDataProviderInterface $subresourceDataProvider, SerializerContextBuilderInterface $serializerContextBuilder, string $nestingSeparator) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->iriConverter = $iriConverter; - $this->collectionDataProvider = $collectionDataProvider; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->serializerContextBuilder = $serializerContextBuilder; - $this->nestingSeparator = $nestingSeparator; - } - - /** - * {@inheritdoc} - */ - public function __invoke(?string $resourceClass, ?string $rootClass, string $operationName, array $context) - { - $resourceMetadata = $resourceClass ? $this->resourceMetadataFactory->create($resourceClass) : null; - if ($resourceMetadata && !$resourceMetadata->getGraphqlAttribute($operationName, 'read', true, true)) { - return $context['is_collection'] ? [] : null; - } - - $args = $context['args']; - $normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, true); - - if (!$context['is_collection']) { - $identifier = $this->getIdentifierFromContext($context); - $item = $this->getItem($identifier, $normalizationContext); - - if ($identifier && ($context['is_mutation'] || $context['is_subscription'])) { - if (null === $item) { - throw new NotFoundHttpException(sprintf('Item "%s" not found.', $args['input']['id'])); - } - - if ($resourceClass !== $this->getObjectClass($item)) { - throw new \UnexpectedValueException(sprintf('Item "%s" did not match expected type "%s".', $args['input']['id'], $resourceMetadata->getShortName())); - } - } - - return $item; - } - - if (null === $rootClass) { - return []; - } - - $normalizationContext['filters'] = $this->getNormalizedFilters($args); - - $source = $context['source']; - /** @var ResolveInfo $info */ - $info = $context['info']; - if (isset($source[$rootProperty = $info->fieldName], $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY], $source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY])) { - $rootResolvedFields = $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY]; - $rootResolvedClass = $source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY]; - $subresourceCollection = $this->getSubresource($rootResolvedClass, $rootResolvedFields, $rootProperty, $resourceClass, $normalizationContext, $operationName); - if (!is_iterable($subresourceCollection)) { - throw new \UnexpectedValueException('Expected subresource collection to be iterable.'); - } - - return $subresourceCollection; - } - - return $this->collectionDataProvider->getCollection($resourceClass, $operationName, $normalizationContext); - } - - /** - * @return object|null - */ - private function getItem(?string $identifier, array $normalizationContext) - { - if (null === $identifier) { - return null; - } - - try { - $item = $this->iriConverter->getItemFromIri($identifier, $normalizationContext); - } catch (ItemNotFoundException $e) { - return null; - } - - return $item; - } - - private function getNormalizedFilters(array $args): array - { - $filters = $args; - - foreach ($filters as $name => $value) { - if (\is_array($value)) { - if (strpos($name, '_list')) { - $name = substr($name, 0, \strlen($name) - \strlen('_list')); - } - - // If the value contains arrays, we need to merge them for the filters to understand this syntax, proper to GraphQL to preserve the order of the arguments. - if ($this->isSequentialArrayOfArrays($value)) { - if (\count($value[0]) > 1) { - $deprecationMessage = "The filter syntax \"$name: {"; - $filterArgsOld = []; - $filterArgsNew = []; - foreach ($value[0] as $filterArgName => $filterArgValue) { - $filterArgsOld[] = "$filterArgName: \"$filterArgValue\""; - $filterArgsNew[] = sprintf('{%s: "%s"}', $filterArgName, $filterArgValue); - } - $deprecationMessage .= sprintf('%s}" is deprecated since API Platform 2.6, use the following syntax instead: "%s: [%s]".', implode(', ', $filterArgsOld), $name, implode(', ', $filterArgsNew)); - @trigger_error($deprecationMessage, \E_USER_DEPRECATED); - } - $value = array_merge(...$value); - } - $filters[$name] = $this->getNormalizedFilters($value); - } - - if (\is_string($name) && strpos($name, $this->nestingSeparator)) { - // Gives a chance to relations/nested fields. - $index = array_search($name, array_keys($filters), true); - $filters = - \array_slice($filters, 0, $index + 1) + - [str_replace($this->nestingSeparator, '.', $name) => $value] + - \array_slice($filters, $index + 1); - } - } - - return $filters; - } - - /** - * @return iterable|object|null - */ - private function getSubresource(string $rootResolvedClass, array $rootResolvedFields, string $rootProperty, string $subresourceClass, array $normalizationContext, string $operationName) - { - $resolvedIdentifiers = []; - $rootIdentifiers = array_keys($rootResolvedFields); - foreach ($rootIdentifiers as $rootIdentifier) { - $resolvedIdentifiers[$rootIdentifier] = [$rootResolvedClass, $rootIdentifier]; - } - - return $this->subresourceDataProvider->getSubresource($subresourceClass, $rootResolvedFields, $normalizationContext + [ - 'property' => $rootProperty, - 'identifiers' => $resolvedIdentifiers, - 'collection' => true, - ], $operationName); - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/ReadStageInterface.php b/src/Core/GraphQl/Resolver/Stage/ReadStageInterface.php deleted file mode 100644 index 7acc16101be..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/ReadStageInterface.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -/** - * Read stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface ReadStageInterface -{ - /** - * @return object|iterable|null - */ - public function __invoke(?string $resourceClass, ?string $rootClass, string $operationName, array $context); -} diff --git a/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php b/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php deleted file mode 100644 index a5db9f35bde..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Security\ResourceAccessCheckerInterface; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; - -/** - * Security post denormalize stage of GraphQL resolvers. - * - * @experimental - * - * @author Vincent Chalamon - */ -final class SecurityPostDenormalizeStage implements SecurityPostDenormalizeStageInterface -{ - private $resourceMetadataFactory; - private $resourceAccessChecker; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ?ResourceAccessCheckerInterface $resourceAccessChecker) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->resourceAccessChecker = $resourceAccessChecker; - } - - /** - * {@inheritdoc} - */ - public function __invoke(string $resourceClass, string $operationName, array $context): void - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'security_post_denormalize', null, true); - - if (null === $isGranted) { - // Backward compatibility - $isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'access_control', null, true); - if (null !== $isGranted) { - @trigger_error('Attribute "access_control" is deprecated since API Platform 2.5, prefer using "security" attribute instead', \E_USER_DEPRECATED); - } - } - - if (null !== $isGranted && null === $this->resourceAccessChecker) { - throw new \LogicException('Cannot check security expression when SecurityBundle is not installed. Try running "composer require symfony/security-bundle".'); - } - - if (null === $isGranted || $this->resourceAccessChecker->isGranted($resourceClass, (string) $isGranted, $context['extra_variables'])) { - return; - } - - throw new AccessDeniedHttpException($resourceMetadata->getGraphqlAttribute($operationName, 'security_post_denormalize_message', 'Access Denied.')); - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageInterface.php b/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageInterface.php deleted file mode 100644 index d60b951cd8e..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use GraphQL\Error\Error; - -/** - * Security post deserialization stage of GraphQL resolvers. - * - * @experimental - * - * @author Vincent Chalamon - */ -interface SecurityPostDenormalizeStageInterface -{ - /** - * @throws Error - */ - public function __invoke(string $resourceClass, string $operationName, array $context): void; -} diff --git a/src/Core/GraphQl/Resolver/Stage/SecurityStage.php b/src/Core/GraphQl/Resolver/Stage/SecurityStage.php deleted file mode 100644 index 6297c6eba4d..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SecurityStage.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Security\ResourceAccessCheckerInterface; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; - -/** - * Security stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class SecurityStage implements SecurityStageInterface -{ - private $resourceMetadataFactory; - private $resourceAccessChecker; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ?ResourceAccessCheckerInterface $resourceAccessChecker) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->resourceAccessChecker = $resourceAccessChecker; - } - - /** - * {@inheritdoc} - */ - public function __invoke(string $resourceClass, string $operationName, array $context): void - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - $isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'security', null, true); - - if (null !== $isGranted && null === $this->resourceAccessChecker) { - throw new \LogicException('Cannot check security expression when SecurityBundle is not installed. Try running "composer require symfony/security-bundle".'); - } - - if (null === $isGranted || $this->resourceAccessChecker->isGranted($resourceClass, (string) $isGranted, $context['extra_variables'])) { - return; - } - - throw new AccessDeniedHttpException($resourceMetadata->getGraphqlAttribute($operationName, 'security_message', 'Access Denied.')); - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/SecurityStageInterface.php b/src/Core/GraphQl/Resolver/Stage/SecurityStageInterface.php deleted file mode 100644 index 1e0c4acbb20..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SecurityStageInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use GraphQL\Error\Error; - -/** - * Security stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - * @author Vincent Chalamon - */ -interface SecurityStageInterface -{ - /** - * @throws Error - */ - public function __invoke(string $resourceClass, string $operationName, array $context): void; -} diff --git a/src/Core/GraphQl/Resolver/Stage/SerializeStage.php b/src/Core/GraphQl/Resolver/Stage/SerializeStage.php deleted file mode 100644 index 56484bc1c1d..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SerializeStage.php +++ /dev/null @@ -1,223 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\DataProvider\Pagination; -use ApiPlatform\Core\DataProvider\PaginatorInterface; -use ApiPlatform\Core\DataProvider\PartialPaginatorInterface; -use ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait; -use ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Serialize stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class SerializeStage implements SerializeStageInterface -{ - use IdentifierTrait; - - private $resourceMetadataFactory; - private $normalizer; - private $serializerContextBuilder; - private $pagination; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, NormalizerInterface $normalizer, SerializerContextBuilderInterface $serializerContextBuilder, Pagination $pagination) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->normalizer = $normalizer; - $this->serializerContextBuilder = $serializerContextBuilder; - $this->pagination = $pagination; - } - - /** - * {@inheritdoc} - */ - public function __invoke($itemOrCollection, string $resourceClass, string $operationName, array $context): ?array - { - $isCollection = $context['is_collection']; - $isMutation = $context['is_mutation']; - $isSubscription = $context['is_subscription']; - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (!$resourceMetadata->getGraphqlAttribute($operationName, 'serialize', true, true)) { - if ($isCollection) { - if ($this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context)) { - return 'cursor' === $this->pagination->getGraphQlPaginationType($resourceClass, $operationName) ? - $this->getDefaultCursorBasedPaginatedData() : - $this->getDefaultPageBasedPaginatedData(); - } - - return []; - } - - if ($isMutation) { - return $this->getDefaultMutationData($context); - } - - if ($isSubscription) { - return $this->getDefaultSubscriptionData($context); - } - - return null; - } - - $normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, true); - - $data = null; - if (!$isCollection) { - if ($isMutation && 'delete' === $operationName) { - $data = ['id' => $this->getIdentifierFromContext($context)]; - } else { - $data = $this->normalizer->normalize($itemOrCollection, ItemNormalizer::FORMAT, $normalizationContext); - } - } - - if ($isCollection && is_iterable($itemOrCollection)) { - if (!$this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context)) { - $data = []; - foreach ($itemOrCollection as $index => $object) { - $data[$index] = $this->normalizer->normalize($object, ItemNormalizer::FORMAT, $normalizationContext); - } - } else { - $data = 'cursor' === $this->pagination->getGraphQlPaginationType($resourceClass, $operationName) ? - $this->serializeCursorBasedPaginatedCollection($itemOrCollection, $normalizationContext, $context) : - $this->serializePageBasedPaginatedCollection($itemOrCollection, $normalizationContext); - } - } - - if (null !== $data && !\is_array($data)) { - throw new \UnexpectedValueException('Expected serialized data to be a nullable array.'); - } - - if ($isMutation || $isSubscription) { - $wrapFieldName = lcfirst($resourceMetadata->getShortName()); - - return [$wrapFieldName => $data] + ($isMutation ? $this->getDefaultMutationData($context) : $this->getDefaultSubscriptionData($context)); - } - - return $data; - } - - /** - * @throws \LogicException - * @throws \UnexpectedValueException - */ - private function serializeCursorBasedPaginatedCollection(iterable $collection, array $normalizationContext, array $context): array - { - $args = $context['args']; - - if (!($collection instanceof PartialPaginatorInterface)) { - throw new \LogicException(sprintf('Collection returned by the collection data provider must implement %s or %s.', PaginatorInterface::class, PartialPaginatorInterface::class)); - } - - $offset = 0; - $totalItems = 1; // For partial pagination, always consider there is at least one item. - $nbPageItems = $collection->count(); - if (isset($args['after'])) { - $after = base64_decode($args['after'], true); - if (false === $after || '' === $args['after']) { - throw new \UnexpectedValueException('' === $args['after'] ? 'Empty cursor is invalid' : sprintf('Cursor %s is invalid', $args['after'])); - } - $offset = 1 + (int) $after; - } - - if ($collection instanceof PaginatorInterface) { - $totalItems = $collection->getTotalItems(); - - if (isset($args['before'])) { - $before = base64_decode($args['before'], true); - if (false === $before || '' === $args['before']) { - throw new \UnexpectedValueException('' === $args['before'] ? 'Empty cursor is invalid' : sprintf('Cursor %s is invalid', $args['before'])); - } - $offset = (int) $before - $nbPageItems; - } - if (isset($args['last']) && !isset($args['before'])) { - $offset = $totalItems - $args['last']; - } - } - - $offset = 0 > $offset ? 0 : $offset; - - $data = $this->getDefaultCursorBasedPaginatedData(); - if ($totalItems > 0) { - $data['pageInfo']['startCursor'] = base64_encode((string) $offset); - $end = $offset + $nbPageItems - 1; - $data['pageInfo']['endCursor'] = base64_encode((string) ($end >= 0 ? $end : 0)); - $data['pageInfo']['hasPreviousPage'] = $offset > 0; - if ($collection instanceof PaginatorInterface) { - $data['totalCount'] = $totalItems; - $itemsPerPage = $collection->getItemsPerPage(); - $data['pageInfo']['hasNextPage'] = (float) ($itemsPerPage > 0 ? $offset % $itemsPerPage : $offset) + $itemsPerPage * $collection->getCurrentPage() < $totalItems; - } - } - - $index = 0; - foreach ($collection as $object) { - $data['edges'][$index] = [ - 'node' => $this->normalizer->normalize($object, ItemNormalizer::FORMAT, $normalizationContext), - 'cursor' => base64_encode((string) ($index + $offset)), - ]; - ++$index; - } - - return $data; - } - - /** - * @throws \LogicException - */ - private function serializePageBasedPaginatedCollection(iterable $collection, array $normalizationContext): array - { - if (!($collection instanceof PaginatorInterface)) { - throw new \LogicException(sprintf('Collection returned by the collection data provider must implement %s.', PaginatorInterface::class)); - } - - $data = $this->getDefaultPageBasedPaginatedData(); - $data['paginationInfo']['totalCount'] = $collection->getTotalItems(); - $data['paginationInfo']['lastPage'] = $collection->getLastPage(); - $data['paginationInfo']['itemsPerPage'] = $collection->getItemsPerPage(); - - foreach ($collection as $object) { - $data['collection'][] = $this->normalizer->normalize($object, ItemNormalizer::FORMAT, $normalizationContext); - } - - return $data; - } - - private function getDefaultCursorBasedPaginatedData(): array - { - return ['totalCount' => 0., 'edges' => [], 'pageInfo' => ['startCursor' => null, 'endCursor' => null, 'hasNextPage' => false, 'hasPreviousPage' => false]]; - } - - private function getDefaultPageBasedPaginatedData(): array - { - return ['collection' => [], 'paginationInfo' => ['itemsPerPage' => 0., 'totalCount' => 0., 'lastPage' => 0.]]; - } - - private function getDefaultMutationData(array $context): array - { - return ['clientMutationId' => $context['args']['input']['clientMutationId'] ?? null]; - } - - private function getDefaultSubscriptionData(array $context): array - { - return ['clientSubscriptionId' => $context['args']['input']['clientSubscriptionId'] ?? null]; - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/SerializeStageInterface.php b/src/Core/GraphQl/Resolver/Stage/SerializeStageInterface.php deleted file mode 100644 index be96883832e..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/SerializeStageInterface.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -/** - * Serialize stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface SerializeStageInterface -{ - /** - * @param object|iterable|null $itemOrCollection - */ - public function __invoke($itemOrCollection, string $resourceClass, string $operationName, array $context): ?array; -} diff --git a/src/Core/GraphQl/Resolver/Stage/ValidateStage.php b/src/Core/GraphQl/Resolver/Stage/ValidateStage.php deleted file mode 100644 index 3c46aea7746..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/ValidateStage.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Validator\ValidatorInterface; - -/** - * Validate stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class ValidateStage implements ValidateStageInterface -{ - private $resourceMetadataFactory; - private $validator; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ValidatorInterface $validator) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->validator = $validator; - } - - /** - * {@inheritdoc} - */ - public function __invoke($object, string $resourceClass, string $operationName, array $context): void - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (!$resourceMetadata->getGraphqlAttribute($operationName, 'validate', true, true)) { - return; - } - - $validationGroups = $resourceMetadata->getGraphqlAttribute($operationName, 'validation_groups', null, true); - $this->validator->validate($object, ['groups' => $validationGroups]); - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/ValidateStageInterface.php b/src/Core/GraphQl/Resolver/Stage/ValidateStageInterface.php deleted file mode 100644 index e798a820671..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/ValidateStageInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use GraphQL\Error\Error; - -/** - * Validate stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface ValidateStageInterface -{ - /** - * @param object $object - * - * @throws Error - */ - public function __invoke($object, string $resourceClass, string $operationName, array $context): void; -} diff --git a/src/Core/GraphQl/Resolver/Stage/WriteStage.php b/src/Core/GraphQl/Resolver/Stage/WriteStage.php deleted file mode 100644 index 5d0b9842941..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/WriteStage.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; - -/** - * Write stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -final class WriteStage implements WriteStageInterface -{ - private $resourceMetadataFactory; - private $dataPersister; - private $serializerContextBuilder; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ContextAwareDataPersisterInterface $dataPersister, SerializerContextBuilderInterface $serializerContextBuilder) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->dataPersister = $dataPersister; - $this->serializerContextBuilder = $serializerContextBuilder; - } - - /** - * {@inheritdoc} - */ - public function __invoke($data, string $resourceClass, string $operationName, array $context) - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (null === $data || !$resourceMetadata->getGraphqlAttribute($operationName, 'write', true, true)) { - return $data; - } - - $denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, false); - - if ('delete' === $operationName) { - $this->dataPersister->remove($data, $denormalizationContext); - - return null; - } - - $persistResult = $this->dataPersister->persist($data, $denormalizationContext); - - if (!\is_object($persistResult)) { - @trigger_error(sprintf('Not returning an object from %s::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3.', DataPersisterInterface::class), \E_USER_DEPRECATED); - $persistResult = null; - } - - return $persistResult; - } -} diff --git a/src/Core/GraphQl/Resolver/Stage/WriteStageInterface.php b/src/Core/GraphQl/Resolver/Stage/WriteStageInterface.php deleted file mode 100644 index 1b54363d443..00000000000 --- a/src/Core/GraphQl/Resolver/Stage/WriteStageInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * 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\GraphQl\Resolver\Stage; - -/** - * Write stage of GraphQL resolvers. - * - * @experimental - * - * @author Alan Poulain - */ -interface WriteStageInterface -{ - /** - * @param object|null $data - * - * @return object|null - */ - public function __invoke($data, string $resourceClass, string $operationName, array $context); -} diff --git a/src/Core/GraphQl/Resolver/Util/IdentifierTrait.php b/src/Core/GraphQl/Resolver/Util/IdentifierTrait.php deleted file mode 100644 index 225074b0254..00000000000 --- a/src/Core/GraphQl/Resolver/Util/IdentifierTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\GraphQl\Resolver\Util; - -class_exists(\ApiPlatform\GraphQl\Resolver\Util\IdentifierTrait::class); - -if (false) { - trait IdentifierTrait - { - use \ApiPlatform\GraphQl\Resolver\Util\IdentifierTrait; - } -} diff --git a/src/Core/GraphQl/Serializer/Exception/ErrorNormalizer.php b/src/Core/GraphQl/Serializer/Exception/ErrorNormalizer.php deleted file mode 100644 index 05b214f1c58..00000000000 --- a/src/Core/GraphQl/Serializer/Exception/ErrorNormalizer.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * 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\GraphQl\Serializer\Exception; - -use GraphQL\Error\Error; -use GraphQL\Error\FormattedError; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Normalize GraphQL error (fallback). - * - * @experimental - * - * @author Alan Poulain - */ -final class ErrorNormalizer implements NormalizerInterface -{ - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []): array - { - return FormattedError::createFromException($object); - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return $data instanceof Error; - } -} diff --git a/src/Core/GraphQl/Serializer/Exception/HttpExceptionNormalizer.php b/src/Core/GraphQl/Serializer/Exception/HttpExceptionNormalizer.php deleted file mode 100644 index 4c7e97c2b90..00000000000 --- a/src/Core/GraphQl/Serializer/Exception/HttpExceptionNormalizer.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * 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\GraphQl\Serializer\Exception; - -use GraphQL\Error\Error; -use GraphQL\Error\FormattedError; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Normalize HTTP exceptions. - * - * @experimental - * - * @author Alan Poulain - */ -final class HttpExceptionNormalizer implements NormalizerInterface -{ - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []): array - { - /** @var HttpExceptionInterface */ - $httpException = $object->getPrevious(); - $error = FormattedError::createFromException($object); - $error['message'] = $httpException->getMessage(); - $error['extensions']['status'] = $statusCode = $httpException->getStatusCode(); - $error['extensions']['category'] = $statusCode < 500 ? 'user' : Error::CATEGORY_INTERNAL; - - return $error; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return $data instanceof Error && $data->getPrevious() instanceof HttpExceptionInterface; - } -} diff --git a/src/Core/GraphQl/Serializer/Exception/RuntimeExceptionNormalizer.php b/src/Core/GraphQl/Serializer/Exception/RuntimeExceptionNormalizer.php deleted file mode 100644 index 61bc85fe7e8..00000000000 --- a/src/Core/GraphQl/Serializer/Exception/RuntimeExceptionNormalizer.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * 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\GraphQl\Serializer\Exception; - -use GraphQL\Error\Error; -use GraphQL\Error\FormattedError; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Normalize runtime exceptions to have the right message in production mode. - * - * @experimental - * - * @author Alan Poulain - */ -final class RuntimeExceptionNormalizer implements NormalizerInterface -{ - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []): array - { - /** @var \RuntimeException */ - $runtimeException = $object->getPrevious(); - $error = FormattedError::createFromException($object); - $error['message'] = $runtimeException->getMessage(); - - return $error; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return $data instanceof Error && $data->getPrevious() instanceof \RuntimeException; - } -} diff --git a/src/Core/GraphQl/Serializer/Exception/ValidationExceptionNormalizer.php b/src/Core/GraphQl/Serializer/Exception/ValidationExceptionNormalizer.php deleted file mode 100644 index 6e4ad1117dd..00000000000 --- a/src/Core/GraphQl/Serializer/Exception/ValidationExceptionNormalizer.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * 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\GraphQl\Serializer\Exception; - -use ApiPlatform\Symfony\Validator\Exception\ValidationException; -use GraphQL\Error\Error; -use GraphQL\Error\FormattedError; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Validator\ConstraintViolation; - -/** - * Normalize validation exceptions. - * - * @experimental - * - * @author Mahmood Bazdar - * @author Alan Poulain - */ -final class ValidationExceptionNormalizer implements NormalizerInterface -{ - private $exceptionToStatus; - - public function __construct(array $exceptionToStatus = []) - { - $this->exceptionToStatus = $exceptionToStatus; - } - - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []): array - { - /** @var ValidationException */ - $validationException = $object->getPrevious(); - $error = FormattedError::createFromException($object); - $error['message'] = $validationException->getMessage(); - - $exceptionClass = \get_class($validationException); - $statusCode = Response::HTTP_UNPROCESSABLE_ENTITY; - - foreach ($this->exceptionToStatus as $class => $status) { - if (is_a($exceptionClass, $class, true)) { - $statusCode = $status; - - break; - } - } - $error['extensions']['status'] = $statusCode; - $error['extensions']['category'] = 'user'; - $error['extensions']['violations'] = []; - - /** @var ConstraintViolation $violation */ - foreach ($validationException->getConstraintViolationList() as $violation) { - $error['extensions']['violations'][] = [ - 'path' => $violation->getPropertyPath(), - 'message' => $violation->getMessage(), - ]; - } - - return $error; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return $data instanceof Error && $data->getPrevious() instanceof ValidationException; - } -} diff --git a/src/Core/GraphQl/Serializer/ItemNormalizer.php b/src/Core/GraphQl/Serializer/ItemNormalizer.php deleted file mode 100644 index 738c4040bdd..00000000000 --- a/src/Core/GraphQl/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,133 +0,0 @@ - - * - * 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\GraphQl\Serializer; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Serializer\ItemNormalizer as BaseItemNormalizer; -use ApiPlatform\Core\Util\ClassInfoTrait; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * GraphQL normalizer. - * - * @author Kévin Dunglas - */ -final class ItemNormalizer extends BaseItemNormalizer -{ - use ClassInfoTrait; - - public const FORMAT = 'graphql'; - public const ITEM_RESOURCE_CLASS_KEY = '#itemResourceClass'; - public const ITEM_IDENTIFIERS_KEY = '#itemIdentifiers'; - - private $identifiersExtractor; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, IdentifiersExtractorInterface $identifiersExtractor, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, LoggerInterface $logger = null, iterable $dataTransformers = [], ResourceMetadataFactoryInterface $resourceMetadataFactory = null) - { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $itemDataProvider, $allowPlainIdentifiers, $logger ?: new NullLogger(), $dataTransformers, $resourceMetadataFactory); - - $this->identifiersExtractor = $identifiersExtractor; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return self::FORMAT === $format && parent::supportsNormalization($data, $format); - } - - /** - * {@inheritdoc} - * - * @throws UnexpectedValueException - * - * @return array|string|int|float|bool|\ArrayObject|null - */ - public function normalize($object, $format = null, array $context = []) - { - if (null !== $this->getOutputClass($this->getObjectClass($object), $context)) { - return parent::normalize($object, $format, $context); - } - - $data = parent::normalize($object, $format, $context); - if (!\is_array($data)) { - throw new UnexpectedValueException('Expected data to be an array.'); - } - - if (!($context['no_resolver_data'] ?? false)) { - $data[self::ITEM_RESOURCE_CLASS_KEY] = $this->getObjectClass($object); - $data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($object); - } - - return $data; - } - - /** - * {@inheritdoc} - */ - protected function normalizeCollectionOfRelations($propertyMetadata, $attributeValue, string $resourceClass, ?string $format, array $context): array - { - // to-many are handled directly by the GraphQL resolver - return []; - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format); - } - - /** - * {@inheritdoc} - * - * @return array|bool - */ - protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false) - { - $allowedAttributes = parent::getAllowedAttributes($classOrObject, $context, $attributesAsString); - - if (($context['api_denormalize'] ?? false) && \is_array($allowedAttributes) && false !== ($indexId = array_search('id', $allowedAttributes, true))) { - $allowedAttributes[] = '_id'; - array_splice($allowedAttributes, (int) $indexId, 1); - } - - return $allowedAttributes; - } - - /** - * {@inheritdoc} - */ - protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = []): void - { - if ('_id' === $attribute) { - $attribute = 'id'; - } - - parent::setAttributeValue($object, $attribute, $value, $format, $context); - } -} diff --git a/src/Core/GraphQl/Serializer/ObjectNormalizer.php b/src/Core/GraphQl/Serializer/ObjectNormalizer.php deleted file mode 100644 index fe0547429c4..00000000000 --- a/src/Core/GraphQl/Serializer/ObjectNormalizer.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * 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\GraphQl\Serializer; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Util\ClassInfoTrait; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; -use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Decorates the output with GraphQL metadata when appropriate, but otherwise just - * passes through to the decorated normalizer. - */ -final class ObjectNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface -{ - use ClassInfoTrait; - - public const FORMAT = 'graphql'; - public const ITEM_RESOURCE_CLASS_KEY = '#itemResourceClass'; - public const ITEM_IDENTIFIERS_KEY = '#itemIdentifiers'; - - private $decorated; - private $iriConverter; - private $identifiersExtractor; - - public function __construct(NormalizerInterface $decorated, IriConverterInterface $iriConverter, IdentifiersExtractorInterface $identifiersExtractor) - { - $this->decorated = $decorated; - $this->iriConverter = $iriConverter; - $this->identifiersExtractor = $identifiersExtractor; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null, array $context = []): bool - { - return self::FORMAT === $format && $this->decorated->supportsNormalization($data, $format, $context); - } - - /** - * {@inheritdoc} - */ - public function hasCacheableSupportsMethod(): bool - { - return $this->decorated instanceof CacheableSupportsMethodInterface && $this->decorated->hasCacheableSupportsMethod(); - } - - /** - * {@inheritdoc} - * - * @throws UnexpectedValueException - * - * @return array|string|int|float|bool|\ArrayObject|null - */ - public function normalize($object, $format = null, array $context = []) - { - if (isset($context['api_resource'])) { - $originalResource = $context['api_resource']; - unset($context['api_resource']); - } - - $data = $this->decorated->normalize($object, $format, $context); - if (!\is_array($data)) { - throw new UnexpectedValueException('Expected data to be an array.'); - } - - if (!isset($originalResource)) { - return $data; - } - - if (isset($data['id'])) { - $data['_id'] = $data['id']; - $data['id'] = $this->iriConverter->getIriFromItem($originalResource); - } - - if (!($context['no_resolver_data'] ?? false)) { - $data[self::ITEM_RESOURCE_CLASS_KEY] = $this->getObjectClass($originalResource); - $data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($originalResource); - } - - return $data; - } -} diff --git a/src/Core/GraphQl/Serializer/SerializerContextBuilder.php b/src/Core/GraphQl/Serializer/SerializerContextBuilder.php deleted file mode 100644 index eeeccdabcb6..00000000000 --- a/src/Core/GraphQl/Serializer/SerializerContextBuilder.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * 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\GraphQl\Serializer; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use GraphQL\Type\Definition\ResolveInfo; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Builds the context used by the Symfony Serializer. - * - * @experimental - * - * @author Alan Poulain - */ -final class SerializerContextBuilder implements SerializerContextBuilderInterface -{ - private $resourceMetadataFactory; - private $nameConverter; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ?NameConverterInterface $nameConverter) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->nameConverter = $nameConverter; - } - - public function create(?string $resourceClass, string $operationName, array $resolverContext, bool $normalization): array - { - $resourceMetadata = $resourceClass ? $this->resourceMetadataFactory->create($resourceClass) : null; - - $context = [ - 'resource_class' => $resourceClass, - 'graphql_operation_name' => $operationName, - ]; - - if (isset($resolverContext['fields'])) { - $context['no_resolver_data'] = true; - } - - if ($resourceMetadata) { - $context['input'] = $resourceMetadata->getGraphqlAttribute($operationName, 'input', null, true); - $context['output'] = $resourceMetadata->getGraphqlAttribute($operationName, 'output', null, true); - - $key = $normalization ? 'normalization_context' : 'denormalization_context'; - $context = array_merge($resourceMetadata->getGraphqlAttribute($operationName, $key, [], true), $context); - } - - if ($normalization) { - $context['attributes'] = $this->fieldsToAttributes($resourceClass, $resourceMetadata, $resolverContext, $context); - } - - return $context; - } - - /** - * Retrieves fields, recursively replaces the "_id" key (the raw id) by "id" (the name of the property expected by the Serializer) and flattens edge and node structures (pagination). - */ - private function fieldsToAttributes(?string $resourceClass, ?ResourceMetadata $resourceMetadata, array $resolverContext, array $context): array - { - if (isset($resolverContext['fields'])) { - $fields = $resolverContext['fields']; - } else { - /** @var ResolveInfo $info */ - $info = $resolverContext['info']; - $fields = $info->getFieldSelection(\PHP_INT_MAX); - } - - $attributes = $this->replaceIdKeys($fields['edges']['node'] ?? $fields['collection'] ?? $fields, $resourceClass, $context); - - if ($resolverContext['is_mutation'] || $resolverContext['is_subscription']) { - if (!$resourceMetadata) { - throw new \LogicException('ResourceMetadata should always exist for a mutation or a subscription.'); - } - - $wrapFieldName = lcfirst($resourceMetadata->getShortName()); - - return $attributes[$wrapFieldName] ?? []; - } - - return $attributes; - } - - private function replaceIdKeys(array $fields, ?string $resourceClass, array $context): array - { - $denormalizedFields = []; - - foreach ($fields as $key => $value) { - if ('_id' === $key) { - $denormalizedFields['id'] = $fields['_id']; - - continue; - } - - $denormalizedFields[$this->denormalizePropertyName((string) $key, $resourceClass, $context)] = \is_array($fields[$key]) ? $this->replaceIdKeys($fields[$key], $resourceClass, $context) : $value; - } - - return $denormalizedFields; - } - - private function denormalizePropertyName(string $property, ?string $resourceClass, array $context): string - { - if (null === $this->nameConverter) { - return $property; - } - if ($this->nameConverter instanceof AdvancedNameConverterInterface) { - return $this->nameConverter->denormalize($property, $resourceClass, null, $context); - } - - return $this->nameConverter->denormalize($property); - } -} diff --git a/src/Core/GraphQl/Serializer/SerializerContextBuilderInterface.php b/src/Core/GraphQl/Serializer/SerializerContextBuilderInterface.php deleted file mode 100644 index cacf362fd28..00000000000 --- a/src/Core/GraphQl/Serializer/SerializerContextBuilderInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * 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\GraphQl\Serializer; - -/** - * Builds the context used by the Symfony Serializer. - * - * @experimental - * - * @author Alan Poulain - */ -interface SerializerContextBuilderInterface -{ - public function create(string $resourceClass, string $operationName, array $resolverContext, bool $normalization): array; -} diff --git a/src/Core/GraphQl/Subscription/MercureSubscriptionIriGenerator.php b/src/Core/GraphQl/Subscription/MercureSubscriptionIriGenerator.php deleted file mode 100644 index 7e0b49897de..00000000000 --- a/src/Core/GraphQl/Subscription/MercureSubscriptionIriGenerator.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * 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\GraphQl\Subscription; - -use Symfony\Component\Mercure\HubRegistry; -use Symfony\Component\Routing\RequestContext; - -/** - * Generates Mercure-related IRIs from a subscription ID. - * - * @experimental - * - * @author Alan Poulain - */ -final class MercureSubscriptionIriGenerator implements MercureSubscriptionIriGeneratorInterface -{ - private $requestContext; - private $registry; - - /** - * @param HubRegistry|string $registry - */ - public function __construct(RequestContext $requestContext, $registry) - { - $this->requestContext = $requestContext; - $this->registry = $registry; - } - - public function generateTopicIri(string $subscriptionId): string - { - if ('' === $scheme = $this->requestContext->getScheme()) { - $scheme = 'https'; - } - if ('' === $host = $this->requestContext->getHost()) { - $host = 'api-platform.com'; - } - - return "$scheme://$host/subscriptions/$subscriptionId"; - } - - public function generateMercureUrl(string $subscriptionId, ?string $hub = null): string - { - if (!$this->registry instanceof HubRegistry) { - return sprintf('%s?topic=%s', $this->registry, $this->generateTopicIri($subscriptionId)); - } - - return sprintf('%s?topic=%s', $this->registry->getHub($hub)->getUrl(), $this->generateTopicIri($subscriptionId)); - } -} diff --git a/src/Core/GraphQl/Subscription/MercureSubscriptionIriGeneratorInterface.php b/src/Core/GraphQl/Subscription/MercureSubscriptionIriGeneratorInterface.php deleted file mode 100644 index 8f6d0920fa6..00000000000 --- a/src/Core/GraphQl/Subscription/MercureSubscriptionIriGeneratorInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * 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\GraphQl\Subscription; - -/** - * Generates Mercure-related IRIs from a subscription ID. - * - * @experimental - * - * @author Alan Poulain - */ -interface MercureSubscriptionIriGeneratorInterface -{ - public function generateTopicIri(string $subscriptionId): string; - - public function generateMercureUrl(string $subscriptionId, ?string $hub = null): string; -} diff --git a/src/Core/GraphQl/Subscription/SubscriptionIdentifierGenerator.php b/src/Core/GraphQl/Subscription/SubscriptionIdentifierGenerator.php deleted file mode 100644 index b64786e45b5..00000000000 --- a/src/Core/GraphQl/Subscription/SubscriptionIdentifierGenerator.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * 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\GraphQl\Subscription; - -/** - * Generates an identifier used to identify a subscription. - * - * @experimental - * - * @author Alan Poulain - */ -final class SubscriptionIdentifierGenerator implements SubscriptionIdentifierGeneratorInterface -{ - public function generateSubscriptionIdentifier(array $fields): string - { - unset($fields['mercureUrl'], $fields['clientSubscriptionId']); - - return hash('sha256', print_r($fields, true)); - } -} diff --git a/src/Core/GraphQl/Subscription/SubscriptionIdentifierGeneratorInterface.php b/src/Core/GraphQl/Subscription/SubscriptionIdentifierGeneratorInterface.php deleted file mode 100644 index bcef927f80f..00000000000 --- a/src/Core/GraphQl/Subscription/SubscriptionIdentifierGeneratorInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * 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\GraphQl\Subscription; - -/** - * Generates an identifier used to identify a subscription. - * - * @experimental - * - * @author Alan Poulain - */ -interface SubscriptionIdentifierGeneratorInterface -{ - public function generateSubscriptionIdentifier(array $fields): string; -} diff --git a/src/Core/GraphQl/Subscription/SubscriptionManager.php b/src/Core/GraphQl/Subscription/SubscriptionManager.php deleted file mode 100644 index f8aae7ce6b6..00000000000 --- a/src/Core/GraphQl/Subscription/SubscriptionManager.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * 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\GraphQl\Subscription; - -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface; -use ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait; -use ApiPlatform\Core\Util\ResourceClassInfoTrait; -use ApiPlatform\Core\Util\SortTrait; -use GraphQL\Type\Definition\ResolveInfo; -use Psr\Cache\CacheItemPoolInterface; - -/** - * Manages all the queried subscriptions by creating their ID - * and saving to a cache the information needed to publish updated data. - * - * @experimental - * - * @author Alan Poulain - */ -final class SubscriptionManager implements SubscriptionManagerInterface -{ - use IdentifierTrait; - use ResourceClassInfoTrait; - use SortTrait; - - private $subscriptionsCache; - private $subscriptionIdentifierGenerator; - private $serializeStage; - private $iriConverter; - - public function __construct(CacheItemPoolInterface $subscriptionsCache, SubscriptionIdentifierGeneratorInterface $subscriptionIdentifierGenerator, SerializeStageInterface $serializeStage, IriConverterInterface $iriConverter) - { - $this->subscriptionsCache = $subscriptionsCache; - $this->subscriptionIdentifierGenerator = $subscriptionIdentifierGenerator; - $this->serializeStage = $serializeStage; - $this->iriConverter = $iriConverter; - } - - public function retrieveSubscriptionId(array $context, ?array $result): ?string - { - /** @var ResolveInfo $info */ - $info = $context['info']; - $fields = $info->getFieldSelection(\PHP_INT_MAX); - $this->arrayRecursiveSort($fields, 'ksort'); - $iri = $this->getIdentifierFromContext($context); - if (null === $iri) { - return null; - } - $subscriptionsCacheItem = $this->subscriptionsCache->getItem($this->encodeIriToCacheKey($iri)); - $subscriptions = []; - if ($subscriptionsCacheItem->isHit()) { - $subscriptions = $subscriptionsCacheItem->get(); - foreach ($subscriptions as [$subscriptionId, $subscriptionFields, $subscriptionResult]) { - if ($subscriptionFields === $fields) { - return $subscriptionId; - } - } - } - - $subscriptionId = $this->subscriptionIdentifierGenerator->generateSubscriptionIdentifier($fields); - unset($result['clientSubscriptionId']); - $subscriptions[] = [$subscriptionId, $fields, $result]; - $subscriptionsCacheItem->set($subscriptions); - $this->subscriptionsCache->save($subscriptionsCacheItem); - - return $subscriptionId; - } - - /** - * @param object $object - */ - public function getPushPayloads($object): array - { - $iri = $this->iriConverter->getIriFromItem($object); - $subscriptions = $this->getSubscriptionsFromIri($iri); - - $resourceClass = $this->getObjectClass($object); - - $payloads = []; - foreach ($subscriptions as [$subscriptionId, $subscriptionFields, $subscriptionResult]) { - $resolverContext = ['fields' => $subscriptionFields, 'is_collection' => false, 'is_mutation' => false, 'is_subscription' => true]; - - $data = ($this->serializeStage)($object, $resourceClass, 'update', $resolverContext); - unset($data['clientSubscriptionId']); - - if ($data !== $subscriptionResult) { - $payloads[] = [$subscriptionId, $data]; - } - } - - return $payloads; - } - - /** - * @return array - */ - private function getSubscriptionsFromIri(string $iri): array - { - $subscriptionsCacheItem = $this->subscriptionsCache->getItem($this->encodeIriToCacheKey($iri)); - - if ($subscriptionsCacheItem->isHit()) { - return $subscriptionsCacheItem->get(); - } - - return []; - } - - private function encodeIriToCacheKey(string $iri): string - { - return str_replace('/', '_', $iri); - } -} diff --git a/src/Core/GraphQl/Subscription/SubscriptionManagerInterface.php b/src/Core/GraphQl/Subscription/SubscriptionManagerInterface.php deleted file mode 100644 index e745b754b51..00000000000 --- a/src/Core/GraphQl/Subscription/SubscriptionManagerInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * 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\GraphQl\Subscription; - -/** - * Manages all the queried subscriptions and creates their ID. - * - * @experimental - * - * @author Alan Poulain - */ -interface SubscriptionManagerInterface -{ - public function retrieveSubscriptionId(array $context, ?array $result): ?string; - - public function getPushPayloads($object): array; -} diff --git a/src/Core/GraphQl/Type/Definition/IterableType.php b/src/Core/GraphQl/Type/Definition/IterableType.php deleted file mode 100644 index f51fbd7f437..00000000000 --- a/src/Core/GraphQl/Type/Definition/IterableType.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Type\Definition; - -class_exists(\ApiPlatform\GraphQl\Type\Definition\IterableType::class); - -if (false) { - final class IterableType extends \ApiPlatform\GraphQl\Type\Definition\IterableType - { - } -} diff --git a/src/Core/GraphQl/Type/Definition/UploadType.php b/src/Core/GraphQl/Type/Definition/UploadType.php deleted file mode 100644 index e1222e7f789..00000000000 --- a/src/Core/GraphQl/Type/Definition/UploadType.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Type\Definition; - -class_exists(\ApiPlatform\GraphQl\Type\Definition\UploadType::class); - -if (false) { - final class UploadType extends \ApiPlatform\GraphQl\Type\Definition\UploadType - { - } -} diff --git a/src/Core/GraphQl/Type/FieldsBuilder.php b/src/Core/GraphQl/Type/FieldsBuilder.php deleted file mode 100644 index ee549828262..00000000000 --- a/src/Core/GraphQl/Type/FieldsBuilder.php +++ /dev/null @@ -1,530 +0,0 @@ - - * - * 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\GraphQl\Type; - -use ApiPlatform\Core\DataProvider\Pagination; -use ApiPlatform\Core\GraphQl\Resolver\Factory\ResolverFactoryInterface as ResolverFactoryLegacyInterface; -use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface; -use ApiPlatform\GraphQl\Type\Definition\TypeInterface; -use ApiPlatform\GraphQl\Type\TypesContainerInterface; -use ApiPlatform\Util\Inflector; -use GraphQL\Type\Definition\InputObjectType; -use GraphQL\Type\Definition\NullableType; -use GraphQL\Type\Definition\Type as GraphQLType; -use GraphQL\Type\Definition\WrappingType; -use Psr\Container\ContainerInterface; -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -/** - * Builds the GraphQL fields. - * - * @author Alan Poulain - */ -final class FieldsBuilder implements FieldsBuilderInterface -{ - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $resourceMetadataFactory; - /** @var TypesContainerLegacyInterface|TypesContainerInterface */ - private $typesContainer; - private $typeBuilder; - /** @var TypeConverterInterface */ - private $typeConverter; - /** @var ResolverFactoryLegacyInterface|ResolverFactoryInterface */ - private $itemResolverFactory; - /** @var ResolverFactoryLegacyInterface|ResolverFactoryInterface */ - private $collectionResolverFactory; - /** @var ResolverFactoryLegacyInterface|ResolverFactoryInterface */ - private $itemMutationResolverFactory; - /** @var ResolverFactoryLegacyInterface|ResolverFactoryInterface */ - private $itemSubscriptionResolverFactory; - private $filterLocator; - private $pagination; - private $nameConverter; - private $nestingSeparator; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, $typesContainer, TypeBuilderInterface $typeBuilder, $typeConverter, $itemResolverFactory, $collectionResolverFactory, $itemMutationResolverFactory, $itemSubscriptionResolverFactory, ContainerInterface $filterLocator, Pagination $pagination, ?NameConverterInterface $nameConverter, string $nestingSeparator) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->typesContainer = $typesContainer; - $this->typeBuilder = $typeBuilder; - $this->typeConverter = $typeConverter; - $this->itemResolverFactory = $itemResolverFactory; - $this->collectionResolverFactory = $collectionResolverFactory; - $this->itemMutationResolverFactory = $itemMutationResolverFactory; - $this->itemSubscriptionResolverFactory = $itemSubscriptionResolverFactory; - $this->filterLocator = $filterLocator; - $this->pagination = $pagination; - $this->nameConverter = $nameConverter; - $this->nestingSeparator = $nestingSeparator; - } - - /** - * {@inheritdoc} - */ - public function getNodeQueryFields(): array - { - return [ - 'type' => $this->typeBuilder->getNodeInterface(), - 'args' => [ - 'id' => ['type' => GraphQLType::nonNull(GraphQLType::id())], - ], - 'resolve' => ($this->itemResolverFactory)(), - ]; - } - - /** - * {@inheritdoc} - */ - public function getItemQueryFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $queryName, array $configuration): array - { - $shortName = $resourceMetadata->getShortName(); - $fieldName = lcfirst('item_query' === $queryName ? $shortName : $queryName.$shortName); - $description = $resourceMetadata->getGraphqlAttribute($queryName, 'description'); - $deprecationReason = $resourceMetadata->getGraphqlAttribute($queryName, 'deprecation_reason', null, true); - - if ($fieldConfiguration = $this->getResourceFieldConfiguration(null, $description, $deprecationReason, new Type(Type::BUILTIN_TYPE_OBJECT, true, $resourceClass), $resourceClass, false, $queryName, null, null)) { - $args = $this->resolveResourceArgs($configuration['args'] ?? [], $queryName, $shortName); - $configuration['args'] = $args ?: $configuration['args'] ?? ['id' => ['type' => GraphQLType::nonNull(GraphQLType::id())]]; - - return [$fieldName => array_merge($fieldConfiguration, $configuration)]; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function getCollectionQueryFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $queryName, array $configuration): array - { - $shortName = $resourceMetadata->getShortName(); - $fieldName = lcfirst('collection_query' === $queryName ? $shortName : $queryName.$shortName); - $description = $resourceMetadata->getGraphqlAttribute($queryName, 'description'); - $deprecationReason = $resourceMetadata->getGraphqlAttribute($queryName, 'deprecation_reason', null, true); - - if ($fieldConfiguration = $this->getResourceFieldConfiguration(null, $description, $deprecationReason, new Type(Type::BUILTIN_TYPE_OBJECT, false, null, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, $resourceClass)), $resourceClass, false, $queryName, null, null)) { - $args = $this->resolveResourceArgs($configuration['args'] ?? [], $queryName, $shortName); - $configuration['args'] = $args ?: $configuration['args'] ?? $fieldConfiguration['args']; - - return [Inflector::pluralize($fieldName) => array_merge($fieldConfiguration, $configuration)]; - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function getMutationFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $mutationName): array - { - $mutationFields = []; - $shortName = $resourceMetadata->getShortName(); - $resourceType = new Type(Type::BUILTIN_TYPE_OBJECT, true, $resourceClass); - $description = $resourceMetadata->getGraphqlAttribute($mutationName, 'description', ucfirst("{$mutationName}s a $shortName."), false); - $deprecationReason = $resourceMetadata->getGraphqlAttribute($mutationName, 'deprecation_reason', null, true); - - if ($fieldConfiguration = $this->getResourceFieldConfiguration(null, $description, $deprecationReason, $resourceType, $resourceClass, false, null, $mutationName, null)) { - $fieldConfiguration['args'] += ['input' => $this->getResourceFieldConfiguration(null, null, $deprecationReason, $resourceType, $resourceClass, true, null, $mutationName, null)]; - } - - $mutationFields[$mutationName.$resourceMetadata->getShortName()] = $fieldConfiguration ?? []; - - return $mutationFields; - } - - /** - * {@inheritdoc} - */ - public function getSubscriptionFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $subscriptionName): array - { - $subscriptionFields = []; - $shortName = $resourceMetadata->getShortName(); - $resourceType = new Type(Type::BUILTIN_TYPE_OBJECT, true, $resourceClass); - $description = $resourceMetadata->getGraphqlAttribute($subscriptionName, 'description', "Subscribes to the $subscriptionName event of a $shortName.", false); - $deprecationReason = $resourceMetadata->getGraphqlAttribute($subscriptionName, 'deprecation_reason', null, true); - - if ($fieldConfiguration = $this->getResourceFieldConfiguration(null, $description, $deprecationReason, $resourceType, $resourceClass, false, null, null, $subscriptionName)) { - $fieldConfiguration['args'] += ['input' => $this->getResourceFieldConfiguration(null, null, $deprecationReason, $resourceType, $resourceClass, true, null, null, $subscriptionName)]; - } - - if (!$fieldConfiguration) { - return []; - } - - $subscriptionFields[$subscriptionName.$resourceMetadata->getShortName().'Subscribe'] = $fieldConfiguration; - - return $subscriptionFields; - } - - /** - * {@inheritdoc} - */ - public function getResourceObjectTypeFields(?string $resourceClass, ResourceMetadata $resourceMetadata, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, int $depth = 0, ?array $ioMetadata = null): array - { - $fields = []; - $idField = ['type' => GraphQLType::nonNull(GraphQLType::id())]; - $optionalIdField = ['type' => GraphQLType::id()]; - $clientMutationId = GraphQLType::string(); - $clientSubscriptionId = GraphQLType::string(); - - if (null !== $ioMetadata && \array_key_exists('class', $ioMetadata) && null === $ioMetadata['class']) { - if ($input) { - return ['clientMutationId' => $clientMutationId]; - } - - return []; - } - - if (null !== $subscriptionName && $input) { - return [ - 'id' => $idField, - 'clientSubscriptionId' => $clientSubscriptionId, - ]; - } - - if ('delete' === $mutationName) { - $fields = [ - 'id' => $idField, - ]; - - if ($input) { - $fields['clientMutationId'] = $clientMutationId; - } - - return $fields; - } - - if (!$input || 'create' !== $mutationName) { - $fields['id'] = $idField; - } - if ($input && $depth >= 1) { - $fields['id'] = $optionalIdField; - } - - ++$depth; // increment the depth for the call to getResourceFieldConfiguration. - - if (null !== $resourceClass) { - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $property) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $property, ['graphql_operation_name' => $subscriptionName ?? $mutationName ?? $queryName]); - if ( - null === ($propertyType = $propertyMetadata->getType()) - || (!$input && false === $propertyMetadata->isReadable()) - || ($input && null !== $mutationName && false === $propertyMetadata->isWritable()) - ) { - continue; - } - - if ($fieldConfiguration = $this->getResourceFieldConfiguration($property, $propertyMetadata->getDescription(), $propertyMetadata->getAttribute('deprecation_reason', null), $propertyType, $resourceClass, $input, $queryName, $mutationName, $subscriptionName, $depth, null !== $propertyMetadata->getAttribute('security'))) { - $fields['id' === $property ? '_id' : $this->normalizePropertyName($property, $resourceClass)] = $fieldConfiguration; - } - } - } - - if (null !== $mutationName && $input) { - $fields['clientMutationId'] = $clientMutationId; - } - - return $fields; - } - - /** - * {@inheritdoc} - */ - public function resolveResourceArgs(array $args, string $operationName, string $shortName): array - { - foreach ($args as $id => $arg) { - if (!isset($arg['type'])) { - throw new \InvalidArgumentException(sprintf('The argument "%s" of the custom operation "%s" in %s needs a "type" option.', $id, $operationName, $shortName)); - } - - $args[$id]['type'] = $this->typeConverter->resolveType($arg['type']); - } - - return $args; - } - - /** - * Get the field configuration of a resource. - * - * @see http://webonyx.github.io/graphql-php/type-system/object-types/ - */ - private function getResourceFieldConfiguration(?string $property, ?string $fieldDescription, ?string $deprecationReason, Type $type, string $rootResource, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, int $depth = 0, bool $forceNullable = false): ?array - { - try { - if ( - $this->typeBuilder->isCollection($type) && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $resourceClass = $collectionValueType->getClassName(); - } else { - $resourceClass = $type->getClassName(); - } - - if (null === $graphqlType = $this->convertType($type, $input, $queryName, $mutationName, $subscriptionName, $resourceClass ?? '', $rootResource, $property, $depth, $forceNullable)) { - return null; - } - - $graphqlWrappedType = $graphqlType instanceof WrappingType ? $graphqlType->getWrappedType(true) : $graphqlType; - $isStandardGraphqlType = \in_array($graphqlWrappedType, GraphQLType::getStandardTypes(), true); - if ($isStandardGraphqlType) { - $resourceClass = ''; - } - - $resourceMetadata = null; - if (!empty($resourceClass)) { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $e) { - } - } - - // Check mercure attribute if it's a subscription at the root level. - if ($subscriptionName && null === $property && (!$resourceMetadata || !$resourceMetadata->getAttribute('mercure', false))) { - return null; - } - - $args = []; - if (!$input && null === $mutationName && null === $subscriptionName && !$isStandardGraphqlType && $this->typeBuilder->isCollection($type)) { - if ($this->pagination->isGraphQlEnabled($resourceClass, $queryName)) { - $args = $this->getGraphQlPaginationArgs($resourceClass, $queryName); - } - - $args = $this->getFilterArgs($args, $resourceClass, $resourceMetadata, $rootResource, $property, $queryName, $mutationName, $depth); - } - - if ($isStandardGraphqlType || $input) { - $resolve = null; - } elseif (($mutationName || $subscriptionName) && $depth <= 0) { - if ($mutationName) { - $resolve = ($this->itemMutationResolverFactory)($resourceClass, $rootResource, $mutationName); - } else { - $resolve = ($this->itemSubscriptionResolverFactory)($resourceClass, $rootResource, $subscriptionName); - } - } elseif ($this->typeBuilder->isCollection($type)) { - $resolve = ($this->collectionResolverFactory)($resourceClass, $rootResource, $queryName); - } else { - $resolve = ($this->itemResolverFactory)($resourceClass, $rootResource, $queryName); - } - - return [ - 'type' => $graphqlType, - 'description' => $fieldDescription, - 'args' => $args, - 'resolve' => $resolve, - 'deprecationReason' => $deprecationReason, - ]; - } catch (InvalidTypeException $e) { - // just ignore invalid types - } - - return null; - } - - private function getGraphQlPaginationArgs(string $resourceClass, string $queryName): array - { - $paginationType = $this->pagination->getGraphQlPaginationType($resourceClass, $queryName); - - if ('cursor' === $paginationType) { - return [ - 'first' => [ - 'type' => GraphQLType::int(), - 'description' => 'Returns the first n elements from the list.', - ], - 'last' => [ - 'type' => GraphQLType::int(), - 'description' => 'Returns the last n elements from the list.', - ], - 'before' => [ - 'type' => GraphQLType::string(), - 'description' => 'Returns the elements in the list that come before the specified cursor.', - ], - 'after' => [ - 'type' => GraphQLType::string(), - 'description' => 'Returns the elements in the list that come after the specified cursor.', - ], - ]; - } - - $paginationOptions = $this->pagination->getOptions(); - - $args = [ - $paginationOptions['page_parameter_name'] => [ - 'type' => GraphQLType::int(), - 'description' => 'Returns the current page.', - ], - ]; - - if ($paginationOptions['client_items_per_page']) { - $args[$paginationOptions['items_per_page_parameter_name']] = [ - 'type' => GraphQLType::int(), - 'description' => 'Returns the number of items per page.', - ]; - } - - return $args; - } - - private function getFilterArgs(array $args, ?string $resourceClass, ?ResourceMetadata $resourceMetadata, string $rootResource, ?string $property, ?string $queryName, ?string $mutationName, int $depth): array - { - if (null === $resourceMetadata || null === $resourceClass) { - return $args; - } - - foreach ($resourceMetadata->getGraphqlAttribute($queryName, 'filters', [], true) as $filterId) { - if (null === $this->filterLocator || !$this->filterLocator->has($filterId)) { - continue; - } - - foreach ($this->filterLocator->get($filterId)->getDescription($resourceClass) as $key => $value) { - $nullable = isset($value['required']) ? !$value['required'] : true; - $filterType = \in_array($value['type'], Type::$builtinTypes, true) ? new Type($value['type'], $nullable) : new Type('object', $nullable, $value['type']); - $graphqlFilterType = $this->convertType($filterType, false, $queryName, $mutationName, null, $resourceClass, $rootResource, $property, $depth); - - if ('[]' === substr($key, -2)) { - $graphqlFilterType = GraphQLType::listOf($graphqlFilterType); - $key = substr($key, 0, -2).'_list'; - } - - /** @var string $key */ - $key = str_replace('.', $this->nestingSeparator, $key); - - parse_str($key, $parsed); - if (\array_key_exists($key, $parsed) && \is_array($parsed[$key])) { - $parsed = [$key => '']; - } - array_walk_recursive($parsed, static function (&$value) use ($graphqlFilterType) { - $value = $graphqlFilterType; - }); - $args = $this->mergeFilterArgs($args, $parsed, $resourceMetadata, $key); - } - } - - return $this->convertFilterArgsToTypes($args); - } - - private function mergeFilterArgs(array $args, array $parsed, ResourceMetadata $resourceMetadata = null, $original = ''): array - { - foreach ($parsed as $key => $value) { - // Never override keys that cannot be merged - if (isset($args[$key]) && !\is_array($args[$key])) { - continue; - } - - if (\is_array($value)) { - $value = $this->mergeFilterArgs($args[$key] ?? [], $value); - if (!isset($value['#name'])) { - $name = (false === $pos = strrpos($original, '[')) ? $original : substr($original, 0, (int) $pos); - $value['#name'] = ($resourceMetadata ? $resourceMetadata->getShortName() : '').'Filter_'.strtr($name, ['[' => '_', ']' => '', '.' => '__']); - } - } - - $args[$key] = $value; - } - - return $args; - } - - private function convertFilterArgsToTypes(array $args): array - { - foreach ($args as $key => $value) { - if (strpos($key, '.')) { - // Declare relations/nested fields in a GraphQL compatible syntax. - $args[str_replace('.', $this->nestingSeparator, $key)] = $value; - unset($args[$key]); - } - } - - foreach ($args as $key => $value) { - if (!\is_array($value) || !isset($value['#name'])) { - continue; - } - - $name = $value['#name']; - - if ($this->typesContainer->has($name)) { - $args[$key] = $this->typesContainer->get($name); - continue; - } - - unset($value['#name']); - - $filterArgType = GraphQLType::listOf(new InputObjectType([ - 'name' => $name, - 'fields' => $this->convertFilterArgsToTypes($value), - ])); - - $this->typesContainer->set($name, $filterArgType); - - $args[$key] = $filterArgType; - } - - return $args; - } - - /** - * Converts a built-in type to its GraphQL equivalent. - * - * @throws InvalidTypeException - */ - private function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $resourceClass, string $rootResource, ?string $property, int $depth, bool $forceNullable = false) - { - $graphqlType = $this->typeConverter->convertType($type, $input, $queryName, $mutationName, $subscriptionName, $resourceClass, $rootResource, $property, $depth); - - if (null === $graphqlType) { - throw new InvalidTypeException(sprintf('The type "%s" is not supported.', $type->getBuiltinType())); - } - - if (\is_string($graphqlType)) { - if (!$this->typesContainer->has($graphqlType)) { - throw new InvalidTypeException(sprintf('The GraphQL type %s is not valid. Valid types are: %s. Have you registered this type by implementing %s?', $graphqlType, implode(', ', array_keys($this->typesContainer->all())), TypeInterface::class)); - } - - $graphqlType = $this->typesContainer->get($graphqlType); - } - - if ($this->typeBuilder->isCollection($type)) { - $operationName = $queryName ?? $mutationName ?? $subscriptionName; - - return $this->pagination->isGraphQlEnabled($resourceClass, $operationName) && !$input ? $this->typeBuilder->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $operationName) : GraphQLType::listOf($graphqlType); - } - - return $forceNullable || !$graphqlType instanceof NullableType || $type->isNullable() || (null !== $mutationName && 'update' === $mutationName) - ? $graphqlType - : GraphQLType::nonNull($graphqlType); - } - - private function normalizePropertyName(string $property, string $resourceClass): string - { - if (null === $this->nameConverter) { - return $property; - } - if ($this->nameConverter instanceof AdvancedNameConverterInterface) { - return $this->nameConverter->normalize($property, $resourceClass); - } - - return $this->nameConverter->normalize($property); - } -} diff --git a/src/Core/GraphQl/Type/FieldsBuilderInterface.php b/src/Core/GraphQl/Type/FieldsBuilderInterface.php deleted file mode 100644 index c693b9a5e9a..00000000000 --- a/src/Core/GraphQl/Type/FieldsBuilderInterface.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * 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\GraphQl\Type; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Interface implemented to build GraphQL fields. - * - * @author Alan Poulain - */ -interface FieldsBuilderInterface -{ - /** - * Gets the fields of a node for a query. - */ - public function getNodeQueryFields(): array; - - /** - * Gets the item query fields of the schema. - */ - public function getItemQueryFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $queryName, array $configuration): array; - - /** - * Gets the collection query fields of the schema. - */ - public function getCollectionQueryFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $queryName, array $configuration): array; - - /** - * Gets the mutation fields of the schema. - */ - public function getMutationFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $mutationName): array; - - /** - * Gets the subscription fields of the schema. - */ - public function getSubscriptionFields(string $resourceClass, ResourceMetadata $resourceMetadata, string $subscriptionName): array; - - /** - * Gets the fields of the type of the given resource. - */ - public function getResourceObjectTypeFields(?string $resourceClass, ResourceMetadata $resourceMetadata, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, int $depth, ?array $ioMetadata): array; - - /** - * Resolve the args of a resource by resolving its types. - */ - public function resolveResourceArgs(array $args, string $operationName, string $shortName): array; -} diff --git a/src/Core/GraphQl/Type/SchemaBuilder.php b/src/Core/GraphQl/Type/SchemaBuilder.php deleted file mode 100644 index f9107e55f28..00000000000 --- a/src/Core/GraphQl/Type/SchemaBuilder.php +++ /dev/null @@ -1,132 +0,0 @@ - - * - * 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\GraphQl\Type; - -use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; -use ApiPlatform\Core\GraphQl\Type\TypesFactoryInterface as TypesFactoryLegacyInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\GraphQl\Type\TypesContainerInterface; -use ApiPlatform\GraphQl\Type\TypesFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use GraphQL\Type\Definition\ObjectType; -use GraphQL\Type\Definition\WrappingType; -use GraphQL\Type\Schema; - -/** - * Builds the GraphQL schema. - * - * @author Raoul Clais - * @author Alan Poulain - * @author Kévin Dunglas - */ -final class SchemaBuilder implements SchemaBuilderInterface -{ - private $resourceNameCollectionFactory; - private $resourceMetadataFactory; - /** @var TypesFactoryLegacyInterface|TypesFactoryInterface */ - private $typesFactory; - /** @var TypesContainerLegacyInterface|TypesContainerInterface */ - private $typesContainer; - private $fieldsBuilder; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, $typesFactory, $typesContainer, FieldsBuilderInterface $fieldsBuilder) - { - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->typesFactory = $typesFactory; - $this->typesContainer = $typesContainer; - $this->fieldsBuilder = $fieldsBuilder; - } - - public function getSchema(): Schema - { - $types = $this->typesFactory->getTypes(); - foreach ($types as $typeId => $type) { - $this->typesContainer->set($typeId, $type); - } - - $queryFields = ['node' => $this->fieldsBuilder->getNodeQueryFields()]; - $mutationFields = []; - $subscriptionFields = []; - - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - /** @var array $graphqlConfiguration */ - $graphqlConfiguration = $resourceMetadata->getGraphql() ?? []; - foreach ($graphqlConfiguration as $operationName => $value) { - if ('item_query' === $operationName) { - $queryFields += $this->fieldsBuilder->getItemQueryFields($resourceClass, $resourceMetadata, $operationName, []); - - continue; - } - - if ('collection_query' === $operationName) { - $queryFields += $this->fieldsBuilder->getCollectionQueryFields($resourceClass, $resourceMetadata, $operationName, []); - - continue; - } - - if ($resourceMetadata->getGraphqlAttribute($operationName, 'item_query')) { - $queryFields += $this->fieldsBuilder->getItemQueryFields($resourceClass, $resourceMetadata, $operationName, $value); - - continue; - } - - if ($resourceMetadata->getGraphqlAttribute($operationName, 'collection_query')) { - $queryFields += $this->fieldsBuilder->getCollectionQueryFields($resourceClass, $resourceMetadata, $operationName, $value); - - continue; - } - - if ('update' === $operationName) { - $subscriptionFields += $this->fieldsBuilder->getSubscriptionFields($resourceClass, $resourceMetadata, $operationName); - } - - $mutationFields += $this->fieldsBuilder->getMutationFields($resourceClass, $resourceMetadata, $operationName); - } - } - - $schema = [ - 'query' => new ObjectType([ - 'name' => 'Query', - 'fields' => $queryFields, - ]), - 'typeLoader' => function ($name) { - $type = $this->typesContainer->get($name); - - if ($type instanceof WrappingType) { - return $type->getWrappedType(true); - } - - return $type; - }, - ]; - - if ($mutationFields) { - $schema['mutation'] = new ObjectType([ - 'name' => 'Mutation', - 'fields' => $mutationFields, - ]); - } - - if ($subscriptionFields) { - $schema['subscription'] = new ObjectType([ - 'name' => 'Subscription', - 'fields' => $subscriptionFields, - ]); - } - - return new Schema($schema); - } -} diff --git a/src/Core/GraphQl/Type/SchemaBuilderInterface.php b/src/Core/GraphQl/Type/SchemaBuilderInterface.php deleted file mode 100644 index 69fd7f7748a..00000000000 --- a/src/Core/GraphQl/Type/SchemaBuilderInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * 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\GraphQl\Type; - -use GraphQL\Type\Schema; - -/** - * Builds a GraphQL schema. - * - * @author Alan Poulain - */ -interface SchemaBuilderInterface -{ - public function getSchema(): Schema; -} diff --git a/src/Core/GraphQl/Type/TypeBuilder.php b/src/Core/GraphQl/Type/TypeBuilder.php deleted file mode 100644 index 8132587bb50..00000000000 --- a/src/Core/GraphQl/Type/TypeBuilder.php +++ /dev/null @@ -1,287 +0,0 @@ - - * - * 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\GraphQl\Type; - -use ApiPlatform\Core\DataProvider\Pagination; -use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\GraphQl\Serializer\ItemNormalizer; -use ApiPlatform\GraphQl\Type\TypesContainerInterface; -use GraphQL\Type\Definition\InputObjectType; -use GraphQL\Type\Definition\InterfaceType; -use GraphQL\Type\Definition\NonNull; -use GraphQL\Type\Definition\ObjectType; -use GraphQL\Type\Definition\Type as GraphQLType; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; - -/** - * Builds the GraphQL types. - * - * @author Alan Poulain - */ -final class TypeBuilder implements TypeBuilderInterface -{ - /** @var TypesContainerLegacyInterface|TypesContainerInterface */ - private $typesContainer; - private $defaultFieldResolver; - private $fieldsBuilderLocator; - private $pagination; - - public function __construct($typesContainer, callable $defaultFieldResolver, ContainerInterface $fieldsBuilderLocator, Pagination $pagination) - { - $this->typesContainer = $typesContainer; - $this->defaultFieldResolver = $defaultFieldResolver; - $this->fieldsBuilderLocator = $fieldsBuilderLocator; - $this->pagination = $pagination; - } - - /** - * {@inheritdoc} - */ - public function getResourceObjectType(?string $resourceClass, ResourceMetadata $resourceMetadata, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, bool $wrapped = false, int $depth = 0): GraphQLType - { - $shortName = $resourceMetadata->getShortName(); - - $ioMetadata = $resourceMetadata->getGraphqlAttribute($subscriptionName ?? $mutationName ?? $queryName, $input ? 'input' : 'output', null, true); - if (null !== $ioMetadata && \array_key_exists('class', $ioMetadata) && null !== $ioMetadata['class']) { - $resourceClass = $ioMetadata['class']; - $shortName = $ioMetadata['name']; - } - - if (null !== $mutationName) { - $shortName = $mutationName.ucfirst($shortName); - } - if (null !== $subscriptionName) { - $shortName = $subscriptionName.ucfirst($shortName).'Subscription'; - } - if ($input) { - if ($depth > 0) { - $shortName .= 'Nested'; - } - $shortName .= 'Input'; - } elseif (null !== $mutationName || null !== $subscriptionName) { - if ($depth > 0) { - $shortName .= 'Nested'; - } - $shortName .= 'Payload'; - } - if (('item_query' === $queryName || 'collection_query' === $queryName) - && $resourceMetadata->getGraphqlAttribute('item_query', 'normalization_context', [], true) !== $resourceMetadata->getGraphqlAttribute('collection_query', 'normalization_context', [], true)) { - if ('item_query' === $queryName) { - $shortName .= 'Item'; - } - if ('collection_query' === $queryName) { - $shortName .= 'Collection'; - } - } - if ($wrapped && (null !== $mutationName || null !== $subscriptionName)) { - $shortName .= 'Data'; - } - - if ($this->typesContainer->has($shortName)) { - $resourceObjectType = $this->typesContainer->get($shortName); - if (!($resourceObjectType instanceof ObjectType || $resourceObjectType instanceof NonNull)) { - throw new \LogicException(sprintf('Expected GraphQL type "%s" to be %s.', $shortName, implode('|', [ObjectType::class, NonNull::class]))); - } - - return $resourceObjectType; - } - - $wrapData = !$wrapped && (null !== $mutationName || null !== $subscriptionName) && !$input && $depth < 1; - - $configuration = [ - 'name' => $shortName, - 'description' => $resourceMetadata->getDescription(), - 'resolveField' => $this->defaultFieldResolver, - 'fields' => function () use ($resourceClass, $resourceMetadata, $input, $queryName, $mutationName, $subscriptionName, $wrapData, $depth, $ioMetadata) { - if ($wrapData) { - $queryNormalizationContext = $resourceMetadata->getGraphqlAttribute($queryName ?? '', 'normalization_context', [], true); - $mutationNormalizationContext = $resourceMetadata->getGraphqlAttribute($mutationName ?? $subscriptionName ?? '', 'normalization_context', [], true); - // Use a new type for the wrapped object only if there is a specific normalization context for the mutation or the subscription. - // If not, use the query type in order to ensure the client cache could be used. - $useWrappedType = $queryNormalizationContext !== $mutationNormalizationContext; - - $fields = [ - lcfirst($resourceMetadata->getShortName()) => $useWrappedType ? - $this->getResourceObjectType($resourceClass, $resourceMetadata, $input, $queryName, $mutationName, $subscriptionName, true, $depth) : - $this->getResourceObjectType($resourceClass, $resourceMetadata, $input, $queryName ?? 'item_query', null, null, true, $depth), - ]; - - if (null !== $subscriptionName) { - $fields['clientSubscriptionId'] = GraphQLType::string(); - if ($resourceMetadata->getAttribute('mercure', false)) { - $fields['mercureUrl'] = GraphQLType::string(); - } - - return $fields; - } - - return $fields + ['clientMutationId' => GraphQLType::string()]; - } - - /** @var FieldsBuilderInterface $fieldsBuilder */ - $fieldsBuilder = $this->fieldsBuilderLocator->get('api_platform.graphql.fields_builder'); - $fields = $fieldsBuilder->getResourceObjectTypeFields($resourceClass, $resourceMetadata, $input, $queryName, $mutationName, $subscriptionName, $depth, $ioMetadata); - - if ($input && null !== $mutationName && null !== $mutationArgs = $resourceMetadata->getGraphql()[$mutationName]['args'] ?? null) { - return $fieldsBuilder->resolveResourceArgs($mutationArgs, $mutationName, $resourceMetadata->getShortName()) + ['clientMutationId' => $fields['clientMutationId']]; - } - - return $fields; - }, - 'interfaces' => $wrapData ? [] : [$this->getNodeInterface()], - ]; - - $resourceObjectType = $input ? GraphQLType::nonNull(new InputObjectType($configuration)) : new ObjectType($configuration); - $this->typesContainer->set($shortName, $resourceObjectType); - - return $resourceObjectType; - } - - /** - * {@inheritdoc} - */ - public function getNodeInterface(): InterfaceType - { - if ($this->typesContainer->has('Node')) { - $nodeInterface = $this->typesContainer->get('Node'); - if (!$nodeInterface instanceof InterfaceType) { - throw new \LogicException(sprintf('Expected GraphQL type "Node" to be %s.', InterfaceType::class)); - } - - return $nodeInterface; - } - - $nodeInterface = new InterfaceType([ - 'name' => 'Node', - 'description' => 'A node, according to the Relay specification.', - 'fields' => [ - 'id' => [ - 'type' => GraphQLType::nonNull(GraphQLType::id()), - 'description' => 'The id of this node.', - ], - ], - 'resolveType' => function ($value) { - if (!isset($value[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY])) { - return null; - } - - $shortName = (new \ReflectionClass($value[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY]))->getShortName(); - - return $this->typesContainer->has($shortName) ? $this->typesContainer->get($shortName) : null; - }, - ]); - - $this->typesContainer->set('Node', $nodeInterface); - - return $nodeInterface; - } - - /** - * {@inheritdoc} - */ - public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, string $operationName): GraphQLType - { - $shortName = $resourceType->name; - $paginationType = $this->pagination->getGraphQlPaginationType($resourceClass, $operationName); - - $connectionTypeKey = sprintf('%s%sConnection', $shortName, ucfirst($paginationType)); - if ($this->typesContainer->has($connectionTypeKey)) { - return $this->typesContainer->get($connectionTypeKey); - } - - $paginationType = $this->pagination->getGraphQlPaginationType($resourceClass, $operationName); - - $fields = 'cursor' === $paginationType ? - $this->getCursorBasedPaginationFields($resourceType) : - $this->getPageBasedPaginationFields($resourceType); - - $configuration = [ - 'name' => $connectionTypeKey, - 'description' => sprintf("%s connection for $shortName.", ucfirst($paginationType)), - 'fields' => $fields, - ]; - - $resourcePaginatedCollectionType = new ObjectType($configuration); - $this->typesContainer->set($connectionTypeKey, $resourcePaginatedCollectionType); - - return $resourcePaginatedCollectionType; - } - - /** - * {@inheritdoc} - */ - public function isCollection(Type $type): bool - { - return $type->isCollection() && ($collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType()) && null !== $collectionValueType->getClassName(); - } - - private function getCursorBasedPaginationFields(GraphQLType $resourceType): array - { - $shortName = $resourceType->name; - - $edgeObjectTypeConfiguration = [ - 'name' => "{$shortName}Edge", - 'description' => "Edge of $shortName.", - 'fields' => [ - 'node' => $resourceType, - 'cursor' => GraphQLType::nonNull(GraphQLType::string()), - ], - ]; - $edgeObjectType = new ObjectType($edgeObjectTypeConfiguration); - $this->typesContainer->set("{$shortName}Edge", $edgeObjectType); - - $pageInfoObjectTypeConfiguration = [ - 'name' => "{$shortName}PageInfo", - 'description' => 'Information about the current page.', - 'fields' => [ - 'endCursor' => GraphQLType::string(), - 'startCursor' => GraphQLType::string(), - 'hasNextPage' => GraphQLType::nonNull(GraphQLType::boolean()), - 'hasPreviousPage' => GraphQLType::nonNull(GraphQLType::boolean()), - ], - ]; - $pageInfoObjectType = new ObjectType($pageInfoObjectTypeConfiguration); - $this->typesContainer->set("{$shortName}PageInfo", $pageInfoObjectType); - - return [ - 'edges' => GraphQLType::listOf($edgeObjectType), - 'pageInfo' => GraphQLType::nonNull($pageInfoObjectType), - 'totalCount' => GraphQLType::nonNull(GraphQLType::int()), - ]; - } - - private function getPageBasedPaginationFields(GraphQLType $resourceType): array - { - $shortName = $resourceType->name; - - $paginationInfoObjectTypeConfiguration = [ - 'name' => "{$shortName}PaginationInfo", - 'description' => 'Information about the pagination.', - 'fields' => [ - 'itemsPerPage' => GraphQLType::nonNull(GraphQLType::int()), - 'lastPage' => GraphQLType::nonNull(GraphQLType::int()), - 'totalCount' => GraphQLType::nonNull(GraphQLType::int()), - ], - ]; - $paginationInfoObjectType = new ObjectType($paginationInfoObjectTypeConfiguration); - $this->typesContainer->set("{$shortName}PaginationInfo", $paginationInfoObjectType); - - return [ - 'collection' => GraphQLType::listOf($resourceType), - 'paginationInfo' => GraphQLType::nonNull($paginationInfoObjectType), - ]; - } -} diff --git a/src/Core/GraphQl/Type/TypeBuilderInterface.php b/src/Core/GraphQl/Type/TypeBuilderInterface.php deleted file mode 100644 index 3270a8d881c..00000000000 --- a/src/Core/GraphQl/Type/TypeBuilderInterface.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * 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\GraphQl\Type; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use GraphQL\Type\Definition\InterfaceType; -use GraphQL\Type\Definition\NonNull; -use GraphQL\Type\Definition\ObjectType; -use GraphQL\Type\Definition\Type as GraphQLType; -use Symfony\Component\PropertyInfo\Type; - -/** - * Interface implemented to build a GraphQL type. - * - * @author Alan Poulain - */ -interface TypeBuilderInterface -{ - /** - * Gets the object type of the given resource. - * - * @return ObjectType|NonNull the object type, possibly wrapped by NonNull - */ - public function getResourceObjectType(?string $resourceClass, ResourceMetadata $resourceMetadata, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, bool $wrapped, int $depth): GraphQLType; - - /** - * Get the interface type of a node. - */ - public function getNodeInterface(): InterfaceType; - - /** - * Gets the type of a paginated collection of the given resource type. - */ - public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, string $operationName): GraphQLType; - - /** - * Returns true if a type is a collection. - */ - public function isCollection(Type $type): bool; -} diff --git a/src/Core/GraphQl/Type/TypeConverter.php b/src/Core/GraphQl/Type/TypeConverter.php deleted file mode 100644 index 96e58ad2502..00000000000 --- a/src/Core/GraphQl/Type/TypeConverter.php +++ /dev/null @@ -1,205 +0,0 @@ - - * - * 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\GraphQl\Type; - -use ApiPlatform\Core\GraphQl\Type\TypesContainerInterface as TypesContainerLegacyInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\GraphQl\Type\TypesContainerInterface; -use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use GraphQL\Error\SyntaxError; -use GraphQL\Language\AST\ListTypeNode; -use GraphQL\Language\AST\NamedTypeNode; -use GraphQL\Language\AST\NonNullTypeNode; -use GraphQL\Language\AST\TypeNode; -use GraphQL\Language\Parser; -use GraphQL\Type\Definition\NullableType; -use GraphQL\Type\Definition\Type as GraphQLType; -use Symfony\Component\PropertyInfo\Type; - -/** - * Converts a type to its GraphQL equivalent. - * - * @author Alan Poulain - */ -final class TypeConverter implements TypeConverterInterface -{ - private $typeBuilder; - /** @var TypesContainerLegacyInterface|TypesContainerInterface */ - private $typesContainer; - private $resourceMetadataFactory; - /** @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface|null */ - private $propertyMetadataFactory; - - public function __construct(TypeBuilderInterface $typeBuilder, $typesContainer, ResourceMetadataFactoryInterface $resourceMetadataFactory, $propertyMetadataFactory = null) - { - $this->typeBuilder = $typeBuilder; - $this->typesContainer = $typesContainer; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - - if (null === $this->propertyMetadataFactory) { - @trigger_error(sprintf('Not injecting %s in the TypeConverter is deprecated since 2.7 and will not be supported in 3.0.', PropertyMetadataFactoryInterface::class), \E_USER_DEPRECATED); - } - } - - /** - * {@inheritdoc} - */ - public function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $resourceClass, string $rootResource, ?string $property, int $depth) - { - switch ($type->getBuiltinType()) { - case Type::BUILTIN_TYPE_BOOL: - return GraphQLType::boolean(); - case Type::BUILTIN_TYPE_INT: - return GraphQLType::int(); - case Type::BUILTIN_TYPE_FLOAT: - return GraphQLType::float(); - case Type::BUILTIN_TYPE_STRING: - return GraphQLType::string(); - case Type::BUILTIN_TYPE_ARRAY: - case Type::BUILTIN_TYPE_ITERABLE: - if ($resourceType = $this->getResourceType($type, $input, $queryName, $mutationName, $subscriptionName, $rootResource, $property, $depth)) { - return $resourceType; - } - - return 'Iterable'; - case Type::BUILTIN_TYPE_OBJECT: - if (is_a($type->getClassName(), \DateTimeInterface::class, true)) { - return GraphQLType::string(); - } - - return $this->getResourceType($type, $input, $queryName, $mutationName, $subscriptionName, $rootResource, $property, $depth); - default: - return null; - } - } - - /** - * {@inheritdoc} - */ - public function resolveType(string $type): ?GraphQLType - { - try { - $astTypeNode = Parser::parseType($type); - } catch (SyntaxError $e) { - throw new InvalidArgumentException(sprintf('"%s" is not a valid GraphQL type.', $type), 0, $e); - } - - if ($graphQlType = $this->resolveAstTypeNode($astTypeNode, $type)) { - return $graphQlType; - } - - throw new InvalidArgumentException(sprintf('The type "%s" was not resolved.', $type)); - } - - private function getResourceType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $rootResource, ?string $property, int $depth): ?GraphQLType - { - if ( - $this->typeBuilder->isCollection($type) && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $resourceClass = $collectionValueType->getClassName(); - } else { - $resourceClass = $type->getClassName(); - } - - if (null === $resourceClass) { - return null; - } - - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (null === $resourceMetadata->getGraphql()) { - return null; - } - if ('Node' === $resourceMetadata->getShortName()) { - throw new \UnexpectedValueException('A "Node" resource cannot be used with GraphQL because the type is already used by the Relay specification.'); - } - } catch (ResourceClassNotFoundException $e) { - // Skip objects that are not resources for now - return null; - } - - $propertyMetadata = null; - if ($property && $this->propertyMetadataFactory) { - $rootResourceMetadata = null; - try { - $rootResourceMetadata = $this->resourceMetadataFactory->create($rootResource); - } catch (ResourceClassNotFoundException $e) { - } - - $context = [ - 'normalization_groups' => $rootResourceMetadata ? $rootResourceMetadata->getGraphqlAttribute($queryName ?? $mutationName ?? $subscriptionName, 'normalization_context', [], true)['groups'] ?? null : null, - 'denormalization_groups' => $rootResourceMetadata ? $rootResourceMetadata->getGraphqlAttribute($queryName ?? $mutationName ?? $subscriptionName, 'denormalization_context', [], true)['groups'] ?? null : null, - ]; - $propertyMetadata = $this->propertyMetadataFactory->create($rootResource, $property, $context); - } - - if ($input && $depth > 0 && (!$propertyMetadata || !$propertyMetadata->isWritableLink())) { - return GraphQLType::string(); - } - - return $this->typeBuilder->getResourceObjectType($resourceClass, $resourceMetadata, $input, $queryName, $mutationName, $subscriptionName, false, $depth); - } - - private function resolveAstTypeNode(TypeNode $astTypeNode, string $fromType): ?GraphQLType - { - if ($astTypeNode instanceof NonNullTypeNode) { - /** @var NullableType|null $nullableAstTypeNode */ - $nullableAstTypeNode = $this->resolveNullableAstTypeNode($astTypeNode->type, $fromType); - - return $nullableAstTypeNode ? GraphQLType::nonNull($nullableAstTypeNode) : null; - } - - return $this->resolveNullableAstTypeNode($astTypeNode, $fromType); - } - - private function resolveNullableAstTypeNode(TypeNode $astTypeNode, string $fromType): ?GraphQLType - { - if ($astTypeNode instanceof ListTypeNode) { - /** @var TypeNode $astTypeNodeElement */ - $astTypeNodeElement = $astTypeNode->type; - - return GraphQLType::listOf($this->resolveAstTypeNode($astTypeNodeElement, $fromType)); - } - - if (!$astTypeNode instanceof NamedTypeNode) { - return null; - } - - $typeName = $astTypeNode->name->value; - - switch ($typeName) { - case GraphQLType::STRING: - return GraphQLType::string(); - case GraphQLType::INT: - return GraphQLType::int(); - case GraphQLType::BOOLEAN: - return GraphQLType::boolean(); - case GraphQLType::FLOAT: - return GraphQLType::float(); - case GraphQLType::ID: - return GraphQLType::id(); - default: - if ($this->typesContainer->has($typeName)) { - return $this->typesContainer->get($typeName); - } - - return null; - } - } -} diff --git a/src/Core/GraphQl/Type/TypeConverterInterface.php b/src/Core/GraphQl/Type/TypeConverterInterface.php deleted file mode 100644 index 53c65c1c592..00000000000 --- a/src/Core/GraphQl/Type/TypeConverterInterface.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * 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\GraphQl\Type; - -use GraphQL\Type\Definition\Type as GraphQLType; -use Symfony\Component\PropertyInfo\Type; - -/** - * Converts a type to its GraphQL equivalent. - * - * @author Alan Poulain - */ -interface TypeConverterInterface -{ - /** - * Converts a built-in type to its GraphQL equivalent. - * A string can be returned for a custom registered type. - * - * @return string|GraphQLType|null - */ - public function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $resourceClass, string $rootResource, ?string $property, int $depth); - - /** - * Resolves a type written with the GraphQL type system to its object representation. - */ - public function resolveType(string $type): ?GraphQLType; -} diff --git a/src/Core/GraphQl/Type/TypeNotFoundException.php b/src/Core/GraphQl/Type/TypeNotFoundException.php deleted file mode 100644 index b09ea7634f1..00000000000 --- a/src/Core/GraphQl/Type/TypeNotFoundException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Type; - -class_exists(\ApiPlatform\GraphQl\Type\TypeNotFoundException::class); - -if (false) { - final class TypeNotFoundException extends \ApiPlatform\GraphQl\Type\TypeNotFoundException - { - } -} diff --git a/src/Core/GraphQl/Type/TypesContainer.php b/src/Core/GraphQl/Type/TypesContainer.php deleted file mode 100644 index ae852470804..00000000000 --- a/src/Core/GraphQl/Type/TypesContainer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Type; - -class_exists(\ApiPlatform\GraphQl\Type\TypesContainer::class); - -if (false) { - final class TypesContainer extends \ApiPlatform\GraphQl\Type\TypesContainer - { - } -} diff --git a/src/Core/GraphQl/Type/TypesFactory.php b/src/Core/GraphQl/Type/TypesFactory.php deleted file mode 100644 index b359c63adda..00000000000 --- a/src/Core/GraphQl/Type/TypesFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\GraphQl\Type; - -class_exists(\ApiPlatform\GraphQl\Type\TypesFactory::class); - -if (false) { - final class TypesFactory extends \ApiPlatform\GraphQl\Type\TypesFactory - { - } -} diff --git a/src/Core/Hal/JsonSchema/SchemaFactory.php b/src/Core/Hal/JsonSchema/SchemaFactory.php deleted file mode 100644 index eaebc028937..00000000000 --- a/src/Core/Hal/JsonSchema/SchemaFactory.php +++ /dev/null @@ -1,137 +0,0 @@ - - * - * 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\Hal\JsonSchema; - -use ApiPlatform\Core\JsonSchema\Schema; -use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface; - -/** - * Decorator factory which adds HAL properties to the JSON Schema document. - * - * @experimental - * - * @author Kévin Dunglas - * @author Jachim Coudenys - */ -final class SchemaFactory implements SchemaFactoryInterface -{ - private const HREF_PROP = [ - 'href' => [ - 'type' => 'string', - 'format' => 'iri-reference', - ], - ]; - private const BASE_PROPS = [ - '_links' => [ - 'type' => 'object', - 'properties' => [ - 'self' => [ - 'type' => 'object', - 'properties' => self::HREF_PROP, - ], - ], - ], - ]; - - private $schemaFactory; - - public function __construct(SchemaFactoryInterface $schemaFactory) - { - $this->schemaFactory = $schemaFactory; - - $this->addDistinctFormat('jsonhal'); - } - - /** - * {@inheritdoc} - */ - public function buildSchema(string $className, string $format = 'json', string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null, ?Schema $schema = null, ?array $serializerContext = null, bool $forceCollection = false): Schema - { - $schema = $this->schemaFactory->buildSchema($className, $format, $type, $operationType, $operationName, $schema, $serializerContext, $forceCollection); - if ('jsonhal' !== $format) { - return $schema; - } - - $definitions = $schema->getDefinitions(); - if ($key = $schema->getRootDefinitionKey()) { - $definitions[$key]['properties'] = self::BASE_PROPS + ($definitions[$key]['properties'] ?? []); - - return $schema; - } - if ($key = $schema->getItemsDefinitionKey()) { - $definitions[$key]['properties'] = self::BASE_PROPS + ($definitions[$key]['properties'] ?? []); - } - - if (($schema['type'] ?? '') === 'array') { - $items = $schema['items']; - unset($schema['items']); - - $schema['type'] = 'object'; - $schema['properties'] = [ - '_embedded' => [ - 'type' => 'array', - 'items' => $items, - ], - 'totalItems' => [ - 'type' => 'integer', - 'minimum' => 0, - ], - 'itemsPerPage' => [ - 'type' => 'integer', - 'minimum' => 0, - ], - '_links' => [ - 'type' => 'object', - 'properties' => [ - 'self' => [ - 'type' => 'object', - 'properties' => self::HREF_PROP, - ], - 'first' => [ - 'type' => 'object', - 'properties' => self::HREF_PROP, - ], - 'last' => [ - 'type' => 'object', - 'properties' => self::HREF_PROP, - ], - 'next' => [ - 'type' => 'object', - 'properties' => self::HREF_PROP, - ], - 'previous' => [ - 'type' => 'object', - 'properties' => self::HREF_PROP, - ], - ], - ], - ]; - $schema['required'] = [ - '_links', - '_embedded', - ]; - - return $schema; - } - - return $schema; - } - - public function addDistinctFormat(string $format): void - { - if (method_exists($this->schemaFactory, 'addDistinctFormat')) { - $this->schemaFactory->addDistinctFormat($format); - } - } -} diff --git a/src/Core/Hal/Serializer/CollectionNormalizer.php b/src/Core/Hal/Serializer/CollectionNormalizer.php deleted file mode 100644 index f3eb171ef3b..00000000000 --- a/src/Core/Hal/Serializer/CollectionNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hal\Serializer; - -class_exists(\ApiPlatform\Hal\Serializer\CollectionNormalizer::class); - -if (false) { - final class CollectionNormalizer extends \ApiPlatform\Hal\Serializer\CollectionNormalizer - { - } -} diff --git a/src/Core/Hal/Serializer/EntrypointNormalizer.php b/src/Core/Hal/Serializer/EntrypointNormalizer.php deleted file mode 100644 index 1ab80f92df8..00000000000 --- a/src/Core/Hal/Serializer/EntrypointNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hal\Serializer; - -class_exists(\ApiPlatform\Hal\Serializer\EntrypointNormalizer::class); - -if (false) { - final class EntrypointNormalizer extends \ApiPlatform\Hal\Serializer\EntrypointNormalizer - { - } -} diff --git a/src/Core/Hal/Serializer/ItemNormalizer.php b/src/Core/Hal/Serializer/ItemNormalizer.php deleted file mode 100644 index 33a67f551b2..00000000000 --- a/src/Core/Hal/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hal\Serializer; - -class_exists(\ApiPlatform\Hal\Serializer\ItemNormalizer::class); - -if (false) { - final class ItemNormalizer extends \ApiPlatform\Hal\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/Hal/Serializer/ObjectNormalizer.php b/src/Core/Hal/Serializer/ObjectNormalizer.php deleted file mode 100644 index b418b891813..00000000000 --- a/src/Core/Hal/Serializer/ObjectNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hal\Serializer; - -class_exists(\ApiPlatform\Hal\Serializer\ObjectNormalizer::class); - -if (false) { - final class ObjectNormalizer extends \ApiPlatform\Hal\Serializer\ObjectNormalizer - { - } -} diff --git a/src/Core/HttpCache/EventListener/AddHeadersListener.php b/src/Core/HttpCache/EventListener/AddHeadersListener.php deleted file mode 100644 index 7dd640e01bf..00000000000 --- a/src/Core/HttpCache/EventListener/AddHeadersListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\HttpCache\EventListener; - -class_exists(\ApiPlatform\HttpCache\EventListener\AddHeadersListener::class); - -if (false) { - final class AddHeadersListener extends \ApiPlatform\HttpCache\EventListener\AddHeadersListener - { - } -} diff --git a/src/Core/HttpCache/EventListener/AddTagsListener.php b/src/Core/HttpCache/EventListener/AddTagsListener.php deleted file mode 100644 index 27d74e1f9ca..00000000000 --- a/src/Core/HttpCache/EventListener/AddTagsListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\HttpCache\EventListener; - -class_exists(\ApiPlatform\HttpCache\EventListener\AddTagsListener::class); - -if (false) { - final class AddTagsListener extends \ApiPlatform\HttpCache\EventListener\AddTagsListener - { - } -} diff --git a/src/Core/HttpCache/PurgerInterface.php b/src/Core/HttpCache/PurgerInterface.php deleted file mode 100644 index b1c14ccd911..00000000000 --- a/src/Core/HttpCache/PurgerInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * 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\HttpCache; - -/** - * Purges resources from the cache. - * - * @author Kévin Dunglas - * - * @experimental - */ -interface PurgerInterface -{ - /** - * Purges all responses containing the given resources from the cache. - * - * @param string[] $iris - */ - public function purge(array $iris): void; -} diff --git a/src/Core/HttpCache/VarnishPurger.php b/src/Core/HttpCache/VarnishPurger.php deleted file mode 100644 index 944b66b965d..00000000000 --- a/src/Core/HttpCache/VarnishPurger.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\HttpCache; - -class_exists(\ApiPlatform\HttpCache\VarnishPurger::class); - -if (false) { - final class VarnishPurger extends \ApiPlatform\HttpCache\VarnishPurger - { - } -} diff --git a/src/Core/HttpCache/VarnishXKeyPurger.php b/src/Core/HttpCache/VarnishXKeyPurger.php deleted file mode 100644 index 06f19ee752e..00000000000 --- a/src/Core/HttpCache/VarnishXKeyPurger.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\HttpCache; - -class_exists(\ApiPlatform\HttpCache\VarnishXKeyPurger::class); - -if (false) { - final class VarnishXKeyPurger extends \ApiPlatform\HttpCache\VarnishXKeyPurger - { - } -} diff --git a/src/Core/Hydra/EventListener/AddLinkHeaderListener.php b/src/Core/Hydra/EventListener/AddLinkHeaderListener.php deleted file mode 100644 index 0a02983bd4a..00000000000 --- a/src/Core/Hydra/EventListener/AddLinkHeaderListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hydra\EventListener; - -class_exists(\ApiPlatform\Hydra\EventListener\AddLinkHeaderListener::class); - -if (false) { - final class AddLinkHeaderListener extends \ApiPlatform\Hydra\EventListener\AddLinkHeaderListener - { - } -} diff --git a/src/Core/Hydra/JsonSchema/SchemaFactory.php b/src/Core/Hydra/JsonSchema/SchemaFactory.php deleted file mode 100644 index 03a8ad49aad..00000000000 --- a/src/Core/Hydra/JsonSchema/SchemaFactory.php +++ /dev/null @@ -1,189 +0,0 @@ - - * - * 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\Hydra\JsonSchema; - -use ApiPlatform\Core\JsonLd\ContextBuilder; -use ApiPlatform\Core\JsonSchema\Schema; -use ApiPlatform\Core\JsonSchema\SchemaFactory as BaseSchemaFactory; -use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface; - -/** - * Decorator factory which adds Hydra properties to the JSON Schema document. - * - * @experimental - * - * @author Kévin Dunglas - */ -final class SchemaFactory implements SchemaFactoryInterface -{ - private const BASE_PROP = [ - 'readOnly' => true, - 'type' => 'string', - ]; - private const BASE_PROPS = [ - '@id' => self::BASE_PROP, - '@type' => self::BASE_PROP, - ]; - private const BASE_ROOT_PROPS = [ - '@context' => [ - 'readOnly' => true, - 'oneOf' => [ - ['type' => 'string'], - [ - 'type' => 'object', - 'properties' => [ - '@vocab' => [ - 'type' => 'string', - ], - 'hydra' => [ - 'type' => 'string', - 'enum' => [ContextBuilder::HYDRA_NS], - ], - ], - 'required' => ['@vocab', 'hydra'], - 'additionalProperties' => true, - ], - ], - ], - ] + self::BASE_PROPS; - - private $schemaFactory; - - public function __construct(SchemaFactoryInterface $schemaFactory) - { - $this->schemaFactory = $schemaFactory; - - $this->addDistinctFormat('jsonld'); - } - - /** - * {@inheritdoc} - */ - public function buildSchema(string $className, string $format = 'json', string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null, ?Schema $schema = null, ?array $serializerContext = null, bool $forceCollection = false): Schema - { - $schema = $this->schemaFactory->buildSchema($className, $format, $type, $operationType, $operationName, $schema, $serializerContext, $forceCollection); - if ('jsonld' !== $format) { - return $schema; - } - - $definitions = $schema->getDefinitions(); - if ($key = $schema->getRootDefinitionKey()) { - $definitions[$key]['properties'] = self::BASE_ROOT_PROPS + ($definitions[$key]['properties'] ?? []); - - return $schema; - } - if ($key = $schema->getItemsDefinitionKey()) { - $definitions[$key]['properties'] = self::BASE_PROPS + ($definitions[$key]['properties'] ?? []); - } - - if (($schema['type'] ?? '') === 'array') { - // hydra:collection - $items = $schema['items']; - unset($schema['items']); - - $nullableStringDefinition = ['type' => 'string']; - - switch ($schema->getVersion()) { - case Schema::VERSION_JSON_SCHEMA: - $nullableStringDefinition = ['type' => ['string', 'null']]; - break; - case Schema::VERSION_OPENAPI: - $nullableStringDefinition = ['type' => 'string', 'nullable' => true]; - break; - } - - $schema['type'] = 'object'; - $schema['properties'] = [ - 'hydra:member' => [ - 'type' => 'array', - 'items' => $items, - ], - 'hydra:totalItems' => [ - 'type' => 'integer', - 'minimum' => 0, - ], - 'hydra:view' => [ - 'type' => 'object', - 'properties' => [ - '@id' => [ - 'type' => 'string', - 'format' => 'iri-reference', - ], - '@type' => [ - 'type' => 'string', - ], - 'hydra:first' => [ - 'type' => 'string', - 'format' => 'iri-reference', - ], - 'hydra:last' => [ - 'type' => 'string', - 'format' => 'iri-reference', - ], - 'hydra:previous' => [ - 'type' => 'string', - 'format' => 'iri-reference', - ], - 'hydra:next' => [ - 'type' => 'string', - 'format' => 'iri-reference', - ], - ], - 'example' => [ - '@id' => 'string', - 'type' => 'string', - 'hydra:first' => 'string', - 'hydra:last' => 'string', - 'hydra:previous' => 'string', - 'hydra:next' => 'string', - ], - ], - 'hydra:search' => [ - 'type' => 'object', - 'properties' => [ - '@type' => ['type' => 'string'], - 'hydra:template' => ['type' => 'string'], - 'hydra:variableRepresentation' => ['type' => 'string'], - 'hydra:mapping' => [ - 'type' => 'array', - 'items' => [ - 'type' => 'object', - 'properties' => [ - '@type' => ['type' => 'string'], - 'variable' => ['type' => 'string'], - 'property' => $nullableStringDefinition, - 'required' => ['type' => 'boolean'], - ], - ], - ], - ], - ], - ]; - $schema['required'] = [ - 'hydra:member', - ]; - - return $schema; - } - - return $schema; - } - - public function addDistinctFormat(string $format): void - { - if ($this->schemaFactory instanceof BaseSchemaFactory) { - $this->schemaFactory->addDistinctFormat($format); - } - } -} diff --git a/src/Core/Hydra/Serializer/CollectionFiltersNormalizer.php b/src/Core/Hydra/Serializer/CollectionFiltersNormalizer.php deleted file mode 100644 index b0e8deda7fd..00000000000 --- a/src/Core/Hydra/Serializer/CollectionFiltersNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer::class); - -if (false) { - final class CollectionFiltersNormalizer extends \ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/CollectionNormalizer.php b/src/Core/Hydra/Serializer/CollectionNormalizer.php deleted file mode 100644 index d3a43938f1d..00000000000 --- a/src/Core/Hydra/Serializer/CollectionNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\CollectionNormalizer::class); - -if (false) { - final class CollectionNormalizer extends \ApiPlatform\Hydra\Serializer\CollectionNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/ConstraintViolationListNormalizer.php b/src/Core/Hydra/Serializer/ConstraintViolationListNormalizer.php deleted file mode 100644 index 631ae16dc87..00000000000 --- a/src/Core/Hydra/Serializer/ConstraintViolationListNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer::class); - -if (false) { - final class ConstraintViolationListNormalizer extends \ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/DocumentationNormalizer.php b/src/Core/Hydra/Serializer/DocumentationNormalizer.php deleted file mode 100644 index 26824ab3a40..00000000000 --- a/src/Core/Hydra/Serializer/DocumentationNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\DocumentationNormalizer::class); - -if (false) { - final class DocumentationNormalizer extends \ApiPlatform\Hydra\Serializer\DocumentationNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/EntrypointNormalizer.php b/src/Core/Hydra/Serializer/EntrypointNormalizer.php deleted file mode 100644 index a7682e82fae..00000000000 --- a/src/Core/Hydra/Serializer/EntrypointNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\EntrypointNormalizer::class); - -if (false) { - final class EntrypointNormalizer extends \ApiPlatform\Hydra\Serializer\EntrypointNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/ErrorNormalizer.php b/src/Core/Hydra/Serializer/ErrorNormalizer.php deleted file mode 100644 index 57de73d96c4..00000000000 --- a/src/Core/Hydra/Serializer/ErrorNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\ErrorNormalizer::class); - -if (false) { - final class ErrorNormalizer extends \ApiPlatform\Hydra\Serializer\ErrorNormalizer - { - } -} diff --git a/src/Core/Hydra/Serializer/PartialCollectionViewNormalizer.php b/src/Core/Hydra/Serializer/PartialCollectionViewNormalizer.php deleted file mode 100644 index 6f8e6e1095c..00000000000 --- a/src/Core/Hydra/Serializer/PartialCollectionViewNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Hydra\Serializer; - -class_exists(\ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer::class); - -if (false) { - final class PartialCollectionViewNormalizer extends \ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer - { - } -} diff --git a/src/Core/Identifier/CompositeIdentifierParser.php b/src/Core/Identifier/CompositeIdentifierParser.php deleted file mode 100644 index f95c1191f07..00000000000 --- a/src/Core/Identifier/CompositeIdentifierParser.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * 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\Identifier; - -/** - * Normalizes a composite identifier. - * - * @author Antoine Bluchet - */ -final class CompositeIdentifierParser -{ - public const COMPOSITE_IDENTIFIER_REGEXP = '/(\w+)=(?<=\w=)(.*?)(?=;\w+=)|(\w+)=([^;]*);?$/'; - - private function __construct() - { - } - - /* - * Normalize takes a string and gives back an array of identifiers. - * - * For example: foo=0;bar=2 returns ['foo' => 0, 'bar' => 2]. - */ - public static function parse(string $identifier): array - { - $matches = []; - $identifiers = []; - $num = preg_match_all(self::COMPOSITE_IDENTIFIER_REGEXP, $identifier, $matches, \PREG_SET_ORDER); - - foreach ($matches as $i => $match) { - if ($i === $num - 1) { - $identifiers[$match[3]] = $match[4]; - continue; - } - $identifiers[$match[1]] = $match[2]; - } - - return $identifiers; - } - - /** - * Renders composite identifiers to string using: key=value;key2=value2. - */ - public static function stringify(array $identifiers): string - { - $composite = []; - foreach ($identifiers as $name => $value) { - $composite[] = sprintf('%s=%s', $name, $value); - } - - return implode(';', $composite); - } -} diff --git a/src/Core/Identifier/ContextAwareIdentifierConverterInterface.php b/src/Core/Identifier/ContextAwareIdentifierConverterInterface.php deleted file mode 100644 index 76f33ad81f0..00000000000 --- a/src/Core/Identifier/ContextAwareIdentifierConverterInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * 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\Identifier; - -/** - * Gives access to the context in the IdentifierConverter. - * - * @author Antoine Bluchet - */ -interface ContextAwareIdentifierConverterInterface extends IdentifierConverterInterface -{ - /** - * {@inheritdoc} - */ - public function convert($data, string $class, array $context = []): array; -} diff --git a/src/Core/Identifier/IdentifierConverter.php b/src/Core/Identifier/IdentifierConverter.php deleted file mode 100644 index 9af469b4f96..00000000000 --- a/src/Core/Identifier/IdentifierConverter.php +++ /dev/null @@ -1,91 +0,0 @@ - - * - * 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\Identifier; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\InvalidIdentifierException; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * Identifier converter that chains identifier denormalizers. - * - * @author Antoine Bluchet - */ -final class IdentifierConverter implements ContextAwareIdentifierConverterInterface -{ - private $propertyMetadataFactory; - private $identifiersExtractor; - private $identifierDenormalizers; - private $resourceMetadataFactory; - - /** - * TODO: rename identifierDenormalizers to identifierTransformers in 3.0 and change their interfaces to a IdentifierTransformerInterface. - * - * @param iterable $identifierDenormalizers - */ - public function __construct(IdentifiersExtractorInterface $identifiersExtractor, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $identifierDenormalizers, ResourceMetadataFactoryInterface $resourceMetadataFactory = null) - { - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->identifiersExtractor = $identifiersExtractor; - $this->identifierDenormalizers = $identifierDenormalizers; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - - /** - * {@inheritdoc} - */ - public function convert($data, string $class, array $context = []): array - { - if (!\is_array($data)) { - @trigger_error(sprintf('Not using an array as the first argument of "%s->convert" is deprecated since API Platform 2.6 and will not be possible anymore in API Platform 3', self::class), \E_USER_DEPRECATED); - $data = ['id' => $data]; - } - - $identifiers = $data; - - foreach ($data as $parameter => $value) { - if (null === $type = $this->getIdentifierType($context['identifiers'][$parameter][0] ?? $class, $context['identifiers'][$parameter][1] ?? $parameter)) { - continue; - } - - /* @var DenormalizerInterface[] */ - foreach ($this->identifierDenormalizers as $identifierTransformer) { - if (!$identifierTransformer->supportsDenormalization($value, $type)) { - continue; - } - - try { - $identifiers[$parameter] = $identifierTransformer->denormalize($value, $type); - break; - } catch (InvalidIdentifierException $e) { - throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $parameter), $e->getCode(), $e); - } - } - } - - return $identifiers; - } - - private function getIdentifierType(string $resourceClass, string $property): ?string - { - if (!$type = $this->propertyMetadataFactory->create($resourceClass, $property)->getType()) { - return null; - } - - return Type::BUILTIN_TYPE_OBJECT === ($builtinType = $type->getBuiltinType()) ? $type->getClassName() : $builtinType; - } -} diff --git a/src/Core/Identifier/IdentifierConverterInterface.php b/src/Core/Identifier/IdentifierConverterInterface.php deleted file mode 100644 index 983525fc132..00000000000 --- a/src/Core/Identifier/IdentifierConverterInterface.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * 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\Identifier; - -use ApiPlatform\Exception\InvalidIdentifierException; - -/** - * Identifier converter. - * - * @author Antoine Bluchet - */ -interface IdentifierConverterInterface -{ - /** - * @internal - */ - public const HAS_IDENTIFIER_CONVERTER = 'has_identifier_converter'; - - /** - * Takes an array of strings representing identifiers and transform their values to the expected type. - * - * @param mixed $data Identifier to convert to php values - * @param string $class The class to which the identifiers belong - * - * @throws InvalidIdentifierException - * - * @return array Indexed by identifiers properties with their values denormalized - */ - public function convert($data, string $class): array; -} diff --git a/src/Core/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php b/src/Core/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php deleted file mode 100644 index 9b73c1eca2a..00000000000 --- a/src/Core/Identifier/Normalizer/DateTimeIdentifierDenormalizer.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * 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\Identifier\Normalizer; - -use ApiPlatform\Exception\InvalidIdentifierException; -use Symfony\Component\Serializer\Exception\NotNormalizableValueException; -use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; - -final class DateTimeIdentifierDenormalizer extends DateTimeNormalizer -{ - /** - * @param mixed|null $format - * @param mixed $data - * @param mixed $class - */ - public function denormalize($data, $class, $format = null, array $context = []): \DateTimeInterface - { - try { - return parent::denormalize($data, $class, $format, $context); - } catch (NotNormalizableValueException $e) { - throw new InvalidIdentifierException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - */ - public function hasCacheableSupportsMethod(): bool - { - return true; - } -} diff --git a/src/Core/Identifier/Normalizer/IntegerDenormalizer.php b/src/Core/Identifier/Normalizer/IntegerDenormalizer.php deleted file mode 100644 index d75e1e9cf00..00000000000 --- a/src/Core/Identifier/Normalizer/IntegerDenormalizer.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * 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\Identifier\Normalizer; - -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -final class IntegerDenormalizer implements DenormalizerInterface, CacheableSupportsMethodInterface -{ - /** - * {@inheritdoc} - */ - public function denormalize($data, $class, $format = null, array $context = []): int - { - return (int) $data; - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null): bool - { - return Type::BUILTIN_TYPE_INT === $type && \is_string($data); - } - - /** - * {@inheritdoc} - */ - public function hasCacheableSupportsMethod(): bool - { - return true; - } -} diff --git a/src/Core/JsonApi/EventListener/TransformFieldsetsParametersListener.php b/src/Core/JsonApi/EventListener/TransformFieldsetsParametersListener.php deleted file mode 100644 index f2b5cb4d7ce..00000000000 --- a/src/Core/JsonApi/EventListener/TransformFieldsetsParametersListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener::class); - -if (false) { - final class TransformFieldsetsParametersListener extends \ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener - { - } -} diff --git a/src/Core/JsonApi/EventListener/TransformFilteringParametersListener.php b/src/Core/JsonApi/EventListener/TransformFilteringParametersListener.php deleted file mode 100644 index efbc636de69..00000000000 --- a/src/Core/JsonApi/EventListener/TransformFilteringParametersListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener::class); - -if (false) { - final class TransformFilteringParametersListener extends \ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener - { - } -} diff --git a/src/Core/JsonApi/EventListener/TransformPaginationParametersListener.php b/src/Core/JsonApi/EventListener/TransformPaginationParametersListener.php deleted file mode 100644 index c8757daf9b9..00000000000 --- a/src/Core/JsonApi/EventListener/TransformPaginationParametersListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener::class); - -if (false) { - final class TransformPaginationParametersListener extends \ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener - { - } -} diff --git a/src/Core/JsonApi/EventListener/TransformSortingParametersListener.php b/src/Core/JsonApi/EventListener/TransformSortingParametersListener.php deleted file mode 100644 index ad743feb683..00000000000 --- a/src/Core/JsonApi/EventListener/TransformSortingParametersListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener::class); - -if (false) { - final class TransformSortingParametersListener extends \ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener - { - } -} diff --git a/src/Core/JsonApi/Serializer/CollectionNormalizer.php b/src/Core/JsonApi/Serializer/CollectionNormalizer.php deleted file mode 100644 index c82d3bcf872..00000000000 --- a/src/Core/JsonApi/Serializer/CollectionNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\CollectionNormalizer::class); - -if (false) { - final class CollectionNormalizer extends \ApiPlatform\JsonApi\Serializer\CollectionNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ConstraintViolationListNormalizer.php b/src/Core/JsonApi/Serializer/ConstraintViolationListNormalizer.php deleted file mode 100644 index 1b8ad3247bc..00000000000 --- a/src/Core/JsonApi/Serializer/ConstraintViolationListNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer::class); - -if (false) { - final class ConstraintViolationListNormalizer extends \ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/EntrypointNormalizer.php b/src/Core/JsonApi/Serializer/EntrypointNormalizer.php deleted file mode 100644 index 0edf014ac61..00000000000 --- a/src/Core/JsonApi/Serializer/EntrypointNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\EntrypointNormalizer::class); - -if (false) { - final class EntrypointNormalizer extends \ApiPlatform\JsonApi\Serializer\EntrypointNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ErrorNormalizer.php b/src/Core/JsonApi/Serializer/ErrorNormalizer.php deleted file mode 100644 index d30771f80a8..00000000000 --- a/src/Core/JsonApi/Serializer/ErrorNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ErrorNormalizer::class); - -if (false) { - final class ErrorNormalizer extends \ApiPlatform\JsonApi\Serializer\ErrorNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ItemNormalizer.php b/src/Core/JsonApi/Serializer/ItemNormalizer.php deleted file mode 100644 index 45df1a32192..00000000000 --- a/src/Core/JsonApi/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ItemNormalizer::class); - -if (false) { - final class ItemNormalizer extends \ApiPlatform\JsonApi\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ObjectNormalizer.php b/src/Core/JsonApi/Serializer/ObjectNormalizer.php deleted file mode 100644 index 5e838cfbe62..00000000000 --- a/src/Core/JsonApi/Serializer/ObjectNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ObjectNormalizer::class); - -if (false) { - final class ObjectNormalizer extends \ApiPlatform\JsonApi\Serializer\ObjectNormalizer - { - } -} diff --git a/src/Core/JsonApi/Serializer/ReservedAttributeNameConverter.php b/src/Core/JsonApi/Serializer/ReservedAttributeNameConverter.php deleted file mode 100644 index ec61d3df8df..00000000000 --- a/src/Core/JsonApi/Serializer/ReservedAttributeNameConverter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonApi\Serializer; - -class_exists(\ApiPlatform\JsonApi\Serializer\ReservedAttributeNameConverter::class); - -if (false) { - final class ReservedAttributeNameConverter extends \ApiPlatform\JsonApi\Serializer\ReservedAttributeNameConverter - { - } -} diff --git a/src/Core/JsonLd/Action/ContextAction.php b/src/Core/JsonLd/Action/ContextAction.php deleted file mode 100644 index f2e668a3ab8..00000000000 --- a/src/Core/JsonLd/Action/ContextAction.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonLd\Action; - -class_exists(\ApiPlatform\JsonLd\Action\ContextAction::class); - -if (false) { - final class ContextAction extends \ApiPlatform\JsonLd\Action\ContextAction - { - } -} diff --git a/src/Core/JsonLd/ContextBuilder.php b/src/Core/JsonLd/ContextBuilder.php deleted file mode 100644 index a65df6d2e1e..00000000000 --- a/src/Core/JsonLd/ContextBuilder.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonLd; - -class_exists(\ApiPlatform\JsonLd\ContextBuilder::class); - -if (false) { - final class ContextBuilder extends \ApiPlatform\JsonLd\ContextBuilder - { - } -} diff --git a/src/Core/JsonLd/Serializer/ItemNormalizer.php b/src/Core/JsonLd/Serializer/ItemNormalizer.php deleted file mode 100644 index ceef30d9f9f..00000000000 --- a/src/Core/JsonLd/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonLd\Serializer; - -class_exists(\ApiPlatform\JsonLd\Serializer\ItemNormalizer::class); - -if (false) { - final class ItemNormalizer extends \ApiPlatform\JsonLd\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/JsonLd/Serializer/JsonLdContextTrait.php b/src/Core/JsonLd/Serializer/JsonLdContextTrait.php deleted file mode 100644 index 84a6f94c001..00000000000 --- a/src/Core/JsonLd/Serializer/JsonLdContextTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\JsonLd\Serializer; - -class_exists(\ApiPlatform\JsonLd\Serializer\JsonLdContextTrait::class); - -if (false) { - trait JsonLdContextTrait - { - use \ApiPlatform\JsonLd\Serializer\JsonLdContextTrait; - } -} diff --git a/src/Core/JsonLd/Serializer/ObjectNormalizer.php b/src/Core/JsonLd/Serializer/ObjectNormalizer.php deleted file mode 100644 index cca5348c115..00000000000 --- a/src/Core/JsonLd/Serializer/ObjectNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonLd\Serializer; - -class_exists(\ApiPlatform\JsonLd\Serializer\ObjectNormalizer::class); - -if (false) { - final class ObjectNormalizer extends \ApiPlatform\JsonLd\Serializer\ObjectNormalizer - { - } -} diff --git a/src/Core/JsonSchema/Command/JsonSchemaGenerateCommand.php b/src/Core/JsonSchema/Command/JsonSchemaGenerateCommand.php deleted file mode 100644 index 5427bd17c6a..00000000000 --- a/src/Core/JsonSchema/Command/JsonSchemaGenerateCommand.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonSchema\Command; - -class_exists(\ApiPlatform\JsonSchema\Command\JsonSchemaGenerateCommand::class); - -if (false) { - final class JsonSchemaGenerateCommand extends \ApiPlatform\JsonSchema\Command\JsonSchemaGenerateCommand - { - } -} diff --git a/src/Core/JsonSchema/Schema.php b/src/Core/JsonSchema/Schema.php deleted file mode 100644 index 759a42ee924..00000000000 --- a/src/Core/JsonSchema/Schema.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonSchema; - -class_exists(\ApiPlatform\JsonSchema\Schema::class); - -if (false) { - final class Schema extends \ApiPlatform\JsonSchema\Schema - { - } -} diff --git a/src/Core/JsonSchema/SchemaFactory.php b/src/Core/JsonSchema/SchemaFactory.php deleted file mode 100644 index 372eb63c3dc..00000000000 --- a/src/Core/JsonSchema/SchemaFactory.php +++ /dev/null @@ -1,447 +0,0 @@ - - * - * 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\JsonSchema; - -use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\JsonSchema\TypeFactoryInterface; -use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\HttpOperation; -use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; -use ApiPlatform\OpenApi\Factory\OpenApiFactory; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * {@inheritdoc} - * - * @experimental - * - * @author Kévin Dunglas - */ -final class SchemaFactory implements SchemaFactoryInterface -{ - use ResourceClassInfoTrait; - - private $typeFactory; - /** - * @var LegacyPropertyNameCollectionFactoryInterface|PropertyNameCollectionFactoryInterface - */ - private $propertyNameCollectionFactory; - /** - * @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface - */ - private $propertyMetadataFactory; - private $nameConverter; - private $distinctFormats = []; - - /** - * @param TypeFactoryInterface $typeFactory - * @param mixed $resourceMetadataFactory - * @param mixed $propertyNameCollectionFactory - * @param mixed $propertyMetadataFactory - */ - public function __construct($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, NameConverterInterface $nameConverter = null, ResourceClassResolverInterface $resourceClassResolver = null) - { - $this->typeFactory = $typeFactory; - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->nameConverter = $nameConverter; - $this->resourceClassResolver = $resourceClassResolver; - } - - /** - * When added to the list, the given format will lead to the creation of a new definition. - * - * @internal - */ - public function addDistinctFormat(string $format): void - { - $this->distinctFormats[$format] = true; - } - - /** - * {@inheritdoc} - */ - public function buildSchema(string $className, string $format = 'json', string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null, ?Schema $schema = null, ?array $serializerContext = null, bool $forceCollection = false): Schema - { - $schema = $schema ? clone $schema : new Schema(); - if (null === $metadata = $this->getMetadata($className, $type, $operationType, $operationName, $serializerContext)) { - return $schema; - } - - [$resourceMetadata, $serializerContext, $validationGroups, $inputOrOutputClass] = $metadata; - - if (null === $resourceMetadata && (null !== $operationType || null !== $operationName)) { - throw new \LogicException('The $operationType and $operationName arguments must be null for non-resource class.'); - } - - $operation = $resourceMetadata instanceof ResourceMetadataCollection ? $resourceMetadata->getOperation($operationName, OperationType::COLLECTION === $operationType) : null; - - $version = $schema->getVersion(); - $definitionName = $this->buildDefinitionName($className, $format, $inputOrOutputClass, $resourceMetadata instanceof ResourceMetadata ? $resourceMetadata : $operation, $serializerContext); - - $method = $operation instanceof HttpOperation ? $operation->getMethod() : 'GET'; - if (!$operation && (null === $operationType || null === $operationName)) { - $method = Schema::TYPE_INPUT === $type ? 'POST' : 'GET'; - } elseif ($resourceMetadata instanceof ResourceMetadata) { - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); - } - - if (Schema::TYPE_OUTPUT !== $type && !\in_array($method, ['POST', 'PATCH', 'PUT'], true)) { - return $schema; - } - - if (!isset($schema['$ref']) && !isset($schema['type'])) { - $ref = Schema::VERSION_OPENAPI === $version ? '#/components/schemas/'.$definitionName : '#/definitions/'.$definitionName; - - if ($forceCollection || (OperationType::COLLECTION === $operationType && 'POST' !== $method)) { - $schema['type'] = 'array'; - $schema['items'] = ['$ref' => $ref]; - } else { - $schema['$ref'] = $ref; - } - } - - $definitions = $schema->getDefinitions(); - if (isset($definitions[$definitionName])) { - // Already computed - return $schema; - } - - /** @var \ArrayObject $definition */ - $definition = new \ArrayObject(['type' => 'object']); - $definitions[$definitionName] = $definition; - - if ($resourceMetadata instanceof ResourceMetadata) { - $definition['description'] = $resourceMetadata->getDescription() ?? ''; - } else { - $definition['description'] = $operation ? ($operation->getDescription() ?? '') : ''; - } - - // additionalProperties are allowed by default, so it does not need to be set explicitly, unless allow_extra_attributes is false - // See https://json-schema.org/understanding-json-schema/reference/object.html#properties - if (false === ($serializerContext[AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES] ?? true)) { - $definition['additionalProperties'] = false; - } - - // see https://github.com/json-schema-org/json-schema-spec/pull/737 - if ( - Schema::VERSION_SWAGGER !== $version - ) { - if (($resourceMetadata instanceof ResourceMetadata && - ($operationType && $operationName ? $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', null, true) : $resourceMetadata->getAttribute('deprecation_reason', null)) - ) || ($operation && $operation->getDeprecationReason()) - ) { - $definition['deprecated'] = true; - } - } - - // externalDocs is an OpenAPI specific extension, but JSON Schema allows additional keys, so we always add it - // See https://json-schema.org/latest/json-schema-core.html#rfc.section.6.4 - if ($resourceMetadata instanceof ResourceMetadata && $resourceMetadata->getIri()) { - $definition['externalDocs'] = ['url' => $resourceMetadata->getIri()]; - } elseif ($operation instanceof HttpOperation && ($operation->getTypes()[0] ?? null)) { - $definition['externalDocs'] = ['url' => $operation->getTypes()[0]]; - } - - // TODO: getFactoryOptions should be refactored because Item & Collection Operations don't exist anymore (API Platform 3.0) - $options = $this->getFactoryOptions($serializerContext, $validationGroups, $operationType, $operationName, $operation instanceof HttpOperation ? $operation : null); - foreach ($this->propertyNameCollectionFactory->create($inputOrOutputClass, $options) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($inputOrOutputClass, $propertyName, $options); - if (!$propertyMetadata->isReadable() && !$propertyMetadata->isWritable()) { - continue; - } - - $normalizedPropertyName = $this->nameConverter ? $this->nameConverter->normalize($propertyName, $inputOrOutputClass, $format, $serializerContext) : $propertyName; - if ($propertyMetadata->isRequired()) { - $definition['required'][] = $normalizedPropertyName; - } - - $this->buildPropertySchema($schema, $definitionName, $normalizedPropertyName, $propertyMetadata, $serializerContext, $format); - } - - return $schema; - } - - private function buildPropertySchema(Schema $schema, string $definitionName, string $normalizedPropertyName, $propertyMetadata, array $serializerContext, string $format): void - { - $version = $schema->getVersion(); - $swagger = Schema::VERSION_SWAGGER === $version; - $propertySchema = $propertyMetadata->getSchema() ?? []; - - if ($propertyMetadata instanceof ApiProperty) { - $additionalPropertySchema = $propertyMetadata->getOpenapiContext() ?? []; - } else { - switch ($version) { - case Schema::VERSION_SWAGGER: - $basePropertySchemaAttribute = 'swagger_context'; - break; - case Schema::VERSION_OPENAPI: - $basePropertySchemaAttribute = 'openapi_context'; - break; - default: - $basePropertySchemaAttribute = 'json_schema_context'; - } - - $additionalPropertySchema = $propertyMetadata->getAttributes()[$basePropertySchemaAttribute] ?? []; - } - - $propertySchema = array_merge( - $propertySchema, - $additionalPropertySchema - ); - - if (false === $propertyMetadata->isWritable() && !$propertyMetadata->isInitializable()) { - $propertySchema['readOnly'] = true; - } - if (!$swagger && false === $propertyMetadata->isReadable()) { - $propertySchema['writeOnly'] = true; - } - if (null !== $description = $propertyMetadata->getDescription()) { - $propertySchema['description'] = $description; - } - - $deprecationReason = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('deprecation_reason') : $propertyMetadata->getDeprecationReason(); - - // see https://github.com/json-schema-org/json-schema-spec/pull/737 - if (!$swagger && null !== $deprecationReason) { - $propertySchema['deprecated'] = true; - } - // externalDocs is an OpenAPI specific extension, but JSON Schema allows additional keys, so we always add it - // See https://json-schema.org/latest/json-schema-core.html#rfc.section.6.4 - $iri = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getIri() : $propertyMetadata->getTypes()[0] ?? null; - if (null !== $iri) { - $propertySchema['externalDocs'] = ['url' => $iri]; - } - - if (!isset($propertySchema['default']) && !empty($default = $propertyMetadata->getDefault())) { - $propertySchema['default'] = $default; - } - - if (!isset($propertySchema['example']) && !empty($example = $propertyMetadata->getExample())) { - $propertySchema['example'] = $example; - } - - if (!isset($propertySchema['example']) && isset($propertySchema['default'])) { - $propertySchema['example'] = $propertySchema['default']; - } - - $valueSchema = []; - // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; - if (null !== $type) { - if ($isCollection = $type->isCollection()) { - $keyType = method_exists(Type::class, 'getCollectionKeyTypes') ? ($type->getCollectionKeyTypes()[0] ?? null) : $type->getCollectionKeyType(); - $valueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType(); - } else { - $keyType = null; - $valueType = $type; - } - - if (null === $valueType) { - $builtinType = 'string'; - $className = null; - } else { - $builtinType = $valueType->getBuiltinType(); - $className = $valueType->getClassName(); - } - - $valueSchema = $this->typeFactory->getType(new Type($builtinType, $type->isNullable(), $className, $isCollection, $keyType, $valueType), $format, $propertyMetadata->isReadableLink(), $serializerContext, $schema); - } - - if (\array_key_exists('type', $propertySchema) && \array_key_exists('$ref', $valueSchema)) { - $propertySchema = new \ArrayObject($propertySchema); - } else { - $propertySchema = new \ArrayObject($propertySchema + $valueSchema); - } - $schema->getDefinitions()[$definitionName]['properties'][$normalizedPropertyName] = $propertySchema; - } - - private function buildDefinitionName(string $className, string $format = 'json', ?string $inputOrOutputClass = null, $resourceMetadata = null, ?array $serializerContext = null): string - { - if ($resourceMetadata) { - $prefix = $resourceMetadata instanceof ResourceMetadata ? $resourceMetadata->getShortName() : $resourceMetadata->getShortName(); - } - - if (!isset($prefix)) { - $prefix = (new \ReflectionClass($className))->getShortName(); - } - - if (null !== $inputOrOutputClass && $className !== $inputOrOutputClass) { - $parts = explode('\\', $inputOrOutputClass); - $shortName = end($parts); - $prefix .= '.'.$shortName; - } - - if (isset($this->distinctFormats[$format])) { - // JSON is the default, and so isn't included in the definition name - $prefix .= '.'.$format; - } - - $definitionName = $serializerContext[OpenApiFactory::OPENAPI_DEFINITION_NAME] ?? $serializerContext[DocumentationNormalizer::SWAGGER_DEFINITION_NAME] ?? null; - if ($definitionName) { - $name = sprintf('%s-%s', $prefix, $definitionName); - } else { - $groups = (array) ($serializerContext[AbstractNormalizer::GROUPS] ?? []); - $name = $groups ? sprintf('%s-%s', $prefix, implode('_', $groups)) : $prefix; - } - - return $this->encodeDefinitionName($name); - } - - private function encodeDefinitionName(string $name): string - { - return preg_replace('/[^a-zA-Z0-9.\-_]/', '.', $name); - } - - private function getMetadata(string $className, string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null, ?array $serializerContext = null): ?array - { - if (!$this->isResourceClass($className)) { - return [ - null, - $serializerContext ?? [], - [], - $className, - ]; - } - - /** @var ResourceMetadata|ResourceMetadataCollection $resourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($className); - $attribute = Schema::TYPE_OUTPUT === $type ? 'output' : 'input'; - $operation = ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) ? null : $resourceMetadata->getOperation($operationName); - - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - if (null === $operationType || null === $operationName) { - $inputOrOutput = $resourceMetadata->getAttribute($attribute, ['class' => $className]); - } else { - $inputOrOutput = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, $attribute, ['class' => $className], true); - } - } elseif ($operation) { - $inputOrOutput = (Schema::TYPE_OUTPUT === $type ? $operation->getOutput() : $operation->getInput()) ?? ['class' => $className]; - } else { - $inputOrOutput = ['class' => $className]; - } - - if (null === ($inputOrOutput['class'] ?? $inputOrOutput->class ?? null)) { - // input or output disabled - return null; - } - - return [ - $resourceMetadata, - $serializerContext ?? $this->getSerializerContext($resourceMetadata, $type, $operationType, $operationName), - $this->getValidationGroups($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface ? $resourceMetadata : $operation, $operationType, $operationName), - $inputOrOutput['class'] ?? $inputOrOutput->class, - ]; - } - - private function getSerializerContext($resourceMetadata, string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null): array - { - if ($resourceMetadata instanceof ResourceMetadata) { - $attribute = Schema::TYPE_OUTPUT === $type ? 'normalization_context' : 'denormalization_context'; - } else { - $operation = $resourceMetadata->getOperation($operationName); - } - - if (null === $operationType || null === $operationName) { - if ($resourceMetadata instanceof ResourceMetadata) { - return $resourceMetadata->getAttribute($attribute, []); - } - - return Schema::TYPE_OUTPUT === $type ? ($operation->getNormalizationContext() ?? []) : ($operation->getDenormalizationContext() ?? []); - } - - if ($resourceMetadata instanceof ResourceMetadata) { - return $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, $attribute, [], true); - } - - return Schema::TYPE_OUTPUT === $type ? ($operation->getNormalizationContext() ?? []) : ($operation->getDenormalizationContext() ?? []); - } - - /** - * @param HttpOperation|ResourceMetadata|null $resourceMetadata - */ - private function getValidationGroups($resourceMetadata, ?string $operationType, ?string $operationName): array - { - if ($resourceMetadata instanceof ResourceMetadata) { - $attribute = 'validation_groups'; - - if (null === $operationType || null === $operationName) { - return \is_array($validationGroups = $resourceMetadata->getAttribute($attribute, [])) ? $validationGroups : []; - } - - return \is_array($validationGroups = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, $attribute, [], true)) ? $validationGroups : []; - } - - $groups = $resourceMetadata ? ($resourceMetadata->getValidationContext()['groups'] ?? []) : []; - - return \is_array($groups) ? $groups : [$groups]; - } - - /** - * Gets the options for the property name collection / property metadata factories. - */ - private function getFactoryOptions(array $serializerContext, array $validationGroups, ?string $operationType, ?string $operationName, ?HttpOperation $operation = null): array - { - $options = [ - /* @see https://github.com/symfony/symfony/blob/v5.1.0/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php */ - 'enable_getter_setter_extraction' => true, - ]; - - if (isset($serializerContext[AbstractNormalizer::GROUPS])) { - /* @see https://github.com/symfony/symfony/blob/v4.2.6/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php */ - $options['serializer_groups'] = (array) $serializerContext[AbstractNormalizer::GROUPS]; - } - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && $operation) { - $options['normalization_groups'] = $operation->getNormalizationContext()['groups'] ?? null; - $options['denormalization_groups'] = $operation->getDenormalizationContext()['groups'] ?? null; - } - - if (null !== $operationType && null !== $operationName) { - switch ($operationType) { - case OperationType::COLLECTION: - $options['collection_operation_name'] = $operationName; - break; - case OperationType::ITEM: - $options['item_operation_name'] = $operationName; - break; - default: - break; - } - } - - if ($validationGroups) { - $options['validation_groups'] = $validationGroups; - } - - return $options; - } -} diff --git a/src/Core/JsonSchema/TypeFactory.php b/src/Core/JsonSchema/TypeFactory.php deleted file mode 100644 index 11a4af3f803..00000000000 --- a/src/Core/JsonSchema/TypeFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\JsonSchema; - -class_exists(\ApiPlatform\JsonSchema\TypeFactory::class); - -if (false) { - final class TypeFactory extends \ApiPlatform\JsonSchema\TypeFactory - { - } -} diff --git a/src/Core/Mercure/EventListener/AddLinkHeaderListener.php b/src/Core/Mercure/EventListener/AddLinkHeaderListener.php deleted file mode 100644 index d629f8e9601..00000000000 --- a/src/Core/Mercure/EventListener/AddLinkHeaderListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Mercure\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\AddLinkHeaderListener::class); - -if (false) { - final class AddLinkHeaderListener extends \ApiPlatform\Symfony\EventListener\AddLinkHeaderListener - { - } -} diff --git a/src/Core/Metadata/Extractor/XmlExtractor.php b/src/Core/Metadata/Extractor/XmlExtractor.php deleted file mode 100644 index e852c9472d4..00000000000 --- a/src/Core/Metadata/Extractor/XmlExtractor.php +++ /dev/null @@ -1,212 +0,0 @@ - - * - * 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\Metadata\Extractor; - -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\Extractor\AbstractResourceExtractor; -use ApiPlatform\Metadata\Extractor\PropertyExtractorInterface; -use ApiPlatform\Metadata\Extractor\XmlPropertyExtractor; -use ApiPlatform\Metadata\Extractor\XmlResourceExtractor; -use Symfony\Component\Config\Util\XmlUtils; - -/** - * Extracts an array of metadata from a list of XML files. - * - * @author Kévin Dunglas - * @author Antoine Bluchet - * @author Baptiste Meyer - * @author Vincent Chalamon - * - * @deprecated since 2.7, to remove in 3.0 (replaced by ApiPlatform\Metadata\Extractor\XmlExtractor) - */ -final class XmlExtractor extends AbstractResourceExtractor implements PropertyExtractorInterface -{ - public const RESOURCE_SCHEMA = __DIR__.'/../schema/metadata.xsd'; - - private $properties; - - /** - * {@inheritdoc} - */ - public function getProperties(): array - { - if (null !== $this->properties) { - return $this->properties; - } - - $this->properties = []; - foreach ($this->paths as $path) { - $this->extractPath($path); - } - - return $this->properties; - } - - /** - * {@inheritdoc} - */ - protected function extractPath(string $path) - { - try { - /** @var \SimpleXMLElement $xml */ - $xml = simplexml_import_dom(XmlUtils::loadFile($path, self::RESOURCE_SCHEMA)); - } catch (\InvalidArgumentException $e) { - // Test if this is a new resource - try { - $xml = XmlUtils::loadFile($path, XmlResourceExtractor::SCHEMA); - - return; - } catch (\InvalidArgumentException $newResourceException) { - try { - $xml = XmlUtils::loadFile($path, XmlPropertyExtractor::SCHEMA); - - return; - } catch (\InvalidArgumentException $newPropertyException) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } - } - - foreach ($xml->resource as $resource) { - $resourceClass = $this->resolve((string) $resource['class']); - - $this->resources[$resourceClass] = [ - 'shortName' => $this->phpizeAttribute($resource, 'shortName', 'string'), - 'description' => $this->phpizeAttribute($resource, 'description', 'string'), - 'iri' => $this->phpizeAttribute($resource, 'iri', 'string'), - 'itemOperations' => $this->extractOperations($resource, 'itemOperation'), - 'collectionOperations' => $this->extractOperations($resource, 'collectionOperation'), - 'subresourceOperations' => $this->extractOperations($resource, 'subresourceOperation'), - 'graphql' => $this->extractOperations($resource, 'operation'), - 'attributes' => $this->extractAttributes($resource, 'attribute') ?: null, - 'properties' => $this->extractProperties($resource) ?: null, - ]; - $this->properties[$resourceClass] = $this->resources[$resourceClass]['properties']; - } - } - - /** - * Returns the array containing configured operations. Returns NULL if there is no operation configuration. - */ - private function extractOperations(\SimpleXMLElement $resource, string $operationType): ?array - { - $graphql = 'operation' === $operationType; - if (!$graphql && $legacyOperations = $this->extractAttributes($resource, $operationType)) { - @trigger_error( - sprintf('Configuring "%1$s" tags without using a parent "%1$ss" tag is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3', $operationType), - \E_USER_DEPRECATED - ); - - return $legacyOperations; - } - - $operationsParent = $graphql ? 'graphql' : "{$operationType}s"; - if (!isset($resource->{$operationsParent})) { - return null; - } - - return $this->extractAttributes($resource->{$operationsParent}, $operationType, true); - } - - /** - * Recursively transforms an attribute structure into an associative array. - */ - private function extractAttributes(\SimpleXMLElement $resource, string $elementName, bool $topLevel = false): array - { - $attributes = []; - foreach ($resource->{$elementName} as $attribute) { - $value = isset($attribute->attribute[0]) ? $this->extractAttributes($attribute, 'attribute') : $this->phpizeContent($attribute); - // allow empty operations definition, like - if ($topLevel && '' === $value) { - $value = []; - } - if (isset($attribute['name'])) { - $attributes[(string) $attribute['name']] = $value; - } else { - $attributes[] = $value; - } - } - - return $attributes; - } - - /** - * Gets metadata of a property. - */ - private function extractProperties(\SimpleXMLElement $resource): array - { - $properties = []; - foreach ($resource->property as $property) { - $properties[(string) $property['name']] = [ - 'description' => $this->phpizeAttribute($property, 'description', 'string'), - 'readable' => $this->phpizeAttribute($property, 'readable', 'bool'), - 'writable' => $this->phpizeAttribute($property, 'writable', 'bool'), - 'readableLink' => $this->phpizeAttribute($property, 'readableLink', 'bool'), - 'writableLink' => $this->phpizeAttribute($property, 'writableLink', 'bool'), - 'required' => $this->phpizeAttribute($property, 'required', 'bool'), - 'identifier' => $this->phpizeAttribute($property, 'identifier', 'bool'), - 'iri' => $this->phpizeAttribute($property, 'iri', 'string'), - 'attributes' => $this->extractAttributes($property, 'attribute'), - 'subresource' => $property->subresource ? [ - 'collection' => $this->phpizeAttribute($property->subresource, 'collection', 'bool'), - 'resourceClass' => $this->resolve($this->phpizeAttribute($property->subresource, 'resourceClass', 'string')), - 'maxDepth' => $this->phpizeAttribute($property->subresource, 'maxDepth', 'integer'), - ] : null, - ]; - } - - return $properties; - } - - /** - * Transforms an XML attribute's value in a PHP value. - * - * @return string|int|bool|null - */ - private function phpizeAttribute(\SimpleXMLElement $array, string $key, string $type) - { - if (!isset($array[$key])) { - return null; - } - - switch ($type) { - case 'string': - return (string) $array[$key]; - case 'integer': - return (int) $array[$key]; - case 'bool': - return (bool) XmlUtils::phpize($array[$key]); - } - - return null; - } - - /** - * Transforms an XML element's content in a PHP value. - */ - private function phpizeContent(\SimpleXMLElement $array) - { - $type = $array['type'] ?? null; - $value = (string) $array; - - switch ($type) { - case 'string': - return $value; - case 'constant': - return \constant($value); - default: - return XmlUtils::phpize($value); - } - } -} diff --git a/src/Core/Metadata/Extractor/YamlExtractor.php b/src/Core/Metadata/Extractor/YamlExtractor.php deleted file mode 100644 index cdd77476094..00000000000 --- a/src/Core/Metadata/Extractor/YamlExtractor.php +++ /dev/null @@ -1,183 +0,0 @@ - - * - * 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\Metadata\Extractor; - -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\Extractor\AbstractResourceExtractor; -use ApiPlatform\Metadata\Extractor\PropertyExtractorInterface; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Yaml; - -/** - * Extracts an array of metadata from a list of YAML files. - * - * @author Antoine Bluchet - * @author Baptiste Meyer - * @author Kévin Dunglas - * @author Vincent Chalamon - * - * @deprecated since 2.7, to remove in 3.0 (replaced by ApiPlatform\Metadata\Extractor\YamlExtractor) - */ -final class YamlExtractor extends AbstractResourceExtractor implements PropertyExtractorInterface -{ - private $properties; - - /** - * {@inheritdoc} - */ - public function getProperties(): array - { - if (null !== $this->properties) { - return $this->properties; - } - - $this->properties = []; - foreach ($this->paths as $path) { - $this->extractPath($path); - } - - return $this->properties; - } - - /** - * {@inheritdoc} - */ - protected function extractPath(string $path) - { - try { - $resourcesYaml = Yaml::parse((string) file_get_contents($path), Yaml::PARSE_CONSTANT); - } catch (ParseException $e) { - $e->setParsedFile($path); - - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - - if (null === $resourcesYaml = $resourcesYaml['resources'] ?? $resourcesYaml) { - return; - } - - if (!\is_array($resourcesYaml)) { - throw new InvalidArgumentException(sprintf('"resources" setting is expected to be null or an array, %s given in "%s".', \gettype($resourcesYaml), $path)); - } - - $this->extractResources($resourcesYaml, $path); - } - - private function extractResources(array $resourcesYaml, string $path): void - { - foreach ($resourcesYaml as $resourceName => $resourceYaml) { - $resourceName = $this->resolve($resourceName); - - if (null === $resourceYaml) { - $resourceYaml = []; - } - - if (!\is_array($resourceYaml)) { - throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', $resourceName, \gettype($resourceYaml), $path)); - } - - $this->resources[$resourceName] = [ - 'shortName' => $this->phpize($resourceYaml, 'shortName', 'string'), - 'description' => $this->phpize($resourceYaml, 'description', 'string'), - 'iri' => $this->phpize($resourceYaml, 'iri', 'string'), - 'itemOperations' => $resourceYaml['itemOperations'] ?? null, - 'collectionOperations' => $resourceYaml['collectionOperations'] ?? null, - 'subresourceOperations' => $resourceYaml['subresourceOperations'] ?? null, - 'graphql' => $resourceYaml['graphql'] ?? null, - 'attributes' => $resourceYaml['attributes'] ?? null, - ]; - - if (!isset($resourceYaml['properties'])) { - $this->properties[$resourceName] = $this->resources[$resourceName]['properties'] = null; - - continue; - } - - if (!\is_array($resourceYaml['properties'])) { - throw new InvalidArgumentException(sprintf('"properties" setting is expected to be null or an array, %s given in "%s".', \gettype($resourceYaml['properties']), $path)); - } - - $this->extractProperties($resourceYaml, $resourceName, $path); - } - } - - private function extractProperties(array $resourceYaml, string $resourceName, string $path): void - { - foreach ($resourceYaml['properties'] as $propertyName => $propertyValues) { - if (null === $propertyValues) { - $this->properties[$resourceName][$propertyName] = $this->resources[$resourceName]['properties'][$propertyName] = null; - - continue; - } - - if (!\is_array($propertyValues)) { - throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', $propertyName, \gettype($propertyValues), $path)); - } - if (isset($propertyValues['subresource']['resourceClass'])) { - $propertyValues['subresource']['resourceClass'] = $this->resolve($propertyValues['subresource']['resourceClass']); - } - - $this->properties[$resourceName][$propertyName] = $this->resources[$resourceName]['properties'][$propertyName] = [ - 'description' => $this->phpize($propertyValues, 'description', 'string'), - 'readable' => $this->phpize($propertyValues, 'readable', 'bool'), - 'writable' => $this->phpize($propertyValues, 'writable', 'bool'), - 'readableLink' => $this->phpize($propertyValues, 'readableLink', 'bool'), - 'writableLink' => $this->phpize($propertyValues, 'writableLink', 'bool'), - 'required' => $this->phpize($propertyValues, 'required', 'bool'), - 'identifier' => $this->phpize($propertyValues, 'identifier', 'bool'), - 'iri' => $this->phpize($propertyValues, 'iri', 'string'), - 'attributes' => $propertyValues['attributes'] ?? [], - 'subresource' => isset($propertyValues['subresource']) ? [ - 'collection' => $this->phpize($propertyValues['subresource'], 'collection', 'bool'), - 'resourceClass' => $this->phpize($propertyValues['subresource'], 'resourceClass', 'string'), - 'maxDepth' => $this->phpize($propertyValues['subresource'], 'maxDepth', 'integer'), - ] : null, - ]; - } - } - - /** - * Transforms a YAML attribute's value in PHP value. - * - * @throws InvalidArgumentException - * - * @return bool|int|string|null - */ - private function phpize(array $array, string $key, string $type) - { - if (!isset($array[$key])) { - return null; - } - - switch ($type) { - case 'bool': - if (\is_bool($array[$key])) { - return $array[$key]; - } - break; - case 'integer': - if (\is_int($array[$key])) { - return $array[$key]; - } - break; - case 'string': - if (\is_string($array[$key])) { - return $array[$key]; - } - break; - } - - throw new InvalidArgumentException(sprintf('The property "%s" must be a "%s", "%s" given.', $key, $type, \gettype($array[$key]))); - } -} diff --git a/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php deleted file mode 100644 index 255b24fb7c2..00000000000 --- a/src/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactory.php +++ /dev/null @@ -1,154 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Util\Reflection; -use Doctrine\Common\Annotations\Reader; - -/** - * Creates a property metadata from {@see ApiProperty} annotations. - * - * @author Kévin Dunglas - */ -final class AnnotationPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $reader; - private $decorated; - - public function __construct(Reader $reader = null, PropertyMetadataFactoryInterface $decorated = null) - { - $this->reader = $reader; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - if (null === ($options['deprecate'] ?? null)) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Decorating the legacy %s is deprecated, use %s instead.', PropertyMetadataFactoryInterface::class, \ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface::class)); - } - - $parentPropertyMetadata = null; - if ($this->decorated) { - try { - $parentPropertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - // Ignore not found exception from decorated factories - } - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property); - } - - if ($reflectionClass->hasProperty($property)) { - $annotation = null; - $reflectionProperty = $reflectionClass->getProperty($property); - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionProperty->getAttributes(ApiProperty::class)) { - $annotation = $attributes[0]->newInstance(); - } elseif (null !== $this->reader) { - $annotation = $this->reader->getPropertyAnnotation($reflectionProperty, ApiProperty::class); - } - - if ($annotation instanceof ApiProperty) { - return $this->createMetadata($annotation, $parentPropertyMetadata); - } - } - - foreach (array_merge(Reflection::ACCESSOR_PREFIXES, Reflection::MUTATOR_PREFIXES) as $prefix) { - $methodName = $prefix.ucfirst($property); - if (!$reflectionClass->hasMethod($methodName)) { - continue; - } - - $reflectionMethod = $reflectionClass->getMethod($methodName); - if (!$reflectionMethod->isPublic()) { - continue; - } - - $annotation = null; - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionMethod->getAttributes(ApiProperty::class)) { - $annotation = $attributes[0]->newInstance(); - } elseif (null !== $this->reader) { - $annotation = $this->reader->getMethodAnnotation($reflectionMethod, ApiProperty::class); - } - - if ($annotation instanceof ApiProperty) { - return $this->createMetadata($annotation, $parentPropertyMetadata); - } - } - - return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws PropertyNotFoundException - */ - private function handleNotFound(?PropertyMetadata $parentPropertyMetadata, string $resourceClass, string $property): PropertyMetadata - { - if (null !== $parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new PropertyNotFoundException(sprintf('Property "%s" of class "%s" not found.', $property, $resourceClass)); - } - - private function createMetadata(ApiProperty $annotation, PropertyMetadata $parentPropertyMetadata = null): PropertyMetadata - { - if (null === $parentPropertyMetadata) { - return new PropertyMetadata( - null, - $annotation->description, - $annotation->readable, - $annotation->writable, - $annotation->readableLink, - $annotation->writableLink, - $annotation->required, - $annotation->identifier, - $annotation->iri, - null, - $annotation->attributes, - null, - null, - $annotation->default, - $annotation->example - ); - } - - $propertyMetadata = $parentPropertyMetadata; - foreach ([['get', 'description'], ['is', 'readable'], ['is', 'writable'], ['is', 'readableLink'], ['is', 'writableLink'], ['is', 'required'], ['get', 'iri'], ['is', 'identifier'], ['get', 'attributes'], ['get', 'default'], ['get', 'example']] as $property) { - if (null !== $value = $annotation->{$property[1]}) { - $propertyMetadata = $this->createWith($propertyMetadata, $property, $value); - } - } - - return $propertyMetadata; - } - - private function createWith(PropertyMetadata $propertyMetadata, array $property, $value): PropertyMetadata - { - $wither = 'with'.ucfirst($property[1]); - - return $propertyMetadata->{$wither}($value); - } -} diff --git a/src/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactory.php deleted file mode 100644 index 1caa639bae8..00000000000 --- a/src/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactory.php +++ /dev/null @@ -1,109 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Util\Reflection; -use Doctrine\Common\Annotations\Reader; - -/** - * Creates a property name collection from {@see ApiProperty} annotations. - * - * @author Kévin Dunglas - */ -final class AnnotationPropertyNameCollectionFactory implements PropertyNameCollectionFactoryInterface -{ - private $reader; - private $decorated; - private $reflection; - - public function __construct(Reader $reader = null, PropertyNameCollectionFactoryInterface $decorated = null) - { - $this->reader = $reader; - $this->decorated = $decorated; - $this->reflection = new Reflection(); - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, array $options = []): PropertyNameCollection - { - $propertyNameCollection = null; - - if ($this->decorated) { - try { - /** @var PropertyNameCollection */ - $propertyNameCollection = $this->decorated->create($resourceClass, $options); - } catch (ResourceClassNotFoundException $resourceClassNotFoundException) { - // Ignore not found exceptions from decorated factory - } - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - if (null !== $propertyNameCollection) { - return $propertyNameCollection; - } - - throw new ResourceClassNotFoundException(sprintf('The resource class "%s" does not exist.', $resourceClass)); - } - - $propertyNames = []; - - // Properties - foreach ($reflectionClass->getProperties() as $reflectionProperty) { - if ( - (\PHP_VERSION_ID >= 80000 && $reflectionProperty->getAttributes(ApiProperty::class)) || - (null !== $this->reader && null !== $this->reader->getPropertyAnnotation($reflectionProperty, ApiProperty::class)) - ) { - $propertyNames[$reflectionProperty->name] = $reflectionProperty->name; - } - } - - // Methods - foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) { - if ($reflectionMethod->isStatic()) { - continue; - } - - $propertyName = $this->reflection->getProperty($reflectionMethod->name); - if (null !== $propertyName && !$reflectionClass->hasProperty($propertyName) && !preg_match('/^[A-Z]{2,}/', $propertyName)) { - $propertyName = lcfirst($propertyName); - } - - if ( - null !== $propertyName && - ( - (\PHP_VERSION_ID >= 80000 && $reflectionMethod->getAttributes(ApiProperty::class)) || - (null !== $this->reader && null !== $this->reader->getMethodAnnotation($reflectionMethod, ApiProperty::class)) - ) - ) { - $propertyNames[$propertyName] = $propertyName; - } - } - - // add property names from decorated factory - if (null !== $propertyNameCollection) { - foreach ($propertyNameCollection as $propertyName) { - $propertyNames[$propertyName] = $propertyName; - } - } - - return new PropertyNameCollection(array_values($propertyNames)); - } -} diff --git a/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php b/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php deleted file mode 100644 index a5a0bad390e..00000000000 --- a/src/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php +++ /dev/null @@ -1,118 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiSubresource; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Exception\InvalidResourceException; -use ApiPlatform\Util\Reflection; -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\PropertyInfo\Type; - -/** - * Adds subresources to the properties metadata from {@see ApiResource} annotations. - * - * @author Antoine Bluchet - */ -final class AnnotationSubresourceMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $reader; - private $decorated; - - public function __construct(Reader $reader, PropertyMetadataFactoryInterface $decorated) - { - $this->reader = $reader; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $propertyMetadata; - } - - if ($reflectionClass->hasProperty($property)) { - $reflectionProperty = $reflectionClass->getProperty($property); - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionProperty->getAttributes(ApiSubresource::class)) { - return $this->updateMetadata($attributes[0]->newInstance(), $propertyMetadata, $resourceClass, $property); - } - - $annotation = $this->reader->getPropertyAnnotation($reflectionProperty, ApiSubresource::class); - if ($annotation instanceof ApiSubresource) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Declare a new resource instead of using ApiSubresource on the property "%s".', $property)); - - return $this->updateMetadata($annotation, $propertyMetadata, $resourceClass, $property); - } - } - - foreach (array_merge(Reflection::ACCESSOR_PREFIXES, Reflection::MUTATOR_PREFIXES) as $prefix) { - $methodName = $prefix.ucfirst($property); - if (!$reflectionClass->hasMethod($methodName)) { - continue; - } - - $reflectionMethod = $reflectionClass->getMethod($methodName); - if (!$reflectionMethod->isPublic()) { - continue; - } - - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionMethod->getAttributes(ApiSubresource::class)) { - return $this->updateMetadata($attributes[0]->newInstance(), $propertyMetadata, $resourceClass, $property); - } - - $annotation = $this->reader->getMethodAnnotation($reflectionMethod, ApiSubresource::class); - if ($annotation instanceof ApiSubresource) { - return $this->updateMetadata($annotation, $propertyMetadata, $resourceClass, $property); - } - } - - return $propertyMetadata; - } - - private function updateMetadata(ApiSubresource $annotation, PropertyMetadata $propertyMetadata, string $originResourceClass, string $propertyName): PropertyMetadata - { - // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata->getType(); - if (null === $type) { - throw new InvalidResourceException(sprintf('Property "%s" on resource "%s" is declared as a subresource, but its type could not be determined.', $propertyName, $originResourceClass)); - } - $isCollection = $type->isCollection(); - - if ( - $isCollection && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $resourceClass = $collectionValueType->getClassName(); - } else { - $resourceClass = $type->getClassName(); - } - - $maxDepth = $annotation->maxDepth; - // @ApiSubresource is on the class identifier (/collection/{id}/subcollection/{subcollectionId}) - if (null === $resourceClass) { - $resourceClass = $originResourceClass; - $isCollection = false; - } - - return $propertyMetadata->withSubresource(new SubresourceMetadata($resourceClass, $isCollection, $maxDepth)); - } -} diff --git a/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php deleted file mode 100644 index ae3ff9c4f77..00000000000 --- a/src/Core/Metadata/Property/Factory/CachedPropertyMetadataFactory.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Util\CachedTrait; -use Psr\Cache\CacheItemPoolInterface; - -/** - * Caches property metadata. - * - * @author Teoh Han Hui - */ -final class CachedPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - use CachedTrait; - - public const CACHE_KEY_PREFIX = 'property_metadata_'; - - private $decorated; - - public function __construct(CacheItemPoolInterface $cacheItemPool, PropertyMetadataFactoryInterface $decorated) - { - $this->cacheItemPool = $cacheItemPool; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $cacheKey = self::CACHE_KEY_PREFIX.md5(serialize([$resourceClass, $property, $options])); - - return $this->getCached($cacheKey, function () use ($resourceClass, $property, $options) { - return $this->decorated->create($resourceClass, $property, $options); - }); - } -} diff --git a/src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php deleted file mode 100644 index 89b20801939..00000000000 --- a/src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -class_exists(\ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class); - -if (false) { - final class CachedPropertyNameCollectionFactory extends \ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory - { - } -} diff --git a/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php deleted file mode 100644 index 9c951077753..00000000000 --- a/src/Core/Metadata/Property/Factory/DefaultPropertyMetadataFactory.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; - -/** - * Populates defaults values of the ressource properties using the default PHP values of properties. - */ -final class DefaultPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $decorated; - - public function __construct(PropertyMetadataFactoryInterface $decorated = null) - { - $this->decorated = $decorated; - } - - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - if (null === $this->decorated) { - $propertyMetadata = new PropertyMetadata(); - } else { - try { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - $propertyMetadata = new PropertyMetadata(); - } - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $propertyMetadata; - } - - $defaultProperties = $reflectionClass->getDefaultProperties(); - - if (!\array_key_exists($property, $defaultProperties) || null === ($defaultProperty = $defaultProperties[$property])) { - return $propertyMetadata; - } - - return $propertyMetadata->withDefault($defaultProperty); - } -} diff --git a/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php deleted file mode 100644 index 74d81229a62..00000000000 --- a/src/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php +++ /dev/null @@ -1,164 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Extractor\ExtractorInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Metadata\Extractor\ResourceExtractorInterface; -use Symfony\Component\PropertyInfo\Type; - -/** - * Creates properties's metadata using an extractor. - * - * @author Kévin Dunglas - */ -final class ExtractorPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $extractor; - private $decorated; - - /** - * @param ResourceExtractorInterface|ExtractorInterface $extractor - */ - public function __construct($extractor, PropertyMetadataFactoryInterface $decorated = null) - { - $this->extractor = $extractor; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $parentPropertyMetadata = null; - if ($this->decorated) { - try { - $parentPropertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - // Ignore not found exception from decorated factories - } - } - - $isInterface = interface_exists($resourceClass); - - if ( - !property_exists($resourceClass, $property) && !$isInterface || - null === ($propertyMetadata = $this->extractor->getResources()[$resourceClass]['properties'][$property] ?? null) - ) { - return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property); - } - - if ($parentPropertyMetadata) { - return $this->update($parentPropertyMetadata, $propertyMetadata); - } - - return ($metadata = new PropertyMetadata( - null, - $propertyMetadata['description'], - $propertyMetadata['readable'], - $propertyMetadata['writable'], - $propertyMetadata['readableLink'], - $propertyMetadata['writableLink'], - $propertyMetadata['required'], - $propertyMetadata['identifier'], - $propertyMetadata['iri'], - null, - $propertyMetadata['attributes'] - ))->withSubresource($this->createSubresourceMetadata($propertyMetadata['subresource'], $metadata)); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws PropertyNotFoundException - */ - private function handleNotFound(?PropertyMetadata $parentPropertyMetadata, string $resourceClass, string $property): PropertyMetadata - { - if ($parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new PropertyNotFoundException(sprintf('Property "%s" of the resource class "%s" not found.', $property, $resourceClass)); - } - - /** - * Creates a new instance of metadata if the property is not already set. - */ - private function update(PropertyMetadata $propertyMetadata, array $metadata): PropertyMetadata - { - $metadataAccessors = [ - 'description' => 'get', - 'readable' => 'is', - 'writable' => 'is', - 'writableLink' => 'is', - 'readableLink' => 'is', - 'required' => 'is', - 'identifier' => 'is', - 'iri' => 'get', - 'attributes' => 'get', - ]; - - foreach ($metadataAccessors as $metadataKey => $accessorPrefix) { - if (null === $metadata[$metadataKey]) { - continue; - } - - $propertyMetadata = $propertyMetadata->{'with'.ucfirst($metadataKey)}($metadata[$metadataKey]); - } - - if ($propertyMetadata->hasSubresource()) { - return $propertyMetadata; - } - - return $propertyMetadata->withSubresource($this->createSubresourceMetadata($metadata['subresource'], $propertyMetadata)); - } - - /** - * Creates a SubresourceMetadata. - * - * @param bool|array|null $subresource the subresource metadata coming from XML or YAML - * @param PropertyMetadata $propertyMetadata the current property metadata - */ - private function createSubresourceMetadata($subresource, PropertyMetadata $propertyMetadata): ?SubresourceMetadata - { - if (!$subresource) { - return null; - } - - $type = $propertyMetadata->getType(); - $maxDepth = \is_array($subresource) ? $subresource['maxDepth'] ?? null : null; - - if (null !== $type) { - $isCollection = $type->isCollection(); - if ( - $isCollection && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $resourceClass = $collectionValueType->getClassName(); - } else { - $resourceClass = $type->getClassName(); - } - } elseif (\is_array($subresource) && isset($subresource['resourceClass'])) { - $resourceClass = $subresource['resourceClass']; - $isCollection = $subresource['collection'] ?? true; - } else { - return null; - } - - return new SubresourceMetadata($resourceClass, $isCollection, $maxDepth); - } -} diff --git a/src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php deleted file mode 100644 index 000f49f61f7..00000000000 --- a/src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -class_exists(\ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class); - -if (false) { - final class ExtractorPropertyNameCollectionFactory extends \ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory - { - } -} diff --git a/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php deleted file mode 100644 index 577abbc45d6..00000000000 --- a/src/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactory.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; - -/** - * @deprecated since 2.6, to be removed in 3.0 - */ -final class InheritedPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - private $resourceNameCollectionFactory; - private $decorated; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, PropertyMetadataFactoryInterface $decorated = null) - { - @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - - $propertyMetadata = $this->decorated ? $this->decorated->create($resourceClass, $property, $options) : new PropertyMetadata(); - - foreach ($this->resourceNameCollectionFactory->create() as $knownResourceClass) { - if ($resourceClass === $knownResourceClass) { - continue; - } - - if (is_subclass_of($knownResourceClass, $resourceClass)) { - $propertyMetadata = $this->create($knownResourceClass, $property, $options); - - return $propertyMetadata->withChildInherited($knownResourceClass); - } - } - - return $propertyMetadata; - } -} diff --git a/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php b/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php deleted file mode 100644 index 6c38c542420..00000000000 --- a/src/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactory.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; - -/** - * @deprecated since 2.6, to be removed in 3.0 - */ -final class InheritedPropertyNameCollectionFactory implements PropertyNameCollectionFactoryInterface -{ - private $resourceNameCollectionFactory; - private $decorated; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, PropertyNameCollectionFactoryInterface $decorated = null) - { - @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, array $options = []): PropertyNameCollection - { - @trigger_error(sprintf('"%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__), \E_USER_DEPRECATED); - - $propertyNames = []; - - // Inherited from parent - if ($this->decorated) { - foreach ($this->decorated->create($resourceClass, $options) as $propertyName) { - $propertyNames[$propertyName] = (string) $propertyName; - } - } - - foreach ($this->resourceNameCollectionFactory->create() as $knownResourceClass) { - if ($resourceClass === $knownResourceClass) { - continue; - } - - if (is_subclass_of($resourceClass, $knownResourceClass)) { - foreach ($this->create($knownResourceClass) as $propertyName) { - $propertyNames[$propertyName] = $propertyName; - } - } - } - - return new PropertyNameCollection(array_values($propertyNames)); - } -} diff --git a/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php b/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php deleted file mode 100644 index 5cb5cc1f76f..00000000000 --- a/src/Core/Metadata/Property/Factory/PropertyMetadataFactoryInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; - -/** - * Creates a property metadata value object. - * - * @author Kévin Dunglas - */ -interface PropertyMetadataFactoryInterface -{ - /** - * Creates a property metadata. - * - * @throws PropertyNotFoundException - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata; -} diff --git a/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php b/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php deleted file mode 100644 index 9c93b2051a8..00000000000 --- a/src/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php +++ /dev/null @@ -1,233 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Util\ResourceClassInfoTrait; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface as SerializerClassMetadataFactoryInterface; - -/** - * Populates read/write and link status using serialization groups. - * - * @author Kévin Dunglas - * @author Teoh Han Hui - */ -final class SerializerPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - use ResourceClassInfoTrait; - - private $serializerClassMetadataFactory; - private $decorated; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, SerializerClassMetadataFactoryInterface $serializerClassMetadataFactory, PropertyMetadataFactoryInterface $decorated, ResourceClassResolverInterface $resourceClassResolver = null) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->serializerClassMetadataFactory = $serializerClassMetadataFactory; - $this->decorated = $decorated; - $this->resourceClassResolver = $resourceClassResolver; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata - { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - - // BC to be removed in 3.0 - if (null !== ($childResourceClass = $propertyMetadata->getChildInherited())) { - $resourceClass = $childResourceClass; - } - - try { - [$normalizationGroups, $denormalizationGroups] = $this->getEffectiveSerializerGroups($options, $resourceClass); - } catch (ResourceClassNotFoundException $e) { - // TODO: for input/output classes, the serializer groups must be read from the actual resource class - return $propertyMetadata; - } - - $propertyMetadata = $this->transformReadWrite($propertyMetadata, $resourceClass, $property, $normalizationGroups, $denormalizationGroups); - - return $this->transformLinkStatus($propertyMetadata, $normalizationGroups, $denormalizationGroups); - } - - /** - * Sets readable/writable based on matching normalization/denormalization groups and property's ignorance. - * - * A false value is never reset as it could be unreadable/unwritable for other reasons. - * If normalization/denormalization groups are not specified and the property is not ignored, the property is implicitly readable/writable. - * - * @param string[]|null $normalizationGroups - * @param string[]|null $denormalizationGroups - */ - private function transformReadWrite(PropertyMetadata $propertyMetadata, string $resourceClass, string $propertyName, array $normalizationGroups = null, array $denormalizationGroups = null): PropertyMetadata - { - $serializerAttributeMetadata = $this->getSerializerAttributeMetadata($resourceClass, $propertyName); - $groups = $serializerAttributeMetadata ? $serializerAttributeMetadata->getGroups() : []; - $ignored = $serializerAttributeMetadata && method_exists($serializerAttributeMetadata, 'isIgnored') ? $serializerAttributeMetadata->isIgnored() : false; - - if (false !== $propertyMetadata->isReadable()) { - $propertyMetadata = $propertyMetadata->withReadable(!$ignored && (null === $normalizationGroups || array_intersect($normalizationGroups, $groups))); - } - - if (false !== $propertyMetadata->isWritable()) { - $propertyMetadata = $propertyMetadata->withWritable(!$ignored && (null === $denormalizationGroups || array_intersect($denormalizationGroups, $groups))); - } - - return $propertyMetadata; - } - - /** - * Sets readableLink/writableLink based on matching normalization/denormalization groups. - * - * If normalization/denormalization groups are not specified, - * set link status to false since embedding of resource must be explicitly enabled - * - * @param string[]|null $normalizationGroups - * @param string[]|null $denormalizationGroups - */ - private function transformLinkStatus(PropertyMetadata $propertyMetadata, array $normalizationGroups = null, array $denormalizationGroups = null): PropertyMetadata - { - // No need to check link status if property is not readable and not writable - if (false === $propertyMetadata->isReadable() && false === $propertyMetadata->isWritable()) { - return $propertyMetadata; - } - - $type = $propertyMetadata->getType(); - if (null === $type) { - return $propertyMetadata; - } - - if ( - $type->isCollection() && - $collectionValueType = method_exists(Type::class, 'getCollectionValueTypes') ? ($type->getCollectionValueTypes()[0] ?? null) : $type->getCollectionValueType() - ) { - $relatedClass = $collectionValueType->getClassName(); - } else { - $relatedClass = $type->getClassName(); - } - - // if property is not a resource relation, don't set link status (as it would have no meaning) - if (null === $relatedClass || !$this->isResourceClass($relatedClass)) { - return $propertyMetadata; - } - - // find the resource class - // this prevents serializer groups on non-resource child class from incorrectly influencing the decision - if (null !== $this->resourceClassResolver) { - $relatedClass = $this->resourceClassResolver->getResourceClass(null, $relatedClass); - } - - $relatedGroups = $this->getClassSerializerGroups($relatedClass); - - if (null === $propertyMetadata->isReadableLink()) { - $propertyMetadata = $propertyMetadata->withReadableLink(null !== $normalizationGroups && !empty(array_intersect($normalizationGroups, $relatedGroups))); - } - - if (null === $propertyMetadata->isWritableLink()) { - $propertyMetadata = $propertyMetadata->withWritableLink(null !== $denormalizationGroups && !empty(array_intersect($denormalizationGroups, $relatedGroups))); - } - - return $propertyMetadata; - } - - /** - * Gets the effective serializer groups used in normalization/denormalization. - * - * Groups are extracted in the following order: - * - * - From the "serializer_groups" key of the $options array. - * - From metadata of the given operation ("collection_operation_name" and "item_operation_name" keys). - * - From metadata of the current resource. - * - * @throws ResourceClassNotFoundException - * - * @return (string[]|null)[] - */ - private function getEffectiveSerializerGroups(array $options, string $resourceClass): array - { - if (isset($options['serializer_groups'])) { - $groups = (array) $options['serializer_groups']; - - return [$groups, $groups]; - } - - if (\array_key_exists('normalization_groups', $options) && \array_key_exists('denormalization_groups', $options)) { - return [$options['normalization_groups'] ?? null, $options['denormalization_groups'] ?? null]; - } - - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (isset($options['collection_operation_name'])) { - $normalizationContext = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], 'normalization_context', null, true); - $denormalizationContext = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], 'denormalization_context', null, true); - } elseif (isset($options['item_operation_name'])) { - $normalizationContext = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], 'normalization_context', null, true); - $denormalizationContext = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], 'denormalization_context', null, true); - } elseif (isset($options['graphql_operation_name'])) { - $normalizationContext = $resourceMetadata->getGraphqlAttribute($options['graphql_operation_name'], 'normalization_context', null, true); - $denormalizationContext = $resourceMetadata->getGraphqlAttribute($options['graphql_operation_name'], 'denormalization_context', null, true); - } else { - $normalizationContext = $resourceMetadata->getAttribute('normalization_context'); - $denormalizationContext = $resourceMetadata->getAttribute('denormalization_context'); - } - - return [ - isset($normalizationContext['groups']) ? (array) $normalizationContext['groups'] : null, - isset($denormalizationContext['groups']) ? (array) $denormalizationContext['groups'] : null, - ]; - } - - private function getSerializerAttributeMetadata(string $class, string $attribute): ?AttributeMetadataInterface - { - $serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($class); - - foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { - if ($attribute === $serializerAttributeMetadata->getName()) { - return $serializerAttributeMetadata; - } - } - - return null; - } - - /** - * Gets all serializer groups used in a class. - * - * @return string[] - */ - private function getClassSerializerGroups(string $class): array - { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($class); - if ($outputClass = $resourceMetadata->getAttribute('output')['class'] ?? null) { - $class = $outputClass; - } - } catch (ResourceClassNotFoundException $e) { - } - - $serializerClassMetadata = $this->serializerClassMetadataFactory->getMetadataFor($class); - - $groups = []; - foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { - $groups = array_merge($groups, $serializerAttributeMetadata->getGroups()); - } - - return array_unique($groups); - } -} diff --git a/src/Core/Metadata/Property/PropertyMetadata.php b/src/Core/Metadata/Property/PropertyMetadata.php deleted file mode 100644 index b547831720f..00000000000 --- a/src/Core/Metadata/Property/PropertyMetadata.php +++ /dev/null @@ -1,435 +0,0 @@ - - * - * 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\Metadata\Property; - -use Symfony\Component\PropertyInfo\Type; - -/** - * Property metadata. - * - * @author Kévin Dunglas - */ -final class PropertyMetadata -{ - /** - * @deprecated since 2.7, to be removed in 3.0, renamed as builtinTypes - */ - private $type; - private $description; - private $readable; - private $writable; - private $readableLink; - private $writableLink; - private $required; - /** - * @deprecated since 2.7, to be removed in 3.0, renamed as types - */ - private $iri; - private $identifier; - /** - * @deprecated since 2.6, to be removed in 3.0 - */ - private $childInherited; - private $attributes; - private $subresource; - private $initializable; - /** - * @var null - */ - private $default; - /** - * @var null - */ - private $example; - private $schema; - - public function __construct(Type $type = null, string $description = null, bool $readable = null, bool $writable = null, bool $readableLink = null, bool $writableLink = null, bool $required = null, bool $identifier = null, string $iri = null, $childInherited = null, array $attributes = null, SubresourceMetadata $subresource = null, bool $initializable = null, $default = null, $example = null, array $schema = null) - { - $this->type = $type; - $this->description = $description; - $this->readable = $readable; - $this->writable = $writable; - $this->readableLink = $readableLink; - $this->writableLink = $writableLink; - $this->required = $required; - $this->identifier = $identifier; - $this->iri = $iri; - if (null !== $childInherited) { - @trigger_error(sprintf('Providing a non-null value for the 10th argument ($childInherited) of the "%s" constructor is deprecated since 2.6 and will not be supported in 3.0.', __CLASS__), \E_USER_DEPRECATED); - } - $this->childInherited = $childInherited; - $this->attributes = $attributes; - $this->subresource = $subresource; - $this->initializable = $initializable; - $this->default = $default; - $this->example = $example; - $this->schema = $schema; - } - - /** - * Gets type. - * - * @deprecated since 2.7, to be removed in 3.0, renamed as getBuiltinTypes - */ - public function getType(): ?Type - { - return $this->type; - } - - /** - * Returns a new instance with the given type. - * - * @deprecated since 2.7, to be removed in 3.0, renamed as withBuiltinTypes - */ - public function withType(Type $type): self - { - $metadata = clone $this; - $metadata->type = $type; - - return $metadata; - } - - /** - * Gets description. - */ - public function getDescription(): ?string - { - return $this->description; - } - - /** - * Returns a new instance with the given description. - */ - public function withDescription(string $description): self - { - $metadata = clone $this; - $metadata->description = $description; - - return $metadata; - } - - /** - * Is readable? - */ - public function isReadable(): ?bool - { - return $this->readable; - } - - /** - * Returns a new instance of Metadata with the given readable flag. - */ - public function withReadable(bool $readable): self - { - $metadata = clone $this; - $metadata->readable = $readable; - - return $metadata; - } - - /** - * Is writable? - */ - public function isWritable(): ?bool - { - return $this->writable; - } - - /** - * Returns a new instance with the given writable flag. - */ - public function withWritable(bool $writable): self - { - $metadata = clone $this; - $metadata->writable = $writable; - - return $metadata; - } - - /** - * Is required? - */ - public function isRequired(): ?bool - { - if (true === $this->required && false === $this->writable) { - return false; - } - - return $this->required; - } - - /** - * Returns a new instance with the given required flag. - */ - public function withRequired(bool $required): self - { - $metadata = clone $this; - $metadata->required = $required; - - return $metadata; - } - - /** - * Should an IRI or an object be provided in write context? - */ - public function isWritableLink(): ?bool - { - return $this->writableLink; - } - - /** - * Returns a new instance with the given writable link flag. - */ - public function withWritableLink(bool $writableLink): self - { - $metadata = clone $this; - $metadata->writableLink = $writableLink; - - return $metadata; - } - - /** - * Is an IRI or an object generated in read context? - */ - public function isReadableLink(): ?bool - { - return $this->readableLink; - } - - /** - * Returns a new instance with the given readable link flag. - */ - public function withReadableLink(bool $readableLink): self - { - $metadata = clone $this; - $metadata->readableLink = $readableLink; - - return $metadata; - } - - /** - * Gets IRI of this property. - */ - public function getIri(): ?string - { - return $this->iri; - } - - /** - * Returns a new instance with the given IRI. - */ - public function withIri(string $iri = null): self - { - $metadata = clone $this; - $metadata->iri = $iri; - - return $metadata; - } - - /** - * Is this attribute an identifier? - */ - public function isIdentifier(): ?bool - { - return $this->identifier; - } - - /** - * Returns a new instance with the given identifier flag. - */ - public function withIdentifier(bool $identifier): self - { - $metadata = clone $this; - $metadata->identifier = $identifier; - - return $metadata; - } - - /** - * Gets attributes. - */ - public function getAttributes(): ?array - { - return $this->attributes; - } - - /** - * Gets an attribute. - * - * @param mixed|null $defaultValue - */ - public function getAttribute(string $key, $defaultValue = null) - { - return $this->attributes[$key] ?? $defaultValue; - } - - /** - * Returns a new instance with the given attribute. - */ - public function withAttributes(array $attributes): self - { - $metadata = clone $this; - $metadata->attributes = $attributes; - - return $metadata; - } - - /** - * @deprecated since 2.6, to be removed in 3.0 - */ - public function getChildInherited(): ?string - { - return $this->childInherited; - } - - /** - * @deprecated since 2.6, to be removed in 3.0 - */ - public function hasChildInherited(): bool - { - return null !== $this->childInherited; - } - - /** - * @deprecated since 2.4, to be removed in 3.0 - */ - public function isChildInherited(): ?string - { - @trigger_error(sprintf('"%s::%s" is deprecated since 2.4 and will be removed in 3.0.', __CLASS__, __METHOD__), \E_USER_DEPRECATED); - - return $this->getChildInherited(); - } - - /** - * @deprecated since 2.6, to be removed in 3.0 - */ - public function withChildInherited(string $childInherited): self - { - @trigger_error(sprintf('"%s::%s" is deprecated since 2.6 and will be removed in 3.0.', __CLASS__, __METHOD__), \E_USER_DEPRECATED); - - $metadata = clone $this; - $metadata->childInherited = $childInherited; - - return $metadata; - } - - /** - * Represents whether the property has a subresource. - */ - public function hasSubresource(): bool - { - return null !== $this->subresource; - } - - /** - * Gets the subresource metadata. - */ - public function getSubresource(): ?SubresourceMetadata - { - return $this->subresource; - } - - /** - * Returns a new instance with the given subresource. - * - * @param SubresourceMetadata $subresource - */ - public function withSubresource(SubresourceMetadata $subresource = null): self - { - $metadata = clone $this; - $metadata->subresource = $subresource; - - return $metadata; - } - - /** - * Is initializable? - */ - public function isInitializable(): ?bool - { - return $this->initializable; - } - - /** - * Returns a new instance with the given initializable flag. - */ - public function withInitializable(bool $initializable): self - { - $metadata = clone $this; - $metadata->initializable = $initializable; - - return $metadata; - } - - /** - * Returns the default value of the property or NULL if the property doesn't have a default value. - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns a new instance with the given default value for the property. - * - * @param mixed $default - */ - public function withDefault($default): self - { - $metadata = clone $this; - $metadata->default = $default; - - return $metadata; - } - - /** - * Returns an example of the value of the property. - */ - public function getExample() - { - return $this->example; - } - - /** - * Returns a new instance with the given example. - * - * @param mixed $example - */ - public function withExample($example): self - { - $metadata = clone $this; - $metadata->example = $example; - - return $metadata; - } - - /** - * @return array - */ - public function getSchema(): ?array - { - return $this->schema; - } - - /** - * Returns a new instance with the given schema. - */ - public function withSchema(array $schema = null): self - { - $metadata = clone $this; - $metadata->schema = $schema; - - return $metadata; - } -} diff --git a/src/Core/Metadata/Property/PropertyNameCollection.php b/src/Core/Metadata/Property/PropertyNameCollection.php deleted file mode 100644 index 4da85d2d1b5..00000000000 --- a/src/Core/Metadata/Property/PropertyNameCollection.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Metadata\Property; - -class_exists(\ApiPlatform\Metadata\Property\PropertyNameCollection::class); - -if (false) { - final class PropertyNameCollection extends \ApiPlatform\Metadata\Property\PropertyNameCollection - { - } -} diff --git a/src/Core/Metadata/Property/SubresourceMetadata.php b/src/Core/Metadata/Property/SubresourceMetadata.php deleted file mode 100644 index f5d1c9e35aa..00000000000 --- a/src/Core/Metadata/Property/SubresourceMetadata.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * 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\Metadata\Property; - -/** - * Subresource metadata. - * - * @author Antoine Bluchet - */ -final class SubresourceMetadata -{ - private $resourceClass; - private $collection; - private $maxDepth; - - public function __construct(string $resourceClass, bool $collection = false, int $maxDepth = null) - { - $this->resourceClass = $resourceClass; - $this->collection = $collection; - $this->maxDepth = $maxDepth; - } - - public function getResourceClass(): string - { - return $this->resourceClass; - } - - public function withResourceClass($resourceClass): self - { - $metadata = clone $this; - $metadata->resourceClass = $resourceClass; - - return $metadata; - } - - public function isCollection(): bool - { - return $this->collection; - } - - public function withCollection(bool $collection): self - { - $metadata = clone $this; - $metadata->collection = $collection; - - return $metadata; - } - - public function getMaxDepth(): ?int - { - return $this->maxDepth; - } -} diff --git a/src/Core/Metadata/Resource/ApiResourceToLegacyResourceMetadataTrait.php b/src/Core/Metadata/Resource/ApiResourceToLegacyResourceMetadataTrait.php deleted file mode 100644 index 482a4b2995e..00000000000 --- a/src/Core/Metadata/Resource/ApiResourceToLegacyResourceMetadataTrait.php +++ /dev/null @@ -1,126 +0,0 @@ - - * - * 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\Metadata\Resource; - -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\CollectionOperationInterface; -use ApiPlatform\Metadata\HttpOperation; -use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; - -/** - * @internal - * - * @deprecated - */ -trait ApiResourceToLegacyResourceMetadataTrait -{ - private $camelCaseToSnakeCaseNameConverter; - - private function transformResourceToResourceMetadata(ApiResource $resource): ResourceMetadata - { - $collectionOperations = []; - $itemOperations = []; - foreach ($resource->getOperations() as $name => $operation) { - $arrayOperation = $this->toArray($operation); - - if (!isset($arrayOperation['openapi_context'])) { - $arrayOperation['openapi_context'] = []; - } - - $arrayOperation['openapi_context']['operationId'] = $name; - $arrayOperation['composite_identifier'] = $this->hasCompositeIdentifier($operation); - - if (HttpOperation::METHOD_POST === $operation->getMethod() && !$operation->getUriVariables()) { - $collectionOperations[$name] = $arrayOperation; - continue; - } - - if ($operation instanceof CollectionOperationInterface) { - $collectionOperations[$name] = $arrayOperation; - continue; - } - - $itemOperations[$name] = $arrayOperation; - } - - $attributes = $this->toArray($resource); - - $graphqlOperations = $resource->getGraphQlOperations() ? [] : null; - foreach ($resource->getGraphQlOperations() ?? [] as $operationName => $operation) { - $graphqlOperations[$operationName] = $this->toArray($operation); - } - - return new ResourceMetadata($resource->getShortName(), $resource->getDescription(), $resource->getTypes()[0] ?? null, $itemOperations, $collectionOperations, $attributes, null, $graphqlOperations); - } - - private function toArray($object): array - { - if (!$this->camelCaseToSnakeCaseNameConverter) { - $this->camelCaseToSnakeCaseNameConverter = new CamelCaseToSnakeCaseNameConverter(); - } - - $arr = []; - foreach (get_class_methods($object) as $methodName) { - if ('getOperations' === $methodName || 0 !== strpos($methodName, 'get')) { - continue; - } - - if (null === $value = $object->{$methodName}()) { - continue; - } - - $arr[$this->camelCaseToSnakeCaseNameConverter->normalize(lcfirst(substr($methodName, 3)))] = $value; - } - - return $this->transformUriVariablesToIdentifiers($arr); - } - - private function transformUriVariablesToIdentifiers(array $arrayOperation): array - { - if (!isset($arrayOperation['uri_variables'])) { - return $arrayOperation; - } - - if (!\is_array($arrayOperation['uri_variables'])) { - $arrayOperation['identifiers'] = $arrayOperation['uri_variables']; - - return $arrayOperation; - } - - $arrayOperation['identifiers'] = []; - foreach ($arrayOperation['uri_variables'] as $parameterName => $identifiedBy) { - if (1 === \count($identifiedBy->getIdentifiers() ?? ['id'])) { - $arrayOperation['identifiers'][$parameterName] = [$identifiedBy->getFromClass(), $identifiedBy->getIdentifiers()[0] ?? ['id']]; - continue; - } - - foreach ($identifiedBy->getIdentifiers() as $identifier) { - $arrayOperation['identifiers'][$identifier] = [$identifiedBy->getFromClass(), $identifier]; - } - } - - return $arrayOperation; - } - - private function hasCompositeIdentifier(HttpOperation $operation): bool - { - foreach ($operation->getUriVariables() ?? [] as $parameterName => $uriVariable) { - if ($uriVariable->getCompositeIdentifier()) { - return true; - } - } - - return false; - } -} diff --git a/src/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php b/src/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php deleted file mode 100644 index bdc02f52afc..00000000000 --- a/src/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php +++ /dev/null @@ -1,94 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Util\AnnotationFilterExtractorTrait; -use Doctrine\Common\Annotations\Reader; - -/** - * Adds filters to the resource metadata {@see ApiFilter} annotation. - * - * @author Antoine Bluchet - */ -final class AnnotationResourceFilterMetadataFactory implements ResourceMetadataFactoryInterface -{ - use AnnotationFilterExtractorTrait; - - private $reader; - private $decorated; - - public function __construct(?Reader $reader = null, ResourceMetadataFactoryInterface $decorated = null) - { - $this->reader = $reader; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $parentResourceMetadata = null; - if ($this->decorated) { - $parentResourceMetadata = $this->decorated->create($resourceClass); - } - - if (null === $parentResourceMetadata) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - $filters = array_keys($this->readFilterAnnotations($reflectionClass, $this->reader)); - - if (!$filters) { - return $parentResourceMetadata; - } - - $parentFilters = $parentResourceMetadata->getAttribute('filters', []); - - if ($parentFilters) { - $filters = array_merge($parentFilters, $filters); - } - - $attributes = $parentResourceMetadata->getAttributes(); - - if (!$attributes) { - $attributes = []; - } - - return $parentResourceMetadata->withAttributes(array_merge($attributes, ['filters' => $filters])); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws ResourceClassNotFoundException - */ - private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, string $resourceClass): ResourceMetadata - { - if (null !== $parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); - } -} diff --git a/src/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php deleted file mode 100644 index 921f9e8c4f8..00000000000 --- a/src/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use Doctrine\Common\Annotations\Reader; - -/** - * Creates a resource metadata from {@see ApiResource} annotations. - * - * @author Kévin Dunglas - */ -final class AnnotationResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $reader; - private $decorated; - private $defaults; - - public function __construct(Reader $reader = null, ResourceMetadataFactoryInterface $decorated = null, array $defaults = []) - { - $this->reader = $reader; - $this->decorated = $decorated; - $this->defaults = $defaults + ['attributes' => []]; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $parentResourceMetadata = null; - if ($this->decorated) { - try { - $parentResourceMetadata = $this->decorated->create($resourceClass); - } catch (ResourceClassNotFoundException $resourceNotFoundException) { - // Ignore not found exception from decorated factories - } - } - - try { - $reflectionClass = new \ReflectionClass($resourceClass); - } catch (\ReflectionException $reflectionException) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - if (\PHP_VERSION_ID >= 80000 && $attributes = $reflectionClass->getAttributes(ApiResource::class)) { - return $this->createMetadata($attributes[0]->newInstance(), $parentResourceMetadata); - } - - if (null === $this->reader) { - $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - $resourceAnnotation = $this->reader->getClassAnnotation($reflectionClass, ApiResource::class); - - if (!$resourceAnnotation instanceof ApiResource) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - return $this->createMetadata($resourceAnnotation, $parentResourceMetadata); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws ResourceClassNotFoundException - */ - private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, string $resourceClass): ResourceMetadata - { - if (null !== $parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); - } - - private function createMetadata(ApiResource $annotation, ResourceMetadata $parentResourceMetadata = null): ResourceMetadata - { - $attributes = null; - if (null !== $annotation->attributes || [] !== $this->defaults['attributes']) { - $attributes = (array) $annotation->attributes; - foreach ($this->defaults['attributes'] as $key => $value) { - if (!isset($attributes[$key])) { - $attributes[$key] = $value; - } - } - } - - if (!$parentResourceMetadata) { - return new ResourceMetadata( - $annotation->shortName, - $annotation->description ?? $this->defaults['description'] ?? null, // @phpstan-ignore-line - $annotation->iri ?? $this->defaults['iri'] ?? null, // @phpstan-ignore-line - $annotation->itemOperations ?? $this->defaults['item_operations'] ?? null, // @phpstan-ignore-line - $annotation->collectionOperations ?? $this->defaults['collection_operations'] ?? null, // @phpstan-ignore-line - $attributes, - $annotation->subresourceOperations, - $annotation->graphql ?? $this->defaults['graphql'] ?? null // @phpstan-ignore-line - ); - } - - $resourceMetadata = $parentResourceMetadata; - foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { - $resourceMetadata = $this->createWith($resourceMetadata, $property, $annotation->{$property}); - } - - return $resourceMetadata; - } - - /** - * Creates a new instance of metadata if the property is not already set. - * - * @param mixed $value - */ - private function createWith(ResourceMetadata $resourceMetadata, string $property, $value): ResourceMetadata - { - $upperProperty = ucfirst($property); - $getter = "get$upperProperty"; - - if (null !== $resourceMetadata->{$getter}()) { - return $resourceMetadata; - } - - if (null === $value) { - return $resourceMetadata; - } - - $wither = "with$upperProperty"; - - return $resourceMetadata->{$wither}($value); - } -} diff --git a/src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php b/src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php deleted file mode 100644 index b99835902bd..00000000000 --- a/src/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactory.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Util\ReflectionClassRecursiveIterator; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use Doctrine\Common\Annotations\Reader; - -/** - * Creates a resource name collection from {@see ApiResource} annotations. - * - * @author Kévin Dunglas - */ -final class AnnotationResourceNameCollectionFactory implements ResourceNameCollectionFactoryInterface -{ - private $reader; - private $paths; - private $decorated; - - /** - * @param string[] $paths - */ - public function __construct(Reader $reader = null, array $paths, ResourceNameCollectionFactoryInterface $decorated = null) - { - $this->reader = $reader; - $this->paths = $paths; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(): ResourceNameCollection - { - $classes = []; - - if ($this->decorated) { - foreach ($this->decorated->create() as $resourceClass) { - $classes[$resourceClass] = true; - } - } - - foreach (ReflectionClassRecursiveIterator::getReflectionClassesFromDirectories($this->paths) as $className => $reflectionClass) { - if ( - (\PHP_VERSION_ID >= 80000 && $reflectionClass->getAttributes(ApiResource::class)) || - (null !== $this->reader && $this->reader->getClassAnnotation($reflectionClass, ApiResource::class)) - ) { - $classes[$className] = true; - } - } - - return new ResourceNameCollection(array_keys($classes)); - } -} diff --git a/src/Core/Metadata/Resource/Factory/CachedResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/CachedResourceMetadataFactory.php deleted file mode 100644 index 1398bb2fabb..00000000000 --- a/src/Core/Metadata/Resource/Factory/CachedResourceMetadataFactory.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Util\CachedTrait; -use Psr\Cache\CacheItemPoolInterface; - -/** - * Caches resource metadata. - * - * @author Teoh Han Hui - */ -final class CachedResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - use CachedTrait; - - public const CACHE_KEY_PREFIX = 'resource_metadata_'; - - private $decorated; - - public function __construct(CacheItemPoolInterface $cacheItemPool, ResourceMetadataFactoryInterface $decorated) - { - $this->cacheItemPool = $cacheItemPool; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $cacheKey = self::CACHE_KEY_PREFIX.md5($resourceClass); - - return $this->getCached($cacheKey, function () use ($resourceClass) { - return $this->decorated->create($resourceClass); - }); - } -} diff --git a/src/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php deleted file mode 100644 index c5992301e46..00000000000 --- a/src/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php +++ /dev/null @@ -1,104 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Exception\ResourceClassNotFoundException; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Metadata\Extractor\ResourceExtractorInterface; - -/** - * Creates resource's metadata using an extractor. - * - * @author Kévin Dunglas - * @author Antoine Bluchet - */ -final class ExtractorResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $extractor; - private $decorated; - private $defaults; - - public function __construct(ResourceExtractorInterface $extractor, ResourceMetadataFactoryInterface $decorated = null, array $defaults = []) - { - $this->extractor = $extractor; - $this->decorated = $decorated; - $this->defaults = $defaults + ['attributes' => []]; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $parentResourceMetadata = null; - if ($this->decorated) { - try { - $parentResourceMetadata = $this->decorated->create($resourceClass); - } catch (ResourceClassNotFoundException $resourceNotFoundException) { - // Ignore not found exception from decorated factories - } - } - - if (!(class_exists($resourceClass) || interface_exists($resourceClass)) || !$resource = $this->extractor->getResources()[$resourceClass] ?? false) { - return $this->handleNotFound($parentResourceMetadata, $resourceClass); - } - - $resource['description'] = $resource['description'] ?? $this->defaults['description'] ?? null; - $resource['iri'] = $resource['iri'] ?? $this->defaults['iri'] ?? null; - $resource['itemOperations'] = $resource['itemOperations'] ?? $this->defaults['item_operations'] ?? null; - $resource['collectionOperations'] = $resource['collectionOperations'] ?? $this->defaults['collection_operations'] ?? null; - $resource['graphql'] = $resource['graphql'] ?? $this->defaults['graphql'] ?? null; - - if (\array_key_exists('attributes', $resource) && (null !== $resource['attributes'] || [] !== $this->defaults['attributes'])) { - $resource['attributes'] = (array) $resource['attributes']; - foreach ($this->defaults['attributes'] as $key => $value) { - if (!isset($resource['attributes'][$key])) { - $resource['attributes'][$key] = $value; - } - } - } - - return $this->update($parentResourceMetadata ?: new ResourceMetadata(), $resource); - } - - /** - * Returns the metadata from the decorated factory if available or throws an exception. - * - * @throws ResourceClassNotFoundException - */ - private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, string $resourceClass): ResourceMetadata - { - if (null !== $parentPropertyMetadata) { - return $parentPropertyMetadata; - } - - throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); - } - - /** - * Creates a new instance of metadata if the property is not already set. - */ - private function update(ResourceMetadata $resourceMetadata, array $metadata): ResourceMetadata - { - foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { - if (!\array_key_exists($property, $metadata) || null === $metadata[$property] || null !== $resourceMetadata->{'get'.ucfirst($property)}()) { - continue; - } - - $resourceMetadata = $resourceMetadata->{'with'.ucfirst($property)}($metadata[$property]); - } - - return $resourceMetadata; - } -} diff --git a/src/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php deleted file mode 100644 index 9b34ba45c43..00000000000 --- a/src/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php +++ /dev/null @@ -1,127 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ResourceClassNotFoundException; - -/** - * Normalizes enabled formats. - * - * Formats hierarchy: - * * resource formats - * * resource input/output formats - * * operation formats - * * operation input/output formats - * - * @author Kévin Dunglas - */ -final class FormatsResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - private $formats; - private $patchFormats; - - public function __construct(ResourceMetadataFactoryInterface $decorated, array $formats, array $patchFormats) - { - $this->decorated = $decorated; - $this->formats = $formats; - $this->patchFormats = $patchFormats; - } - - /** - * Adds the formats attributes. - * - * @see OperationResourceMetadataFactory - * - * @throws ResourceClassNotFoundException - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - $rawResourceFormats = $resourceMetadata->getAttribute('formats'); - $resourceFormats = null === $rawResourceFormats ? $this->formats : $this->normalizeFormats($rawResourceFormats); - - $rawResourceInputFormats = $resourceMetadata->getAttribute('input_formats'); - $rawResourceOutputFormats = $resourceMetadata->getAttribute('output_formats'); - - $resourceInputFormats = $rawResourceInputFormats ? $this->normalizeFormats($rawResourceInputFormats) : $resourceFormats; - $resourceOutputFormats = $rawResourceOutputFormats ? $this->normalizeFormats($rawResourceOutputFormats) : $resourceFormats; - - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $collectionOperations)); - } - - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $itemOperations)); - } - - if (null !== $subresourceOperations = $resourceMetadata->getSubresourceOperations()) { - $resourceMetadata = $resourceMetadata->withSubresourceOperations($this->normalize($resourceInputFormats, $resourceOutputFormats, $subresourceOperations)); - } - - return $resourceMetadata; - } - - private function normalize(array $resourceInputFormats, array $resourceOutputFormats, array $operations): array - { - $newOperations = []; - foreach ($operations as $operationName => $operation) { - if ('PATCH' === ($operation['method'] ?? '') && !isset($operation['formats']) && !isset($operation['input_formats'])) { - $operation['input_formats'] = $this->patchFormats; - } - - if (isset($operation['formats'])) { - $operation['formats'] = $this->normalizeFormats($operation['formats']); - } - - $operation['input_formats'] = isset($operation['input_formats']) ? $this->normalizeFormats($operation['input_formats']) : $operation['formats'] ?? $resourceInputFormats; - $operation['output_formats'] = isset($operation['output_formats']) ? $this->normalizeFormats($operation['output_formats']) : $operation['formats'] ?? $resourceOutputFormats; - - $newOperations[$operationName] = $operation; - } - - return $newOperations; - } - - /** - * @param array|string $currentFormats - * - * @throws InvalidArgumentException - */ - private function normalizeFormats($currentFormats): array - { - $currentFormats = (array) $currentFormats; - - $normalizedFormats = []; - foreach ($currentFormats as $format => $value) { - if (!is_numeric($format)) { - $normalizedFormats[$format] = (array) $value; - continue; - } - if (!\is_string($value)) { - throw new InvalidArgumentException(sprintf("The 'formats' attributes value must be a string when trying to include an already configured format, %s given.", \gettype($value))); - } - if (\array_key_exists($value, $this->formats)) { - $normalizedFormats[$value] = $this->formats[$value]; - continue; - } - - throw new InvalidArgumentException(sprintf("You either need to add the format '%s' to your project configuration or declare a mime type for it in your annotation.", $value)); - } - - return $normalizedFormats; - } -} diff --git a/src/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php deleted file mode 100644 index 24e7b997d72..00000000000 --- a/src/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php +++ /dev/null @@ -1,109 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Transforms the given input/output metadata to a normalized one. - * - * @author Antoine Bluchet - */ -final class InputOutputResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - - public function __construct(ResourceMetadataFactoryInterface $decorated) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - - $attributes = $resourceMetadata->getAttributes() ?: []; - $attributes['input'] = isset($attributes['input']) ? $this->transformInputOutput($attributes['input']) : null; - $attributes['output'] = isset($attributes['output']) ? $this->transformInputOutput($attributes['output']) : null; - - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->getTransformedOperations($collectionOperations, $attributes)); - } - - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - $resourceMetadata = $resourceMetadata->withItemOperations($this->getTransformedOperations($itemOperations, $attributes)); - } - - if (null !== $graphQlAttributes = $resourceMetadata->getGraphql()) { - $resourceMetadata = $resourceMetadata->withGraphql($this->getTransformedOperations($graphQlAttributes, $attributes)); - } - - return $resourceMetadata->withAttributes($attributes); - } - - private function getTransformedOperations(array $operations, array $resourceAttributes): array - { - foreach ($operations as $key => &$operation) { - if (!\is_array($operation)) { - continue; - } - - $operation['input'] = isset($operation['input']) ? $this->transformInputOutput($operation['input']) : $resourceAttributes['input']; - $operation['output'] = isset($operation['output']) ? $this->transformInputOutput($operation['output']) : $resourceAttributes['output']; - - if ( - isset($operation['input']) - && \array_key_exists('class', $operation['input']) - && null === $operation['input']['class'] - ) { - $operation['deserialize'] ?? $operation['deserialize'] = false; - $operation['validate'] ?? $operation['validate'] = false; - } - - if ( - isset($operation['output']) - && \array_key_exists('class', $operation['output']) - && null === $operation['output']['class'] - ) { - $operation['status'] ?? $operation['status'] = 204; - } - } - - return $operations; - } - - private function transformInputOutput($attribute): ?array - { - if (null === $attribute) { - return null; - } - - if (false === $attribute) { - return ['class' => null]; - } - - if (\is_string($attribute)) { - $attribute = ['class' => $attribute]; - } - - if (!isset($attribute['name']) && isset($attribute['class'])) { - $attribute['name'] = (new \ReflectionClass($attribute['class']))->getShortName(); - } - - return $attribute; - } -} diff --git a/src/Core/Metadata/Resource/Factory/OperationResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/OperationResourceMetadataFactory.php deleted file mode 100644 index 52f65fde23c..00000000000 --- a/src/Core/Metadata/Resource/Factory/OperationResourceMetadataFactory.php +++ /dev/null @@ -1,153 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Creates or completes operations. - * - * @author Kévin Dunglas - */ -final class OperationResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - /** - * @internal - */ - public const SUPPORTED_COLLECTION_OPERATION_METHODS = [ - 'GET' => true, - 'POST' => true, - ]; - - /** - * @internal - */ - public const SUPPORTED_ITEM_OPERATION_METHODS = [ - 'GET' => true, - 'PUT' => true, - // PATCH is automatically supported if at least one patch format has been configured - 'DELETE' => true, - ]; - - private $decorated; - private $patchFormats; - - public function __construct(ResourceMetadataFactoryInterface $decorated, array $patchFormats = []) - { - $this->decorated = $decorated; - $this->patchFormats = $patchFormats; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - $isAbstract = (new \ReflectionClass($resourceClass))->isAbstract(); - - $collectionOperations = $resourceMetadata->getCollectionOperations(); - if (null === $collectionOperations) { - $resourceMetadata = $resourceMetadata->withCollectionOperations($this->createOperations($isAbstract ? ['GET'] : ['GET', 'POST'], $resourceMetadata)); - } else { - $resourceMetadata = $this->normalize(true, $resourceClass, $resourceMetadata, $collectionOperations); - } - - $itemOperations = $resourceMetadata->getItemOperations(); - if (null === $itemOperations) { - $methods = ['GET', 'DELETE']; - - if (!$isAbstract) { - $methods[] = 'PUT'; - - if ($this->patchFormats) { - $methods[] = 'PATCH'; - } - } - - $resourceMetadata = $resourceMetadata->withItemOperations($this->createOperations($methods, $resourceMetadata)); - } else { - $resourceMetadata = $this->normalize(false, $resourceClass, $resourceMetadata, $itemOperations); - } - - $graphql = $resourceMetadata->getGraphql(); - if (null === $graphql) { - $resourceMetadata = $resourceMetadata->withGraphql(['item_query' => [], 'collection_query' => [], 'delete' => [], 'update' => [], 'create' => []]); - } else { - $resourceMetadata = $this->normalizeGraphQl($resourceMetadata, $graphql); - } - - return $resourceMetadata; - } - - private function createOperations(array $methods, ResourceMetadata $resourceMetadata): array - { - $operations = []; - foreach ($methods as $method) { - $operations[strtolower($method)] = ['method' => $method, 'stateless' => $resourceMetadata->getAttribute('stateless')]; - } - - return $operations; - } - - private function normalize(bool $collection, string $resourceClass, ResourceMetadata $resourceMetadata, array $operations): ResourceMetadata - { - $newOperations = []; - foreach ($operations as $operationName => $operation) { - // e.g.: @ApiResource(itemOperations={"get"}) - if (\is_int($operationName) && \is_string($operation)) { - $operationName = $operation; - $operation = []; - } - - $upperOperationName = strtoupper((string) $operationName); - if ($collection) { - $supported = isset(self::SUPPORTED_COLLECTION_OPERATION_METHODS[$upperOperationName]); - } else { - $supported = isset(self::SUPPORTED_ITEM_OPERATION_METHODS[$upperOperationName]) || ($this->patchFormats && 'PATCH' === $upperOperationName); - } - - if (!isset($operation['method']) && !isset($operation['route_name'])) { - if ($supported) { - $operation['method'] = $upperOperationName; - } else { - @trigger_error(sprintf('The "route_name" attribute will not be set automatically again in API Platform 3.0, set it for the %s operation "%s" of the class "%s".', $collection ? 'collection' : 'item', $operationName, $resourceClass), \E_USER_DEPRECATED); - $operation['route_name'] = $operationName; - } - } - - if (isset($operation['method'])) { - $operation['method'] = strtoupper($operation['method']); - } - - $operation['stateless'] = $operation['stateless'] ?? $resourceMetadata->getAttribute('stateless'); - - $newOperations[$operationName] = $operation; - } - - return $collection ? $resourceMetadata->withCollectionOperations($newOperations) : $resourceMetadata->withItemOperations($newOperations); - } - - private function normalizeGraphQl(ResourceMetadata $resourceMetadata, array $operations): ResourceMetadata - { - foreach ($operations as $operationName => $operation) { - if (\is_int($operationName) && \is_string($operation)) { - unset($operations[$operationName]); - $operations[$operation] = []; - } - } - - return $resourceMetadata->withGraphql($operations); - } -} diff --git a/src/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php deleted file mode 100644 index f2257d24efd..00000000000 --- a/src/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use phpDocumentor\Reflection\DocBlockFactory; -use phpDocumentor\Reflection\DocBlockFactoryInterface; -use phpDocumentor\Reflection\Types\ContextFactory; - -/** - * Extracts descriptions from PHPDoc. - * - * @author Kévin Dunglas - */ -final class PhpDocResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - private $docBlockFactory; - private $contextFactory; - - public function __construct(ResourceMetadataFactoryInterface $decorated, DocBlockFactoryInterface $docBlockFactory = null) - { - $this->decorated = $decorated; - $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance(); - $this->contextFactory = new ContextFactory(); - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - - if (null !== $resourceMetadata->getDescription()) { - return $resourceMetadata; - } - - $reflectionClass = new \ReflectionClass($resourceClass); - - try { - $docBlock = $this->docBlockFactory->create($reflectionClass, $this->contextFactory->createFromReflector($reflectionClass)); - $resourceMetadata = $resourceMetadata->withDescription($docBlock->getSummary()); - } catch (\InvalidArgumentException $e) { - // Ignore empty DocBlocks - } - - return $resourceMetadata; - } -} diff --git a/src/Core/Metadata/Resource/Factory/ResourceMetadataFactoryInterface.php b/src/Core/Metadata/Resource/Factory/ResourceMetadataFactoryInterface.php deleted file mode 100644 index 8032e73377e..00000000000 --- a/src/Core/Metadata/Resource/Factory/ResourceMetadataFactoryInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; - -/** - * Creates a resource metadata value object. - * - * @author Kévin Dunglas - */ -interface ResourceMetadataFactoryInterface -{ - /** - * Creates a resource metadata. - * - * @throws ResourceClassNotFoundException - */ - public function create(string $resourceClass): ResourceMetadata; -} diff --git a/src/Core/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php b/src/Core/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php deleted file mode 100644 index c7f9e898f63..00000000000 --- a/src/Core/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; - -/** - * Guesses the short name from the class name if not already set. - * - * @author Kévin Dunglas - */ -final class ShortNameResourceMetadataFactory implements ResourceMetadataFactoryInterface -{ - private $decorated; - - public function __construct(ResourceMetadataFactoryInterface $decorated) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): ResourceMetadata - { - $resourceMetadata = $this->decorated->create($resourceClass); - - if (null !== $resourceMetadata->getShortName()) { - return $resourceMetadata; - } - - if (false !== $pos = strrpos($resourceClass, '\\')) { - return $resourceMetadata->withShortName(substr($resourceClass, $pos + 1)); - } - - return $resourceMetadata->withShortName($resourceClass); - } -} diff --git a/src/Core/Metadata/Resource/ResourceMetadata.php b/src/Core/Metadata/Resource/ResourceMetadata.php deleted file mode 100644 index cc226f6c201..00000000000 --- a/src/Core/Metadata/Resource/ResourceMetadata.php +++ /dev/null @@ -1,311 +0,0 @@ - - * - * 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\Metadata\Resource; - -use ApiPlatform\Core\Api\OperationType; - -/** - * Resource metadata. - * - * @author Kévin Dunglas - */ -final class ResourceMetadata -{ - private $shortName; - private $description; - private $iri; - private $itemOperations; - private $collectionOperations; - private $subresourceOperations; - private $graphql; - private $attributes; - - public function __construct(string $shortName = null, string $description = null, string $iri = null, array $itemOperations = null, array $collectionOperations = null, array $attributes = null, array $subresourceOperations = null, array $graphql = null) - { - $this->shortName = $shortName; - $this->description = $description; - $this->iri = $iri; - $this->itemOperations = $itemOperations; - $this->collectionOperations = $collectionOperations; - $this->subresourceOperations = $subresourceOperations; - $this->graphql = $graphql; - $this->attributes = $attributes; - } - - /** - * Gets the short name. - */ - public function getShortName(): ?string - { - return $this->shortName; - } - - /** - * Returns a new instance with the given short name. - */ - public function withShortName(string $shortName): self - { - $metadata = clone $this; - $metadata->shortName = $shortName; - - return $metadata; - } - - /** - * Gets the description. - */ - public function getDescription(): ?string - { - return $this->description; - } - - /** - * Returns a new instance with the given description. - */ - public function withDescription(string $description): self - { - $metadata = clone $this; - $metadata->description = $description; - - return $metadata; - } - - /** - * Gets the associated IRI. - */ - public function getIri(): ?string - { - return $this->iri; - } - - /** - * Returns a new instance with the given IRI. - */ - public function withIri(string $iri): self - { - $metadata = clone $this; - $metadata->iri = $iri; - - return $metadata; - } - - /** - * Gets item operations. - */ - public function getItemOperations(): ?array - { - return $this->itemOperations; - } - - /** - * Returns a new instance with the given item operations. - */ - public function withItemOperations(array $itemOperations): self - { - $metadata = clone $this; - $metadata->itemOperations = $itemOperations; - - return $metadata; - } - - /** - * Gets collection operations. - */ - public function getCollectionOperations(): ?array - { - return $this->collectionOperations; - } - - /** - * Returns a new instance with the given collection operations. - */ - public function withCollectionOperations(array $collectionOperations): self - { - $metadata = clone $this; - $metadata->collectionOperations = $collectionOperations; - - return $metadata; - } - - /** - * Gets subresource operations. - */ - public function getSubresourceOperations(): ?array - { - return $this->subresourceOperations; - } - - /** - * Returns a new instance with the given subresource operations. - */ - public function withSubresourceOperations(array $subresourceOperations): self - { - $metadata = clone $this; - $metadata->subresourceOperations = $subresourceOperations; - - return $metadata; - } - - /** - * Gets a collection operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - public function getCollectionOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - return $this->findOperationAttribute($this->collectionOperations, $operationName, $key, $defaultValue, $resourceFallback); - } - - /** - * Gets an item operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - public function getItemOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - return $this->findOperationAttribute($this->itemOperations, $operationName, $key, $defaultValue, $resourceFallback); - } - - /** - * Gets a subresource operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - public function getSubresourceOperationAttribute(?string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - return $this->findOperationAttribute($this->subresourceOperations, $operationName, $key, $defaultValue, $resourceFallback); - } - - public function getGraphqlAttribute(string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - if (isset($this->graphql[$operationName][$key])) { - return $this->graphql[$operationName][$key]; - } - - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; - } - - /** - * Gets the first available operation attribute according to the following order: collection, item, subresource, optionally fallback to a default value. - * - * @param mixed|null $defaultValue - */ - public function getOperationAttribute(array $attributes, string $key, $defaultValue = null, bool $resourceFallback = false) - { - if (isset($attributes['collection_operation_name'])) { - return $this->getCollectionOperationAttribute($attributes['collection_operation_name'], $key, $defaultValue, $resourceFallback); - } - - if (isset($attributes['item_operation_name'])) { - return $this->getItemOperationAttribute($attributes['item_operation_name'], $key, $defaultValue, $resourceFallback); - } - - if (isset($attributes['subresource_operation_name'])) { - return $this->getSubresourceOperationAttribute($attributes['subresource_operation_name'], $key, $defaultValue, $resourceFallback); - } - - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; - } - - /** - * Gets an attribute for a given operation type and operation name. - * - * @param mixed|null $defaultValue - */ - public function getTypedOperationAttribute(string $operationType, string $operationName, string $key, $defaultValue = null, bool $resourceFallback = false) - { - switch ($operationType) { - case OperationType::COLLECTION: - return $this->getCollectionOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - case OperationType::ITEM: - return $this->getItemOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - default: - return $this->getSubresourceOperationAttribute($operationName, $key, $defaultValue, $resourceFallback); - } - } - - /** - * Gets attributes. - */ - public function getAttributes(): ?array - { - return $this->attributes; - } - - /** - * Gets an attribute. - * - * @param mixed|null $defaultValue - */ - public function getAttribute(string $key, $defaultValue = null) - { - return $this->attributes[$key] ?? $defaultValue; - } - - /** - * Returns a new instance with the given attribute. - */ - public function withAttributes(array $attributes): self - { - $metadata = clone $this; - $metadata->attributes = $attributes; - - return $metadata; - } - - /** - * Gets options of for the GraphQL query. - */ - public function getGraphql(): ?array - { - return $this->graphql; - } - - /** - * Returns a new instance with the given GraphQL options. - */ - public function withGraphql(array $graphql): self - { - $metadata = clone $this; - $metadata->graphql = $graphql; - - return $metadata; - } - - /** - * Gets an operation attribute, optionally fallback to a resource attribute. - * - * @param mixed|null $defaultValue - */ - private function findOperationAttribute(?array $operations, ?string $operationName, string $key, $defaultValue, bool $resourceFallback) - { - if (null !== $operationName && isset($operations[$operationName][$key])) { - return $operations[$operationName][$key]; - } - - if ($resourceFallback && isset($this->attributes[$key])) { - return $this->attributes[$key]; - } - - return $defaultValue; - } -} diff --git a/src/Core/Metadata/Resource/ToggleableOperationAttributeTrait.php b/src/Core/Metadata/Resource/ToggleableOperationAttributeTrait.php deleted file mode 100644 index b1aa81da947..00000000000 --- a/src/Core/Metadata/Resource/ToggleableOperationAttributeTrait.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * 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\Metadata\Resource; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; - -/** - * @internal - * TODO: 3.0 remove the trait - */ -trait ToggleableOperationAttributeTrait -{ - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface|null - */ - private $resourceMetadataFactory; - - private function isOperationAttributeDisabled(array $attributes, string $attribute, bool $default = false, bool $resourceFallback = true): bool - { - if (null === $this->resourceMetadataFactory) { - return !($attributes[$attribute] ?? !$default); - } - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - return !$default; - } - - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - - return !((bool) $resourceMetadata->getOperationAttribute($attributes, $attribute, !$default, $resourceFallback)); - } -} diff --git a/src/Core/Metadata/schema/metadata.xsd b/src/Core/Metadata/schema/metadata.xsd deleted file mode 100644 index 2515d2440fc..00000000000 --- a/src/Core/Metadata/schema/metadata.xsd +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Core/OpenApi/Factory/OpenApiFactory.php b/src/Core/OpenApi/Factory/OpenApiFactory.php deleted file mode 100644 index 4937f73cd08..00000000000 --- a/src/Core/OpenApi/Factory/OpenApiFactory.php +++ /dev/null @@ -1,539 +0,0 @@ - - * - * 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\OpenApi\Factory; - -use ApiPlatform\Core\Api\FilterLocatorTrait; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\JsonSchema\Schema; -use ApiPlatform\JsonSchema\TypeFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; -use ApiPlatform\OpenApi\Model; -use ApiPlatform\OpenApi\Model\ExternalDocumentation; -use ApiPlatform\OpenApi\Model\PathItem; -use ApiPlatform\OpenApi\OpenApi; -use ApiPlatform\OpenApi\Options; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use ApiPlatform\State\Pagination\PaginationOptions; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; - -/** - * Generates an Open API v3 specification. - */ -final class OpenApiFactory implements OpenApiFactoryInterface -{ - use FilterLocatorTrait; - - public const BASE_URL = 'base_url'; - public const OPENAPI_DEFINITION_NAME = 'openapi_definition_name'; - - private $resourceNameCollectionFactory; - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $operationPathResolver; - private $subresourceOperationFactory; - private $formats; - private $jsonSchemaFactory; - private $jsonSchemaTypeFactory; - private $openApiOptions; - private $paginationOptions; - private $identifiersExtractor; - - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, SchemaFactoryInterface $jsonSchemaFactory, TypeFactoryInterface $jsonSchemaTypeFactory, OperationPathResolverInterface $operationPathResolver, ContainerInterface $filterLocator, SubresourceOperationFactoryInterface $subresourceOperationFactory, IdentifiersExtractorInterface $identifiersExtractor = null, array $formats = [], Options $openApiOptions = null, PaginationOptions $paginationOptions = null) - { - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->jsonSchemaFactory = $jsonSchemaFactory; - $this->jsonSchemaTypeFactory = $jsonSchemaTypeFactory; - $this->formats = $formats; - $this->setFilterLocator($filterLocator, true); - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->operationPathResolver = $operationPathResolver; - $this->subresourceOperationFactory = $subresourceOperationFactory; - $this->identifiersExtractor = $identifiersExtractor; - $this->openApiOptions = $openApiOptions ?: new Options('API Platform'); - $this->paginationOptions = $paginationOptions ?: new PaginationOptions(); - } - - /** - * {@inheritdoc} - */ - public function __invoke(array $context = []): OpenApi - { - $baseUrl = $context[self::BASE_URL] ?? '/'; - $contact = null === $this->openApiOptions->getContactUrl() || null === $this->openApiOptions->getContactEmail() ? null : new Model\Contact($this->openApiOptions->getContactName(), $this->openApiOptions->getContactUrl(), $this->openApiOptions->getContactEmail()); - $license = null === $this->openApiOptions->getLicenseName() ? null : new Model\License($this->openApiOptions->getLicenseName(), $this->openApiOptions->getLicenseUrl()); - $info = new Model\Info($this->openApiOptions->getTitle(), $this->openApiOptions->getVersion(), trim($this->openApiOptions->getDescription()), $this->openApiOptions->getTermsOfService(), $contact, $license); - $servers = '/' === $baseUrl || '' === $baseUrl ? [new Model\Server('/')] : [new Model\Server($baseUrl)]; - $paths = new Model\Paths(); - $links = []; - $schemas = new \ArrayObject(); - - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - // Items needs to be parsed first to be able to reference the lines from the collection operation - $this->collectPaths($resourceMetadata, $resourceClass, OperationType::ITEM, $context, $paths, $links, $schemas); - $this->collectPaths($resourceMetadata, $resourceClass, OperationType::COLLECTION, $context, $paths, $links, $schemas); - - $this->collectPaths($resourceMetadata, $resourceClass, OperationType::SUBRESOURCE, $context, $paths, $links, $schemas); - } - - $securitySchemes = $this->getSecuritySchemes(); - $securityRequirements = []; - - foreach (array_keys($securitySchemes) as $key) { - $securityRequirements[] = [$key => []]; - } - - return new OpenApi( - $info, - $servers, - $paths, - new Model\Components( - $schemas, - new \ArrayObject(), - new \ArrayObject(), - new \ArrayObject(), - new \ArrayObject(), - new \ArrayObject(), - new \ArrayObject($securitySchemes) - ), - $securityRequirements - ); - } - - private function collectPaths(ResourceMetadata $resourceMetadata, string $resourceClass, string $operationType, array $context, Model\Paths $paths, array &$links, \ArrayObject $schemas): void - { - $resourceShortName = $resourceMetadata->getShortName(); - $operations = OperationType::COLLECTION === $operationType ? $resourceMetadata->getCollectionOperations() : (OperationType::ITEM === $operationType ? $resourceMetadata->getItemOperations() : $this->subresourceOperationFactory->create($resourceClass)); - if (!$operations) { - return; - } - - $rootResourceClass = $resourceClass; - foreach ($operations as $operationName => $operation) { - if (OperationType::COLLECTION === $operationType && !$resourceMetadata->getItemOperations()) { - $identifiers = []; - } else { - $identifiers = (array) ($operation['identifiers'] ?? $resourceMetadata->getAttribute('identifiers', null === $this->identifiersExtractor ? ['id'] : $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass))); - } - if (\count($identifiers) > 1 ? $resourceMetadata->getAttribute('composite_identifier', true) : false) { - $identifiers = ['id']; - } - - $resourceClass = $operation['resource_class'] ?? $rootResourceClass; - $path = $this->getPath($resourceShortName, $operationName, $operation, $operationType); - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); - - if (!\in_array($method, PathItem::$methods, true)) { - continue; - } - - [$requestMimeTypes, $responseMimeTypes] = $this->getMimeTypes($resourceClass, $operationName, $operationType, $resourceMetadata); - $operationId = $operation['openapi_context']['operationId'] ?? lcfirst($operationName).ucfirst($resourceShortName).ucfirst($operationType); - $linkedOperationId = 'get'.ucfirst($resourceShortName).ucfirst(OperationType::ITEM); - $pathItem = $paths->getPath($path) ?: new Model\PathItem(); - $forceSchemaCollection = OperationType::SUBRESOURCE === $operationType ? ($operation['collection'] ?? false) : false; - - $schema = new Schema('openapi'); - $schema->setDefinitions($schemas); - - $operationOutputSchemas = []; - foreach ($responseMimeTypes as $operationFormat) { - $operationOutputSchema = $this->jsonSchemaFactory->buildSchema($resourceClass, $operationFormat, Schema::TYPE_OUTPUT, $operationType, $operationName, $schema, null, $forceSchemaCollection); - $operationOutputSchemas[$operationFormat] = $operationOutputSchema; - $this->appendSchemaDefinitions($schemas, $operationOutputSchema->getDefinitions()); - } - - $parameters = []; - $responses = []; - - if ($operation['openapi_context']['parameters'] ?? false) { - foreach ($operation['openapi_context']['parameters'] as $parameter) { - $parameters[] = new Model\Parameter($parameter['name'], $parameter['in'], $parameter['description'] ?? '', $parameter['required'] ?? false, $parameter['deprecated'] ?? false, $parameter['allowEmptyValue'] ?? false, $parameter['schema'] ?? [], $parameter['style'] ?? null, $parameter['explode'] ?? false, $parameter['allowReserved '] ?? false, $parameter['example'] ?? null, isset($parameter['examples']) ? new \ArrayObject($parameter['examples']) : null, isset($parameter['content']) ? new \ArrayObject($parameter['content']) : null); - } - } - - // Set up parameters - if (OperationType::ITEM === $operationType) { - foreach ($identifiers as $parameterName => $identifier) { - $parameterName = \is_string($parameterName) ? $parameterName : $identifier; - $parameter = new Model\Parameter($parameterName, 'path', 'Resource identifier', true, false, false, ['type' => 'string']); - if ($this->hasParameter($parameter, $parameters)) { - continue; - } - - $parameters[] = $parameter; - } - $links[$operationId] = $this->getLink($resourceClass, $operationId, $path); - } elseif (OperationType::COLLECTION === $operationType && 'GET' === $method) { - foreach (array_merge($this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($resourceMetadata, $operationName, $resourceClass)) as $parameter) { - if ($this->hasParameter($parameter, $parameters)) { - continue; - } - - $parameters[] = $parameter; - } - } elseif (OperationType::SUBRESOURCE === $operationType) { - foreach ($operation['identifiers'] as $parameterName => [$class, $property]) { - $parameter = new Model\Parameter($parameterName, 'path', $this->resourceMetadataFactory->create($class)->getShortName().' identifier', true, false, false, ['type' => 'string']); - if ($this->hasParameter($parameter, $parameters)) { - continue; - } - - $parameters[] = $parameter; - } - - if ($operation['collection']) { - $subresourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - foreach (array_merge($this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($subresourceMetadata, $operationName, $resourceClass)) as $parameter) { - if ($this->hasParameter($parameter, $parameters)) { - continue; - } - - $parameters[] = $parameter; - } - } - } - - // Create responses - switch ($method) { - case 'GET': - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); - $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); - $responses[$successStatus] = new Model\Response(sprintf('%s %s', $resourceShortName, OperationType::COLLECTION === $operationType ? 'collection' : 'resource'), $responseContent); - break; - case 'POST': - $responseLinks = new \ArrayObject(isset($links[$linkedOperationId]) ? [ucfirst($linkedOperationId) => $links[$linkedOperationId]] : []); - $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '201'); - $responses[$successStatus] = new Model\Response(sprintf('%s resource created', $resourceShortName), $responseContent, null, $responseLinks); - $responses['400'] = new Model\Response('Invalid input'); - $responses['422'] = new Model\Response('Unprocessable entity'); - break; - case 'PATCH': - case 'PUT': - $responseLinks = new \ArrayObject(isset($links[$linkedOperationId]) ? [ucfirst($linkedOperationId) => $links[$linkedOperationId]] : []); - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); - $responseContent = $this->buildContent($responseMimeTypes, $operationOutputSchemas); - $responses[$successStatus] = new Model\Response(sprintf('%s resource updated', $resourceShortName), $responseContent, null, $responseLinks); - $responses['400'] = new Model\Response('Invalid input'); - $responses['422'] = new Model\Response('Unprocessable entity'); - break; - case 'DELETE': - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '204'); - $responses[$successStatus] = new Model\Response(sprintf('%s resource deleted', $resourceShortName)); - break; - } - - if (OperationType::ITEM === $operationType) { - $responses['404'] = new Model\Response('Resource not found'); - } - - if (!$responses) { - $responses['default'] = new Model\Response('Unexpected error'); - } - - if ($contextResponses = $operation['openapi_context']['responses'] ?? false) { - foreach ($contextResponses as $statusCode => $contextResponse) { - $responses[$statusCode] = new Model\Response($contextResponse['description'] ?? '', isset($contextResponse['content']) ? new \ArrayObject($contextResponse['content']) : null, isset($contextResponse['headers']) ? new \ArrayObject($contextResponse['headers']) : null, isset($contextResponse['links']) ? new \ArrayObject($contextResponse['links']) : null); - } - } - - $requestBody = null; - if ($contextRequestBody = $operation['openapi_context']['requestBody'] ?? false) { - $requestBody = new Model\RequestBody($contextRequestBody['description'] ?? '', new \ArrayObject($contextRequestBody['content']), $contextRequestBody['required'] ?? false); - } elseif ('PUT' === $method || 'POST' === $method || 'PATCH' === $method) { - $operationInputSchemas = []; - foreach ($requestMimeTypes as $operationFormat) { - $operationInputSchema = $this->jsonSchemaFactory->buildSchema($resourceClass, $operationFormat, Schema::TYPE_INPUT, $operationType, $operationName, $schema, null, $forceSchemaCollection); - $operationInputSchemas[$operationFormat] = $operationInputSchema; - $this->appendSchemaDefinitions($schemas, $operationInputSchema->getDefinitions()); - } - - $requestBody = new Model\RequestBody(sprintf('The %s %s resource', 'POST' === $method ? 'new' : 'updated', $resourceShortName), $this->buildContent($requestMimeTypes, $operationInputSchemas), true); - } - - $pathItem = $pathItem->{'with'.ucfirst($method)}(new Model\Operation( - $operationId, - $operation['openapi_context']['tags'] ?? (OperationType::SUBRESOURCE === $operationType ? $operation['shortNames'] : [$resourceShortName]), - $responses, - $operation['openapi_context']['summary'] ?? $this->getPathDescription($resourceShortName, $method, $operationType), - $operation['openapi_context']['description'] ?? $this->getPathDescription($resourceShortName, $method, $operationType), - isset($operation['openapi_context']['externalDocs']) ? new ExternalDocumentation($operation['openapi_context']['externalDocs']['description'] ?? null, $operation['openapi_context']['externalDocs']['url']) : null, - $parameters, - $requestBody, - isset($operation['openapi_context']['callbacks']) ? new \ArrayObject($operation['openapi_context']['callbacks']) : null, - $operation['openapi_context']['deprecated'] ?? (bool) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', false, true), - $operation['openapi_context']['security'] ?? null, - $operation['openapi_context']['servers'] ?? null, - array_filter($operation['openapi_context'] ?? [], static function ($item) { - return preg_match('/^x-.*$/i', $item); - }, \ARRAY_FILTER_USE_KEY) - )); - - $paths->addPath($path, $pathItem); - } - } - - private function buildContent(array $responseMimeTypes, array $operationSchemas): \ArrayObject - { - /** @var \ArrayObject */ - $content = new \ArrayObject(); - - foreach ($responseMimeTypes as $mimeType => $format) { - $content[$mimeType] = new Model\MediaType(new \ArrayObject($operationSchemas[$format]->getArrayCopy(false))); - } - - return $content; - } - - private function getMimeTypes(string $resourceClass, string $operationName, string $operationType, ResourceMetadata $resourceMetadata = null): array - { - $requestFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input_formats', $this->formats, true); - $responseFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output_formats', $this->formats, true); - - $requestMimeTypes = $this->flattenMimeTypes($requestFormats); - $responseMimeTypes = $this->flattenMimeTypes($responseFormats); - - return [$requestMimeTypes, $responseMimeTypes]; - } - - private function flattenMimeTypes(array $responseFormats): array - { - $responseMimeTypes = []; - foreach ($responseFormats as $responseFormat => $mimeTypes) { - foreach ($mimeTypes as $mimeType) { - $responseMimeTypes[$mimeType] = $responseFormat; - } - } - - return $responseMimeTypes; - } - - /** - * Gets the path for an operation. - * - * If the path ends with the optional _format parameter, it is removed - * as optional path parameters are not yet supported. - * - * @see https://github.com/OAI/OpenAPI-Specification/issues/93 - */ - private function getPath(string $resourceShortName, string $operationName, array $operation, string $operationType): string - { - $path = $this->operationPathResolver->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - if ('.{_format}' === substr($path, -10)) { - $path = substr($path, 0, -10); - } - - return 0 === strpos($path, '/') ? $path : '/'.$path; - } - - private function getPathDescription(string $resourceShortName, string $method, string $operationType): string - { - switch ($method) { - case 'GET': - $pathSummary = OperationType::COLLECTION === $operationType ? 'Retrieves the collection of %s resources.' : 'Retrieves a %s resource.'; - break; - case 'POST': - $pathSummary = 'Creates a %s resource.'; - break; - case 'PATCH': - $pathSummary = 'Updates the %s resource.'; - break; - case 'PUT': - $pathSummary = 'Replaces the %s resource.'; - break; - case 'DELETE': - $pathSummary = 'Removes the %s resource.'; - break; - default: - return $resourceShortName; - } - - return sprintf($pathSummary, $resourceShortName); - } - - /** - * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#linkObject. - */ - private function getLink(string $resourceClass, string $operationId, string $path): Model\Link - { - $parameters = []; - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - if (!$propertyMetadata->isIdentifier()) { - continue; - } - - $parameters[$propertyName] = sprintf('$response.body#/%s', $propertyName); - } - - return new Model\Link( - $operationId, - new \ArrayObject($parameters), - null, - 1 === \count($parameters) ? sprintf('The `%1$s` value returned in the response can be used as the `%1$s` parameter in `GET %2$s`.', key($parameters), $path) : sprintf('The values returned in the response can be used in `GET %s`.', $path) - ); - } - - /** - * Gets parameters corresponding to enabled filters. - */ - private function getFiltersParameters(ResourceMetadata $resourceMetadata, string $operationName, string $resourceClass): array - { - $parameters = []; - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); - foreach ($resourceFilters as $filterId) { - if (!$filter = $this->getFilter($filterId)) { - continue; - } - - foreach ($filter->getDescription($resourceClass) as $name => $data) { - $schema = $data['schema'] ?? (\in_array($data['type'], Type::$builtinTypes, true) ? $this->jsonSchemaTypeFactory->getType(new Type($data['type'], false, null, $data['is_collection'] ?? false)) : ['type' => 'string']); - - $parameters[] = new Model\Parameter( - $name, - 'query', - $data['description'] ?? '', - $data['required'] ?? false, - $data['openapi']['deprecated'] ?? false, - $data['openapi']['allowEmptyValue'] ?? true, - $schema, - 'array' === $schema['type'] && \in_array($data['type'], - [Type::BUILTIN_TYPE_ARRAY, Type::BUILTIN_TYPE_OBJECT], true) ? 'deepObject' : 'form', - $data['openapi']['explode'] ?? ('array' === $schema['type']), - $data['openapi']['allowReserved'] ?? false, - $data['openapi']['example'] ?? null, - isset($data['openapi']['examples'] - ) ? new \ArrayObject($data['openapi']['examples']) : null); - } - } - - return $parameters; - } - - private function getPaginationParameters(ResourceMetadata $resourceMetadata, string $operationName): array - { - if (!$this->paginationOptions->isPaginationEnabled()) { - return []; - } - - $parameters = []; - - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_enabled', true, true)) { - $parameters[] = new Model\Parameter($this->paginationOptions->getPaginationPageParameterName(), 'query', 'The collection page number', false, false, true, ['type' => 'integer', 'default' => 1]); - - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->paginationOptions->getClientItemsPerPage(), true)) { - $schema = [ - 'type' => 'integer', - 'default' => $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', 30, true), - 'minimum' => 0, - ]; - - if (null !== $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', null, true)) { - $schema['maximum'] = $maxItemsPerPage; - } - - $parameters[] = new Model\Parameter($this->paginationOptions->getItemsPerPageParameterName(), 'query', 'The number of items per page', false, false, true, $schema); - } - } - - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_enabled', $this->paginationOptions->getPaginationClientEnabled(), true)) { - $parameters[] = new Model\Parameter($this->paginationOptions->getPaginationClientEnabledParameterName(), 'query', 'Enable or disable pagination', false, false, true, ['type' => 'boolean']); - } - - return $parameters; - } - - private function getOauthSecurityScheme(): Model\SecurityScheme - { - $oauthFlow = new Model\OAuthFlow($this->openApiOptions->getOAuthAuthorizationUrl(), $this->openApiOptions->getOAuthTokenUrl(), $this->openApiOptions->getOAuthRefreshUrl(), new \ArrayObject($this->openApiOptions->getOAuthScopes())); - $description = sprintf( - 'OAuth 2.0 %s Grant', - strtolower(preg_replace('/[A-Z]/', ' \\0', lcfirst($this->openApiOptions->getOAuthFlow()))) - ); - $implicit = $password = $clientCredentials = $authorizationCode = null; - - switch ($this->openApiOptions->getOAuthFlow()) { - case 'implicit': - $implicit = $oauthFlow; - break; - case 'password': - $password = $oauthFlow; - break; - case 'application': - case 'clientCredentials': - $clientCredentials = $oauthFlow; - break; - case 'accessCode': - case 'authorizationCode': - $authorizationCode = $oauthFlow; - break; - default: - throw new \LogicException('OAuth flow must be one of: implicit, password, clientCredentials, authorizationCode'); - } - - return new Model\SecurityScheme($this->openApiOptions->getOAuthType(), $description, null, null, null, null, new Model\OAuthFlows($implicit, $password, $clientCredentials, $authorizationCode), null); - } - - private function getSecuritySchemes(): array - { - $securitySchemes = []; - - if ($this->openApiOptions->getOAuthEnabled()) { - $securitySchemes['oauth'] = $this->getOauthSecurityScheme(); - } - - foreach ($this->openApiOptions->getApiKeys() as $key => $apiKey) { - $description = sprintf('Value for the %s %s parameter.', $apiKey['name'], $apiKey['type']); - $securitySchemes[$key] = new Model\SecurityScheme('apiKey', $description, $apiKey['name'], $apiKey['type']); - } - - return $securitySchemes; - } - - private function appendSchemaDefinitions(\ArrayObject $schemas, \ArrayObject $definitions): void - { - foreach ($definitions as $key => $value) { - $schemas[$key] = $value; - } - } - - /** - * @param Model\Parameter[] $parameters - */ - private function hasParameter(Model\Parameter $parameter, array $parameters): bool - { - foreach ($parameters as $existingParameter) { - if ($existingParameter->getName() === $parameter->getName() && $existingParameter->getIn() === $parameter->getIn()) { - return true; - } - } - - return false; - } -} diff --git a/src/Core/OpenApi/Model/Components.php b/src/Core/OpenApi/Model/Components.php deleted file mode 100644 index 0d67b0427f7..00000000000 --- a/src/Core/OpenApi/Model/Components.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Components::class); - -if (false) { - final class Components extends \ApiPlatform\OpenApi\Model\Components - { - } -} diff --git a/src/Core/OpenApi/Model/Contact.php b/src/Core/OpenApi/Model/Contact.php deleted file mode 100644 index 9d581ea108f..00000000000 --- a/src/Core/OpenApi/Model/Contact.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Contact::class); - -if (false) { - final class Contact extends \ApiPlatform\OpenApi\Model\Contact - { - } -} diff --git a/src/Core/OpenApi/Model/Encoding.php b/src/Core/OpenApi/Model/Encoding.php deleted file mode 100644 index bd8e3bcd106..00000000000 --- a/src/Core/OpenApi/Model/Encoding.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Encoding::class); - -if (false) { - final class Encoding extends \ApiPlatform\OpenApi\Model\Encoding - { - } -} diff --git a/src/Core/OpenApi/Model/ExtensionTrait.php b/src/Core/OpenApi/Model/ExtensionTrait.php deleted file mode 100644 index 1c14b40fc2e..00000000000 --- a/src/Core/OpenApi/Model/ExtensionTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\ExtensionTrait::class); - -if (false) { - trait ExtensionTrait - { - use \ApiPlatform\OpenApi\Model\ExtensionTrait; - } -} diff --git a/src/Core/OpenApi/Model/ExternalDocumentation.php b/src/Core/OpenApi/Model/ExternalDocumentation.php deleted file mode 100644 index e5b093f74e1..00000000000 --- a/src/Core/OpenApi/Model/ExternalDocumentation.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\ExternalDocumentation::class); - -if (false) { - final class ExternalDocumentation extends \ApiPlatform\OpenApi\Model\ExternalDocumentation - { - } -} diff --git a/src/Core/OpenApi/Model/Info.php b/src/Core/OpenApi/Model/Info.php deleted file mode 100644 index 5a1bcad4f44..00000000000 --- a/src/Core/OpenApi/Model/Info.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Info::class); - -if (false) { - final class Info extends \ApiPlatform\OpenApi\Model\Info - { - } -} diff --git a/src/Core/OpenApi/Model/License.php b/src/Core/OpenApi/Model/License.php deleted file mode 100644 index 294f1e3ba1e..00000000000 --- a/src/Core/OpenApi/Model/License.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\License::class); - -if (false) { - final class License extends \ApiPlatform\OpenApi\Model\License - { - } -} diff --git a/src/Core/OpenApi/Model/Link.php b/src/Core/OpenApi/Model/Link.php deleted file mode 100644 index 74eeb0cd700..00000000000 --- a/src/Core/OpenApi/Model/Link.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Link::class); - -if (false) { - final class Link extends \ApiPlatform\OpenApi\Model\Link - { - } -} diff --git a/src/Core/OpenApi/Model/MediaType.php b/src/Core/OpenApi/Model/MediaType.php deleted file mode 100644 index 0e097e418f3..00000000000 --- a/src/Core/OpenApi/Model/MediaType.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\MediaType::class); - -if (false) { - final class MediaType extends \ApiPlatform\OpenApi\Model\MediaType - { - } -} diff --git a/src/Core/OpenApi/Model/OAuthFlow.php b/src/Core/OpenApi/Model/OAuthFlow.php deleted file mode 100644 index e87a3070be6..00000000000 --- a/src/Core/OpenApi/Model/OAuthFlow.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\OAuthFlow::class); - -if (false) { - final class OAuthFlow extends \ApiPlatform\OpenApi\Model\OAuthFlow - { - } -} diff --git a/src/Core/OpenApi/Model/OAuthFlows.php b/src/Core/OpenApi/Model/OAuthFlows.php deleted file mode 100644 index 6ad827f3b47..00000000000 --- a/src/Core/OpenApi/Model/OAuthFlows.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\OAuthFlows::class); - -if (false) { - final class OAuthFlows extends \ApiPlatform\OpenApi\Model\OAuthFlows - { - } -} diff --git a/src/Core/OpenApi/Model/Operation.php b/src/Core/OpenApi/Model/Operation.php deleted file mode 100644 index 438d1babbcf..00000000000 --- a/src/Core/OpenApi/Model/Operation.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Operation::class); - -if (false) { - final class Operation extends \ApiPlatform\OpenApi\Model\Operation - { - } -} diff --git a/src/Core/OpenApi/Model/Parameter.php b/src/Core/OpenApi/Model/Parameter.php deleted file mode 100644 index 15cf20105ea..00000000000 --- a/src/Core/OpenApi/Model/Parameter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Parameter::class); - -if (false) { - final class Parameter extends \ApiPlatform\OpenApi\Model\Parameter - { - } -} diff --git a/src/Core/OpenApi/Model/PathItem.php b/src/Core/OpenApi/Model/PathItem.php deleted file mode 100644 index 620b550d86e..00000000000 --- a/src/Core/OpenApi/Model/PathItem.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\PathItem::class); - -if (false) { - final class PathItem extends \ApiPlatform\OpenApi\Model\PathItem - { - } -} diff --git a/src/Core/OpenApi/Model/Paths.php b/src/Core/OpenApi/Model/Paths.php deleted file mode 100644 index 71b34eb4cd5..00000000000 --- a/src/Core/OpenApi/Model/Paths.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Paths::class); - -if (false) { - final class Paths extends \ApiPlatform\OpenApi\Model\Paths - { - } -} diff --git a/src/Core/OpenApi/Model/RequestBody.php b/src/Core/OpenApi/Model/RequestBody.php deleted file mode 100644 index bddb2198353..00000000000 --- a/src/Core/OpenApi/Model/RequestBody.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\RequestBody::class); - -if (false) { - final class RequestBody extends \ApiPlatform\OpenApi\Model\RequestBody - { - } -} diff --git a/src/Core/OpenApi/Model/Response.php b/src/Core/OpenApi/Model/Response.php deleted file mode 100644 index eea31238412..00000000000 --- a/src/Core/OpenApi/Model/Response.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Response::class); - -if (false) { - final class Response extends \ApiPlatform\OpenApi\Model\Response - { - } -} diff --git a/src/Core/OpenApi/Model/Schema.php b/src/Core/OpenApi/Model/Schema.php deleted file mode 100644 index 73a32a49a0c..00000000000 --- a/src/Core/OpenApi/Model/Schema.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Schema::class); - -if (false) { - final class Schema extends \ApiPlatform\OpenApi\Model\Schema - { - } -} diff --git a/src/Core/OpenApi/Model/SecurityScheme.php b/src/Core/OpenApi/Model/SecurityScheme.php deleted file mode 100644 index 8faffa45d28..00000000000 --- a/src/Core/OpenApi/Model/SecurityScheme.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\SecurityScheme::class); - -if (false) { - final class SecurityScheme extends \ApiPlatform\OpenApi\Model\SecurityScheme - { - } -} diff --git a/src/Core/OpenApi/Model/Server.php b/src/Core/OpenApi/Model/Server.php deleted file mode 100644 index a63c045560e..00000000000 --- a/src/Core/OpenApi/Model/Server.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Model; - -class_exists(\ApiPlatform\OpenApi\Model\Server::class); - -if (false) { - final class Server extends \ApiPlatform\OpenApi\Model\Server - { - } -} diff --git a/src/Core/OpenApi/OpenApi.php b/src/Core/OpenApi/OpenApi.php deleted file mode 100644 index 0bd7f40b086..00000000000 --- a/src/Core/OpenApi/OpenApi.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi; - -class_exists(\ApiPlatform\OpenApi\OpenApi::class); - -if (false) { - final class OpenApi extends \ApiPlatform\OpenApi\OpenApi - { - } -} diff --git a/src/Core/OpenApi/Options.php b/src/Core/OpenApi/Options.php deleted file mode 100644 index c82e2176249..00000000000 --- a/src/Core/OpenApi/Options.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi; - -class_exists(\ApiPlatform\OpenApi\Options::class); - -if (false) { - final class Options extends \ApiPlatform\OpenApi\Options - { - } -} diff --git a/src/Core/OpenApi/Serializer/OpenApiNormalizer.php b/src/Core/OpenApi/Serializer/OpenApiNormalizer.php deleted file mode 100644 index 22f696d0643..00000000000 --- a/src/Core/OpenApi/Serializer/OpenApiNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\OpenApi\Serializer; - -class_exists(\ApiPlatform\OpenApi\Serializer\OpenApiNormalizer::class); - -if (false) { - final class OpenApiNormalizer extends \ApiPlatform\OpenApi\Serializer\OpenApiNormalizer - { - } -} diff --git a/src/Core/Operation/DashPathSegmentNameGenerator.php b/src/Core/Operation/DashPathSegmentNameGenerator.php deleted file mode 100644 index f7bfa15455d..00000000000 --- a/src/Core/Operation/DashPathSegmentNameGenerator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Operation; - -class_exists(\ApiPlatform\Operation\DashPathSegmentNameGenerator::class); - -if (false) { - final class DashPathSegmentNameGenerator extends \ApiPlatform\Operation\DashPathSegmentNameGenerator - { - } -} diff --git a/src/Core/Operation/Factory/CachedSubresourceOperationFactory.php b/src/Core/Operation/Factory/CachedSubresourceOperationFactory.php deleted file mode 100644 index fa5ced37a34..00000000000 --- a/src/Core/Operation/Factory/CachedSubresourceOperationFactory.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * 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\Operation\Factory; - -use ApiPlatform\Util\CachedTrait; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @internal - */ -final class CachedSubresourceOperationFactory implements SubresourceOperationFactoryInterface -{ - use CachedTrait; - - public const CACHE_KEY_PREFIX = 'subresource_operations_'; - - private $decorated; - - public function __construct(CacheItemPoolInterface $cacheItemPool, SubresourceOperationFactoryInterface $decorated) - { - $this->cacheItemPool = $cacheItemPool; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): array - { - $cacheKey = self::CACHE_KEY_PREFIX.md5($resourceClass); - - return $this->getCached($cacheKey, function () use ($resourceClass) { - return $this->decorated->create($resourceClass); - }); - } -} diff --git a/src/Core/Operation/Factory/SubresourceOperationFactory.php b/src/Core/Operation/Factory/SubresourceOperationFactory.php deleted file mode 100644 index 2b442ff4806..00000000000 --- a/src/Core/Operation/Factory/SubresourceOperationFactory.php +++ /dev/null @@ -1,214 +0,0 @@ - - * - * 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\Operation\Factory; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Operation\PathSegmentNameGeneratorInterface; - -/** - * @internal - */ -final class SubresourceOperationFactory implements SubresourceOperationFactoryInterface -{ - public const SUBRESOURCE_SUFFIX = '_subresource'; - public const FORMAT_SUFFIX = '.{_format}'; - public const ROUTE_OPTIONS = ['defaults' => [], 'requirements' => [], 'options' => [], 'host' => '', 'schemes' => [], 'condition' => '', 'controller' => null, 'stateless' => null]; - - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $pathSegmentNameGenerator; - private $identifiersExtractor; - - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, PathSegmentNameGeneratorInterface $pathSegmentNameGenerator, IdentifiersExtractorInterface $identifiersExtractor = null) - { - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->pathSegmentNameGenerator = $pathSegmentNameGenerator; - $this->identifiersExtractor = $identifiersExtractor; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass): array - { - $tree = []; - - try { - $this->computeSubresourceOperations($resourceClass, $tree); - } catch (ResourceClassNotFoundException $e) { - return []; - } - - return $tree; - } - - /** - * Handles subresource operations recursively and declare their corresponding routes. - * - * @param string $rootResourceClass null on the first iteration, it then keeps track of the origin resource class - * @param array $parentOperation the previous call operation - * @param int $depth the number of visited - * @param int $maxDepth - */ - private function computeSubresourceOperations(string $resourceClass, array &$tree, string $rootResourceClass = null, array $parentOperation = null, array $visited = [], int $depth = 0, int $maxDepth = null): void - { - if (null === $rootResourceClass) { - $rootResourceClass = $resourceClass; - } - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $property) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $property, ['deprecate' => false]); - - if (!$subresource = $propertyMetadata->getSubresource()) { - continue; - } - - trigger_deprecation('api-platform/core', '2.7', sprintf('A subresource is declared on "%s::%s". Subresources are deprecated, use another #[ApiResource] instead.', $resourceClass, $property)); - $subresourceClass = $subresource->getResourceClass(); - $subresourceMetadata = $this->resourceMetadataFactory->create($subresourceClass); - $subresourceMetadata = $subresourceMetadata->withAttributes(($subresourceMetadata->getAttributes() ?: []) + ['identifiers' => !$this->identifiersExtractor ? [$property] : $this->identifiersExtractor->getIdentifiersFromResourceClass($subresourceClass)]); - $isLastItem = ($parentOperation['resource_class'] ?? null) === $resourceClass && $propertyMetadata->isIdentifier(); - - // A subresource that is also an identifier can't be a start point - if ($isLastItem && (null === $parentOperation || false === $parentOperation['collection'])) { - continue; - } - - $visiting = "$resourceClass $property $subresourceClass"; - - // Handle maxDepth - if (null !== $maxDepth && $depth >= $maxDepth) { - break; - } - if (isset($visited[$visiting])) { - continue; - } - - $rootResourceMetadata = $this->resourceMetadataFactory->create($rootResourceClass); - $rootResourceMetadata = $rootResourceMetadata->withAttributes(($rootResourceMetadata->getAttributes() ?: []) + ['identifiers' => !$this->identifiersExtractor ? ['id'] : $this->identifiersExtractor->getIdentifiersFromResourceClass($rootResourceClass)]); - $operationName = 'get'; - $operation = [ - 'property' => $property, - 'collection' => $subresource->isCollection(), - 'resource_class' => $subresourceClass, - 'shortNames' => [$subresourceMetadata->getShortName()], - 'legacy_filters' => $subresourceMetadata->getAttribute('filters', []), - 'legacy_normalization_context' => $subresourceMetadata->getAttribute('normalization_context', []), - 'legacy_type' => $subresourceMetadata->getIri(), - ]; - - if (null === $parentOperation) { - $identifiers = (array) $rootResourceMetadata->getAttribute('identifiers'); - $rootShortname = $rootResourceMetadata->getShortName(); - $identifier = \is_string($key = array_key_first($identifiers)) ? $key : $identifiers[0]; - $operation['identifiers'][$identifier] = [$rootResourceClass, $identifiers[$identifier][1] ?? $identifier, true]; - $operation['operation_name'] = sprintf( - '%s_%s%s', - RouteNameGenerator::inflector($operation['property'], $operation['collection']), - $operationName, - self::SUBRESOURCE_SUFFIX - ); - - $subresourceOperation = $rootResourceMetadata->getSubresourceOperations()[$operation['operation_name']] ?? []; - - $operation['route_name'] = sprintf( - '%s%s_%s', - RouteNameGenerator::ROUTE_NAME_PREFIX, - RouteNameGenerator::inflector($rootShortname), - $operation['operation_name'] - ); - - $prefix = trim(trim($rootResourceMetadata->getAttribute('route_prefix', '')), '/'); - if ('' !== $prefix) { - $prefix .= '/'; - } - - $operation['path'] = $subresourceOperation['path'] ?? sprintf( - '/%s%s/{%s}/%s%s', - $prefix, - $this->pathSegmentNameGenerator->getSegmentName($rootShortname), - $identifier, - $this->pathSegmentNameGenerator->getSegmentName($operation['property'], $operation['collection']), - self::FORMAT_SUFFIX - ); - - if (!\in_array($rootShortname, $operation['shortNames'], true)) { - $operation['shortNames'][] = $rootShortname; - } - } else { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $identifiers = (array) $resourceMetadata->getAttribute('identifiers', null === $this->identifiersExtractor ? ['id'] : $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)); - $identifier = \is_string($key = array_key_first($identifiers)) ? $key : $identifiers[0]; - $operation['identifiers'] = $parentOperation['identifiers']; - - if (!isset($operation['identifiers'][$parentOperation['property']])) { - $operation['identifiers'][$parentOperation['property']] = [$resourceClass, $identifiers[$identifier][1] ?? $identifier, $isLastItem ? true : $parentOperation['collection']]; - } - - $operation['operation_name'] = str_replace( - 'get'.self::SUBRESOURCE_SUFFIX, - RouteNameGenerator::inflector($isLastItem ? 'item' : $property, $operation['collection']).'_get'.self::SUBRESOURCE_SUFFIX, - $parentOperation['operation_name'] - ); - $operation['route_name'] = str_replace($parentOperation['operation_name'], $operation['operation_name'], $parentOperation['route_name']); - - if (!\in_array($resourceMetadata->getShortName(), $operation['shortNames'], true)) { - $operation['shortNames'][] = $resourceMetadata->getShortName(); - } - - $subresourceOperation = $rootResourceMetadata->getSubresourceOperations()[$operation['operation_name']] ?? []; - - if (isset($subresourceOperation['path'])) { - $operation['path'] = $subresourceOperation['path']; - } else { - $operation['path'] = str_replace(self::FORMAT_SUFFIX, '', (string) $parentOperation['path']); - - if ($parentOperation['collection']) { - $operation['path'] .= sprintf('/{%s}', array_key_last($operation['identifiers'])); - } - - if ($isLastItem) { - $operation['path'] .= self::FORMAT_SUFFIX; - } else { - $operation['path'] .= sprintf('/%s%s', $this->pathSegmentNameGenerator->getSegmentName($property, $operation['collection']), self::FORMAT_SUFFIX); - } - } - } - - if (isset($subresourceOperation['openapi_context'])) { - $operation['openapi_context'] = $subresourceOperation['openapi_context']; - } - - foreach (self::ROUTE_OPTIONS as $routeOption => $defaultValue) { - $operation[$routeOption] = $subresourceOperation[$routeOption] ?? $defaultValue; - } - - $tree[$operation['route_name']] = $operation; - - // Get the minimum maxDepth between the rootMaxDepth and the maxDepth of the to be visited Subresource - $currentMaxDepth = array_filter([$maxDepth, $subresource->getMaxDepth()], 'is_int'); - $currentMaxDepth = empty($currentMaxDepth) ? null : min($currentMaxDepth); - - $this->computeSubresourceOperations($subresourceClass, $tree, $rootResourceClass, $operation, $visited + [$visiting => true], $depth + 1, $currentMaxDepth); - } - } -} diff --git a/src/Core/Operation/Factory/SubresourceOperationFactoryInterface.php b/src/Core/Operation/Factory/SubresourceOperationFactoryInterface.php deleted file mode 100644 index 030c81a07a7..00000000000 --- a/src/Core/Operation/Factory/SubresourceOperationFactoryInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * 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\Operation\Factory; - -/** - * Computes subresource operation for a given resource. - * - * @author Antoine Bluchet - */ -interface SubresourceOperationFactoryInterface -{ - /** - * Creates subresource operations. - */ - public function create(string $resourceClass): array; -} diff --git a/src/Core/Operation/UnderscorePathSegmentNameGenerator.php b/src/Core/Operation/UnderscorePathSegmentNameGenerator.php deleted file mode 100644 index 854d0b08074..00000000000 --- a/src/Core/Operation/UnderscorePathSegmentNameGenerator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Operation; - -class_exists(\ApiPlatform\Operation\UnderscorePathSegmentNameGenerator::class); - -if (false) { - final class UnderscorePathSegmentNameGenerator extends \ApiPlatform\Operation\UnderscorePathSegmentNameGenerator - { - } -} diff --git a/src/Core/PathResolver/CustomOperationPathResolver.php b/src/Core/PathResolver/CustomOperationPathResolver.php deleted file mode 100644 index 6aa963d40fe..00000000000 --- a/src/Core/PathResolver/CustomOperationPathResolver.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\PathResolver; - -class_exists(\ApiPlatform\PathResolver\CustomOperationPathResolver::class); - -if (false) { - final class CustomOperationPathResolver extends \ApiPlatform\PathResolver\CustomOperationPathResolver - { - } -} diff --git a/src/Core/PathResolver/DashOperationPathResolver.php b/src/Core/PathResolver/DashOperationPathResolver.php deleted file mode 100644 index 25810ebea45..00000000000 --- a/src/Core/PathResolver/DashOperationPathResolver.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * 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\PathResolver; - -use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator; -use ApiPlatform\PathResolver\OperationPathResolverInterface; - -/** - * Generates a path with words separated by underscores. - * - * @author Paul Le Corre - * - * @deprecated since version 2.1, to be removed in 3.0. Use {@see \ApiPlatform\Core\Operation\DashPathSegmentNameGenerator} instead. - */ -final class DashOperationPathResolver implements OperationPathResolverInterface -{ - public function __construct() - { - @trigger_error(sprintf('The use of %s is deprecated since 2.1. Please use %s instead.', __CLASS__, DashPathSegmentNameGenerator::class), \E_USER_DEPRECATED); - } - - /** - * {@inheritdoc} - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() >= 4) { - $operationName = func_get_arg(3); - } else { - $operationName = null; - } - - return (new OperationPathResolver(new DashPathSegmentNameGenerator()))->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - } -} diff --git a/src/Core/PathResolver/OperationPathResolver.php b/src/Core/PathResolver/OperationPathResolver.php deleted file mode 100644 index 7ff7f7c7da7..00000000000 --- a/src/Core/PathResolver/OperationPathResolver.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\PathResolver; - -class_exists(\ApiPlatform\PathResolver\OperationPathResolver::class); - -if (false) { - final class OperationPathResolver extends \ApiPlatform\PathResolver\OperationPathResolver - { - } -} diff --git a/src/Core/PathResolver/UnderscoreOperationPathResolver.php b/src/Core/PathResolver/UnderscoreOperationPathResolver.php deleted file mode 100644 index 99615c74adc..00000000000 --- a/src/Core/PathResolver/UnderscoreOperationPathResolver.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * 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\PathResolver; - -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\PathResolver\OperationPathResolverInterface; - -/** - * Generates a path with words separated by underscores. - * - * @author Paul Le Corre - * - * @deprecated since version 2.1, to be removed in 3.0. Use {@see \ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator} instead. - */ -final class UnderscoreOperationPathResolver implements OperationPathResolverInterface -{ - public function __construct() - { - @trigger_error(sprintf('The use of %s is deprecated since 2.1. Please use %s instead.', __CLASS__, UnderscorePathSegmentNameGenerator::class), \E_USER_DEPRECATED); - } - - /** - * {@inheritdoc} - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() >= 4) { - $operationName = func_get_arg(3); - } else { - $operationName = null; - } - - return (new OperationPathResolver(new UnderscorePathSegmentNameGenerator()))->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - } -} diff --git a/src/Core/Problem/Serializer/ConstraintViolationListNormalizer.php b/src/Core/Problem/Serializer/ConstraintViolationListNormalizer.php deleted file mode 100644 index 9b8ff0b88c5..00000000000 --- a/src/Core/Problem/Serializer/ConstraintViolationListNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Problem\Serializer; - -class_exists(\ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer::class); - -if (false) { - final class ConstraintViolationListNormalizer extends \ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer - { - } -} diff --git a/src/Core/Problem/Serializer/ErrorNormalizer.php b/src/Core/Problem/Serializer/ErrorNormalizer.php deleted file mode 100644 index fcd78ee5356..00000000000 --- a/src/Core/Problem/Serializer/ErrorNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Problem\Serializer; - -class_exists(\ApiPlatform\Problem\Serializer\ErrorNormalizer::class); - -if (false) { - final class ErrorNormalizer extends \ApiPlatform\Problem\Serializer\ErrorNormalizer - { - } -} diff --git a/src/Core/Problem/Serializer/ErrorNormalizerTrait.php b/src/Core/Problem/Serializer/ErrorNormalizerTrait.php deleted file mode 100644 index 767688c159f..00000000000 --- a/src/Core/Problem/Serializer/ErrorNormalizerTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Problem\Serializer; - -class_exists(\ApiPlatform\Problem\Serializer\ErrorNormalizerTrait::class); - -if (false) { - trait ErrorNormalizerTrait - { - use \ApiPlatform\Problem\Serializer\ErrorNormalizerTrait; - } -} diff --git a/src/Core/Security/Core/Authorization/ExpressionLanguageProvider.php b/src/Core/Security/Core/Authorization/ExpressionLanguageProvider.php deleted file mode 100644 index 51e66c90598..00000000000 --- a/src/Core/Security/Core/Authorization/ExpressionLanguageProvider.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Security\Core\Authorization; - -class_exists(\ApiPlatform\Symfony\Security\Core\Authorization\ExpressionLanguageProvider::class); - -if (false) { - final class ExpressionLanguageProvider extends \ApiPlatform\Symfony\Security\Core\Authorization\ExpressionLanguageProvider - { - } -} diff --git a/src/Core/Security/EventListener/DenyAccessListener.php b/src/Core/Security/EventListener/DenyAccessListener.php deleted file mode 100644 index db2a9e059bf..00000000000 --- a/src/Core/Security/EventListener/DenyAccessListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Security\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\DenyAccessListener::class); - -if (false) { - final class DenyAccessListener extends \ApiPlatform\Symfony\EventListener\DenyAccessListener - { - } -} diff --git a/src/Core/Security/ExpressionLanguage.php b/src/Core/Security/ExpressionLanguage.php deleted file mode 100644 index 2fb29d73851..00000000000 --- a/src/Core/Security/ExpressionLanguage.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Security; - -class_exists(\ApiPlatform\Symfony\Security\ExpressionLanguage::class); - -if (false) { - class ExpressionLanguage extends \ApiPlatform\Symfony\Security\ExpressionLanguage - { - } -} diff --git a/src/Core/Security/ResourceAccessChecker.php b/src/Core/Security/ResourceAccessChecker.php deleted file mode 100644 index c9990d2ae6e..00000000000 --- a/src/Core/Security/ResourceAccessChecker.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Security; - -class_exists(\ApiPlatform\Symfony\Security\ResourceAccessChecker::class); - -if (false) { - final class ResourceAccessChecker extends \ApiPlatform\Symfony\Security\ResourceAccessChecker - { - } -} diff --git a/src/Core/Serializer/AbstractCollectionNormalizer.php b/src/Core/Serializer/AbstractCollectionNormalizer.php deleted file mode 100644 index a4c82b907a9..00000000000 --- a/src/Core/Serializer/AbstractCollectionNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\AbstractCollectionNormalizer::class); - -if (false) { - class AbstractCollectionNormalizer extends \ApiPlatform\Serializer\AbstractCollectionNormalizer - { - } -} diff --git a/src/Core/Serializer/AbstractConstraintViolationListNormalizer.php b/src/Core/Serializer/AbstractConstraintViolationListNormalizer.php deleted file mode 100644 index 106dc418511..00000000000 --- a/src/Core/Serializer/AbstractConstraintViolationListNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\AbstractConstraintViolationListNormalizer::class); - -if (false) { - class AbstractConstraintViolationListNormalizer extends \ApiPlatform\Serializer\AbstractConstraintViolationListNormalizer - { - } -} diff --git a/src/Core/Serializer/AbstractItemNormalizer.php b/src/Core/Serializer/AbstractItemNormalizer.php deleted file mode 100644 index fcec2177f32..00000000000 --- a/src/Core/Serializer/AbstractItemNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\AbstractItemNormalizer::class); - -if (false) { - class AbstractItemNormalizer extends \ApiPlatform\Serializer\AbstractItemNormalizer - { - } -} diff --git a/src/Core/Serializer/CacheKeyTrait.php b/src/Core/Serializer/CacheKeyTrait.php deleted file mode 100644 index e047229da1d..00000000000 --- a/src/Core/Serializer/CacheKeyTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\CacheKeyTrait::class); - -if (false) { - trait CacheKeyTrait - { - use \ApiPlatform\Serializer\CacheKeyTrait; - } -} diff --git a/src/Core/Serializer/ContextTrait.php b/src/Core/Serializer/ContextTrait.php deleted file mode 100644 index e173d5ae011..00000000000 --- a/src/Core/Serializer/ContextTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\ContextTrait::class); - -if (false) { - trait ContextTrait - { - use \ApiPlatform\Serializer\ContextTrait; - } -} diff --git a/src/Core/Serializer/Filter/GroupFilter.php b/src/Core/Serializer/Filter/GroupFilter.php deleted file mode 100644 index 25abf1d0fd9..00000000000 --- a/src/Core/Serializer/Filter/GroupFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer\Filter; - -class_exists(\ApiPlatform\Serializer\Filter\GroupFilter::class); - -if (false) { - final class GroupFilter extends \ApiPlatform\Serializer\Filter\GroupFilter - { - } -} diff --git a/src/Core/Serializer/Filter/PropertyFilter.php b/src/Core/Serializer/Filter/PropertyFilter.php deleted file mode 100644 index 7e0cc0c46e2..00000000000 --- a/src/Core/Serializer/Filter/PropertyFilter.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer\Filter; - -class_exists(\ApiPlatform\Serializer\Filter\PropertyFilter::class); - -if (false) { - final class PropertyFilter extends \ApiPlatform\Serializer\Filter\PropertyFilter - { - } -} diff --git a/src/Core/Serializer/InputOutputMetadataTrait.php b/src/Core/Serializer/InputOutputMetadataTrait.php deleted file mode 100644 index 0073cc00912..00000000000 --- a/src/Core/Serializer/InputOutputMetadataTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\InputOutputMetadataTrait::class); - -if (false) { - trait InputOutputMetadataTrait - { - use \ApiPlatform\Serializer\InputOutputMetadataTrait; - } -} diff --git a/src/Core/Serializer/ItemNormalizer.php b/src/Core/Serializer/ItemNormalizer.php deleted file mode 100644 index b9ff47a2f9e..00000000000 --- a/src/Core/Serializer/ItemNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\ItemNormalizer::class); - -if (false) { - class ItemNormalizer extends \ApiPlatform\Serializer\ItemNormalizer - { - } -} diff --git a/src/Core/Serializer/JsonEncoder.php b/src/Core/Serializer/JsonEncoder.php deleted file mode 100644 index 3bc790a7429..00000000000 --- a/src/Core/Serializer/JsonEncoder.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\JsonEncoder::class); - -if (false) { - final class JsonEncoder extends \ApiPlatform\Serializer\JsonEncoder - { - } -} diff --git a/src/Core/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Core/Serializer/Mapping/Factory/ClassMetadataFactory.php deleted file mode 100644 index 88245f55bfd..00000000000 --- a/src/Core/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer\Mapping\Factory; - -class_exists(\ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory::class); - -if (false) { - final class ClassMetadataFactory extends \ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory - { - } -} diff --git a/src/Core/Serializer/ResourceList.php b/src/Core/Serializer/ResourceList.php deleted file mode 100644 index 3c992b93f7c..00000000000 --- a/src/Core/Serializer/ResourceList.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\ResourceList::class); - -if (false) { - class ResourceList extends \ApiPlatform\Serializer\ResourceList - { - } -} diff --git a/src/Core/Serializer/SerializerContextBuilder.php b/src/Core/Serializer/SerializerContextBuilder.php deleted file mode 100644 index aaf4f86cc48..00000000000 --- a/src/Core/Serializer/SerializerContextBuilder.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\SerializerContextBuilder::class); - -if (false) { - final class SerializerContextBuilder extends \ApiPlatform\Serializer\SerializerContextBuilder - { - } -} diff --git a/src/Core/Serializer/SerializerFilterContextBuilder.php b/src/Core/Serializer/SerializerFilterContextBuilder.php deleted file mode 100644 index 538503c8baf..00000000000 --- a/src/Core/Serializer/SerializerFilterContextBuilder.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Serializer; - -class_exists(\ApiPlatform\Serializer\SerializerFilterContextBuilder::class); - -if (false) { - final class SerializerFilterContextBuilder extends \ApiPlatform\Serializer\SerializerFilterContextBuilder - { - } -} diff --git a/src/Core/Swagger/Serializer/ApiGatewayNormalizer.php b/src/Core/Swagger/Serializer/ApiGatewayNormalizer.php deleted file mode 100644 index 9d359d15391..00000000000 --- a/src/Core/Swagger/Serializer/ApiGatewayNormalizer.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Swagger\Serializer; - -class_exists(\ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer::class); - -if (false) { - final class ApiGatewayNormalizer extends \ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer - { - } -} diff --git a/src/Core/Swagger/Serializer/DocumentationNormalizer.php b/src/Core/Swagger/Serializer/DocumentationNormalizer.php deleted file mode 100644 index fa3709060fd..00000000000 --- a/src/Core/Swagger/Serializer/DocumentationNormalizer.php +++ /dev/null @@ -1,955 +0,0 @@ - - * - * 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\Swagger\Serializer; - -use ApiPlatform\Api\FilterLocatorTrait; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\UrlGeneratorInterface; -use ApiPlatform\Core\JsonSchema\SchemaFactory as LegacySchemaFactory; -use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface as LegacySchemaFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ApiResourceToLegacyResourceMetadataTrait; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\JsonSchema\Schema; -use ApiPlatform\JsonSchema\SchemaFactory; -use ApiPlatform\JsonSchema\SchemaFactoryInterface; -use ApiPlatform\JsonSchema\TypeFactory; -use ApiPlatform\JsonSchema\TypeFactoryInterface; -use ApiPlatform\Metadata\HttpOperation; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\OpenApi\OpenApi; -use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * Generates an OpenAPI specification (formerly known as Swagger). OpenAPI v2 and v3 are supported. - * - * @author Amrouche Hamza - * @author Teoh Han Hui - * @author Kévin Dunglas - * @author Anthony GRASSIOT - */ -final class DocumentationNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface -{ - use ApiResourceToLegacyResourceMetadataTrait; - use FilterLocatorTrait; - - public const FORMAT = 'json'; - public const BASE_URL = 'base_url'; - public const SPEC_VERSION = 'spec_version'; - public const OPENAPI_VERSION = '3.0.2'; - public const SWAGGER_DEFINITION_NAME = 'swagger_definition_name'; - public const SWAGGER_VERSION = '2.0'; - - /** - * @deprecated - */ - public const ATTRIBUTE_NAME = 'swagger_context'; - - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $operationMethodResolver; - private $operationPathResolver; - private $oauthEnabled; - private $oauthType; - private $oauthFlow; - private $oauthTokenUrl; - private $oauthAuthorizationUrl; - private $oauthScopes; - private $apiKeys; - private $subresourceOperationFactory; - private $paginationEnabled; - private $paginationPageParameterName; - private $clientItemsPerPage; - private $itemsPerPageParameterName; - private $paginationClientEnabled; - private $paginationClientEnabledParameterName; - private $formats; - private $formatsProvider; - - /** - * @var SchemaFactoryInterface|LegacySchemaFactoryInterface - */ - private $jsonSchemaFactory; - /** - * @var TypeFactoryInterface - */ - private $jsonSchemaTypeFactory; - private $defaultContext = [ - self::BASE_URL => '/', - ApiGatewayNormalizer::API_GATEWAY => false, - ]; - - private $identifiersExtractor; - - private $openApiNormalizer; - private $legacyMode; - - /** - * @param LegacySchemaFactoryInterface|SchemaFactoryInterface|ResourceClassResolverInterface|null $jsonSchemaFactory - * @param ContainerInterface|FilterCollection|null $filterLocator - * @param array|OperationAwareFormatsProviderInterface $formats - * @param mixed|null $jsonSchemaTypeFactory - * @param int[] $swaggerVersions - * @param mixed $resourceMetadataFactory - */ - public function __construct($resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, $jsonSchemaFactory = null, $jsonSchemaTypeFactory = null, OperationPathResolverInterface $operationPathResolver = null, UrlGeneratorInterface $urlGenerator = null, $filterLocator = null, NameConverterInterface $nameConverter = null, bool $oauthEnabled = false, string $oauthType = '', string $oauthFlow = '', string $oauthTokenUrl = '', string $oauthAuthorizationUrl = '', array $oauthScopes = [], array $apiKeys = [], SubresourceOperationFactoryInterface $subresourceOperationFactory = null, bool $paginationEnabled = true, string $paginationPageParameterName = 'page', bool $clientItemsPerPage = false, string $itemsPerPageParameterName = 'itemsPerPage', $formats = [], bool $paginationClientEnabled = false, string $paginationClientEnabledParameterName = 'pagination', array $defaultContext = [], array $swaggerVersions = [2, 3], IdentifiersExtractorInterface $identifiersExtractor = null, NormalizerInterface $openApiNormalizer = null, bool $legacyMode = false) - { - if ($jsonSchemaTypeFactory instanceof OperationMethodResolverInterface) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', OperationMethodResolverInterface::class, __METHOD__), \E_USER_DEPRECATED); - - $this->operationMethodResolver = $jsonSchemaTypeFactory; - $this->jsonSchemaTypeFactory = new TypeFactory(); - } else { - $this->jsonSchemaTypeFactory = $jsonSchemaTypeFactory ?? new TypeFactory(); - } - - if ($jsonSchemaFactory instanceof ResourceClassResolverInterface) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', ResourceClassResolverInterface::class, __METHOD__), \E_USER_DEPRECATED); - } - - if (null === $jsonSchemaFactory || $jsonSchemaFactory instanceof ResourceClassResolverInterface) { - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $jsonSchemaFactory = new LegacySchemaFactory($this->jsonSchemaTypeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $nameConverter); - } else { - $jsonSchemaFactory = new SchemaFactory($this->jsonSchemaTypeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $nameConverter); - } - - $this->jsonSchemaTypeFactory->setSchemaFactory($jsonSchemaFactory); - } - $this->jsonSchemaFactory = $jsonSchemaFactory; - - if ($nameConverter) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', NameConverterInterface::class, __METHOD__), \E_USER_DEPRECATED); - } - - if ($urlGenerator) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.1 and will be removed in 3.0.', UrlGeneratorInterface::class, __METHOD__), \E_USER_DEPRECATED); - } - - if ($formats instanceof FormatsProviderInterface) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0, pass an array instead.', FormatsProviderInterface::class, __METHOD__), \E_USER_DEPRECATED); - - $this->formatsProvider = $formats; - } else { - $this->formats = $formats; - } - - $this->setFilterLocator($filterLocator, true); - - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->operationPathResolver = $operationPathResolver; - $this->oauthEnabled = $oauthEnabled; - $this->oauthType = $oauthType; - $this->oauthFlow = $oauthFlow; - $this->oauthTokenUrl = $oauthTokenUrl; - $this->oauthAuthorizationUrl = $oauthAuthorizationUrl; - $this->oauthScopes = $oauthScopes; - $this->subresourceOperationFactory = $subresourceOperationFactory; - $this->paginationEnabled = $paginationEnabled; - $this->paginationPageParameterName = $paginationPageParameterName; - $this->apiKeys = $apiKeys; - $this->clientItemsPerPage = $clientItemsPerPage; - $this->itemsPerPageParameterName = $itemsPerPageParameterName; - $this->paginationClientEnabled = $paginationClientEnabled; - $this->paginationClientEnabledParameterName = $paginationClientEnabledParameterName; - $this->defaultContext[self::SPEC_VERSION] = $swaggerVersions[0] ?? 2; - $this->defaultContext = array_merge($this->defaultContext, $defaultContext); - $this->identifiersExtractor = $identifiersExtractor; - $this->openApiNormalizer = $openApiNormalizer; - $this->legacyMode = $legacyMode; - } - - /** - * {@inheritdoc} - * - * @return array|string|int|float|bool|\ArrayObject|null - */ - public function normalize($object, $format = null, array $context = []) - { - if ($object instanceof OpenApi) { - @trigger_error('Using the swagger DocumentationNormalizer is deprecated in favor of decorating the OpenApiFactory, use the "openapi.backward_compatibility_layer" configuration to change this behavior.', \E_USER_DEPRECATED); - - return $this->openApiNormalizer->normalize($object, $format, $context); - } - - $v3 = 3 === ($context['spec_version'] ?? $this->defaultContext['spec_version']) && !($context['api_gateway'] ?? $this->defaultContext['api_gateway']); - - $definitions = new \ArrayObject(); - $paths = new \ArrayObject(); - $links = new \ArrayObject(); - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - foreach ($object->getResourceNameCollection() as $resourceClass) { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - foreach ($resourceMetadataCollection as $i => $resourceMetadata) { - $resourceMetadata = $this->transformResourceToResourceMetadata($resourceMetadata); - // Items needs to be parsed first to be able to reference the lines from the collection operation - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceMetadata->getShortName(), $resourceMetadata, OperationType::ITEM, $links); - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceMetadata->getShortName(), $resourceMetadata, OperationType::COLLECTION, $links); - } - } - - $definitions->ksort(); - $paths->ksort(); - - return $this->computeDoc($v3, $object, $definitions, $paths, $context); - } - - foreach ($object->getResourceNameCollection() as $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($this->identifiersExtractor) { - $identifiers = []; - if ($resourceMetadata->getItemOperations()) { - $identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass); - } - - $resourceMetadata = $resourceMetadata->withAttributes(($resourceMetadata->getAttributes() ?: []) + ['identifiers' => $identifiers]); - } - $resourceShortName = $resourceMetadata->getShortName(); - - // Items needs to be parsed first to be able to reference the lines from the collection operation - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceShortName, $resourceMetadata, OperationType::ITEM, $links); - $this->addPaths($v3, $paths, $definitions, $resourceClass, $resourceShortName, $resourceMetadata, OperationType::COLLECTION, $links); - - if (null === $this->subresourceOperationFactory) { - continue; - } - - foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $subresourceOperation) { - $method = $resourceMetadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, $subresourceOperation['operation_name'], 'method', 'GET'); - $paths[$this->getPath($subresourceOperation['shortNames'][0], $subresourceOperation['route_name'], $subresourceOperation, OperationType::SUBRESOURCE)][strtolower($method)] = $this->addSubresourceOperation($v3, $subresourceOperation, $definitions, $operationId, $resourceMetadata); - } - } - - $definitions->ksort(); - $paths->ksort(); - - return $this->computeDoc($v3, $object, $definitions, $paths, $context); - } - - /** - * Updates the list of entries in the paths collection. - */ - private function addPaths(bool $v3, \ArrayObject $paths, \ArrayObject $definitions, string $resourceClass, string $resourceShortName, ResourceMetadata $resourceMetadata, string $operationType, \ArrayObject $links) - { - if (null === $operations = OperationType::COLLECTION === $operationType ? $resourceMetadata->getCollectionOperations() : $resourceMetadata->getItemOperations()) { - return; - } - - foreach ($operations as $operationName => $operation) { - if (isset($operation['uri_template'])) { - $path = str_replace('.{_format}', '', $operation['uri_template']); - if (0 !== strpos($path, '/')) { - $path = '/'.$path; - } - } else { - $path = $this->getPath($resourceShortName, $operationName, $operation, $operationType); - } - - if ($this->operationMethodResolver) { - $method = OperationType::ITEM === $operationType ? $this->operationMethodResolver->getItemOperationMethod($resourceClass, $operationName) : $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); - } else { - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); - } - - $paths[$path][strtolower($method)] = $this->getPathOperation($v3, $operationName, $operation, $method, $operationType, $resourceClass, $resourceMetadata, $definitions, $links); - } - } - - /** - * Gets the path for an operation. - * - * If the path ends with the optional _format parameter, it is removed - * as optional path parameters are not yet supported. - * - * @see https://github.com/OAI/OpenAPI-Specification/issues/93 - */ - private function getPath(string $resourceShortName, string $operationName, array $operation, string $operationType): string - { - $path = $this->operationPathResolver->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - - if ('.{_format}' === substr($path, -10)) { - $path = substr($path, 0, -10); - } - - return $path; - } - - /** - * Gets a path Operation Object. - * - * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#operation-object - */ - private function getPathOperation(bool $v3, string $operationName, array $operation, string $method, string $operationType, string $resourceClass, ResourceMetadata $resourceMetadata, \ArrayObject $definitions, \ArrayObject $links): \ArrayObject - { - $pathOperation = new \ArrayObject($operation[$v3 ? 'openapi_context' : 'swagger_context'] ?? []); - $resourceShortName = $resourceMetadata->getShortName(); - $pathOperation['tags'] ?? $pathOperation['tags'] = [$resourceShortName]; - $pathOperation['operationId'] ?? $pathOperation['operationId'] = lcfirst($operationName).ucfirst($resourceShortName).ucfirst($operationType); - if ($v3 && 'GET' === $method && OperationType::ITEM === $operationType && $link = $this->getLinkObject($resourceClass, $pathOperation['operationId'], $this->getPath($resourceShortName, $operationName, $operation, $operationType))) { - $links[$pathOperation['operationId']] = $link; - } - if ($resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', null, true)) { - $pathOperation['deprecated'] = true; - } - - if (null === $this->formatsProvider) { - $requestFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input_formats', [], true); - $responseFormats = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output_formats', [], true); - } else { - $requestFormats = $responseFormats = $this->formatsProvider->getFormatsFromOperation($resourceClass, $operationName, $operationType); - } - - $requestMimeTypes = $this->flattenMimeTypes($requestFormats); - $responseMimeTypes = $this->flattenMimeTypes($responseFormats); - switch ($method) { - case 'GET': - return $this->updateGetOperation($v3, $pathOperation, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); - case 'POST': - return $this->updatePostOperation($v3, $pathOperation, $requestMimeTypes, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions, $links); - case 'PATCH': - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Updates the %s resource.', $resourceShortName); - // no break - case 'PUT': - return $this->updatePutOperation($v3, $pathOperation, $requestMimeTypes, $responseMimeTypes, $operationType, $resourceMetadata, $resourceClass, $resourceShortName, $operationName, $definitions); - case 'DELETE': - return $this->updateDeleteOperation($v3, $pathOperation, $resourceShortName, $operationType, $operationName, $resourceMetadata, $resourceClass); - } - - return $pathOperation; - } - - /** - * @return array the update message as first value, and if the schema is defined as second - */ - private function addSchemas(bool $v3, array $message, \ArrayObject $definitions, string $resourceClass, string $operationType, string $operationName, array $mimeTypes, string $type = Schema::TYPE_OUTPUT, bool $forceCollection = false): array - { - if (!$v3) { - $jsonSchema = $this->getJsonSchema($v3, $definitions, $resourceClass, $type, $operationType, $operationName, 'json', null, $forceCollection); - if (!$jsonSchema->isDefined()) { - return [$message, false]; - } - - $message['schema'] = $jsonSchema->getArrayCopy(false); - - return [$message, true]; - } - - foreach ($mimeTypes as $mimeType => $format) { - $jsonSchema = $this->getJsonSchema($v3, $definitions, $resourceClass, $type, $operationType, $operationName, $format, null, $forceCollection); - if (!$jsonSchema->isDefined()) { - return [$message, false]; - } - - $message['content'][$mimeType] = ['schema' => $jsonSchema->getArrayCopy(false)]; - } - - return [$message, true]; - } - - private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array $mimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions): \ArrayObject - { - $successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200'); - - if (!$v3) { - $pathOperation['produces'] ?? $pathOperation['produces'] = array_keys($mimeTypes); - } - - if (OperationType::COLLECTION === $operationType) { - $outputResourseShortName = $resourceMetadata->getCollectionOperations()[$operationName]['output']['name'] ?? $resourceShortName; - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Retrieves the collection of %s resources.', $outputResourseShortName); - - $successResponse = ['description' => sprintf('%s collection response', $outputResourseShortName)]; - [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $mimeTypes); - - $pathOperation['responses'] ?? $pathOperation['responses'] = [$successStatus => $successResponse]; - - if ( - ($resourceMetadata->getAttributes()['extra_properties']['is_legacy_subresource'] ?? false) || - ($resourceMetadata->getAttributes()['extra_properties']['is_alternate_resource_metadata'] ?? false)) { - // Avoid duplicates parameters when there is a filter on a subresource identifier - $parametersMemory = []; - $pathOperation['parameters'] = []; - - foreach ($resourceMetadata->getAttributes()['identifiers'] as $parameterName => [$class, $identifier]) { - $parameter = ['name' => $parameterName, 'in' => 'path', 'required' => true]; - $v3 ? $parameter['schema'] = ['type' => 'string'] : $parameter['type'] = 'string'; - $pathOperation['parameters'][] = $parameter; - $parametersMemory[] = $parameterName; - } - - if ($parameters = $this->getFiltersParameters($v3, $resourceClass, $operationName, $resourceMetadata)) { - foreach ($parameters as $parameter) { - if (!\in_array($parameter['name'], $parametersMemory, true)) { - $pathOperation['parameters'][] = $parameter; - } - } - } - } else { - $pathOperation['parameters'] ?? $pathOperation['parameters'] = $this->getFiltersParameters($v3, $resourceClass, $operationName, $resourceMetadata); - } - - $this->addPaginationParameters($v3, $resourceMetadata, OperationType::COLLECTION, $operationName, $pathOperation); - - return $pathOperation; - } - - $outputResourseShortName = $resourceMetadata->getItemOperations()[$operationName]['output']['name'] ?? $resourceShortName; - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Retrieves a %s resource.', $outputResourseShortName); - - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata, $resourceClass); - - $successResponse = ['description' => sprintf('%s resource response', $outputResourseShortName)]; - [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $mimeTypes); - - $pathOperation['responses'] ?? $pathOperation['responses'] = [ - $successStatus => $successResponse, - '404' => ['description' => 'Resource not found'], - ]; - - return $pathOperation; - } - - private function addPaginationParameters(bool $v3, ResourceMetadata $resourceMetadata, string $operationType, string $operationName, \ArrayObject $pathOperation) - { - if ($this->paginationEnabled && $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_enabled', true, true)) { - $paginationParameter = [ - 'name' => $this->paginationPageParameterName, - 'in' => 'query', - 'required' => false, - 'description' => 'The collection page number', - ]; - $v3 ? $paginationParameter['schema'] = [ - 'type' => 'integer', - 'default' => 1, - ] : $paginationParameter['type'] = 'integer'; - $pathOperation['parameters'][] = $paginationParameter; - - if ($resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) { - $itemPerPageParameter = [ - 'name' => $this->itemsPerPageParameterName, - 'in' => 'query', - 'required' => false, - 'description' => 'The number of items per page', - ]; - if ($v3) { - $itemPerPageParameter['schema'] = [ - 'type' => 'integer', - 'default' => $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_items_per_page', 30, true), - 'minimum' => 0, - ]; - - $maxItemsPerPage = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'maximum_items_per_page', null, true); - if (null !== $maxItemsPerPage) { - @trigger_error('The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3.', \E_USER_DEPRECATED); - } - $maxItemsPerPage = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage, true); - - if (null !== $maxItemsPerPage) { - $itemPerPageParameter['schema']['maximum'] = $maxItemsPerPage; - } - } else { - $itemPerPageParameter['type'] = 'integer'; - } - - $pathOperation['parameters'][] = $itemPerPageParameter; - } - } - - if ($this->paginationEnabled && $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'pagination_client_enabled', $this->paginationClientEnabled, true)) { - $paginationEnabledParameter = [ - 'name' => $this->paginationClientEnabledParameterName, - 'in' => 'query', - 'required' => false, - 'description' => 'Enable or disable pagination', - ]; - $v3 ? $paginationEnabledParameter['schema'] = ['type' => 'boolean'] : $paginationEnabledParameter['type'] = 'boolean'; - $pathOperation['parameters'][] = $paginationEnabledParameter; - } - } - - /** - * @throws ResourceClassNotFoundException - */ - private function addSubresourceOperation(bool $v3, array $subresourceOperation, \ArrayObject $definitions, string $operationId, ResourceMetadata $resourceMetadata): \ArrayObject - { - $operationName = 'get'; // TODO: we might want to extract that at some point to also support other subresource operations - $collection = $subresourceOperation['collection'] ?? false; - - $subResourceMetadata = $this->resourceMetadataFactory->create($subresourceOperation['resource_class']); - - $pathOperation = new \ArrayObject([]); - $pathOperation['tags'] = $subresourceOperation['shortNames']; - $pathOperation['operationId'] = $operationId; - $pathOperation['summary'] = sprintf('Retrieves %s%s resource%s.', $subresourceOperation['collection'] ? 'the collection of ' : 'a ', $subresourceOperation['shortNames'][0], $subresourceOperation['collection'] ? 's' : ''); - - if (null === $this->formatsProvider) { - // TODO: Subresource operation metadata aren't available by default, for now we have to fallback on default formats. - // TODO: A better approach would be to always populate the subresource operation array. - $subResourceMetadata = $this - ->resourceMetadataFactory - ->create($subresourceOperation['resource_class']); - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $subResourceMetadata = $this->transformResourceToResourceMetadata($subResourceMetadata[0]); - } - - $responseFormats = $subResourceMetadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, $operationName, 'output_formats', $this->formats, true); - } else { - $responseFormats = $this->formatsProvider->getFormatsFromOperation($subresourceOperation['resource_class'], $operationName, OperationType::SUBRESOURCE); - } - - $mimeTypes = $this->flattenMimeTypes($responseFormats); - - if (!$v3) { - $pathOperation['produces'] = array_keys($mimeTypes); - } - - $successResponse = [ - 'description' => sprintf('%s %s response', $subresourceOperation['shortNames'][0], $collection ? 'collection' : 'resource'), - ]; - [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $subresourceOperation['resource_class'], OperationType::SUBRESOURCE, $operationName, $mimeTypes, Schema::TYPE_OUTPUT, $collection); - - $pathOperation['responses'] = ['200' => $successResponse, '404' => ['description' => 'Resource not found']]; - - // Avoid duplicates parameters when there is a filter on a subresource identifier - $parametersMemory = []; - $pathOperation['parameters'] = []; - foreach ($subresourceOperation['identifiers'] as $parameterName => [$class, $identifier, $hasIdentifier]) { - if (false === strpos($subresourceOperation['path'], sprintf('{%s}', $parameterName))) { - continue; - } - - $parameter = ['name' => $parameterName, 'in' => 'path', 'required' => true]; - $v3 ? $parameter['schema'] = ['type' => 'string'] : $parameter['type'] = 'string'; - $pathOperation['parameters'][] = $parameter; - $parametersMemory[] = $parameterName; - } - - if ($parameters = $this->getFiltersParameters($v3, $subresourceOperation['resource_class'], $operationName, $subResourceMetadata)) { - foreach ($parameters as $parameter) { - if (!\in_array($parameter['name'], $parametersMemory, true)) { - $pathOperation['parameters'][] = $parameter; - } - } - } - - if ($subresourceOperation['collection']) { - $this->addPaginationParameters($v3, $subResourceMetadata, OperationType::SUBRESOURCE, $subresourceOperation['operation_name'], $pathOperation); - } - - return $pathOperation; - } - - private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, array $requestMimeTypes, array $responseMimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions, \ArrayObject $links): \ArrayObject - { - if (!$v3) { - $pathOperation['consumes'] ?? $pathOperation['consumes'] = array_keys($requestMimeTypes); - $pathOperation['produces'] ?? $pathOperation['produces'] = array_keys($responseMimeTypes); - } - - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Creates a %s resource.', $resourceShortName); - - $identifiers = (array) $resourceMetadata - ->getTypedOperationAttribute($operationType, $operationName, 'identifiers', [], false); - - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata, $resourceClass, OperationType::ITEM === $operationType ? false : true); - - $successResponse = ['description' => sprintf('%s resource created', $resourceShortName)]; - [$successResponse, $defined] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $responseMimeTypes); - - if ($defined && $v3 && ($links[$key = 'get'.ucfirst($resourceShortName).ucfirst(OperationType::ITEM)] ?? null)) { - $successResponse['links'] = [ucfirst($key) => $links[$key]]; - } - - $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '201') => $successResponse, - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ]; - - return $this->addRequestBody($v3, $pathOperation, $definitions, $resourceClass, $resourceShortName, $operationType, $operationName, $requestMimeTypes); - } - - private function updatePutOperation(bool $v3, \ArrayObject $pathOperation, array $requestMimeTypes, array $responseMimeTypes, string $operationType, ResourceMetadata $resourceMetadata, string $resourceClass, string $resourceShortName, string $operationName, \ArrayObject $definitions): \ArrayObject - { - if (!$v3) { - $pathOperation['consumes'] ?? $pathOperation['consumes'] = array_keys($requestMimeTypes); - $pathOperation['produces'] ?? $pathOperation['produces'] = array_keys($responseMimeTypes); - } - - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Replaces the %s resource.', $resourceShortName); - - $pathOperation = $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata, $resourceClass); - - $successResponse = ['description' => sprintf('%s resource updated', $resourceShortName)]; - [$successResponse] = $this->addSchemas($v3, $successResponse, $definitions, $resourceClass, $operationType, $operationName, $responseMimeTypes); - - $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200') => $successResponse, - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ]; - - return $this->addRequestBody($v3, $pathOperation, $definitions, $resourceClass, $resourceShortName, $operationType, $operationName, $requestMimeTypes, true); - } - - private function addRequestBody(bool $v3, \ArrayObject $pathOperation, \ArrayObject $definitions, string $resourceClass, string $resourceShortName, string $operationType, string $operationName, array $requestMimeTypes, bool $put = false) - { - if (isset($pathOperation['requestBody'])) { - return $pathOperation; - } - - [$message, $defined] = $this->addSchemas($v3, [], $definitions, $resourceClass, $operationType, $operationName, $requestMimeTypes, Schema::TYPE_INPUT); - if (!$defined) { - return $pathOperation; - } - - $description = sprintf('The %s %s resource', $put ? 'updated' : 'new', $resourceShortName); - if ($v3) { - $pathOperation['requestBody'] = $message + ['description' => $description]; - - return $pathOperation; - } - - if (!$this->hasBodyParameter($pathOperation['parameters'] ?? [])) { - $pathOperation['parameters'][] = [ - 'name' => lcfirst($resourceShortName), - 'in' => 'body', - 'description' => $description, - ] + $message; - } - - return $pathOperation; - } - - private function hasBodyParameter(array $parameters): bool - { - foreach ($parameters as $parameter) { - if (\array_key_exists('in', $parameter) && 'body' === $parameter['in']) { - return true; - } - } - - return false; - } - - private function updateDeleteOperation(bool $v3, \ArrayObject $pathOperation, string $resourceShortName, string $operationType, string $operationName, ResourceMetadata $resourceMetadata, string $resourceClass): \ArrayObject - { - $pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Removes the %s resource.', $resourceShortName); - $pathOperation['responses'] ?? $pathOperation['responses'] = [ - (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '204') => ['description' => sprintf('%s resource deleted', $resourceShortName)], - '404' => ['description' => 'Resource not found'], - ]; - - return $this->addItemOperationParameters($v3, $pathOperation, $operationType, $operationName, $resourceMetadata, $resourceClass); - } - - private function addItemOperationParameters(bool $v3, \ArrayObject $pathOperation, string $operationType, string $operationName, ResourceMetadata $resourceMetadata, string $resourceClass, bool $isPost = false): \ArrayObject - { - $identifiers = (array) $resourceMetadata - ->getTypedOperationAttribute($operationType, $operationName, 'identifiers', [], false); - - // Auto-generated routes in API Platform < 2.7 are considered as collection, hotfix this as the OpenApi Factory supports new operations anyways. - // this also fixes a bug where we could not create POST item operations in API P 2.6 - if (OperationType::ITEM === $operationType && $isPost) { - $operationType = OperationType::COLLECTION; - } - - if (!$identifiers && OperationType::COLLECTION !== $operationType) { - try { - $identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass); - } catch (RuntimeException $e) { - // Ignore exception here - } catch (ResourceClassNotFoundException $e) { - if (false === $this->legacyMode) { - // Skipping these, swagger is not compatible with post 2.7 resource metadata - return $pathOperation; - } - throw $e; - } - } - - if (\count($identifiers) > 1 ? $resourceMetadata->getItemOperationAttribute($operationName, 'composite_identifier', true, true) : false) { - $identifiers = ['id']; - } - - if (!$identifiers && OperationType::COLLECTION === $operationType) { - return $pathOperation; - } - - if (!isset($pathOperation['parameters'])) { - $pathOperation['parameters'] = []; - } - - foreach ($identifiers as $parameterName => $identifier) { - $parameter = [ - 'name' => \is_string($parameterName) ? $parameterName : $identifier, - 'in' => 'path', - 'required' => true, - ]; - $v3 ? $parameter['schema'] = ['type' => 'string'] : $parameter['type'] = 'string'; - $pathOperation['parameters'][] = $parameter; - } - - return $pathOperation; - } - - private function getJsonSchema(bool $v3, \ArrayObject $definitions, string $resourceClass, string $type, ?string $operationType, ?string $operationName, string $format = 'json', ?array $serializerContext = null, bool $forceCollection = false): Schema - { - $schema = new Schema($v3 ? Schema::VERSION_OPENAPI : Schema::VERSION_SWAGGER); - $schema->setDefinitions($definitions); - - if ($this->jsonSchemaFactory instanceof SchemaFactoryInterface) { - $operation = $operationName ? (new class() extends HttpOperation {})->withName($operationName) : null; - - return $this->jsonSchemaFactory->buildSchema($resourceClass, $format, $type, $operation, $schema, $serializerContext, $forceCollection); - } - - return $this->jsonSchemaFactory->buildSchema($resourceClass, $format, $type, $operationType, $operationName, $schema, $serializerContext, $forceCollection); - } - - private function computeDoc(bool $v3, Documentation $documentation, \ArrayObject $definitions, \ArrayObject $paths, array $context): array - { - $baseUrl = $context[self::BASE_URL] ?? $this->defaultContext[self::BASE_URL]; - - if ($v3) { - $docs = ['openapi' => self::OPENAPI_VERSION]; - if ('/' !== $baseUrl && '' !== $baseUrl) { - $docs['servers'] = [['url' => $baseUrl]]; - } - } else { - $docs = [ - 'swagger' => self::SWAGGER_VERSION, - 'basePath' => $baseUrl, - ]; - } - - $docs += [ - 'info' => [ - 'title' => $documentation->getTitle(), - 'version' => $documentation->getVersion(), - ], - 'paths' => $paths, - ]; - - if ('' !== $description = $documentation->getDescription()) { - $docs['info']['description'] = $description; - } - - $securityDefinitions = []; - $security = []; - - if ($this->oauthEnabled) { - $oauthAttributes = [ - 'authorizationUrl' => $this->oauthAuthorizationUrl, - 'scopes' => new \ArrayObject($this->oauthScopes), - ]; - - if ($this->oauthTokenUrl) { - $oauthAttributes['tokenUrl'] = $this->oauthTokenUrl; - } - - $securityDefinitions['oauth'] = [ - 'type' => $this->oauthType, - 'description' => sprintf( - 'OAuth 2.0 %s Grant', - strtolower(preg_replace('/[A-Z]/', ' \\0', lcfirst($this->oauthFlow))) - ), - ]; - - if ($v3) { - $securityDefinitions['oauth']['flows'] = [ - $this->oauthFlow => $oauthAttributes, - ]; - } else { - $securityDefinitions['oauth']['flow'] = $this->oauthFlow; - $securityDefinitions['oauth'] = array_merge($securityDefinitions['oauth'], $oauthAttributes); - } - - $security[] = ['oauth' => []]; - } - - foreach ($this->apiKeys as $key => $apiKey) { - $name = $apiKey['name']; - $type = $apiKey['type']; - - $securityDefinitions[$key] = [ - 'type' => 'apiKey', - 'in' => $type, - 'description' => sprintf('Value for the %s %s', $name, 'query' === $type ? sprintf('%s parameter', $type) : $type), - 'name' => $name, - ]; - - $security[] = [$key => []]; - } - - if ($securityDefinitions && $security) { // @phpstan-ignore-line false positive - $docs['security'] = $security; - if (!$v3) { - $docs['securityDefinitions'] = $securityDefinitions; - } - } - - if ($v3) { - if (\count($definitions) + \count($securityDefinitions)) { - $docs['components'] = []; - if (\count($definitions)) { - $docs['components']['schemas'] = $definitions; - } - if (\count($securityDefinitions)) { - $docs['components']['securitySchemes'] = $securityDefinitions; - } - } - } elseif (\count($definitions) > 0) { - $docs['definitions'] = $definitions; - } - - return $docs; - } - - /** - * Gets parameters corresponding to enabled filters. - */ - private function getFiltersParameters(bool $v3, string $resourceClass, string $operationName, ResourceMetadata $resourceMetadata): array - { - if (null === $this->filterLocator) { - return []; - } - - $parameters = []; - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); - foreach ($resourceFilters as $filterId) { - if (!$filter = $this->getFilter($filterId)) { - continue; - } - - foreach ($filter->getDescription($resourceClass) as $name => $data) { - $parameter = [ - 'name' => $name, - 'in' => 'query', - 'required' => $data['required'], - ]; - - $type = \in_array($data['type'], Type::$builtinTypes, true) ? $this->jsonSchemaTypeFactory->getType(new Type($data['type'], false, null, $data['is_collection'] ?? false)) : ['type' => 'string']; - $v3 ? $parameter['schema'] = $type : $parameter += $type; - - if ($v3 && isset($data['schema'])) { - $parameter['schema'] = $data['schema']; - } - - if ('array' === ($type['type'] ?? '')) { - $deepObject = \in_array($data['type'], [Type::BUILTIN_TYPE_ARRAY, Type::BUILTIN_TYPE_OBJECT], true); - - if ($v3) { - $parameter['style'] = $deepObject ? 'deepObject' : 'form'; - $parameter['explode'] = true; - } else { - $parameter['collectionFormat'] = $deepObject ? 'csv' : 'multi'; - } - } - - $key = $v3 ? 'openapi' : 'swagger'; - if (isset($data[$key])) { - $parameter = $data[$key] + $parameter; - } - - $parameters[] = $parameter; - } - } - - return $parameters; - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null): bool - { - return self::FORMAT === $format && ($data instanceof Documentation || $this->openApiNormalizer && $data instanceof OpenApi); - } - - /** - * {@inheritdoc} - */ - public function hasCacheableSupportsMethod(): bool - { - return true; - } - - private function flattenMimeTypes(array $responseFormats): array - { - $responseMimeTypes = []; - foreach ($responseFormats as $responseFormat => $mimeTypes) { - foreach ($mimeTypes as $mimeType) { - $responseMimeTypes[$mimeType] = $responseFormat; - } - } - - return $responseMimeTypes; - } - - /** - * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#linkObject. - */ - private function getLinkObject(string $resourceClass, string $operationId, string $path): array - { - $linkObject = $identifiers = []; - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - if (!$propertyMetadata->isIdentifier()) { - continue; - } - - $linkObject['parameters'][$propertyName] = sprintf('$response.body#/%s', $propertyName); - $identifiers[] = $propertyName; - } - - if (!$linkObject) { - return []; - } - $linkObject['operationId'] = $operationId; - $linkObject['description'] = 1 === \count($identifiers) ? sprintf('The `%1$s` value returned in the response can be used as the `%1$s` parameter in `GET %2$s`.', $identifiers[0], $path) : sprintf('The values returned in the response can be used in `GET %s`.', $path); - - return $linkObject; - } -} diff --git a/src/Core/Test/DoctrineMongoDbOdmFilterTestCase.php b/src/Core/Test/DoctrineMongoDbOdmFilterTestCase.php deleted file mode 100644 index 2a58a772cf8..00000000000 --- a/src/Core/Test/DoctrineMongoDbOdmFilterTestCase.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Test; - -class_exists(\ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase::class); - -if (false) { - class DoctrineMongoDbOdmFilterTestCase extends \ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase - { - } -} diff --git a/src/Core/Test/DoctrineMongoDbOdmSetup.php b/src/Core/Test/DoctrineMongoDbOdmSetup.php deleted file mode 100644 index 87b4cdfd54d..00000000000 --- a/src/Core/Test/DoctrineMongoDbOdmSetup.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Test; - -class_exists(\ApiPlatform\Test\DoctrineMongoDbOdmSetup::class); - -if (false) { - class DoctrineMongoDbOdmSetup extends \ApiPlatform\Test\DoctrineMongoDbOdmSetup - { - } -} diff --git a/src/Core/Test/DoctrineMongoDbOdmTestCase.php b/src/Core/Test/DoctrineMongoDbOdmTestCase.php deleted file mode 100644 index 79cbe9fc64c..00000000000 --- a/src/Core/Test/DoctrineMongoDbOdmTestCase.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Test; - -class_exists(\ApiPlatform\Test\DoctrineMongoDbOdmTestCase::class); - -if (false) { - class DoctrineMongoDbOdmTestCase extends \ApiPlatform\Test\DoctrineMongoDbOdmTestCase - { - } -} diff --git a/src/Core/Test/DoctrineOrmFilterTestCase.php b/src/Core/Test/DoctrineOrmFilterTestCase.php deleted file mode 100644 index 487505038a8..00000000000 --- a/src/Core/Test/DoctrineOrmFilterTestCase.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Test; - -class_exists(\ApiPlatform\Test\DoctrineOrmFilterTestCase::class); - -if (false) { - class DoctrineOrmFilterTestCase extends \ApiPlatform\Test\DoctrineOrmFilterTestCase - { - } -} diff --git a/src/Core/Upgrade/ColorConsoleDiffFormatter.php b/src/Core/Upgrade/ColorConsoleDiffFormatter.php deleted file mode 100644 index c423afaf390..00000000000 --- a/src/Core/Upgrade/ColorConsoleDiffFormatter.php +++ /dev/null @@ -1,119 +0,0 @@ - - * - * 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\Upgrade; - -use Symfony\Component\Console\Formatter\OutputFormatter; - -/** - * Inspired by @see https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/src/Differ/DiffConsoleFormatter.php to be - * used as standalone class, without need to require whole package by Dariusz Rumiński - * Forked by @soyuka from Symplify\PackageBuilder\Console\Formatter to remove Nette\Utils\Strings dependency to be even more standalone. - * - * @see \Symplify\PackageBuilder\Tests\Console\Formatter\ColorConsoleDiffFormatterTest - * - * @internal - */ -final class ColorConsoleDiffFormatter -{ - /** - * @var string - * - * @see https://regex101.com/r/ovLMDF/1 - */ - private const PLUS_START_REGEX = '#^(\+.*)#'; - - /** - * @var string - * - * @see https://regex101.com/r/xwywpa/1 - */ - private const MINUT_START_REGEX = '#^(\-.*)#'; - - /** - * @var string - * - * @see https://regex101.com/r/CMlwa8/1 - */ - private const AT_START_REGEX = '#^(@.*)#'; - - /** - * @var string - * - * @see https://regex101.com/r/qduj2O/1 - */ - private const NEWLINES_REGEX = "#\n\r|\n#"; - - private string $template; - - public function __construct() - { - $this->template = sprintf( - ' ---------- begin diff ----------%s%%s%s ----------- end diff -----------'.\PHP_EOL, - \PHP_EOL, - \PHP_EOL - ); - } - - public function format(string $diff): string - { - return $this->formatWithTemplate($diff, $this->template); - } - - private function formatWithTemplate(string $diff, string $template): string - { - $escapedDiff = OutputFormatter::escape(rtrim($diff)); - - $escapedDiffLines = preg_split(self::NEWLINES_REGEX, $escapedDiff); - - // remove description of added + remove; obvious on diffs - foreach ($escapedDiffLines as $key => $escapedDiffLine) { - if ('--- Original' === $escapedDiffLine) { - unset($escapedDiffLines[$key]); - } - - if ('+++ New' === $escapedDiffLine) { - unset($escapedDiffLines[$key]); - } - } - - $coloredLines = array_map(function (string $string): string { - $string = $this->makePlusLinesGreen($string); - $string = $this->makeMinusLinesRed($string); - $string = $this->makeAtNoteCyan($string); - - if (' ' === $string) { - return ''; - } - - return $string; - }, $escapedDiffLines); - - return sprintf($template, implode(\PHP_EOL, $coloredLines)); - } - - private function makePlusLinesGreen(string $string): string - { - return preg_replace(self::PLUS_START_REGEX, '$1', $string); - } - - private function makeMinusLinesRed(string $string): string - { - return preg_replace(self::MINUT_START_REGEX, '$1', $string); - } - - private function makeAtNoteCyan(string $string): string - { - return preg_replace(self::AT_START_REGEX, '$1', $string); - } -} diff --git a/src/Core/Upgrade/RemoveAnnotationTrait.php b/src/Core/Upgrade/RemoveAnnotationTrait.php deleted file mode 100644 index be49d3ce0ec..00000000000 --- a/src/Core/Upgrade/RemoveAnnotationTrait.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\Upgrade; - -use phpDocumentor\Reflection\DocBlock\Serializer; -use phpDocumentor\Reflection\DocBlockFactory; -use PhpParser\Comment\Doc; - -trait RemoveAnnotationTrait -{ - private function removeAnnotationByTag(Doc $comment, string $tagName): Doc - { - $factory = DocBlockFactory::createInstance(); - $docBlock = $factory->create($comment->getText()); - foreach ($docBlock->getTagsByName($tagName) as $tag) { - $docBlock->removeTag($tag); - } - - $serializer = new Serializer(0, '', true, null, null, \PHP_EOL); - - return new Doc($serializer->getDocComment($docBlock)); - } -} diff --git a/src/Core/Upgrade/SubresourceTransformer.php b/src/Core/Upgrade/SubresourceTransformer.php deleted file mode 100644 index e14dd94d9e9..00000000000 --- a/src/Core/Upgrade/SubresourceTransformer.php +++ /dev/null @@ -1,112 +0,0 @@ - - * - * 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\Upgrade; - -use ApiPlatform\Util\Inflector; -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as ODMClassMetadata; -use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver as ODMAnnotationDriver; -use Doctrine\ODM\MongoDB\Mapping\MappingException as ODMMappingException; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Mapping\Driver\AnnotationDriver; -use Doctrine\ORM\Mapping\MappingException; -use Doctrine\Persistence\Mapping\RuntimeReflectionService; - -final class SubresourceTransformer -{ - private $ormMetadataFactory; - private $odmMetadataFactory; - - public function __construct() - { - $this->ormMetadataFactory = class_exists(AnnotationDriver::class) ? new AnnotationDriver(new AnnotationReader()) : null; - $this->odmMetadataFactory = class_exists(ODMAnnotationDriver::class) ? new ODMAnnotationDriver(new AnnotationReader()) : null; - } - - public function toUriVariables(array $subresourceMetadata): array - { - $uriVariables = []; - $toClass = $subresourceMetadata['resource_class']; - $fromProperty = $subresourceMetadata['property']; - - foreach (array_reverse($subresourceMetadata['identifiers']) as $identifier => $identifiedBy) { - [$fromClass, $fromIdentifier, $fromPathVariable] = $identifiedBy; - $fromClassMetadata = $this->getDoctrineMetadata($fromClass); - $fromClassMetadataAssociationMappings = $fromClassMetadata->associationMappings; - - $uriVariables[$identifier] = [ - 'from_class' => $fromClass, - 'from_property' => null, - 'to_property' => null, - 'identifiers' => $fromPathVariable ? [$fromIdentifier] : [], - 'composite_identifier' => false, - 'expanded_value' => $fromPathVariable ? null : Inflector::tableize($identifier), - ]; - - if ($toClass === $fromClass) { - $fromProperty = $identifier; - continue; - } - - $toClass = $fromClass; - - if (isset($fromProperty, $fromClassMetadataAssociationMappings[$fromProperty])) { - $type = $fromClassMetadataAssociationMappings[$fromProperty]['type']; - if (((class_exists(ODMClassMetadata::class) && ODMClassMetadata::MANY === $type) || (\is_int($type) && $type & ClassMetadataInfo::TO_MANY)) && isset($fromClassMetadataAssociationMappings[$fromProperty]['mappedBy'])) { - $uriVariables[$identifier]['to_property'] = $fromClassMetadataAssociationMappings[$fromProperty]['mappedBy']; - $fromProperty = $identifier; - continue; - } - $uriVariables[$identifier]['from_property'] = $fromProperty; - $fromProperty = $identifier; - } - } - - return array_reverse($uriVariables); - } - - /** - * @return ODMClassMetadata|ClassMetadata - */ - private function getDoctrineMetadata(string $class) - { - if ($this->odmMetadataFactory && class_exists(ODMClassMetadata::class)) { - $isDocument = true; - $metadata = new ODMClassMetadata($class); - - try { - $this->odmMetadataFactory->loadMetadataForClass($class, $metadata); - } catch (ODMMappingException $e) { - $isDocument = false; - } - - if ($isDocument) { - return $metadata; - } - } - - $metadata = new ClassMetadata($class); - $metadata->initializeReflection(new RuntimeReflectionService()); - - try { - if ($this->ormMetadataFactory) { - $this->ormMetadataFactory->loadMetadataForClass($class, $metadata); - } - } catch (MappingException $e) { - } - - return $metadata; - } -} diff --git a/src/Core/Upgrade/UpgradeApiResourceVisitor.php b/src/Core/Upgrade/UpgradeApiResourceVisitor.php deleted file mode 100644 index f88590c74b5..00000000000 --- a/src/Core/Upgrade/UpgradeApiResourceVisitor.php +++ /dev/null @@ -1,444 +0,0 @@ - - * - * 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\Upgrade; - -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource as LegacyApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Delete; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\GraphQl\Mutation; -use ApiPlatform\Metadata\GraphQl\Query; -use ApiPlatform\Metadata\GraphQl\QueryCollection; -use ApiPlatform\Metadata\Link; -use ApiPlatform\Metadata\Patch; -use ApiPlatform\Metadata\Post; -use ApiPlatform\Metadata\Put; -use ApiPlatform\Metadata\Resource\DeprecationMetadataTrait; -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; - -final class UpgradeApiResourceVisitor extends NodeVisitorAbstract -{ - use DeprecationMetadataTrait; - use RemoveAnnotationTrait; - - private LegacyApiResource $resourceAnnotation; - private IdentifiersExtractorInterface $identifiersExtractor; - private bool $isAnnotation = false; - private string $resourceClass; - - public function __construct(LegacyApiResource $resourceAnnotation, bool $isAnnotation, IdentifiersExtractorInterface $identifiersExtractor, string $resourceClass) - { - $this->resourceAnnotation = $resourceAnnotation; - $this->isAnnotation = $isAnnotation; - $this->identifiersExtractor = $identifiersExtractor; - $this->resourceClass = $resourceClass; - } - - /** - * In API Platform 3.x there's no difference between items and collections other then a flag within the Operation - * Therefore we need to fix the behavior with an empty array. - */ - private function getLegacyOperations(bool $isCollection = false): array - { - $key = $isCollection ? 'collectionOperations' : 'itemOperations'; - if ([] === $this->resourceAnnotation->{$key}) { - return []; - } - - $default = $isCollection ? ['post', 'get'] : ['get', 'put', 'patch', 'delete']; - - return $this->resourceAnnotation->{$key} ?? $default; - } - - /** - * @return int|Node|null - */ - public function enterNode(Node $node) - { - // We don't go through every resources to remove ApiSubresource annotations, do this here as well if there are some - // @see UpgradeApiSubresourceVisitor - $comment = $node->getDocComment(); - if ($comment && preg_match('/@ApiSubresource/', $comment->getText())) { - $node->setDocComment($this->removeAnnotationByTag($comment, 'ApiSubresource')); - } - - if ($node instanceof Node\Stmt\Namespace_) { - $namespaces = array_unique(array_merge( - [ApiResource::class], - $this->getOperationsNamespaces($this->getLegacyOperations()), - $this->getOperationsNamespaces($this->getLegacyOperations(true), true), - $this->getGraphQlOperationsNamespaces($this->resourceAnnotation->graphql ?? []) - )); - - if (true === !($this->resourceAnnotation->attributes['composite_identifier'] ?? true)) { - $namespaces[] = Link::class; - } - - foreach ($node->stmts as $k => $stmt) { - if (!$stmt instanceof Node\Stmt\Use_) { - break; - } - - $useStatement = implode('\\', $stmt->uses[0]->name->parts); - - if (LegacyApiResource::class === $useStatement) { - unset($node->stmts[$k]); - continue; - } - - // There might be a use left as the UpgradeApiSubresourceVisitor doesn't go through all the resources - if (ApiSubresource::class === $useStatement) { - unset($node->stmts[$k]); - continue; - } - - if (false !== ($key = array_search($useStatement, $namespaces, true))) { - unset($namespaces[$key]); - } - } - - foreach ($namespaces as $namespace) { - array_unshift($node->stmts, new Node\Stmt\Use_([ - new Node\Stmt\UseUse( - new Node\Name( - $namespace - ) - ), - ])); - } - } - - if ($node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Interface_) { - if ($this->isAnnotation) { - $this->removeAnnotation($node); - } else { - $this->removeAttribute($node); - } - - $arguments = []; - $operations = null === $this->resourceAnnotation->itemOperations && null === $this->resourceAnnotation->collectionOperations ? null : array_merge( - $this->legacyOperationsToOperations($this->getLegacyOperations()), - $this->legacyOperationsToOperations($this->getLegacyOperations(true), true) - ); - - if (null !== $operations) { - $arguments['operations'] = new Node\Expr\Array_( - array_map(function ($value) { - return new Node\Expr\ArrayItem($value); - }, $operations), - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ); - } - - $graphQlOperations = null === $this->resourceAnnotation->graphql ? null : []; - foreach ($this->resourceAnnotation->graphql ?? [] as $operationName => $graphQlOperation) { - if (\is_int($operationName)) { - $ns = $this->getGraphQlOperationNamespace($graphQlOperation); - $graphQlOperations[] = new Node\Expr\New_(new Node\Name($this->getShortName($ns)), $this->arrayToArguments(['name' => $this->valueToNode($graphQlOperation)])); - continue; - } - - $ns = $this->getGraphQlOperationNamespace($operationName, $graphQlOperation); - $args = ['name' => $this->valueToNode($operationName)]; - foreach ($graphQlOperation as $key => $value) { - [$key, $value] = $this->getKeyValue($key, $value); - $args[$key] = $this->valueToNode($value); - } - - $graphQlOperations[] = new Node\Expr\New_(new Node\Name($this->getShortName($ns)), $this->arrayToArguments($args)); - } - - if (null !== $graphQlOperations) { - $arguments['graphQlOperations'] = new Node\Expr\Array_( - array_map(function ($value) { - return new Node\Expr\ArrayItem($value); - }, $graphQlOperations), - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ); - } - - foreach (['shortName', 'description', 'iri'] as $key) { - if (!($value = $this->resourceAnnotation->{$key})) { - continue; - } - - if ('iri' === $key) { - $arguments['types'] = new Node\Expr\Array_([new Node\Expr\ArrayItem( - new Node\Scalar\String_($value) - )], ['kind' => Node\Expr\Array_::KIND_SHORT]); - continue; - } - - $arguments[$key] = new Node\Scalar\String_($value); - } - - foreach ($this->resourceAnnotation->attributes ?? [] as $key => $value) { - if (null === $value) { - continue; - } - - [$key, $value] = $this->getKeyValue($key, $value); - - if ('urlGenerationStrategy' === $key) { - $urlGeneratorInterface = new \ReflectionClass(UrlGeneratorInterface::class); - $urlGeneratorConstants = array_flip($urlGeneratorInterface->getConstants()); - $currentUrlGeneratorConstant = $urlGeneratorConstants[$value]; - - $arguments[$key] = - new Node\Expr\ClassConstFetch( - new Node\Name('UrlGeneratorInterface'), - $currentUrlGeneratorConstant - ); - continue; - } - - if ('compositeIdentifier' === $key) { - if (false !== $value) { - continue; - } - - $identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($this->resourceClass); - $identifierNodeItems = []; - foreach ($identifiers as $identifier) { - $identifierNodes = [ - 'compositeIdentifier' => new Node\Expr\ConstFetch(new Node\Name('false')), - 'fromClass' => new Node\Expr\ClassConstFetch( - new Node\Name( - 'self' - ), - 'class' - ), - 'identifiers' => new Node\Expr\Array_( - [ - new Node\Expr\ArrayItem(new Node\Scalar\String_($identifier)), - ], - ['kind' => Node\Expr\Array_::KIND_SHORT] - ), - ]; - - $identifierNodeItems[] = new Node\Expr\ArrayItem( - new Node\Expr\New_(new Node\Name('Link'), $this->arrayToArguments($identifierNodes)), - new Node\Scalar\String_($identifier) - ); - } - - $arguments['uriVariables'] = new Node\Expr\Array_($identifierNodeItems, ['kind' => Node\Expr\Array_::KIND_SHORT]); - continue; - } - - $arguments[$key] = $this->valueToNode($value); - } - - $apiResourceAttribute = - new Node\AttributeGroup([ - new Node\Attribute( - new Node\Name('ApiResource'), - $this->arrayToArguments($arguments) - ), - ]); - - array_unshift($node->attrGroups, $apiResourceAttribute); - } - } - - private function getGraphQlOperationNamespace(string $operationName, array $operation = []): string - { - switch ($operationName) { - case 'item_query': - return Query::class; - case 'collection_query': - return QueryCollection::class; - case 'update': - return Mutation::class; - case 'delete': - return Mutation::class; - case 'create': - return Mutation::class; - default: - if (isset($operation['item_query'])) { - return Query::class; - } - - if (isset($operation['collection_query'])) { - return QueryCollection::class; - } - - if (isset($operation['mutation'])) { - return Mutation::class; - } - - throw new \LogicException(sprintf('The graphql operation %s is not following API Platform naming convention.', $operationName)); - } - } - - private function getOperationNamespace(string $method, bool $isCollection = false): string - { - switch ($method) { - case 'POST': - return Post::class; - case 'PUT': - return Put::class; - case 'PATCH': - return Patch::class; - case 'DELETE': - return Delete::class; - default: - return $isCollection ? GetCollection::class : Get::class; - } - } - - private function getGraphQlOperationsNamespaces(array $operations): array - { - $namespaces = []; - foreach ($operations as $operationName => $operation) { - if (\is_string($operationName)) { - $namespaces[] = $this->getGraphQlOperationNamespace($operationName, $operation); - continue; - } - - $namespaces[] = $this->getGraphQlOperationNamespace($operation); - } - - return $namespaces; - } - - private function getOperationsNamespaces(array $operations, bool $isCollection = false): array - { - $namespaces = []; - foreach ($operations as $operationName => $operation) { - if (\is_string($operationName)) { - $namespaces[] = $this->getOperationNamespace($operation['method'] ?? strtoupper($operationName), $isCollection); - continue; - } - - $method = \is_string($operation) ? strtoupper($operation) : $operation['method']; - $namespaces[] = $this->getOperationNamespace($method, $isCollection); - } - - return $namespaces; - } - - /** - * @return Node\Arg[] - */ - private function arrayToArguments(array $arguments) - { - $args = []; - foreach ($arguments as $key => $value) { - $args[] = new Node\Arg($value, false, false, [], new Node\Identifier($key)); - } - - return $args; - } - - private function removeAttribute(Node\Stmt\Class_|Node\Stmt\Interface_ $node) - { - foreach ($node->attrGroups as $k => $attrGroupNode) { - foreach ($attrGroupNode->attrs as $i => $attribute) { - if (str_ends_with(implode('\\', $attribute->name->parts), 'ApiResource')) { - unset($node->attrGroups[$k]); - break; - } - } - } - } - - private function removeAnnotation(Node\Stmt\Class_|Node\Stmt\Interface_ $node) - { - $comment = $node->getDocComment(); - - if (preg_match('/@ApiResource/', $comment->getText())) { - $node->setDocComment($this->removeAnnotationByTag($comment, 'ApiResource')); - } - } - - private function valueToNode(mixed $value) - { - if (\is_string($value)) { - if (class_exists($value)) { - return new Node\Expr\ClassConstFetch(new Node\Name($this->getShortName($value)), 'class'); - } - - return new Node\Scalar\String_($value); - } - - if (\is_bool($value)) { - return new Node\Expr\ConstFetch(new Node\Name($value ? 'true' : 'false')); - } - - if (is_numeric($value)) { - return \is_int($value) ? new Node\Scalar\LNumber($value) : new Node\Scalar\DNumber($value); - } - - if (\is_array($value)) { - return new Node\Expr\Array_( - array_map(function ($key, $value) { - return new Node\Expr\ArrayItem( - $this->valueToNode($value), - \is_string($key) ? $this->valueToNode($key) : null, - ); - }, array_keys($value), array_values($value)), - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ); - } - } - - private function getShortName(string $class): string - { - if (false !== $pos = strrpos($class, '\\')) { - return substr($class, $pos + 1); - } - - return $class; - } - - private function createOperation(string $namespace, array $arguments = []) - { - $args = []; - foreach ($arguments as $key => $value) { - [$key, $value] = $this->getKeyValue($key, $value); - $args[$key] = $this->valueToNode($value); - } - - return new Node\Expr\New_(new Node\Name($this->getShortName($namespace)), $this->arrayToArguments($args)); - } - - private function legacyOperationsToOperations($legacyOperations, bool $isCollection = false) - { - $operations = []; - foreach ($legacyOperations as $operationName => $operation) { - if (\is_int($operationName)) { - $operations[] = $this->createOperation($this->getOperationNamespace(strtoupper($operation), $isCollection)); - continue; - } - - $method = $operation['method'] ?? strtoupper($operationName); - unset($operation['method']); - $operations[] = $this->createOperation($this->getOperationNamespace($method, $isCollection), $operation); - } - - return $operations; - } -} diff --git a/src/Core/Upgrade/UpgradeApiSubresourceVisitor.php b/src/Core/Upgrade/UpgradeApiSubresourceVisitor.php deleted file mode 100644 index 087160db7d4..00000000000 --- a/src/Core/Upgrade/UpgradeApiSubresourceVisitor.php +++ /dev/null @@ -1,301 +0,0 @@ - - * - * 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\Upgrade; - -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiSubresource; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Link; -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; -use ReflectionClass; - -final class UpgradeApiSubresourceVisitor extends NodeVisitorAbstract -{ - use RemoveAnnotationTrait; - private $subresourceMetadata; - private $referenceType; - - public function __construct($subresourceMetadata, $referenceType) - { - $this->subresourceMetadata = $subresourceMetadata; - $this->referenceType = $referenceType; - } - - /** - * @return int|Node|null - */ - public function enterNode(Node $node) - { - $operationToCreate = $this->subresourceMetadata['collection'] ? GetCollection::class : Get::class; - $operationUseStatementNeeded = true; - $apiResourceUseStatementNeeded = true; - $linkUseStatementNeeded = true; - - $comment = $node->getDocComment(); - if ($comment && preg_match('/@ApiSubresource/', $comment->getText())) { - $node->setDocComment($this->removeAnnotationByTag($comment, 'ApiSubresource')); - } - - if ($node instanceof Node\Stmt\Namespace_) { - foreach ($node->stmts as $i => $stmt) { - if (!$stmt instanceof Node\Stmt\Use_) { - break; - } - - $useStatement = implode('\\', $stmt->uses[0]->name->parts); - if (ApiSubresource::class === $useStatement) { - unset($node->stmts[$i]); - } - - if (ApiResource::class === $useStatement) { - $apiResourceUseStatementNeeded = false; - continue; - } - - if (Link::class === $useStatement) { - $linkUseStatementNeeded = false; - continue; - } - - if ($useStatement === $operationToCreate) { - $operationUseStatementNeeded = false; - continue; - } - } - - if ($operationUseStatementNeeded) { - array_unshift( - $node->stmts, - new Node\Stmt\Use_([ - new Node\Stmt\UseUse( - new Node\Name( - $this->subresourceMetadata['collection'] ? GetCollection::class : Get::class - ) - ), - ]) - ); - } - - if ($apiResourceUseStatementNeeded) { - array_unshift( - $node->stmts, - new Node\Stmt\Use_([ - new Node\Stmt\UseUse( - new Node\Name( - ApiResource::class - ) - ), - ]) - ); - } - - if ($linkUseStatementNeeded) { - array_unshift( - $node->stmts, - new Node\Stmt\Use_([ - new Node\Stmt\UseUse( - new Node\Name( - Link::class - ) - ), - ]) - ); - } - } - - if ($node instanceof Node\Stmt\Class_) { - $identifiersNodeItems = []; - - foreach ($this->subresourceMetadata['uri_variables'] as $identifier => $resource) { - $identifierNodes = [ - 'fromClass' => new Node\Expr\ClassConstFetch( - new Node\Name( - ($resource['from_class'] === $this->subresourceMetadata['resource_class']) ? 'self' : '\\'.$resource['from_class'] - ), - 'class' - ), - 'identifiers' => new Node\Expr\Array_( - isset($resource['identifiers'][0]) ? [ - new Node\Expr\ArrayItem(new Node\Scalar\String_($resource['identifiers'][0])), - ] : [], - ['kind' => Node\Expr\Array_::KIND_SHORT] - ), - ]; - - if (isset($resource['expanded_value'])) { - $identifierNodes['expandedValue'] = new Node\Scalar\String_($resource['expanded_value']); - } - - if (isset($resource['from_property']) || isset($resource['to_property'])) { - $identifierNodes[isset($resource['to_property']) ? 'toProperty' : 'fromProperty'] = new Node\Scalar\String_($resource['to_property'] ?? $resource['from_property']); - } - - $identifierNodeItems[] = new Node\Expr\ArrayItem( - new Node\Expr\New_(new Node\Name('Link'), $this->arrayToArguments($identifierNodes)), - new Node\Scalar\String_($identifier) - ); - } - - $arguments = [ - new Node\Arg( - new Node\Scalar\String_($this->subresourceMetadata['path']), - false, - false, - [], - new Node\Identifier('uriTemplate') - ), - new Node\Arg( - new Node\Expr\Array_($identifierNodeItems, ['kind' => Node\Expr\Array_::KIND_SHORT]), - false, - false, - [], - new Node\Identifier('uriVariables') - ), - new Node\Arg( - new Node\Scalar\LNumber(200), - false, - false, - [], - new Node\Identifier('status') - ), - ]; - - if (null !== $this->referenceType) { - $urlGeneratorInterface = new ReflectionClass(UrlGeneratorInterface::class); - $urlGeneratorConstants = array_flip($urlGeneratorInterface->getConstants()); - $currentUrlGeneratorConstant = $urlGeneratorConstants[$this->referenceType]; - - $arguments[] = new Node\Arg( - new Node\Expr\ClassConstFetch( - new Node\Name('UrlGeneratorInterface'), - $currentUrlGeneratorConstant - ), - false, - false, - [], - new Node\Identifier('urlGenerationStrategy') - ); - } - - if ($this->subresourceMetadata['legacy_type'] ?? false) { - $arguments[] = new Node\Arg( - new Node\Expr\ArrayItem( - new Node\Expr\Array_( - [ - new Node\Expr\ArrayItem( - new Node\Scalar\String_($this->subresourceMetadata['legacy_type']) - ), - ], - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ) - ), - false, - false, - [], - new Node\Identifier('types') - ); - } - - if ($this->subresourceMetadata['legacy_filters'] ?? false) { - $arguments[] = new Node\Arg( - new Node\Expr\ArrayItem( - new Node\Expr\Array_( - array_map(function ($filter) { - return new Node\Expr\ArrayItem( - new Node\Scalar\String_($filter) - ); - }, $this->subresourceMetadata['legacy_filters']), - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ) - ), - false, - false, - [], - new Node\Identifier('filters') - ); - } - - if ($this->subresourceMetadata['legacy_normalization_context']['groups'] ?? false) { - $arguments[] = new Node\Arg( - new Node\Expr\ArrayItem( - new Node\Expr\Array_([ - new Node\Expr\ArrayItem( - new Node\Expr\Array_( - array_map(function ($group) { - return new Node\Expr\ArrayItem(new Node\Scalar\String_($group)); - }, $this->subresourceMetadata['legacy_normalization_context']['groups']), - ['kind' => Node\Expr\Array_::KIND_SHORT] - ), - new Node\Scalar\String_('groups') - ), - ], ['kind' => Node\Expr\Array_::KIND_SHORT]) - ), - false, - false, - [], - new Node\Identifier('normalizationContext') - ); - } - - $arguments[] = new Node\Arg( - new Node\Expr\Array_( - [ - new Node\Expr\ArrayItem( - new Node\Expr\New_( - new Node\Name($this->subresourceMetadata['collection'] ? 'GetCollection' : 'Get') - ), - ), - ], - [ - 'kind' => Node\Expr\Array_::KIND_SHORT, - ] - ), - false, - false, - [], - new Node\Identifier('operations') - ); - - $apiResourceAttribute = - new Node\AttributeGroup([ - new Node\Attribute( - new Node\Name('ApiResource'), - $arguments - ), - ]); - - $node->attrGroups[] = $apiResourceAttribute; - } - } - - /** - * @return Node\Arg[] - */ - private function arrayToArguments(array $arguments) - { - $args = []; - foreach ($arguments as $key => $value) { - $args[] = new Node\Arg($value, false, false, [], new Node\Identifier($key)); - } - - return $args; - } -} diff --git a/src/Core/Util/AnnotationFilterExtractorTrait.php b/src/Core/Util/AnnotationFilterExtractorTrait.php deleted file mode 100644 index 62498a53fb1..00000000000 --- a/src/Core/Util/AnnotationFilterExtractorTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\AnnotationFilterExtractorTrait::class); - -if (false) { - trait AnnotationFilterExtractorTrait - { - use \ApiPlatform\Util\AnnotationFilterExtractorTrait; - } -} diff --git a/src/Core/Util/ArrayTrait.php b/src/Core/Util/ArrayTrait.php deleted file mode 100644 index 2fc3bc81c37..00000000000 --- a/src/Core/Util/ArrayTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\ArrayTrait::class); - -if (false) { - trait ArrayTrait - { - use \ApiPlatform\Util\ArrayTrait; - } -} diff --git a/src/Core/Util/AttributesExtractor.php b/src/Core/Util/AttributesExtractor.php deleted file mode 100644 index 1ef911cca26..00000000000 --- a/src/Core/Util/AttributesExtractor.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\AttributesExtractor::class); - -if (false) { - final class AttributesExtractor extends \ApiPlatform\Util\AttributesExtractor - { - } -} diff --git a/src/Core/Util/ClassInfoTrait.php b/src/Core/Util/ClassInfoTrait.php deleted file mode 100644 index 9fc3fb7751b..00000000000 --- a/src/Core/Util/ClassInfoTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\ClassInfoTrait::class); - -if (false) { - trait ClassInfoTrait - { - use \ApiPlatform\Util\ClassInfoTrait; - } -} diff --git a/src/Core/Util/ClientTrait.php b/src/Core/Util/ClientTrait.php deleted file mode 100644 index 376776f80f7..00000000000 --- a/src/Core/Util/ClientTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\ClientTrait::class); - -if (false) { - trait ClientTrait - { - use \ApiPlatform\Util\ClientTrait; - } -} diff --git a/src/Core/Util/CloneTrait.php b/src/Core/Util/CloneTrait.php deleted file mode 100644 index a2a221b85b3..00000000000 --- a/src/Core/Util/CloneTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\CloneTrait::class); - -if (false) { - trait CloneTrait - { - use \ApiPlatform\Util\CloneTrait; - } -} diff --git a/src/Core/Util/CorsTrait.php b/src/Core/Util/CorsTrait.php deleted file mode 100644 index 7b66cb2697b..00000000000 --- a/src/Core/Util/CorsTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\CorsTrait::class); - -if (false) { - trait CorsTrait - { - use \ApiPlatform\Util\CorsTrait; - } -} diff --git a/src/Core/Util/ErrorFormatGuesser.php b/src/Core/Util/ErrorFormatGuesser.php deleted file mode 100644 index 5bc6fb11b0e..00000000000 --- a/src/Core/Util/ErrorFormatGuesser.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\ErrorFormatGuesser::class); - -if (false) { - final class ErrorFormatGuesser extends \ApiPlatform\Util\ErrorFormatGuesser - { - } -} diff --git a/src/Core/Util/Inflector.php b/src/Core/Util/Inflector.php deleted file mode 100644 index ab2ec6ca1f4..00000000000 --- a/src/Core/Util/Inflector.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\Inflector::class); - -if (false) { - final class Inflector extends \ApiPlatform\Util\Inflector - { - } -} diff --git a/src/Core/Util/IriHelper.php b/src/Core/Util/IriHelper.php deleted file mode 100644 index aca7d8dfd23..00000000000 --- a/src/Core/Util/IriHelper.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\IriHelper::class); - -if (false) { - final class IriHelper extends \ApiPlatform\Util\IriHelper - { - } -} diff --git a/src/Core/Util/Reflection.php b/src/Core/Util/Reflection.php deleted file mode 100644 index 2e4910c4321..00000000000 --- a/src/Core/Util/Reflection.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\Reflection::class); - -if (false) { - final class Reflection extends \ApiPlatform\Util\Reflection - { - } -} diff --git a/src/Core/Util/ReflectionClassRecursiveIterator.php b/src/Core/Util/ReflectionClassRecursiveIterator.php deleted file mode 100644 index 56504a2c544..00000000000 --- a/src/Core/Util/ReflectionClassRecursiveIterator.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\ReflectionClassRecursiveIterator::class); - -if (false) { - final class ReflectionClassRecursiveIterator extends \ApiPlatform\Util\ReflectionClassRecursiveIterator - { - } -} diff --git a/src/Core/Util/RequestAttributesExtractor.php b/src/Core/Util/RequestAttributesExtractor.php deleted file mode 100644 index cb834b5d9f6..00000000000 --- a/src/Core/Util/RequestAttributesExtractor.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\RequestAttributesExtractor::class); - -if (false) { - final class RequestAttributesExtractor extends \ApiPlatform\Util\RequestAttributesExtractor - { - } -} diff --git a/src/Core/Util/RequestParser.php b/src/Core/Util/RequestParser.php deleted file mode 100644 index db51ba35427..00000000000 --- a/src/Core/Util/RequestParser.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\RequestParser::class); - -if (false) { - final class RequestParser extends \ApiPlatform\Util\RequestParser - { - } -} diff --git a/src/Core/Util/ResourceClassInfoTrait.php b/src/Core/Util/ResourceClassInfoTrait.php deleted file mode 100644 index ab7bbc12c28..00000000000 --- a/src/Core/Util/ResourceClassInfoTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\ResourceClassInfoTrait::class); - -if (false) { - trait ResourceClassInfoTrait - { - use \ApiPlatform\Util\ResourceClassInfoTrait; - } -} diff --git a/src/Core/Util/ResponseTrait.php b/src/Core/Util/ResponseTrait.php deleted file mode 100644 index 8df237ceb58..00000000000 --- a/src/Core/Util/ResponseTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\ResponseTrait::class); - -if (false) { - trait ResponseTrait - { - use \ApiPlatform\Util\ResponseTrait; - } -} diff --git a/src/Core/Util/SortTrait.php b/src/Core/Util/SortTrait.php deleted file mode 100644 index 0367e29b6fb..00000000000 --- a/src/Core/Util/SortTrait.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * 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\Util; - -class_exists(\ApiPlatform\Util\SortTrait::class); - -if (false) { - trait SortTrait - { - use \ApiPlatform\Util\SortTrait; - } -} diff --git a/src/Core/Validator/EventListener/ValidateListener.php b/src/Core/Validator/EventListener/ValidateListener.php deleted file mode 100644 index b5b9ae12341..00000000000 --- a/src/Core/Validator/EventListener/ValidateListener.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Validator\EventListener; - -class_exists(\ApiPlatform\Symfony\EventListener\ValidateListener::class); - -if (false) { - final class ValidateListener extends \ApiPlatform\Symfony\EventListener\ValidateListener - { - } -} diff --git a/src/Core/Validator/Exception/ValidationException.php b/src/Core/Validator/Exception/ValidationException.php deleted file mode 100644 index a18f4def1f6..00000000000 --- a/src/Core/Validator/Exception/ValidationException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * 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\Validator\Exception; - -class_exists(\ApiPlatform\Validator\Exception\ValidationException::class); - -if (false) { - class ValidationException extends \ApiPlatform\Validator\Exception\ValidationException - { - } -} diff --git a/tests/Action/EntrypointActionTest.php b/tests/Action/EntrypointActionTest.php index 1ee49540df1..102dd38fd3d 100644 --- a/tests/Action/EntrypointActionTest.php +++ b/tests/Action/EntrypointActionTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Action\EntrypointAction; use ApiPlatform\Api\Entrypoint; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use PHPUnit\Framework\TestCase; diff --git a/tests/Action/ExceptionActionTest.php b/tests/Action/ExceptionActionTest.php index a33229d637d..3431d32f4dc 100644 --- a/tests/Action/ExceptionActionTest.php +++ b/tests/Action/ExceptionActionTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Action\ExceptionAction; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; diff --git a/tests/Api/IdentifiersExtractorTest.php b/tests/Api/IdentifiersExtractorTest.php index 762d699d32b..72baaea9662 100644 --- a/tests/Api/IdentifiersExtractorTest.php +++ b/tests/Api/IdentifiersExtractorTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\IdentifiersExtractor; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Link; diff --git a/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php b/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php index c076153b81a..746e64a844e 100644 --- a/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php +++ b/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/Core/Behat/CommandContext.php b/tests/Behat/CommandContext.php similarity index 98% rename from tests/Core/Behat/CommandContext.php rename to tests/Behat/CommandContext.php index c1417b51443..5afe54b009e 100644 --- a/tests/Core/Behat/CommandContext.php +++ b/tests/Behat/CommandContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Gherkin\Node\PyStringNode; diff --git a/tests/Core/Behat/CoverageContext.php b/tests/Behat/CoverageContext.php similarity index 97% rename from tests/Core/Behat/CoverageContext.php rename to tests/Behat/CoverageContext.php index 2143d4e6bf1..ed16a536527 100644 --- a/tests/Core/Behat/CoverageContext.php +++ b/tests/Behat/CoverageContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; diff --git a/tests/Core/Behat/DoctrineContext.php b/tests/Behat/DoctrineContext.php similarity index 99% rename from tests/Core/Behat/DoctrineContext.php rename to tests/Behat/DoctrineContext.php index 7707d44e478..cea400d57ba 100644 --- a/tests/Core/Behat/DoctrineContext.php +++ b/tests/Behat/DoctrineContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\EntityManager; use ApiPlatform\Tests\Fixtures\TestBundle\Document\AbsoluteUrlDummy as AbsoluteUrlDummyDocument; diff --git a/tests/Core/Behat/ElasticsearchContext.php b/tests/Behat/ElasticsearchContext.php similarity index 98% rename from tests/Core/Behat/ElasticsearchContext.php rename to tests/Behat/ElasticsearchContext.php index 94a185f86e0..a11435d0889 100644 --- a/tests/Core/Behat/ElasticsearchContext.php +++ b/tests/Behat/ElasticsearchContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use Behat\Behat\Context\Context; diff --git a/tests/Core/Behat/GraphqlContext.php b/tests/Behat/GraphqlContext.php similarity index 99% rename from tests/Core/Behat/GraphqlContext.php rename to tests/Behat/GraphqlContext.php index a0621f3996c..73e90212104 100644 --- a/tests/Core/Behat/GraphqlContext.php +++ b/tests/Behat/GraphqlContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; diff --git a/tests/Core/Behat/HttpCacheContext.php b/tests/Behat/HttpCacheContext.php similarity index 96% rename from tests/Core/Behat/HttpCacheContext.php rename to tests/Behat/HttpCacheContext.php index 26e49e83e20..5eb40c5f4eb 100644 --- a/tests/Core/Behat/HttpCacheContext.php +++ b/tests/Behat/HttpCacheContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use PHPUnit\Framework\ExpectationFailedException; diff --git a/tests/Core/Behat/HydraContext.php b/tests/Behat/HydraContext.php similarity index 99% rename from tests/Core/Behat/HydraContext.php rename to tests/Behat/HydraContext.php index 9ac151d6148..27fe569cb0c 100644 --- a/tests/Core/Behat/HydraContext.php +++ b/tests/Behat/HydraContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; diff --git a/tests/Core/Behat/JsonApiContext.php b/tests/Behat/JsonApiContext.php similarity index 99% rename from tests/Core/Behat/JsonApiContext.php rename to tests/Behat/JsonApiContext.php index 87855f328bb..e4c17635e87 100644 --- a/tests/Core/Behat/JsonApiContext.php +++ b/tests/Behat/JsonApiContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use ApiPlatform\Tests\Fixtures\TestBundle\Document\CircularReference as CircularReferenceDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyFriend as DummyFriendDocument; diff --git a/tests/Core/Behat/JsonContext.php b/tests/Behat/JsonContext.php similarity index 98% rename from tests/Core/Behat/JsonContext.php rename to tests/Behat/JsonContext.php index 944dcec738d..059df954d78 100644 --- a/tests/Core/Behat/JsonContext.php +++ b/tests/Behat/JsonContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; use Behat\Gherkin\Node\PyStringNode; diff --git a/tests/Core/Behat/JsonHalContext.php b/tests/Behat/JsonHalContext.php similarity index 98% rename from tests/Core/Behat/JsonHalContext.php rename to tests/Behat/JsonHalContext.php index fdab6e63737..f1f3c890fdf 100644 --- a/tests/Core/Behat/JsonHalContext.php +++ b/tests/Behat/JsonHalContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; diff --git a/tests/Core/Behat/MercureContext.php b/tests/Behat/MercureContext.php similarity index 97% rename from tests/Core/Behat/MercureContext.php rename to tests/Behat/MercureContext.php index 2ee18723932..35b2e213bbc 100644 --- a/tests/Core/Behat/MercureContext.php +++ b/tests/Behat/MercureContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Gherkin\Node\PyStringNode; diff --git a/tests/Core/Behat/OpenApiContext.php b/tests/Behat/OpenApiContext.php similarity index 99% rename from tests/Core/Behat/OpenApiContext.php rename to tests/Behat/OpenApiContext.php index 2ddc5ed1875..d53c529fc4b 100644 --- a/tests/Core/Behat/OpenApiContext.php +++ b/tests/Behat/OpenApiContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; diff --git a/tests/Core/Behat/XmlContext.php b/tests/Behat/XmlContext.php similarity index 96% rename from tests/Core/Behat/XmlContext.php rename to tests/Behat/XmlContext.php index 8e18ffd9408..af05fed1fce 100644 --- a/tests/Core/Behat/XmlContext.php +++ b/tests/Behat/XmlContext.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Behat; +namespace ApiPlatform\Tests\Behat; use Behat\Gherkin\Node\PyStringNode; use Behatch\Context\XmlContext as BaseXmlContext; diff --git a/tests/Core/Annotation/ApiFilterTest.php b/tests/Core/Annotation/ApiFilterTest.php deleted file mode 100644 index 45b175ecaa8..00000000000 --- a/tests/Core/Annotation/ApiFilterTest.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * 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\Annotation; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Tests\Fixtures\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * @author Antoine Bluchet - */ -class ApiFilterTest extends TestCase -{ - public function testInvalidConstructor() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('This annotation needs a value representing the filter class.'); - - new ApiFilter(null); // @phpstan-ignore-line - } - - public function testInvalidFilter() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The filter class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy" does not implement "ApiPlatform\\Api\\FilterInterface". Did you forget a use statement?'); - - new ApiFilter(['value' => Dummy::class]); // @phpstan-ignore-line - } - - public function testInvalidProperty() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Property "foo" does not exist on the ApiFilter annotation.'); - - new ApiFilter(['value' => DummyFilter::class, 'foo' => 'bar']); // @phpstan-ignore-line - } - - public function testAssignation() - { - $resource = new ApiFilter(['value' => DummyFilter::class, 'strategy' => 'test', 'properties' => ['one', 'two'], 'arguments' => ['args']]); // @phpstan-ignore-line - - $this->assertEquals($resource->filterClass, DummyFilter::class); - $this->assertEquals($resource->strategy, 'test'); - $this->assertEquals($resource->properties, ['one', 'two']); - $this->assertEquals($resource->arguments, ['args']); - } - - /** - * @requires PHP 8.0 - */ - public function testAssignationAttribute() - { - $filter = eval(<<<'PHP' -return new \ApiPlatform\Core\Annotation\ApiFilter(\ApiPlatform\Tests\Fixtures\DummyFilter::class, strategy: 'test', properties: ['one', 'two'], arguments: ['args']); -PHP -); - - $this->assertEquals($filter->filterClass, DummyFilter::class); - $this->assertEquals($filter->strategy, 'test'); - $this->assertEquals($filter->properties, ['one', 'two']); - $this->assertEquals($filter->arguments, ['args']); - } -} diff --git a/tests/Core/Annotation/ApiPropertyTest.php b/tests/Core/Annotation/ApiPropertyTest.php deleted file mode 100644 index e777127395b..00000000000 --- a/tests/Core/Annotation/ApiPropertyTest.php +++ /dev/null @@ -1,107 +0,0 @@ - - * - * 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\Annotation; - -use ApiPlatform\Core\Annotation\ApiProperty; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class ApiPropertyTest extends TestCase -{ - public function testAssignation() - { - $property = new ApiProperty(); - $property->description = 'description'; - $property->readable = true; - $property->writable = true; - $property->readableLink = true; - $property->writableLink = true; - $property->required = true; - $property->iri = 'http://example.com/prop'; - $property->identifier = true; - $property->attributes = ['foo' => 'bar']; - - $this->assertEquals('description', $property->description); - $this->assertTrue($property->readable); - $this->assertTrue($property->writable); - $this->assertTrue($property->readableLink); - $this->assertTrue($property->writableLink); - $this->assertTrue($property->required); - $this->assertEquals('http://example.com/prop', $property->iri); - $this->assertTrue($property->identifier); - $this->assertEquals(['foo' => 'bar'], $property->attributes); - } - - public function testConstruct() - { - $property = new ApiProperty([ - 'deprecationReason' => 'this field is deprecated', - 'fetchable' => true, - 'fetchEager' => false, - 'jsonldContext' => ['foo' => 'bar'], - 'security' => 'is_granted(\'ROLE_ADMIN\')', - 'swaggerContext' => ['foo' => 'baz'], - 'openapiContext' => ['foo' => 'baz'], - 'push' => true, - 'attributes' => ['unknown' => 'unknown', 'fetchable' => false], - ]); - $this->assertEquals([ - 'deprecation_reason' => 'this field is deprecated', - 'fetchable' => false, - 'fetch_eager' => false, - 'jsonld_context' => ['foo' => 'bar'], - 'security' => 'is_granted(\'ROLE_ADMIN\')', - 'swagger_context' => ['foo' => 'baz'], - 'openapi_context' => ['foo' => 'baz'], - 'push' => true, - 'unknown' => 'unknown', - ], $property->attributes); - } - - /** - * @requires PHP 8.0 - */ - public function testConstructAttribute() - { - $property = eval(<<<'PHP' -return new \ApiPlatform\Core\Annotation\ApiProperty( - deprecationReason: 'this field is deprecated', - fetchable: true, - fetchEager: false, - jsonldContext: ['foo' => 'bar'], - security: 'is_granted(\'ROLE_ADMIN\')', - swaggerContext: ['foo' => 'baz'], - openapiContext: ['foo' => 'baz'], - push: true, - attributes: ['unknown' => 'unknown', 'fetchable' => false] -); -PHP - ); - - $this->assertEquals([ - 'deprecation_reason' => 'this field is deprecated', - 'fetchable' => false, - 'fetch_eager' => false, - 'jsonld_context' => ['foo' => 'bar'], - 'security' => 'is_granted(\'ROLE_ADMIN\')', - 'swagger_context' => ['foo' => 'baz'], - 'openapi_context' => ['foo' => 'baz'], - 'push' => true, - 'unknown' => 'unknown', - 'security_post_denormalize' => null, - ], $property->attributes); - } -} diff --git a/tests/Core/Annotation/ApiResourceTest.php b/tests/Core/Annotation/ApiResourceTest.php deleted file mode 100644 index 1e1a3b6e550..00000000000 --- a/tests/Core/Annotation/ApiResourceTest.php +++ /dev/null @@ -1,297 +0,0 @@ - - * - * 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\Annotation; - -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Tests\Fixtures\AnnotatedClass; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8; -use Doctrine\Common\Annotations\AnnotationReader; -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Kévin Dunglas - */ -class ApiResourceTest extends TestCase -{ - use ExpectDeprecationTrait; - - /** - * @group legacy - */ - public function testConstruct() - { - $resource = new ApiResource([ - 'security' => 'is_granted("ROLE_FOO")', - 'securityMessage' => 'You are not foo.', - 'securityPostDenormalize' => 'is_granted("ROLE_BAR")', - 'securityPostDenormalizeMessage' => 'You are not bar.', - 'securityPostValidation' => 'is_granted("ROLE_FOO")', - 'securityPostValidationMessage' => 'You are not foo.', - 'attributes' => ['foo' => 'bar', 'validation_groups' => ['baz', 'qux'], 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']]], - 'collectionOperations' => ['bar' => ['foo']], - 'denormalizationContext' => ['groups' => ['foo']], - 'description' => 'description', - 'fetchPartial' => true, - 'forceEager' => false, - 'formats' => ['foo', 'bar' => ['application/bar']], - 'filters' => ['foo', 'bar'], - 'graphql' => ['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], - 'input' => 'Foo', - 'iri' => 'http://example.com/res', - 'itemOperations' => ['foo' => ['bar']], - 'mercure' => ['private' => true], - 'messenger' => true, - 'normalizationContext' => ['groups' => ['bar']], - 'order' => ['foo', 'bar' => 'ASC'], - 'openapiContext' => ['description' => 'foo'], - 'output' => 'Bar', - 'paginationClientEnabled' => true, - 'paginationClientItemsPerPage' => true, - 'paginationClientPartial' => true, - 'paginationEnabled' => true, - 'paginationFetchJoinCollection' => true, - 'paginationItemsPerPage' => 42, - 'paginationMaximumItemsPerPage' => 50, - 'paginationPartial' => true, - 'routePrefix' => '/foo', - 'shortName' => 'shortName', - 'subresourceOperations' => [], - 'swaggerContext' => ['description' => 'bar'], - 'validationGroups' => ['foo', 'bar'], - 'sunset' => 'Thu, 11 Oct 2018 00:00:00 +0200', - 'urlGenerationStrategy' => UrlGeneratorInterface::ABS_PATH, - 'queryParameterValidationEnabled' => false, - ]); - - $this->assertSame('shortName', $resource->shortName); - $this->assertSame('description', $resource->description); - $this->assertSame('http://example.com/res', $resource->iri); - $this->assertSame(['foo' => ['bar']], $resource->itemOperations); - $this->assertSame(['bar' => ['foo']], $resource->collectionOperations); - $this->assertSame([], $resource->subresourceOperations); - $this->assertSame(['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], $resource->graphql); - $this->assertEquals([ - 'security' => 'is_granted("ROLE_FOO")', - 'security_message' => 'You are not foo.', - 'security_post_denormalize' => 'is_granted("ROLE_BAR")', - 'security_post_denormalize_message' => 'You are not bar.', - 'security_post_validation' => 'is_granted("ROLE_FOO")', - 'security_post_validation_message' => 'You are not foo.', - 'denormalization_context' => ['groups' => ['foo']], - 'fetch_partial' => true, - 'foo' => 'bar', - 'force_eager' => false, - 'formats' => ['foo', 'bar' => ['application/bar']], - 'filters' => ['foo', 'bar'], - 'input' => 'Foo', - 'mercure' => ['private' => true], - 'messenger' => true, - 'normalization_context' => ['groups' => ['bar']], - 'order' => ['foo', 'bar' => 'ASC'], - 'openapi_context' => ['description' => 'foo'], - 'output' => 'Bar', - 'pagination_client_enabled' => true, - 'pagination_client_items_per_page' => true, - 'pagination_client_partial' => true, - 'pagination_enabled' => true, - 'pagination_fetch_join_collection' => true, - 'pagination_items_per_page' => 42, - 'pagination_maximum_items_per_page' => 50, - 'pagination_partial' => true, - 'route_prefix' => '/foo', - 'swagger_context' => ['description' => 'bar'], - 'validation_groups' => ['baz', 'qux'], - 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']], - 'sunset' => 'Thu, 11 Oct 2018 00:00:00 +0200', - 'url_generation_strategy' => 1, - 'query_parameter_validation_enabled' => false, - ], $resource->attributes); - } - - /** - * @requires PHP 8.0 - */ - public function testConstructAttribute() - { - $resource = eval(<<<'PHP' -return new \ApiPlatform\Core\Annotation\ApiResource( - security: 'is_granted("ROLE_FOO")', - securityMessage: 'You are not foo.', - securityPostDenormalize: 'is_granted("ROLE_BAR")', - securityPostDenormalizeMessage: 'You are not bar.', - securityPostValidation: 'is_granted("ROLE_FOO")', - securityPostValidationMessage: 'You are not foo.', - attributes: ['foo' => 'bar', 'validation_groups' => ['baz', 'qux'], 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']]], - collectionOperations: ['bar' => ['foo']], - denormalizationContext: ['groups' => ['foo']], - description: 'description', - fetchPartial: true, - forceEager: false, - formats: ['foo', 'bar' => ['application/bar']], - filters: ['foo', 'bar'], - graphql: ['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], - input: 'Foo', - iri: 'http://example.com/res', - itemOperations: ['foo' => ['bar']], - mercure: ['private' => true], - messenger: true, - normalizationContext: ['groups' => ['bar']], - order: ['foo', 'bar' => 'ASC'], - openapiContext: ['description' => 'foo'], - output: 'Bar', - paginationClientEnabled: true, - paginationClientItemsPerPage: true, - paginationClientPartial: true, - paginationEnabled: true, - paginationFetchJoinCollection: true, - paginationItemsPerPage: 42, - paginationMaximumItemsPerPage: 50, - paginationPartial: true, - routePrefix: '/foo', - shortName: 'shortName', - subresourceOperations: [], - swaggerContext: ['description' => 'bar'], - validationGroups: ['foo', 'bar'], - sunset: 'Thu, 11 Oct 2018 00:00:00 +0200', - urlGenerationStrategy: \ApiPlatform\Api\UrlGeneratorInterface::ABS_PATH, - deprecationReason: 'reason', - elasticsearch: true, - hydraContext: ['hydra' => 'foo'], - paginationViaCursor: ['foo'], - stateless: true, - exceptionToStatus: [ - \DomainException::class => 400, - ], - queryParameterValidationEnabled: false, -); -PHP - ); - - $this->assertSame('shortName', $resource->shortName); - $this->assertSame('description', $resource->description); - $this->assertSame('http://example.com/res', $resource->iri); - $this->assertSame(['foo' => ['bar']], $resource->itemOperations); - $this->assertSame(['bar' => ['foo']], $resource->collectionOperations); - $this->assertSame([], $resource->subresourceOperations); - $this->assertSame(['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], $resource->graphql); - $this->assertEquals([ - 'security' => 'is_granted("ROLE_FOO")', - 'security_message' => 'You are not foo.', - 'security_post_denormalize' => 'is_granted("ROLE_BAR")', - 'security_post_denormalize_message' => 'You are not bar.', - 'security_post_validation' => 'is_granted("ROLE_FOO")', - 'security_post_validation_message' => 'You are not foo.', - 'denormalization_context' => ['groups' => ['foo']], - 'fetch_partial' => true, - 'foo' => 'bar', - 'force_eager' => false, - 'formats' => ['foo', 'bar' => ['application/bar']], - 'filters' => ['foo', 'bar'], - 'input' => 'Foo', - 'mercure' => ['private' => true], - 'messenger' => true, - 'normalization_context' => ['groups' => ['bar']], - 'order' => ['foo', 'bar' => 'ASC'], - 'openapi_context' => ['description' => 'foo'], - 'output' => 'Bar', - 'pagination_client_enabled' => true, - 'pagination_client_items_per_page' => true, - 'pagination_client_partial' => true, - 'pagination_enabled' => true, - 'pagination_fetch_join_collection' => true, - 'pagination_items_per_page' => 42, - 'pagination_maximum_items_per_page' => 50, - 'pagination_partial' => true, - 'route_prefix' => '/foo', - 'swagger_context' => ['description' => 'bar'], - 'validation_groups' => ['baz', 'qux'], - 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']], - 'sunset' => 'Thu, 11 Oct 2018 00:00:00 +0200', - 'url_generation_strategy' => 1, - 'deprecation_reason' => 'reason', - 'elasticsearch' => true, - 'hydra_context' => ['hydra' => 'foo'], - 'pagination_via_cursor' => ['foo'], - 'stateless' => true, - 'composite_identifier' => null, - 'exception_to_status' => [ - \DomainException::class => 400, - ], - 'query_parameter_validation_enabled' => false, - ], $resource->attributes); - } - - /** - * @requires PHP 8.0 - */ - public function testUseAttribute() - { - $this->assertSame('Hey PHP 8', (new \ReflectionClass(DummyPhp8::class))->getAttributes(ApiResource::class)[0]->getArguments()['description']); - } - - /** - * @group legacy - */ - public function testApiResourceAnnotation() - { - $reader = new AnnotationReader(); - /** - * @var ApiResource - */ - $resource = $reader->getClassAnnotation(new \ReflectionClass(AnnotatedClass::class), ApiResource::class); - - $this->assertSame('shortName', $resource->shortName); - $this->assertSame('description', $resource->description); - $this->assertSame('http://example.com/res', $resource->iri); - $this->assertSame(['bar' => ['foo']], $resource->collectionOperations); - $this->assertSame(['query' => ['normalization_context' => ['groups' => ['foo', 'bar']]]], $resource->graphql); - $this->assertEquals([ - 'foo' => 'bar', - 'route_prefix' => '/whatever', - 'security' => "is_granted('ROLE_FOO')", - 'security_message' => 'You are not foo.', - 'security_post_denormalize' => "is_granted('ROLE_BAR')", - 'security_post_denormalize_message' => 'You are not bar.', - 'cache_headers' => ['max_age' => 0, 'shared_max_age' => 0, 'vary' => ['Custom-Vary-1', 'Custom-Vary-2']], - ], $resource->attributes); - } - - public function testConstructWithInvalidAttribute() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unknown property "invalidAttribute" on annotation "ApiPlatform\\Core\\Annotation\\ApiResource".'); - - new ApiResource([ - 'shortName' => 'shortName', - 'routePrefix' => '/foo', - 'invalidAttribute' => 'exception', - ]); - } - - /** - * @group legacy - * @expectedDeprecation Attribute "accessControl" is deprecated in annotation since API Platform 2.5, prefer using "security" attribute instead - * @expectedDeprecation Attribute "accessControlMessage" is deprecated in annotation since API Platform 2.5, prefer using "securityMessage" attribute instead - */ - public function testWithDeprecatedAttributes() - { - new ApiResource([ - 'accessControl' => "is_granted('ROLE_USER')", - 'accessControlMessage' => 'Nope!', - ]); - } -} diff --git a/tests/Core/Annotation/ApiSubresourceTest.php b/tests/Core/Annotation/ApiSubresourceTest.php deleted file mode 100644 index fc1ed117299..00000000000 --- a/tests/Core/Annotation/ApiSubresourceTest.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * 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\Annotation; - -use ApiPlatform\Core\Annotation\ApiSubresource; -use PHPUnit\Framework\TestCase; - -/** - * @author Cody Banman - */ -class ApiSubresourceTest extends TestCase -{ - public function testAssignation() - { - $property = new ApiSubresource(); - $property->maxDepth = 1; - - $this->assertEquals(1, $property->maxDepth); - } - - public function testConstruct() - { - $property = new ApiSubresource([ // @phpstan-ignore-line - 'maxDepth' => 1, - ]); - $this->assertEquals(1, $property->maxDepth); - } - - /** - * @requires PHP 8.0 - */ - public function testConstructAttribute() - { - $property = eval(<<<'PHP' -return new \ApiPlatform\Core\Annotation\ApiSubresource( - maxDepth: 1 -); -PHP - ); - $this->assertEquals(1, $property->maxDepth); - } -} diff --git a/tests/Core/Api/CachedIdentifiersExtractorTest.php b/tests/Core/Api/CachedIdentifiersExtractorTest.php deleted file mode 100644 index 96666aac644..00000000000 --- a/tests/Core/Api/CachedIdentifiersExtractorTest.php +++ /dev/null @@ -1,244 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Core\Api\CachedIdentifiersExtractor; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class CachedIdentifiersExtractorTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function itemProvider() - { - $dummy = new Dummy(); - $dummy->setId($id = 1); - yield [$dummy, ['id' => $id]]; - - $dummy = new Dummy(); - $dummy->setId($id = new Uuid()); - yield [$dummy, ['id' => $id]]; - } - - /** - * @dataProvider itemProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testFirstPass($item, $expected) - { - $cacheItemKey = 'iri_identifiers'.md5(Dummy::class); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(false); - $cacheItemProphecy->set(['id'])->shouldBeCalled()->willReturn($cacheItemProphecy->reveal()); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem($cacheItemKey)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldBeCalled(); - - $decoratedProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $decoratedProphecy->getIdentifiersFromItem($item)->willReturn($expected); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new CachedIdentifiersExtractor($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item), 'Trigger the local cache'); - - $expected = ['id']; - - $decoratedProphecy->getIdentifiersFromResourceClass(Dummy::class)->willReturn($expected); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class), 'Trigger the local cache'); - } - - /** - * @dataProvider itemProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testSecondPass($item, $expected) - { - $cacheItemKey = 'iri_identifiers'.md5(Dummy::class); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(true); - $cacheItemProphecy->get()->willReturn(['id']); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem($cacheItemKey)->willReturn($cacheItemProphecy); - - $decoratedProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $decoratedProphecy->getIdentifiersFromItem($item)->shouldNotBeCalled(); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new CachedIdentifiersExtractor($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item), 'Trigger the local cache'); - - $expected = ['id']; - - $decoratedProphecy->getIdentifiersFromResourceClass(Dummy::class)->willReturn($expected); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class), 'Trigger the local cache'); - } - - public function identifiersRelatedProvider() - { - $related = new RelatedDummy(); - $related->setId($relatedId = 2); - - $dummy = new Dummy(); - $dummy->setId($id = 1); - $dummy->setRelatedDummy($related); - - yield [$dummy, ['id' => $id, 'relatedDummy' => $relatedId]]; - - $related = new RelatedDummy(); - $related->setId($relatedId = 1); - - $dummy = new Dummy(); - $dummy->setId($id = new Uuid()); - $dummy->setRelatedDummy($related); - - yield [$dummy, ['id' => $id, 'relatedDummy' => $relatedId]]; - - $related = new RelatedDummy(); - $related->setId($relatedId = new Uuid()); - - $dummy = new Dummy(); - $dummy->setId($id = new Uuid()); - $dummy->setRelatedDummy($related); - - yield [$dummy, ['id' => $id, 'relatedDummy' => $relatedId]]; - } - - /** - * @dataProvider identifiersRelatedProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testFirstPassWithRelated($item, $expected) - { - $cacheItemKey = 'iri_identifiers'.md5(Dummy::class); - $relatedCacheItemKey = 'iri_identifiers'.md5(RelatedDummy::class); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(true); - $cacheItemProphecy->get()->willReturn(['id', 'relatedDummy']); - - $relatedCacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $relatedCacheItemProphecy->isHit()->willReturn(false); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem($cacheItemKey)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->getItem($relatedCacheItemKey)->willReturn($relatedCacheItemProphecy); - - $decoratedProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $decoratedProphecy->getIdentifiersFromItem($item)->willReturn($expected); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(Argument::type(RelatedDummy::class))->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new CachedIdentifiersExtractor($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item), 'Trigger the local cache'); - } - - /** - * @dataProvider identifiersRelatedProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testSecondPassWithRelated($item, $expected) - { - $cacheItemKey = 'iri_identifiers'.md5(Dummy::class); - $relatedCacheItemKey = 'iri_identifiers'.md5(RelatedDummy::class); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(true); - $cacheItemProphecy->get()->willReturn(['id', 'relatedDummy']); - - $relatedCacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $relatedCacheItemProphecy->isHit()->willReturn(true); - $relatedCacheItemProphecy->get()->willReturn(['id']); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem($cacheItemKey)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->getItem($relatedCacheItemKey)->willReturn($relatedCacheItemProphecy); - - $decoratedProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $decoratedProphecy->getIdentifiersFromItem($item)->shouldNotBeCalled(); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(Argument::type(RelatedDummy::class))->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new CachedIdentifiersExtractor($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item), 'Trigger the local cache'); - } - - /** - * @group legacy - */ - public function testDeprecationResourceClassResolver() - { - $this->expectDeprecation('Not injecting ApiPlatform\Core\Api\ResourceClassResolverInterface in the CachedIdentifiersExtractor might introduce cache issues with object identifiers.'); - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $decoration = $this->prophesize(IdentifiersExtractorInterface::class); - - new CachedIdentifiersExtractor($cacheItemPool->reveal(), $decoration->reveal(), null); - } -} diff --git a/tests/Core/Api/EntrypointTest.php b/tests/Core/Api/EntrypointTest.php deleted file mode 100644 index 85b0a3d7756..00000000000 --- a/tests/Core/Api/EntrypointTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Api\Entrypoint; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * @author Amrouche Hamza - */ -class EntrypointTest extends TestCase -{ - public function testGetResourceNameCollection() - { - $resourceNameCollection = new ResourceNameCollection([Dummy::class]); - $entrypoint = new Entrypoint($resourceNameCollection); - $this->assertEquals($entrypoint->getResourceNameCollection(), $resourceNameCollection); - } -} diff --git a/tests/Core/Api/FilterCollectionFactoryTest.php b/tests/Core/Api/FilterCollectionFactoryTest.php deleted file mode 100644 index ef94c8edad4..00000000000 --- a/tests/Core/Api/FilterCollectionFactoryTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\FilterCollectionFactory; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; - -/** - * @author Baptiste Meyer - */ -class FilterCollectionFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testCreateFilterCollectionFromLocator() - { - $filter = $this->prophesize(FilterInterface::class)->reveal(); - - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filterLocatorProphecy->has('foo')->willReturn(true)->shouldBeCalled(); - $filterLocatorProphecy->get('foo')->willReturn($filter)->shouldBeCalled(); - $filterLocatorProphecy->has('bar')->willReturn(false)->shouldBeCalled(); - - $filterCollection = (new FilterCollectionFactory(['foo', 'bar']))->createFilterCollectionFromLocator($filterLocatorProphecy->reveal()); - - $this->assertArrayNotHasKey('bar', $filterCollection); - $this->assertTrue(isset($filterCollection['foo'])); - $this->assertInstanceOf(FilterInterface::class, $filterCollection['foo']); - $this->assertEquals(new FilterCollection(['foo' => $filter]), $filterCollection); - } -} diff --git a/tests/Core/Api/FilterCollectionTest.php b/tests/Core/Api/FilterCollectionTest.php deleted file mode 100644 index 65461d060ad..00000000000 --- a/tests/Core/Api/FilterCollectionTest.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Core\Api\FilterCollection; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class FilterCollectionTest extends TestCase -{ - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testIsArrayObject() - { - $filterCollection = new FilterCollection(); - $this->assertInstanceOf(\ArrayObject::class, $filterCollection); - } -} diff --git a/tests/Core/Api/FilterLocatorTraitTest.php b/tests/Core/Api/FilterLocatorTraitTest.php deleted file mode 100644 index 4501a427dc5..00000000000 --- a/tests/Core/Api/FilterLocatorTraitTest.php +++ /dev/null @@ -1,161 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Api\FilterLocatorTrait; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; - -/** - * @author Baptiste Meyer - */ -class FilterLocatorTraitTest extends TestCase -{ - use ProphecyTrait; - - public function testSetFilterLocator() - { - $filterLocator = $this->prophesize(ContainerInterface::class)->reveal(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator($filterLocator); - - $this->assertEquals($filterLocator, $filterLocatorTraitImpl->getFilterLocator()); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testSetFilterLocatorWithDeprecatedFilterCollection() - { - $filterCollection = new FilterCollection(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator($filterCollection); - - $this->assertEquals($filterCollection, $filterLocatorTraitImpl->getFilterLocator()); - } - - public function testSetFilterLocatorWithNullAndNullAllowed() - { - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(null, true); - - $this->assertNull($filterLocatorTraitImpl->getFilterLocator()); - } - - /** - * @group legacy - */ - public function testSetFilterLocatorWithNullAndNullNotAllowed() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface.'); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(null); - } - - /** - * @group legacy - */ - public function testSetFilterLocatorWithInvalidFilterLocator() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface or null.'); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(new \ArrayObject(), true); - } - - public function testGetFilter() - { - $filter = $this->prophesize(FilterInterface::class)->reveal(); - - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filterLocatorProphecy->has('foo')->willReturn(true)->shouldBeCalled(); - $filterLocatorProphecy->get('foo')->willReturn($filter)->shouldBeCalled(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator($filterLocatorProphecy->reveal()); - - $returnedFilter = $filterLocatorTraitImpl->getFilter('foo'); - - $this->assertInstanceOf(FilterInterface::class, $returnedFilter); - $this->assertEquals($filter, $returnedFilter); - } - - public function testGetFilterWithNonexistentFilterId() - { - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filterLocatorProphecy->has('foo')->willReturn(false)->shouldBeCalled(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator($filterLocatorProphecy->reveal()); - - $filter = $filterLocatorTraitImpl->getFilter('foo'); - - $this->assertNull($filter); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testGetFilterWithDeprecatedFilterCollection() - { - $filter = $this->prophesize(FilterInterface::class)->reveal(); - - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(new FilterCollection(['foo' => $filter])); - - $returnedFilter = $filterLocatorTraitImpl->getFilter('foo'); - - $this->assertInstanceOf(FilterInterface::class, $returnedFilter); - $this->assertEquals($filter, $returnedFilter); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testGetFilterWithNonexistentFilterIdAndDeprecatedFilterCollection() - { - $filterLocatorTraitImpl = $this->getFilterLocatorTraitImpl(); - $filterLocatorTraitImpl->setFilterLocator(new FilterCollection()); - - $filter = $filterLocatorTraitImpl->getFilter('foo'); - - $this->assertNull($filter); - } - - private function getFilterLocatorTraitImpl() - { - return new class() { - use FilterLocatorTrait { - FilterLocatorTrait::setFilterLocator as public; - FilterLocatorTrait::getFilter as public; - } - - public function getFilterLocator() - { - return $this->filterLocator; - } - }; - } -} diff --git a/tests/Core/Api/FormatsProviderTest.php b/tests/Core/Api/FormatsProviderTest.php deleted file mode 100644 index e29e5430226..00000000000 --- a/tests/Core/Api/FormatsProviderTest.php +++ /dev/null @@ -1,189 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Core\Api\FormatsProvider; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - * - * @group legacy - */ -class FormatsProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testNoResourceClass() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create()->shouldNotBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => 'application/ld+json']); - - $this->assertSame(['jsonld' => 'application/ld+json'], $formatProvider->getFormatsFromAttributes([])); - } - - public function testResourceClassWithoutFormatsAttributes() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata())->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testResourceClassWithFormatsAttributes() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testResourceClassWithFormatsAttributesOverRiddingMimeTypes() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => 'application/fuz']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => ['application/fuz']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testBadFormatsShortDeclaration() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('You either need to add the format \'foo\' to your project configuration or declare a mime type for it in your annotation.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['foo']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); - - $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get']); - } - - public function testInvalidFormatsShortDeclaration() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes value must be a string when trying to include an already configured format, array given.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => [['badFormat']]]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testInvalidFormatsDeclaration() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes must be an array, string given for resource class \'Foo\'.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => 'badFormat']); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get'])); - } - - public function testResourceClassWithoutFormatsAttributesFromOperation() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata())->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } - - public function testResourceClassWithFormatsAttributesFromOperation() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } - - public function testResourceClassWithFormatsAttributesOverRiddingMimeTypesFromOperation() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => 'application/fuz']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/foo'], 'bar' => ['application/bar', 'application/baz'], 'buz' => ['application/fuz']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } - - public function testBadFormatsShortDeclarationFromOperation() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('You either need to add the format \'foo\' to your project configuration or declare a mime type for it in your annotation.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => ['foo']]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json']]); - - $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION); - } - - public function testInvalidFormatsShortDeclarationFromOperation() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes value must be a string when trying to include an already configured format, array given.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => [['badFormat']]]); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } - - public function testInvalidFormatsDeclarationFromOperation() - { - $this->expectException(\ApiPlatform\Exception\InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes must be an array, string given for resource class \'Foo\'.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['formats' => 'badFormat']); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $formatProvider = new FormatsProvider($resourceMetadataFactoryProphecy->reveal(), ['jsonld' => ['application/ld+json'], 'json' => ['application/json']]); - - $this->assertSame(['jsonld' => ['application/ld+json']], $formatProvider->getFormatsFromOperation('Foo', 'get', OperationType::COLLECTION)); - } -} diff --git a/tests/Core/Api/IdentifiersExtractorTest.php b/tests/Core/Api/IdentifiersExtractorTest.php deleted file mode 100644 index 60e2bf924e7..00000000000 --- a/tests/Core/Api/IdentifiersExtractorTest.php +++ /dev/null @@ -1,276 +0,0 @@ - - * - * 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\Api; - -use ApiPlatform\Core\Api\IdentifiersExtractor; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterfaceImplementation; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Antoine Bluchet - */ -class IdentifiersExtractorTest extends TestCase -{ - use ProphecyTrait; - - public function testGetIdentifiersFromResourceClass() - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id']); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame(['id'], $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - } - - public function testGetCompositeIdentifiersFromResourceClass() - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id', 'name']); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame(['id', 'name'], $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - } - - public function itemProvider() - { - $dummy = new Dummy(); - $dummy->setId(1); - yield [$dummy, ['id' => 1]]; - - $uuid = new Uuid(); - $dummy = new Dummy(); - $dummy->setId($uuid); - yield [$dummy, ['id' => $uuid]]; - } - - /** - * @dataProvider itemProvider - * - * @param mixed $item - * @param mixed $expected - */ - public function testGetIdentifiersFromItem($item, $expected) - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id']); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - } - - public function itemProviderComposite() - { - $dummy = new Dummy(); - $dummy->setId(1); - $dummy->setName('foo'); - yield [$dummy, ['id' => 1, 'name' => 'foo']]; - - $dummy = new Dummy(); - $dummy->setId($uuid = new Uuid()); - $dummy->setName('foo'); - yield [$dummy, ['id' => $uuid, 'name' => 'foo']]; - } - - /** - * @dataProvider itemProviderComposite - * - * @param mixed $item - * @param mixed $expected - */ - public function testGetCompositeIdentifiersFromItem($item, $expected) - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id', 'name']); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - } - - public function itemProviderRelated() - { - $related = new RelatedDummy(); - $related->setId(2); - - $dummy = new Dummy(); - $dummy->setId(1); - $dummy->setRelatedDummy($related); - yield [$dummy, ['id' => 1, 'relatedDummy' => 2]]; - - $uuid2 = new Uuid(); - $related = new RelatedDummy(); - $related->setId($uuid2); - - $uuid = new Uuid(); - $dummy = new Dummy(); - $dummy->setId($uuid); - $dummy->setRelatedDummy($related); - yield [$dummy, ['id' => $uuid, 'relatedDummy' => $uuid2]]; - } - - /** - * @dataProvider itemProviderRelated - * - * @param mixed $item - * @param mixed $expected - */ - public function testGetRelatedIdentifiersFromItem($item, $expected) - { - $prophecies = $this->getMetadataFactoryProphecies(Dummy::class, ['id', 'relatedDummy']); - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(RelatedDummy::class, ['id'], $prophecies); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(Argument::type(RelatedDummy::class))->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(Uuid::class)->willReturn(false); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame($expected, $identifiersExtractor->getIdentifiersFromItem($item)); - } - - public function testThrowNoIdentifierFromItem() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('No identifier found in "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\RelatedDummy" through relation "relatedDummy" of "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy" used as identifier'); - - $related = new RelatedDummy(); - $related->setId(2); - - $dummy = new Dummy(); - $dummy->setId(1); - $dummy->setRelatedDummy($related); - - $prophecies = $this->getMetadataFactoryProphecies(Dummy::class, ['id', 'relatedDummy']); - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(RelatedDummy::class, [], $prophecies); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($dummy)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(Argument::type(RelatedDummy::class))->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $identifiersExtractor->getIdentifiersFromItem($dummy); - } - - public function testGetsIdentifiersFromCorrectResourceClass(): void - { - $item = new ResourceInterfaceImplementation(); - $item->setFoo('woot'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(ResourceInterface::class)->willReturn(new PropertyNameCollection(['foo', 'fooz'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(ResourceInterface::class, 'foo')->willReturn((new PropertyMetadata())->withIdentifier(true)); - $propertyMetadataFactoryProphecy->create(ResourceInterface::class, 'fooz')->willReturn(new PropertyMetadata()); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($item)->willReturn(ResourceInterface::class); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $identifiersExtractor->getIdentifiersFromItem($item); - - $this->assertSame(['foo' => 'woot'], $identifiersExtractor->getIdentifiersFromItem($item)); - } - - public function testNoIdentifiers(): void - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('No identifier defined in "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy". You should add #[\ApiPlatform\Core\Annotation\ApiProperty(identifier: true)]" on the property identifying the resource.'); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['foo'])); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'foo')->willReturn(new PropertyMetadata()); - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class); - } - - /** - * @group legacy - * @expectedDeprecation Not injecting ApiPlatform\Core\Api\ResourceClassResolverInterface in the IdentifiersExtractor might introduce cache issues with object identifiers. - */ - public function testLegacyGetIdentifiersFromItem() - { - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $this->getMetadataFactoryProphecies(Dummy::class, ['id']); - - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()); - - $dummy = new Dummy(); - $dummy->setId(1); - - $this->assertSame(['id' => 1], $identifiersExtractor->getIdentifiersFromItem($dummy)); - } - - private function getMetadataFactoryProphecies($class, $identifiers, array $prophecies = null) - { - // adds a random property that is not an identifier - $properties = array_merge(['foo'], $identifiers); - - if (!$prophecies) { - $prophecies = [$this->prophesize(PropertyNameCollectionFactoryInterface::class), $this->prophesize(PropertyMetadataFactoryInterface::class)]; - } - - [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy] = $prophecies; - - $propertyNameCollectionFactoryProphecy->create($class)->willReturn(new PropertyNameCollection($properties)); - - foreach ($properties as $prop) { - $metadata = new PropertyMetadata(); - $propertyMetadataFactoryProphecy->create($class, $prop)->willReturn($metadata->withIdentifier(\in_array($prop, $identifiers, true))); - } - - return [$propertyNameCollectionFactoryProphecy, $propertyMetadataFactoryProphecy]; - } - - public function testDefaultIdentifierId(): void - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['id'])); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn(new PropertyMetadata()); - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $identifiersExtractor = new IdentifiersExtractor($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal()); - - $this->assertSame(['id'], $identifiersExtractor->getIdentifiersFromResourceClass(Dummy::class)); - } -} diff --git a/tests/Core/Api/ResourceClassResolverTest.php b/tests/Core/Api/ResourceClassResolverTest.php deleted file mode 100644 index c775778da41..00000000000 --- a/tests/Core/Api/ResourceClassResolverTest.php +++ /dev/null @@ -1,209 +0,0 @@ - - * - * 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\Tests\Api; - -use ApiPlatform\Api\ResourceClassResolver; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\State\Pagination\PaginatorInterface; -use ApiPlatform\Tests\Fixtures\DummyResourceImplementation; -use ApiPlatform\Tests\Fixtures\DummyResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; -use PHPUnit\Framework\TestCase; - -/** - * @author Amrouche Hamza - */ -class ResourceClassResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testGetResourceClassWithIntendedClassName() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $dummy = new Dummy(); - $dummy->setName('Smail'); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass($dummy, Dummy::class)); - } - - public function testGetResourceClassWithNonResourceClassName() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Specified class "ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar" is not a resource class.'); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $dummy = new Dummy(); - $dummy->setName('Smail'); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $resourceClassResolver->getResourceClass($dummy, DummyCar::class, true); - } - - public function testGetResourceClassWithNoClassName() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $dummy = new Dummy(); - $dummy->setName('Smail'); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass($dummy)); - } - - public function testGetResourceClassWithTraversableAsValue() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $dummy = new Dummy(); - $dummy->setName('JLM'); - - $dummies = new \ArrayIterator([$dummy]); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass($dummies, Dummy::class)); - } - - public function testGetResourceClassWithTraversable() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([\ArrayObject::class])); - - $dummy = new \ArrayObject(); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(\ArrayObject::class, $resourceClassResolver->getResourceClass($dummy)); - } - - public function testGetResourceClassWithPaginatorInterfaceAsValue() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $paginatorProphecy = $this->prophesize(PaginatorInterface::class); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass($paginatorProphecy->reveal(), Dummy::class)); - } - - public function testGetResourceClassWithWrongClassName() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No resource class found for object of type "stdClass".'); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $resourceClassResolver->getResourceClass(new \stdClass()); - } - - public function testGetResourceClassWithNoResourceClassName() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Resource type could not be determined. Resource class must be specified.'); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([])); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $resourceClassResolver->getResourceClass(new \ArrayIterator([])); - } - - public function testIsResourceClassWithIntendedClassName() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertTrue($resourceClassResolver->isResourceClass(Dummy::class)); - } - - public function testIsResourceClassWithWrongClassName() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([\ArrayIterator::class])); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertFalse($resourceClassResolver->isResourceClass('')); - } - - public function testGetResourceClassWithNoResourceClassNameAndNoObject() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Resource type could not be determined. Resource class must be specified.'); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $resourceClassResolver->getResourceClass(false); - } - - public function testGetResourceClassWithResourceClassNameAndNoObject() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class])); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(Dummy::class, $resourceClassResolver->getResourceClass(false, Dummy::class)); - } - - public function testGetResourceClassWithChildResource() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyTableInheritance::class, DummyTableInheritanceChild::class])); - - $dummy = new DummyTableInheritanceChild(); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(DummyTableInheritanceChild::class, $resourceClassResolver->getResourceClass($dummy, DummyTableInheritance::class)); - } - - public function testGetResourceClassWithInterfaceResource() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyResourceInterface::class])); - - $dummy = new DummyResourceImplementation(); - - $resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal()); - - $this->assertEquals(DummyResourceInterface::class, $resourceClassResolver->getResourceClass($dummy, DummyResourceInterface::class, true)); - } -} diff --git a/tests/Core/Bridge/Doctrine/Common/DataPersisterTest.php b/tests/Core/Bridge/Doctrine/Common/DataPersisterTest.php deleted file mode 100644 index 804339a9c9e..00000000000 --- a/tests/Core/Bridge/Doctrine/Common/DataPersisterTest.php +++ /dev/null @@ -1,162 +0,0 @@ - - * - * 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\Doctrine\Common; - -use ApiPlatform\Core\Bridge\Doctrine\Common\DataPersister; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use PHPUnit\Framework\TestCase; -use Prophecy\Prediction\CallPrediction; -use Prophecy\Prediction\NoCallsPrediction; - -/** - * @author Baptiste Meyer - */ -class DataPersisterTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $this->assertInstanceOf(DataPersisterInterface::class, new DataPersister($this->prophesize(ManagerRegistry::class)->reveal())); - } - - public function testSupports() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($this->prophesize(ObjectManager::class)->reveal())->shouldBeCalled(); - - $this->assertTrue((new DataPersister($managerRegistryProphecy->reveal()))->supports(new Dummy())); - } - - public function testDoesNotSupport() - { - $this->assertFalse((new DataPersister($this->prophesize(ManagerRegistry::class)->reveal()))->supports('dummy')); - } - - public function testPersist() - { - $dummy = new Dummy(); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->contains($dummy)->willReturn(false); - $objectManagerProphecy->persist($dummy)->shouldBeCalled(); - $objectManagerProphecy->flush()->shouldBeCalled(); - $objectManagerProphecy->refresh($dummy)->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($objectManagerProphecy->reveal())->shouldBeCalled(); - - $result = (new DataPersister($managerRegistryProphecy->reveal()))->persist($dummy); - $this->assertSame($dummy, $result); - } - - public function testPersistIfEntityAlreadyManaged() - { - $dummy = new Dummy(); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->contains($dummy)->willReturn(true); - $objectManagerProphecy->persist($dummy)->shouldNotBeCalled(); - $objectManagerProphecy->flush()->shouldBeCalled(); - $objectManagerProphecy->refresh($dummy)->shouldBeCalled(); - $objectManagerProphecy->getClassMetadata(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($objectManagerProphecy->reveal())->shouldBeCalled(); - - $result = (new DataPersister($managerRegistryProphecy->reveal()))->persist($dummy); - $this->assertSame($dummy, $result); - } - - public function testPersistWithNullManager() - { - $dummy = new Dummy(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $result = (new DataPersister($managerRegistryProphecy->reveal()))->persist($dummy); - $this->assertSame($dummy, $result); - } - - public function testRemove() - { - $dummy = new Dummy(); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->remove($dummy)->shouldBeCalled(); - $objectManagerProphecy->flush()->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($objectManagerProphecy->reveal())->shouldBeCalled(); - - (new DataPersister($managerRegistryProphecy->reveal()))->remove($dummy); - } - - public function testRemoveWithNullManager() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - (new DataPersister($managerRegistryProphecy->reveal()))->remove(new Dummy()); - } - - public function getTrackingPolicyParameters() - { - return [ - 'deferred explicit ORM' => [ClassMetadataInfo::class, true, true], - 'deferred implicit ORM' => [ClassMetadataInfo::class, false, false], - 'deferred explicit ODM' => [ClassMetadata::class, true, true], - 'deferred implicit ODM' => [ClassMetadata::class, false, false], - ]; - } - - /** - * @dataProvider getTrackingPolicyParameters - * - * @param mixed $metadataClass - * @param mixed $deferredExplicit - * @param mixed $persisted - */ - public function testTrackingPolicy($metadataClass, $deferredExplicit, $persisted) - { - $dummy = new Dummy(); - - $classMetadataInfo = $this->prophesize($metadataClass); - if (method_exists($metadataClass, 'isChangeTrackingDeferredExplicit')) { - $classMetadataInfo->isChangeTrackingDeferredExplicit()->willReturn($deferredExplicit)->shouldBeCalled(); - } else { - $persisted = false; - } - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataInfo)->shouldBeCalled(); - $objectManagerProphecy->contains($dummy)->willReturn(true); - $objectManagerProphecy->persist($dummy)->should($persisted ? new CallPrediction() : new NoCallsPrediction()); - $objectManagerProphecy->flush()->shouldBeCalled(); - $objectManagerProphecy->refresh($dummy)->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($objectManagerProphecy)->shouldBeCalled(); - - $result = (new DataPersister($managerRegistryProphecy->reveal()))->persist($dummy); - $this->assertSame($dummy, $result); - } -} diff --git a/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php b/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php deleted file mode 100644 index 5c1f3a07a6b..00000000000 --- a/tests/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTraitTest.php +++ /dev/null @@ -1,245 +0,0 @@ - - * - * 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\Doctrine\Common\Util; - -use ApiPlatform\Core\Bridge\Doctrine\Common\Util\IdentifierManagerTrait; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\PropertyNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy as DummyDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\Types\Type as DBALType; -use Doctrine\DBAL\Types\Types; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MongoDbOdmClassMetadata; -use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\Mapping\ClassMetadata; -use Doctrine\Persistence\ObjectManager; -use PHPUnit\Framework\TestCase; -use Ramsey\Uuid\Doctrine\UuidType; - -/** - * @group legacy - */ -class IdentifierManagerTraitTest extends TestCase -{ - use ProphecyTrait; - - private function getIdentifierManagerTraitImpl(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - return new class($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory) { - use IdentifierManagerTrait { - IdentifierManagerTrait::normalizeIdentifiers as public; - } - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - } - }; - } - - /** - * @group legacy - */ - public function testSingleIdentifier() - { - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $objectManager = $this->getEntityManager(Dummy::class, [ - 'id' => [ - 'type' => Types::INTEGER, - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $this->assertEquals($identifierManager->normalizeIdentifiers(1, $objectManager, Dummy::class), ['id' => 1]); - } - - /** - * @group legacy - * @group mongodb - */ - public function testSingleDocumentIdentifier() - { - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(DummyDocument::class, [ - 'id', - ]); - $objectManager = $this->getDocumentManager(DummyDocument::class, [ - 'id' => [ - 'type' => MongoDbType::INTEGER, - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $this->assertEquals($identifierManager->normalizeIdentifiers(1, $objectManager, DummyDocument::class), ['id' => 1]); - } - - /** - * @group legacy - */ - public function testCompositeIdentifier() - { - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $objectManager = $this->getEntityManager(Dummy::class, [ - 'ida' => [ - 'type' => Types::INTEGER, - ], - 'idb' => [ - 'type' => Types::INTEGER, - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $this->assertEquals($identifierManager->normalizeIdentifiers('ida=1;idb=2', $objectManager, Dummy::class), ['ida' => 1, 'idb' => 2]); - } - - /** - * @group legacy - */ - public function testInvalidIdentifier() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Invalid identifier "idbad=1;idb=2", "ida" was not found for resource "dummy".'); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $objectManager = $this->getEntityManager(Dummy::class, [ - 'ida' => [ - 'type' => Types::INTEGER, - ], - 'idb' => [ - 'type' => Types::INTEGER, - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $identifierManager->normalizeIdentifiers('idbad=1;idb=2', $objectManager, Dummy::class); - } - - /** - * Gets mocked metadata factories. - */ - private function getMetadataFactories(string $resourceClass, array $identifiers): array - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - $resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('dummy')); - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()]; - } - - /** - * Gets a mocked entity manager. - */ - private function getEntityManager(string $resourceClass, array $identifierFields): ObjectManager - { - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(array_keys($identifierFields)); - - foreach ($identifierFields as $name => $field) { - $classMetadataProphecy->getTypeOfField($name)->willReturn($field['type']); - } - - $platformProphecy = $this->prophesize(AbstractPlatform::class); - - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy->getDatabasePlatform()->willReturn($platformProphecy); - - $managerProphecy = $this->prophesize(EntityManagerInterface::class); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - $managerProphecy->getConnection()->willReturn($connectionProphecy); - - return $managerProphecy->reveal(); - } - - /** - * Gets a mocked document manager. - */ - private function getDocumentManager(string $resourceClass, array $identifierFields): ObjectManager - { - $classMetadataProphecy = $this->prophesize(MongoDbOdmClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(array_keys($identifierFields)); - - foreach ($identifierFields as $name => $field) { - $classMetadataProphecy->getTypeOfField($name)->willReturn($field['type']); - } - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - - return $managerProphecy->reveal(); - } - - /** - * @group legacy - */ - public function testInvalidIdentifierConversion() - { - DBALType::addType('ramsey-uuid', UuidType::class); - - $this->expectException(InvalidIdentifierException::class); - $this->expectExceptionMessage('Invalid value "ida" provided for an identifier for resource "dummy".'); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - ]); - $objectManager = $this->getEntityManager(Dummy::class, [ - 'ida' => [ - 'type' => 'ramsey-uuid', - ], - ]); - - $identifierManager = $this->getIdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory); - - $identifierManager->normalizeIdentifiers('notanuuid', $objectManager, Dummy::class); - } -} diff --git a/tests/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php b/tests/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php deleted file mode 100644 index f85de944385..00000000000 --- a/tests/Core/Bridge/Doctrine/MongoDbOdm/CollectionDataProviderTest.php +++ /dev/null @@ -1,166 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\CollectionDataProvider; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; -use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Operations; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Iterator\Iterator; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; - -/** - * @author Alan Poulain - * - * @group mongodb - */ -class CollectionDataProviderTest extends TestCase -{ - use ProphecyTrait; - - private $managerRegistryProphecy; - private $resourceMetadataFactoryProphecy; - - /** - * {@inheritdoc} - */ - protected function setUp(): void - { - parent::setUp(); - - $this->managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - } - - public function testGetCollection() - { - // No solution for this see https://github.com/doctrine/mongodb-odm/pull/2395 - if (method_exists(Builder::class, 'getAggregation')) { - $this->markTestSkipped('Can not mock Aggregation.'); - } - - $iterator = $this->prophesize(Iterator::class)->reveal(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute([])->willReturn($iterator)->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['foo' => new GetCollection()]))])); - - $extensionProphecy = $this->prophesize(AggregationCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, Dummy::class, 'foo', [])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals($iterator, $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testGetCollectionWithExecuteOptions() - { - if (method_exists(Builder::class, 'getAggregation')) { - $this->markTestSkipped('Can not mock Aggregation.'); - } - - $iterator = $this->prophesize(Iterator::class)->reveal(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute(['allowDiskUse' => true])->willReturn($iterator)->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['foo' => (new GetCollection())->withExtraProperties(['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]])]))])); - - $extensionProphecy = $this->prophesize(AggregationCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, Dummy::class, 'foo', [])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals($iterator, $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testAggregationResultExtension() - { - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(AggregationResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, Dummy::class, 'foo', [])->shouldBeCalled(); - $extensionProphecy->supportsResult(Dummy::class, 'foo', [])->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($aggregationBuilder, Dummy::class, 'foo', [])->willReturn([])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testCannotCreateAggregationBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository for "ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy" must be an instance of "Doctrine\ODM\MongoDB\Repository\DocumentRepository".'); - - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal()); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testUnsupportedClass() - { - $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(AggregationResultCollectionExtensionInterface::class); - - $dataProvider = new CollectionDataProvider($this->managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); - } -} diff --git a/tests/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php b/tests/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php deleted file mode 100644 index 37c883f255f..00000000000 --- a/tests/Core/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php +++ /dev/null @@ -1,307 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationItemExtensionInterface; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultItemExtensionInterface; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\ItemDataProvider; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch; -use Doctrine\ODM\MongoDB\Iterator\Iterator; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; - -/** - * @group mongodb - * - * @author Alan Poulain - */ -class ItemDataProviderTest extends TestCase -{ - use ProphecyTrait; - - private $resourceMetadataFactoryProphecy; - - /** - * {@inheritdoc} - */ - protected function setUp(): void - { - parent::setUp(); - - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - } - - public function testGetItemSingleIdentifier() - { - $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $matchProphecy = $this->prophesize(AggregationMatch::class); - $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->equals(1)->shouldBeCalled(); - - $iterator = $this->prophesize(Iterator::class); - $result = new \stdClass(); - $iterator->current()->willReturn($result)->shouldBeCalled(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute([])->willReturn($iterator->reveal())->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testGetItemWithExecuteOptions() - { - $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $matchProphecy = $this->prophesize(AggregationMatch::class); - $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->equals(1)->shouldBeCalled(); - - $iterator = $this->prophesize(Iterator::class); - $result = new \stdClass(); - $iterator->current()->willReturn($result)->shouldBeCalled(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute(['allowDiskUse' => true])->willReturn($iterator->reveal())->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata( - 'Dummy', - null, - null, - ['foo' => ['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]]] - )); - - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testGetItemDoubleIdentifier() - { - $matchProphecy = $this->prophesize(AggregationMatch::class); - $matchProphecy->field('ida')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->field('idb')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->equals(1)->shouldBeCalled(); - $matchProphecy->equals(2)->shouldBeCalled(); - - $iterator = $this->prophesize(Iterator::class); - $result = new \stdClass(); - $iterator->current()->willReturn($result)->shouldBeCalled(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); - $aggregationBuilderProphecy->hydrate(Dummy::class)->willReturn($aggregationBuilderProphecy)->shouldBeCalled(); - $aggregationBuilderProphecy->execute([])->willReturn($iterator->reveal())->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)); - } - - /** - * @group legacy - */ - public function testGetItemWrongCompositeIdentifier() - { - $this->expectException(PropertyNotFoundException::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $this->prophesize(Builder::class)->reveal(), [ - 'ida' => [ - 'type' => MongoDbType::INTEGER, - ], - 'idb' => [ - 'type' => MongoDbType::INTEGER, - ], - ]); - - $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getItem(Dummy::class, 'ida=1;', 'foo'); - } - - public function testAggregationResultExtension() - { - $matchProphecy = $this->prophesize(AggregationMatch::class); - $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); - $matchProphecy->equals(1)->shouldBeCalled(); - - $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(AggregationResultItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $extensionProphecy->supportsResult(Dummy::class, 'foo', $context)->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($aggregationBuilder, Dummy::class, 'foo', $context)->willReturn([])->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testUnsupportedClass() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); - } - - public function testCannotCreateAggregationBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository for "ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy" must be an instance of "Doctrine\ODM\MongoDB\Repository\DocumentRepository".'); - - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal()); - - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - - (new ItemDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo', null, [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]); - } - - /** - * Gets mocked metadata factories. - */ - private function getMetadataFactories(string $resourceClass, array $identifiers): array - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; - } - - /** - * Gets a mocked manager registry. - */ - private function getManagerRegistry(string $resourceClass, Builder $aggregationBuilder, array $identifierFields = []): ManagerRegistry - { - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(array_keys($identifierFields)); - - foreach ($identifierFields as $name => $field) { - $classMetadataProphecy->getTypeOfField($name)->willReturn($field['type']); - } - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal()); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal()); - - return $managerRegistryProphecy->reveal(); - } -} diff --git a/tests/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php b/tests/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php deleted file mode 100644 index 54def94b3d0..00000000000 --- a/tests/Core/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php +++ /dev/null @@ -1,541 +0,0 @@ - - * - * 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\Doctrine\MongoDbOdm; - -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\SubresourceDataProvider; -use ApiPlatform\Core\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel; -use Doctrine\ODM\MongoDB\Aggregation\Builder; -use Doctrine\ODM\MongoDB\Aggregation\Stage\Lookup; -use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch; -use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Iterator\Iterator; -use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\ODM\MongoDB\Repository\DocumentRepository; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @group mongodb - * - * @author Alan Poulain - */ -class SubresourceDataProviderTest extends TestCase -{ - use ProphecyTrait; - - private $resourceMetadataFactoryProphecy; - - /** - * {@inheritdoc} - */ - protected function setUp(): void - { - parent::setUp(); - - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - } - - private function getMetadataProphecies(array $resourceClassesIdentifiers) - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - foreach ($resourceClassesIdentifiers as $resourceClass => $identifiers) { - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - } - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; - } - - private function getManagerRegistryProphecy(Builder $aggregationBuilder, array $identifiers, string $resourceClass) - { - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->willReturn($aggregationBuilder); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass($resourceClass)->willReturn($managerProphecy->reveal()); - - return $managerRegistryProphecy->reveal(); - } - - public function testNotASubresource() - { - $this->expectException(ResourceClassNotSupportedException::class); - $this->expectExceptionMessage('The given resource class is not a subresource.'); - - $identifiers = ['id']; - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - $aggregationBuilder = $this->prophesize(Builder::class)->reveal(); - $managerRegistry = $this->getManagerRegistryProphecy($aggregationBuilder, $identifiers, Dummy::class); - - $dataProvider = new SubresourceDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, []); - - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testGetSubresource() - { - $aggregationBuilder = $this->prophesize(Builder::class); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $dummyAggregationBuilder = $this->prophesize(Builder::class); - $dummyLookup = $this->prophesize(Lookup::class); - $dummyLookup->alias('relatedDummies')->shouldBeCalled(); - $dummyAggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($dummyLookup->reveal()); - - $dummyMatch = $this->prophesize(AggregationMatch::class); - $dummyMatch->equals(1)->shouldBeCalled(); - $dummyMatch->field('id')->shouldBeCalled()->willReturn($dummyMatch); - $dummyAggregationBuilder->match()->shouldBeCalled()->willReturn($dummyMatch->reveal()); - - $dummyIterator = $this->prophesize(Iterator::class); - $dummyIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'relatedDummies' => [['_id' => 2]]]]); - $dummyAggregationBuilder->execute([])->shouldBeCalled()->willReturn($dummyIterator->reveal()); - - $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($dummyAggregationBuilder->reveal()); - - $match = $this->prophesize(AggregationMatch::class); - $match->in([2])->shouldBeCalled(); - $match->field('_id')->shouldBeCalled()->willReturn($match); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match); - - $iterator = $this->prophesize(Iterator::class); - $iterator->toArray()->shouldBeCalled()->willReturn([]); - $aggregationBuilder->execute([])->shouldBeCalled()->willReturn($iterator->reveal()); - $aggregationBuilder->hydrate(RelatedDummy::class)->shouldBeCalled()->willReturn($aggregationBuilder); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => ['id']]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testGetSubSubresourceItem() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - - // First manager (Dummy) - $dummyAggregationBuilder = $this->prophesize(Builder::class); - $dummyLookup = $this->prophesize(Lookup::class); - $dummyLookup->alias('relatedDummies')->shouldBeCalled(); - $dummyAggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($dummyLookup->reveal()); - - $dummyMatch = $this->prophesize(AggregationMatch::class); - $dummyMatch->equals(1)->shouldBeCalled(); - $dummyMatch->field('id')->shouldBeCalled()->willReturn($dummyMatch); - $dummyAggregationBuilder->match()->shouldBeCalled()->willReturn($dummyMatch->reveal()); - - $dummyIterator = $this->prophesize(Iterator::class); - $dummyIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'relatedDummies' => [['_id' => 2]]]]); - $dummyAggregationBuilder->execute([])->shouldBeCalled()->willReturn($dummyIterator->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - - $dummyManagerProphecy = $this->prophesize(DocumentManager::class); - $dummyManagerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($dummyAggregationBuilder->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $rAggregationBuilder = $this->prophesize(Builder::class); - $rLookup = $this->prophesize(Lookup::class); - $rLookup->alias('thirdLevel')->shouldBeCalled(); - $rAggregationBuilder->lookup('thirdLevel')->shouldBeCalled()->willReturn($rLookup->reveal()); - - $rMatch = $this->prophesize(AggregationMatch::class); - $rMatch->equals(1)->shouldBeCalled(); - $rMatch->field('id')->shouldBeCalled()->willReturn($rMatch); - $previousRMatch = $this->prophesize(AggregationMatch::class); - $previousRMatch->in([2])->shouldBeCalled(); - $previousRMatch->field('_id')->shouldBeCalled()->willReturn($previousRMatch); - $rAggregationBuilder->match()->shouldBeCalled()->willReturn($rMatch->reveal(), $previousRMatch->reveal()); - - $rIterator = $this->prophesize(Iterator::class); - $rIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'thirdLevel' => [['_id' => 3]]]]); - $rAggregationBuilder->execute([])->shouldBeCalled()->willReturn($rIterator->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('thirdLevel')->shouldBeCalled()->willReturn(true); - - $rDummyManagerProphecy = $this->prophesize(DocumentManager::class); - $rDummyManagerProphecy->createAggregationBuilder(RelatedDummy::class)->shouldBeCalled()->willReturn($rAggregationBuilder->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - // Origin manager (ThirdLevel) - $aggregationBuilder = $this->prophesize(Builder::class); - - $match = $this->prophesize(AggregationMatch::class); - $match->in([3])->shouldBeCalled(); - $match->field('_id')->shouldBeCalled()->willReturn($match); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match); - - $iterator = $this->prophesize(Iterator::class); - $iterator->current()->shouldBeCalled()->willReturn($result); - $aggregationBuilder->execute([])->shouldBeCalled()->willReturn($iterator->reveal()); - $aggregationBuilder->hydrate(ThirdLevel::class)->shouldBeCalled()->willReturn($aggregationBuilder); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(ThirdLevel::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(ThirdLevel::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'thirdLevel', 'identifiers' => ['id' => [Dummy::class, 'id'], 'relatedDummies' => [RelatedDummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context)); - } - - public function testGetSubSubresourceItemWithExecuteOptions() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - - // First manager (Dummy) - $dummyAggregationBuilder = $this->prophesize(Builder::class); - $dummyLookup = $this->prophesize(Lookup::class); - $dummyLookup->alias('relatedDummies')->shouldBeCalled(); - $dummyAggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($dummyLookup->reveal()); - - $dummyMatch = $this->prophesize(AggregationMatch::class); - $dummyMatch->equals(1)->shouldBeCalled(); - $dummyMatch->field('id')->shouldBeCalled()->willReturn($dummyMatch); - $dummyAggregationBuilder->match()->shouldBeCalled()->willReturn($dummyMatch->reveal()); - - $dummyIterator = $this->prophesize(Iterator::class); - $dummyIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'relatedDummies' => [['_id' => 2]]]]); - $dummyAggregationBuilder->execute(['allowDiskUse' => true])->shouldBeCalled()->willReturn($dummyIterator->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - - $dummyManagerProphecy = $this->prophesize(DocumentManager::class); - $dummyManagerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($dummyAggregationBuilder->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $rAggregationBuilder = $this->prophesize(Builder::class); - $rLookup = $this->prophesize(Lookup::class); - $rLookup->alias('thirdLevel')->shouldBeCalled(); - $rAggregationBuilder->lookup('thirdLevel')->shouldBeCalled()->willReturn($rLookup->reveal()); - - $rMatch = $this->prophesize(AggregationMatch::class); - $rMatch->equals(1)->shouldBeCalled(); - $rMatch->field('id')->shouldBeCalled()->willReturn($rMatch); - $previousRMatch = $this->prophesize(AggregationMatch::class); - $previousRMatch->in([2])->shouldBeCalled(); - $previousRMatch->field('_id')->shouldBeCalled()->willReturn($previousRMatch); - $rAggregationBuilder->match()->shouldBeCalled()->willReturn($rMatch->reveal(), $previousRMatch->reveal()); - - $rIterator = $this->prophesize(Iterator::class); - $rIterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'thirdLevel' => [['_id' => 3]]]]); - $rAggregationBuilder->execute(['allowDiskUse' => true])->shouldBeCalled()->willReturn($rIterator->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('thirdLevel')->shouldBeCalled()->willReturn(true); - - $rDummyManagerProphecy = $this->prophesize(DocumentManager::class); - $rDummyManagerProphecy->createAggregationBuilder(RelatedDummy::class)->shouldBeCalled()->willReturn($rAggregationBuilder->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - // Origin manager (ThirdLevel) - $aggregationBuilder = $this->prophesize(Builder::class); - - $match = $this->prophesize(AggregationMatch::class); - $match->in([3])->shouldBeCalled(); - $match->field('_id')->shouldBeCalled()->willReturn($match); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match); - - $iterator = $this->prophesize(Iterator::class); - $iterator->current()->shouldBeCalled()->willReturn($result); - $aggregationBuilder->execute(['allowDiskUse' => true])->shouldBeCalled()->willReturn($iterator->reveal()); - $aggregationBuilder->hydrate(ThirdLevel::class)->shouldBeCalled()->willReturn($aggregationBuilder); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(ThirdLevel::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(ThirdLevel::class)->willReturn(new ResourceMetadata( - 'ThirdLevel', - null, - null, - null, - null, - null, - ['third_level_operation_name' => ['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]]] - )); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'thirdLevel', 'identifiers' => ['id' => [Dummy::class, 'id'], 'relatedDummies' => [RelatedDummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context, 'third_level_operation_name')); - } - - public function testGetSubresourceOneToOneOwningRelation() - { - // RelatedOwningDummy OneToOne Dummy - $identifiers = ['id']; - $aggregationBuilder = $this->prophesize(Builder::class); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('ownedDummy')->willReturn(true)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $lookup = $this->prophesize(Lookup::class); - $lookup->alias('ownedDummy')->shouldBeCalled(); - $aggregationBuilder->lookup('ownedDummy')->shouldBeCalled()->willReturn($lookup->reveal()); - $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $match = $this->prophesize(AggregationMatch::class); - $match->equals(1)->shouldBeCalled(); - $match->field('id')->shouldBeCalled()->willReturn($match); - $previousMatch = $this->prophesize(AggregationMatch::class); - $previousMatch->in([3])->shouldBeCalled(); - $previousMatch->field('_id')->shouldBeCalled()->willReturn($previousMatch); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match->reveal(), $previousMatch->reveal()); - - $iterator = $this->prophesize(Iterator::class); - $iterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'ownedDummy' => [['_id' => 3]]]]); - $result = new \stdClass(); - $iterator->current()->shouldBeCalled()->willReturn($result); - $aggregationBuilder->execute([])->shouldBeCalled()->willReturn($iterator->reveal()); - $aggregationBuilder->hydrate(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($aggregationBuilder); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(RelatedOwningDummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'ownedDummy', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(RelatedOwningDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testAggregationResultExtension() - { - $identifiers = ['id']; - $aggregationBuilder = $this->prophesize(Builder::class); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $lookup = $this->prophesize(Lookup::class); - $lookup->alias('relatedDummies')->shouldBeCalled(); - $aggregationBuilder->lookup('relatedDummies')->shouldBeCalled()->willReturn($lookup->reveal()); - $managerProphecy->createAggregationBuilder(Dummy::class)->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $match = $this->prophesize(AggregationMatch::class); - $match->equals(1)->shouldBeCalled(); - $match->field('id')->shouldBeCalled()->willReturn($match); - $previousMatch = $this->prophesize(AggregationMatch::class); - $previousMatch->in([3])->shouldBeCalled(); - $previousMatch->field('_id')->shouldBeCalled()->willReturn($previousMatch); - $aggregationBuilder->match()->shouldBeCalled()->willReturn($match->reveal(), $previousMatch->reveal()); - - $iterator = $this->prophesize(Iterator::class); - $iterator->toArray()->shouldBeCalled()->willReturn([['_id' => 1, 'relatedDummies' => [['_id' => 3]]]]); - $aggregationBuilder->execute([])->shouldBeCalled()->willReturn($iterator->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $extensionProphecy = $this->prophesize(AggregationResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, RelatedDummy::class, null, Argument::type('array'))->shouldBeCalled(); - $extensionProphecy->supportsResult(RelatedDummy::class, null, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($aggregationBuilder, RelatedDummy::class, null, Argument::type('array'))->willReturn([])->shouldBeCalled(); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testCannotCreateQueryBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository for "ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy" must be an instance of "Doctrine\ODM\MongoDB\Repository\DocumentRepository".'); - - $identifiers = ['id']; - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(DocumentManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testThrowResourceClassNotSupportedException() - { - $this->expectException(ResourceClassNotSupportedException::class); - - $identifiers = ['id']; - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testGetSubresourceCollectionItem() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - - $rAggregationBuilder = $this->prophesize(Builder::class); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('id')->shouldBeCalled()->willReturn(false); - $rClassMetadataProphecy->isIdentifier('id')->shouldBeCalled()->willReturn(true); - - $rDummyManagerProphecy = $this->prophesize(DocumentManager::class); - $rDummyManagerProphecy->createAggregationBuilder(RelatedDummy::class)->shouldBeCalled()->willReturn($rAggregationBuilder->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - - $rIterator = $this->prophesize(Iterator::class); - $rIterator->current()->shouldBeCalled()->willReturn($result); - $rAggregationBuilder->execute([])->shouldBeCalled()->willReturn($rIterator->reveal()); - $rAggregationBuilder->hydrate(RelatedDummy::class)->shouldBeCalled()->willReturn($rAggregationBuilder); - - $aggregationBuilder = $this->prophesize(Builder::class); - - $repositoryProphecy = $this->prophesize(DocumentRepository::class); - $repositoryProphecy->createAggregationBuilder()->shouldBeCalled()->willReturn($aggregationBuilder->reveal()); - - $rDummyManagerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $this->resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'id', 'identifiers' => ['id' => [Dummy::class, 'id', true], [RelatedDummy::class, 'relatedDummies', true]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 2]], $context)); - } -} diff --git a/tests/Core/Bridge/Doctrine/Orm/CollectionDataProviderTest.php b/tests/Core/Bridge/Doctrine/Orm/CollectionDataProviderTest.php deleted file mode 100644 index a814cb70520..00000000000 --- a/tests/Core/Bridge/Doctrine/Orm/CollectionDataProviderTest.php +++ /dev/null @@ -1,114 +0,0 @@ - - * - * 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\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Orm\CollectionDataProvider; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\ORM\AbstractQuery; -use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Kévin Dunglas - */ -class CollectionDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetCollection() - { - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getResult()->willReturn([])->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilderProphecy->getQuery()->willReturn($queryProphecy->reveal())->shouldBeCalled(); - $queryBuilder = $queryBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(QueryCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, 'foo', [])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testQueryResultExtension() - { - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilder = $queryBuilderProphecy->reveal(); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(QueryResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, 'foo', [])->shouldBeCalled(); - $extensionProphecy->supportsResult(Dummy::class, 'foo', [])->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($queryBuilder, Dummy::class, 'foo', [])->willReturn([])->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testCannotCreateQueryBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository class must have a "createQueryBuilder" method.'); - - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $dataProvider = new CollectionDataProvider($managerRegistryProphecy->reveal()); - $this->assertEquals([], $dataProvider->getCollection(Dummy::class, 'foo')); - } - - public function testUnsupportedClass() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(QueryResultCollectionExtensionInterface::class); - - $dataProvider = new CollectionDataProvider($managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); - } -} diff --git a/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php b/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php deleted file mode 100644 index f3a47a8feea..00000000000 --- a/tests/Core/Bridge/Doctrine/Orm/ItemDataProviderTest.php +++ /dev/null @@ -1,305 +0,0 @@ - - * - * 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\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Exception\PropertyNotFoundException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\Types\Types; -use Doctrine\ORM\AbstractQuery; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\Expr; -use Doctrine\ORM\Query\Expr\Comparison; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class ItemDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetItemSingleIdentifier() - { - $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->willReturn([])->shouldBeCalled(); - - $comparisonProphecy = $this->prophesize(Comparison::class); - $comparison = $comparisonProphecy->reveal(); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->eq('o.id', ':id_p1')->willReturn($comparisonProphecy)->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilderProphecy->getQuery()->willReturn($queryProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->expr()->willReturn($exprProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->andWhere($comparison)->shouldBeCalled(); - $queryBuilderProphecy->getRootAliases()->shouldBeCalled()->willReturn(['o']); - $queryBuilderProphecy->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled(); - - $queryBuilder = $queryBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, [ - 'id' => [ - 'type' => Types::INTEGER, - ], - ], $queryBuilder); - - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testGetItemDoubleIdentifier() - { - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->willReturn([])->shouldBeCalled(); - - $comparisonProphecy = $this->prophesize(Comparison::class); - $comparison = $comparisonProphecy->reveal(); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->eq('o.ida', ':ida_p1')->willReturn($comparisonProphecy)->shouldBeCalled(); - $exprProphecy->eq('o.idb', ':idb_p2')->willReturn($comparisonProphecy)->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilderProphecy->getQuery()->willReturn($queryProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->expr()->willReturn($exprProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->andWhere($comparison)->shouldBeCalled(); - $queryBuilderProphecy->getRootAliases()->shouldBeCalled()->willReturn(['o']); - - $queryBuilderProphecy->setParameter('ida_p1', 1, Types::INTEGER)->shouldBeCalled(); - $queryBuilderProphecy->setParameter('idb_p2', 2, Types::INTEGER)->shouldBeCalled(); - - $queryBuilder = $queryBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, [ - 'ida' => [ - 'type' => Types::INTEGER, - ], - 'idb' => [ - 'type' => Types::INTEGER, - ], - ], $queryBuilder); - - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)); - } - - /** - * @group legacy - */ - public function testGetItemWrongCompositeIdentifier() - { - $this->expectException(PropertyNotFoundException::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'ida', - 'idb', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, [ - 'ida' => [ - 'type' => Types::INTEGER, - ], - 'idb' => [ - 'type' => Types::INTEGER, - ], - ], $this->prophesize(QueryBuilder::class)->reveal()); - - $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [], $resourceMetadataFactory); - $dataProvider->getItem(Dummy::class, 'ida=1;', 'foo'); - } - - public function testQueryResultExtension() - { - $comparisonProphecy = $this->prophesize(Comparison::class); - $comparison = $comparisonProphecy->reveal(); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->eq('o.id', ':id_p1')->willReturn($comparisonProphecy)->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - $queryBuilderProphecy->expr()->willReturn($exprProphecy->reveal())->shouldBeCalled(); - $queryBuilderProphecy->andWhere($comparison)->shouldBeCalled(); - $queryBuilderProphecy->getRootAliases()->shouldBeCalled()->willReturn(['o']); - $queryBuilderProphecy->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled(); - - $queryBuilder = $queryBuilderProphecy->reveal(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - $managerRegistry = $this->getManagerRegistry(Dummy::class, [ - 'id' => [ - 'type' => Types::INTEGER, - ], - ], $queryBuilder); - - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(QueryResultItemExtensionInterface::class); - $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $extensionProphecy->supportsResult(Dummy::class, 'foo', $context)->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($queryBuilder, Dummy::class, 'foo', $context)->willReturn([])->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); - } - - public function testUnsupportedClass() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); - } - - public function testCannotCreateQueryBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository class must have a "createQueryBuilder" method.'); - - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn([ - 'id', - ]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER); - - $platformProphecy = $this->prophesize(AbstractPlatform::class); - - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy->getDatabasePlatform()->willReturn($platformProphecy); - - $managerProphecy = $this->prophesize(EntityManagerInterface::class); - $managerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataProphecy->reveal()); - $managerProphecy->getConnection()->willReturn($connectionProphecy); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal()); - - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - - [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ - 'id', - ]); - - $itemDataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()], $resourceMetadataFactory); - $itemDataProvider->getItem(Dummy::class, ['id' => 1234], null, [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]); - } - - /** - * Gets mocked metadata factories. - */ - private function getMetadataFactories(string $resourceClass, array $identifiers): array - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - $resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('dummy')); - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()]; - } - - /** - * Gets a mocked manager registry. - */ - private function getManagerRegistry(string $resourceClass, array $identifierFields, QueryBuilder $queryBuilder): ManagerRegistry - { - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(array_keys($identifierFields)); - - foreach ($identifierFields as $name => $field) { - $classMetadataProphecy->getTypeOfField($name)->willReturn($field['type']); - } - - $platformProphecy = $this->prophesize(AbstractPlatform::class); - - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy->getDatabasePlatform()->willReturn($platformProphecy); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder); - - $managerProphecy = $this->prophesize(EntityManagerInterface::class); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - $managerProphecy->getConnection()->willReturn($connectionProphecy); - $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal()); - - return $managerRegistryProphecy->reveal(); - } -} diff --git a/tests/Core/Bridge/Doctrine/Orm/SubresourceDataProviderTest.php b/tests/Core/Bridge/Doctrine/Orm/SubresourceDataProviderTest.php deleted file mode 100644 index 32b412ee011..00000000000 --- a/tests/Core/Bridge/Doctrine/Orm/SubresourceDataProviderTest.php +++ /dev/null @@ -1,615 +0,0 @@ - - * - * 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\Doctrine\Orm; - -use ApiPlatform\Core\Bridge\Doctrine\Orm\SubresourceDataProvider; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\Types\Types; -use Doctrine\ORM\AbstractQuery; -use Doctrine\ORM\EntityManager; -use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\Expr; -use Doctrine\ORM\Query\Expr\Func; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use Doctrine\Persistence\ObjectRepository; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Kévin Dunglas - */ -class SubresourceDataProviderTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - private function assertIdentifierManagerMethodCalls($managerProphecy) - { - $platformProphecy = $this->prophesize(AbstractPlatform::class); - - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy->getDatabasePlatform()->willReturn($platformProphecy); - - $managerProphecy->getConnection()->willReturn($connectionProphecy); - } - - private function getMetadataProphecies(array $resourceClassesIdentifiers) - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - foreach ($resourceClassesIdentifiers as $resourceClass => $identifiers) { - $nameCollection = ['foobar']; - - foreach ($identifiers as $identifier) { - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); - - $nameCollection[] = $identifier; - } - - // random property to prevent the use of non-identifiers metadata while looping - $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); - - $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); - } - - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; - } - - private function getManagerRegistryProphecy(QueryBuilder $queryBuilder, array $identifiers, string $resourceClass) - { - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn($identifiers); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getClassMetadata($resourceClass)->willReturn($classMetadataProphecy->reveal()); - $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass($resourceClass)->willReturn($managerProphecy->reveal()); - - return $managerRegistryProphecy->reveal(); - } - - public function testNotASubresource() - { - $this->expectException(ResourceClassNotSupportedException::class); - $this->expectExceptionMessage('The given resource class is not a subresource.'); - - $identifiers = ['id']; - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - $queryBuilder = $this->prophesize(QueryBuilder::class)->reveal(); - $managerRegistry = $this->getManagerRegistryProphecy($queryBuilder, $identifiers, Dummy::class); - - $dataProvider = new SubresourceDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, []); - - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testGetSubresource() - { - $dql = 'SELECT relatedDummies_a2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a1 INNER JOIN id_a1.relatedDummies relatedDummies_a2 WHERE id_a1.id = :id_p1'; - - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getResult()->shouldBeCalled()->willReturn([]); - - $identifiers = ['id']; - $queryBuilder = $this->prophesize(QueryBuilder::class); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(EntityManager::class); - $managerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a2')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a1')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a1.relatedDummies', 'relatedDummies_a2')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a1.id = :id_p1')->shouldBeCalled()->willReturn($qb); - $qb->getDQL()->shouldBeCalled()->willReturn($dql); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->in('o', $dql)->willReturn($func)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($exprProphecy->reveal()); - - $managerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testGetSubSubresourceItem() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - // First manager (Dummy) - $dummyDQL = 'SELECT relatedDummies_a3 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a2 INNER JOIN id_a2.relatedDummies relatedDummies_a3 WHERE id_a2.id = :id_p2'; - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a2')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a2.relatedDummies', 'relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a2.id = :id_p2')->shouldBeCalled()->willReturn($qb); - - $dummyFunc = new Func('in', ['any']); - - $dummyExpProphecy = $this->prophesize(Expr::class); - $dummyExpProphecy->in('relatedDummies_a1', $dummyDQL)->willReturn($dummyFunc)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($dummyExpProphecy->reveal()); - - $qb->getDQL()->shouldBeCalled()->willReturn($dummyDQL); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $dummyManagerProphecy = $this->prophesize(EntityManager::class); - $dummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($dummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $relatedDQL = 'SELECT IDENTITY(relatedDummies_a1.thirdLevel) FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy relatedDummies_a1 WHERE relatedDummies_a1.id = :id_p1 AND relatedDummies_a1 IN(SELECT relatedDummies_a3 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a2 INNER JOIN id_a2.relatedDummies relatedDummies_a3 WHERE id_a2.id = :id_p2)'; - - $rqb = $this->prophesize(QueryBuilder::class); - $rqb->select('IDENTITY(relatedDummies_a1.thirdLevel)')->shouldBeCalled()->willReturn($rqb); - $rqb->from(RelatedDummy::class, 'relatedDummies_a1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere('relatedDummies_a1.id = :id_p1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere($dummyFunc)->shouldBeCalled()->willReturn($rqb); - $rqb->getDQL()->shouldBeCalled()->willReturn($relatedDQL); - - $relatedExpProphecy = $this->prophesize(Expr::class); - $relatedExpProphecy->in('o', $relatedDQL)->willReturn($func)->shouldBeCalled(); - - $rqb->expr()->shouldBeCalled()->willReturn($relatedExpProphecy->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('thirdLevel')->shouldBeCalled()->willReturn(true); - $rClassMetadataProphecy->getAssociationMapping('thirdLevel')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_ONE]); - $rClassMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $rDummyManagerProphecy = $this->prophesize(EntityManager::class); - $rDummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($rqb->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($rDummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - // Origin manager (ThirdLevel) - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn($result); - - $queryBuilder = $this->prophesize(QueryBuilder::class); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $queryBuilder->setParameter('id_p2', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(ThirdLevel::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'thirdLevel', 'identifiers' => ['id' => [Dummy::class, 'id'], 'relatedDummies' => [RelatedDummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context)); - } - - public function testGetSubresourceOneToOneOwningRelation() - { - // RelatedOwningDummy OneToOne Dummy - $dql = 'SELECT ownedDummy_a2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a1 INNER JOIN id_a1.ownedDummy ownedDummy_a2 WHERE id_a1.id = :id_p1'; - - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn([]); - - $identifiers = ['id']; - $queryBuilder = $this->prophesize(QueryBuilder::class); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(EntityManager::class); - $managerProphecy->getRepository(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('ownedDummy')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('ownedDummy')->shouldBeCalled()->willReturn(['type' => ClassMetadata::ONE_TO_ONE]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('IDENTITY(id_a1.ownedDummy)')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a1')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a1.id = :id_p1')->shouldBeCalled()->willReturn($qb); - $qb->getDQL()->shouldBeCalled()->willReturn($dql); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->in('o', $dql)->willReturn($func)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($exprProphecy->reveal()); - - $managerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedOwningDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'ownedDummy', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedOwningDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testQueryResultExtension() - { - $dql = 'SELECT relatedDummies_a2 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a1 INNER JOIN id_a1.relatedDummies relatedDummies_a2 WHERE id_a1.id = :id_p1'; - - $identifiers = ['id']; - $queryBuilder = $this->prophesize(QueryBuilder::class); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(EntityManager::class); - $managerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->willReturn(Types::INTEGER)->shouldBeCalled(); - - $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a2')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a1')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a1.relatedDummies', 'relatedDummies_a2')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a1.id = :id_p1')->shouldBeCalled()->willReturn($qb); - $qb->getDQL()->shouldBeCalled()->willReturn($dql); - - $exprProphecy = $this->prophesize(Expr::class); - $exprProphecy->in('o', $dql)->willReturn($func)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($exprProphecy->reveal()); - - $managerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - $this->assertIdentifierManagerMethodCalls($managerProphecy); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $extensionProphecy = $this->prophesize(QueryResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), RelatedDummy::class, null, Argument::type('array'))->shouldBeCalled(); - $extensionProphecy->supportsResult(RelatedDummy::class, null, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($queryBuilder, RelatedDummy::class, null, Argument::type('array'))->willReturn([])->shouldBeCalled(); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - - $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); - } - - public function testCannotCreateQueryBuilder() - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('The repository class must have a "createQueryBuilder" method.'); - - $identifiers = ['id']; - $repositoryProphecy = $this->prophesize(ObjectRepository::class); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - public function testThrowResourceClassNotSupportedException() - { - $this->expectException(ResourceClassNotSupportedException::class); - - $identifiers = ['id']; - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $dataProvider->getSubresource(Dummy::class, ['id' => 1], []); - } - - /** - * @group legacy - */ - public function testGetSubSubresourceItemLegacy() - { - $this->expectDeprecation('Identifiers should match the convention introduced in ADR 0001-resource-identifiers, this behavior will be removed in 3.0.'); - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - // First manager (Dummy) - $dummyDQL = 'SELECT relatedDummies_a3 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a2 INNER JOIN id_a2.relatedDummies relatedDummies_a3 WHERE id_a2.id = :id_p2'; - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a2')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a2.relatedDummies', 'relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a2.id = :id_p2')->shouldBeCalled()->willReturn($qb); - - $dummyFunc = new Func('in', ['any']); - - $dummyExpProphecy = $this->prophesize(Expr::class); - $dummyExpProphecy->in('relatedDummies_a1', $dummyDQL)->willReturn($dummyFunc)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($dummyExpProphecy->reveal()); - - $qb->getDQL()->shouldBeCalled()->willReturn($dummyDQL); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn($identifiers); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->shouldBeCalled()->willReturn(Types::INTEGER); - - $dummyManagerProphecy = $this->prophesize(EntityManager::class); - $dummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($dummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $relatedDQL = 'SELECT IDENTITY(relatedDummies_a1.thirdLevel) FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy relatedDummies_a1 WHERE relatedDummies_a1.id = :id_p1 AND relatedDummies_a1 IN(SELECT relatedDummies_a3 FROM ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy id_a2 INNER JOIN id_a2.relatedDummies relatedDummies_a3 WHERE id_a2.id = :id_p2)'; - - $rqb = $this->prophesize(QueryBuilder::class); - $rqb->select('IDENTITY(relatedDummies_a1.thirdLevel)')->shouldBeCalled()->willReturn($rqb); - $rqb->from(RelatedDummy::class, 'relatedDummies_a1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere('relatedDummies_a1.id = :id_p1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere($dummyFunc)->shouldBeCalled()->willReturn($rqb); - $rqb->getDQL()->shouldBeCalled()->willReturn($relatedDQL); - - $relatedExpProphecy = $this->prophesize(Expr::class); - $relatedExpProphecy->in('o', $relatedDQL)->willReturn($func)->shouldBeCalled(); - - $rqb->expr()->shouldBeCalled()->willReturn($relatedExpProphecy->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn($identifiers); - $rClassMetadataProphecy->getTypeOfField('id')->shouldBeCalled()->willReturn(Types::INTEGER); - $rClassMetadataProphecy->hasAssociation('thirdLevel')->shouldBeCalled()->willReturn(true); - $rClassMetadataProphecy->getAssociationMapping('thirdLevel')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_ONE]); - - $rDummyManagerProphecy = $this->prophesize(EntityManager::class); - $rDummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($rqb->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($rDummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - // Origin manager (ThirdLevel) - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn($result); - - $queryBuilder = $this->prophesize(QueryBuilder::class); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - $queryBuilder->setParameter('id_p1', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $queryBuilder->setParameter('id_p2', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(ThirdLevel::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - $managerRegistryProphecy->getManagerForClass(ThirdLevel::class)->shouldBeCalled()->willReturn($managerProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'thirdLevel', 'identifiers' => [['id', Dummy::class], ['relatedDummies', RelatedDummy::class]], 'collection' => false]; - - $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => 1, 'relatedDummies' => 1], $context)); - } - - public function testGetSubresourceCollectionItem() - { - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $identifiers = ['id']; - $funcProphecy = $this->prophesize(Func::class); - $func = $funcProphecy->reveal(); - - // First manager (Dummy) - $dummyDQL = 'dql'; - - $qb = $this->prophesize(QueryBuilder::class); - $qb->select('relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->from(Dummy::class, 'id_a2')->shouldBeCalled()->willReturn($qb); - $qb->innerJoin('id_a2.relatedDummies', 'relatedDummies_a3')->shouldBeCalled()->willReturn($qb); - $qb->andWhere('id_a2.id = :id_p2')->shouldBeCalled()->willReturn($qb); - - $dummyFunc = new Func('in', ['any']); - - $dummyExpProphecy = $this->prophesize(Expr::class); - $dummyExpProphecy->in('relatedDummies_a1', $dummyDQL)->willReturn($dummyFunc)->shouldBeCalled(); - - $qb->expr()->shouldBeCalled()->willReturn($dummyExpProphecy->reveal()); - - $qb->getDQL()->shouldBeCalled()->willReturn($dummyDQL); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->hasAssociation('relatedDummies')->willReturn(true)->shouldBeCalled(); - $classMetadataProphecy->getAssociationMapping('relatedDummies')->shouldBeCalled()->willReturn(['type' => ClassMetadata::MANY_TO_MANY]); - $classMetadataProphecy->getTypeOfField('id')->shouldBeCalled()->willReturn(Types::INTEGER); - - $dummyManagerProphecy = $this->prophesize(EntityManager::class); - $dummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($qb->reveal()); - $dummyManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($dummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($dummyManagerProphecy->reveal()); - - // Second manager (RelatedDummy) - $relatedDQL = 'relateddql'; - - $rqb = $this->prophesize(QueryBuilder::class); - $rqb->select('relatedDummies_a1')->shouldBeCalled()->willReturn($rqb); - $rqb->from(RelatedDummy::class, 'relatedDummies_a1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere('relatedDummies_a1.id = :id_p1')->shouldBeCalled()->willReturn($rqb); - $rqb->andWhere($dummyFunc)->shouldBeCalled()->willReturn($rqb); - $rqb->getDQL()->shouldBeCalled()->willReturn($relatedDQL); - - $relatedExpProphecy = $this->prophesize(Expr::class); - $relatedExpProphecy->in('o', $relatedDQL)->willReturn($func)->shouldBeCalled(); - - $rqb->expr()->shouldBeCalled()->willReturn($relatedExpProphecy->reveal()); - - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - $rClassMetadataProphecy->hasAssociation('id')->shouldBeCalled()->willReturn(false); - $rClassMetadataProphecy->isIdentifier('id')->shouldBeCalled()->willReturn(true); - $rClassMetadataProphecy->getTypeOfField('id')->shouldBeCalled()->willReturn(Types::INTEGER); - - $rDummyManagerProphecy = $this->prophesize(EntityManager::class); - $rDummyManagerProphecy->createQueryBuilder()->shouldBeCalled()->willReturn($rqb->reveal()); - $rDummyManagerProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($rClassMetadataProphecy->reveal()); - $this->assertIdentifierManagerMethodCalls($rDummyManagerProphecy); - - $managerRegistryProphecy->getManagerForClass(RelatedDummy::class)->shouldBeCalled()->willReturn($rDummyManagerProphecy->reveal()); - - $result = new \stdClass(); - $queryProphecy = $this->prophesize(AbstractQuery::class); - $queryProphecy->getOneOrNullResult()->shouldBeCalled()->willReturn($result); - - $queryBuilder = $this->prophesize(QueryBuilder::class); - - $queryBuilder->andWhere($func)->shouldBeCalled()->willReturn($queryBuilder); - - $queryBuilder->getQuery()->shouldBeCalled()->willReturn($queryProphecy->reveal()); - $queryBuilder->setParameter('id_p1', 2, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - $queryBuilder->setParameter('id_p2', 1, Types::INTEGER)->shouldBeCalled()->willReturn($queryBuilder); - - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->shouldBeCalled()->willReturn($queryBuilder->reveal()); - - $rDummyManagerProphecy->getRepository(RelatedDummy::class)->shouldBeCalled()->willReturn($repositoryProphecy->reveal()); - - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataProphecies([Dummy::class => $identifiers, RelatedDummy::class => $identifiers]); - - $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - - $context = ['property' => 'id', 'identifiers' => ['id' => [Dummy::class, 'id', true], 'relatedDummies' => [RelatedDummy::class, 'id', true]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $this->assertEquals($result, $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 2]], $context)); - } -} diff --git a/tests/Core/Bridge/Elasticsearch/Api/IdentifierExtractorTest.php b/tests/Core/Bridge/Elasticsearch/Api/IdentifierExtractorTest.php deleted file mode 100644 index a83edb0c647..00000000000 --- a/tests/Core/Bridge/Elasticsearch/Api/IdentifierExtractorTest.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * 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\Elasticsearch\Api; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractor; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -class IdentifierExtractorTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - self::assertInstanceOf( - IdentifierExtractorInterface::class, - new IdentifierExtractor($this->prophesize(IdentifiersExtractorInterface::class)->reveal()) - ); - } - - public function testGetIdentifierFromResourceClass() - { - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Dummy::class)->willReturn(['id'])->shouldBeCalled(); - - $identifierExtractor = new IdentifierExtractor($identifiersExtractorProphecy->reveal()); - - self::assertSame('id', $identifierExtractor->getIdentifierFromResourceClass(Dummy::class)); - } - - public function testGetIdentifierFromResourceClassWithCompositeIdentifiers() - { - $this->expectException(NonUniqueIdentifierException::class); - $this->expectExceptionMessage('Composite identifiers not supported.'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(CompositeRelation::class)->willReturn(['compositeItem', 'compositeLabel'])->shouldBeCalled(); - - $identifierExtractor = new IdentifierExtractor($identifiersExtractorProphecy->reveal()); - $identifierExtractor->getIdentifierFromResourceClass(CompositeRelation::class); - } - - public function testGetIdentifierFromResourceClassWithNoIdentifier() - { - $this->expectException(NonUniqueIdentifierException::class); - $this->expectExceptionMessage('Resource "ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy" has no identifiers.'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Dummy::class)->willReturn([])->shouldBeCalled(); - - $identifierExtractor = new IdentifierExtractor($identifiersExtractorProphecy->reveal()); - $identifierExtractor->getIdentifierFromResourceClass(Dummy::class); - } -} diff --git a/tests/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php b/tests/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php deleted file mode 100644 index f2fc0809db7..00000000000 --- a/tests/Core/Bridge/Elasticsearch/DataProvider/CollectionDataProviderTest.php +++ /dev/null @@ -1,186 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider; - -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\CollectionDataProvider; -use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; -use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; -use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\State\Pagination\Pagination; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarColor; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; -use Elasticsearch\Client; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * @group legacy - * @requires PHP >= 7.4 - */ -class CollectionDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - self::assertInstanceOf( - CollectionDataProviderInterface::class, - new CollectionDataProvider( - $this->prophesize(Client::class)->reveal(), - $this->prophesize(DocumentMetadataFactoryInterface::class)->reveal(), - $this->prophesize(IdentifierExtractorInterface::class)->reveal(), - $this->prophesize(DenormalizerInterface::class)->reveal(), - new Pagination($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal() - ) - ); - } - - public function testSupports() - { - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - $documentMetadataFactoryProphecy->create(Dummy::class)->willThrow(new IndexNotFoundException())->shouldBeCalled(); - $documentMetadataFactoryProphecy->create(CompositeRelation::class)->willReturn(new DocumentMetadata('composite_relation'))->shouldBeCalled(); - - $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $identifierExtractorProphecy->getIdentifierFromResourceClass(CompositeRelation::class)->willThrow(new NonUniqueIdentifierException())->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata())->withAttributes(['elasticsearch' => false])); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyCarColor::class)->shouldBeCalled()->willThrow(new ResourceClassNotFoundException()); - - $collectionDataProvider = new CollectionDataProvider( - $this->prophesize(Client::class)->reveal(), - $documentMetadataFactoryProphecy->reveal(), - $identifierExtractorProphecy->reveal(), - $this->prophesize(DenormalizerInterface::class)->reveal(), - new Pagination($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()), - $resourceMetadataFactoryProphecy->reveal() - ); - - self::assertTrue($collectionDataProvider->supports(Foo::class)); - self::assertFalse($collectionDataProvider->supports(Dummy::class)); - self::assertFalse($collectionDataProvider->supports(CompositeRelation::class)); - self::assertFalse($collectionDataProvider->supports(DummyCar::class)); - self::assertFalse($collectionDataProvider->supports(DummyCarColor::class)); - } - - public function testGetCollection() - { - $context = [ - 'groups' => ['custom'], - ]; - - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->willReturn(new ResourceMetadata()); - - $documents = [ - 'took' => 15, - 'time_out' => false, - '_shards' => [ - 'total' => 5, - 'successful' => 5, - 'skipped' => 0, - 'failed' => 0, - ], - 'hits' => [ - 'total' => 4, - 'max_score' => 1, - 'hits' => [ - [ - '_index' => 'foo', - '_type' => '_doc', - '_id' => '1', - '_score' => 1, - '_source' => [ - 'id' => 1, - 'name' => 'Kilian', - 'bar' => 'Jornet', - ], - ], - [ - '_index' => 'foo', - '_type' => '_doc', - '_id' => '2', - '_score' => 1, - '_source' => [ - 'id' => 2, - 'name' => 'François', - 'bar' => 'D\'Haene', - ], - ], - ], - ], - ]; - - $clientProphecy = $this->prophesize(Client::class); - $clientProphecy - ->search( - Argument::allOf( - Argument::withEntry('index', 'foo'), - Argument::withEntry('body', Argument::allOf( - Argument::withEntry('size', 2), - Argument::withEntry('from', 0), - Argument::withEntry('query', Argument::allOf( - Argument::withEntry('match_all', Argument::type(\stdClass::class)), - Argument::size(1) - )), - Argument::size(3) - )), - Argument::size(2) - ) - ) - ->willReturn($documents) - ->shouldBeCalled(); - - $requestBodySearchCollectionExtensionProphecy = $this->prophesize(RequestBodySearchCollectionExtensionInterface::class); - $requestBodySearchCollectionExtensionProphecy->applyToCollection([], Foo::class, 'get', $context)->willReturn([])->shouldBeCalled(); - - $collectionDataProvider = new CollectionDataProvider( - $clientProphecy->reveal(), - $documentMetadataFactoryProphecy->reveal(), - $this->prophesize(IdentifierExtractorInterface::class)->reveal(), - $denormalizer = $this->prophesize(DenormalizerInterface::class)->reveal(), - new Pagination($resourceMetadataFactoryProphecy->reveal(), ['items_per_page' => 2]), - $resourceMetadataFactoryProphecy->reveal(), - [$requestBodySearchCollectionExtensionProphecy->reveal()] - ); - - self::assertEquals( - new Paginator($denormalizer, $documents, Foo::class, 2, 0, $context), - $collectionDataProvider->getCollection(Foo::class, 'get', $context) - ); - } -} diff --git a/tests/Core/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php b/tests/Core/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php deleted file mode 100644 index adfe2f6c3a2..00000000000 --- a/tests/Core/Bridge/Elasticsearch/DataProvider/ItemDataProviderTest.php +++ /dev/null @@ -1,149 +0,0 @@ - - * - * 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\Elasticsearch\DataProvider; - -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\ItemDataProvider; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; -use ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException; -use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; -use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; -use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarColor; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; -use Elasticsearch\Client; -use Elasticsearch\Common\Exceptions\Missing404Exception; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * @group legacy - * @requires PHP >= 7.4 - */ -class ItemDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - self::assertInstanceOf( - ItemDataProviderInterface::class, - new ItemDataProvider( - $this->prophesize(Client::class)->reveal(), - $this->prophesize(DocumentMetadataFactoryInterface::class)->reveal(), - $this->prophesize(IdentifierExtractorInterface::class)->reveal(), - $this->prophesize(DenormalizerInterface::class)->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal() - ) - ); - } - - public function testSupports() - { - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - $documentMetadataFactoryProphecy->create(Dummy::class)->willThrow(new IndexNotFoundException())->shouldBeCalled(); - $documentMetadataFactoryProphecy->create(CompositeRelation::class)->willReturn(new DocumentMetadata('composite_relation'))->shouldBeCalled(); - - $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $identifierExtractorProphecy->getIdentifierFromResourceClass(CompositeRelation::class)->willThrow(new NonUniqueIdentifierException())->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Foo::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(CompositeRelation::class)->shouldBeCalled()->willReturn(new ResourceMetadata()); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->shouldBeCalled()->willReturn((new ResourceMetadata())->withAttributes(['elasticsearch' => false])); - $resourceMetadataFactoryProphecy->create(DummyCarColor::class)->shouldBeCalled()->willThrow(new ResourceClassNotFoundException()); - - $itemDataProvider = new ItemDataProvider( - $this->prophesize(Client::class)->reveal(), - $documentMetadataFactoryProphecy->reveal(), - $identifierExtractorProphecy->reveal(), - $this->prophesize(DenormalizerInterface::class)->reveal(), - $resourceMetadataFactoryProphecy->reveal() - ); - - self::assertTrue($itemDataProvider->supports(Foo::class)); - self::assertFalse($itemDataProvider->supports(Dummy::class)); - self::assertFalse($itemDataProvider->supports(CompositeRelation::class)); - self::assertFalse($itemDataProvider->supports(DummyCar::class)); - self::assertFalse($itemDataProvider->supports(DummyCarColor::class)); - } - - public function testGetItem() - { - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - - $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - - $document = [ - '_index' => 'foo', - '_type' => '_doc', - '_id' => '1', - '_version' => 1, - 'found' => true, - '_source' => [ - 'id' => 1, - 'name' => 'Rossinière', - 'bar' => 'erèinissor', - ], - ]; - - $foo = new Foo(); - $foo->setName('Rossinière'); - $foo->setBar('erèinissor'); - - $clientProphecy = $this->prophesize(Client::class); - $clientProphecy->get(['index' => 'foo', 'id' => '1'])->willReturn($document)->shouldBeCalled(); - - $denormalizerProphecy = $this->prophesize(DenormalizerInterface::class); - $denormalizerProphecy->denormalize($document, Foo::class, DocumentNormalizer::FORMAT, [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true])->willReturn($foo)->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $itemDataProvider = new ItemDataProvider($clientProphecy->reveal(), $documentMetadataFactoryProphecy->reveal(), $identifierExtractorProphecy->reveal(), $denormalizerProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - - self::assertSame($foo, $itemDataProvider->getItem(Foo::class, ['id' => 1])); - } - - public function testGetItemWithMissing404Exception() - { - $documentMetadataFactoryProphecy = $this->prophesize(DocumentMetadataFactoryInterface::class); - $documentMetadataFactoryProphecy->create(Foo::class)->willReturn(new DocumentMetadata('foo'))->shouldBeCalled(); - - $identifierExtractorProphecy = $this->prophesize(IdentifierExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - - $clientProphecy = $this->prophesize(Client::class); - $clientProphecy->get(['index' => 'foo', 'id' => '404'])->willThrow(new Missing404Exception())->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $itemDataProvider = new ItemDataProvider($clientProphecy->reveal(), $documentMetadataFactoryProphecy->reveal(), $identifierExtractorProphecy->reveal(), $this->prophesize(DenormalizerInterface::class)->reveal(), $resourceMetadataFactoryProphecy->reveal()); - - self::assertNull($itemDataProvider->getItem(Foo::class, ['id' => 404])); - } -} diff --git a/tests/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php b/tests/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php deleted file mode 100644 index 7ade6ced88f..00000000000 --- a/tests/Core/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactoryTest.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * 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\Elasticsearch\Metadata\Resource\Factory; - -use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Resource\Factory\ElasticsearchOperationResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class ElasticsearchOperationResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - self::assertInstanceOf( - ResourceMetadataFactoryInterface::class, - new ElasticsearchOperationResourceMetadataFactory($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal()) - ); - } - - public function testCreate() - { - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(Foo::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - - $resourceMetadata = (new ElasticsearchOperationResourceMetadataFactory($decoratedProphecy->reveal()))->create(Foo::class); - - self::assertSame(['get' => ['method' => 'GET']], $resourceMetadata->getCollectionOperations()); - self::assertSame(['get' => ['method' => 'GET']], $resourceMetadata->getItemOperations()); - } - - public function testCreateWithExistingOperations() - { - $originalResourceMetadata = new ResourceMetadata(); - $originalResourceMetadata = $originalResourceMetadata->withItemOperations(['foo' => ['method' => 'GET']]); - $originalResourceMetadata = $originalResourceMetadata->withCollectionOperations(['bar' => ['method' => 'GET']]); - - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(Foo::class)->willReturn($originalResourceMetadata)->shouldBeCalled(); - - $resourceMetadata = (new ElasticsearchOperationResourceMetadataFactory($decoratedProphecy->reveal()))->create(Foo::class); - - self::assertSame($originalResourceMetadata, $resourceMetadata); - self::assertSame(['foo' => ['method' => 'GET']], $resourceMetadata->getItemOperations()); - self::assertSame(['bar' => ['method' => 'GET']], $resourceMetadata->getCollectionOperations()); - } -} diff --git a/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php b/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php deleted file mode 100644 index b3e1f2afee9..00000000000 --- a/tests/Core/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php +++ /dev/null @@ -1,569 +0,0 @@ - - * - * 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\NelmioApiDoc\Extractor\AnnotationsProvider; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider; -use ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser; -use ApiPlatform\Core\Bridge\Symfony\Routing\OperationMethodResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use Nelmio\ApiDocBundle\Annotation\ApiDoc; -use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface; -use Nelmio\ApiDocBundle\NelmioApiDocBundle; -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * @author Teoh Han Hui - * - * @group legacy - */ -class ApiPlatformProviderTest extends TestCase -{ - use ProphecyTrait; - - protected function setUp(): void - { - if (!class_exists(NelmioApiDocBundle::class)) { - $this->markTestSkipped('NelmioApiDocBundle is not installed.'); - } - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testConstruct() - { - $apiPlatformProvider = new ApiPlatformProvider( - $this->prophesize(ResourceNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(NormalizerInterface::class)->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - - $this->assertInstanceOf(AnnotationsProviderInterface::class, $apiPlatformProvider); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testGetAnnotations() - { - $dummySearchFilterProphecy = $this->prophesize(FilterInterface::class); - $dummySearchFilterProphecy->getDescription(Dummy::class)->willReturn([ - 'name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => 'false', - 'strategy' => 'partial', - ], - ])->shouldBeCalled(); - - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filterLocatorProphecy->has('my_dummy.search')->willReturn(true)->shouldBeCalled(); - $filterLocatorProphecy->get('my_dummy.search')->willReturn($dummySearchFilterProphecy->reveal())->shouldBeCalled(); - - $this->extractAnnotations($filterLocatorProphecy->reveal()); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testGetAnnotationsWithDeprecatedFilterCollection() - { - $dummySearchFilterProphecy = $this->prophesize(FilterInterface::class); - $dummySearchFilterProphecy->getDescription(Dummy::class)->willReturn([ - 'name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => 'false', - 'strategy' => 'partial', - ], - ])->shouldBeCalled(); - - $this->extractAnnotations(new FilterCollection(['my_dummy.search' => $dummySearchFilterProphecy->reveal()])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testConstructWithInvalidFilterLocator() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface.'); - - new ApiPlatformProvider( - $this->prophesize(ResourceNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(NormalizerInterface::class)->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - new \ArrayObject(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - } - - private function extractAnnotations($filterLocator) - { - $resourceNameCollection = new ResourceNameCollection([Dummy::class, RelatedDummy::class]); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn($resourceNameCollection)->shouldBeCalled(); - - $apiDocumentationBuilderProphecy = $this->prophesize(NormalizerInterface::class); - $apiDocumentationBuilderProphecy->normalize(new Documentation($resourceNameCollection))->willReturn($this->getHydraDoc())->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withItemOperations([ - 'get' => [ - 'method' => 'GET', - ], - 'put' => [ - 'method' => 'PUT', - ], - 'delete' => [ - 'method' => 'DELETE', - ], - ]) - ->withCollectionOperations([ - 'get' => [ - 'filters' => [ - 'my_dummy.search', - ], - 'method' => 'GET', - ], - 'post' => [ - 'method' => 'POST', - ], - ]); - - $relatedDummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('RelatedDummy'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyResourceMetadata)->shouldBeCalled(); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'post')->willReturn('POST')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'put')->willReturn('PUT')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'delete')->willReturn('DELETE')->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationRoute(Dummy::class, 'get')->willReturn((new Route('/dummies'))->setMethods(['GET']))->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationRoute(Dummy::class, 'post')->willReturn((new Route('/dummies'))->setMethods(['POST']))->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'get')->willReturn((new Route('/dummies/{id}'))->setMethods(['GET']))->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'put')->willReturn((new Route('/dummies/{id}'))->setMethods(['PUT']))->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'delete')->willReturn((new Route('/dummies/{id}'))->setMethods(['DELETE']))->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $apiDocumentationBuilderProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $filterLocator, - $operationMethodResolverProphecy->reveal() - ); - - $annotations = $apiPlatformProvider->getAnnotations(); - - $this->assertCount(5, $annotations); - - $expectedResults = [ - [ - 'resource' => '/dummies', - 'description' => 'Retrieves the collection of Dummy resources.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => null, - 'output' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - 'filters' => [ - 'name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => 'false', - 'strategy' => 'partial', - ], - ], - 'path' => '/dummies', - 'methods' => ['GET'], - ], - [ - 'resource' => '/dummies', - 'description' => 'Creates a Dummy resource.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => sprintf('%s:%s:%s', ApiPlatformParser::IN_PREFIX, Dummy::class, 'post'), - 'output' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'post'), - 'filters' => [], - 'path' => '/dummies', - 'methods' => ['POST'], - ], - [ - 'resource' => '/dummies/{id}', - 'description' => 'Retrieves Dummy resource.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => null, - 'output' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - 'filters' => [], - 'path' => '/dummies/{id}', - 'methods' => ['GET'], - ], - [ - 'resource' => '/dummies/{id}', - 'description' => 'Replaces the Dummy resource.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => sprintf('%s:%s:%s', ApiPlatformParser::IN_PREFIX, Dummy::class, 'put'), - 'output' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'put'), - 'filters' => [], - 'path' => '/dummies/{id}', - 'methods' => ['PUT'], - ], - [ - 'resource' => '/dummies/{id}', - 'description' => 'Deletes the Dummy resource.', - 'resource_description' => 'Dummy', - 'section' => 'Dummy', - 'input' => null, - 'output' => null, - 'filters' => [], - 'path' => '/dummies/{id}', - 'methods' => ['DELETE'], - ], - ]; - - foreach ($expectedResults as $i => $expected) { - /** @var ApiDoc $apiDoc */ - $apiDoc = $annotations[$i]; - - $this->assertInstanceOf(ApiDoc::class, $apiDoc); - $this->assertEquals($expected['resource'], $apiDoc->getResource()); - $this->assertEquals($expected['description'], $apiDoc->getDescription()); - $this->assertEquals($expected['resource_description'], $apiDoc->getResourceDescription()); - $this->assertEquals($expected['section'], $apiDoc->getSection()); - $this->assertEquals($expected['input'], $apiDoc->getInput()); - $this->assertEquals($expected['output'], $apiDoc->getOutput()); - $this->assertEquals($expected['filters'], $apiDoc->getFilters()); - $this->assertInstanceOf(Route::class, $apiDoc->getRoute()); - $this->assertEquals($expected['path'], $apiDoc->getRoute()->getPath()); - $this->assertEquals($expected['methods'], $apiDoc->getRoute()->getMethods()); - } - } - - private function getHydraDoc() - { - $hydraDocJson = <<<'JSON' - { - "hydra:supportedClass": [ - { - "@id": "#Dummy", - "hydra:title": "Dummy", - "hydra:supportedOperation": [ - { - "hydra:method": "GET", - "hydra:title": "Retrieves Dummy resource.", - "returns": "#Dummy" - }, - { - "expects": "#Dummy", - "hydra:method": "PUT", - "hydra:title": "Replaces the Dummy resource.", - "returns": "#Dummy" - }, - { - "hydra:method": "DELETE", - "hydra:title": "Deletes the Dummy resource.", - "returns": "owl:Nothing" - } - ] - }, - { - "@id": "#Entrypoint", - "hydra:supportedProperty": [ - { - "hydra:property": { - "@id": "#Entrypoint\/dummy", - "hydra:supportedOperation": [ - { - "hydra:method": "GET", - "hydra:title": "Retrieves the collection of Dummy resources.", - "returns": "hydra:PagedCollection" - }, - { - "expects": "#Dummy", - "hydra:method": "POST", - "hydra:title": "Creates a Dummy resource.", - "returns": "#Dummy" - } - ] - } - } - ] - } - ] - } -JSON; - - return json_decode($hydraDocJson, true); - } - - public function testGetAnnotationsWithEmptyHydraDoc() - { - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn([])->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - - $this->assertEquals([], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithInvalidHydraSupportedClass() - { - $hydraDoc = ['hydra:supportedClass' => 'not an array']; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - - $this->assertEquals([], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithEmptyHydraSupportedClass() - { - $hydraDoc = ['hydra:supportedClass' => []]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal() - ); - - $this->assertEquals([], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithInvalidHydraSupportedOperation() - { - $hydraDoc = ['hydra:supportedClass' => [ - ['@id' => '#Entrypoint'], - ['@id' => '#Dummy', 'hydra:supportedOperation' => 'not an array'], - ]]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withItemOperations([ - 'get' => [ - 'method' => 'GET', - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - - $route = (new Route('/dummies/{id}'))->setMethods(['GET']); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'get')->willReturn($route)->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $operationMethodResolverProphecy->reveal() - ); - - $apiDoc = new ApiDoc(['resource' => $route->getPath(), 'description' => '', 'resourceDescription' => '', 'section' => '']); - $apiDoc->setRoute($route); - - $this->assertEquals([$apiDoc], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithEmptyHydraSupportedOperation() - { - $hydraDoc = ['hydra:supportedClass' => [ - ['@id' => '#Entrypoint'], - ['@id' => '#Dummy', 'hydra:supportedOperation' => []], - ]]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withItemOperations([ - 'get' => [ - 'method' => 'GET', - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - - $route = (new Route('/dummies/{id}'))->setMethods(['GET']); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getItemOperationRoute(Dummy::class, 'get')->willReturn($route)->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $operationMethodResolverProphecy->reveal() - ); - - $apiDoc = new ApiDoc(['resource' => $route->getPath(), 'description' => '', 'resourceDescription' => '', 'section' => '']); - $apiDoc->setRoute($route); - - $this->assertEquals([$apiDoc], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithInvalidHydraSupportedProperty() - { - $hydraDoc = ['hydra:supportedClass' => [ - ['@id' => '#Entrypoint', 'hydra:supportedProperty' => 'not an array'], - ['@id' => '#Dummy'], - ]]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withCollectionOperations([ - 'get' => [ - 'method' => 'GET', - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - - $route = (new Route('/dummies'))->setMethods(['GET']); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationRoute(Dummy::class, 'get')->willReturn($route)->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $operationMethodResolverProphecy->reveal() - ); - - $apiDoc = new ApiDoc(['resource' => $route->getPath(), 'description' => '', 'resourceDescription' => '', 'section' => '', 'filters' => []]); - $apiDoc->setRoute($route); - - $this->assertEquals([$apiDoc], $apiPlatformProvider->getAnnotations()); - } - - public function testGetAnnotationsWithEmptyHydraSupportedProperty() - { - $hydraDoc = ['hydra:supportedClass' => [ - ['@id' => '#Entrypoint', 'hydra:supportedProperty' => []], - ['@id' => '#Dummy'], - ]]; - - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize(new Documentation(new ResourceNameCollection([Dummy::class])))->willReturn($hydraDoc)->shouldBeCalled(); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $dummyResourceMetadata = (new ResourceMetadata()) - ->withShortName('Dummy') - ->withCollectionOperations([ - 'get' => [ - 'method' => 'GET', - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata)->shouldBeCalled(); - - $route = (new Route('/dummies'))->setMethods(['GET']); - - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET')->shouldBeCalled(); - $operationMethodResolverProphecy->getCollectionOperationRoute(Dummy::class, 'get')->willReturn($route)->shouldBeCalled(); - - $apiPlatformProvider = new ApiPlatformProvider( - $resourceNameCollectionFactoryProphecy->reveal(), - $documentationNormalizerProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $this->prophesize(ContainerInterface::class)->reveal(), - $operationMethodResolverProphecy->reveal() - ); - - $apiDoc = new ApiDoc(['resource' => $route->getPath(), 'description' => '', 'resourceDescription' => '', 'section' => '', 'filters' => []]); - $apiDoc->setRoute($route); - - $this->assertEquals([$apiDoc], $apiPlatformProvider->getAnnotations()); - } -} diff --git a/tests/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php b/tests/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php deleted file mode 100644 index 0b35c0c68f6..00000000000 --- a/tests/Core/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php +++ /dev/null @@ -1,540 +0,0 @@ - - * - * 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\NelmioApiDoc\Parser; - -use ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser; -use ApiPlatform\Core\Exception\ResourceClassNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UnknownDummy; -use ApiPlatform\Core\Tests\ProphecyTrait; -use Doctrine\Common\Collections\Collection; -use Nelmio\ApiDocBundle\DataTypes; -use Nelmio\ApiDocBundle\Parser\ParserInterface; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * @author Teoh Han Hui - * - * @group legacy - */ -class ApiPlatformParserTest extends TestCase -{ - use ProphecyTrait; - - protected function setUp(): void - { - if (!class_exists(NelmioApiDocBundle::class)) { - $this->markTestSkipped('NelmioApiDocBundle is not installed.'); - } - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testConstruct() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertInstanceOf(ParserInterface::class, $apiPlatformParser); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testSupports() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertTrue($apiPlatformParser->supports([ - 'class' => sprintf('%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class), - ])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testNoOnDataFirstArray() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertFalse($apiPlatformParser->supports([ - 'class' => sprintf('%s', ApiPlatformParser::OUT_PREFIX), - ])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testSupportsAttributeNormalization() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Acme\CustomAttributeDummy')->willReturn(new ResourceMetadata('dummy', 'dummy', null, [ - 'get' => ['method' => 'GET', 'normalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_get']]], - 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], - 'delete' => ['method' => 'DELETE'], - ], []))->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create('Acme\CustomAttributeDummy', Argument::cetera())->willReturn(new PropertyNameCollection([ - 'id', - 'name', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $idPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_INT, false)) - ->withDescription('The id.') - ->withReadable(true) - ->withWritable(false) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create('Acme\CustomAttributeDummy', 'id')->willReturn($idPropertyMetadata)->shouldBeCalled(); - $namePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, false)) - ->withDescription('The dummy name.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create('Acme\CustomAttributeDummy', 'name')->willReturn($namePropertyMetadata)->shouldBeCalled(); - - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, 'Acme\CustomAttributeDummy', 'get'), - ]); - - $this->assertEquals([ - 'id' => [ - 'dataType' => DataTypes::INTEGER, - 'required' => false, - 'description' => 'The id.', - 'readonly' => true, - ], - 'name' => [ - 'dataType' => DataTypes::STRING, - 'required' => true, - 'description' => 'The dummy name.', - 'readonly' => false, - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testSupportsUnknownResource() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(UnknownDummy::class)->willThrow(ResourceClassNotFoundException::class)->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertFalse($apiPlatformParser->supports([ - 'class' => sprintf('%s:%s', ApiPlatformParser::OUT_PREFIX, UnknownDummy::class), - ])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testSupportsUnsupportedClassFormat() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Argument::any())->shouldNotBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $this->assertFalse($apiPlatformParser->supports([ - 'class' => Dummy::class, - ])); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParse() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [ - 'get' => ['method' => 'GET', 'normalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_get']]], - 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], - 'gerard' => ['method' => 'get', 'path' => '/gerard', 'denormalization_context' => [AbstractNormalizer::GROUPS => ['custom_attr_dummy_put']]], - 'delete' => ['method' => 'DELETE'], - ], []))->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'id', - 'name', - 'dummyPrice', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $idPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_INT, false)) - ->withDescription('The id.') - ->withReadable(true) - ->withWritable(false) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn($idPropertyMetadata)->shouldBeCalled(); - $namePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, false)) - ->withDescription('The dummy name.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name')->willReturn($namePropertyMetadata)->shouldBeCalled(); - $dummyPricePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_FLOAT, true)) - ->withDescription('A dummy price.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyPrice')->willReturn($dummyPricePropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'gerard'), - ]); - - $this->assertEquals([ - 'id' => [ - 'dataType' => DataTypes::INTEGER, - 'required' => false, - 'description' => 'The id.', - 'readonly' => true, - ], - 'name' => [ - 'dataType' => DataTypes::STRING, - 'required' => true, - 'description' => 'The dummy name.', - 'readonly' => false, - ], - 'dummyPrice' => [ - 'dataType' => DataTypes::FLOAT, - 'required' => false, - 'description' => 'A dummy price.', - 'readonly' => false, - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParseDateTime() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'dummyDate', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $dummyDatePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class)) - ->withDescription('A dummy date.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate')->willReturn($dummyDatePropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - ]); - - $this->assertEquals([ - 'dummyDate' => [ - 'dataType' => DataTypes::DATETIME, - 'required' => false, - 'description' => 'A dummy date.', - 'readonly' => false, - 'format' => sprintf('{DateTime %s}', \DateTime::RFC3339), - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParseRelation() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'relatedDummy', - 'relatedDummies', - ]))->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'id', - 'name', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relatedDummyPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class)) - ->withDescription('A related dummy.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy')->willReturn($relatedDummyPropertyMetadata)->shouldBeCalled(); - $relatedDummiesPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, Collection::class, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class))) - ->withDescription('Several dummies.') - ->withReadable(true) - ->withWritable(true) - ->withReadableLink(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies')->willReturn($relatedDummiesPropertyMetadata)->shouldBeCalled(); - $idPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_INT, false)) - ->withReadable(true) - ->withWritable(false) - ->withRequired(true); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'id')->willReturn($idPropertyMetadata)->shouldBeCalled(); - $namePropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, false)) - ->withDescription('A name.') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name')->willReturn($namePropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - ]); - - $this->assertEquals([ - 'relatedDummy' => [ - 'dataType' => 'IRI', - 'required' => false, - 'description' => 'A related dummy.', - 'readonly' => false, - 'actualType' => DataTypes::STRING, - ], - 'relatedDummies' => [ - 'dataType' => null, - 'required' => false, - 'description' => 'Several dummies.', - 'readonly' => false, - 'actualType' => DataTypes::COLLECTION, - 'subType' => RelatedDummy::class, - 'children' => [ - 'id' => [ - 'dataType' => DataTypes::INTEGER, - 'required' => false, - 'description' => null, - 'readonly' => true, - ], - 'name' => [ - 'dataType' => DataTypes::STRING, - 'required' => false, - 'description' => 'A name.', - 'readonly' => false, - ], - ], - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParseWithNameConverter() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'nameConverted', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $nameConvertedPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, true)) - ->withDescription('A converted name') - ->withReadable(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'nameConverted')->willReturn($nameConvertedPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $nameConverterProphecy = $this->prophesize(NameConverterInterface::class); - $nameConverterProphecy->normalize('nameConverted', Dummy::class)->willReturn('name_converted')->shouldBeCalled(); - $nameConverter = $nameConverterProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $nameConverter); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - ]); - - $this->assertEquals([ - 'name_converted' => [ - 'dataType' => DataTypes::STRING, - 'required' => false, - 'description' => 'A converted name', - 'readonly' => false, - ], - ], $actual); - } - - /** - * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. - */ - public function testParseRecursive() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy', 'dummy', null, [], []))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'relatedDummy', - ]))->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, Argument::cetera())->willReturn(new PropertyNameCollection([ - 'dummy', - ]))->shouldBeCalled(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relatedDummyMetadatata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class)) - ->withDescription('A related Dummy.') - ->withReadable(true) - ->withReadableLink(true) - ->withWritableLink(true) - ->withWritable(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy')->willReturn($relatedDummyMetadatata)->shouldBeCalled(); - $dummyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class)) - ->withDescription('A Dummy.') - ->withReadable(true) - ->withWritable(true) - ->withReadableLink(true) - ->withWritableLink(true) - ->withRequired(false); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'dummy')->willReturn($dummyMetadata)->shouldBeCalled(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $apiPlatformParser = new ApiPlatformParser($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); - - $actual = $apiPlatformParser->parse([ - 'class' => sprintf('%s:%s:%s', ApiPlatformParser::OUT_PREFIX, Dummy::class, 'get'), - ]); - - $this->assertEquals([ - 'relatedDummy' => [ - 'dataType' => null, - 'required' => false, - 'description' => 'A related Dummy.', - 'readonly' => false, - 'actualType' => 'model', - 'subType' => RelatedDummy::class, - 'children' => [ - 'dummy' => [ - 'dataType' => null, - 'required' => false, - 'description' => 'A Dummy.', - 'readonly' => false, - 'actualType' => 'model', - 'subType' => Dummy::class, - 'children' => [], - ], - ], - ], - ], $actual); - } -} diff --git a/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php b/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php deleted file mode 100644 index 3cd3cf99136..00000000000 --- a/tests/Core/Bridge/RamseyUuid/Identifier/Normalizer/UuidNormalizerTest.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * 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\RamseyUuid\Identifier\Normalizer; - -use ApiPlatform\Core\Bridge\RamseyUuid\Identifier\Normalizer\UuidNormalizer; -use ApiPlatform\Exception\InvalidIdentifierException; -use PHPUnit\Framework\TestCase; -use Ramsey\Uuid\Uuid; - -class UuidNormalizerTest extends TestCase -{ - public function testDenormalizeUuid() - { - $uuid = Uuid::uuid4(); - $normalizer = new UuidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($uuid->toString(), Uuid::class)); - $this->assertEquals($uuid, $normalizer->denormalize($uuid->toString(), Uuid::class)); - } - - public function testNoSupportDenormalizeUuid() - { - $uuid = 'notanuuid'; - $normalizer = new UuidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($uuid, '')); - } - - public function testFailDenormalizeUuid() - { - $this->expectException(InvalidIdentifierException::class); - - $uuid = 'notanuuid'; - $normalizer = new UuidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($uuid, Uuid::class)); - $normalizer->denormalize($uuid, Uuid::class); - } - - public function testDoNotSupportNotString() - { - $uuid = Uuid::uuid4(); - $normalizer = new UuidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($uuid, Uuid::class)); - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandTest.php b/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandTest.php deleted file mode 100644 index aef9ec5a63f..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandTest.php +++ /dev/null @@ -1,137 +0,0 @@ - - * - * 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\Bundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\Console\Exception\InvalidOptionException; -use Symfony\Component\Console\Tester\ApplicationTester; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Yaml; - -/** - * @author Amrouche Hamza - * @group legacy - */ -class SwaggerCommandTest extends KernelTestCase -{ - /** - * @var ApplicationTester - */ - private $tester; - - protected function setUp(): void - { - self::bootKernel(); - - $application = new Application(static::$kernel); - $application->setCatchExceptions(false); - $application->setAutoExit(false); - - $this->tester = new ApplicationTester($application); - - if (false === static::$kernel->getContainer()->getParameter('api_platform.metadata_backward_compatibility_layer')) { - $this->markTestSkipped( - 'Swagger is not compatible with the new metadata.' - ); - } - } - - /** - * @group legacy - * @expectedDeprecation The command "api:swagger:export" is deprecated for the spec version 3 use "api:openapi:export". - */ - public function testExecuteWithAliasVersion3() - { - $this->tester->run(['command' => 'api:swagger:export', '--spec-version' => 3]); - - $this->assertJson($this->tester->getDisplay()); - } - - /** - * @group legacy - * @expectedDeprecation The command "api:swagger:export" is deprecated for the spec version 3 use "api:openapi:export". - */ - public function testExecuteWithYamlVersion3() - { - $this->tester->run(['command' => 'api:swagger:export', '--yaml' => true, '--spec-version' => 3]); - - $result = $this->tester->getDisplay(); - $this->assertYaml($result); - - $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result, 'nested object should be present.'); - - $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result, 'arrays should be correctly formatted.'); - $this->assertStringContainsString('openapi: 3.0.2', $result); - - $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result, 'multiline formatting must be preserved (using literal style).'); - - $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result); - } - - public function testExecuteWithBadArguments() - { - $this->expectException(InvalidOptionException::class); - $this->expectExceptionMessage('This tool only supports versions 2, 3 of the OpenAPI specification ("foo" given).'); - $this->tester->run(['command' => 'api:swagger:export', '--spec-version' => 'foo', '--yaml' => true]); - } - - public function testWriteToFile() - { - /** @var string $tmpFile */ - $tmpFile = tempnam(sys_get_temp_dir(), 'test_write_to_file'); - - $this->tester->run(['command' => 'api:swagger:export', '--output' => $tmpFile]); - - $this->assertJson((string) @file_get_contents($tmpFile)); - @unlink($tmpFile); - } - - /** - * @param string $data - */ - private function assertYaml($data) - { - try { - Yaml::parse($data); - } catch (ParseException $exception) { - $this->fail('Is not valid YAML: '.$exception->getMessage()); - } - $this->addToAssertionCount(1); - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php b/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php deleted file mode 100644 index e783dd213bd..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/Command/SwaggerCommandUnitTest.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * 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\Bundle\Command; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\Command\SwaggerCommand; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use PHPUnit\Framework\MockObject\MockObject; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\BufferedOutput; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -class SwaggerCommandUnitTest extends KernelTestCase -{ - use ExpectDeprecationTrait; - /** @var MockObject&NormalizerInterface */ - private $normalizer; - - /** @var ResourceNameCollectionFactoryInterface&MockObject */ - private $resources; - - /** @var SwaggerCommand */ - private $command; - - protected function setUp(): void - { - $this->normalizer = $this->createMock(NormalizerInterface::class); - $this->resources = $this->createMock(ResourceNameCollectionFactoryInterface::class); - $this->command = new SwaggerCommand( - $this->normalizer, - $this->resources, - 'My API', - 'I told you already: it is my API', - 'one-zero-zero' - ); - - $this->resources->method('create') - ->willReturn(new ResourceNameCollection()); - } - - /** - * @group legacy - */ - public function testDocumentationJsonDoesNotUseEscapedSlashes(): void - { - $this->expectDeprecation('The command "api:swagger:export" is using pre-2.7 metadata, new metadata will not appear, use "api:openapi:export" instead.'); - $this->normalizer->method('normalize') - ->with(self::isInstanceOf(Documentation::class)) - ->willReturn(['a-jsonable-documentation' => 'containing/some/slashes']); - - $output = new BufferedOutput(); - - $this->command->run(new ArrayInput([]), $output); - - $jsonOutput = $output->fetch(); - - self::assertJson($jsonOutput); - self::assertStringNotContainsString('containing\/some\/slashes', $jsonOutput); - self::assertStringContainsString('containing/some/slashes', $jsonOutput); - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommandTest.php b/tests/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommandTest.php deleted file mode 100644 index a67f0904c4b..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/Command/UpgradeApiResourceCommandTest.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * 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\Bundle\Command; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Bridge\Symfony\Bundle\Command\UpgradeApiResourceCommand; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Core\Upgrade\SubresourceTransformer; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use Doctrine\Common\Annotations\AnnotationReader; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Tester\CommandTester; - -class UpgradeApiResourceCommandTest extends TestCase -{ - use ProphecyTrait; - - private function getCommandTester(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, SubresourceOperationFactoryInterface $subresourceOperationFactory): CommandTester - { - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - - $application = new Application(); - $application->setCatchExceptions(false); - $application->setAutoExit(false); - - $application->add(new UpgradeApiResourceCommand($resourceNameCollectionFactory, $resourceMetadataFactory, $subresourceOperationFactory, new SubresourceTransformer(), $identifiersExtractor->reveal(), new AnnotationReader())); - - $command = $application->find('api:upgrade-resource'); - - return new CommandTester($command); - } - - /** - * @requires PHP 8.1 - */ - public function testDebugResource() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([RelatedDummy::class])); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata()); - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create(RelatedDummy::class)->willReturn([[ - 'property' => 'id', - 'collection' => false, - 'resource_class' => RelatedDummy::class, - 'shortNames' => [ - 'RelatedDummy', - ], - 'legacy_filters' => [ - 'related_dummy.friends', - 'related_dummy.complex_sub_query', - ], - 'legacy_normalization_context' => [ - 'groups' => [ - 'friends', - ], - ], - 'legacy_type' => 'https://schema.org/Product', - 'identifiers' => [ - 'id' => [ - RelatedDummy::class, - 'id', - true, - ], - ], - 'operation_name' => 'id_get_subresource', - 'route_name' => 'api_related_dummies_id_get_subresource', - 'path' => '/related_dummies/{id}/id.{_format}', - ]]); - - $commandTester = $this->getCommandTester($resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), $subresourceOperationFactoryProphecy->reveal()); - $commandTester->execute([]); - - $expectedStrings = [ - '-use ApiPlatform\\Core\\Annotation\\ApiSubresource', - '-use ApiPlatform\\Core\\Annotation\\ApiResource', - '+use ApiPlatform\\Metadata\\ApiResource', - '+use ApiPlatform\\Metadata\\Get', - "+#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'])]", - "#[ApiResource(uriTemplate: '/related_dummies/{id}/id.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])]", - ]; - - $display = $commandTester->getDisplay(); - foreach ($expectedStrings as $expectedString) { - $this->assertStringContainsString($expectedString, $display); - } - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php b/tests/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php deleted file mode 100644 index 79e28babcd4..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersisterTest.php +++ /dev/null @@ -1,185 +0,0 @@ - - * - * 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\Bundle\DataPersister; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister\TraceableChainDataPersister; -use ApiPlatform\Core\DataPersister\ChainDataPersister; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataPersister\ResumableDataPersisterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - */ -class TraceableChainDataPersisterTest extends TestCase -{ - use ProphecyTrait; - - /** @dataProvider dataPersisterProvider */ - public function testPersist($persister, $expected) - { - $dataPersister = new TraceableChainDataPersister($persister); - $dataPersister->persist(''); - - $result = $dataPersister->getPersistersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, DataPersisterInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - } - - /** @dataProvider dataPersisterProvider */ - public function testRemove($persister, $expected) - { - $dataPersister = new TraceableChainDataPersister($persister); - $dataPersister->remove(''); - - $result = $dataPersister->getPersistersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, DataPersisterInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - } - - public function testSupports() - { - $context = ['ok' => true]; - $persister = $this->prophesize(DataPersisterInterface::class); - $persister->supports('', $context)->willReturn(true)->shouldBeCalled(); - $chain = new ChainDataPersister([$persister->reveal()]); - $persister->persist('', $context)->shouldBeCalled(); - $dataPersister = new TraceableChainDataPersister($chain); - $dataPersister->persist('', $context); - } - - public function dataPersisterProvider(): iterable - { - yield [ - new ChainDataPersister([]), - [], - ]; - - yield [ - new ChainDataPersister([ - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return false; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - ]), - [false, true, false], - ]; - - yield [ - new ChainDataPersister([ - new class() implements DataPersisterInterface, ResumableDataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function resumable(array $context = []): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return false; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - ]), - [true, false, true], - ]; - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php b/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php deleted file mode 100644 index 82c4282773c..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainCollectionDataCollectorTest.php +++ /dev/null @@ -1,149 +0,0 @@ - - * - * 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\Bundle\DataProvider; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainCollectionDataProvider; -use ApiPlatform\Core\DataProvider\ChainCollectionDataProvider; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - */ -class TraceableChainCollectionDataCollectorTest extends TestCase -{ - /** @dataProvider dataProviderProvider */ - public function testGetCollection($provider, $context, $expected) - { - $dataProvider = new TraceableChainCollectionDataProvider($provider); - $dataProvider->getCollection('', null, $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, CollectionDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - /** - * @dataProvider deprecatedDataProviderProvider - * @group legacy - * - * @param mixed $provider - * @param mixed $context - * @param mixed $expected - */ - public function testDeprecatedGetCollection($provider, $context, $expected) - { - $dataProvider = new TraceableChainCollectionDataProvider($provider); - $dataProvider->getCollection('', null, $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, CollectionDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - public function dataProviderProvider(): iterable - { - yield 'Not a ChainCollectionDataProvider' => [ - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - }, - ['some_context'], - [], - ]; - - yield 'Empty ChainCollectionDataProvider' => [ - new ChainCollectionDataProvider([]), - ['some_context'], - [], - ]; - - yield 'ChainCollectionDataProvider' => [ - new ChainCollectionDataProvider([ - new class() implements CollectionDataProviderInterface, RestrictedDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return false; - } - }, - new class() implements CollectionDataProviderInterface, RestrictedDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return true; - } - }, - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - }, - ]), - ['some_context'], - [false, true, null], - ]; - } - - public function deprecatedDataProviderProvider(): iterable - { - yield 'ChainCollectionDataProvider' => [ - new ChainCollectionDataProvider([ - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - throw new ResourceClassNotSupportedException('nope'); - } - }, - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - }, - ]), - ['some_context'], - [false, true], - ]; - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php b/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php deleted file mode 100644 index d8cfb0c387a..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainItemDataCollectorTest.php +++ /dev/null @@ -1,150 +0,0 @@ - - * - * 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\Bundle\DataProvider; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainItemDataProvider; -use ApiPlatform\Core\DataProvider\ChainItemDataProvider; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - */ -class TraceableChainItemDataCollectorTest extends TestCase -{ - /** @dataProvider dataProviderProvider */ - public function testGetItem($provider, $context, $expected) - { - $dataProvider = new TraceableChainItemDataProvider($provider); - $dataProvider->getItem('', '', null, $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, ItemDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - /** - * @dataProvider deprecatedDataProviderProvider - * @group legacy - * - * @param mixed $provider - * @param mixed $context - * @param mixed $expected - */ - public function testDeprecatedGetItem($provider, $context, $expected) - { - $dataProvider = new TraceableChainItemDataProvider($provider); - $dataProvider->getItem('', '', null, $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, ItemDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - public function dataProviderProvider(): iterable - { - yield 'Not a ChainItemDataProvider' => [ - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - ['some_context'], - [], - ]; - - yield 'Empty ChainItemDataProvider' => [ - new ChainItemDataProvider([]), - ['some_context'], - [], - ]; - - yield 'ChainItemDataProvider' => [ - new ChainItemDataProvider([ - new class() implements ItemDataProviderInterface, RestrictedDataProviderInterface { - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return false; - } - - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - new class() implements ItemDataProviderInterface, RestrictedDataProviderInterface, DenormalizedIdentifiersAwareItemDataProviderInterface { - public function getItem(string $resourceClass, /* array */ $id, string $operationName = null, array $context = []) - { - return null; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return true; - } - }, - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - ]), - ['some_context'], - [false, true, null], - ]; - } - - public function deprecatedDataProviderProvider(): iterable - { - yield 'deprecated ChainItemDataProvider - ResourceClassNotSupportedException' => [ - new ChainItemDataProvider([ - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - throw new ResourceClassNotSupportedException('nope'); - } - }, - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - ]), - ['some_context'], - [false, true], - ]; - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php b/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php deleted file mode 100644 index 41bc0d2f2e0..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/DataProvider/TraceableChainSubresourceDataCollectorTest.php +++ /dev/null @@ -1,149 +0,0 @@ - - * - * 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\Bundle\DataProvider; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainSubresourceDataProvider; -use ApiPlatform\Core\DataProvider\ChainSubresourceDataProvider; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use PHPUnit\Framework\TestCase; - -/** - * @author Anthony GRASSIOT - */ -class TraceableChainSubresourceDataCollectorTest extends TestCase -{ - /** @dataProvider dataProviderProvider */ - public function testGetSubresource($provider, $context, $expected) - { - $dataProvider = new TraceableChainSubresourceDataProvider($provider); - $dataProvider->getSubresource('', [], $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, SubresourceDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - /** - * @dataProvider deprecatedDataProviderProvider - * @group legacy - * - * @param mixed $provider - * @param mixed $context - * @param mixed $expected - */ - public function testDeprecatedGetSubResource($provider, $context, $expected) - { - $dataProvider = new TraceableChainSubresourceDataProvider($provider); - $dataProvider->getSubresource('', [], $context); - - $result = $dataProvider->getProvidersResponse(); - $this->assertCount(\count($expected), $result); - $this->assertEmpty(array_filter($result, function ($key) { - if (\PHP_VERSION_ID >= 80000) { - return !str_starts_with($key, SubresourceDataProviderInterface::class.'@anonymous'); - } - - return 0 !== strpos($key, 'class@anonymous'); - }, \ARRAY_FILTER_USE_KEY)); - $this->assertSame($expected, array_values($result)); - $this->assertSame($context, $dataProvider->getContext()); - } - - public function dataProviderProvider(): iterable - { - yield 'Not a ChainSubresourceDataProvider' => [ - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - }, - ['some_context'], - [], - ]; - - yield 'Empty ChainSubresourceDataProvider' => [ - new ChainSubresourceDataProvider([]), - ['some_context'], - [], - ]; - - yield 'ChainSubresourceDataProvider' => [ - new ChainSubresourceDataProvider([ - new class() implements SubresourceDataProviderInterface, RestrictedDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return false; - } - }, - new class() implements SubresourceDataProviderInterface, RestrictedDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return true; - } - }, - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - }, - ]), - ['some_context'], - [false, true, null], - ]; - } - - public function deprecatedDataProviderProvider(): iterable - { - yield 'deprecated ChainSubresourceDataProvider - ResourceClassNotSupportedException' => [ - new ChainSubresourceDataProvider([ - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - throw new ResourceClassNotSupportedException('nope'); - } - }, - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - }, - ]), - ['some_context'], - [false, true], - ]; - } -} diff --git a/tests/Core/Bridge/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php b/tests/Core/Bridge/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php deleted file mode 100644 index d4b84ac03fa..00000000000 --- a/tests/Core/Bridge/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php +++ /dev/null @@ -1,299 +0,0 @@ - - * - * 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\Bundle\Twig; - -use ApiPlatform\Core\Bridge\Doctrine\Common\DataPersister; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\CollectionDataProvider as OdmCollectionDataProvider; -use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\ItemDataProvider as OdmItemDataProvider; -use ApiPlatform\Core\Bridge\Doctrine\Orm\CollectionDataProvider; -use ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider; -use ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ContainNonResourceItemDataProvider; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy as DocumentDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Tools\SchemaTool; -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; - -/** - * @author Anthony GRASSIOT - */ -class ApiPlatformProfilerPanelTest extends WebTestCase -{ - /** - * @var EntityManagerInterface - */ - private $manager; - private $schemaTool; - private $env; - private $legacy; - - protected function setUp(): void - { - parent::setUp(); - $kernel = self::bootKernel(); - $this->env = $kernel->getEnvironment(); - $this->legacy = $kernel->getContainer()->getParameter('api_platform.metadata_backward_compatibility_layer'); - - /** @var ManagerRegistry $doctrine */ - $doctrine = $kernel->getContainer()->get('doctrine'); - /** @var EntityManagerInterface $manager */ - $manager = $doctrine->getManager(); - $this->manager = $manager; - $this->schemaTool = new SchemaTool($this->manager); - /** @var \Doctrine\ORM\Mapping\ClassMetadata[] $classes */ - $classes = $this->manager->getMetadataFactory()->getAllMetadata(); - $this->schemaTool->dropSchema($classes); - $this->manager->clear(); - $this->schemaTool->createSchema($classes); - - $this->ensureKernelShutdown(); - } - - protected function tearDown(): void - { - $this->schemaTool->dropSchema($this->manager->getMetadataFactory()->getAllMetadata()); - $this->manager->clear(); - parent::tearDown(); - } - - public function testDebugBarContentNotResourceClass() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - // Using html to get default Swagger UI - $client->request('GET', '/'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - /** @var string $token */ - $token = $client->getResponse()->headers->get('X-Debug-Token'); - $crawler = $client->request('GET', "/_wdt/$token"); - - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $block = $crawler->filter('div[class*=sf-toolbar-block-api_platform]'); - - // Check extra info content - $this->assertStringContainsString('sf-toolbar-status-default', $block->attr('class'), 'The toolbar block should have the default color.'); - $this->assertSame('Not an API Platform resource', $block->filterXPath('//div[@class="sf-toolbar-info-piece"][./b[contains(., "Resource Class")]]/span')->html()); - } - - public function testDebugBarContent() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('GET', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json']); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - /** @var string $token */ - $token = $client->getResponse()->headers->get('X-Debug-Token'); - - $crawler = $client->request('GET', "/_wdt/$token"); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $block = $crawler->filter('div[class*=sf-toolbar-block-api_platform]'); - - // Check extra info content - $this->assertStringContainsString('sf-toolbar-status-default', $block->attr('class'), 'The toolbar block should have the default color.'); - $this->assertSame('mongodb' === $this->env ? DocumentDummy::class : Dummy::class, $block->filterXPath('//div[@class="sf-toolbar-info-piece"][./b[contains(., "Resource Class")]]/span')->html()); - } - - public function testProfilerGeneralLayoutNotResourceClass() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - // Using html to get default Swagger UI - $client->request('GET', '/'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $crawler = $client->request('GET', '/_profiler/latest?panel=api_platform.data_collector.request', [], [], []); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Check that the Api-Platform sidebar link is active - $this->assertNotEmpty($menuLink = $crawler->filter('a[href$="panel=api_platform.data_collector.request"]')); - $this->assertNotEmpty($menuLink->filter('.disabled'), 'The sidebar menu should be disabled.'); - - $metrics = $crawler->filter('.metrics'); - $this->assertCount(1, $metrics->filter('.metric'), 'The should be one metric displayed (resource class).'); - $this->assertSame('Not an API Platform resource', $metrics->filter('span.value')->html()); - - $this->assertEmpty($crawler->filter('.sf-tabs .tab'), 'Tabs must not be presents on the panel.'); - } - - public function testProfilerGeneralLayout() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('GET', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json']); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $crawler = $client->request('GET', '/_profiler/latest?panel=api_platform.data_collector.request', [], [], []); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Check that the Api-Platform sidebar link is active - $this->assertNotEmpty($menuLink = $crawler->filter('a[href$="panel=api_platform.data_collector.request"]')); - $this->assertEmpty($menuLink->filter('.disabled'), 'The sidebar menu should not be disabled.'); - - $metrics = $crawler->filter('.metrics'); - $this->assertCount(1, $metrics->filter('.metric'), 'The should be one metric displayed (resource class).'); - $this->assertSame('mongodb' === $this->env ? DocumentDummy::class : Dummy::class, $metrics->filter('span.value')->html()); - - $this->assertCount(3, $crawler->filter('.sf-tabs .tab'), 'Tabs must be presents on the panel.'); - - // Metadata tab - $this->assertSame('Resource Metadata', $crawler->filter('.tab:nth-of-type(1) .tab-title')->html()); - $tabContent = $crawler->filter('.tab:nth-of-type(1) .tab-content'); - $this->assertStringEndsWith('"Dummy"', $tabContent->filter('h3')->html(), 'the resource shortname should be displayed.'); - - $this->assertCount(4, $tabContent->filter('table')); - $this->assertSame('Item operations', $tabContent->filter('table:first-of-type thead th:first-of-type')->html()); - $this->assertSame('Collection operations', $tabContent->filter('table:nth-of-type(2) thead th:first-of-type')->html()); - $this->assertSame('Filters', $tabContent->filter('table:nth-of-type(3) thead th:first-of-type')->html()); - $this->assertSame('Attributes', $tabContent->filter('table:last-of-type thead th:first-of-type')->html()); - - // Data providers tab - $this->assertSame('Data Providers', $crawler->filter('.tab:nth-of-type(2) .tab-title')->html()); - $this->assertNotEmpty($crawler->filter('.tab:nth-of-type(2) .tab-content')); - - // Data persisters tab - $this->assertSame('Data Persisters', $crawler->filter('.tab:last-child .tab-title')->html()); - $this->assertNotEmpty($crawler->filter('.tab:nth-of-type(3) .tab-content')); - } - - public function testGetCollectionProfiler() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('GET', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json']); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $crawler = $client->request('GET', '/_profiler/latest?panel=api_platform.data_collector.request'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Metadata tab - $tabContent = $crawler->filter('.tab:nth-of-type(1) .tab-content'); - $this->assertSame('get', $tabContent->filter('table:nth-of-type(2) th.status-success')->html(), 'The actual operation should be highlighted.'); - $this->assertEmpty($tabContent->filter('table:not(:nth-of-type(2)) .status-success'), 'Only the actual operation should be highlighted.'); - - // Data provider tab - $tabContent = $crawler->filter('.tab:nth-of-type(2) .tab-content'); - $this->assertSame('TRUE', $tabContent->filter('table tbody .status-success')->html()); - $this->assertStringContainsString('mongodb' === $this->env ? OdmCollectionDataProvider::class : CollectionDataProvider::class, $tabContent->filter('table tbody')->html()); - - $this->assertStringContainsString('No calls to item data provider have been recorded.', $tabContent->html()); - $this->assertStringContainsString('No calls to subresource data provider have been recorded.', $tabContent->html()); - - // Data persiters tab - $this->assertStringContainsString('No calls to data persister have been recorded.', $crawler->filter('.tab:nth-of-type(3) .tab-content .empty')->html()); - } - - public function testPostCollectionProfiler() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('POST', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json', 'CONTENT_TYPE' => 'application/ld+json'], '{"name": "foo"}'); - $this->assertEquals(201, $client->getResponse()->getStatusCode()); - $crawler = $client->request('get', '/_profiler/latest?panel=api_platform.data_collector.request'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Metadata tab - $tabContent = $crawler->filter('.tab:nth-of-type(1) .tab-content'); - $this->assertSame('post', $tabContent->filter('table:nth-of-type(2) th.status-success')->html(), 'The actual operation should be highlighted.'); - $this->assertEmpty($tabContent->filter('table:not(:nth-of-type(2)) .status-success'), 'Only the actual operation should be highlighted.'); - - // Data provider tab - $tabContent = $crawler->filter('.tab:nth-of-type(2) .tab-content'); - $this->assertStringContainsString('No calls to collection data provider have been recorded.', $tabContent->html()); - $this->assertStringContainsString('No calls to item data provider have been recorded.', $tabContent->html()); - $this->assertStringContainsString('No calls to subresource data provider have been recorded.', $tabContent->html()); - - // Data persiters tab - $tabContent = $crawler->filter('.tab:nth-of-type(3) .tab-content'); - $this->assertSame('TRUE', $tabContent->filter('table tbody .status-success')->html()); - $this->assertStringContainsString(DataPersister::class, $tabContent->filter('table tbody')->html()); - } - - /** - * @group legacy - * Group legacy is due ApiPlatform\Core\Exception\ResourceClassNotSupportedException, the annotation could be removed in 3.0 but the test should stay - */ - public function testGetItemProfiler() - { - if (!$this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - - $dummy = new Dummy(); - $dummy->setName('bar'); - $this->manager->persist($dummy); - $this->manager->flush(); - - $client = static::createClient(); - $client->enableProfiler(); - $client->request('GET', '/dummies/1', [], [], ['HTTP_ACCEPT' => 'application/ld+json', 'CONTENT_TYPE' => 'application/ld+json'], '{"name": "foo"}'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $crawler = $client->request('get', '/_profiler/latest?panel=api_platform.data_collector.request'); - $this->assertEquals(200, $client->getResponse()->getStatusCode()); - - // Metadata tab - $tabContent = $crawler->filter('.tab:nth-of-type(1) .tab-content'); - $this->assertSame('get', $tabContent->filter('table:nth-of-type(1) th.status-success')->html(), 'The actual operation should be highlighted.'); - $this->assertEmpty($tabContent->filter('table:not(:nth-of-type(1)) .status-success'), 'Only the actual operation should be highlighted.'); - - // Data provider tab - $tabContent = $crawler->filter('.tab:nth-of-type(2) .tab-content'); - $this->assertSame('FALSE', $tabContent->filter('table tbody tr:first-of-type .status-error')->html()); - $this->assertSame(ContainNonResourceItemDataProvider::class, $tabContent->filter('table tbody tr:first-of-type td:nth-of-type(3)')->html()); - - $this->assertSame('TRUE', $tabContent->filter('table tbody .status-success')->html()); - $this->assertStringContainsString('mongodb' === $this->env ? OdmItemDataProvider::class : ItemDataProvider::class, $tabContent->filter('table tbody')->html()); - - $this->assertStringContainsString('No calls to collection data provider have been recorded.', $tabContent->html()); - $this->assertStringContainsString('No calls to subresource data provider have been recorded.', $tabContent->html()); - - // Data persiters tab - $this->assertStringContainsString('No calls to data persister have been recorded.', $crawler->filter('.tab:nth-of-type(3) .tab-content .empty')->html()); - } -} diff --git a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php b/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php deleted file mode 100644 index 170fab26d65..00000000000 --- a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UlidNormalizerTest.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * 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\Identifier\Normalizer; - -use ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UlidNormalizer; -use ApiPlatform\Exception\InvalidIdentifierException; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Uid\AbstractUid; -use Symfony\Component\Uid\Ulid; - -final class UlidNormalizerTest extends TestCase -{ - protected function setUp(): void - { - if (!class_exists(AbstractUid::class)) { - $this->markTestSkipped(); - } - } - - public function testDenormalizeUlid() - { - $ulid = new Ulid(); - $normalizer = new UlidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($ulid->__toString(), Ulid::class)); - $this->assertEquals($ulid, $normalizer->denormalize($ulid->__toString(), Ulid::class)); - } - - public function testNoSupportDenormalizeUlid() - { - $ulid = 'notanulid'; - $normalizer = new UlidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($ulid, '')); - } - - public function testFailDenormalizeUlid() - { - $this->expectException(InvalidIdentifierException::class); - - $ulid = 'notanulid'; - $normalizer = new UlidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($ulid, Ulid::class)); - $normalizer->denormalize($ulid, Ulid::class); - } - - public function testDoNotSupportNotString() - { - $ulid = new Ulid(); - $normalizer = new UlidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($ulid, Ulid::class)); - } -} diff --git a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php b/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php deleted file mode 100644 index 32c124a72ad..00000000000 --- a/tests/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizerTest.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * 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\Identifier\Normalizer; - -use ApiPlatform\Core\Bridge\Symfony\Identifier\Normalizer\UuidNormalizer; -use ApiPlatform\Exception\InvalidIdentifierException; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Uid\AbstractUid; -use Symfony\Component\Uid\Uuid; - -final class UuidNormalizerTest extends TestCase -{ - protected function setUp(): void - { - if (!class_exists(AbstractUid::class)) { - $this->markTestSkipped(); - } - } - - public function testDenormalizeUuid() - { - $uuid = Uuid::v4(); - $normalizer = new UuidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($uuid->__toString(), Uuid::class)); - $this->assertEquals($uuid, $normalizer->denormalize($uuid->__toString(), Uuid::class)); - } - - public function testNoSupportDenormalizeUuid() - { - $uuid = 'notanuuid'; - $normalizer = new UuidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($uuid, '')); - } - - public function testFailDenormalizeUuid() - { - $this->expectException(InvalidIdentifierException::class); - - $uuid = 'notanuuid'; - $normalizer = new UuidNormalizer(); - $this->assertTrue($normalizer->supportsDenormalization($uuid, Uuid::class)); - $normalizer->denormalize($uuid, Uuid::class); - } - - public function testDoNotSupportNotString() - { - $uuid = Uuid::v4(); - $normalizer = new UuidNormalizer(); - $this->assertFalse($normalizer->supportsDenormalization($uuid, Uuid::class)); - } -} diff --git a/tests/Core/Bridge/Symfony/Maker/MakeDataPersisterTest.php b/tests/Core/Bridge/Symfony/Maker/MakeDataPersisterTest.php deleted file mode 100644 index 12cc2aa2785..00000000000 --- a/tests/Core/Bridge/Symfony/Maker/MakeDataPersisterTest.php +++ /dev/null @@ -1,187 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Filesystem\Filesystem; - -class MakeDataPersisterTest extends KernelTestCase -{ - protected function tearDown(): void - { - (new Filesystem())->remove(self::tempDir()); - parent::tearDown(); - } - - /** @dataProvider dataPersisterProvider */ - public function testMakeDataPersister(array $commandInputs, array $userInputs, string $expected) - { - $this->assertFileDoesNotExist(self::tempFile('src/DataPersister/CustomDataPersister.php')); - - $tester = new CommandTester((new Application(self::bootKernel()))->find('make:data-persister')); - $tester->setInputs($userInputs); - $tester->execute($commandInputs); - - $this->assertFileExists(self::tempFile('src/DataPersister/CustomDataPersister.php')); - - // Unify line endings - $expected = preg_replace('~\R~u', "\r\n", $expected); - $result = preg_replace('~\R~u', "\r\n", file_get_contents(self::tempFile('src/DataPersister/CustomDataPersister.php'))); - $this->assertSame($expected, $result); - - $display = $tester->getDisplay(); - $this->assertStringContainsString('Success!', $display); - - if (!isset($commandInputs['name'])) { - $this->assertStringContainsString('Choose a class name for your data persister (e.g. AwesomeDataPersister):', $display); - } else { - $this->assertStringNotContainsString('Choose a class name for your data persister (e.g. AwesomeDataPersister):', $display); - } - if (!isset($commandInputs['resource-class'])) { - $this->assertStringContainsString('Choose a Resource class:', $display); - } else { - $this->assertStringNotContainsString('Choose a Resource class:', $display); - } - $this->assertStringContainsString(<< [ - [], - ['CustomDataPersister', ''], - \PHP_VERSION_ID >= 70200 ? $expected : str_replace(': object', '', $expected), - ]; - - $expected = <<<'EOF' - [ - [], - ['CustomDataPersister', Question::class], - $expected, - ]; - - yield 'Generate data persister with resource class not interactively' => [ - ['name' => 'CustomDataPersister', 'resource-class' => Question::class], - [], - $expected, - ]; - } - - private static function tempDir(): string - { - return __DIR__.'/../../../../Fixtures/app/var/tmp'; - } - - private static function tempFile(string $path): string - { - return sprintf('%s/%s', self::tempDir(), $path); - } -} diff --git a/tests/Core/Bridge/Symfony/Maker/MakeDataProviderTest.php b/tests/Core/Bridge/Symfony/Maker/MakeDataProviderTest.php deleted file mode 100644 index 5dfc87c52d0..00000000000 --- a/tests/Core/Bridge/Symfony/Maker/MakeDataProviderTest.php +++ /dev/null @@ -1,332 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; -use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Filesystem\Filesystem; - -class MakeDataProviderTest extends KernelTestCase -{ - protected function tearDown(): void - { - (new Filesystem())->remove(self::tempDir()); - parent::tearDown(); - } - - /** @dataProvider dataProviderProvider */ - public function testMakeDataProvider(array $commandInputs, array $userInputs, string $expected) - { - $this->assertFileDoesNotExist(self::tempFile('src/DataProvider/CustomDataProvider.php')); - - $tester = new CommandTester((new Application(self::bootKernel()))->find('make:data-provider')); - $tester->setInputs($userInputs); - $tester->execute($commandInputs); - - $this->assertFileExists(self::tempFile('src/DataProvider/CustomDataProvider.php')); - - // Unify line endings - $expected = preg_replace('~\R~u', "\r\n", $expected); - $result = preg_replace('~\R~u', "\r\n", file_get_contents(self::tempFile('src/DataProvider/CustomDataProvider.php'))); - $this->assertSame($expected, $result); - - $display = $tester->getDisplay(); - $this->assertStringContainsString('Success!', $display); - - if (!isset($commandInputs['name'])) { - $this->assertStringContainsString('Choose a class name for your data provider (e.g. AwesomeDataProvider):', $display); - } else { - $this->assertStringNotContainsString('Choose a class name for your data provider (e.g. AwesomeDataProvider):', $display); - } - if (!isset($commandInputs['resource-class'])) { - $this->assertStringContainsString(' Choose a Resource class:', $display); - } else { - $this->assertStringNotContainsString('Choose a Resource class:', $display); - } - - $this->assertStringContainsString(<< [ - [], - ['CustomDataProvider', ''], - \PHP_VERSION_ID >= 70200 ? $expected : str_replace(': ?object', '', $expected), - ]; - - $expected = <<<'EOF' - [ - [], - ['CustomDataProvider', Question::class], - $expected, - ]; - - yield 'Generate all with resource class not interactively' => [ - ['name' => 'CustomDataProvider', 'resource-class' => Question::class], - [], - $expected, - ]; - - $expected = <<<'EOF' - [ - ['--item-only' => true], - ['CustomDataProvider', ''], - \PHP_VERSION_ID >= 70200 ? $expected : str_replace(': ?object', '', $expected), - ]; - - $expected = <<<'EOF' - [ - ['--item-only' => true], - ['CustomDataProvider', Question::class], - $expected, - ]; - - yield 'Generate an item data provider with a resource class not interactively' => [ - ['name' => 'CustomDataProvider', 'resource-class' => Question::class, '--item-only' => true], - [], - $expected, - ]; - - $expected = <<<'EOF' - [ - ['--collection-only' => true], - ['CustomDataProvider', ''], - $expected, - ]; - - $expected = <<<'EOF' - [ - ['--collection-only' => true], - ['CustomDataProvider', Question::class], - $expected, - ]; - - yield 'Generate a collection data provider with a resource class not interactively' => [ - ['name' => 'CustomDataProvider', 'resource-class' => Question::class, '--collection-only' => true], - [], - $expected, - ]; - } - - public function testMakeDataProviderThrows() - { - $tester = new CommandTester((new Application(self::bootKernel()))->find('make:data-provider')); - $this->expectException(RuntimeCommandException::class); - $this->expectExceptionMessage('You should at least generate an item or a collection data provider'); - - $tester->execute(['name' => 'CustomDataProvider', 'resource-class' => Question::class, '--collection-only' => true, '--item-only' => true]); - } - - private static function tempDir(): string - { - return __DIR__.'/../../../../Fixtures/app/var/tmp'; - } - - private static function tempFile(string $path): string - { - return sprintf('%s/%s', self::tempDir(), $path); - } -} diff --git a/tests/Core/Bridge/Symfony/Messenger/DataPersisterTest.php b/tests/Core/Bridge/Symfony/Messenger/DataPersisterTest.php deleted file mode 100644 index 983fa78db75..00000000000 --- a/tests/Core/Bridge/Symfony/Messenger/DataPersisterTest.php +++ /dev/null @@ -1,107 +0,0 @@ - - * - * 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\Messenger; - -use ApiPlatform\Core\Bridge\Symfony\Messenger\DataPersister; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Symfony\Messenger\ContextStamp; -use ApiPlatform\Symfony\Messenger\RemoveStamp; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Messenger\Stamp\HandledStamp; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class DataPersisterTest extends TestCase -{ - use ProphecyTrait; - - public function testSupport() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); - - $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal()); - $this->assertTrue($dataPersister->supports(new Dummy())); - } - - public function testSupportWithContext() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); - $metadataFactoryProphecy->create(DummyCar::class)->willThrow(new ResourceClassNotFoundException()); - - $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal()); - $this->assertTrue($dataPersister->supports(new DummyCar(), ['resource_class' => Dummy::class])); - $this->assertFalse($dataPersister->supports(new DummyCar())); - } - - public function testPersist() - { - $dummy = new Dummy(); - - $messageBus = $this->prophesize(MessageBusInterface::class); - $messageBus->dispatch(Argument::that(function (Envelope $envelope) use ($dummy) { - return $dummy === $envelope->getMessage() && null !== $envelope->last(ContextStamp::class); - }))->willReturn(new Envelope($dummy))->shouldBeCalled(); - - $dataPersister = new DataPersister($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), $messageBus->reveal()); - $this->assertSame($dummy, $dataPersister->persist($dummy)); - } - - public function testRemove() - { - $dummy = new Dummy(); - - $messageBus = $this->prophesize(MessageBusInterface::class); - - $messageBus->dispatch(Argument::that(function (Envelope $envelope) use ($dummy) { - return $dummy === $envelope->getMessage() && null !== $envelope->last(RemoveStamp::class); - }))->willReturn(new Envelope($dummy))->shouldBeCalled(); - - $dataPersister = new DataPersister($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), $messageBus->reveal()); - $dataPersister->remove($dummy); - } - - public function testHandle() - { - $dummy = new Dummy(); - - $messageBus = $this->prophesize(MessageBusInterface::class); - $messageBus->dispatch(Argument::that(function (Envelope $envelope) use ($dummy) { - return $dummy === $envelope->getMessage() && null !== $envelope->last(ContextStamp::class); - }))->willReturn((new Envelope($dummy))->with(new HandledStamp($dummy, 'DummyHandler::__invoke')))->shouldBeCalled(); - - $dataPersister = new DataPersister($this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), $messageBus->reveal()); - $this->assertSame($dummy, $dataPersister->persist($dummy)); - } - - public function testSupportWithGraphqlContext() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata(null, null, null, null, null, []))->withGraphQl(['create' => ['messenger' => 'input']])); - - $dataPersister = new DataPersister($metadataFactoryProphecy->reveal(), $this->prophesize(MessageBusInterface::class)->reveal()); - $this->assertTrue($dataPersister->supports(new DummyCar(), ['resource_class' => Dummy::class, 'graphql_operation_name' => 'create'])); - } -} diff --git a/tests/Core/Bridge/Symfony/Messenger/DataTransformerTest.php b/tests/Core/Bridge/Symfony/Messenger/DataTransformerTest.php deleted file mode 100644 index d7b7ab5e78d..00000000000 --- a/tests/Core/Bridge/Symfony/Messenger/DataTransformerTest.php +++ /dev/null @@ -1,101 +0,0 @@ - - * - * 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\Tests\Symfony\Messenger; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Messenger\DataTransformer; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class DataTransformerTest extends TestCase -{ - use ProphecyTrait; - - public function testSupport() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth']])); - } - - public function testSupportWithinRequest() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['foo' => ['messenger' => 'input']], null, [])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'operation_type' => OperationType::ITEM, 'item_operation_name' => 'foo'])); - } - - public function testNoSupport() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => true])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth']])); - } - - public function testNoSupportWithinRequest() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['foo' => ['messenger' => true]], null, [])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'operation_type' => OperationType::ITEM, 'item_operation_name' => 'foo'])); - } - - public function testNoSupportWithoutInput() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertFalse($dataTransformer->supportsTransformation([], Dummy::class, [])); - } - - public function testNoSupportWithObject() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['messenger' => 'input'])); - - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertFalse($dataTransformer->supportsTransformation(new Dummy(), Dummy::class, [])); - } - - public function testTransform() - { - $dummy = new Dummy(); - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertSame($dummy, $dataTransformer->transform($dummy, Dummy::class)); - } - - public function testSupportWithGraphqlContext() - { - $metadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $metadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata(null, null, null, null, null, []))->withGraphQl(['create' => ['messenger' => 'input']])); - $dataTransformer = new DataTransformer($metadataFactoryProphecy->reveal()); - $this->assertTrue($dataTransformer->supportsTransformation([], Dummy::class, ['input' => ['class' => 'smth'], 'graphql_operation_name' => 'create'])); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php b/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php deleted file mode 100644 index a38b5033507..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/ApiLoaderTest.php +++ /dev/null @@ -1,361 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidResourceException; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; -use ApiPlatform\Symfony\Routing\ApiLoader; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use ApiPlatform\Tests\Fixtures\RelatedDummyEntity; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Routing\Route; - -/** - * @author Antoine Bluchet - * @author Amrouche Hamza - * - * @group legacy - */ -class ApiLoaderTest extends TestCase -{ - use ProphecyTrait; - - public function testLegacyApiLoader() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withAttributes(['identifiers' => 'id']); - // default operation based on OperationResourceMetadataFactory - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'requirements' => ['id' => '\d+'], 'defaults' => ['my_default' => 'default_value', '_controller' => 'should_not_be_overriden'], 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], - ]); - // custom operations - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op' => ['method' => 'GET', 'controller' => 'some.service.name', 'requirements' => ['_format' => 'a valid format'], 'defaults' => ['my_default' => 'default_value', '_format' => 'a valid format'], 'condition' => "request.headers.get('User-Agent') matches '/firefox/i'", 'stateless' => null], // with controller - 'my_second_op' => ['method' => 'POST', 'options' => ['option' => 'option_value'], 'host' => '{subdomain}.api-platform.com', 'schemes' => ['https'], 'stateless' => null], // without controller, takes the default one - 'my_path_op' => ['method' => 'GET', 'path' => 'some/custom/path', 'stateless' => null], // custom path - 'my_stateless_op' => ['method' => 'GET', 'stateless' => true], - ]); - $resourceMetadata = $resourceMetadata->withSubresourceOperations([ - 'subresources_get_subresource' => ['stateless' => true], - ]); - - $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); - - $this->assertEquals( - $this->getRoute('/dummies/{id}.{_format}', 'api_platform.action.get_item', DummyEntity::class, 'api_dummies_get_item', ['GET'], false, ['id' => '\d+'], ['my_default' => 'default_value', '_stateless' => null]), - $routeCollection->get('api_dummies_get_item') - ); - - $this->assertEquals( - $this->getRoute('/dummies/{id}.{_format}', 'api_platform.action.delete_item', DummyEntity::class, 'api_dummies_delete_item', ['DELETE']), - $routeCollection->get('api_dummies_delete_item') - ); - - $this->assertEquals( - $this->getRoute('/dummies/{id}.{_format}', 'api_platform.action.put_item', DummyEntity::class, 'api_dummies_put_item', ['PUT']), - $routeCollection->get('api_dummies_put_item') - ); - - $this->assertEquals( - $this->getRoute('/dummies.{_format}', 'some.service.name', DummyEntity::class, 'api_dummies_my_op_collection', ['GET'], true, ['_format' => 'a valid format'], ['my_default' => 'default_value', '_format' => 'a valid format', '_stateless' => null], [], '', [], "request.headers.get('User-Agent') matches '/firefox/i'"), - $routeCollection->get('api_dummies_my_op_collection') - ); - - $this->assertEquals( - $this->getRoute('/dummies.{_format}', 'api_platform.action.post_collection', DummyEntity::class, 'api_dummies_my_second_op_collection', ['POST'], true, [], ['_stateless' => null], ['option' => 'option_value'], '{subdomain}.api-platform.com', ['https']), - $routeCollection->get('api_dummies_my_second_op_collection') - ); - - $this->assertEquals( - $this->getRoute('/some/custom/path', 'api_platform.action.get_collection', DummyEntity::class, 'api_dummies_my_path_op_collection', ['GET'], true), - $routeCollection->get('api_dummies_my_path_op_collection') - ); - - $this->assertEquals( - $this->getRoute('/dummies.{_format}', 'api_platform.action.get_collection', DummyEntity::class, 'api_dummies_my_stateless_op_collection', ['GET'], true, [], ['_stateless' => true]), - $routeCollection->get('api_dummies_my_stateless_op_collection') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/dummies/{id}/subresources.{_format}', 'api_platform.action.get_subresource', RelatedDummyEntity::class, 'api_dummies_subresources_get_subresource', ['property' => 'subresource', 'identifiers' => ['id' => [DummyEntity::class, 'id', true]], 'collection' => true, 'operationId' => 'api_dummies_subresources_get_subresource'], [], ['_stateless' => true]), - $routeCollection->get('api_dummies_subresources_get_subresource') - ); - } - - public function testApiLoaderWithPrefix() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'requirements' => ['id' => '\d+'], 'defaults' => ['my_default' => 'default_value', '_controller' => 'should_not_be_overriden'], 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], - ]); - $resourceMetadata = $resourceMetadata->withAttributes(['route_prefix' => '/foobar-prefix', 'identifiers' => 'id']); - - $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); - - $this->assertEquals( - $this->getRoute('/foobar-prefix/dummies/{id}.{_format}', 'api_platform.action.get_item', DummyEntity::class, 'api_dummies_get_item', ['GET'], false, ['id' => '\d+'], ['my_default' => 'default_value', '_stateless' => null]), - $routeCollection->get('api_dummies_get_item') - ); - - $this->assertEquals( - $this->getRoute('/foobar-prefix/dummies/{id}.{_format}', 'api_platform.action.delete_item', DummyEntity::class, 'api_dummies_delete_item', ['DELETE']), - $routeCollection->get('api_dummies_delete_item') - ); - - $this->assertEquals( - $this->getRoute('/foobar-prefix/dummies/{id}.{_format}', 'api_platform.action.put_item', DummyEntity::class, 'api_dummies_put_item', ['PUT']), - $routeCollection->get('api_dummies_put_item') - ); - } - - public function testNoMethodApiLoader() - { - $this->expectException(\RuntimeException::class); - - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => [], - ]); - - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], - ]); - - $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); - } - - public function testWrongMethodApiLoader() - { - $this->expectException(\RuntimeException::class); - - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'post' => ['method' => 'POST', 'stateless' => null], - ]); - - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], - ]); - - $this->getApiLoaderWithResourceMetadata($resourceMetadata)->load(null); - } - - public function testNoShortNameApiLoader() - { - $this->expectException(InvalidResourceException::class); - - $this->getApiLoaderWithResourceMetadata(new ResourceMetadata())->load(null); - } - - public function testRecursiveSubresource() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withShortName('dummy'); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'get' => ['method' => 'GET', 'stateless' => null], - 'put' => ['method' => 'PUT', 'stateless' => null], - 'delete' => ['method' => 'DELETE', 'stateless' => null], - ]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op' => ['method' => 'GET', 'controller' => 'some.service.name', 'stateless' => null], // with controller - 'my_second_op' => ['method' => 'POST', 'stateless' => null], // without controller, takes the default one - 'my_path_op' => ['method' => 'GET', 'path' => 'some/custom/path', 'stateless' => null], // custom path - ]); - - $routeCollection = $this->getApiLoaderWithResourceMetadata($resourceMetadata, true)->load(null); - - $this->assertEquals( - $this->getSubresourceRoute('/dummies/{id}/subresources.{_format}', 'api_platform.action.get_subresource', RelatedDummyEntity::class, 'api_dummies_subresources_get_subresource', ['property' => 'subresource', 'identifiers' => ['id' => [DummyEntity::class, 'id', true]], 'collection' => true, 'operationId' => 'api_dummies_subresources_get_subresource']), - $routeCollection->get('api_dummies_subresources_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/related_dummies/{id}/recursivesubresource/subresources.{_format}', 'api_platform.action.get_subresource', RelatedDummyEntity::class, 'api_related_dummies_recursivesubresource_subresources_get_subresource', ['property' => 'subresource', 'identifiers' => ['id' => [RelatedDummyEntity::class, 'id', true], 'recursivesubresource' => [DummyEntity::class, 'id', false]], 'collection' => true, 'operationId' => 'api_related_dummies_recursivesubresource_subresources_get_subresource']), - $routeCollection->get('api_related_dummies_recursivesubresource_subresources_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/related_dummies/{id}/recursivesubresource.{_format}', 'dummy_controller', DummyEntity::class, 'api_related_dummies_recursivesubresource_get_subresource', ['property' => 'recursivesubresource', 'identifiers' => ['id' => [RelatedDummyEntity::class, 'id', true]], 'collection' => false, 'operationId' => 'api_related_dummies_recursivesubresource_get_subresource']), - $routeCollection->get('api_related_dummies_recursivesubresource_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/dummies/{id}/subresources/{subresource}/recursivesubresource.{_format}', 'api_platform.action.get_subresource', DummyEntity::class, 'api_dummies_subresources_recursivesubresource_get_subresource', ['property' => 'recursivesubresource', 'identifiers' => ['id' => [DummyEntity::class, 'id', true], 'subresource' => [RelatedDummyEntity::class, 'id', true]], 'collection' => false, 'operationId' => 'api_dummies_subresources_recursivesubresource_get_subresource']), - $routeCollection->get('api_dummies_subresources_recursivesubresource_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/related_dummies/{id}/secondrecursivesubresource/subresources.{_format}', 'api_platform.action.get_subresource', RelatedDummyEntity::class, 'api_related_dummies_secondrecursivesubresource_subresources_get_subresource', ['property' => 'subresource', 'identifiers' => ['id' => [RelatedDummyEntity::class, 'id', true], 'secondrecursivesubresource' => [DummyEntity::class, 'id', false]], 'collection' => true, 'operationId' => 'api_related_dummies_secondrecursivesubresource_subresources_get_subresource']), - $routeCollection->get('api_related_dummies_secondrecursivesubresource_subresources_get_subresource') - ); - - $this->assertEquals( - $this->getSubresourceRoute('/related_dummies/{id}/secondrecursivesubresource.{_format}', 'api_platform.action.get_subresource', DummyEntity::class, 'api_related_dummies_secondrecursivesubresource_get_subresource', ['property' => 'secondrecursivesubresource', 'identifiers' => ['id' => [RelatedDummyEntity::class, 'id', true]], 'collection' => false, 'operationId' => 'api_related_dummies_secondrecursivesubresource_get_subresource']), - $routeCollection->get('api_related_dummies_secondrecursivesubresource_get_subresource') - ); - } - - private function getApiLoaderWithResourceMetadata(ResourceMetadata $resourceMetadata, $recursiveSubresource = false): ApiLoader - { - $routingConfig = __DIR__.'/../../../../../src/Symfony/Bundle/Resources/config/routing'; - - $kernelProphecy = $this->prophesize(KernelInterface::class); - $kernelProphecy->locateResource(Argument::any())->willReturn($routingConfig); - $possibleArguments = [ - 'api_platform.action.get_collection', - 'api_platform.action.post_collection', - 'api_platform.action.get_item', - 'api_platform.action.put_item', - 'api_platform.action.delete_item', - 'api_platform.action.get_subresource', - ]; - $containerProphecy = $this->prophesize(ContainerInterface::class); - - foreach ($possibleArguments as $possibleArgument) { - $containerProphecy->has($possibleArgument)->willReturn(true); - } - - $containerProphecy->has(Argument::type('string'))->willReturn(false); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata); - - $relatedDummyEntityMetadata = (new ResourceMetadata())->withShortName('related_dummies')->withSubresourceOperations([ - 'recursivesubresource_get_subresource' => [ - 'controller' => 'dummy_controller', - ], - ]); - - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->willReturn($relatedDummyEntityMetadata); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyEntity::class, RelatedDummyEntity::class])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->willReturn(new PropertyNameCollection(['id', 'subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->willReturn(new PropertyNameCollection(['id', 'recursivesubresource', 'secondrecursivesubresource'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata()); - - $relatedType = new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummyEntity::class); - - $subResourcePropertyMetadata = (new PropertyMetadata()) - ->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, true)) - ->withType(new Type(Type::BUILTIN_TYPE_ARRAY, false, \ArrayObject::class, true, null, $relatedType)); - - if (false === $recursiveSubresource) { - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'recursivesubresource', Argument::type('array'))->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'secondrecursivesubresource', Argument::type('array'))->willReturn(new PropertyMetadata()); - } else { - $dummyType = new Type(Type::BUILTIN_TYPE_OBJECT, false, DummyEntity::class); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'recursivesubresource', Argument::type('array')) - ->willReturn((new PropertyMetadata()) - ->withSubresource(new SubresourceMetadata(DummyEntity::class, false)) - ->withType($dummyType)); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'secondrecursivesubresource', Argument::type('array')) - ->willReturn((new PropertyMetadata()) - ->withSubresource(new SubresourceMetadata(DummyEntity::class, false)) - ->withType($dummyType)); - } - - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->willReturn($subResourcePropertyMetadata); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - $identifiersExtractor = $identifiersExtractorProphecy->reveal(); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), new UnderscorePathSegmentNameGenerator(), $identifiersExtractor); - - return new ApiLoader($kernelProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactory, $operationPathResolver, $containerProphecy->reveal(), ['jsonld' => ['application/ld+json']], [], $subresourceOperationFactory, false, true, true, false, false, $identifiersExtractor); - } - - private function getRoute(string $path, string $controller, string $resourceClass, string $operationName, array $methods, bool $collection = false, array $requirements = [], array $extraDefaults = ['_stateless' => null], array $options = [], string $host = '', array $schemes = [], string $condition = ''): Route - { - $legacyOperationName = str_replace('api_dummies_', '', str_replace($collection ? '_collection' : '_item', '', $operationName)); - - return new Route( - $path, - [ - '_controller' => $controller, - '_format' => $extraDefaults['_format'] ?? null, - '_api_resource_class' => $resourceClass, - '_api_identifiers' => ['id'], - '_api_has_composite_identifier' => false, - sprintf('_api_%s_operation_name', $collection ? 'collection' : 'item') => $legacyOperationName, - '_api_operation_name' => $operationName, - ] + $extraDefaults, - $requirements, - $options, - $host, - $schemes, - $methods, - $condition - ); - } - - private function getSubresourceRoute(string $path, string $controller, string $resourceClass, string $operationName, array $context, array $requirements = [], array $extraDefaults = ['_stateless' => null]): Route - { - return new Route( - $path, - [ - '_controller' => $controller, - '_format' => $extraDefaults['_format'] ?? null, - '_api_resource_class' => $resourceClass, - '_api_subresource_operation_name' => $operationName, - '_api_subresource_context' => $context, - '_api_identifiers' => $context['identifiers'], - '_api_has_composite_identifier' => false, - ] + $extraDefaults, - $requirements, - [], - '', - [], - ['GET'] - ); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/CachedRouteNameResolverTest.php b/tests/Core/Bridge/Symfony/Routing/CachedRouteNameResolverTest.php deleted file mode 100644 index 1c4b0f59252..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/CachedRouteNameResolverTest.php +++ /dev/null @@ -1,178 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\CachedRouteNameResolver; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Teoh Han Hui - */ -class CachedRouteNameResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertInstanceOf(RouteNameResolverInterface::class, $cachedRouteNameResolver); - } - - public function testGetRouteNameForItemRouteWithNoMatchingRoute() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No item route associated with the type "AppBundle\\Entity\\User".'); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(false)->shouldBeCalled(); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldNotBeCalled(); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', OperationType::ITEM, []) - ->willThrow(new InvalidArgumentException('No item route associated with the type "AppBundle\Entity\User".')) - ->shouldBeCalled(); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM); - } - - public function testGetRouteNameForItemRouteOnCacheMiss() - { - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(false)->shouldBeCalledTimes(1); - $cacheItemProphecy->set('some_item_route')->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy->reveal()); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldBeCalledTimes(1)->willReturn(true); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', false, [])->willReturn('some_item_route')->shouldBeCalledTimes(1); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', false)); - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', false), 'Trigger the local cache'); - } - - public function testGetRouteNameForItemRouteOnCacheHit() - { - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->shouldBeCalledTimes(1)->willReturn(true); - $cacheItemProphecy->get()->shouldBeCalledTimes(1)->willReturn('some_item_route'); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldNotBeCalled(); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName(Argument::cetera())->shouldNotBeCalled(); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM)); - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM), 'Trigger the local cache'); - } - - public function testGetRouteNameForCollectionRouteWithNoMatchingRoute() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No collection route associated with the type "AppBundle\\Entity\\User".'); - - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(false)->shouldBeCalled(); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldNotBeCalled(); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION, []) - ->willThrow(new InvalidArgumentException('No collection route associated with the type "AppBundle\Entity\User".')) - ->shouldBeCalled(); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION); - } - - public function testGetRouteNameForCollectionRouteOnCacheMiss() - { - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->shouldBeCalledTimes(1)->willReturn(false); - $cacheItemProphecy->set('some_collection_route')->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy->reveal()); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldBeCalledTimes(1)->willReturn(true); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', true, [])->willReturn('some_collection_route')->shouldBeCalledTimes(1); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_collection_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', true)); - $this->assertSame('some_collection_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', true), 'Trigger the local cache'); - } - - public function testGetRouteNameForCollectionRouteOnCacheHit() - { - $cacheItemProphecy = $this->prophesize(CacheItemInterface::class); - $cacheItemProphecy->isHit()->willReturn(true)->shouldBeCalledTimes(1); - $cacheItemProphecy->get()->willReturn('some_collection_route')->shouldBeCalledTimes(1); - - $cacheItemPoolProphecy = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPoolProphecy->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willReturn($cacheItemProphecy); - $cacheItemPoolProphecy->save($cacheItemProphecy)->shouldNotBeCalled(); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName(Argument::cetera())->shouldNotBeCalled(); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPoolProphecy->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_collection_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION)); - $this->assertSame('some_collection_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION), 'Trigger the local cache'); - } - - public function testGetRouteNameWithCacheItemThrowsCacheException() - { - $cacheException = new class() extends \Exception implements CacheException {}; - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem(Argument::type('string'))->shouldBeCalledTimes(1)->willThrow($cacheException); - - $decoratedProphecy = $this->prophesize(RouteNameResolverInterface::class); - $decoratedProphecy->getRouteName('AppBundle\Entity\User', OperationType::ITEM, [])->willReturn('some_item_route')->shouldBeCalledTimes(1); - - $cachedRouteNameResolver = new CachedRouteNameResolver($cacheItemPool->reveal(), $decoratedProphecy->reveal()); - - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM)); - $this->assertSame('some_item_route', $cachedRouteNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM), 'Trigger the local cache'); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/IriConverterTest.php b/tests/Core/Bridge/Symfony/Routing/IriConverterTest.php deleted file mode 100644 index f215880d50a..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/IriConverterTest.php +++ /dev/null @@ -1,453 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IdentifiersExtractor; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\IriConverter; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolverInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\ItemNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RouterInterface; - -/** - * @author Vincent Chalamon - * @group legacy - */ -class IriConverterTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function testGetItemFromIriNoRouteException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No route matches "/users/3".'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willThrow(new RouteNotFoundException())->shouldBeCalledTimes(1); - $converter = $this->getIriConverter($routerProphecy); - $converter->getItemFromIri('/users/3'); - } - - public function testGetItemFromIriNoResourceException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No resource associated to "/users/3".'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy); - $converter->getItemFromIri('/users/3'); - } - - public function testGetItemFromIriCollectionRouteException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The iri "/users" references a collection not an item.'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_collection_operation_name' => 'get', - '_api_identifiers' => ['id'], - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy); - $converter->getItemFromIri('/users'); - } - - public function testGetItemFromIriItemNotFoundException() - { - $this->expectException(ItemNotFoundException::class); - $this->expectExceptionMessage('Item not found for "/users/3".'); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy - ->getItem(Dummy::class, ['id' => 3], 'get', [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]) - ->shouldBeCalled()->willReturn(null); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_item_operation_name' => 'get', - '_api_identifiers' => ['id'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy); - $converter->getItemFromIri('/users/3'); - } - - public function testGetItemFromIri() - { - $item = new \stdClass(); - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(Dummy::class, ['id' => 3], 'get', ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->shouldBeCalled()->willReturn($item); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_item_operation_name' => 'get', - '_api_identifiers' => ['id'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item); - } - - public function testGetItemFromIriWithOperationName() - { - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem('AppBundle\Entity\User', ['id' => 3], 'operation_name', ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]) - ->willReturn('foo') - ->shouldBeCalledTimes(1); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'operation_name', - '_api_identifiers' => ['id'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), 'foo'); - } - - public function testGetIriFromResourceClass() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::COLLECTION)->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', [], UrlGeneratorInterface::ABS_PATH)->willReturn('/dummies'); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - $this->assertEquals($converter->getIriFromResourceClass(Dummy::class), '/dummies'); - } - - public function testGetIriFromResourceClassAbsoluteUrl() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::COLLECTION)->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', [], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('', '', '', [], [], ['url_generation_strategy' => UrlGeneratorInterface::ABS_URL])); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); - $this->assertEquals($converter->getIriFromResourceClass(Dummy::class), 'http://example.com/dummies'); - } - - public function testNotAbleToGenerateGetIriFromResourceClass() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unable to generate an IRI for "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy"'); - - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::COLLECTION)->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', [], UrlGeneratorInterface::ABS_PATH)->willThrow(new RouteNotFoundException()); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - $converter->getIriFromResourceClass(Dummy::class); - } - - /** - * @group legacy - */ - public function testGetSubresourceIriFromResourceClass() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::SUBRESOURCE, Argument::type('array'))->willReturn('api_dummies_related_dummies_get_subresource'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('api_dummies_related_dummies_get_subresource', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willReturn('/dummies/1/related_dummies'); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - $this->assertEquals($converter->getSubresourceIriFromResourceClass(Dummy::class, ['subresource_identifiers' => ['id' => 1], 'subresource_resources' => [RelatedDummy::class => 1]]), '/dummies/1/related_dummies'); - } - - /** - * @group legacy - */ - public function testNotAbleToGenerateGetSubresourceIriFromResourceClass() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unable to generate an IRI for "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy"'); - - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::SUBRESOURCE, Argument::type('array'))->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willThrow(new RouteNotFoundException()); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - $converter->getSubresourceIriFromResourceClass(Dummy::class, ['subresource_identifiers' => ['id' => 1], 'subresource_resources' => [RelatedDummy::class => 1]]); - } - - /** - * @group legacy - */ - public function testGetItemIriFromResourceClass() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::ITEM)->willReturn('api_dummies_get_item'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('api_dummies_get_item', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willReturn('/dummies/1'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['composite_identifier' => true])); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); - $this->assertEquals($converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]), '/dummies/1'); - } - - /** - * @group legacy - */ - public function testGetItemIriFromResourceClassAbsoluteUrl() - { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::ITEM)->willReturn('api_dummies_get_item'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('api_dummies_get_item', ['id' => 1], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/dummies/1'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('', '', '', [], [], ['url_generation_strategy' => UrlGeneratorInterface::ABS_URL])); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); - $this->assertEquals($converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]), 'http://example.com/dummies/1'); - } - - /** - * @group legacy - */ - public function testNotAbleToGenerateGetItemIriFromResourceClass() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Unable to generate an IRI for "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy"'); - - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routeNameResolverProphecy->getRouteName(Dummy::class, OperationType::ITEM)->willReturn('dummies'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->generate('dummies', ['id' => 1], UrlGeneratorInterface::ABS_PATH)->willThrow(new RouteNotFoundException()); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['composite_identifier' => true])); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, null, $resourceMetadataFactoryProphecy->reveal()); - $converter->getItemIriFromResourceClass(Dummy::class, ['id' => 1]); - } - - public function testGetItemFromIriWithIdentifierConverter() - { - $item = new \stdClass(); - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(Dummy::class, ['id' => 3], 'get', ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->shouldBeCalled()->willReturn($item); - $identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willReturn(['id' => 3]); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_item_operation_name' => 'get', - '_api_identifiers' => ['id' => [Dummy::class, 'id']], - 'id' => 3, - ])->shouldBeCalledTimes(1); - - $converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy, null, $identifierConverterProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item); - } - - public function testGetItemFromIriWithSubresourceDataProvider() - { - $item = new \stdClass(); - $subresourceContext = ['identifiers' => ['id' => [Dummy::class, 'id', true]]]; - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3/adresses')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_subresource_context' => $subresourceContext, - '_api_subresource_operation_name' => 'get_subresource', - '_api_identifiers' => $subresourceContext['identifiers'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - $subresourceDataProviderProphecy = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProviderProphecy->getSubresource(Dummy::class, ['id' => ['id' => 3]], $subresourceContext + ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true], 'get_subresource')->shouldBeCalled()->willReturn($item); - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $subresourceDataProviderProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3/adresses', ['fetch_data' => true]), $item); - } - - public function testGetItemFromIriWithSubresourceDataProviderNotFound() - { - $this->expectException(ItemNotFoundException::class); - $this->expectExceptionMessage('Item not found for "/users/3/adresses".'); - - $subresourceContext = ['identifiers' => ['id' => [Dummy::class, 'id', true]]]; - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3/adresses')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_subresource_context' => $subresourceContext, - '_api_subresource_operation_name' => 'get_subresource', - '_api_identifiers' => $subresourceContext['identifiers'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - $identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willReturn(['id' => 3]); - $subresourceDataProviderProphecy = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProviderProphecy->getSubresource(Dummy::class, ['id' => ['id' => 3]], $subresourceContext + ['fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true], 'get_subresource')->shouldBeCalled()->willReturn(null); - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $subresourceDataProviderProphecy, $identifierConverterProphecy); - $converter->getItemFromIri('/users/3/adresses', ['fetch_data' => true]); - } - - public function testGetItemFromIriBadIdentifierException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Item not found for "/users/3".'); - - $item = new \stdClass(); - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->match('/users/3')->willReturn([ - '_api_resource_class' => Dummy::class, - '_api_item_operation_name' => 'get_subresource', - '_api_identifiers' => ['id'], - 'id' => 3, - ])->shouldBeCalledTimes(1); - $identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverterProphecy->convert(['id' => '3'], Dummy::class)->shouldBeCalled()->willThrow(new InvalidIdentifierException('Item not found for "/users/3".')); - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, $identifierConverterProphecy); - $this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item); - } - - public function testNoIdentifiersException() - { - $this->markTestSkipped('The method "generateIdentifiersUrl" has been removed.'); - /* @phpstan-ignore-next-line */ - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('No identifiers defined for resource of type "\App\Entity\Sample"'); - - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - - $converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy); - - $method = new \ReflectionMethod(IriConverter::class, 'generateIdentifiersUrl'); - $method->setAccessible(true); - $method->invoke($converter, [], '\App\Entity\Sample'); - } - - /** - * @group legacy - */ - public function testLegacyConstructor() - { - $this->expectDeprecation('Not injecting ApiPlatform\Core\Api\ResourceClassResolverInterface in the IdentifiersExtractor might introduce cache issues with object identifiers.'); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $routerProphecy = $this->prophesize(RouterInterface::class); - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - - new IriConverter( - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $itemDataProviderProphecy->reveal(), - $routeNameResolverProphecy->reveal(), - $routerProphecy->reveal(), - null - ); - } - - private function getResourceClassResolver() - { - $resourceClassResolver = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolver->isResourceClass(Argument::type('string'))->will(function ($args) { - return true; - }); - - $resourceClassResolver->getResourceClass(Argument::cetera())->will(function ($args) { - return \get_class($args[0]); - }); - - return $resourceClassResolver->reveal(); - } - - private function getIriConverter($routerProphecy = null, $routeNameResolverProphecy = null, $itemDataProviderProphecy = null, $subresourceDataProviderProphecy = null, $identifierConverterProphecy = null, $resourceMetadataFactory = null) - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - if (!$routerProphecy) { - $routerProphecy = $this->prophesize(RouterInterface::class); - } - - if (!$routeNameResolverProphecy) { - $routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class); - } - - $itemDataProvider = $itemDataProviderProphecy ?: $this->prophesize(ItemDataProviderInterface::class); - - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - if (null === $identifierConverterProphecy) { - $identifierConverterProphecy = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverterProphecy->convert(Argument::type('array'), Argument::type('string'))->will(function ($args) { - return $args[0]; - }); - } - - return new IriConverter( - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $itemDataProvider->reveal(), - $routeNameResolverProphecy->reveal(), - $routerProphecy->reveal(), - null, - new IdentifiersExtractor($propertyNameCollectionFactory, $propertyMetadataFactory, null, $this->getResourceClassResolver()), - $subresourceDataProviderProphecy ? $subresourceDataProviderProphecy->reveal() : null, - $identifierConverterProphecy->reveal(), - null, - $resourceMetadataFactory - ); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/RouteNameGeneratorTest.php b/tests/Core/Bridge/Symfony/Routing/RouteNameGeneratorTest.php deleted file mode 100644 index 0d3663e7669..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/RouteNameGeneratorTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; - -/** - * @author Baptiste Meyer - */ -class RouteNameGeneratorTest extends TestCase -{ - public function testGenerate() - { - $this->assertEquals('api_foos_get_collection', RouteNameGenerator::generate('get', 'Foo', OperationType::COLLECTION)); - $this->assertEquals('api_bars_custom_operation_item', RouteNameGenerator::generate('custom_operation', 'Bar', OperationType::ITEM)); - } - - /** - * @group legacy - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testLegacyGenerate() - { - $this->assertEquals('api_foos_get_collection', RouteNameGenerator::generate('get', 'Foo', true)); - } - - public function testGenerateWithSubresource() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Subresource operations are not supported by the RouteNameGenerator.'); - - $this->assertEquals('api_foos_bar_get_subresource', RouteNameGenerator::generate('get', 'Foo', OperationType::SUBRESOURCE)); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/RouteNameResolverTest.php b/tests/Core/Bridge/Symfony/Routing/RouteNameResolverTest.php deleted file mode 100644 index 7f7ba96d33b..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/RouteNameResolverTest.php +++ /dev/null @@ -1,195 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolver; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; - -/** - * @author Teoh Han Hui - */ -class RouteNameResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $routerProphecy = $this->prophesize(RouterInterface::class); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - - $this->assertInstanceOf(RouteNameResolverInterface::class, $routeNameResolver); - } - - public function testGetRouteNameForItemRouteWithNoMatchingRoute() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('No item route associated with the type "AppBundle\\Entity\\User".'); - - $routeCollection = new RouteCollection(); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM); - } - - /** - * @group legacy - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testGetRouteNameForItemRouteLegacy() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', false); - - $this->assertSame('some_item_route', $actual); - } - - public function testGetRouteNameForItemRoute() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::ITEM); - - $this->assertSame('some_item_route', $actual); - } - - public function testGetRouteNameForCollectionRouteWithNoMatchingRoute() - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('No collection route associated with the type "AppBundle\\Entity\\User".'); - - $routeCollection = new RouteCollection(); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION); - } - - /** - * @group legacy - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testGetRouteNameForCollectionRouteLegacy() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', true); - - $this->assertSame('some_collection_route', $actual); - } - - public function testGetRouteNameForCollectionRoute() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('some_item_route', new Route('/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_item_operation_name' => 'some_item_op', - ])); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::COLLECTION); - - $this->assertSame('some_collection_route', $actual); - } - - public function testGetRouteNameForSubresourceRoute() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('a_some_subresource_route', new Route('/a/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_subresource_operation_name' => 'some_other_item_op', - '_api_subresource_context' => ['identifiers' => ['id' => ['Bar', 'id']]], - ])); - $routeCollection->add('b_some_subresource_route', new Route('/b/some/item/path/{id}', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_subresource_operation_name' => 'some_item_op', - '_api_subresource_context' => ['identifiers' => ['id' => ['Foo', 'id']]], - ])); - $routeCollection->add('some_collection_route', new Route('/some/collection/path', [ - '_api_resource_class' => 'AppBundle\Entity\User', - '_api_collection_operation_name' => 'some_collection_op', - ])); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $routeNameResolver = new RouteNameResolver($routerProphecy->reveal()); - $actual = $routeNameResolver->getRouteName('AppBundle\Entity\User', OperationType::SUBRESOURCE, ['subresource_resources' => ['Foo' => 1]]); - - $this->assertSame('b_some_subresource_route', $actual); - } -} diff --git a/tests/Core/Bridge/Symfony/Routing/RouterOperationPathResolverTest.php b/tests/Core/Bridge/Symfony/Routing/RouterOperationPathResolverTest.php deleted file mode 100644 index c8c72e99afc..00000000000 --- a/tests/Core/Bridge/Symfony/Routing/RouterOperationPathResolverTest.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * 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\Routing; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; - -/** - * @author Baptiste Meyer - */ -class RouterOperationPathResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testResolveOperationPath() - { - $routeCollection = new RouteCollection(); - $routeCollection->add('foos', new Route('/foos')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection)->shouldBeCalled(); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), $this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $this->assertEquals('/foos', $operationPathResolver->resolveOperationPath('Foo', ['route_name' => 'foos'], OperationType::COLLECTION, 'get')); - } - - public function testResolveOperationPathWithSubresource() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Subresource operations are not supported by the RouterOperationPathResolver without a route name.'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), $this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $operationPathResolver->resolveOperationPath('Foo', ['property' => 'bar', 'collection' => true, 'resource_class' => 'Foo'], OperationType::SUBRESOURCE, 'get'); - } - - public function testResolveOperationPathWithRouteNameGeneration() - { - $routeCollection = new RouteCollection(); - $routeCollection->add(RouteNameGenerator::generate('get', 'Foo', OperationType::COLLECTION), new Route('/foos')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection)->shouldBeCalled(); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), $this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $this->assertEquals('/foos', $operationPathResolver->resolveOperationPath('Foo', [], OperationType::COLLECTION, 'get')); - } - - public function testResolveOperationPathWithRouteNotFound() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The route "api_foos_get_collection" of the resource "Foo" was not found.'); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn(new RouteCollection())->shouldBeCalled(); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), $this->prophesize(OperationPathResolverInterface::class)->reveal()); - $operationPathResolver->resolveOperationPath('Foo', [], OperationType::COLLECTION, 'get'); - } - - /** - * @group legacy - * @expectedDeprecation Method ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver::resolveOperationPath() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1. - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testLegacyResolveOperationPath() - { - $operationPathResolverProphecy = $this->prophesize(OperationPathResolverInterface::class); - $operationPathResolverProphecy->resolveOperationPath('Foo', [], OperationType::ITEM, null)->willReturn('/foos/{id}.{_format}')->shouldBeCalled(); - - $operationPathResolver = new RouterOperationPathResolver($this->prophesize(RouterInterface::class)->reveal(), $operationPathResolverProphecy->reveal()); - - $this->assertEquals('/foos/{id}.{_format}', $operationPathResolver->resolveOperationPath('Foo', [], false)); - } -} diff --git a/tests/Core/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php b/tests/Core/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php deleted file mode 100644 index 6fd2b4f3073..00000000000 --- a/tests/Core/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php +++ /dev/null @@ -1,212 +0,0 @@ - - * - * 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\EventListener; - -use ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidateListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use ApiPlatform\Validator\Exception\ValidationException; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\Validator\ConstraintViolationListInterface; -use Symfony\Component\Validator\Validator\ValidatorInterface; - -/** - * @author Samuel ROZE - * - * @group legacy - */ -class ValidateListenerTest extends TestCase -{ - use ProphecyTrait; - - public function testNotAnApiPlatformRequest() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - $validator = $validatorProphecy->reveal(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $request = new Request(); - $request->setMethod('POST'); - - $listener = new ValidateListener($validator, $resourceMetadataFactory); - - $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, []); - $listener->onKernelView($event); - } - - public function testValidatorIsCalled() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $constraintViolationList = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationList->count()->willReturn(0); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->willReturn($constraintViolationList)->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->has(Argument::any())->shouldNotBeCalled(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory, $containerProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testGetGroupsFromCallable() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $constraintViolationList = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationList->count()->willReturn(0); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->willReturn($constraintViolationList)->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - $closure = function ($data) use ($expectedValidationGroups): array { - return $data instanceof DummyEntity ? $expectedValidationGroups : []; - }; - - [$resourceMetadataFactory, $event] = $this->createEventObject($closure, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - public function testGetGroupsFromService() - { - $data = new DummyEntity(); - - $constraintViolationList = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationList->count()->willReturn(0); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, ['a', 'b', 'c'])->willReturn($constraintViolationList)->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject('groups_builder', $data); - - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->has('groups_builder')->willReturn(true)->shouldBeCalled(); - $containerProphecy->get('groups_builder')->willReturn(new class() { - public function __invoke($data): array - { - return $data instanceof DummyEntity ? ['a', 'b', 'c'] : []; - } - } - )->shouldBeCalled(); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory, $containerProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testValidatorWithScalarGroup() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['foo']; - - $constraintViolationList = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationList->count()->willReturn(0); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->willreturn($constraintViolationList)->shouldBeCalled(); - - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->has('foo')->willReturn(false)->shouldBeCalled(); - - [$resourceMetadataFactory, $event] = $this->createEventObject('foo', $data); - - $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactory, $containerProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testDoNotCallWhenReceiveFlagIsFalse() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->shouldNotBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data, false); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - public function testThrowsValidationExceptionWithViolationsFound() - { - $this->expectException(ValidationException::class); - - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $violationsProphecy = $this->prophesize(ConstraintViolationListInterface::class); - $violationsProphecy->rewind()->shouldBeCalled(); - $violationsProphecy->valid()->shouldBeCalled(); - $violationsProphecy->count()->willReturn(1)->shouldBeCalled(); - $violations = $violationsProphecy->reveal(); - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, null, $expectedValidationGroups)->willReturn($violations)->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - private function createEventObject($expectedValidationGroups, $data, bool $receive = true): array - { - $resourceMetadata = new ResourceMetadata(null, null, null, [ - 'create' => ['validation_groups' => $expectedValidationGroups], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - if ($receive) { - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata)->shouldBeCalled(); - } - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $kernel = $this->prophesize(HttpKernelInterface::class)->reveal(); - $request = new Request([], [], [ - '_api_resource_class' => DummyEntity::class, - '_api_item_operation_name' => 'create', - '_api_format' => 'json', - '_api_mime_type' => 'application/json', - '_api_receive' => $receive, - ]); - - $request->setMethod('POST'); - $event = new ViewEvent($kernel, $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $data); - - return [$resourceMetadataFactory, $event]; - } -} diff --git a/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php b/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php deleted file mode 100644 index b261e167ff3..00000000000 --- a/tests/Core/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,398 +0,0 @@ - - * - * 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; - -use ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; -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\ValidatorPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\DummyAtLeastOneOfValidatedEntity; -use ApiPlatform\Tests\Fixtures\DummyIriWithValidationEntity; -use ApiPlatform\Tests\Fixtures\DummySequentiallyValidatedEntity; -use ApiPlatform\Tests\Fixtures\DummyValidatedEntity; -use Doctrine\Common\Annotations\AnnotationReader; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Intl\Countries; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Validator\Constraints\AtLeastOneOf; -use Symfony\Component\Validator\Constraints\Sequentially; -use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; -use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; - -/** - * @author Baptiste Meyer - */ -class ValidatorPropertyMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - private $validatorClassMetadata; - - protected function setUp(): void - { - $this->validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($this->validatorClassMetadata); - } - - public function testCreateWithPropertyWithRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(true); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy', [])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy'); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithNotRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy date', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(false); - $expectedPropertyMetadata = $expectedPropertyMetadata->withIri('http://schema.org/Date'); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate', [])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate'); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithoutConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy id', true, true, null, null, null, true); - $expectedPropertyMetadata = $propertyMetadata->withRequired(false); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyId', [])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyId'); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithRightValidationGroupsAndRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(true); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['dummy']])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['dummy']]); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithBadValidationGroupsAndRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(false); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['ymmud']])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => ['ymmud']]); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithNonStringValidationGroupsAndRequiredConstraints() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); - $expectedPropertyMetadata = $propertyMetadata->withRequired(false); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [1312]])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [1312]]); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithRequiredByDecorated() - { - $propertyMetadata = new PropertyMetadata(null, 'A dummy date', true, true, null, null, true, false, 'foo:bar'); - $expectedPropertyMetadata = clone $propertyMetadata; - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate', [])->willReturn($propertyMetadata)->shouldBeCalled(); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyDate'); - - $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); - } - - public function testCreateWithPropertyWithValidationConstraints() - { - if (!class_exists(Countries::class)) { - $this->markTestSkipped('symfony/intl not installed'); - } - - $validatorClassMetadata = new ClassMetadata(DummyIriWithValidationEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $types = [ - 'dummyUrl' => 'http://schema.org/url', - 'dummyEmail' => 'http://schema.org/email', - 'dummyUuid' => 'http://schema.org/identifier', - 'dummyCardScheme' => 'http://schema.org/identifier', - 'dummyBic' => 'http://schema.org/identifier', - 'dummyIban' => 'http://schema.org/identifier', - 'dummyDate' => 'http://schema.org/Date', - 'dummyDateTime' => 'http://schema.org/DateTime', - 'dummyTime' => 'http://schema.org/Time', - 'dummyImage' => 'http://schema.org/image', - 'dummyFile' => 'http://schema.org/MediaObject', - 'dummyCurrency' => 'http://schema.org/priceCurrency', - 'dummyIsbn' => 'http://schema.org/isbn', - 'dummyIssn' => 'http://schema.org/issn', - ]; - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - foreach ($types as $property => $iri) { - $decoratedPropertyMetadataFactory->create(DummyIriWithValidationEntity::class, $property, [])->willReturn(new PropertyMetadata())->shouldBeCalled(); - } - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyIriWithValidationEntity::class)->willReturn($validatorClassMetadata)->shouldBeCalled(); - - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [] - ); - - foreach ($types as $property => $iri) { - $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyIriWithValidationEntity::class, $property); - $this->assertSame($iri, $resultedPropertyMetadata->getIri()); - } - } - - public function testCreateWithPropertyLengthRestriction(): void - { - $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $property = 'dummy'; - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, $property, [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) - )->shouldBeCalled(); - - $lengthRestrictions = new PropertySchemaLengthRestriction(); - $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(), [$lengthRestrictions] - ); - - $schema = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, $property)->getSchema(); - $this->assertNotNull($schema); - $this->assertArrayHasKey('minLength', $schema); - $this->assertArrayHasKey('maxLength', $schema); - } - - public function testCreateWithPropertyRegexRestriction(): void - { - $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy', [])->willReturn( - new PropertyMetadata() - )->shouldBeCalled(); - - $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(), - [new PropertySchemaRegexRestriction()] - ); - - $schema = $validationPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy')->getSchema(); - $this->assertNotNull($schema); - $this->assertArrayHasKey('pattern', $schema); - $this->assertEquals('^(dummy)$', $schema['pattern']); - } - - public function testCreateWithPropertyFormatRestriction(): void - { - $validatorClassMetadata = new ClassMetadata(DummyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - $formats = [ - 'dummyEmail' => 'email', - 'dummyUuid' => 'uuid', - 'dummyIpv4' => 'ipv4', - 'dummyIpv6' => 'ipv6', - ]; - - foreach ($formats as $property => $format) { - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, $property, [])->willReturn( - new PropertyMetadata() - )->shouldBeCalled(); - $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [new PropertySchemaFormat()] - ); - $schema = $validationPropertyMetadataFactory->create(DummyValidatedEntity::class, $property)->getSchema(); - $this->assertNotNull($schema); - $this->assertArrayHasKey('format', $schema); - $this->assertEquals($format, $schema['format']); - } - } - - public function testCreateWithSequentiallyConstraint(): void - { - if (!class_exists(Sequentially::class)) { - $this->markTestSkipped(); - } - - $validatorClassMetadata = new ClassMetadata(DummySequentiallyValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummySequentiallyValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummySequentiallyValidatedEntity::class, 'dummy', [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) - )->shouldBeCalled(); - $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - [new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()] - ); - $schema = $validationPropertyMetadataFactory->create(DummySequentiallyValidatedEntity::class, 'dummy')->getSchema(); - - $this->assertNotNull($schema); - $this->assertArrayHasKey('minLength', $schema); - $this->assertArrayHasKey('maxLength', $schema); - $this->assertArrayHasKey('pattern', $schema); - } - - public function testCreateWithAtLeastOneOfConstraint(): void - { - if (!class_exists(AtLeastOneOf::class)) { - $this->markTestSkipped(); - } - - $validatorClassMetadata = new ClassMetadata(DummyAtLeastOneOfValidatedEntity::class); - (new AnnotationLoader(new AnnotationReader()))->loadClassMetadata($validatorClassMetadata); - - $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); - $validatorMetadataFactory->getMetadataFor(DummyAtLeastOneOfValidatedEntity::class) - ->willReturn($validatorClassMetadata) - ->shouldBeCalled(); - - $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedPropertyMetadataFactory->create(DummyAtLeastOneOfValidatedEntity::class, 'dummy', [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING)) - )->shouldBeCalled(); - $restrictionsMetadata = [new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()]; - $restrictionsMetadata = [new PropertySchemaOneOfRestriction($restrictionsMetadata), new PropertySchemaLengthRestriction(), new PropertySchemaRegexRestriction()]; - $validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory( - $validatorMetadataFactory->reveal(), - $decoratedPropertyMetadataFactory->reveal(), - $restrictionsMetadata - ); - $schema = $validationPropertyMetadataFactory->create(DummyAtLeastOneOfValidatedEntity::class, 'dummy')->getSchema(); - - $this->assertNotNull($schema); - $this->assertArrayHasKey('oneOf', $schema); - $this->assertSame([ - ['pattern' => '^(.*#.*)$'], - ['minLength' => 10], - ], $schema['oneOf']); - } -} diff --git a/tests/Core/DataPersister/ChainDataPersisterTest.php b/tests/Core/DataPersister/ChainDataPersisterTest.php deleted file mode 100644 index 4248a3f6feb..00000000000 --- a/tests/Core/DataPersister/ChainDataPersisterTest.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * 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\DataPersister; - -use ApiPlatform\Core\DataPersister\ChainDataPersister; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataPersister\ResumableDataPersisterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Baptiste Meyer - */ -class ChainDataPersisterTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $this->assertInstanceOf(DataPersisterInterface::class, new ChainDataPersister([$this->prophesize(DataPersisterInterface::class)->reveal()])); - } - - public function testSupports() - { - $dummy = new Dummy(); - - $persisterProphecy = $this->prophesize(DataPersisterInterface::class); - $persisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - - $this->assertTrue((new ChainDataPersister([$persisterProphecy->reveal()]))->supports($dummy)); - } - - public function testDoesNotSupport() - { - $dummy = new Dummy(); - - $persisterProphecy = $this->prophesize(DataPersisterInterface::class); - $persisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - - $this->assertFalse((new ChainDataPersister([$persisterProphecy->reveal()]))->supports($dummy)); - } - - public function testPersist() - { - $dummy = new Dummy(); - - $fooPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $fooPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - $fooPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $barPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $barPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $barPersisterProphecy->persist($dummy, Argument::type('array'))->shouldBeCalled(); - - $foobarPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $foobarPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled(); - $foobarPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - - (new ChainDataPersister([$fooPersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->persist($dummy); - } - - public function testRemove() - { - $dummy = new Dummy(); - - $fooPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $fooPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - $fooPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $barPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $barPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $barPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled(); - - $foobarPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $foobarPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled(); - $foobarPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - (new ChainDataPersister([$fooPersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->remove($dummy); - } - - public function testResumable() - { - $dummy = new Dummy(); - $fooPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $fooPersisterProphecy->willImplement(ResumableDataPersisterInterface::class); - $fooPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $fooPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - $fooPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled(); - $fooPersisterProphecy->resumable(Argument::type('array'))->willReturn(true)->shouldBeCalled(); - - $foo2PersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $foo2PersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - $foo2PersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $foo2PersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $barPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $barPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $barPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - $barPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled(); - - $foobarPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $foobarPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldNotBeCalled(); - $foobarPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $foobarPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - (new ChainDataPersister([$fooPersisterProphecy->reveal(), $foo2PersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->persist($dummy); - (new ChainDataPersister([$fooPersisterProphecy->reveal(), $foo2PersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->remove($dummy); - } -} diff --git a/tests/Core/DataProvider/ChainCollectionDataProviderTest.php b/tests/Core/DataProvider/ChainCollectionDataProviderTest.php deleted file mode 100644 index 4788181528a..00000000000 --- a/tests/Core/DataProvider/ChainCollectionDataProviderTest.php +++ /dev/null @@ -1,126 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainCollectionDataProvider; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * Retrieves items from a persistence layer. - * - * @author Kévin Dunglas - */ -class ChainCollectionDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetCollection() - { - $dummy = new Dummy(); - $dummy->setName('Rosa'); - $dummy2 = new Dummy(); - $dummy2->setName('Parks'); - - $firstDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, null, [])->willReturn(false); - - $secondDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $secondDataProvider->willImplement(RestrictedDataProviderInterface::class); - $secondDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $secondDataProvider->getCollection(Dummy::class, null, []) - ->willReturn([$dummy, $dummy2]); - - $thirdDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $thirdDataProvider->willImplement(RestrictedDataProviderInterface::class); - $thirdDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $thirdDataProvider->getCollection(Dummy::class, null, [])->willReturn([$dummy]); - - $chainItemDataProvider = new ChainCollectionDataProvider([ - $firstDataProvider->reveal(), - $secondDataProvider->reveal(), - $thirdDataProvider->reveal(), - ]); - - $this->assertEquals( - [$dummy, $dummy2], - $chainItemDataProvider->getCollection(Dummy::class) - ); - } - - public function testGetCollectionNotSupported() - { - $firstDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports('notfound', 'op', [])->willReturn(false); - - $collection = (new ChainCollectionDataProvider([$firstDataProvider->reveal()]))->getCollection('notfound', 'op'); - - $this->assertTrue(is_iterable($collection)); - $this->assertEmpty($collection); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetCollection() - { - $dummy = new Dummy(); - $dummy->setName('Rosa'); - $dummy2 = new Dummy(); - $dummy2->setName('Parks'); - - $firstDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $firstDataProvider->getCollection(Dummy::class, null, [])->willThrow(ResourceClassNotSupportedException::class); - - $secondDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $secondDataProvider->getCollection(Dummy::class, null, [])->willReturn([$dummy, $dummy2]); - - $thirdDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $thirdDataProvider->getCollection(Dummy::class, null, [])->willReturn([$dummy]); - - $chainItemDataProvider = new ChainCollectionDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]); - - $this->assertEquals([$dummy, $dummy2], $chainItemDataProvider->getCollection(Dummy::class)); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetCollectionExceptions() - { - $firstDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $firstDataProvider->getCollection('notfound', 'op', [])->willThrow(ResourceClassNotSupportedException::class); - - $collection = (new ChainCollectionDataProvider([$firstDataProvider->reveal()]))->getCollection('notfound', 'op'); - - $this->assertTrue(is_iterable($collection)); - $this->assertEmpty($collection); - } - - public function testGetCollectionWithEmptyDataProviders() - { - $collection = (new ChainCollectionDataProvider([]))->getCollection(Dummy::class); - - $this->assertTrue(is_iterable($collection)); - $this->assertEmpty($collection); - } -} diff --git a/tests/Core/DataProvider/ChainItemDataProviderTest.php b/tests/Core/DataProvider/ChainItemDataProviderTest.php deleted file mode 100644 index a28aad91635..00000000000 --- a/tests/Core/DataProvider/ChainItemDataProviderTest.php +++ /dev/null @@ -1,158 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainItemDataProvider; -use ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositePrimitiveItem; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * Retrieves items from a persistence layer. - * - * @author Kévin Dunglas - */ -class ChainItemDataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetItem() - { - $dummy = new Dummy(); - $dummy->setName('Lucie'); - - $firstDataProvider = $this->prophesize(DenormalizedIdentifiersAwareItemDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, null, [])->willReturn(false); - - $secondDataProvider = $this->prophesize(DenormalizedIdentifiersAwareItemDataProviderInterface::class); - $secondDataProvider->willImplement(RestrictedDataProviderInterface::class); - $secondDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $secondDataProvider->getItem(Dummy::class, ['id' => 1], null, [])->willReturn($dummy); - - $thirdDataProvider = $this->prophesize(DenormalizedIdentifiersAwareItemDataProviderInterface::class); - $thirdDataProvider->willImplement(RestrictedDataProviderInterface::class); - $thirdDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $thirdDataProvider->getItem(Dummy::class, ['id' => 1], null, [])->willReturn(new \stdClass()); - - $chainItemDataProvider = new ChainItemDataProvider([ - $firstDataProvider->reveal(), - $secondDataProvider->reveal(), - $thirdDataProvider->reveal(), - ]); - - $this->assertEquals($dummy, $chainItemDataProvider->getItem(Dummy::class, ['id' => 1])); - } - - public function testGetItemWithoutDenormalizedIdentifiers() - { - $dummy = new Dummy(); - $dummy->setName('Lucie'); - - $firstDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, null, [])->willReturn(false); - - $secondDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $secondDataProvider->willImplement(RestrictedDataProviderInterface::class); - $secondDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $secondDataProvider->getItem(Dummy::class, '1', null, [])->willReturn($dummy); - - $thirdDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $thirdDataProvider->willImplement(RestrictedDataProviderInterface::class); - $thirdDataProvider->supports(Dummy::class, null, [])->willReturn(true); - $thirdDataProvider->getItem(Dummy::class, 1, null, [])->willReturn(new \stdClass()); - - $chainItemDataProvider = new ChainItemDataProvider([ - $firstDataProvider->reveal(), - $secondDataProvider->reveal(), - $thirdDataProvider->reveal(), - ]); - - $this->assertEquals($dummy, $chainItemDataProvider->getItem(Dummy::class, ['id' => 1])); - } - - public function testGetItemExceptions() - { - $firstDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports('notfound', null, [])->willReturn(false); - - $chainItemDataProvider = new ChainItemDataProvider([$firstDataProvider->reveal()]); - - $this->assertEquals('', $chainItemDataProvider->getItem('notfound', 1)); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetItem() - { - $dummy = new Dummy(); - $dummy->setName('Lucie'); - - $firstDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $firstDataProvider->getItem(Dummy::class, 1, null, [])->willThrow(ResourceClassNotSupportedException::class); - - $secondDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $secondDataProvider->getItem(Dummy::class, 1, null, [])->willReturn($dummy); - - $thirdDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $thirdDataProvider->getItem(Dummy::class, 1, null, [])->willReturn(new \stdClass()); - - $chainItemDataProvider = new ChainItemDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]); - - $chainItemDataProvider->getItem(Dummy::class, 1); - } - - /** - * @group legacy - * @expectedDeprecation Receiving "$id" as non-array in an item data provider is deprecated in 2.3 in favor of implementing "ApiPlatform\Core\DataProvider\DenormalizedIdentifiersAwareItemDataProviderInterface". - */ - public function testLegacyGetItemWithoutDenormalizedIdentifiersAndCompositeIdentifier() - { - $dummy = new CompositePrimitiveItem('Lucie', 1984); - - $dataProvider = $this->prophesize(ItemDataProviderInterface::class); - $dataProvider->willImplement(RestrictedDataProviderInterface::class); - $dataProvider->supports(CompositePrimitiveItem::class, null, [])->willReturn(true); - $dataProvider->getItem(CompositePrimitiveItem::class, 'name=Lucie;year=1984', null, [])->willReturn($dummy); - - $chainItemDataProvider = new ChainItemDataProvider([ - $dataProvider->reveal(), - ]); - - $this->assertEquals($dummy, $chainItemDataProvider->getItem(CompositePrimitiveItem::class, ['name' => 'Lucie', 'year' => 1984])); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetItemExceptions() - { - $firstDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $firstDataProvider->getItem('notfound', 1, null, [])->willThrow(ResourceClassNotSupportedException::class); - - $chainItemDataProvider = new ChainItemDataProvider([$firstDataProvider->reveal()]); - - $this->assertEquals('', $chainItemDataProvider->getItem('notfound', 1)); - } -} diff --git a/tests/Core/DataProvider/ChainSubresourcedataProviderTest.php b/tests/Core/DataProvider/ChainSubresourcedataProviderTest.php deleted file mode 100644 index c451d62194a..00000000000 --- a/tests/Core/DataProvider/ChainSubresourcedataProviderTest.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * 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\DataProvider; - -use ApiPlatform\Core\DataProvider\ChainSubresourceDataProvider; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotSupportedException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * Retrieves items from a persistence layer. - */ -class ChainSubresourcedataProviderTest extends TestCase -{ - use ProphecyTrait; - - public function testGetSubresource() - { - $dummy = new Dummy(); - $dummy->setName('Rosa'); - $dummy2 = new Dummy(); - $dummy2->setName('Parks'); - - $context = ['identifiers' => ['id' => Dummy::class], 'property' => 'relatedDummies']; - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false); - $firstDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2])->willThrow(ResourceClassNotSupportedException::class); - - $secondDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $secondDataProvider->willImplement(RestrictedDataProviderInterface::class); - $secondDataProvider->supports(Dummy::class, 'get', $context)->willReturn(true); - $secondDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2]); - - $thirdDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $thirdDataProvider->willImplement(RestrictedDataProviderInterface::class); - $thirdDataProvider->supports(Dummy::class, 'get', $context)->willReturn(true); - $thirdDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy]); - - $chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]); - - $this->assertEquals([$dummy, $dummy2], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')); - } - - public function testGetSubresourceExceptionsItem() - { - $context = ['collection' => false]; - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false); - - $chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal()]); - - $this->assertNull($chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')); - } - - public function testGetSubresourceExceptionsCollection() - { - $context = ['collection' => true]; - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->willImplement(RestrictedDataProviderInterface::class); - $firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false); - - $chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal()]); - - $this->assertEquals([], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetSubresource() - { - $dummy = new Dummy(); - $dummy->setName('Rosa'); - $dummy2 = new Dummy(); - $dummy2->setName('Parks'); - - $context = ['identifiers' => ['id' => Dummy::class], 'property' => 'relatedDummies']; - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2])->willThrow(ResourceClassNotSupportedException::class); - - $secondDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $secondDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2]); - - $thirdDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $thirdDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy]); - - $chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]); - - $this->assertEquals([$dummy, $dummy2], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')); - } - - /** - * @group legacy - * @expectedDeprecation Throwing a "ApiPlatform\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface" - */ - public function testLegacyGetCollectionExceptions() - { - $firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $firstDataProvider->getSubresource('notfound', ['id' => 1], [], 'get')->willThrow(ResourceClassNotSupportedException::class); - - $chainItemDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal()]); - - $this->assertEquals('', $chainItemDataProvider->getSubresource('notfound', ['id' => 1], [], 'get')); - } -} diff --git a/tests/Core/EventListener/ReadListenerTest.php b/tests/Core/EventListener/ReadListenerTest.php deleted file mode 100644 index 08b9596545f..00000000000 --- a/tests/Core/EventListener/ReadListenerTest.php +++ /dev/null @@ -1,409 +0,0 @@ - - * - * 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\EventListener; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\EventListener\ReadListener; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidIdentifierException; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class ReadListenerTest extends TestCase -{ - use ProphecyTrait; - - public function testNotAnApiPlatformRequest() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn(new Request())->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - /** - * @group legacy - */ - public function testLegacyConstructor() - { - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn(new Request())->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testDoNotReadWhenReceiveFlagIsFalse() - { - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection(Argument::cetera())->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem(Argument::cetera())->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource(Argument::cetera())->shouldNotBeCalled(); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $request = new Request([], [], ['id' => 1, 'data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'put', '_api_receive' => false]); - $request->setMethod('PUT'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testDoNotReadWhenDisabledInOperationAttribute() - { - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection(Argument::cetera())->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem(Argument::cetera())->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource(Argument::cetera())->shouldNotBeCalled(); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [ - 'put' => [ - 'read' => false, - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); - - $request = new Request([], [], ['id' => 1, 'data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'put']); - $request->setMethod('PUT'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveCollectionPost() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_format' => 'json', '_api_mime_type' => 'application/json'], [], [], [], '{}'); - $request->setMethod('POST'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $this->assertFalse($request->attributes->has('data')); - $this->assertFalse($request->attributes->has('previous_data')); - } - - public function testRetrieveCollectionGet() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection('Foo', 'get', ['filters' => ['foo' => 'bar']])->willReturn([])->shouldBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json'], [], [], ['QUERY_STRING' => 'foo=bar']); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $this->assertSame([], $request->attributes->get('data')); - $this->assertFalse($request->attributes->has('previous_data')); - } - - public function testRetrieveItem() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $data = new \stdClass(); - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem('Foo', ['id' => '1'], 'get', [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->willReturn($data)->shouldBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $this->assertSame($data, $request->attributes->get('data')); - $this->assertEquals($data, $request->attributes->get('previous_data')); - } - - public function testRetrieveItemNoIdentifier() - { - $this->expectException(NotFoundHttpException::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal()); - $listener->onKernelRequest($event->reveal()); - - $request->attributes->get('data'); - } - - public function testRetrieveSubresource() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $data = [new \stdClass()]; - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource('Foo', ['id' => ['id' => '1']], ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar', IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true], 'get')->willReturn($data)->shouldBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar']]); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $this->assertSame($data, $request->attributes->get('data')); - $this->assertSame($data, $request->attributes->get('previous_data')); - } - - public function testRetrieveSubresourceNoDataProvider() - { - $this->expectException(RuntimeException::class); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willReturn(['id' => '1']); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar']]); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), null, null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - - $request->attributes->get('data'); - } - - public function testRetrieveSubresourceNotFound() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->willThrow(new InvalidIdentifierException())->shouldBeCalled(); - $this->expectException(NotFoundHttpException::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar']]); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $this->prophesize(SubresourceDataProviderInterface::class)->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveItemNotFound() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '22'], 'Foo')->shouldBeCalled()->willReturn(['id' => 22]); - $this->expectException(NotFoundHttpException::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem('Foo', ['id' => 22], 'get', [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->willReturn(null)->shouldBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - - $request = new Request([], [], ['id' => '22', '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveBadItemNormalizedIdentifiers() - { - $this->expectException(NotFoundHttpException::class); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['id' => '1'], 'Foo')->shouldBeCalled()->willThrow(new InvalidIdentifierException()); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $request->setMethod(Request::METHOD_GET); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveBadSubresourceNormalizedIdentifiers() - { - $this->expectException(NotFoundHttpException::class); - - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(Argument::type('array'), Argument::type('string'))->shouldBeCalled()->willThrow(new InvalidIdentifierException()); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - $collectionDataProvider->getCollection()->shouldNotBeCalled(); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem()->shouldNotBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - - $request = new Request([], [], ['id' => '1', '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true, ['id']]], 'property' => 'bar']]); - $request->setMethod(Request::METHOD_GET); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } - - public function testRetrieveItemWithCompositeIdentifiersCallsIdentifierConverter() - { - $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); - $identifierConverter->convert(['foo' => '22', 'bar' => 'test'], 'DummyWithCompositeIdentifier')->shouldBeCalled()->willReturn(['foo' => 22, 'bar' => 'test']); - $this->expectException(NotFoundHttpException::class); - - $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); - - $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProvider->getItem('DummyWithCompositeIdentifier', ['foo' => 22, 'bar' => 'test'], 'get', [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true])->willReturn(null)->shouldBeCalled(); - - $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); - - $request = new Request([], [], ['id' => 'foo=22;bar=test', '_api_resource_class' => 'DummyWithCompositeIdentifier', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_identifiers' => ['foo', 'bar'], '_api_has_composite_identifier' => true]); - $request->setMethod('GET'); - - $event = $this->prophesize(RequestEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); - } -} diff --git a/tests/Core/EventListener/WriteListenerTest.php b/tests/Core/EventListener/WriteListenerTest.php deleted file mode 100644 index 94743b941a8..00000000000 --- a/tests/Core/EventListener/WriteListenerTest.php +++ /dev/null @@ -1,400 +0,0 @@ - - * - * 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\EventListener; - -use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\EventListener\WriteListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ConcreteDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * @author Baptiste Meyer - * @group legacy - */ -class WriteListenerTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function testOnKernelViewWithControllerResultAndPersist() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummy/1')->shouldBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class]); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { - $request->setMethod($httpMethod); - $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - $this->assertSame($dummy, $event->getControllerResult()); - $this->assertEquals('/dummy/1', $request->attributes->get('_api_write_item_iri')); - } - } - - /** - * @group legacy - * @expectedDeprecation Not returning an object from ApiPlatform\Core\DataPersister\DataPersisterInterface::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3. - */ - public function testOnKernelViewWithControllerResultAndPersistReturningVoid() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummy/1'); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class]); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { - $request->setMethod($httpMethod); - $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - $this->assertSame($dummy, $event->getControllerResult()); - } - } - - /** - * @see https://github.com/api-platform/core/issues/1799 - * @see https://github.com/api-platform/core/issues/2692 - */ - public function testOnKernelViewWithControllerResultAndPersistWithImmutableResource() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dummy2 = new Dummy(); - $dummy2->setId(2); - $dummy2->setName('Dummyferoce'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy2); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy2)->willReturn('/dummy/2'); - - $writeListener = new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class]); - - foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $request->setMethod($httpMethod); - $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - - $writeListener->onKernelView($event); - - $this->assertSame($dummy2, $event->getControllerResult()); - $this->assertEquals('/dummy/2', $request->attributes->get('_api_write_item_iri')); - } - } - - public function testOnKernelViewDoNotCallIriConverterWhenOutputClassDisabled() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['output' => ['class' => null]])); - - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()))->onKernelView($event); - } - - public function testOnKernelViewWithControllerResultAndRemove() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $dataPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'delete']); - $request->setMethod('DELETE'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - } - - public function testOnKernelViewWithSafeMethod() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'head']); - $request->setMethod('HEAD'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal()))->onKernelView($event); - } - - public function testDoNotWriteWhenControllerResultIsResponse() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->persist(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->remove(Argument::cetera())->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $request = new Request(); - - $response = new Response(); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $response - ); - - $listener = new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()); - $listener->onKernelView($event); - } - - public function testDoNotWriteWhenPersistFlagIsFalse() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->persist(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->remove(Argument::cetera())->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $request = new Request([], [], ['data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post', '_api_persist' => false]); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $listener = new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()); - $listener->onKernelView($event); - } - - public function testDoNotWriteWhenDisabledInOperationAttribute() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->persist(Argument::cetera())->shouldNotBeCalled(); - $dataPersisterProphecy->remove(Argument::cetera())->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ - 'post' => [ - 'write' => false, - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); - - $request = new Request([], [], ['data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $listener = new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelView($event); - } - - public function testOnKernelViewWithNoResourceClass() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $request = new Request(); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - } - - public function testOnKernelViewWithParentResourceClass() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new ConcreteDummy(); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->willReturn($dummy)->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummy/1')->shouldBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => ConcreteDummy::class, '_api_item_operation_name' => 'put', '_api_persist' => true]); - $request->setMethod('PUT'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - } - - public function testOnKernelViewWithNoDataPersisterSupport() - { - $this->expectDeprecation('Since api-platform/core 2.7: The listener "ApiPlatform\Core\EventListener\WriteListener" is deprecated and will be removed in 3.0, use "ApiPlatform\Symfony\EventListener\WriteListener" instead'); - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); - $dataPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled(); - $dataPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled(); - $dataPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResource($dummy)->shouldNotBeCalled(); - - $request = new Request([], [], ['_api_resource_class' => 'Dummy', '_api_collection_operation_name' => 'post']); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - } -} diff --git a/tests/Core/Identifier/CompositeIdentifierParserTest.php b/tests/Core/Identifier/CompositeIdentifierParserTest.php deleted file mode 100644 index 79e87b99e0d..00000000000 --- a/tests/Core/Identifier/CompositeIdentifierParserTest.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * 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\Identifier; - -use ApiPlatform\Core\Identifier\CompositeIdentifierParser; -use PHPUnit\Framework\TestCase; - -class CompositeIdentifierParserTest extends TestCase -{ - /** - * @dataProvider variousIdentifiers - */ - public function testNormalizeCompositeCorrectly(array $identifiers) - { - foreach ($identifiers as $string => $expected) { - $this->assertEquals(CompositeIdentifierParser::parse($string), $expected); - } - } - - public function variousIdentifiers(): array - { - return [[[ - 'a=bd;dc=d' => ['a' => 'bd', 'dc' => 'd'], - 'a=b;c=d foo;d23i=e' => ['a' => 'b', 'c' => 'd foo', 'd23i' => 'e'], - 'a=1;c=2;d=10-30-24' => ['a' => '1', 'c' => '2', 'd' => '10-30-24'], - 'a=test;b=bar;foo;c=123' => ['a' => 'test', 'b' => 'bar;foo', 'c' => '123'], - 'a=test;b=bar ;foo;c=123;459;barz=123asgfjasdg4;' => ['a' => 'test', 'b' => 'bar ;foo', 'c' => '123;459', 'barz' => '123asgfjasdg4'], - 'foo=test=bar;;bar=bazzz;' => ['foo' => 'test=bar;', 'bar' => 'bazzz'], - 'foo=test=bar;bar=;test=foo' => ['foo' => 'test=bar', 'bar' => '', 'test' => 'foo'], - 'foo=test=bar;bar=' => ['foo' => 'test=bar', 'bar' => ''], - ]]]; - } - - /** - * @dataProvider compositeIdentifiers - */ - public function testStringify(array $identifiers) - { - foreach ($identifiers as $string => $arr) { - $this->assertEquals(CompositeIdentifierParser::stringify($arr), $string); - } - } - - public function compositeIdentifiers(): array - { - return [[[ - 'a=bd;dc=d' => ['a' => 'bd', 'dc' => 'd'], - 'a=b;c=d foo;d23i=e' => ['a' => 'b', 'c' => 'd foo', 'd23i' => 'e'], - 'a=1;c=2;d=10-30-24' => ['a' => '1', 'c' => '2', 'd' => '10-30-24'], - 'a=test;b=bar;foo;c=123' => ['a' => 'test', 'b' => 'bar;foo', 'c' => '123'], - 'foo=test=bar;;bar=bazzz' => ['foo' => 'test=bar;', 'bar' => 'bazzz'], - 'foo=test=bar;bar=;test=foo' => ['foo' => 'test=bar', 'bar' => '', 'test' => 'foo'], - 'foo=test=bar;bar=' => ['foo' => 'test=bar', 'bar' => ''], - ]]]; - } -} diff --git a/tests/Core/Identifier/IdentifierConverterTest.php b/tests/Core/Identifier/IdentifierConverterTest.php deleted file mode 100644 index c2a39234f6d..00000000000 --- a/tests/Core/Identifier/IdentifierConverterTest.php +++ /dev/null @@ -1,147 +0,0 @@ - - * - * 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\Identifier; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Identifier\IdentifierConverter; -use ApiPlatform\Core\Identifier\Normalizer\DateTimeIdentifierDenormalizer; -use ApiPlatform\Core\Identifier\Normalizer\IntegerDenormalizer; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; - -/** - * @author Antoine Bluchet - */ -class IdentifierConverterTest extends TestCase -{ - use ProphecyTrait; - - public function testCompositeIdentifier() - { - $identifiers = [ - 'a' => '1', - 'c' => '2', - 'd' => '2015-04-05', - ]; - - $class = 'Dummy'; - - $integerPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT)); - $identifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true); - $dateIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTime::class)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create($class, 'a')->shouldBeCalled()->willReturn($integerPropertyMetadata); - $propertyMetadataFactory->create($class, 'c')->shouldBeCalled()->willReturn($identifierPropertyMetadata); - $propertyMetadataFactory->create($class, 'd')->shouldBeCalled()->willReturn($dateIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass($class)->willReturn(['a', 'c', 'd']); - - $identifierDenormalizers = [new IntegerDenormalizer(), new DateTimeIdentifierDenormalizer()]; - - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $result = $identifierDenormalizer->convert($identifiers, $class); - $this->assertEquals(['a' => 1, 'c' => '2', 'd' => new \DateTime('2015-04-05')], $result); - $this->assertSame(1, $result['a']); - } - - public function testSingleDateIdentifier() - { - $identifier = ['funkyid' => '2015-04-05']; - $class = 'Dummy'; - - $dateIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTime::class)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create($class, 'funkyid')->shouldBeCalled()->willReturn($dateIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass($class)->willReturn(['funkyid']); - - $identifierDenormalizers = [new DateTimeIdentifierDenormalizer()]; - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $this->assertEquals($identifierDenormalizer->convert($identifier, $class), ['funkyid' => new \DateTime('2015-04-05')]); - } - - public function testIntegerIdentifier() - { - $identifier = ['id' => '42']; - $class = 'Dummy'; - - $integerIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create($class, 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass($class)->willReturn(['id']); - - $identifierDenormalizers = [new IntegerDenormalizer()]; - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $this->assertSame(['id' => 42], $identifierDenormalizer->convert($identifier, $class)); - } - - public function testShouldBreakAfterTransforming() - { - $identifier = ['id' => '42']; - $class = 'Dummy'; - - $integerIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create($class, 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass($class)->willReturn(['id']); - - $shouldNotBeCalled = $this->prophesize(DenormalizerInterface::class); - $shouldNotBeCalled->supportsDenormalization()->shouldNotBeCalled(); - - $identifierDenormalizers = [new IntegerDenormalizer(), $shouldNotBeCalled->reveal()]; - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $this->assertSame(['id' => 42], $identifierDenormalizer->convert($identifier, $class)); - } - - public function testWithContextAndMultipleIdentifiers() - { - $identifier = ['id' => '42', 'book' => '21']; - - $integerIdentifierPropertyMetadata = (new PropertyMetadata())->withIdentifier(true)->withType(new Type(Type::BUILTIN_TYPE_INT)); - - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create('Author', 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata); - $propertyMetadataFactory->create('Book', 'id')->shouldBeCalled()->willReturn($integerIdentifierPropertyMetadata); - - $identifiersExtractor = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractor->getIdentifiersFromResourceClass('Book')->willReturn(['id']); - $identifiersExtractor->getIdentifiersFromResourceClass('Author')->willReturn(['id']); - - $shouldNotBeCalled = $this->prophesize(DenormalizerInterface::class); - $shouldNotBeCalled->supportsDenormalization()->shouldNotBeCalled(); - - $identifierDenormalizers = [new IntegerDenormalizer(), $shouldNotBeCalled->reveal()]; - $identifierDenormalizer = new IdentifierConverter($identifiersExtractor->reveal(), $propertyMetadataFactory->reveal(), $identifierDenormalizers); - - $this->assertSame(['id' => 42, 'book' => 21], $identifierDenormalizer->convert($identifier, 'Book', ['identifiers' => ['id' => ['Author', 'id'], 'book' => ['Book', 'id']]])); - } -} diff --git a/tests/Core/Identifier/Normalizer/DateTimeIdentifierNormalizerTest.php b/tests/Core/Identifier/Normalizer/DateTimeIdentifierNormalizerTest.php deleted file mode 100644 index ccd386d93ad..00000000000 --- a/tests/Core/Identifier/Normalizer/DateTimeIdentifierNormalizerTest.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * 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\Identifier\Normalizer; - -use ApiPlatform\Core\Identifier\Normalizer\DateTimeIdentifierDenormalizer; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class DateTimeIdentifierNormalizerTest extends TestCase -{ - public function testDenormalize() - { - $this->expectException(\ApiPlatform\Exception\InvalidIdentifierException::class); - - $normalizer = new DateTimeIdentifierDenormalizer(); - $normalizer->denormalize('not valid', \DateTimeImmutable::class); - } - - public function testHasCacheableSupportsMethod() - { - $this->assertTrue((new DateTimeIdentifierDenormalizer())->hasCacheableSupportsMethod()); - } -} diff --git a/tests/Core/Identifier/Normalizer/IntegerDenormalizerTest.php b/tests/Core/Identifier/Normalizer/IntegerDenormalizerTest.php deleted file mode 100644 index a900c24f7ca..00000000000 --- a/tests/Core/Identifier/Normalizer/IntegerDenormalizerTest.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * 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\Identifier\Normalizer; - -use ApiPlatform\Core\Identifier\Normalizer\IntegerDenormalizer; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class IntegerDenormalizerTest extends TestCase -{ - public function testDenormalize() - { - $this->assertSame(2, (new IntegerDenormalizer())->denormalize('2', 'int')); - } - - public function testSupportsDenormalization() - { - $normalizer = new IntegerDenormalizer(); - $this->assertTrue($normalizer->supportsDenormalization('1', 'int')); - $this->assertFalse($normalizer->supportsDenormalization([], 'int')); - $this->assertFalse($normalizer->supportsDenormalization('1', 'foo')); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } -} diff --git a/tests/Core/Metadata/Extractor/ExtractorTestCase.php b/tests/Core/Metadata/Extractor/ExtractorTestCase.php deleted file mode 100644 index 61d95c152cd..00000000000 --- a/tests/Core/Metadata/Extractor/ExtractorTestCase.php +++ /dev/null @@ -1,614 +0,0 @@ - - * - * 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\Metadata\Extractor; - -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Extractor\ResourceExtractorInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; - -/** - * @author Théo Fidry - */ -abstract class ExtractorTestCase extends TestCase -{ - use ProphecyTrait; - - protected $extractorClass; - - final public function testEmptyResources() - { - $resources = $this->createExtractor([$this->getEmptyResourcesFile()])->getResources(); - - $this->assertEmpty($resources); - } - - final public function testEmptyOperation() - { - $resources = $this->createExtractor([$this->getEmptyOperationFile()])->getResources(); - - $this->assertSame(['filters' => ['greeting.search_filter']], $resources['App\Entity\Greeting']['collectionOperations']['get']); - // There is a difference between XML & YAML here for example, one will parse `null` or the lack of value as `null` - // whilst the other will parse it as an empty array. Since it doesn't affect the processing of those values, there is no - // real need to fix this. - $this->assertEmpty($resources['App\Entity\Greeting']['collectionOperations']['post']); - $this->assertEmpty($resources['App\Entity\Greeting']['itemOperations']['get']); - $this->assertEmpty($resources['App\Entity\Greeting']['itemOperations']['put']); - } - - final public function testCorrectResources() - { - $resources = $this->createExtractor([$this->getCorrectResourceFile()])->getResources(); - - $this->assertSame([ - Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => null, - ], - FileConfigDummy::class => [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'iri' => 'someirischema', - 'itemOperations' => [ - 'my_op_name' => [ - 'method' => 'GET', - ], - 'my_other_op_name' => [ - 'method' => 'POST', - ], - ], - 'collectionOperations' => [ - 'my_collection_op' => [ - 'method' => 'POST', - 'path' => 'the/collection/path', - ], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => [ - 'path' => 'the/subresource/path', - ], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - 'groups' => [ - 'graphql', - ], - ], - ], - ], - 'attributes' => [ - 'normalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'denormalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - 'stateless' => true, - ], - 'properties' => [ - 'foo' => [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => null, - 'iri' => null, - 'attributes' => [ - 'foo' => [ - 'Foo', - ], - 'bar' => [ - [ - 'Bar', - ], - 'baz' => 'Baz', - ], - 'baz' => 'Baz', - ], - 'subresource' => [ - 'collection' => true, - 'resourceClass' => 'Foo', - 'maxDepth' => 1, - ], - ], - 'name' => [ - 'description' => 'The dummy name', - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => null, - ], - ], - ], - ], $resources); - } - - final public function testResourcesParametersResolution() - { - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->get('dummy_class')->willReturn(Dummy::class); - $containerProphecy->get('dummy_related_owned_class')->willReturn(RelatedOwnedDummy::class); - $containerProphecy->get('file_config_dummy_class')->willReturn(FileConfigDummy::class); - - $resources = $this->createExtractor([$this->getResourceWithParametersFile()], $containerProphecy->reveal())->getResources(); - - $this->assertSame([ - Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => [ - 'relatedOwnedDummy' => [ - 'description' => null, - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => [ - 'collection' => null, - 'resourceClass' => RelatedOwnedDummy::class, - 'maxDepth' => null, - ], - ], - ], - ], - 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyBis' => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => null, - ], - FileConfigDummy::class => [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'iri' => 'someirischema', - 'itemOperations' => [ - 'my_op_name' => [ - 'method' => 'GET', - ], - 'my_other_op_name' => [ - 'method' => 'POST', - ], - ], - 'collectionOperations' => [ - 'my_collection_op' => [ - 'method' => 'POST', - 'path' => 'the/collection/path', - ], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => [ - 'path' => 'the/subresource/path', - ], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - 'groups' => [ - 'graphql', - ], - ], - ], - ], - 'attributes' => [ - 'normalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'denormalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - ], - 'properties' => [ - 'foo' => [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => null, - 'iri' => null, - 'attributes' => [ - 'foo' => [ - 'Foo', - ], - 'bar' => [ - [ - 'Bar', - ], - 'baz' => 'Baz', - ], - 'baz' => 'Baz', - 'const' => 0, - ], - 'subresource' => [ - 'collection' => true, - 'resourceClass' => 'Foo', - 'maxDepth' => 1, - ], - ], - 'name' => [ - 'description' => 'The dummy name', - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => null, - ], - ], - ], - ], $resources); - - $containerProphecy->get(Argument::cetera())->shouldHaveBeenCalledTimes(3); - } - - final public function testResourcesParametersResolutionWithTheSymfonyContainer() - { - $containerProphecy = $this->prophesize(SymfonyContainerInterface::class); - $containerProphecy->getParameter('dummy_class')->willReturn(Dummy::class); - $containerProphecy->getParameter('dummy_related_owned_class')->willReturn(RelatedOwnedDummy::class); - $containerProphecy->getParameter('file_config_dummy_class')->willReturn(FileConfigDummy::class); - - $resources = $this->createExtractor([$this->getResourceWithParametersFile()], $containerProphecy->reveal())->getResources(); - - $this->assertSame([ - Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => [ - 'relatedOwnedDummy' => [ - 'description' => null, - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => [ - 'collection' => null, - 'resourceClass' => RelatedOwnedDummy::class, - 'maxDepth' => null, - ], - ], - ], - ], - 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyBis' => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => null, - ], - FileConfigDummy::class => [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'iri' => 'someirischema', - 'itemOperations' => [ - 'my_op_name' => [ - 'method' => 'GET', - ], - 'my_other_op_name' => [ - 'method' => 'POST', - ], - ], - 'collectionOperations' => [ - 'my_collection_op' => [ - 'method' => 'POST', - 'path' => 'the/collection/path', - ], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => [ - 'path' => 'the/subresource/path', - ], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - 'groups' => [ - 'graphql', - ], - ], - ], - ], - 'attributes' => [ - 'normalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'denormalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - ], - 'properties' => [ - 'foo' => [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => null, - 'iri' => null, - 'attributes' => [ - 'foo' => [ - 'Foo', - ], - 'bar' => [ - [ - 'Bar', - ], - 'baz' => 'Baz', - ], - 'baz' => 'Baz', - 'const' => 0, - ], - 'subresource' => [ - 'collection' => true, - 'resourceClass' => 'Foo', - 'maxDepth' => 1, - ], - ], - 'name' => [ - 'description' => 'The dummy name', - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => null, - ], - ], - ], - ], $resources); - - $containerProphecy->getParameter(Argument::cetera())->shouldHaveBeenCalledTimes(3); - } - - final public function testResourcesParametersResolutionWithoutAContainer() - { - $resources = $this->createExtractor([$this->getResourceWithParametersFile()])->getResources(); - - $this->assertSame([ - '%dummy_class%' => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => [ - 'relatedOwnedDummy' => [ - 'description' => null, - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => [ - 'collection' => null, - 'resourceClass' => '%dummy_related_owned_class%', - 'maxDepth' => null, - ], - ], - ], - ], - '%dummy_class%Bis' => [ - 'shortName' => null, - 'description' => null, - 'iri' => null, - 'itemOperations' => null, - 'collectionOperations' => null, - 'subresourceOperations' => null, - 'graphql' => null, - 'attributes' => null, - 'properties' => null, - ], - '%file_config_dummy_class%' => [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'iri' => 'someirischema', - 'itemOperations' => [ - 'my_op_name' => [ - 'method' => 'GET', - ], - 'my_other_op_name' => [ - 'method' => 'POST', - ], - ], - 'collectionOperations' => [ - 'my_collection_op' => [ - 'method' => 'POST', - 'path' => 'the/collection/path', - ], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => [ - 'path' => 'the/subresource/path', - ], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - 'groups' => [ - 'graphql', - ], - ], - ], - ], - 'attributes' => [ - 'normalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'denormalization_context' => [ - 'groups' => [ - 'default', - ], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - ], - 'properties' => [ - 'foo' => [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => null, - 'iri' => null, - 'attributes' => [ - 'foo' => [ - 'Foo', - ], - 'bar' => [ - [ - 'Bar', - ], - 'baz' => 'Baz', - ], - 'baz' => 'Baz', - 'const' => 0, - ], - 'subresource' => [ - 'collection' => true, - 'resourceClass' => 'Foo', - 'maxDepth' => 1, - ], - ], - 'name' => [ - 'description' => 'The dummy name', - 'readable' => null, - 'writable' => null, - 'readableLink' => null, - 'writableLink' => null, - 'required' => null, - 'identifier' => null, - 'iri' => null, - 'attributes' => [], - 'subresource' => null, - ], - ], - ], - ], $resources); - } - - /** - * @param string[] $paths - */ - final protected function createExtractor(array $paths, ContainerInterface $container = null): ResourceExtractorInterface - { - $extractorClass = $this->getExtractorClass(); - - $this->assertTrue(is_a($extractorClass, ResourceExtractorInterface::class, true)); - - return new $extractorClass($paths, $container); - } - - abstract protected function getExtractorClass(): string; - - abstract protected function getEmptyResourcesFile(): string; - - abstract protected function getEmptyOperationFile(): string; - - abstract protected function getCorrectResourceFile(): string; - - abstract protected function getResourceWithParametersFile(): string; -} diff --git a/tests/Core/Metadata/Extractor/XmlExtractorTest.php b/tests/Core/Metadata/Extractor/XmlExtractorTest.php deleted file mode 100644 index cfa45257756..00000000000 --- a/tests/Core/Metadata/Extractor/XmlExtractorTest.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * 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\Metadata\Extractor; - -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; - -/** - * @author Kévin Dunglas - * @author Théo Fidry - */ -class XmlExtractorTest extends ExtractorTestCase -{ - /** - * {@inheritdoc} - */ - protected function getExtractorClass(): string - { - return XmlExtractor::class; - } - - /** - * {@inheritdoc} - */ - protected function getEmptyResourcesFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources_empty.xml'; - } - - /** - * {@inheritdoc} - */ - protected function getEmptyOperationFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/empty-operation.xml'; - } - - /** - * {@inheritdoc} - */ - protected function getCorrectResourceFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources.xml'; - } - - /** - * {@inheritdoc} - */ - protected function getResourceWithParametersFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources_with_parameters.xml'; - } -} diff --git a/tests/Core/Metadata/Extractor/YamlExtractorTest.php b/tests/Core/Metadata/Extractor/YamlExtractorTest.php deleted file mode 100644 index a949062dbe6..00000000000 --- a/tests/Core/Metadata/Extractor/YamlExtractorTest.php +++ /dev/null @@ -1,121 +0,0 @@ - - * - * 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\Metadata\Extractor; - -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Exception\InvalidArgumentException; -use Generator; - -/** - * @author Kévin Dunglas - * @author Théo Fidry - */ -class YamlExtractorTest extends ExtractorTestCase -{ - public function testInvalidProperty() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The property "shortName" must be a "string", "integer" given.'); - - (new YamlExtractor([__DIR__.'/../../../Fixtures/FileConfigurations/badpropertytype.yml']))->getResources(); - } - - public function testParseException() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/Unable to parse in ".+\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/parse_exception.yml"/'); - - (new YamlExtractor([__DIR__.'/../../../Fixtures/FileConfigurations/parse_exception.yml']))->getResources(); - } - - /** - * @dataProvider provideInvalidResources - */ - public function testInvalidResources(string $path, string $exceptionRegex) - { - try { - (new YamlExtractor([$path]))->getResources(); - - $this->fail('Expected exception to be thrown.'); - } catch (\InvalidArgumentException $exception) { - $this->assertMatchesRegularExpression( - $exceptionRegex, - $exception->getMessage() - ); - } - } - - public function provideInvalidResources(): Generator - { - yield [ - __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid.yml', - '/^"resources" setting is expected to be null or an array, string given in ".*resourcesinvalid\.yml"\.$/', - ]; - - yield [ - __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid_2.yml', - '/^"Foo" setting is expected to be null or an array, string given in ".*resourcesinvalid_2\.yml"\.$/', - ]; - - yield [ - __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid_3.yml', - '/^"properties" setting is expected to be null or an array, string given in ".*resourcesinvalid_3\.yml"\.$/', - ]; - - yield [ - __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid_4.yml', - '/^"myprop" setting is expected to be null or an array, string given in ".*resourcesinvalid_4\.yml"\.$/', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExtractorClass(): string - { - return YamlExtractor::class; - } - - /** - * {@inheritdoc} - */ - protected function getEmptyResourcesFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources_empty.yml'; - } - - /** - * {@inheritdoc} - */ - protected function getEmptyOperationFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/empty-operation.yml'; - } - - /** - * {@inheritdoc} - */ - protected function getCorrectResourceFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources.yml'; - } - - /** - * {@inheritdoc} - */ - protected function getResourceWithParametersFile(): string - { - return __DIR__.'/../../../Fixtures/FileConfigurations/resources_with_parameters.yml'; - } -} diff --git a/tests/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactoryTest.php deleted file mode 100644 index 680426ce8f5..00000000000 --- a/tests/Core/Metadata/Property/Factory/AnnotationPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,163 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\AnnotationPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Kévin Dunglas - */ -class AnnotationPropertyMetadataFactoryTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - /** - * @dataProvider dependenciesProvider - * - * @param mixed $reader - * @param mixed $decorated - * @group legacy - */ - public function testCreateProperty($reader, $decorated, string $description) - { - $factory = new AnnotationPropertyMetadataFactory($reader->reveal(), $decorated ? $decorated->reveal() : null); - $metadata = $factory->create(Dummy::class, 'name'); - - $this->assertEquals($description, $metadata->getDescription()); - $this->assertTrue($metadata->isReadable()); - $this->assertTrue($metadata->isWritable()); - $this->assertFalse($metadata->isReadableLink()); - $this->assertFalse($metadata->isWritableLink()); - $this->assertFalse($metadata->isIdentifier()); - $this->assertTrue($metadata->isRequired()); - $this->assertEquals('foo', $metadata->getIri()); - $this->assertEquals(['foo' => 'bar'], $metadata->getAttributes()); - } - - /** - * @requires PHP 8.0 - * @group legacy - */ - public function testCreateAttribute() - { - $this->expectDeprecation('Since api-platform/core 2.7: Decorating the legacy ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface is deprecated, use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface instead.'); - $factory = new AnnotationPropertyMetadataFactory(); - - $metadata = $factory->create(DummyPhp8::class, 'id'); - $this->assertTrue($metadata->isIdentifier()); - $this->assertSame('the identifier', $metadata->getDescription()); - - $metadata = $factory->create(DummyPhp8::class, 'foo'); - $this->assertSame('a foo', $metadata->getDescription()); - } - - public function dependenciesProvider(): array - { - $annotation = new ApiProperty(); - $annotation->description = 'description'; - $annotation->readable = true; - $annotation->writable = true; - $annotation->readableLink = false; - $annotation->writableLink = false; - $annotation->identifier = false; - $annotation->required = true; - $annotation->iri = 'foo'; - $annotation->attributes = ['foo' => 'bar']; - - $propertyReaderProphecy = $this->prophesize(Reader::class); - $propertyReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn($annotation)->shouldBeCalled(); - - $getterReaderProphecy = $this->prophesize(Reader::class); - $getterReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $getterReaderProphecy->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn($annotation)->shouldBeCalled(); - - $setterReaderProphecy = $this->prophesize(Reader::class); - $setterReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $setterReaderProphecy->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $setterReaderProphecy->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn($annotation)->shouldBeCalled(); - - $decoratedThrowNotFoundProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedThrowNotFoundProphecy->create(Dummy::class, 'name', [])->willThrow(new PropertyNotFoundException())->shouldBeCalled(); - - $decoratedReturnProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedReturnProphecy->create(Dummy::class, 'name', [])->willReturn(new PropertyMetadata(null, 'Hi'))->shouldBeCalled(); - - return [ - [$propertyReaderProphecy, null, 'description'], - [$getterReaderProphecy, $decoratedThrowNotFoundProphecy, 'description'], - [$setterReaderProphecy, $decoratedThrowNotFoundProphecy, 'description'], - [$setterReaderProphecy, $decoratedReturnProphecy, 'description'], - ]; - } - - /** - * @group legacy - */ - public function testClassNotFound() - { - $this->expectDeprecation('Since api-platform/core 2.7: Decorating the legacy ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface is deprecated, use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface instead.'); - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "foo" of class "\\DoNotExist" not found.'); - - $factory = new AnnotationPropertyMetadataFactory($this->prophesize(Reader::class)->reveal()); - $factory->create('\DoNotExist', 'foo'); - } - - /** - * @group legacy - */ - public function testClassNotFoundButParentFound() - { - $this->expectDeprecation('Since api-platform/core 2.7: Decorating the legacy ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface is deprecated, use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface instead.'); - $propertyMetadata = new PropertyMetadata(); - - $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedProphecy->create('\DoNotExist', 'foo', [])->willReturn($propertyMetadata); - - $factory = new AnnotationPropertyMetadataFactory($this->prophesize(Reader::class)->reveal(), $decoratedProphecy->reveal()); - $this->assertEquals($propertyMetadata, $factory->create('\DoNotExist', 'foo')); - } - - public function testSkipDeprecation() - { - $annotation = new ApiProperty(); - $annotation->description = 'description'; - $annotation->readable = true; - $annotation->writable = true; - $annotation->readableLink = false; - $annotation->writableLink = false; - $annotation->identifier = false; - $annotation->required = true; - $annotation->iri = 'foo'; - $annotation->attributes = ['foo' => 'bar']; - - $propertyReaderProphecy = $this->prophesize(Reader::class); - $propertyReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn($annotation)->shouldBeCalled(); - - $factory = new AnnotationPropertyMetadataFactory($propertyReaderProphecy->reveal()); - $metadata = $factory->create(Dummy::class, 'name', ['deprecate' => false]); - } -} diff --git a/tests/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactoryTest.php b/tests/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactoryTest.php deleted file mode 100644 index 9b284d864c4..00000000000 --- a/tests/Core/Metadata/Property/Factory/AnnotationPropertyNameCollectionFactoryTest.php +++ /dev/null @@ -1,126 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Metadata\Property\Factory\AnnotationPropertyNameCollectionFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\UpperCaseIdentifierDummy; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class AnnotationPropertyNameCollectionFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider dependenciesProvider - * - * @param mixed $decorated - */ - public function testCreate($decorated, array $results) - { - $reader = $this->prophesize(Reader::class); - $reader->getPropertyAnnotation(new \ReflectionProperty(Dummy::class, 'name'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(Dummy::class, 'getName'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(Dummy::class, 'getAlias'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(Dummy::class, 'staticMethod'), ApiProperty::class)->shouldNotBeCalled(); - $reader->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - - $factory = new AnnotationPropertyNameCollectionFactory($reader->reveal(), $decorated ? $decorated->reveal() : null); - $metadata = $factory->create(Dummy::class); - - $this->assertEquals($results, iterator_to_array($metadata)); - } - - public function dependenciesProvider(): array - { - $decoratedThrowsNotFound = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $decoratedThrowsNotFound->create(Dummy::class, [])->willThrow(new ResourceClassNotFoundException())->shouldBeCalled(); - - $decoratedReturnParent = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $decoratedReturnParent->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['foo']))->shouldBeCalled(); - - return [ - [null, ['name', 'alias']], - [$decoratedThrowsNotFound, ['name', 'alias']], - [$decoratedReturnParent, ['name', 'alias', 'foo']], - ]; - } - - /** - * @requires PHP 8.0 - */ - public function testCreateAttribute() - { - $factory = new AnnotationPropertyNameCollectionFactory(); - $metadata = $factory->create(DummyPhp8::class); - - $this->assertSame(['id', 'foo'], iterator_to_array($metadata)); - } - - /** - * @dataProvider upperCaseDependenciesProvider - * - * @param mixed $decorated - */ - public function testUpperCaseCreate($decorated, array $results) - { - $reader = $this->prophesize(Reader::class); - $reader->getPropertyAnnotation(new \ReflectionProperty(UpperCaseIdentifierDummy::class, 'name'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getPropertyAnnotation(new \ReflectionProperty(UpperCaseIdentifierDummy::class, 'Uuid'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(UpperCaseIdentifierDummy::class, 'getName'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getMethodAnnotation(new \ReflectionMethod(UpperCaseIdentifierDummy::class, 'getUuid'), ApiProperty::class)->willReturn(new ApiProperty())->shouldBeCalled(); - $reader->getMethodAnnotation(Argument::type(\ReflectionMethod::class), ApiProperty::class)->willReturn(null)->shouldBeCalled(); - - $factory = new AnnotationPropertyNameCollectionFactory($reader->reveal(), $decorated ? $decorated->reveal() : null); - $metadata = $factory->create(UpperCaseIdentifierDummy::class); - - $this->assertEquals($results, iterator_to_array($metadata)); - } - - public function upperCaseDependenciesProvider(): array - { - $decoratedThrowsNotFound = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $decoratedThrowsNotFound->create(UpperCaseIdentifierDummy::class, [])->willThrow(new ResourceClassNotFoundException())->shouldBeCalled(); - - return [ - [null, ['Uuid', 'name']], - [$decoratedThrowsNotFound, ['Uuid', 'name']], - ]; - } - - public function testClassDoesNotExist() - { - $this->expectException(ResourceClassNotFoundException::class); - $this->expectExceptionMessage('The resource class "\\DoNotExist" does not exist.'); - - $reader = $this->prophesize(Reader::class); - - $factory = new AnnotationPropertyNameCollectionFactory($reader->reveal()); - $factory->create('\DoNotExist'); - } -} diff --git a/tests/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactoryTest.php deleted file mode 100644 index 6f6081f1cb2..00000000000 --- a/tests/Core/Metadata/Property/Factory/AnnotationSubresourceMetadataFactoryTest.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Annotation\ApiSubresource; -use ApiPlatform\Core\Metadata\Property\Factory\AnnotationSubresourceMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidResourceException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use Doctrine\Common\Annotations\Reader; -use Doctrine\Common\Collections\ArrayCollection; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\PropertyInfo\Type; - -/** - * @group legacy - */ -class AnnotationSubresourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider dependenciesProvider - * - * @param mixed $reader - * @param mixed $decorated - */ - public function testCreateProperty($reader, $decorated) - { - $factory = new AnnotationSubresourceMetadataFactory($reader->reveal(), $decorated->reveal()); - $metadata = $factory->create(Dummy::class, 'relatedDummies'); - - $this->assertEquals(new SubresourceMetadata(RelatedDummy::class, true, null), $metadata->getSubresource()); - } - - public function dependenciesProvider(): array - { - $annotation = new ApiSubresource(); - - $propertyReaderProphecy = $this->prophesize(Reader::class); - $propertyReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiSubresource::class)->willReturn($annotation)->shouldBeCalled(); - - $relatedDummyType = new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class); - $subresourceType = new Type(Type::BUILTIN_TYPE_OBJECT, false, ArrayCollection::class, true, new Type(Type::BUILTIN_TYPE_INT), $relatedDummyType); - - $decoratedReturnProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedReturnProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new PropertyMetadata())->withType($subresourceType)->withDescription('Several dummies'))->shouldBeCalled(); - - return [ - [$propertyReaderProphecy, $decoratedReturnProphecy], - ]; - } - - public function testCreatePropertyUnknownType() - { - $this->expectException(InvalidResourceException::class); - $this->expectExceptionMessage('Property "relatedDummies" on resource "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\Dummy" is declared as a subresource, but its type could not be determined.'); - - $annotation = new ApiSubresource(); - - $propertyReaderProphecy = $this->prophesize(Reader::class); - $propertyReaderProphecy->getPropertyAnnotation(Argument::type(\ReflectionProperty::class), ApiSubresource::class)->willReturn($annotation)->shouldBeCalled(); - - $decoratedReturnProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decoratedReturnProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new PropertyMetadata())->withDescription('Several dummies'))->shouldBeCalled(); - - $factory = new AnnotationSubresourceMetadataFactory($propertyReaderProphecy->reveal(), $decoratedReturnProphecy->reveal()); - $factory->create(Dummy::class, 'relatedDummies'); - } -} diff --git a/tests/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactoryTest.php deleted file mode 100644 index 4653ed682cb..00000000000 --- a/tests/Core/Metadata/Property/Factory/ExtractorPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,259 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Exception\InvalidArgumentException; -use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\DummyResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use Doctrine\Common\Collections\ArrayCollection; -use Symfony\Component\PropertyInfo\Type; - -/** - * @author Baptiste Meyer - * @group legacy - */ -class ExtractorPropertyMetadataFactoryTest extends FileConfigurationMetadataFactoryProvider -{ - use ProphecyTrait; - - /** - * @dataProvider propertyMetadataProvider - */ - public function testCreateXml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath])); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - /** - * @dataProvider decoratedPropertyMetadataProvider - */ - public function testCreateWithParentPropertyMetadataFactoryXml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - $decorated = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated - ->create(FileConfigDummy::class, 'foo', []) - ->willReturn(new PropertyMetadata(null, null, null, null, true, null, null, false, null, null, ['Foo'], new SubresourceMetadata('Foo', false))) - ->shouldBeCalled(); - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath]), $decorated->reveal()); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - public function testCreateWithNonexistentResourceXml() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "foo" of the resource class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\ThisDoesNotExist" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcenotfound.xml'; - - (new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath])))->create('ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThisDoesNotExist', 'foo'); - } - - public function testCreateWithNonexistentPropertyXml() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "bar" of the resource class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\FileConfigDummy" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - (new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath])))->create(FileConfigDummy::class, 'bar'); - } - - public function testCreateWithInvalidXml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('#.+Element \'\\{https://api-platform.com/schema/metadata\\}foo\': This element is not expected\\..+#'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/propertyinvalid.xml'; - - (new ExtractorPropertyMetadataFactory(new XmlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - /** - * @dataProvider propertyMetadataProvider - */ - public function testCreateYaml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - /** - * @dataProvider decoratedPropertyMetadataProvider - */ - public function testCreateWithParentPropertyMetadataFactoryYaml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $decorated = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated - ->create(FileConfigDummy::class, 'foo', []) - ->willReturn(new PropertyMetadata(null, null, null, null, true, null, null, false, null, null, ['Foo'], new SubresourceMetadata('Foo', false))) - ->shouldBeCalled(); - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - /** - * @dataProvider decoratedPropertyMetadataProvider - */ - public function testCreateWithCollectionTypedParentPropertyMetadataFactoryYaml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $collectionType = new Type(Type::BUILTIN_TYPE_OBJECT, - false, - ArrayCollection::class, - true, - new Type(Type::BUILTIN_TYPE_INT), - new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class) - ); - - $expectedPropertyMetadata = $expectedPropertyMetadata->withType($collectionType); - $expectedPropertyMetadata = $expectedPropertyMetadata->withSubresource(new SubresourceMetadata(RelatedDummy::class, true, 1)); - - $decorated = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated - ->create(FileConfigDummy::class, 'foo', []) - ->willReturn(new PropertyMetadata($collectionType, null, null, null, true, null, null, false, null, null, ['Foo'], null)) - ->shouldBeCalled(); - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - /** - * @dataProvider decoratedPropertyMetadataProvider - */ - public function testCreateWithTypedParentPropertyMetadataFactoryYaml(PropertyMetadata $expectedPropertyMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $type = new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class); - - $expectedPropertyMetadata = $expectedPropertyMetadata->withType($type); - $expectedPropertyMetadata = $expectedPropertyMetadata->withSubresource(new SubresourceMetadata(RelatedDummy::class, false, 1)); - - $decorated = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated - ->create(FileConfigDummy::class, 'foo', []) - ->willReturn(new PropertyMetadata($type, null, null, null, true, null, null, false, null, null, ['Foo'], null)) - ->shouldBeCalled(); - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - $propertyMetadata = $propertyMetadataFactory->create(FileConfigDummy::class, 'foo'); - - $this->assertEquals($expectedPropertyMetadata, $propertyMetadata); - } - - public function testCreateWithNonexistentResourceYaml() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "foo" of the resource class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\ThisDoesNotExist" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcenotfound.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create('ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThisDoesNotExist', 'foo'); - } - - public function testCreateWithNonexistentPropertyYaml() - { - $this->expectException(PropertyNotFoundException::class); - $this->expectExceptionMessage('Property "bar" of the resource class "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\FileConfigDummy" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'bar'); - } - - public function testCreateWithMalformedResourcesSettingYaml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"resources" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/resourcesinvalid\\.yml"\\./'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesinvalid.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - public function testCreateWithMalformedPropertiesSettingYaml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"properties" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/propertiesinvalid\\.yml"\\./'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/propertiesinvalid.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - public function testCreateWithMalformedPropertySettingYaml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"foo" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/propertyinvalid\\.yml"\\./'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/propertyinvalid.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - public function testCreateWithMalformedYaml() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/parse_exception.yml'; - - (new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo'); - } - - public function testItExtractPropertiesFromInterfaceResources() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/interface_resource.yml'; - - $propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])); - $metadataSomething = $propertyMetadataFactory->create(DummyResourceInterface::class, 'something'); - $metadataSomethingElse = $propertyMetadataFactory->create(DummyResourceInterface::class, 'somethingElse'); - - $this->assertInstanceOf(PropertyMetadata::class, $metadataSomething); - $this->assertInstanceOf(PropertyMetadata::class, $metadataSomethingElse); - $this->assertTrue($metadataSomething->isIdentifier()); - $this->assertFalse($metadataSomethingElse->isWritable()); - } -} diff --git a/tests/Core/Metadata/Property/Factory/FileConfigurationMetadataFactoryProvider.php b/tests/Core/Metadata/Property/Factory/FileConfigurationMetadataFactoryProvider.php deleted file mode 100644 index 431d04b8853..00000000000 --- a/tests/Core/Metadata/Property/Factory/FileConfigurationMetadataFactoryProvider.php +++ /dev/null @@ -1,79 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use PHPUnit\Framework\TestCase; - -/** - * Property metadata provider for file configured factories tests. - * - * @author Baptiste Meyer - * @group legacy - */ -abstract class FileConfigurationMetadataFactoryProvider extends TestCase -{ - public function propertyMetadataProvider() - { - $metadata = [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'attributes' => [ - 'foo' => ['Foo'], - 'bar' => [['Bar'], 'baz' => 'Baz'], - 'baz' => 'Baz', - ], - 'subresource' => new SubresourceMetadata('Foo', true, 1), - ]; - - return [[$this->getPropertyMetadata($metadata)]]; - } - - public function decoratedPropertyMetadataProvider() - { - $metadata = [ - 'description' => 'The dummy foo', - 'readable' => true, - 'writable' => true, - 'readableLink' => false, - 'writableLink' => false, - 'required' => true, - 'identifier' => false, - 'attributes' => [ - 'foo' => ['Foo'], - 'bar' => [['Bar'], 'baz' => 'Baz'], - 'baz' => 'Baz', - ], - 'subresource' => new SubresourceMetadata('Foo', false, null), - ]; - - return [[$this->getPropertyMetadata($metadata)]]; - } - - private function getPropertyMetadata(array $metadata): PropertyMetadata - { - $propertyMetadata = new PropertyMetadata(); - - foreach ($metadata as $propertyName => $propertyValue) { - $propertyMetadata = $propertyMetadata->{'with'.ucfirst($propertyName)}($propertyValue); - } - - return $propertyMetadata; - } -} diff --git a/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php deleted file mode 100644 index 84396146240..00000000000 --- a/tests/Core/Metadata/Property/Factory/InheritedPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\Factory\InheritedPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyInfo\Type; - -/** - * @group legacy - */ -class InheritedPropertyMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreate() - { - $resourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactory->create()->willReturn(new ResourceNameCollection([DummyTableInheritance::class, DummyTableInheritanceChild::class]))->shouldBeCalled(); - - $type = new Type(Type::BUILTIN_TYPE_STRING); - $nicknameMetadata = (new PropertyMetadata())->withType($type)->withDescription('nickname')->withReadable(true)->withWritable(true)->withWritableLink(false)->withReadableLink(false)->withRequired(true)->withIdentifier(false)->withIri('http://example.com/foo')->withAttributes(['foo' => 'bar']); - $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactory->create(DummyTableInheritance::class, 'nickname', [])->willReturn($nicknameMetadata)->shouldBeCalled(); - $propertyMetadataFactory->create(DummyTableInheritanceChild::class, 'nickname', [])->willReturn($nicknameMetadata)->shouldBeCalled(); - - $factory = new InheritedPropertyMetadataFactory($resourceNameCollectionFactory->reveal(), $propertyMetadataFactory->reveal()); - $metadata = $factory->create(DummyTableInheritance::class, 'nickname'); - - $this->assertEquals($metadata, $nicknameMetadata->withChildInherited(DummyTableInheritanceChild::class)); - } -} diff --git a/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php b/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php deleted file mode 100644 index a828bf2801b..00000000000 --- a/tests/Core/Metadata/Property/Factory/InheritedPropertyNameCollectionFactoryTest.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\Factory\InheritedPropertyNameCollectionFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class InheritedPropertyNameCollectionFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreateOnParent() - { - $resourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactory->create()->willReturn(new ResourceNameCollection([DummyTableInheritance::class, DummyTableInheritanceChild::class]))->shouldBeCalled(); - - $propertyNameCollectionFactory = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory->create(DummyTableInheritance::class, [])->willReturn(new PropertyNameCollection(['name']))->shouldBeCalled(); - $propertyNameCollectionFactory->create(DummyTableInheritanceChild::class, [])->shouldNotBeCalled(); - - $factory = new InheritedPropertyNameCollectionFactory($resourceNameCollectionFactory->reveal(), $propertyNameCollectionFactory->reveal()); - $metadata = $factory->create(DummyTableInheritance::class); - - $this->assertSame((array) new PropertyNameCollection(['name']), (array) $metadata); - } - - public function testCreateOnChild() - { - $resourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactory->create()->willReturn(new ResourceNameCollection([DummyTableInheritance::class, DummyTableInheritanceChild::class]))->shouldBeCalled(); - - $propertyNameCollectionFactory = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactory->create(DummyTableInheritance::class, [])->willReturn(new PropertyNameCollection(['name']))->shouldBeCalled(); - $propertyNameCollectionFactory->create(DummyTableInheritanceChild::class, [])->willReturn(new PropertyNameCollection(['nickname', '169']))->shouldBeCalled(); - - $factory = new InheritedPropertyNameCollectionFactory($resourceNameCollectionFactory->reveal(), $propertyNameCollectionFactory->reveal()); - $metadata = $factory->create(DummyTableInheritanceChild::class); - - $this->assertSame((array) new PropertyNameCollection(['nickname', '169', 'name']), (array) $metadata); - } -} diff --git a/tests/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php b/tests/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php deleted file mode 100644 index 7ab32e44c47..00000000000 --- a/tests/Core/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php +++ /dev/null @@ -1,187 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Serializer\Mapping\AttributeMetadata as SerializerAttributeMetadata; -use Symfony\Component\Serializer\Mapping\ClassMetadata as SerializerClassMetadata; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface as SerializerClassMetadataFactoryInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * @group legacy - */ -class SerializerPropertyMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); - $serializerClassMetadataFactory = $serializerClassMetadataFactoryProphecy->reveal(); - - $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $decorated = $decoratedProphecy->reveal(); - - $serializerPropertyMetadataFactory = new SerializerPropertyMetadataFactory($resourceMetadataFactory, $serializerClassMetadataFactory, $decorated); - - $this->assertInstanceOf(PropertyMetadataFactoryInterface::class, $serializerPropertyMetadataFactory); - } - - /** - * @dataProvider groupsProvider - * - * @param mixed $readGroups - * @param mixed $writeGroups - */ - public function testCreateLegacy($readGroups, $writeGroups, ?string $relatedOutputClass = null) - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $dummyResourceMetadata = (new ResourceMetadata()) - ->withAttributes([ - 'normalization_context' => [ - AbstractNormalizer::GROUPS => $readGroups, - ], - 'denormalization_context' => [ - AbstractNormalizer::GROUPS => $writeGroups, - ], - ]); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyResourceMetadata); - $relatedDummyResourceMetadata = new ResourceMetadata(); - if ($relatedOutputClass) { - $relatedDummyResourceMetadata = $relatedDummyResourceMetadata->withAttributes([ - 'output' => ['class' => $relatedOutputClass], - ]); - } - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyResourceMetadata); - - $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); - $dummySerializerClassMetadata = new SerializerClassMetadata(Dummy::class); - $fooSerializerAttributeMetadata = new SerializerAttributeMetadata('foo'); - $fooSerializerAttributeMetadata->addGroup('dummy_read'); - $fooSerializerAttributeMetadata->addGroup('dummy_write'); - $dummySerializerClassMetadata->addAttributeMetadata($fooSerializerAttributeMetadata); - $relatedDummySerializerAttributeMetadata = new SerializerAttributeMetadata('relatedDummy'); - $relatedDummySerializerAttributeMetadata->addGroup('dummy_read'); - $relatedDummySerializerAttributeMetadata->addGroup('dummy_write'); - $dummySerializerClassMetadata->addAttributeMetadata($relatedDummySerializerAttributeMetadata); - $nameConvertedSerializerAttributeMetadata = new SerializerAttributeMetadata('nameConverted'); - $dummySerializerClassMetadata->addAttributeMetadata($nameConvertedSerializerAttributeMetadata); - $serializerClassMetadataFactoryProphecy->getMetadataFor(Dummy::class)->willReturn($dummySerializerClassMetadata); - $relatedDummySerializerClassMetadata = new SerializerClassMetadata(RelatedDummy::class); - $nameSerializerAttributeMetadata = new SerializerAttributeMetadata('name'); - $nameSerializerAttributeMetadata->addGroup('dummy_read'); - $relatedDummySerializerClassMetadata->addAttributeMetadata($nameSerializerAttributeMetadata); - $serializerClassMetadataFactoryProphecy->getMetadataFor(RelatedDummy::class)->willReturn($relatedDummySerializerClassMetadata); - $dummyCarSerializerClassMetadata = new SerializerClassMetadata(DummyCar::class); - $nameSerializerAttributeMetadata = new SerializerAttributeMetadata('name'); - $nameSerializerAttributeMetadata->addGroup('dummy_car_read'); - $nameSerializerAttributeMetadata->addGroup('dummy_write'); - $dummyCarSerializerClassMetadata->addAttributeMetadata($nameSerializerAttributeMetadata); - $serializerClassMetadataFactoryProphecy->getMetadataFor(DummyCar::class)->willReturn($dummyCarSerializerClassMetadata); - - $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $fooPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_ARRAY, true)) - ->withReadable(false) - ->withWritable(true); - $decoratedProphecy->create(Dummy::class, 'foo', [])->willReturn($fooPropertyMetadata); - $relatedDummyPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class)); - $decoratedProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn($relatedDummyPropertyMetadata); - $nameConvertedPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_STRING, true)); - $decoratedProphecy->create(Dummy::class, 'nameConverted', [])->willReturn($nameConvertedPropertyMetadata); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - $resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class); - - $serializerPropertyMetadataFactory = new SerializerPropertyMetadataFactory($resourceMetadataFactoryProphecy->reveal(), $serializerClassMetadataFactoryProphecy->reveal(), $decoratedProphecy->reveal(), $resourceClassResolverProphecy->reveal()); - - $actual = []; - $actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'foo'); - $actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'relatedDummy'); - $actual[] = $serializerPropertyMetadataFactory->create(Dummy::class, 'nameConverted'); - - $this->assertInstanceOf(PropertyMetadata::class, $actual[0]); - $this->assertFalse($actual[0]->isReadable()); - $this->assertTrue($actual[0]->isWritable()); - - $this->assertInstanceOf(PropertyMetadata::class, $actual[1]); - $this->assertTrue($actual[1]->isReadable()); - $this->assertTrue($actual[1]->isWritable()); - if ($relatedOutputClass) { - $this->assertFalse($actual[1]->isReadableLink()); - $this->assertTrue($actual[1]->isWritableLink()); - } else { - $this->assertTrue($actual[1]->isReadableLink()); - $this->assertFalse($actual[1]->isWritableLink()); - } - - $this->assertInstanceOf(PropertyMetadata::class, $actual[2]); - $this->assertFalse($actual[2]->isReadable()); - $this->assertFalse($actual[2]->isWritable()); - } - - public function groupsProvider(): array - { - return [ - [['dummy_read'], ['dummy_write']], - ['dummy_read', 'dummy_write'], - ['dummy_read', 'dummy_write', DummyCar::class], - ]; - } - - /** - * @group legacy - */ - public function testCreateInherited(): void - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyTableInheritanceChild::class)->willReturn(new ResourceMetadata()); - - $serializerClassMetadataFactoryProphecy = $this->prophesize(SerializerClassMetadataFactoryInterface::class); - $dummySerializerClassMetadata = new SerializerClassMetadata(DummyTableInheritanceChild::class); - $serializerClassMetadataFactoryProphecy->getMetadataFor(DummyTableInheritanceChild::class)->willReturn($dummySerializerClassMetadata); - - $decoratedProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $fooPropertyMetadata = (new PropertyMetadata()) - ->withType(new Type(Type::BUILTIN_TYPE_ARRAY, true)) - ->withChildInherited(DummyTableInheritanceChild::class); - $decoratedProphecy->create(DummyTableInheritance::class, 'nickname', [])->willReturn($fooPropertyMetadata); - - $serializerPropertyMetadataFactory = new SerializerPropertyMetadataFactory($resourceMetadataFactoryProphecy->reveal(), $serializerClassMetadataFactoryProphecy->reveal(), $decoratedProphecy->reveal()); - - $actual = $serializerPropertyMetadataFactory->create(DummyTableInheritance::class, 'nickname'); - - $this->assertEquals($actual->getChildInherited(), DummyTableInheritanceChild::class); - } -} diff --git a/tests/Core/Metadata/Property/PropertyMetadataTest.php b/tests/Core/Metadata/Property/PropertyMetadataTest.php deleted file mode 100644 index d1c0d0a3add..00000000000 --- a/tests/Core/Metadata/Property/PropertyMetadataTest.php +++ /dev/null @@ -1,115 +0,0 @@ - - * - * 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\Metadata\Property; - -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyInfo\Type; - -/** - * @author Kévin Dunglas - */ -class PropertyMetadataTest extends TestCase -{ - public function testValueObject() - { - $type = new Type(Type::BUILTIN_TYPE_STRING); - $metadata = new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'desc', true, true, false, false, true, false, 'http://example.com/foo', null, ['foo' => 'bar']); - $this->assertEquals($type, $metadata->getType()); - $this->assertEquals('desc', $metadata->getDescription()); - $this->assertTrue($metadata->isReadable()); - $this->assertTrue($metadata->isWritable()); - $this->assertFalse($metadata->isReadableLink()); - $this->assertFalse($metadata->isWritableLink()); - $this->assertTrue($metadata->isRequired()); - $this->assertFalse($metadata->isIdentifier()); - $this->assertEquals('http://example.com/foo', $metadata->getIri()); - $this->assertEquals(['foo' => 'bar'], $metadata->getAttributes()); - - $newType = new Type(Type::BUILTIN_TYPE_BOOL); - $newMetadata = $metadata->withType($newType); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals($newType, $newMetadata->getType()); - - $newMetadata = $metadata->withDescription('description'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals('description', $newMetadata->getDescription()); - - $newMetadata = $metadata->withReadable(false); - $this->assertNotSame($metadata, $newMetadata); - $this->assertFalse($newMetadata->isReadable()); - - $newMetadata = $metadata->withWritable(false); - $this->assertNotSame($metadata, $newMetadata); - $this->assertFalse($newMetadata->isWritable()); - - $newMetadata = $metadata->withReadableLink(true); - $this->assertNotSame($metadata, $newMetadata); - $this->assertTrue($newMetadata->isReadableLink()); - - $newMetadata = $metadata->withWritableLink(true); - $this->assertNotSame($metadata, $newMetadata); - $this->assertTrue($newMetadata->isWritableLink()); - - $newMetadata = $metadata->withRequired(false); - $this->assertNotSame($metadata, $newMetadata); - $this->assertFalse($newMetadata->isRequired()); - - $newMetadata = $metadata->withIdentifier(true); - $this->assertNotSame($metadata, $newMetadata); - $this->assertTrue($newMetadata->isIdentifier()); - - $newMetadata = $metadata->withIri('foo:bar'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals('foo:bar', $newMetadata->getIri()); - - $newMetadata = $metadata->withAttributes(['a' => 'b']); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals(['a' => 'b'], $newMetadata->getAttributes()); - $this->assertEquals('b', $newMetadata->getAttribute('a')); - - $newMetadata = $metadata->withInitializable(true); - $this->assertNotSame($metadata, $newMetadata); - $this->assertTrue($newMetadata->isInitializable()); - - $newMetadata = $metadata->withDefault('foobar'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals('foobar', $newMetadata->getDefault()); - - $newMetadata = $metadata->withExample('foobarexample'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertEquals('foobarexample', $newMetadata->getExample()); - } - - public function testShouldReturnRequiredFalseWhenRequiredTrueIsSetButMaskedByWritableFalse() - { - $metadata = new PropertyMetadata(); - - $metadata = $metadata->withRequired(true); - $metadata = $metadata->withWritable(false); - - $this->assertFalse($metadata->isRequired()); - } - - public function testShouldReturnPreviouslySetRequiredTrueWhenWritableFalseUnmasked() - { - $metadata = new PropertyMetadata(); - - $metadata = $metadata->withRequired(true); - $metadata = $metadata->withWritable(false); - $metadata = $metadata->withWritable(true); - - $this->assertTrue($metadata->isRequired()); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php deleted file mode 100644 index 75f35871ff7..00000000000 --- a/tests/Core/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactoryTest.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceFilterMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\Filter\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class AnnotationResourceFilterMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreate() - { - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(Dummy::class)->willReturn(new ResourceMetadata('hello', 'blabla'))->shouldBeCalled(); - - $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotations(Argument::type(\ReflectionClass::class))->shouldBeCalled()->willReturn([ // @phpstan-ignore-next-line - new ApiFilter(['value' => DummyFilter::class]), - ]); - - $reader->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->shouldBeCalled()->willReturn([]); - - $factory = new AnnotationResourceFilterMetadataFactory($reader->reveal(), $decorated->reveal()); - - $metadata = $factory->create(Dummy::class); - - $this->assertEquals(['filters' => [ - 'annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_doctrine_orm_filter_dummy_filter', - ]], $metadata->getAttributes()); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php deleted file mode 100644 index bfd09e60dd2..00000000000 --- a/tests/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php +++ /dev/null @@ -1,156 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class AnnotationResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider getCreateDependencies - * - * @param mixed $reader - * @param mixed $decorated - */ - public function testCreate($reader, $decorated, string $expectedShortName, ?string $expectedDescription) - { - $factory = new AnnotationResourceMetadataFactory($reader->reveal(), $decorated ? $decorated->reveal() : null); - $metadata = $factory->create(Dummy::class); - - $this->assertEquals($expectedShortName, $metadata->getShortName()); - $this->assertEquals($expectedDescription, $metadata->getDescription()); - $this->assertEquals('http://example.com', $metadata->getIri()); - $this->assertEquals(['foo' => ['bar' => true]], $metadata->getItemOperations()); - $this->assertEquals(['baz' => ['tab' => false]], $metadata->getCollectionOperations()); - $this->assertEquals(['sub' => ['bus' => false]], $metadata->getSubresourceOperations()); - $this->assertEquals(['a' => 1, 'route_prefix' => '/foobar', 'stateless' => false], $metadata->getAttributes()); - $this->assertEquals(['foo' => 'bar'], $metadata->getGraphql()); - } - - /** - * @requires PHP 8.0 - */ - public function testCreateAttribute() - { - $factory = new AnnotationResourceMetadataFactory(); - $metadata = $factory->create(DummyPhp8::class); - - $this->assertSame('Hey PHP 8', $metadata->getDescription()); - } - - public function testCreateWithDefaults() - { - $defaults = [ - 'shortName' => 'Default shortname should not be ignored', - 'description' => 'CHANGEME!', - 'collection_operations' => ['get'], - 'item_operations' => ['get', 'put'], - 'attributes' => [ - 'pagination_items_per_page' => 4, - 'pagination_maximum_items_per_page' => 6, - 'stateless' => true, - ], - ]; - - $annotation = new ApiResource([ - 'itemOperations' => ['get', 'delete'], - 'attributes' => [ - 'pagination_client_enabled' => true, - 'pagination_maximum_items_per_page' => 10, - 'stateless' => null, - ], - ]); - $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotation)->shouldBeCalled(); - $factory = new AnnotationResourceMetadataFactory($reader->reveal(), null, $defaults); - $metadata = $factory->create(Dummy::class); - - $this->assertNull($metadata->getShortName()); - $this->assertEquals('CHANGEME!', $metadata->getDescription()); - $this->assertEquals(['get'], $metadata->getCollectionOperations()); - $this->assertEquals(['get', 'delete'], $metadata->getItemOperations()); - $this->assertTrue($metadata->getAttribute('pagination_client_enabled')); - $this->assertEquals(4, $metadata->getAttribute('pagination_items_per_page')); - $this->assertEquals(10, $metadata->getAttribute('pagination_maximum_items_per_page')); - $this->assertTrue($metadata->getAttribute('stateless')); - } - - public function testCreateWithoutAttributes() - { - $annotation = new ApiResource([]); - $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotation)->shouldBeCalled(); - $factory = new AnnotationResourceMetadataFactory($reader->reveal(), null); - $metadata = $factory->create(Dummy::class); - - $this->assertNull($metadata->getAttributes()); - } - - public function getCreateDependencies() - { - $resourceData = [ - 'shortName' => 'shortName', - 'description' => 'description', - 'iri' => 'http://example.com', - 'itemOperations' => ['foo' => ['bar' => true]], - 'collectionOperations' => ['baz' => ['tab' => false]], - 'subresourceOperations' => ['sub' => ['bus' => false]], - 'attributes' => ['a' => 1, 'route_prefix' => '/foobar'], - 'graphql' => ['foo' => 'bar'], - 'stateless' => false, - ]; - $annotationFull = new ApiResource($resourceData); - - $reader = $this->prophesize(Reader::class); - $reader->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotationFull)->shouldBeCalled(); - - $decoratedThrow = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedThrow->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); - - $decoratedReturn = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedReturn->create(Dummy::class)->willReturn(new ResourceMetadata('hello', 'blabla'))->shouldBeCalled(); - - $resourceData['description'] = null; - $annotationWithNull = new ApiResource($resourceData); - - $decoratedReturnWithNull = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedReturnWithNull->create(Dummy::class)->willReturn(new ResourceMetadata('hello'))->shouldBeCalled(); - - $readerWithNull = $this->prophesize(Reader::class); - $readerWithNull->getClassAnnotation(Argument::type(\ReflectionClass::class), ApiResource::class)->willReturn($annotationWithNull)->shouldBeCalled(); - - return [ - [$reader, $decoratedThrow, 'shortName', 'description'], - [$reader, null, 'shortName', 'description'], - [$reader, $decoratedReturn, 'hello', 'blabla'], - [$readerWithNull, $decoratedReturnWithNull, 'hello', null], - ]; - } -} diff --git a/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php deleted file mode 100644 index 97f62394e43..00000000000 --- a/tests/Core/Metadata/Resource/Factory/AnnotationResourceNameCollectionFactoryTest.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\AnnotationResourceNameCollectionFactory; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Antoine Bluchet - */ -class AnnotationResourceNameCollectionFactoryTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function testCreate() - { - $decorated = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $decorated->create()->willReturn(new ResourceNameCollection(['foo', 'bar']))->shouldBeCalled(); - - $reader = $this->prophesize(Reader::class); - - $metadata = new AnnotationResourceNameCollectionFactory($reader->reveal(), [], $decorated->reveal()); - - $this->assertEquals(new ResourceNameCollection(['foo', 'bar']), $metadata->create()); - } - - public function testCreateAttribute() - { - $decorated = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $decorated->create()->willReturn(new ResourceNameCollection(['foo', 'bar']))->shouldBeCalled(); - - $metadata = new AnnotationResourceNameCollectionFactory(null, [], $decorated->reveal()); - $this->assertEquals(new ResourceNameCollection(['foo', 'bar']), $metadata->create()); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php deleted file mode 100644 index d972c6a3101..00000000000 --- a/tests/Core/Metadata/Resource/Factory/CachedResourceMetadataFactoryTest.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\CachedResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Baptiste Meyer - * @group legacy - */ -class CachedResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreateWithItemHit() - { - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(true)->shouldBeCalled(); - $cacheItem->get()->willReturn(new ResourceMetadata(null, 'Dummy.'))->shouldBeCalled(); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalled(); - - $decoratedResourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); - $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - - $this->assertEquals(new ResourceMetadata(null, 'Dummy.'), $resultedResourceMetadata); - } - - public function testCreateWithItemNotHit() - { - $propertyMetadata = new ResourceMetadata(null, 'Dummy.'); - - $decoratedResourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedResourceMetadataFactory->create(Dummy::class)->willReturn($propertyMetadata)->shouldBeCalled(); - - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(false)->shouldBeCalled(); - $cacheItem->set($propertyMetadata)->willReturn($cacheItem->reveal())->shouldBeCalled(); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalled(); - $cacheItemPool->save($cacheItem->reveal())->willReturn(true)->shouldBeCalled(); - - $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); - $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - - $expectedResult = new ResourceMetadata(null, 'Dummy.'); - $this->assertEquals($expectedResult, $resultedResourceMetadata); - $this->assertEquals($expectedResult, $cachedResourceMetadataFactory->create(Dummy::class), 'Trigger the local cache'); - } - - public function testCreateWithGetCacheItemThrowsCacheException() - { - $decoratedResourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedResourceMetadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata(null, 'Dummy.'))->shouldBeCalled(); - - $cacheException = new class() extends \Exception implements CacheException {}; - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willThrow($cacheException)->shouldBeCalled(); - - $cachedResourceMetadataFactory = new CachedResourceMetadataFactory($cacheItemPool->reveal(), $decoratedResourceMetadataFactory->reveal()); - $resultedResourceMetadata = $cachedResourceMetadataFactory->create(Dummy::class); - - $expectedResult = new ResourceMetadata(null, 'Dummy.'); - $this->assertEquals($expectedResult, $resultedResourceMetadata); - $this->assertEquals($expectedResult, $cachedResourceMetadataFactory->create(Dummy::class), 'Trigger the local cache'); - } - - private function generateCacheKey(string $resourceClass = Dummy::class) - { - return CachedResourceMetadataFactory::CACHE_KEY_PREFIX.md5($resourceClass); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php deleted file mode 100644 index 3965c3375f0..00000000000 --- a/tests/Core/Metadata/Resource/Factory/CachedResourceNameCollectionFactoryTest.php +++ /dev/null @@ -1,92 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Metadata\Resource\Factory\CachedResourceNameCollectionFactory; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Baptiste Meyer - */ -class CachedResourceNameCollectionFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreateWithItemHit() - { - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(true)->shouldBeCalled(); - $cacheItem->get()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem(CachedResourceNameCollectionFactory::CACHE_KEY)->willReturn($cacheItem->reveal())->shouldBeCalled(); - - $decoratedResourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - - $cachedResourceNameCollectionFactory = new CachedResourceNameCollectionFactory($cacheItemPool->reveal(), $decoratedResourceNameCollectionFactory->reveal()); - $resultedResourceNameCollection = $cachedResourceNameCollectionFactory->create(); - - $expectedResult = new ResourceNameCollection([Dummy::class]); - $this->assertEquals($expectedResult, $resultedResourceNameCollection); - $this->assertEquals($expectedResult, $cachedResourceNameCollectionFactory->create(), 'Trigger the local cache'); - } - - public function testCreateWithItemNotHit() - { - $resourceNameCollection = new ResourceNameCollection([Dummy::class]); - - $decoratedResourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $decoratedResourceNameCollectionFactory->create()->willReturn($resourceNameCollection)->shouldBeCalled(); - - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(false)->shouldBeCalled(); - $cacheItem->set($resourceNameCollection)->willReturn($cacheItem->reveal())->shouldBeCalled(); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem(CachedResourceNameCollectionFactory::CACHE_KEY)->willReturn($cacheItem->reveal())->shouldBeCalled(); - $cacheItemPool->save($cacheItem->reveal())->willReturn(true)->shouldBeCalled(); - - $cachedResourceNameCollectionFactory = new CachedResourceNameCollectionFactory($cacheItemPool->reveal(), $decoratedResourceNameCollectionFactory->reveal()); - $resultedResourceNameCollection = $cachedResourceNameCollectionFactory->create(); - - $expectedResult = new ResourceNameCollection([Dummy::class]); - $this->assertEquals($expectedResult, $resultedResourceNameCollection); - $this->assertEquals($expectedResult, $cachedResourceNameCollectionFactory->create(), 'Trigger the local cache'); - } - - public function testCreateWithGetCacheItemThrowsCacheException() - { - $decoratedResourceNameCollectionFactory = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $decoratedResourceNameCollectionFactory->create()->willReturn(new ResourceNameCollection([Dummy::class]))->shouldBeCalled(); - - $cacheException = new class() extends \Exception implements CacheException {}; - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem(CachedResourceNameCollectionFactory::CACHE_KEY)->willThrow($cacheException)->shouldBeCalled(); - - $cachedResourceNameCollectionFactory = new CachedResourceNameCollectionFactory($cacheItemPool->reveal(), $decoratedResourceNameCollectionFactory->reveal()); - $resultedResourceNameCollection = $cachedResourceNameCollectionFactory->create(); - - $expectedResult = new ResourceNameCollection([Dummy::class]); - $this->assertEquals($expectedResult, $resultedResourceNameCollection); - $this->assertEquals($expectedResult, $cachedResourceNameCollectionFactory->create(), 'Trigger the local cache'); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php deleted file mode 100644 index 629aee72ef3..00000000000 --- a/tests/Core/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php +++ /dev/null @@ -1,361 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Extractor\ExtractorInterface; -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Core\Metadata\Resource\Factory\ExtractorResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ShortNameResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ExtractorResourceNameCollectionFactory; -use ApiPlatform\Tests\Fixtures\DummyResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * Tests extractor resource metadata factory. - * - * @author Antoine Bluchet - * @group legacy - */ -class ExtractorResourceMetadataFactoryTest extends FileConfigurationMetadataFactoryProvider -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - /** - * @dataProvider resourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testXmlCreateResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - public function testXmlDoesNotExistMetadataFactory() - { - $this->expectException(ResourceClassNotFoundException::class); - $this->expectExceptionMessage('Resource "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\ThisDoesNotExist" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcenotfound.xml'; - $factory = new ExtractorResourceNameCollectionFactory(new XmlExtractor([$configPath])); - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - - foreach ($factory->create() as $resourceName) { - $resourceMetadataFactory->create($resourceName); - } - } - - /** - * @dataProvider optionalResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testXmlOptionalResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesoptional.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @expectedDeprecation Configuring "%s" tags without using a parent "%ss" tag is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - * @group legacy - * @dataProvider legacyOperationsResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testLegacyOperationsResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/legacyoperations.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider noCollectionOperationsResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testXmlNoCollectionOperationsResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/nocollectionoperations.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider noItemOperationsResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testXmlNoItemOperationsResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/noitemoperations.xml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - public function testInvalidXmlResourceMetadataFactory() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesinvalid.xml'; - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath])); - - $resourceMetadataFactory->create(FileConfigDummy::class); - } - - /** - * @dataProvider optionalResourceMetadataProvider - */ - public function testXmlParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesoptional.xml'; - - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn(new ResourceMetadata(null, 'test'))->shouldBeCalled(); - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath]), $decorated->reveal()); - - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - $expectedResourceMetadata = $expectedResourceMetadata->withDescription('test'); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider resourceMetadataProvider - */ - public function testXmlExistingParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn($expectedResourceMetadata)->shouldBeCalled(); - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath]), $decorated->reveal()); - - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider resourceMetadataProvider - */ - public function testYamlCreateResourceMetadata(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - public function testYamlDoesNotExistMetadataFactory() - { - $this->expectException(ResourceClassNotFoundException::class); - $this->expectExceptionMessage('Resource "ApiPlatform\\Tests\\Fixtures\\TestBundle\\Entity\\ThisDoesNotExist" not found.'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcenotfound.yml'; - $factory = new ExtractorResourceNameCollectionFactory(new YamlExtractor([$configPath])); - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - - foreach ($factory->create() as $resourceName) { - $resourceMetadataFactory->create($resourceName); - } - } - - /** - * @dataProvider optionalResourceMetadataProvider - * - * @param mixed $expectedResourceMetadata - */ - public function testYamlOptionalResourceMetadata($expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesoptional.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider resourceMetadataProvider - */ - public function testYamlSingleResourceMetadata(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/single_resource.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider optionalResourceMetadataProvider - */ - public function testYamlParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesoptional.yml'; - - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn(new ResourceMetadata(null, 'test'))->shouldBeCalled(); - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - $expectedResourceMetadata = $expectedResourceMetadata->withDescription('test'); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - /** - * @dataProvider resourceMetadataProvider - */ - public function testYamlExistingParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - - $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decorated->create(FileConfigDummy::class)->willReturn($expectedResourceMetadata)->shouldBeCalled(); - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); - - $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); - - $this->assertEquals($expectedResourceMetadata, $resourceMetadata); - } - - public function testCreateWithMalformedYaml() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/parse_exception.yml'; - - (new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class); - } - - public function testCreateWithBadDeclaration() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"ApiPlatform\\\\Tests\\\\Fixtures\\\\TestBundle\\\\Entity\\\\Dummy" setting is expected to be null or an array, string given in ".+\\/Fixtures\\/FileConfigurations\\/bad_declaration\\.yml"\\./'); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/bad_declaration.yml'; - - (new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class); - } - - public function testCreateShortNameResourceMetadataForClassWithoutNamespace() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourceswithoutnamespace.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $shortNameResourceMetadataFactory = new ShortNameResourceMetadataFactory($resourceMetadataFactory); - - $resourceMetadata = $shortNameResourceMetadataFactory->create(\DateTime::class); - $this->assertSame(\DateTime::class, $resourceMetadata->getShortName()); - } - - public function testItSupportsInterfaceAsAResource() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/interface_resource.yml'; - - $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath])); - $shortNameResourceMetadataFactory = new ShortNameResourceMetadataFactory($resourceMetadataFactory); - - $resourceMetadata = $shortNameResourceMetadataFactory->create(DummyResourceInterface::class); - $this->assertSame('DummyResourceInterface', $resourceMetadata->getShortName()); - } - - public function testItFallbacksToDefaultConfiguration() - { - $defaults = [ - 'shortName' => 'Default shortname should not be ignored', - 'description' => 'CHANGEME!', - 'collection_operations' => ['get'], - 'item_operations' => ['get', 'put'], - 'attributes' => [ - 'pagination_items_per_page' => 4, - 'pagination_maximum_items_per_page' => 6, - 'stateless' => true, - ], - ]; - $resourceConfiguration = [ - Dummy::class => [ - 'shortName' => null, - 'description' => null, - 'subresourceOperations' => null, - 'itemOperations' => ['get', 'delete'], - 'attributes' => [ - 'pagination_items_per_page' => null, - 'pagination_maximum_items_per_page' => 10, - 'stateless' => false, - ], - ], - ]; - - $extractor = new class($resourceConfiguration) implements ExtractorInterface { - private $resources; - - public function __construct(array $resources) - { - $this->resources = $resources; - } - - public function getResources(): array - { - return $this->resources; - } - }; - $factory = new ExtractorResourceMetadataFactory($extractor, null, $defaults); - $metadata = $factory->create(Dummy::class); - - $this->assertNull($metadata->getShortName()); - $this->assertEquals('CHANGEME!', $metadata->getDescription()); - $this->assertEquals(['get'], $metadata->getCollectionOperations()); - $this->assertEquals(['get', 'delete'], $metadata->getItemOperations()); - $this->assertEquals(4, $metadata->getAttribute('pagination_items_per_page')); - $this->assertEquals(10, $metadata->getAttribute('pagination_maximum_items_per_page')); - $this->assertFalse($metadata->getAttribute('stateless')); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php b/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php deleted file mode 100644 index a8617b5216a..00000000000 --- a/tests/Core/Metadata/Resource/Factory/ExtractorResourceNameCollectionFactoryTest.php +++ /dev/null @@ -1,79 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\Resource\Factory\ExtractorResourceNameCollectionFactory; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; -use PHPUnit\Framework\TestCase; - -/** - * Tests extractor resource name collection factory. - * - * @author Antoine Bluchet - */ -class ExtractorResourceNameCollectionFactoryTest extends TestCase -{ - public function testXmlResourceName() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.xml'; - $factory = new ExtractorResourceNameCollectionFactory(new XmlExtractor([$configPath])); - - $this->assertEquals($factory->create(), new ResourceNameCollection([ - Dummy::class, - FileConfigDummy::class, - ])); - } - - public function testInvalidExtractorResourceNameCollectionFactory() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resourcesinvalid.xml'; - $factory = new ExtractorResourceNameCollectionFactory(new XmlExtractor([$configPath])); - $factory->create(); - } - - public function testYamlResourceName() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/resources.yml'; - $factory = new ExtractorResourceNameCollectionFactory(new YamlExtractor([$configPath])); - - $this->assertEquals($factory->create(), new ResourceNameCollection([ - Dummy::class, - FileConfigDummy::class, - ])); - } - - public function testYamlSingleResourceName() - { - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/single_resource.yml'; - $factory = new ExtractorResourceNameCollectionFactory(new YamlExtractor([$configPath])); - - $this->assertEquals($factory->create(), new ResourceNameCollection([FileConfigDummy::class])); - } - - public function testCreateWithMalformedYaml() - { - $this->expectException(InvalidArgumentException::class); - - $configPath = __DIR__.'/../../../../Fixtures/FileConfigurations/parse_exception.yml'; - - (new ExtractorResourceNameCollectionFactory(new YamlExtractor([$configPath])))->create(); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php b/tests/Core/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php deleted file mode 100644 index 39c81511c39..00000000000 --- a/tests/Core/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php +++ /dev/null @@ -1,114 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * Resource metadata provider for file configured factories tests. - * - * @author Antoine Bluchet - */ -abstract class FileConfigurationMetadataFactoryProvider extends TestCase -{ - public function resourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - - $metadata = [ - 'shortName' => 'thedummyshortname', - 'description' => 'Dummy resource', - 'itemOperations' => [ - 'my_op_name' => ['method' => 'GET'], - 'my_other_op_name' => ['method' => 'POST'], - ], - 'collectionOperations' => [ - 'my_collection_op' => ['method' => 'POST', 'path' => 'the/collection/path'], - ], - 'subresourceOperations' => [ - 'my_collection_subresource' => ['path' => 'the/subresource/path'], - ], - 'graphql' => [ - 'query' => [ - 'normalization_context' => [ - AbstractNormalizer::GROUPS => ['graphql'], - ], - ], - ], - 'iri' => 'someirischema', - 'attributes' => [ - 'normalization_context' => [ - AbstractNormalizer::GROUPS => ['default'], - ], - 'denormalization_context' => [ - AbstractNormalizer::GROUPS => ['default'], - ], - 'hydra_context' => [ - '@type' => 'hydra:Operation', - '@hydra:title' => 'File config Dummy', - ], - 'stateless' => true, - ], - ]; - - foreach (['shortName', 'description', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'iri', 'attributes'] as $property) { - $wither = 'with'.ucfirst($property); - $resourceMetadata = $resourceMetadata->{$wither}($metadata[$property]); - } - - return [[$resourceMetadata]]; - } - - public function optionalResourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations(['my_op_name' => ['method' => 'POST']]); - - return [[$resourceMetadata]]; - } - - public function noCollectionOperationsResourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations(['my_op_name' => ['method' => 'POST']]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([]); - - return [[$resourceMetadata]]; - } - - public function noItemOperationsResourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withCollectionOperations(['my_op_name' => ['method' => 'POST']]); - $resourceMetadata = $resourceMetadata->withItemOperations([]); - - return [[$resourceMetadata]]; - } - - public function legacyOperationsResourceMetadataProvider() - { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withItemOperations([ - 'my_op_name' => ['method' => 'POST'], - 'my_other_op_name' => ['method' => 'GET'], - ]); - $resourceMetadata = $resourceMetadata->withCollectionOperations([ - 'my_op_name' => ['method' => 'POST'], - ]); - - return [[$resourceMetadata]]; - } -} diff --git a/tests/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactoryTest.php deleted file mode 100644 index 6f247ff792f..00000000000 --- a/tests/Core/Metadata/Resource/Factory/FormatsResourceMetadataFactoryTest.php +++ /dev/null @@ -1,193 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\FormatsResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class FormatsResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider createProvider - */ - public function testCreate(ResourceMetadata $previous, ResourceMetadata $expected, array $formats = [], array $patchFormats = []): void - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($previous); - - $actual = (new FormatsResourceMetadataFactory($resourceMetadataFactoryProphecy->reveal(), $formats, $patchFormats))->create('Foo'); - $this->assertEquals($expected, $actual); - } - - public function createProvider(): iterable - { - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => []], - ['get' => []], - ['formats' => 'json'], - ['get' => []] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]], - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]], - ['formats' => 'json'], - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]] - ), - ['json' => ['application/json']], - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => []], - ['get' => []], - ['formats' => ['json' => ['application/json']]], - ['get' => []] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]], - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]], - ['formats' => ['json' => ['application/json']]], - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]] - ), - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => []], - ['get' => []], - ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => 'text/csv']], - ['get' => []] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => ['text/csv']]]], - ['get' => ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => ['text/csv']]]], - ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => 'text/csv']], - ['get' => ['input_formats' => ['json' => ['application/json'], 'xml' => ['text/xml', 'application/xml']], 'output_formats' => ['csv' => ['text/csv']]]] - ), - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['patch' => ['method' => 'PATCH']] - ), - new ResourceMetadata( - null, - null, - null, - ['patch' => ['method' => 'PATCH', 'input_formats' => ['json' => ['application/merge-patch+json']], 'output_formats' => []]] - ), - [], - ['json' => ['application/merge-patch+json']], - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => ['formats' => 'json']] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['formats' => ['json' => ['application/json']], 'input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]] - ), - ['json' => ['application/json']], - ]; - - yield [ - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => 'json', 'output_formats' => 'json']] - ), - new ResourceMetadata( - null, - null, - null, - ['get' => ['input_formats' => ['json' => ['application/json']], 'output_formats' => ['json' => ['application/json']]]] - ), - ['json' => ['application/json']], - ]; - } - - public function testInvalidFormatType(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The \'formats\' attributes value must be a string when trying to include an already configured format, object given.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - null, - ['formats' => [new \stdClass()]] - )); - - (new FormatsResourceMetadataFactory($resourceMetadataFactoryProphecy->reveal(), [], []))->create('Foo'); - } - - public function testNotConfiguredFormat(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('You either need to add the format \'xml\' to your project configuration or declare a mime type for it in your annotation.'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - null, - ['formats' => ['xml']] - )); - - (new FormatsResourceMetadataFactory($resourceMetadataFactoryProphecy->reveal(), [], []))->create('Foo'); - } -} diff --git a/tests/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php deleted file mode 100644 index 1d3f4ffa862..00000000000 --- a/tests/Core/Metadata/Resource/Factory/InputOutputResourceMetadataFactoryTest.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\InputOutputResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class InputOutputResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider getAttributes - * - * @param mixed $attributes - * @param mixed $expected - */ - public function testInputOutputMetadata($attributes, $expected) - { - $resourceMetadata = (new ResourceMetadata(null))->withAttributes($attributes); - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new InputOutputResourceMetadataFactory($decorated); - $this->assertSame($expected, $factory->create('Foo')->getAttributes()['input']); - } - - /** - * @dataProvider getAttributes - * - * @param mixed $attributes - * @param mixed $expected - */ - public function testInputOutputViaGraphQlMetadata($attributes, $expected) - { - $resourceMetadata = (new ResourceMetadata(null))->withGraphQl(['create' => $attributes]); - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new InputOutputResourceMetadataFactory($decorated); - $this->assertSame($expected, $factory->create('Foo')->getGraphqlAttribute('create', 'input')); - } - - public function getAttributes(): array - { - return [ - // no input class defined - [[], null], - // input is a string - [['input' => DummyEntity::class], ['class' => DummyEntity::class, 'name' => 'DummyEntity']], - // input is false - [['input' => false], ['class' => null]], - // input is an array - [['input' => ['class' => DummyEntity::class, 'type' => 'Foo']], ['class' => DummyEntity::class, 'type' => 'Foo', 'name' => 'DummyEntity']], - ]; - } -} diff --git a/tests/Core/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php deleted file mode 100644 index 517ff91d407..00000000000 --- a/tests/Core/Metadata/Resource/Factory/OperationResourceMetadataFactoryTest.php +++ /dev/null @@ -1,79 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\OperationResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class OperationResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - /** - * @dataProvider getMetadata - */ - public function testCreateOperation(ResourceMetadata $before, ResourceMetadata $after, array $formats = []): void - { - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($before); - - $this->assertEquals($after, (new OperationResourceMetadataFactory($decoratedProphecy->reveal(), $formats))->create(Dummy::class)); - } - - public function getMetadata(): iterable - { - $jsonapi = ['jsonapi' => ['application/vnd.api+json']]; - - // Item operations - yield [new ResourceMetadata(null, null, null, null, [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get', 'put', 'delete']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, null, [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get', 'put', 'patch', 'delete']), [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['get'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['get']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['put'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['put']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['delete'], [], null, [], []), new ResourceMetadata(null, null, null, $this->getOperations(['delete']), [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch']], [], null, [], []), new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch', 'stateless' => null]], [], null, [], [])]; - yield [new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch']], [], null, [], []), new ResourceMetadata(null, null, null, ['patch' => ['method' => 'PATCH', 'route_name' => 'patch', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['untouched' => ['method' => 'GET']], [], null, [], []), new ResourceMetadata(null, null, null, ['untouched' => ['method' => 'GET', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['untouched_custom' => ['route_name' => 'custom_route']], [], null, [], []), new ResourceMetadata(null, null, null, ['untouched_custom' => ['route_name' => 'custom_route', 'stateless' => null]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['stateless_operation' => ['method' => 'GET', 'stateless' => true]], [], null, [], []), new ResourceMetadata(null, null, null, ['stateless_operation' => ['method' => 'GET', 'stateless' => true]], [], null, [], []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, ['statefull_attribute' => ['method' => 'GET']], [], ['stateless' => false], [], []), new ResourceMetadata(null, null, null, ['statefull_attribute' => ['method' => 'GET', 'stateless' => false]], [], ['stateless' => false], [], []), $jsonapi]; - - // Collection operations - yield [new ResourceMetadata(null, null, null, [], null, null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['get', 'post']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['get'], null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['get']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['post'], null, [], []), new ResourceMetadata(null, null, null, [], $this->getOperations(['post']), null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['options' => ['method' => 'OPTIONS', 'route_name' => 'options']], null, [], []), new ResourceMetadata(null, null, null, [], ['options' => ['route_name' => 'options', 'method' => 'OPTIONS', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['untouched' => ['method' => 'GET']], null, [], []), new ResourceMetadata(null, null, null, [], ['untouched' => ['method' => 'GET', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['untouched_custom' => ['route_name' => 'custom_route']], null, [], []), new ResourceMetadata(null, null, null, [], ['untouched_custom' => ['route_name' => 'custom_route', 'stateless' => null]], null, [], [])]; - yield [new ResourceMetadata(null, null, null, [], ['statefull_operation' => ['method' => 'GET', 'stateless' => false]], null, null, []), new ResourceMetadata(null, null, null, [], ['statefull_operation' => ['method' => 'GET', 'stateless' => false]], null, null, []), $jsonapi]; - yield [new ResourceMetadata(null, null, null, [], ['stateless_attribute' => ['method' => 'GET']], ['stateless' => true], null, []), new ResourceMetadata(null, null, null, [], ['stateless_attribute' => ['method' => 'GET', 'stateless' => true]], ['stateless' => true], null, []), $jsonapi]; - } - - private function getOperations(array $names): array - { - $operations = []; - foreach ($names as $name) { - $operations[$name] = ['method' => strtoupper($name), 'stateless' => null]; - } - - return $operations; - } -} diff --git a/tests/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php b/tests/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php deleted file mode 100644 index 7f75db1f485..00000000000 --- a/tests/Core/Metadata/Resource/Factory/PhpDocResourceMetadataFactoryTest.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Metadata\Resource\Factory\PhpDocResourceMetadataFactory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\ClassWithNoDocBlock; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use PHPUnit\Framework\TestCase; - -/** - * @group legacy - */ -class PhpDocResourceMetadataFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testExistingDescription() - { - $resourceMetadata = new ResourceMetadata(null, 'My desc'); - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new PhpDocResourceMetadataFactory($decorated); - $this->assertSame($resourceMetadata, $factory->create('Foo')); - } - - public function testNoDocBlock() - { - $resourceMetadata = new ResourceMetadata(); - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(ClassWithNoDocBlock::class)->willReturn($resourceMetadata)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new PhpDocResourceMetadataFactory($decorated); - $this->assertSame($resourceMetadata, $factory->create(ClassWithNoDocBlock::class)); - } - - public function testExtractDescription() - { - $decoratedProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $decoratedProphecy->create(DummyEntity::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new PhpDocResourceMetadataFactory($decorated); - $this->assertSame('My dummy entity.', $factory->create(DummyEntity::class)->getDescription()); - } -} diff --git a/tests/Core/Metadata/Resource/ResourceMetadataTest.php b/tests/Core/Metadata/Resource/ResourceMetadataTest.php deleted file mode 100644 index 863f5a447f4..00000000000 --- a/tests/Core/Metadata/Resource/ResourceMetadataTest.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * 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\Metadata\Resource; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class ResourceMetadataTest extends TestCase -{ - public function testValueObject() - { - $metadata = new ResourceMetadata('shortName', 'desc', 'http://example.com/foo', ['iop1' => ['foo' => 'a'], 'iop2' => ['bar' => 'b']], ['cop1' => ['foo' => 'c'], 'cop2' => ['bar' => 'd']], ['baz' => 'bar'], ['sop1' => ['sub' => 'bus']], ['query' => ['foo' => 'graphql']]); - $this->assertSame('shortName', $metadata->getShortName()); - $this->assertSame('desc', $metadata->getDescription()); - $this->assertSame('http://example.com/foo', $metadata->getIri()); - $this->assertSame(['iop1' => ['foo' => 'a'], 'iop2' => ['bar' => 'b']], $metadata->getItemOperations()); - $this->assertSame('a', $metadata->getItemOperationAttribute('iop1', 'foo', 'z')); - $this->assertSame('a', $metadata->getTypedOperationAttribute(OperationType::ITEM, 'iop1', 'foo', 'z')); - $this->assertSame('bar', $metadata->getItemOperationAttribute('iop1', 'baz', 'z', true)); - $this->assertSame('bar', $metadata->getItemOperationAttribute(null, 'baz', 'z', true)); - $this->assertSame('z', $metadata->getItemOperationAttribute('iop1', 'notExist', 'z', true)); - $this->assertSame('z', $metadata->getItemOperationAttribute('notExist', 'notExist', 'z', true)); - $this->assertSame(['cop1' => ['foo' => 'c'], 'cop2' => ['bar' => 'd']], $metadata->getCollectionOperations()); - $this->assertSame('c', $metadata->getCollectionOperationAttribute('cop1', 'foo', 'z')); - $this->assertSame('c', $metadata->getTypedOperationAttribute(OperationType::COLLECTION, 'cop1', 'foo', 'z')); - $this->assertSame('bar', $metadata->getCollectionOperationAttribute('cop1', 'baz', 'z', true)); - $this->assertSame('bar', $metadata->getCollectionOperationAttribute(null, 'baz', 'z', true)); - $this->assertSame('z', $metadata->getCollectionOperationAttribute('cop1', 'notExist', 'z', true)); - $this->assertSame('z', $metadata->getCollectionOperationAttribute('notExist', 'notExist', 'z', true)); - $this->assertSame(['baz' => 'bar'], $metadata->getAttributes()); - $this->assertSame('bar', $metadata->getAttribute('baz')); - $this->assertSame('z', $metadata->getAttribute('notExist', 'z')); - $this->assertSame(['sop1' => ['sub' => 'bus']], $metadata->getSubresourceOperations()); - $this->assertSame('bus', $metadata->getSubresourceOperationAttribute('sop1', 'sub')); - $this->assertSame('bus', $metadata->getTypedOperationAttribute(OperationType::SUBRESOURCE, 'sop1', 'sub')); - $this->assertSame('sub', $metadata->getSubresourceOperationAttribute('sop1', 'bus', 'sub')); - $this->assertSame('bar', $metadata->getSubresourceOperationAttribute('sop1', 'baz', 'sub', true)); - $this->assertSame('graphql', $metadata->getGraphqlAttribute('query', 'foo')); - $this->assertSame('bar', $metadata->getGraphqlAttribute('query', 'baz', null, true)); - $this->assertSame('hey', $metadata->getGraphqlAttribute('query', 'notExist', 'hey', true)); - - $newMetadata = $metadata->withShortName('name'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame('name', $newMetadata->getShortName()); - - $newMetadata = $metadata->withDescription('description'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame('description', $newMetadata->getDescription()); - - $newMetadata = $metadata->withIri('foo:bar'); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame('foo:bar', $newMetadata->getIri()); - - $newMetadata = $metadata->withItemOperations(['a' => ['b' => 'c']]); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame(['a' => ['b' => 'c']], $newMetadata->getItemOperations()); - } - - /** - * @dataProvider getWithMethods - * - * @param mixed $value - */ - public function testWithMethods(string $name, $value) - { - $metadata = new ResourceMetadata(); - $newMetadata = $metadata->{"with$name"}($value); - $this->assertNotSame($metadata, $newMetadata); - $this->assertSame($value, $newMetadata->{"get$name"}()); - } - - public function testGetOperationAttributeFallback() - { - $metadata = new ResourceMetadata(); - $this->assertSame('okay', $metadata->getOperationAttribute([], 'doh', 'okay')); - } - - public function testGetOperationAttributeFallbackToResourceAttribute() - { - $metadata = new ResourceMetadata(null, null, null, null, null, ['doh' => 'nuts']); - $this->assertSame('nuts', $metadata->getOperationAttribute([], 'doh', 'okay', true)); - } - - public function getWithMethods(): array - { - return [ - ['ShortName', 'shortName'], - ['Description', 'description'], - ['Iri', 'iri'], - ['ItemOperations', ['a' => ['b' => 'c']]], - ['CollectionOperations', ['a' => ['b' => 'c']]], - ['Attributes', ['a' => ['b' => 'c']]], - ['Graphql', ['query' => ['b' => 'c']]], - ]; - } -} diff --git a/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php b/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php deleted file mode 100644 index a36905990eb..00000000000 --- a/tests/Core/Metadata/Resource/ResourceNameCollectionTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * 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\Metadata\Resource; - -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use PHPUnit\Framework\TestCase; - -/** - * @author Kévin Dunglas - */ -class ResourceNameCollectionTest extends TestCase -{ - public function testValueObject() - { - $collection = new ResourceNameCollection(['foo', 'bar']); - $this->assertInstanceOf(\Countable::class, $collection); - $this->assertInstanceOf(\IteratorAggregate::class, $collection); - $this->assertCount(2, $collection); - $this->assertInstanceOf(\ArrayIterator::class, $collection->getIterator()); - } -} diff --git a/tests/Core/Metadata/schema/XmlSchemaTest.php b/tests/Core/Metadata/schema/XmlSchemaTest.php deleted file mode 100644 index a54fa18e6dc..00000000000 --- a/tests/Core/Metadata/schema/XmlSchemaTest.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * 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\Metadata\schema; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Config\Util\XmlUtils; - -/** - * @author Grégoire Hébert - */ -class XmlSchemaTest extends TestCase -{ - public function testSchema(): void - { - $fixtures = __DIR__.'/../../../Fixtures/Metadata/schema/'; - $schema = __DIR__.'/../../../../src/Core/Metadata/schema/metadata.xsd'; - - try { - XmlUtils::loadFile($fixtures.'invalid.xml', $schema); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertStringContainsString('ERROR 1845', $e->getMessage()); - } - - $this->assertInstanceOf(\DOMDocument::class, XmlUtils::loadFile($fixtures.'valid.xml', $schema)); - } -} diff --git a/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php b/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php deleted file mode 100644 index 12f9403e244..00000000000 --- a/tests/Core/OpenApi/Factory/OpenApiFactoryTest.php +++ /dev/null @@ -1,818 +0,0 @@ - - * - * 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\OpenApi\Factory; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver; -use ApiPlatform\Core\JsonSchema\SchemaFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\JsonSchema\Schema; -use ApiPlatform\JsonSchema\TypeFactory; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\OpenApi\Model; -use ApiPlatform\OpenApi\OpenApi; -use ApiPlatform\OpenApi\Options; -use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; -use ApiPlatform\State\Pagination\PaginationOptions; -use ApiPlatform\Tests\Fixtures\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; -use Symfony\Component\Serializer\Serializer; - -/** - * @group legacy - */ -class OpenApiFactoryTest extends TestCase -{ - use ProphecyTrait; - - private const OPERATION_FORMATS = [ - 'input_formats' => ['jsonld' => ['application/ld+json']], - 'output_formats' => ['jsonld' => ['application/ld+json']], - ]; - - public function testInvoke(): void - { - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - 'delete' => ['method' => 'DELETE'] + self::OPERATION_FORMATS, - 'custom' => ['method' => 'HEAD', 'path' => '/foo/{id}', 'openapi_context' => [ - 'x-visibility' => 'hide', - 'description' => 'Custom description', - 'parameters' => [ - ['description' => 'Test parameter', 'name' => 'param', 'in' => 'path', 'required' => true], - ['description' => 'Replace parameter', 'name' => 'id', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'string', 'format' => 'uuid']], - ], - 'tags' => ['Dummy', 'Profile'], - 'responses' => [ - '202' => [ - 'description' => 'Success', - 'content' => [ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'headers' => [ - 'Foo' => ['description' => 'A nice header', 'schema' => ['type' => 'integer']], - ], - 'links' => [ - 'Foo' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - '205' => [], - ], - 'requestBody' => [ - 'required' => true, - 'description' => 'Custom request body', - 'content' => [ - 'multipart/form-data' => [ - 'schema' => [ - 'type' => 'object', - 'properties' => [ - 'file' => [ - 'type' => 'string', - 'format' => 'binary', - ], - ], - ], - ], - ], - ], - ]] + self::OPERATION_FORMATS, - 'formats' => ['method' => 'PUT', 'path' => '/formatted/{id}', 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]], - ], - [ - 'get' => ['method' => 'GET', 'openapi_context' => [ - 'parameters' => [ - ['description' => 'Test modified collection page number', 'name' => 'page', 'in' => 'query', 'required' => false, 'schema' => ['type' => 'integer', 'default' => 1], 'allowEmptyValue' => true], - ], - ]] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - 'filtered' => ['method' => 'GET', 'filters' => ['f1', 'f2', 'f3', 'f4', 'f5'], 'path' => '/filtered'] + self::OPERATION_FORMATS, - 'paginated' => ['method' => 'GET', 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'pagination_maximum_items_per_page' => 80, 'path' => '/paginated'] + self::OPERATION_FORMATS, - ], - [ - 'pagination_client_items_per_page' => true, - 'output' => ['class' => OutputDto::class], - ] - ); - - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create(Argument::any())->willReturn([]); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Dummy::class])); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate', 'enum'])); - $propertyNameCollectionFactoryProphecy->create(OutputDto::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate', 'enum'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'enum', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an enum.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'enum', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an enum.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filters = [ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'openapi' => ['example' => 'bar', 'deprecated' => true, 'allowEmptyValue' => true, 'allowReserved' => true, 'explode' => true], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - 'f4' => new DummyFilter(['order[name]' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => false, - 'schema' => [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ], - ]]), - ]; - - foreach ($filters as $filterId => $filter) { - $filterLocatorProphecy->has($filterId)->willReturn(true)->shouldBeCalled(); - $filterLocatorProphecy->get($filterId)->willReturn($filter)->shouldBeCalled(); - } - - $filterLocatorProphecy->has('f5')->willReturn(false)->shouldBeCalled(); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new CamelCaseToSnakeCaseNameConverter()); - $typeFactory->setSchemaFactory($schemaFactory); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $factory = new OpenApiFactory( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - $filterLocatorProphecy->reveal(), - $subresourceOperationFactoryProphecy->reveal(), - $identifiersExtractorProphecy->reveal(), - [], - new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]), - new PaginationOptions(true, 'page', true, 'itemsPerPage', true, 'pagination') - ); - - $dummySchema = new Schema('openapi'); - // $dummySchema = new Model\Schema(false, null, false, false, null, ['url' => 'http://schema.example.com/Dummy']); - $dummySchema->setDefinitions(new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'minLength' => 3, - 'maxLength' => 20, - 'pattern' => '^dummyPattern$', - ]), - 'description' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is an initializable but not writable property.', - ]), - 'dummy_date' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a \DateTimeInterface object.', - 'format' => 'date-time', - 'nullable' => true, - ]), - 'enum' => new \ArrayObject([ - 'type' => 'string', - 'enum' => ['one', 'two'], - 'example' => 'one', - 'description' => 'This is an enum.', - ]), - ], - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - ])); - - $openApi = $factory(['base_url' => '/app_dev.php/']); - - $this->assertInstanceOf(OpenApi::class, $openApi); - $this->assertEquals($openApi->getInfo(), new Model\Info('Test API', '1.2.3', 'This is a test API.')); - $this->assertEquals($openApi->getServers(), [new Model\Server('/app_dev.php/')]); - - $components = $openApi->getComponents(); - $this->assertInstanceOf(Model\Components::class, $components); - - $this->assertEquals($components->getSchemas(), new \ArrayObject(['Dummy' => $dummySchema->getDefinitions(), 'Dummy.OutputDto' => $dummySchema->getDefinitions()])); - - $this->assertEquals($components->getSecuritySchemes(), new \ArrayObject([ - 'oauth' => new Model\SecurityScheme('oauth2', 'OAuth 2.0 authorization code Grant', null, null, null, null, new Model\OAuthFlows(null, null, null, new Model\OAuthFlow('/oauth/v2/auth', '/oauth/v2/token', '/oauth/v2/refresh', new \ArrayObject(['scope param'])))), - 'header' => new Model\SecurityScheme('apiKey', 'Value for the Authorization header parameter.', 'Authorization', 'header'), - 'query' => new Model\SecurityScheme('apiKey', 'Value for the key query parameter.', 'key', 'query'), - ])); - - $this->assertSame([ - ['oauth' => []], - ['header' => []], - ['query' => []], - ], $openApi->getSecurity()); - - $paths = $openApi->getPaths(); - $dummiesPath = $paths->getPath('/dummies'); - $this->assertNotNull($dummiesPath); - foreach (['Put', 'Head', 'Trace', 'Delete', 'Options', 'Patch'] as $method) { - $this->assertNull($dummiesPath->{'get'.$method}()); - } - - $this->assertEquals($dummiesPath->getGet(), new Model\Operation( - 'getDummyCollection', - ['Dummy'], - [ - '200' => new Model\Response('Dummy collection', new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject([ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy.OutputDto'], - ]))), - ])), - ], - 'Retrieves the collection of Dummy resources.', - 'Retrieves the collection of Dummy resources.', - null, - [ - new Model\Parameter('page', 'query', 'Test modified collection page number', false, false, true, [ - 'type' => 'integer', - 'default' => 1, - ]), - new Model\Parameter('itemsPerPage', 'query', 'The number of items per page', false, false, true, [ - 'type' => 'integer', - 'default' => 30, - 'minimum' => 0, - ]), - new Model\Parameter('pagination', 'query', 'Enable or disable pagination', false, false, true, [ - 'type' => 'boolean', - ]), - ] - )); - - $this->assertEquals($dummiesPath->getPost(), new Model\Operation( - 'postDummyCollection', - ['Dummy'], - [ - '201' => new Model\Response( - 'Dummy resource created', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto']))), - ]), - null, - new \ArrayObject(['GetDummyItem' => new Model\Link('getDummyItem', new \ArrayObject(['id' => '$response.body#/id']), null, 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.')]) - ), - '400' => new Model\Response('Invalid input'), - '422' => new Model\Response('Unprocessable entity'), - ], - 'Creates a Dummy resource.', - 'Creates a Dummy resource.', - null, - [], - new Model\RequestBody( - 'The new Dummy resource', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Dummy']))), - ]), - true - ) - )); - - $dummyPath = $paths->getPath('/dummies/{id}'); - $this->assertNotNull($dummyPath); - foreach (['Post', 'Head', 'Trace', 'Options', 'Patch'] as $method) { - $this->assertNull($dummyPath->{'get'.$method}()); - } - - $this->assertEquals($dummyPath->getGet(), new Model\Operation( - 'getDummyItem', - ['Dummy'], - [ - '200' => new Model\Response( - 'Dummy resource', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto']))), - ]) - ), - '404' => new Model\Response('Resource not found'), - ], - 'Retrieves a Dummy resource.', - 'Retrieves a Dummy resource.', - null, - [new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])] - )); - - $this->assertEquals($dummyPath->getPut(), new Model\Operation( - 'putDummyItem', - ['Dummy'], - [ - '200' => new Model\Response( - 'Dummy resource updated', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto'])), - ]), - null, - new \ArrayObject(['GetDummyItem' => new Model\Link('getDummyItem', new \ArrayObject(['id' => '$response.body#/id']), null, 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.')]) - ), - '400' => new Model\Response('Invalid input'), - '422' => new Model\Response('Unprocessable entity'), - '404' => new Model\Response('Resource not found'), - ], - 'Replaces the Dummy resource.', - 'Replaces the Dummy resource.', - null, - [new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])], - new Model\RequestBody( - 'The updated Dummy resource', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy'])), - ]), - true - ) - )); - - $this->assertEquals($dummyPath->getDelete(), new Model\Operation( - 'deleteDummyItem', - ['Dummy'], - [ - '204' => new Model\Response('Dummy resource deleted'), - '404' => new Model\Response('Resource not found'), - ], - 'Removes the Dummy resource.', - 'Removes the Dummy resource.', - null, - [new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])] - )); - - $customPath = $paths->getPath('/foo/{id}'); - $this->assertEquals($customPath->getHead(), new Model\Operation( - 'customDummyItem', - ['Dummy', 'Profile'], - [ - '202' => new Model\Response('Success', new \ArrayObject([ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ]), new \ArrayObject([ - 'Foo' => ['description' => 'A nice header', 'schema' => ['type' => 'integer']], - ]), new \ArrayObject([ - 'Foo' => ['$ref' => '#/components/schemas/Dummy'], - ])), - '205' => new Model\Response(), - '404' => new Model\Response('Resource not found'), - ], - 'Dummy', - 'Custom description', - null, - [new Model\Parameter('param', 'path', 'Test parameter', true), new Model\Parameter('id', 'path', 'Replace parameter', true, false, false, ['type' => 'string', 'format' => 'uuid'])], - new Model\RequestBody('Custom request body', new \ArrayObject([ - 'multipart/form-data' => [ - 'schema' => [ - 'type' => 'object', - 'properties' => [ - 'file' => [ - 'type' => 'string', - 'format' => 'binary', - ], - ], - ], - ], - ]), true), - null, - false, - null, - null, - ['x-visibility' => 'hide'] - )); - - $formattedPath = $paths->getPath('/formatted/{id}'); - $this->assertEquals($formattedPath->getPut(), new Model\Operation( - 'formatsDummyItem', - ['Dummy'], - [ - '200' => new Model\Response( - 'Dummy resource updated', - new \ArrayObject([ - 'application/json' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto'])), - 'text/csv' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto'])), - ]), - null, - new \ArrayObject(['GetDummyItem' => new Model\Link('getDummyItem', new \ArrayObject(['id' => '$response.body#/id']), null, 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.')]) - ), - '400' => new Model\Response('Invalid input'), - '422' => new Model\Response('Unprocessable entity'), - '404' => new Model\Response('Resource not found'), - ], - 'Replaces the Dummy resource.', - 'Replaces the Dummy resource.', - null, - [new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])], - new Model\RequestBody( - 'The updated Dummy resource', - new \ArrayObject([ - 'application/json' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy'])), - 'text/csv' => new Model\MediaType(new \ArrayObject(['$ref' => '#/components/schemas/Dummy'])), - ]), - true - ) - )); - - $filteredPath = $paths->getPath('/filtered'); - $this->assertEquals($filteredPath->getGet(), new Model\Operation( - 'filteredDummyCollection', - ['Dummy'], - [ - '200' => new Model\Response('Dummy collection', new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject([ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy.OutputDto'], - ])), - ])), - ], - 'Retrieves the collection of Dummy resources.', - 'Retrieves the collection of Dummy resources.', - null, - [ - new Model\Parameter('page', 'query', 'The collection page number', false, false, true, [ - 'type' => 'integer', - 'default' => 1, - ]), - new Model\Parameter('itemsPerPage', 'query', 'The number of items per page', false, false, true, [ - 'type' => 'integer', - 'default' => 30, - 'minimum' => 0, - ]), - new Model\Parameter('pagination', 'query', 'Enable or disable pagination', false, false, true, [ - 'type' => 'boolean', - ]), - new Model\Parameter('name', 'query', '', true, true, true, [ - 'type' => 'string', - ], 'form', true, true, 'bar'), - new Model\Parameter('ha', 'query', '', false, false, true, [ - 'type' => 'integer', - ]), - new Model\Parameter('toto', 'query', '', true, false, true, [ - 'type' => 'array', - 'items' => ['type' => 'string'], - ], 'deepObject', true), - new Model\Parameter('order[name]', 'query', '', false, false, true, [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ]), - ] - )); - - $paginatedPath = $paths->getPath('/paginated'); - $this->assertEquals($paginatedPath->getGet(), new Model\Operation( - 'paginatedDummyCollection', - ['Dummy'], - [ - '200' => new Model\Response('Dummy collection', new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject([ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy.OutputDto'], - ])), - ])), - ], - 'Retrieves the collection of Dummy resources.', - 'Retrieves the collection of Dummy resources.', - null, - [ - new Model\Parameter('page', 'query', 'The collection page number', false, false, true, [ - 'type' => 'integer', - 'default' => 1, - ]), - new Model\Parameter('itemsPerPage', 'query', 'The number of items per page', false, false, true, [ - 'type' => 'integer', - 'default' => 20, - 'minimum' => 0, - 'maximum' => 80, - ]), - new Model\Parameter('pagination', 'query', 'Enable or disable pagination', false, false, true, [ - 'type' => 'boolean', - ]), - ] - )); - } - - public function testOverrideDocumentation() - { - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - 'delete' => ['method' => 'DELETE'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ], - [] - ); - - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create(Argument::any())->willReturn([]); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Dummy::class])); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate'])); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new CamelCaseToSnakeCaseNameConverter()); - $typeFactory->setSchemaFactory($schemaFactory); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $factory = new OpenApiFactory( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - $filterLocatorProphecy->reveal(), - $subresourceOperationFactoryProphecy->reveal(), - $identifiersExtractorProphecy->reveal(), - [], - new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]), - new PaginationOptions(true, 'page', true, 'itemsPerPage', true, 'pagination') - ); - - $openApi = $factory(['base_url' => '/app_dev.php/']); - - $pathItem = $openApi->getPaths()->getPath('/dummies/{id}'); - $operation = $pathItem->getGet(); - - $openApi->getPaths()->addPath('/dummies/{id}', $pathItem->withGet( - $operation->withParameters(array_merge( - $operation->getParameters(), - [new Model\Parameter('fields', 'query', 'Fields to remove of the output')] - )) - )); - - $openApi = $openApi->withInfo((new Model\Info('New Title', 'v2', 'Description of my custom API'))->withExtensionProperty('info-key', 'Info value')); - $openApi = $openApi->withExtensionProperty('key', 'Custom x-key value'); - $openApi = $openApi->withExtensionProperty('x-value', 'Custom x-value value'); - - $this->assertEquals($openApi->getInfo()->getExtensionProperties(), ['x-info-key' => 'Info value']); - $this->assertEquals($openApi->getExtensionProperties(), ['x-key' => 'Custom x-key value', 'x-value' => 'Custom x-value value']); - } - - public function testSubresourceDocumentation() - { - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Question::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['answer'])); - $propertyNameCollectionFactoryProphecy->create(Answer::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['content'])); - - $questionMetadata = new ResourceMetadata( - 'Question', - 'This is a question.', - 'http://schema.example.com/Question', - ['get' => ['method' => 'GET', 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]]] - ); - $answerMetadata = new ResourceMetadata( - 'Answer', - 'This is an answer.', - 'http://schema.example.com/Answer', - [], - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS], - [], - ['get' => ['method' => 'GET', 'input_formats' => ['xml' => ['text/xml']], 'output_formats' => ['xml' => ['text/xml']]]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Question::class)->shouldBeCalled()->willReturn($questionMetadata); - $resourceMetadataFactoryProphecy->create(Answer::class)->shouldBeCalled()->willReturn($answerMetadata); - - $subresourceMetadata = new SubresourceMetadata(Answer::class, false); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Question::class, 'answer', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [], $subresourceMetadata)); - - $propertyMetadataFactoryProphecy->create(Answer::class, 'content', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $routeCollection = new RouteCollection(); - $routeCollection->add('api_answers_get_collection', new Route('/api/answers.{_format}')); - $routeCollection->add('api_questions_answer_get_subresource', new Route('/api/questions/{id}/answer.{_format}')); - $routeCollection->add('api_questions_get_item', new Route('/api/questions/{id}.{_format}')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->shouldBeCalled()->willReturn($routeCollection); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()))); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - $identifiersExtractor = $identifiersExtractorProphecy->reveal(); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new UnderscorePathSegmentNameGenerator(), $identifiersExtractor); - - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Question::class, Answer::class])); - - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new CamelCaseToSnakeCaseNameConverter()); - $typeFactory->setSchemaFactory($schemaFactory); - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - - $factory = new OpenApiFactory( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - $filterLocatorProphecy->reveal(), - $subresourceOperationFactory, - $identifiersExtractor, - ['jsonld' => ['application/ld+json']], - new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]), - new PaginationOptions(true, 'page', true, 'itemsPerPage', true, 'pagination') - ); - - $openApi = $factory(['base_url', '/app_dev.php/']); - - $paths = $openApi->getPaths(); - $pathItem = $paths->getPath('/api/questions/{id}/answer'); - - $this->assertEquals($pathItem->getGet(), new Model\Operation( - 'api_questions_answer_get_subresourceQuestionSubresource', - ['Answer', 'Question'], - [ - '200' => new Model\Response( - 'Question resource', - new \ArrayObject([ - 'application/ld+json' => new Model\MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Answer']))), - ]) - ), - ], - 'Retrieves a Question resource.', - 'Retrieves a Question resource.', - null, - [new Model\Parameter('id', 'path', 'Question identifier', true, false, false, ['type' => 'string'])] - )); - - $encoders = [new JsonEncoder()]; - $normalizers = [new ObjectNormalizer()]; - - $serializer = new Serializer($normalizers, $encoders); - $normalizers[0]->setSerializer($serializer); - - // Call the normalizer to see if everything is smooth - $normalizer = new OpenApiNormalizer($normalizers[0]); - $normalizer->normalize($openApi); - } - - public function testResetPathItem() - { - $pathItem = new Model\PathItem( - null, - '', - '', - new Model\Operation(), - new Model\Operation(), - new Model\Operation(), - new Model\Operation(), - new Model\Operation() - ); - - $this->assertNull($pathItem->withGet(null)->getGet()); - $this->assertNull($pathItem->withDelete(null)->getDelete()); - $this->assertNull($pathItem->withPost(null)->getPost()); - $this->assertNull($pathItem->withPut(null)->getPut()); - $this->assertNull($pathItem->withPatch(null)->getPatch()); - } -} diff --git a/tests/Core/Operation/DashedPathSegmentNameGeneratorTest.php b/tests/Core/Operation/DashedPathSegmentNameGeneratorTest.php deleted file mode 100644 index 40aa614f96a..00000000000 --- a/tests/Core/Operation/DashedPathSegmentNameGeneratorTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * 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\Operation; - -use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator; -use PHPUnit\Framework\TestCase; - -class DashedPathSegmentNameGeneratorTest extends TestCase -{ - public function testCreateSegmentNameGeneration() - { - $generator = new DashPathSegmentNameGenerator(); - $this->assertSame('ordering-people', $generator->getSegmentName('orderingPerson')); - $this->assertSame('some-person-names', $generator->getSegmentName('somePersonName')); - } -} diff --git a/tests/Core/Operation/Factory/CachedSubresourceOperationFactoryTest.php b/tests/Core/Operation/Factory/CachedSubresourceOperationFactoryTest.php deleted file mode 100644 index 6e0d826ad71..00000000000 --- a/tests/Core/Operation/Factory/CachedSubresourceOperationFactoryTest.php +++ /dev/null @@ -1,92 +0,0 @@ - - * - * 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\Operation\Factory; - -use ApiPlatform\Core\Operation\Factory\CachedSubresourceOperationFactory; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; - -/** - * @author Antoine Bluchet - */ -class CachedSubresourceOperationFactoryTest extends TestCase -{ - use ProphecyTrait; - - public function testCreateWithItemHit() - { - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(true)->shouldBeCalledTimes(1); - $cacheItem->get()->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalledTimes(1); - - $decoratedSubresourceOperationFactory = $this->prophesize(SubresourceOperationFactoryInterface::class); - $decoratedSubresourceOperationFactory->create()->shouldNotBeCalled(); - - $cachedSubresourceOperationFactory = new CachedSubresourceOperationFactory($cacheItemPool->reveal(), $decoratedSubresourceOperationFactory->reveal()); - - $expectedResult = ['foo' => 'bar']; - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class)); - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class), 'Trigger the local cache'); - } - - public function testCreateWithItemNotHit() - { - $cacheItem = $this->prophesize(CacheItemInterface::class); - $cacheItem->isHit()->willReturn(false)->shouldBeCalledTimes(1); - $cacheItem->set(['foo' => 'bar'])->willReturn($cacheItem->reveal())->shouldBeCalledTimes(1); - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willReturn($cacheItem->reveal())->shouldBeCalledTimes(1); - $cacheItemPool->save($cacheItem->reveal())->willReturn(true)->shouldBeCalledTimes(1); - - $decoratedSubresourceOperationFactory = $this->prophesize(SubresourceOperationFactoryInterface::class); - $decoratedSubresourceOperationFactory->create(Dummy::class)->shouldBeCalledTimes(1)->willReturn(['foo' => 'bar']); - - $cachedSubresourceOperationFactory = new CachedSubresourceOperationFactory($cacheItemPool->reveal(), $decoratedSubresourceOperationFactory->reveal()); - - $expectedResult = ['foo' => 'bar']; - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class)); - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class), 'Trigger the local cache'); - } - - public function testCreateWithGetCacheItemThrowsCacheException() - { - $cacheException = new class() extends \Exception implements CacheException {}; - - $cacheItemPool = $this->prophesize(CacheItemPoolInterface::class); - $cacheItemPool->getItem($this->generateCacheKey())->willThrow($cacheException)->shouldBeCalledTimes(1); - - $decoratedSubresourceOperationFactory = $this->prophesize(SubresourceOperationFactoryInterface::class); - $decoratedSubresourceOperationFactory->create(Dummy::class)->shouldBeCalledTimes(1)->willReturn(['foo' => 'bar']); - - $cachedSubresourceOperationFactory = new CachedSubresourceOperationFactory($cacheItemPool->reveal(), $decoratedSubresourceOperationFactory->reveal()); - - $expectedResult = ['foo' => 'bar']; - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class)); - $this->assertEquals($expectedResult, $cachedSubresourceOperationFactory->create(Dummy::class), 'Trigger the local cache'); - } - - private function generateCacheKey(string $resourceClass = Dummy::class) - { - return CachedSubresourceOperationFactory::CACHE_KEY_PREFIX.md5($resourceClass); - } -} diff --git a/tests/Core/Operation/Factory/SubresourceOperationFactoryTest.php b/tests/Core/Operation/Factory/SubresourceOperationFactoryTest.php deleted file mode 100644 index 2974f30be05..00000000000 --- a/tests/Core/Operation/Factory/SubresourceOperationFactoryTest.php +++ /dev/null @@ -1,988 +0,0 @@ - - * - * 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\Operation\Factory; - -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Operation\PathSegmentNameGeneratorInterface; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use ApiPlatform\Tests\Fixtures\DummyValidatedEntity; -use ApiPlatform\Tests\Fixtures\RelatedDummyEntity; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -/** - * @author Antoine Bluchet - * @group legacy - */ -class SubresourceOperationFactoryTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public function testCreate() - { - $this->expectDeprecation('Since api-platform/core 2.7: A subresource is declared on "ApiPlatform\Tests\Fixtures\DummyEntity::subresource". Subresources are deprecated, use another #[ApiResource] instead.'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo', 'subresource', 'subcollection'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - - $subresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class)); - $subresourceMetadataCollection = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, true)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'foo', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadata); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subcollection', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollection); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subcollection', true)->shouldBeCalled()->willReturn('subcollections'); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('anotherSubresource', false)->shouldBeCalled()->willReturn('another_subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $pathSegmentNameGeneratorProphecy->reveal(), $identifiersExtractorProphecy->reveal()); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_another_subresource_get_subresource' => [ - 'property' => 'anotherSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_another_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/another_subresource.{_format}', - 'operation_name' => 'subresource_another_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_another_subresource_subcollections_get_subresource' => [ - 'property' => 'subcollection', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', false], - 'anotherSubresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_another_subresource_subcollections_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/another_subresource/subcollections.{_format}', - 'operation_name' => 'subresource_another_subresource_subcollections_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_get_subresource' => [ - 'property' => 'subcollection', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subcollections_get_subresource', - 'path' => '/dummy_entities/{id}/subcollections.{_format}', - 'operation_name' => 'subcollections_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_another_subresource_get_subresource' => [ - 'property' => 'anotherSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subcollection' => [RelatedDummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subcollections_another_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subcollections/{subcollection}/another_subresource.{_format}', - 'operation_name' => 'subcollections_another_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_another_subresource_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subcollection' => [RelatedDummyEntity::class, 'id', true], - 'anotherSubresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subcollections_another_subresource_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subcollections/{subcollection}/another_subresource/subresource.{_format}', - 'operation_name' => 'subcollections_another_subresource_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateByOverriding() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn((new ResourceMetadata('dummyEntity'))->withSubresourceOperations([ - 'subcollections_get_subresource' => [ - 'path' => '/dummy_entities/{id}/foobars', - ], - 'subcollections_another_subresource_get_subresource' => [ - 'path' => '/dummy_entities/{id}/foobars/{subcollection}/another_foobar.{_format}', - ], - ])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo', 'subresource', 'subcollection'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - - $subresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class)); - $subresourceMetadataCollection = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, true)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'foo', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadata); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subcollection', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollection); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subcollection', true)->shouldBeCalled()->willReturn('subcollections'); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('anotherSubresource', false)->shouldBeCalled()->willReturn('another_subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $pathSegmentNameGeneratorProphecy->reveal(), $identifiersExtractorProphecy->reveal()); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_another_subresource_get_subresource' => [ - 'property' => 'anotherSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_another_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/another_subresource.{_format}', - 'operation_name' => 'subresource_another_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_another_subresource_subcollections_get_subresource' => [ - 'property' => 'subcollection', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', false], - 'anotherSubresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_another_subresource_subcollections_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/another_subresource/subcollections.{_format}', - 'operation_name' => 'subresource_another_subresource_subcollections_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_get_subresource' => [ - 'property' => 'subcollection', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subcollections_get_subresource', - 'path' => '/dummy_entities/{id}/foobars', - 'operation_name' => 'subcollections_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_another_subresource_get_subresource' => [ - 'property' => 'anotherSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subcollection' => [RelatedDummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subcollections_another_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/foobars/{subcollection}/another_foobar.{_format}', - 'operation_name' => 'subcollections_another_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subcollections_another_subresource_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subcollection' => [RelatedDummyEntity::class, 'id', true], - 'anotherSubresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subcollections_another_subresource_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/foobars/{subcollection}/another_foobar/subresource.{_format}', - 'operation_name' => 'subcollections_another_subresource_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateWithMaxDepth() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - - $subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - /** - * Test for issue: https://github.com/api-platform/core/issues/1711. - */ - public function testCreateWithMaxDepthMultipleSubresources() - { - /** - * DummyEntity -subresource-> RelatedDummyEntity -anotherSubresource-> DummyEntity - * DummyEntity -secondSubresource-> dummyValidatedEntity -moreSubresource-> RelatedDummyEntity. - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyValidatedEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - $propertyNameCollectionFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['moreSubresource'])); - - $subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - $secondSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyValidatedEntity::class, false, 2)); - $moreSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'secondSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($secondSubresourceMetadata); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - $propertyMetadataFactoryProphecy->create(DummyValidatedEntity::class, 'moreSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($moreSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('secondSubresource', false)->shouldBeCalled()->willReturn('second_subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('moreSubresource', false)->shouldBeCalled()->willReturn('mode_subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_second_subresource_get_subresource' => [ - 'property' => 'secondSubresource', - 'collection' => false, - 'resource_class' => DummyValidatedEntity::class, - 'shortNames' => ['dummyValidatedEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_second_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/second_subresources.{_format}', - 'operation_name' => 'second_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_second_subresource_more_subresource_get_subresource' => [ - 'property' => 'moreSubresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyValidatedEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'secondSubresource' => [DummyValidatedEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_second_subresource_more_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/second_subresources/mode_subresources.{_format}', - 'operation_name' => 'second_subresource_more_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - /** - * Test for issue: https://github.com/api-platform/core/issues/2103. - */ - public function testCreateWithMaxDepthMultipleSubresourcesSameMaxDepth() - { - /** - * DummyEntity -subresource (maxDepth=1)-> RelatedDummyEntity -anotherSubresource-> DummyEntity - * DummyEntity -secondSubresource (maxDepth=1)-> dummyValidatedEntity -moreSubresource-> RelatedDummyEntity. - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyValidatedEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - $propertyNameCollectionFactoryProphecy->create(DummyValidatedEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['moreSubresource'])); - - $subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1)); - $secondSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyValidatedEntity::class, false, 1)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - $moreSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'secondSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($secondSubresourceMetadata); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - $propertyMetadataFactoryProphecy->create(DummyValidatedEntity::class, 'moreSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($moreSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('secondSubresource', false)->shouldBeCalled()->willReturn('second_subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_second_subresource_get_subresource' => [ - 'property' => 'secondSubresource', - 'collection' => false, - 'resource_class' => DummyValidatedEntity::class, - 'shortNames' => ['dummyValidatedEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_second_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/second_subresources.{_format}', - 'operation_name' => 'second_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateSelfReferencingSubresources() - { - /** - * DummyEntity -subresource-> DummyEntity --> DummyEntity ... - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - - $subresource = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresource); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - /** - * Test for issue: https://github.com/api-platform/core/issues/2533. - */ - public function testCreateWithDifferentMaxDepthSelfReferencingSubresources() - { - /** - * subresource: maxDepth = 2 - * secondSubresource: maxDepth = 1 - * DummyEntity -subresource-> DummyEntity -secondSubresource-> DummyEntity ... - * DummyEntity -secondSubresource-> DummyEntity !!!-subresource-> DummyEntity ... - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'secondSubresource'])); - - $subresourceWithMaxDepthMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false, 2)); - $secondSubresourceWithMaxDepthMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false, 1)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceWithMaxDepthMetadata); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'secondSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($secondSubresourceWithMaxDepthMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('secondSubresource', false)->shouldBeCalled()->willReturn('second_subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresource_second_subresource_get_subresource' => [ - 'property' => 'secondSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [DummyEntity::class, 'id', false], - ], - 'route_name' => 'api_dummy_entities_subresource_second_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources/second_subresources.{_format}', - 'operation_name' => 'subresource_second_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_second_subresource_get_subresource' => [ - 'property' => 'secondSubresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_second_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/second_subresources.{_format}', - 'operation_name' => 'second_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateWithEnd() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['id'])); - - $subresourceMetadataCollection = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, true)); - $identifierSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false))->withIdentifier(true); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollection); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'id', Argument::type('array'))->shouldBeCalled()->willReturn($identifierSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', true)->shouldBeCalled()->willReturn('subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $result = $subresourceOperationFactory->create(DummyEntity::class); - $this->assertEquals([ - 'api_dummy_entities_subresources_get_subresource' => [ - 'property' => 'subresource', - 'collection' => true, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresources_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresources_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_subresources_item_get_subresource' => [ - 'property' => 'id', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity', 'relatedDummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - 'subresource' => [RelatedDummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresources_item_get_subresource', - 'path' => '/dummy_entities/{id}/subresource/{subresource}.{_format}', - 'operation_name' => 'subresources_item_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $result); - } - - public function testCreateWithEndButNoCollection() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['id'])); - - $subresourceMetadataCollection = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - $identifierSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false))->withIdentifier(true); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollection); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'id', Argument::type('array'))->shouldBeCalled()->willReturn($identifierSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $result = $subresourceOperationFactory->create(DummyEntity::class); - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $result); - } - - public function testCreateWithRootResourcePrefix() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity', null, null, null, null, ['route_prefix' => 'root_resource_prefix'])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['bar', 'anotherSubresource'])); - - $subresourceMetadataCollectionWithMaxDepth = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false, 1)); - $anotherSubresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadataCollectionWithMaxDepth); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'bar', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyMetadata()); - $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'anotherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($anotherSubresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresource'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/root_resource_prefix/dummy_entities/{id}/subresource.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateSelfReferencingSubresourcesWithSubresources() - { - /** - * DummyEntity -otherSubresource-> RelatedDummyEntity - * DummyEntity -subresource (maxDepth=1) -> DummyEntity -otherSubresource-> RelatedDummyEntity. - */ - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('dummyEntity')); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource', 'otherSubresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection([])); - - $subresource = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(DummyEntity::class, false, 1)); - $otherSubresourceSubresource = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresource); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'otherSubresource', Argument::type('array'))->shouldBeCalled()->willReturn($otherSubresourceSubresource); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - $pathSegmentNameGeneratorProphecy->getSegmentName('otherSubresource', false)->shouldBeCalled()->willReturn('other_subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => DummyEntity::class, - 'shortNames' => ['dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - 'api_dummy_entities_other_subresource_get_subresource' => [ - 'property' => 'otherSubresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_other_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/other_subresources.{_format}', - 'operation_name' => 'other_subresource_get_subresource', - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } - - public function testCreateWithOpenapiContext() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummyEntity')); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn((new ResourceMetadata('dummyEntity'))->withSubresourceOperations([ - 'subresource_get_subresource' => [ - 'openapi_context' => [ - 'summary' => 'Get related dummy entities', - 'tags' => ['Dummy'], - ], - ], - ])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['subresource'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummyEntity::class)->shouldBeCalled()->willReturn(new PropertyNameCollection([])); - - $subresourceMetadata = (new PropertyMetadata())->withSubresource(new SubresourceMetadata(RelatedDummyEntity::class, false)); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'subresource', Argument::type('array'))->shouldBeCalled()->willReturn($subresourceMetadata); - - $pathSegmentNameGeneratorProphecy = $this->prophesize(PathSegmentNameGeneratorInterface::class); - $pathSegmentNameGeneratorProphecy->getSegmentName('dummyEntity')->shouldBeCalled()->willReturn('dummy_entities'); - $pathSegmentNameGeneratorProphecy->getSegmentName('subresource', false)->shouldBeCalled()->willReturn('subresources'); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $pathSegmentNameGeneratorProphecy->reveal(), - $identifiersExtractorProphecy->reveal() - ); - - $this->assertEquals([ - 'api_dummy_entities_subresource_get_subresource' => [ - 'property' => 'subresource', - 'collection' => false, - 'resource_class' => RelatedDummyEntity::class, - 'shortNames' => ['relatedDummyEntity', 'dummyEntity'], - 'identifiers' => [ - 'id' => [DummyEntity::class, 'id', true], - ], - 'route_name' => 'api_dummy_entities_subresource_get_subresource', - 'path' => '/dummy_entities/{id}/subresources.{_format}', - 'operation_name' => 'subresource_get_subresource', - 'openapi_context' => [ - 'summary' => 'Get related dummy entities', - 'tags' => ['Dummy'], - ], - 'legacy_filters' => [], - 'legacy_normalization_context' => [], - 'legacy_type' => null, - ] + SubresourceOperationFactory::ROUTE_OPTIONS, - ], $subresourceOperationFactory->create(DummyEntity::class)); - } -} diff --git a/tests/Core/PathResolver/DashOperationPathResolverTest.php b/tests/Core/PathResolver/DashOperationPathResolverTest.php deleted file mode 100644 index d789228c847..00000000000 --- a/tests/Core/PathResolver/DashOperationPathResolverTest.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * 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\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\PathResolver\DashOperationPathResolver; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; - -/** - * @author Guilhem N. - * - * @group legacy - */ -class DashOperationPathResolverTest extends TestCase -{ - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\DashOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator instead. - */ - public function testResolveCollectionOperationPath() - { - $dashOperationPathResolver = new DashOperationPathResolver(); - - $this->assertSame('/short-names.{_format}', $dashOperationPathResolver->resolveOperationPath('ShortName', [], OperationType::COLLECTION, 'get')); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\DashOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator instead. - */ - public function testResolveItemOperationPath() - { - $dashOperationPathResolver = new DashOperationPathResolver(); - - $this->assertSame('/short-names/{id}.{_format}', $dashOperationPathResolver->resolveOperationPath('ShortName', [], OperationType::ITEM, 'get')); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\DashOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator instead. - */ - public function testResolveSubresourceOperationPath() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Subresource operations are not supported by the OperationPathResolver.'); - - $dashOperationPathResolver = new DashOperationPathResolver(); - - $dashOperationPathResolver->resolveOperationPath('ShortName', ['property' => 'bar', 'identifiers' => [['id', 'class'], ['relatedId', 'class']], 'collection' => false], OperationType::SUBRESOURCE, 'get'); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\DashOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\DashPathSegmentNameGenerator instead. - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testLegacyResolveOperationPath() - { - $dashOperationPathResolver = new DashOperationPathResolver(); - - $this->assertSame('/short-names.{_format}', $dashOperationPathResolver->resolveOperationPath('ShortName', [], true)); - } -} diff --git a/tests/Core/PathResolver/UnderscoreOperationPathResolverTest.php b/tests/Core/PathResolver/UnderscoreOperationPathResolverTest.php deleted file mode 100644 index 0c7a5df2a84..00000000000 --- a/tests/Core/PathResolver/UnderscoreOperationPathResolverTest.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * 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\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver; -use ApiPlatform\Exception\InvalidArgumentException; -use PHPUnit\Framework\TestCase; - -/** - * @author Guilhem N. - * - * @group legacy - */ -class UnderscoreOperationPathResolverTest extends TestCase -{ - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator instead. - */ - public function testResolveCollectionOperationPath() - { - $underscoreOperationPathResolver = new UnderscoreOperationPathResolver(); - - $this->assertSame('/short_names.{_format}', $underscoreOperationPathResolver->resolveOperationPath('ShortName', [], OperationType::COLLECTION, 'get')); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator instead. - */ - public function testResolveItemOperationPath() - { - $underscoreOperationPathResolver = new UnderscoreOperationPathResolver(); - - $this->assertSame('/short_names/{id}.{_format}', $underscoreOperationPathResolver->resolveOperationPath('ShortName', [], OperationType::ITEM, 'get')); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator instead. - */ - public function testResolveSubresourceOperationPath() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Subresource operations are not supported by the OperationPathResolver.'); - - $dashOperationPathResolver = new UnderscoreOperationPathResolver(); - - $dashOperationPathResolver->resolveOperationPath('ShortName', ['property' => 'relatedFoo', 'identifiers' => [['id', 'class']], 'collection' => true], OperationType::SUBRESOURCE, 'get'); - } - - /** - * @expectedDeprecation The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator instead. - * @expectedDeprecation Using a boolean for the Operation Type is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3 - */ - public function testLegacyResolveOperationPath() - { - $underscoreOperationPathResolver = new UnderscoreOperationPathResolver(); - - $this->assertSame('/short_names.{_format}', $underscoreOperationPathResolver->resolveOperationPath('ShortName', [], true)); - } -} diff --git a/tests/Core/ProphecyTrait.php b/tests/Core/ProphecyTrait.php deleted file mode 100644 index e9058776377..00000000000 --- a/tests/Core/ProphecyTrait.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - * 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; - -use PHPUnit\Framework\AssertionFailedError; -use PHPUnit\Framework\TestCase; -use Prophecy\Exception\Doubler\DoubleException; -use Prophecy\Exception\Doubler\InterfaceNotFoundException; -use Prophecy\Exception\Prediction\PredictionException; -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Prophecy\ObjectProphecy; -use Prophecy\Prophet; - -/** - * Copied and adapted from phpspec/prophecy-phpunit. - * To replace by the official package when we'll drop support for PHP 7.1. - * - * @see https://github.com/phpspec/prophecy-phpunit - * - * @copyright Christophe Coevoet - * @author Christophe Coevoet - * @mixin TestCase - */ -trait ProphecyTrait -{ - /** - * @var Prophet|null - * - * @internal - */ - private $prophet; - - /** - * @var bool - * - * @internal - */ - private $prophecyAssertionsCounted = false; - - /** - * @psalm-param class-string|null $classOrInterface - * - * @param mixed|null $classOrInterface - * - * @throws DoubleException - * @throws InterfaceNotFoundException - */ - protected function prophesize($classOrInterface = null): ObjectProphecy - { - if ( - \is_string($classOrInterface) && - \is_callable([$this, 'recordDoubledType']) // Support for PHPUnit 7 - ) { - \assert($this instanceof TestCase); - $this->recordDoubledType($classOrInterface); - } - - return $this->getProphet()->prophesize($classOrInterface); - } - - /** - * @postCondition - * @after - */ - protected function verifyProphecyDoubles(): void - { - if (null === $this->prophet) { - return; - } - - try { - $this->prophet->checkPredictions(); - } catch (PredictionException $e) { - throw new AssertionFailedError($e->getMessage()); - } finally { - $this->countProphecyAssertions(); - } - } - - /** - * @after - */ - protected function tearDownProphecy(): void - { - if (null !== $this->prophet && !$this->prophecyAssertionsCounted) { - // Some Prophecy assertions may have been done in tests themselves even when a failure happened before checking mock objects. - $this->countProphecyAssertions(); - } - - $this->prophet = null; - } - - /** - * @internal - */ - private function countProphecyAssertions(): void - { - \assert($this instanceof TestCase); - $this->prophecyAssertionsCounted = true; - - foreach ($this->prophet->getProphecies() as $objectProphecy) { - /** @var MethodProphecy[] $methodProphecies */ - foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) { - foreach ($methodProphecies as $methodProphecy) { - \assert($methodProphecy instanceof MethodProphecy); - - $this->addToAssertionCount(\count($methodProphecy->getCheckedPredictions())); - } - } - } - } - - /** - * @internal - */ - private function getProphet(): Prophet - { - if (null === $this->prophet) { - $this->prophet = new Prophet(); - } - - return $this->prophet; - } -} diff --git a/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php b/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php deleted file mode 100644 index f4c5848d31a..00000000000 --- a/tests/Core/Swagger/Serializer/DocumentationNormalizerV2Test.php +++ /dev/null @@ -1,3483 +0,0 @@ - - * - * 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\Swagger\Serializer; - -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver; -use ApiPlatform\Core\JsonSchema\SchemaFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\JsonSchema\TypeFactory; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use ApiPlatform\Tests\Fixtures\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPropertyWithDefaultValue; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; - -/** - * @author Amrouche Hamza - * @author Kévin Dunglas - * @group legacy - */ -class DocumentationNormalizerV2Test extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - private const OPERATION_FORMATS = [ - 'input_formats' => ['jsonld' => ['application/ld+json']], - 'output_formats' => ['jsonld' => ['application/ld+json']], - ]; - - /** - * @group legacy - */ - public function testLegacyConstruct(): void - { - $this->expectDeprecation('Passing an instance of ApiPlatform\Core\Api\UrlGeneratorInterface to ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer::__construct() is deprecated since version 2.1 and will be removed in 3.0.'); - - $normalizer = new DocumentationNormalizer( - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - $this->prophesize(OperationMethodResolverInterface::class)->reveal(), - $this->prophesize(OperationPathResolverInterface::class)->reveal(), - $this->prophesize(UrlGeneratorInterface::class)->reveal() - ); - - $this->assertInstanceOf(DocumentationNormalizer::class, $normalizer); - } - - public function testNormalize(): void - { - $this->doTestNormalize(); - } - - public function testLegacyNormalize(): void - { - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET'); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'put')->willReturn('PUT'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'post')->willReturn('POST'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'custom')->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'custom2')->willReturn('POST'); - - $this->doTestNormalize($operationMethodResolverProphecy->reveal()); - } - - private function doTestNormalize(OperationMethodResolverInterface $operationMethodResolver = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET', 'status' => '202'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'status' => '202'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET', 'status' => '202'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST', 'status' => '202'] + self::OPERATION_FORMATS, - 'custom' => ['method' => 'GET', 'path' => '/foo', 'status' => '202'] + self::OPERATION_FORMATS, - 'custom2' => ['method' => 'POST', 'path' => '/foo'] + self::OPERATION_FORMATS, - ], - ['pagination_client_items_per_page' => true, 'normalization_context' => [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTimeInterface::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - $operationMethodResolver, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/foo' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'customDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'custom2DummyCollection', - 'produces' => ['application/ld+json'], - 'consumes' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'additionalProperties' => false, - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'description' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is an initializable but not writable property.', - ]), - 'dummyDate' => new \ArrayObject([ - 'type' => 'string', - 'format' => 'date-time', - 'description' => 'This is a \DateTimeInterface object.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithNameConverter(): void - { - $this->doTestNormalizeWithNameConverter(); - } - - public function testLegacyNormalizeWithNameConverter(): void - { - $this->doTestNormalizeWithNameConverter(true); - } - - private function doTestNormalizeWithNameConverter(bool $legacy = false): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Dummy API', 'This is a dummy API', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name', 'nameConverted'])); - - $dummyMetadata = new ResourceMetadata('Dummy', 'This is a dummy.', null, ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, null, null, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'nameConverted', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a converted name.', true, true, null, null, false)); - - if (interface_exists(AdvancedNameConverterInterface::class)) { - $nameConverter = $this->createMock(AdvancedNameConverterInterface::class); - } else { - $nameConverter = $this->createMock(NameConverterInterface::class); - } - - $nameConverter->method('normalize') - ->with(self::logicalOr('name', 'nameConverted')) - ->willReturnCallback(static function (string $nameToNormalize): string { - return 'nameConverted' === $nameToNormalize - ? 'name_converted' - : $nameToNormalize; - }); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $typeFactory = null; - $schemaFactory = null; - - if (!$legacy) { - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $nameConverter); - $typeFactory->setSchemaFactory($schemaFactory); - } - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $schemaFactory, - $typeFactory, - $operationPathResolver, - null, - null, - $legacy ? $nameConverter : null, - true, - 'oauth2', - 'application', - '/oauth/v2/token', - '/oauth/v2/auth', - ['scope param'], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Dummy API', - 'description' => 'This is a dummy API', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'name_converted' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a converted name.', - ]), - ], - ]), - ]), - 'securityDefinitions' => [ - 'oauth' => [ - 'type' => 'oauth2', - 'description' => 'OAuth 2.0 application Grant', - 'flow' => 'application', - 'tokenUrl' => '/oauth/v2/token', - 'authorizationUrl' => '/oauth/v2/auth', - 'scopes' => new \ArrayObject(['scope param']), - ], - ], - 'security' => [['oauth' => []]], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithApiKeysEnabled(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata('Dummy', 'This is a dummy.', null, ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, null, null, false)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $apiKeysConfiguration = [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]; - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - $apiKeysConfiguration, - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - 'securityDefinitions' => [ - 'header' => [ - 'type' => 'apiKey', - 'in' => 'header', - 'description' => 'Value for the Authorization header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'apiKey', - 'in' => 'query', - 'description' => 'Value for the key query parameter', - 'name' => 'key', - ], - ], - 'security' => [ - ['header' => []], - ['query' => []], - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithOnlyNormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - - $ref = 'Dummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/'.$ref], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeNotAddExtraBodyParameters(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - - $ref = 'Dummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => [ - 'method' => 'POST', - 'swagger_context' => [ - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new custom Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new custom Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/'.$ref], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithSwaggerDefinitionName(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => [ - 'method' => 'GET', - 'normalization_context' => [ - DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'Read', - ], - ] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy-Read'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy-Read' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithOnlyDenormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', ['dummy']) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => 'dummy']] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy-dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - 'Dummy-dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithNormalizationAndDenormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', ['dummy']) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => [ - 'method' => 'PUT', - 'normalization_context' => [AbstractNormalizer::GROUPS => 'dummy'], 'denormalization_context' => [AbstractNormalizer::GROUPS => 'dummy'], - ] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy-dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy-dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - 'Dummy-dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeSkipsNotReadableAndNotWritableProperties(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'dummy', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET', 'status' => '202'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'status' => '202'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET', 'status' => '202'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST', 'status' => '202'] + self::OPERATION_FORMATS, - ], - ['pagination_client_items_per_page' => true] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), null, false, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummy', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a public id.', true, false, true, true, false, true, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 202 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'dummy' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a public id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testFilters(): void - { - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filters = [ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'swagger' => ['x-foo' => 'bar'], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - ]; - - foreach ($filters as $filterId => $filter) { - $filterLocatorProphecy->has($filterId)->willReturn(true); - $filterLocatorProphecy->get($filterId)->willReturn($filter); - } - - $filterLocatorProphecy->has('f4')->willReturn(false); - - $this->doTestNormalizeWithFilters($filterLocatorProphecy->reveal()); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testFiltersWithDeprecatedFilterCollection(): void - { - $this->doTestNormalizeWithFilters(new FilterCollection([ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'swagger' => ['x-foo' => 'bar'], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - ])); - } - - public function testConstructWithInvalidFilterLocator(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface or null.'); - - new DocumentationNormalizer( - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), - null, - null, - $this->prophesize(OperationPathResolverInterface::class)->reveal(), - null, - new \ArrayObject(), - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $this->prophesize(IdentifiersExtractorInterface::class)->reveal() - ); - } - - public function testSupports(): void - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $this->assertTrue($normalizer->supportsNormalization($documentation, 'json')); - $this->assertFalse($normalizer->supportsNormalization($documentation)); - $this->assertFalse($normalizer->supportsNormalization(new Dummy(), 'json')); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - - public function testNormalizeWithNoOperations(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->shouldNotBeCalled(); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.' - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name')->shouldNotBeCalled(); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithCustomMethod(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - ['get' => ['method' => 'FOO']] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'foo' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - ]), - ], - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithNestedNormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - $ref = 'Dummy-'.implode('_', $groups); - $relatedDummyRef = 'RelatedDummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['name', 'relatedDummy', 'relatedDummyWithCustomOpenApiContextType'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - - $relatedDummyMetadata = new ResourceMetadata( - 'RelatedDummy', - 'This is a related dummy.', - 'http://schema.example.com/RelatedDummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - ] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class), 'This is a related dummy \o/.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummyWithCustomOpenApiContextType', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class), 'This is a related dummy with type string \o/.', true, true, true, true, false, false, null, null, ['swagger_context' => ['type' => 'string']])); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [[ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ]], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ]], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/'.$ref], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'relatedDummy' => new \ArrayObject([ - 'description' => 'This is a related dummy \o/.', - '$ref' => '#/definitions/'.$relatedDummyRef, - ]), - 'relatedDummyWithCustomOpenApiContextType' => new \ArrayObject([ - 'description' => 'This is a related dummy with type string \o/.', - 'type' => 'string', - ]), - ], - ]), - $relatedDummyRef => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a related dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/RelatedDummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - private function doTestNormalizeWithFilters($filterLocator): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - ['get' => ['method' => 'GET', 'filters' => ['f1', 'f2', 'f3', 'f4']] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - $filterLocator, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - 'parameters' => [ - [ - 'x-foo' => 'bar', - 'name' => 'name', - 'in' => 'query', - 'required' => true, - 'type' => 'string', - ], - [ - 'name' => 'ha', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - ], - [ - 'name' => 'toto', - 'in' => 'query', - 'required' => true, - 'type' => 'array', - 'items' => [ - 'type' => 'string', - ], - 'collectionFormat' => 'csv', - ], - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'description' => 'This is a name.', - 'type' => 'string', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithSubResource(): void - { - $this->doTestNormalizeWithSubResource(); - } - - public function testLegacyNormalizeWithSubResource(): void - { - $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class); - $formatProviderProphecy->getFormatsFromOperation(Question::class, 'get', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]); - $formatProviderProphecy->getFormatsFromOperation(Answer::class, 'get', OperationType::SUBRESOURCE)->willReturn(['xml' => ['text/xml']]); - - $this->doTestNormalizeWithSubResource($formatProviderProphecy->reveal()); - } - - private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInterface $formatsProvider = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Question::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Question::class, Argument::cetera())->willReturn(new PropertyNameCollection(['answer'])); - $propertyNameCollectionFactoryProphecy->create(Answer::class, Argument::cetera())->willReturn(new PropertyNameCollection(['content'])); - - $questionMetadata = new ResourceMetadata( - 'Question', - 'This is a question.', - 'http://schema.example.com/Question', - ['get' => ['method' => 'GET', 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]]] - ); - $answerMetadata = new ResourceMetadata( - 'Answer', - 'This is an answer.', - 'http://schema.example.com/Answer', - [], - ['get' => ['method' => 'GET']] + self::OPERATION_FORMATS, - [], - ['get' => ['method' => 'GET', 'input_formats' => ['xml' => ['text/xml']], 'output_formats' => ['xml' => ['text/xml']]]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Question::class)->willReturn($questionMetadata); - $resourceMetadataFactoryProphecy->create(Answer::class)->willReturn($answerMetadata); - - $subresourceMetadata = new SubresourceMetadata(Answer::class, false); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Question::class, 'answer', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [], $subresourceMetadata)); - $propertyMetadataFactoryProphecy->create(Answer::class, 'content', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $routeCollection = new RouteCollection(); - $routeCollection->add('api_questions_answer_get_subresource', new Route('/api/questions/{id}/answer.{_format}')); - $routeCollection->add('api_questions_get_item', new Route('/api/questions/{id}.{_format}')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()))); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new UnderscorePathSegmentNameGenerator(), $identifiersExtractorProphecy->reveal()); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - $subresourceOperationFactory, - true, - 'page', - false, - 'itemsPerPage', - $formatsProvider ?? ['json' => ['application/json'], 'csv' => ['text/csv']], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/api/questions/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Question'], - 'operationId' => 'getQuestionItem', - 'produces' => ['application/json', 'text/csv'], - 'summary' => 'Retrieves a Question resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Question resource response', - 'schema' => ['$ref' => '#/definitions/Question'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - '/api/questions/{id}/answer' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Answer', 'Question'], - 'operationId' => 'api_questions_answer_get_subresource', - 'produces' => ['text/xml'], - 'summary' => 'Retrieves a Answer resource.', - 'responses' => [ - 200 => [ - 'description' => 'Answer resource response', - 'schema' => ['$ref' => '#/definitions/Answer'], - ], - 404 => ['description' => 'Resource not found'], - ], - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Question' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a question.', - 'externalDocs' => ['url' => 'http://schema.example.com/Question'], - 'properties' => [ - 'answer' => new \ArrayObject([ - 'type' => 'array', - 'description' => 'This is a name.', - 'items' => ['$ref' => '#/definitions/Answer'], - ]), - ], - ]), - 'Answer' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is an answer.', - 'externalDocs' => ['url' => 'http://schema.example.com/Answer'], - 'properties' => [ - 'content' => new \ArrayObject([ - 'type' => 'array', - 'description' => 'This is a name.', - 'items' => ['$ref' => '#/definitions/Answer'], - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithPropertySwaggerContext(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['swagger_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithPaginationClientEnabled(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [], - ['get' => ['method' => 'GET', 'pagination_client_enabled' => true] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['swagger_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'type' => 'integer', - 'description' => 'The collection page number', - ], - [ - 'name' => 'pagination', - 'in' => 'query', - 'required' => false, - 'type' => 'boolean', - 'description' => 'Enable or disable pagination', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithCustomFormatsDefinedAtOperationLevel(): void - { - $this->doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(); - } - - public function testLegacyNormalizeWithCustomFormatsDefinedAtOperationLevel(): void - { - $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::ITEM)->willReturn(['jsonapi' => ['application/vnd.api+json']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'put', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::COLLECTION)->willReturn(['xml' => ['application/xml', 'text/xml']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'post', OperationType::COLLECTION)->willReturn(['xml' => ['text/xml'], 'csv' => ['text/csv']]); - - $this->doTestNormalizeWithCustomFormatsDefinedAtOperationLevel($formatProviderProphecy->reveal()); - } - - private function doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAwareFormatsProviderInterface $formatProvider = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET', 'output_formats' => ['jsonapi' => ['application/vnd.api+json']]], - 'put' => ['method' => 'PUT', 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]], ], - [ - 'get' => ['method' => 'GET', 'output_formats' => ['xml' => ['application/xml', 'text/xml']]], - 'post' => ['method' => 'POST', 'output_formats' => ['xml' => ['text/xml'], 'csv' => ['text/csv']], 'input_formats' => ['xml' => ['text/xml'], 'csv' => ['text/csv']]], - ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, false, - '', - '', - '', - '', - [], - [], - null, - false, - 'page', - false, - 'itemsPerPage', - $formatProvider, - false, - 'pagination', - [], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/xml', 'text/xml'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/definitions/Dummy'], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['text/xml', 'text/csv'], - 'produces' => ['text/xml', 'text/csv'], - 'summary' => 'Creates a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/vnd.api+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/json', 'text/csv'], - 'produces' => ['application/json', 'text/csv'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'type' => 'string', - 'required' => true, - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => ['$ref' => '#/definitions/Dummy'], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/'])); - } - - public function testLegacyNormalizeWithInputAndOutputClass(): void - { - $this->doTestNormalizeWithInputAndOutputClass(); - } - - private function doTestNormalizeWithInputAndOutputClass(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(InputDto::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['foo', 'bar'])); - $propertyNameCollectionFactoryProphecy->create(OutputDto::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['baz', 'bat'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ], - [ - 'input' => ['class' => InputDto::class], - 'output' => ['class' => OutputDto::class], - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - // InputDto - $propertyMetadataFactoryProphecy->create(InputDto::class, 'foo', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'foo', true, false)); - $propertyMetadataFactoryProphecy->create(InputDto::class, 'bar', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'bar', true, true, true, true, false, false, null, null, [])); - // OutputDto - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'baz', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'baz', true, false)); - $propertyMetadataFactoryProphecy->create(OutputDto::class, 'bat', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'bat', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - '', - [], - [], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'swagger' => '2.0', - 'basePath' => '/app_dev.php/', - 'info' => [ - 'title' => 'Test API', - 'version' => '1.2.3', - 'description' => 'This is a test API.', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves the collection of Dummy resources.', - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'schema' => [ - 'type' => 'array', - 'items' => [ - '$ref' => '#/definitions/Dummy.OutputDto', - ], - ], - ], - ], - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'description' => 'The collection page number', - 'type' => 'integer', - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'schema' => [ - '$ref' => '#/definitions/Dummy.OutputDto', - ], - ], - 400 => [ - 'description' => 'Invalid input', - ], - 404 => [ - 'description' => 'Resource not found', - ], - 422 => [ - 'description' => 'Unprocessable entity', - ], - ], - 'parameters' => [ - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The new Dummy resource', - 'schema' => [ - '$ref' => '#/definitions/Dummy.InputDto', - ], - ], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'produces' => ['application/ld+json'], - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'required' => true, - 'type' => 'string', - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'schema' => [ - '$ref' => '#/definitions/Dummy.OutputDto', - ], - ], - 404 => [ - 'description' => 'Resource not found', - ], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'consumes' => ['application/ld+json'], - 'produces' => ['application/ld+json'], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'required' => true, - 'type' => 'string', - ], - [ - 'name' => 'dummy', - 'in' => 'body', - 'description' => 'The updated Dummy resource', - 'schema' => [ - '$ref' => '#/definitions/Dummy.InputDto', - ], - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'schema' => [ - '$ref' => '#/definitions/Dummy.OutputDto', - ], - ], - 400 => [ - 'description' => 'Invalid input', - ], - 404 => [ - 'description' => 'Resource not found', - ], - 422 => [ - 'description' => 'Unprocessable entity', - ], - ], - ]), - ], - ]), - 'definitions' => new \ArrayObject([ - 'Dummy.OutputDto' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => [ - 'url' => 'http://schema.example.com/Dummy', - ], - 'properties' => [ - 'baz' => new \ArrayObject([ - 'readOnly' => true, - 'description' => 'baz', - 'type' => 'string', - ]), - 'bat' => new \ArrayObject([ - 'description' => 'bat', - 'type' => 'integer', - ]), - ], - ]), - 'Dummy.InputDto' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => [ - 'url' => 'http://schema.example.com/Dummy', - ], - 'properties' => [ - 'foo' => new \ArrayObject([ - 'readOnly' => true, - 'description' => 'foo', - 'type' => 'string', - ]), - 'bar' => new \ArrayObject([ - 'description' => 'bar', - 'type' => 'integer', - ]), - ], - ]), - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - /** - * @dataProvider propertyWithDefaultProvider - * - * @param mixed $expectedDefault - * @param mixed $expectedExample - */ - public function testNormalizeWithDefaultProperty($expectedDefault, $expectedExample, PropertyMetadata $propertyMetadata) - { - $documentation = new Documentation(new ResourceNameCollection([DummyPropertyWithDefaultValue::class])); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyPropertyWithDefaultValue::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['foo'])); - - $dummyMetadata = new ResourceMetadata('DummyPropertyWithDefaultValue', null, null, ['get' => ['method' => 'GET']]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyPropertyWithDefaultValue::class)->shouldBeCalled()->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyPropertyWithDefaultValue::class, 'foo', Argument::any())->shouldBeCalled()->willReturn($propertyMetadata); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - '', - [], - [], - $identifiersExtractorProphecy->reveal() - ); - - $result = $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT); - - $this->assertIsArray($result); - $this->assertEquals($expectedDefault, $result['definitions']['DummyPropertyWithDefaultValue']['properties']['foo']['default']); - $this->assertEquals($expectedExample, $result['definitions']['DummyPropertyWithDefaultValue']['properties']['foo']['example']); - } - - public function propertyWithDefaultProvider() - { - yield 'default should be use for the example if it is not defined' => [ - 'default name', - 'default name', - $this->createStringPropertyMetada('default name'), - ]; - - yield 'should use default and example if they are defined' => [ - 'default name', - 'example name', - $this->createStringPropertyMetada('default name', 'example name'), - ]; - - yield 'should use default and example from swagger context if they are defined' => [ - 'swagger default', - 'swagger example', - $this->createStringPropertyMetada('default name', 'example name', ['swagger_context' => ['default' => 'swagger default', 'example' => 'swagger example']]), - ]; - } - - protected function createStringPropertyMetada($default = null, $example = null, $attributes = []): PropertyMetadata - { - return new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), null, true, true, true, true, false, false, null, null, $attributes, null, null, $default, $example); - } -} diff --git a/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php b/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php deleted file mode 100644 index 53939a43505..00000000000 --- a/tests/Core/Swagger/Serializer/DocumentationNormalizerV3Test.php +++ /dev/null @@ -1,3280 +0,0 @@ - - * - * 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\Swagger\Serializer; - -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouterOperationPathResolver; -use ApiPlatform\Core\JsonSchema\SchemaFactory; -use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactory; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\JsonSchema\TypeFactory; -use ApiPlatform\JsonSchema\TypeFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\OpenApi\Model; -use ApiPlatform\OpenApi\OpenApi; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use ApiPlatform\Tests\Fixtures\DummyFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Psr\Container\ContainerInterface; -use Symfony\Component\PropertyInfo\Type; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * @author Amrouche Hamza - * @author Kévin Dunglas - * @author Anthony GRASSIOT - * @group legacy - */ -class DocumentationNormalizerV3Test extends TestCase -{ - use ProphecyTrait; - - private const OPERATION_FORMATS = [ - 'input_formats' => ['jsonld' => ['application/ld+json']], - 'output_formats' => ['jsonld' => ['application/ld+json']], - ]; - - public function testNormalize(): void - { - $this->doTestNormalize(); - } - - public function testLegacyNormalize(): void - { - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'get')->willReturn('GET'); - $operationMethodResolverProphecy->getItemOperationMethod(Dummy::class, 'put')->willReturn('PUT'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'get')->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'post')->willReturn('POST'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'custom')->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod(Dummy::class, 'custom2')->willReturn('POST'); - - $this->doTestNormalize($operationMethodResolverProphecy->reveal()); - } - - private function doTestNormalize(OperationMethodResolverInterface $operationMethodResolver = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - 'custom' => ['method' => 'GET', 'path' => '/foo'] + self::OPERATION_FORMATS, - 'custom2' => ['method' => 'POST', 'path' => '/foo'] + self::OPERATION_FORMATS, - ], - ['pagination_client_items_per_page' => true, 'normalization_context' => [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::cetera())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::cetera())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - $operationMethodResolver, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 30, - 'minimum' => 0, - ], - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'links' => [ - 'GetDummyItem' => [ - 'operationId' => 'getDummyItem', - 'parameters' => ['id' => '$response.body#/id'], - 'description' => 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.', - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/foo' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'customDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 30, - 'minimum' => 0, - ], - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'custom2DummyCollection', - 'summary' => 'Creates a Dummy resource.', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'links' => [ - 'GetDummyItem' => [ - 'operationId' => 'getDummyItem', - 'parameters' => ['id' => '$response.body#/id'], - 'description' => 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.', - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'additionalProperties' => false, - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'minLength' => 3, - 'maxLength' => 20, - 'pattern' => '^dummyPattern$', - ]), - 'description' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is an initializable but not writable property.', - ]), - 'dummyDate' => new \ArrayObject([ - 'nullable' => true, - 'type' => 'string', - 'format' => 'date-time', - 'description' => 'This is a \DateTimeInterface object.', - ]), - ], - ]), - ]), - ], - 'servers' => [['url' => '/app_dev.php/']], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - $this->assertArrayNotHasKey('servers', (array) $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/'])); - $this->assertArrayNotHasKey('servers', (array) $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => ''])); - } - - public function testNormalizeWithNameConverter(): void - { - $this->doTestNormalizeWithNameConverter(); - } - - public function testLegacyNormalizeWithNameConverter(): void - { - $this->doTestNormalizeWithNameConverter(true); - } - - private function doTestNormalizeWithNameConverter(bool $legacy = false): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Dummy API', 'This is a dummy API', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name', 'nameConverted'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, null, null, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'nameConverted', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a converted name.', true, true, null, null, false)); - - $nameConverterProphecy = $this->prophesize(NameConverterInterface::class); - $nameConverterProphecy->normalize('name', Dummy::class, 'jsonld', [])->willReturn('name'); - $nameConverterProphecy->normalize('nameConverted', Dummy::class, 'jsonld', [])->willReturn('name_converted'); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - /** - * @var ResourceMetadataFactoryInterface - */ - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - /** - * @var PropertyNameCollectionFactoryInterface - */ - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - /** - * @var PropertyMetadataFactoryInterface - */ - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - /** - * @var NameConverterInterface - */ - $nameConverter = $nameConverterProphecy->reveal(); - - /** - * @var TypeFactoryInterface|null - */ - $typeFactory = null; - /** - * @var SchemaFactoryInterface|null - */ - $schemaFactory = null; - - if (!$legacy) { - $typeFactory = new TypeFactory(); - $schemaFactory = new SchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $nameConverter); - $typeFactory->setSchemaFactory($schemaFactory); - } - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - null, - null, - $legacy ? $nameConverter : null, - true, - 'oauth2', - 'authorizationCode', - '/oauth/v2/token', - '/oauth/v2/auth', - ['scope param'], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Dummy API', - 'description' => 'This is a dummy API', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'name_converted' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a converted name.', - ]), - ], - ]), - ]), - 'securitySchemes' => [ - 'oauth' => [ - 'type' => 'oauth2', - 'description' => 'OAuth 2.0 authorization code Grant', - 'flows' => [ - 'authorizationCode' => [ - 'tokenUrl' => '/oauth/v2/token', - 'authorizationUrl' => '/oauth/v2/auth', - 'scopes' => new \ArrayObject(['scope param']), - ], - ], - ], - ], - ], - 'security' => [['oauth' => []]], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithApiKeysEnabled(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, null, null, false)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $apiKeysConfiguration = [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]; - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - $apiKeysConfiguration, - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - 'securitySchemes' => [ - 'header' => [ - 'type' => 'apiKey', - 'in' => 'header', - 'description' => 'Value for the Authorization header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'apiKey', - 'in' => 'query', - 'description' => 'Value for the key query parameter', - 'name' => 'key', - ], - ], - ], - 'security' => [ - ['header' => []], - ['query' => []], - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithOnlyNormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - - $ref = 'Dummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'summary' => 'Creates a Dummy resource.', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/'.$ref], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithOpenApiDefinitionName(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => [ - 'method' => 'GET', - 'normalization_context' => [ - DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'Read', - ], - ] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy-Read'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy-Read' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - ], - ]), - ]), - ], - 'servers' => [['url' => '/app_dev.php/']], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithOnlyDenormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', ['dummy']) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'denormalization_context' => [AbstractNormalizer::GROUPS => 'dummy']] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ]], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - 'Dummy-dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithNormalizationAndDenormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', ['dummy']) - ))->willReturn(new PropertyNameCollection(['gerard'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => [ - 'method' => 'PUT', - 'normalization_context' => [AbstractNormalizer::GROUPS => 'dummy'], 'denormalization_context' => [AbstractNormalizer::GROUPS => 'dummy'], - ] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'gerard', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a gerard.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ]], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - 'Dummy-dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'gerard' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a gerard.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testFilters(): void - { - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $filters = [ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'openapi' => ['x-foo' => 'bar'], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - 'f4' => new DummyFilter(['order[name]' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => false, - 'schema' => [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ], - ]]), - ]; - - foreach ($filters as $filterId => $filter) { - $filterLocatorProphecy->has($filterId)->willReturn(true); - $filterLocatorProphecy->get($filterId)->willReturn($filter); - } - - $filterLocatorProphecy->has('f5')->willReturn(false); - - $this->doTestNormalizeWithFilters($filterLocatorProphecy->reveal()); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testFiltersWithDeprecatedFilterCollection(): void - { - $this->doTestNormalizeWithFilters(new FilterCollection([ - 'f1' => new DummyFilter(['name' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => true, - 'strategy' => 'exact', - 'openapi' => ['x-foo' => 'bar'], - ]]), - 'f2' => new DummyFilter(['ha' => [ - 'property' => 'foo', - 'type' => 'int', - 'required' => false, - 'strategy' => 'partial', - ]]), - 'f3' => new DummyFilter(['toto' => [ - 'property' => 'name', - 'type' => 'array', - 'is_collection' => true, - 'required' => true, - 'strategy' => 'exact', - ]]), - 'f4' => new DummyFilter(['order[name]' => [ - 'property' => 'name', - 'type' => 'string', - 'required' => false, - 'schema' => [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ], - ]]), - ])); - } - - public function testConstructWithInvalidFilterLocator(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface or null.'); - - new DocumentationNormalizer( - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), - null, - null, - $this->prophesize(OperationPathResolverInterface::class)->reveal(), - null, - new \ArrayObject(), - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $this->prophesize(IdentifiersExtractorInterface::class)->reveal() - ); - } - - public function testSupports(): void - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $this->assertTrue($normalizer->supportsNormalization($documentation, 'json')); - $this->assertFalse($normalizer->supportsNormalization($documentation)); - $this->assertFalse($normalizer->supportsNormalization(new Dummy(), 'json')); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - - public function testNormalizeWithNoOperations(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->shouldNotBeCalled(); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - [], - ['formats' => ['jsonld' => ['application/ld+json']]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name')->shouldNotBeCalled(); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithCustomMethod(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - ['get' => ['method' => 'FOO'] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'foo' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - ]), - ], - ]), - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithNestedNormalizationGroups(): void - { - $title = 'Test API'; - $description = 'This is a test API.'; - $version = '1.2.3'; - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), $title, $description, $version); - $groups = ['dummy', 'foo', 'bar']; - $ref = 'Dummy-'.implode('_', $groups); - $relatedDummyRef = 'RelatedDummy-'.implode('_', $groups); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['name', 'relatedDummy'])); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['name'])); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, Argument::allOf( - Argument::type('array'), - Argument::withEntry('serializer_groups', $groups) - ))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS, - ] - ); - - $relatedDummyMetadata = new ResourceMetadata( - 'RelatedDummy', - 'This is a related dummy.', - 'http://schema.example.com/RelatedDummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - ] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedDummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, RelatedDummy::class), 'This is a related dummy \o/.', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => [ - 'Dummy', - ], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'summary' => 'Creates a Dummy resource.', - 'responses' => [ - '201' => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [[ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ]], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'requestBody' => [ - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/'.$ref], - ], - ], - ], - '400' => ['description' => 'Invalid input'], - '404' => ['description' => 'Resource not found'], - '422' => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - $ref => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - 'relatedDummy' => new \ArrayObject([ - 'description' => 'This is a related dummy \o/.', - 'nullable' => true, - 'anyOf' => [ - ['$ref' => '#/components/schemas/'.$relatedDummyRef], - ], - ]), - ], - ]), - $relatedDummyRef => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a related dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/RelatedDummy'], - 'properties' => [ - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - private function doTestNormalizeWithFilters($filterLocator): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), '', '', '0.0.0'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - null, - [], - ['get' => ['method' => 'GET', 'filters' => ['f1', 'f2', 'f3', 'f4', 'f5']] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - $filterLocator, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => '', - 'version' => '0.0.0', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - 'parameters' => [ - [ - 'x-foo' => 'bar', - 'name' => 'name', - 'in' => 'query', - 'required' => true, - 'schema' => ['type' => 'string'], - ], - [ - 'name' => 'ha', - 'in' => 'query', - 'required' => false, - 'schema' => ['type' => 'integer'], - ], - [ - 'name' => 'toto', - 'in' => 'query', - 'required' => true, - 'schema' => [ - 'type' => 'array', - 'items' => [ - 'type' => 'string', - ], - ], - 'style' => 'deepObject', - 'explode' => true, - ], - [ - 'name' => 'order[name]', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'string', - 'enum' => ['asc', 'desc'], - ], - ], - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'properties' => [ - 'name' => new \ArrayObject([ - 'description' => 'This is a name.', - 'type' => 'string', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithSubResource(): void - { - $this->doTestNormalizeWithSubResource(); - } - - public function testLegacytNormalizeWithSubResource(): void - { - $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class); - $formatProviderProphecy->getFormatsFromOperation(Question::class, 'get', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]); - $formatProviderProphecy->getFormatsFromOperation(Answer::class, 'get', OperationType::SUBRESOURCE)->willReturn(['xml' => ['text/xml']]); - - $this->doTestNormalizeWithSubResource($formatProviderProphecy->reveal()); - } - - private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInterface $formatProvider = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Question::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Question::class, Argument::cetera())->willReturn(new PropertyNameCollection(['answer'])); - $propertyNameCollectionFactoryProphecy->create(Answer::class, Argument::cetera())->willReturn(new PropertyNameCollection(['content'])); - - $questionMetadata = new ResourceMetadata( - 'Question', - 'This is a question.', - 'http://schema.example.com/Question', - ['get' => ['method' => 'GET', 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]]] - ); - $answerMetadata = new ResourceMetadata( - 'Answer', - 'This is an answer.', - 'http://schema.example.com/Answer', - [], - ['get' => ['method' => 'GET']] + self::OPERATION_FORMATS, - [], - ['get' => ['method' => 'GET', 'input_formats' => ['xml' => ['text/xml']], 'output_formats' => ['xml' => ['text/xml']]]] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Question::class)->willReturn($questionMetadata); - $resourceMetadataFactoryProphecy->create(Answer::class)->willReturn($answerMetadata); - - $subresourceMetadata = new SubresourceMetadata(Answer::class, false); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Question::class, 'answer', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [], $subresourceMetadata)); - $propertyMetadataFactoryProphecy->create(Answer::class, 'content', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, Question::class, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, Answer::class)), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $routeCollection = new RouteCollection(); - $routeCollection->add('api_questions_answer_get_subresource', new Route('/api/questions/{id}/answer.{_format}')); - $routeCollection->add('api_questions_get_item', new Route('/api/questions/{id}.{_format}')); - - $routerProphecy = $this->prophesize(RouterInterface::class); - $routerProphecy->getRouteCollection()->willReturn($routeCollection); - - $operationPathResolver = new RouterOperationPathResolver($routerProphecy->reveal(), new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()))); - - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new UnderscorePathSegmentNameGenerator(), $identifiersExtractorProphecy->reveal()); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - $subresourceOperationFactory, - true, - 'page', - false, - 'itemsPerPage', - $formatProvider ?? [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/api/questions/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Question'], - 'operationId' => 'getQuestionItem', - 'summary' => 'Retrieves a Question resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Question resource response', - 'content' => [ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Question'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Question'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - '/api/questions/{id}/answer' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Answer', 'Question'], - 'operationId' => 'api_questions_answer_get_subresource', - 'summary' => 'Retrieves a Answer resource.', - 'responses' => [ - '200' => [ - 'description' => 'Answer resource response', - 'content' => [ - 'text/xml' => [ - 'schema' => ['$ref' => '#/components/schemas/Answer'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Question' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a question.', - 'externalDocs' => ['url' => 'http://schema.example.com/Question'], - 'properties' => [ - 'answer' => new \ArrayObject([ - 'type' => 'array', - 'description' => 'This is a name.', - 'items' => ['$ref' => '#/components/schemas/Answer'], - ]), - ], - ]), - 'Answer' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is an answer.', - 'externalDocs' => ['url' => 'http://schema.example.com/Answer'], - 'properties' => [ - 'content' => new \ArrayObject([ - 'type' => 'array', - 'description' => 'This is a name.', - 'items' => ['$ref' => '#/components/schemas/Answer'], - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation)); - } - - public function testNormalizeWithPropertyOpenApiContext(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - '404' => ['description' => 'Resource not found'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithPaginationClientEnabled(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [], - ['get' => ['method' => 'GET', 'pagination_client_enabled' => true] + self::OPERATION_FORMATS] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'pagination', - 'in' => 'query', - 'required' => false, - 'schema' => ['type' => 'boolean'], - 'description' => 'Enable or disable pagination', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithPaginationCustomDefaultAndMaxItemsPerPage(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [], - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS], - ['pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'pagination_maximum_items_per_page' => 80] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 20, - 'minimum' => 0, - 'maximum' => 80, - ], - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - /** - * @group legacy - * @expectedDeprecation The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3. - */ - public function testLegacyNormalizeWithPaginationCustomDefaultAndMaxItemsPerPage(): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::type('array'))->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [], - ['get' => ['method' => 'GET'] + self::OPERATION_FORMATS], - ['pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'maximum_items_per_page' => 80] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, ['openapi_context' => ['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']])); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, - false, - '', - '', - '', - '', - [], - [], - null, - true, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'servers' => [['url' => '/app_dev.php/']], - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [ - [ - 'name' => 'page', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 1, - ], - 'description' => 'The collection page number', - ], - [ - 'name' => 'itemsPerPage', - 'in' => 'query', - 'required' => false, - 'schema' => [ - 'type' => 'integer', - 'default' => 20, - 'minimum' => 0, - 'maximum' => 80, - ], - 'description' => 'The number of items per page', - ], - ], - 'responses' => [ - '200' => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/ld+json' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - 'enum' => ['one', 'two'], - 'example' => 'one', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/app_dev.php/'])); - } - - public function testNormalizeWithCustomFormatsDefinedAtOperationLevel(): void - { - $this->doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(); - } - - public function testLegacyNormalizeWithCustomFormatsDefinedAtOperationLevel(): void - { - $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::ITEM)->willReturn(['jsonapi' => ['application/vnd.api+json']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'put', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::COLLECTION)->willReturn(['xml' => ['application/xml', 'text/xml']]); - $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'post', OperationType::COLLECTION)->willReturn(['xml' => ['text/xml'], 'csv' => ['text/csv']]); - - $this->doTestNormalizeWithCustomFormatsDefinedAtOperationLevel($formatProviderProphecy->reveal()); - } - - private function doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAwareFormatsProviderInterface $formatsProvider = null): void - { - $documentation = new Documentation(new ResourceNameCollection([Dummy::class]), 'Test API', 'This is a test API.', '1.2.3'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::cetera())->willReturn(new PropertyNameCollection(['id', 'name'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET', 'output_formats' => ['jsonapi' => ['application/vnd.api+json']]], - 'put' => ['method' => 'PUT', 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]], ], - [ - 'get' => ['method' => 'GET', 'output_formats' => ['xml' => ['application/xml', 'text/xml']]], - 'post' => ['method' => 'POST', 'output_formats' => ['xml' => ['text/xml'], 'csv' => ['text/csv']], 'input_formats' => ['xml' => ['text/xml'], 'csv' => ['text/csv']]], - ] - ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::cetera())->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [])); - - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, false, - '', - '', - '', - '', - [], - [], - null, - false, - 'page', - false, - 'itemsPerPage', - $formatsProvider ?? [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal() - ); - - $expected = [ - 'openapi' => '3.0.2', - 'info' => [ - 'title' => 'Test API', - 'description' => 'This is a test API.', - 'version' => '1.2.3', - ], - 'paths' => new \ArrayObject([ - '/dummies' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyCollection', - 'summary' => 'Retrieves the collection of Dummy resources.', - 'parameters' => [], - 'responses' => [ - 200 => [ - 'description' => 'Dummy collection response', - 'content' => [ - 'application/xml' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'text/xml' => [ - 'schema' => [ - 'type' => 'array', - 'items' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - ], - ], - ]), - 'post' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'postDummyCollection', - 'summary' => 'Creates a Dummy resource.', - 'requestBody' => [ - 'content' => [ - 'text/xml' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The new Dummy resource', - ], - 'responses' => [ - 201 => [ - 'description' => 'Dummy resource created', - 'content' => [ - 'text/xml' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'links' => [ - 'GetDummyItem' => [ - 'operationId' => 'getDummyItem', - 'parameters' => ['id' => '$response.body#/id'], - 'description' => 'The `id` value returned in the response can be used as the `id` parameter in `GET /dummies/{id}`.', - ], - ], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - '/dummies/{id}' => [ - 'get' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'getDummyItem', - 'summary' => 'Retrieves a Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource response', - 'content' => [ - 'application/vnd.api+json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - 404 => ['description' => 'Resource not found'], - ], - ]), - 'put' => new \ArrayObject([ - 'tags' => ['Dummy'], - 'operationId' => 'putDummyItem', - 'summary' => 'Replaces the Dummy resource.', - 'parameters' => [ - [ - 'name' => 'id', - 'in' => 'path', - 'schema' => ['type' => 'string'], - 'required' => true, - ], - ], - 'requestBody' => [ - 'content' => [ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - 'description' => 'The updated Dummy resource', - ], - 'responses' => [ - 200 => [ - 'description' => 'Dummy resource updated', - 'content' => [ - 'application/json' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - 'text/csv' => [ - 'schema' => ['$ref' => '#/components/schemas/Dummy'], - ], - ], - ], - 400 => ['description' => 'Invalid input'], - 404 => ['description' => 'Resource not found'], - 422 => ['description' => 'Unprocessable entity'], - ], - ]), - ], - ]), - 'components' => [ - 'schemas' => new \ArrayObject([ - 'Dummy' => new \ArrayObject([ - 'type' => 'object', - 'description' => 'This is a dummy.', - 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], - 'properties' => [ - 'id' => new \ArrayObject([ - 'type' => 'integer', - 'description' => 'This is an id.', - 'readOnly' => true, - ]), - 'name' => new \ArrayObject([ - 'type' => 'string', - 'description' => 'This is a name.', - ]), - ], - ]), - ]), - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, ['base_url' => '/'])); - } - - /** - * @group legacy - * @expectedDeprecation Using the swagger DocumentationNormalizer is deprecated in favor of decorating the OpenApiFactory, use the "openapi.backward_compatibility_layer" configuration to change this behavior. - */ - public function testNormalizeOpenApi() - { - $openapi = new OpenApi(new Model\Info('api', 'v1'), [], new Model\Paths()); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - - $openApiNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $openApiNormalizerProphecy->normalize($openapi, null, [])->willReturn([])->shouldBeCalled(); - - $normalizer = new DocumentationNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - null, - null, - $operationPathResolver, - null, - null, - null, false, - '', - '', - '', - '', - [], - [], - null, - false, - 'page', - false, - 'itemsPerPage', - [], - false, - 'pagination', - ['spec_version' => 3], - [2, 3], - $identifiersExtractorProphecy->reveal(), - $openApiNormalizerProphecy->reveal() - ); - - $this->assertTrue($normalizer->supportsNormalization($openapi, 'json')); - $this->assertEquals([], $normalizer->normalize($openapi)); - } -} diff --git a/tests/Core/Test/BookTestDeprecatedClient.php b/tests/Core/Test/BookTestDeprecatedClient.php deleted file mode 100644 index cca8e280df9..00000000000 --- a/tests/Core/Test/BookTestDeprecatedClient.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * 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\Test; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase; -use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client; -use ApiPlatform\Core\Bridge\Symfony\Routing\Router; - -class BookTestDeprecatedClient extends ApiTestCase -{ - /** @phpstan-ignore-next-line */ - private Client $client; - /** @phpstan-ignore-next-line */ - private Router $router; - - protected function setup(): void - { - /* @phpstan-ignore-next-line */ - $this->client = static::createClient(); - } - - public function testWorks(): void - { - $this->assertTrue(true); - } -} diff --git a/tests/Core/Upgrade/SubresourceTransformerTest.php b/tests/Core/Upgrade/SubresourceTransformerTest.php deleted file mode 100644 index aa70709adee..00000000000 --- a/tests/Core/Upgrade/SubresourceTransformerTest.php +++ /dev/null @@ -1,337 +0,0 @@ - - * - * 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\Tests\Core\Bridge\Rector\Service; - -use ApiPlatform\Core\Upgrade\SubresourceTransformer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyOffer; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FourthLevel; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Greeting; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Person; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; -use PHPUnit\Framework\TestCase; - -class SubresourceTransformerTest extends TestCase -{ - /** - * @dataProvider toUriVariablesProvider - */ - public function testToUriVariables(array $metadata, array $expectedMetadata): void - { - $subresourceTransformer = new SubresourceTransformer(); - self::assertEquals($expectedMetadata, $subresourceTransformer->toUriVariables($metadata)); - } - - public function toUriVariablesProvider(): \Generator - { - yield '/questions/{id}/answer' => [ - [ - 'property' => 'answer', - 'collection' => false, - 'resource_class' => Answer::class, - 'identifiers' => ['id' => [Question::class, 'id', true]], - 'path' => '/questions/{id}/answer.{_format}', - ], - [ - 'id' => [ - 'from_class' => Question::class, - 'from_property' => 'answer', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/questions/{id}/answer/related_questions' => [ - [ - 'property' => 'relatedQuestions', - 'collection' => true, - 'resource_class' => Question::class, - 'identifiers' => [ - 'id' => [Question::class, 'id', true], - 'answer' => [Answer::class, 'id', false], - ], - 'path' => '/questions/{id}/answer/related_questions.{_format}', - ], - [ - 'id' => [ - 'from_class' => Question::class, - 'from_property' => 'answer', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'answer' => [ - 'from_class' => Answer::class, - 'from_property' => null, - 'to_property' => 'answer', - 'identifiers' => [], - 'composite_identifier' => false, - 'expanded_value' => 'answer', - ], - ], - ]; - - yield '/dummies/{id}/related_dummies' => [ - [ - 'property' => 'relatedDummies', - 'collection' => true, - 'resource_class' => RelatedDummy::class, - 'identifiers' => ['id' => [Dummy::class, 'id', true]], - 'path' => '/dummies/{id}/related_dummies.{_format}', - ], - [ - 'id' => [ - 'from_class' => Dummy::class, - 'from_property' => 'relatedDummies', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/dummies/{id}/related_dummies/{relatedDummies}' => [ - [ - 'property' => 'id', - 'collection' => false, - 'resource_class' => RelatedDummy::class, - 'identifiers' => [ - 'id' => [Dummy::class, 'id', true], - 'relatedDummies' => [RelatedDummy::class, 'id', true], - ], - 'path' => '/dummies/{id}/related_dummies/{relatedDummies}.{_format}', - ], - [ - 'id' => [ - 'from_class' => Dummy::class, - 'from_property' => 'relatedDummies', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'relatedDummies' => [ - 'from_class' => RelatedDummy::class, - 'from_property' => null, - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/dummies/{id}/related_dummies/{relatedDummies}/third_level' => [ - [ - 'property' => 'thirdLevel', - 'collection' => false, - 'resource_class' => ThirdLevel::class, - 'identifiers' => [ - 'id' => [Dummy::class, 'id', true], - 'relatedDummies' => [RelatedDummy::class, 'id', true], - ], - 'path' => '/dummies/{id}/related_dummies/{relatedDummies}/third_level.{_format}', - ], - [ - 'id' => [ - 'from_class' => Dummy::class, - 'from_property' => 'relatedDummies', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'relatedDummies' => [ - 'from_class' => RelatedDummy::class, - 'from_property' => 'thirdLevel', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level' => [ - [ - 'property' => 'fourthLevel', - 'collection' => false, - 'resource_class' => FourthLevel::class, - 'identifiers' => [ - 'id' => [Dummy::class, 'id', true], - 'relatedDummies' => [RelatedDummy::class, 'id', true], - 'thirdLevel' => [ThirdLevel::class, 'id', false], - ], - 'path' => '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', - ], - [ - 'id' => [ - 'from_class' => Dummy::class, - 'from_property' => 'relatedDummies', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'relatedDummies' => [ - 'from_class' => RelatedDummy::class, - 'from_property' => 'thirdLevel', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'thirdLevel' => [ - 'from_class' => ThirdLevel::class, - 'from_property' => 'fourthLevel', - 'to_property' => null, - 'identifiers' => [], - 'composite_identifier' => false, - 'expanded_value' => 'third_level', - ], - ], - ]; - - yield '/dummy_products/{id}/offers/{offers}/offers' => [ - [ - 'property' => 'offers', - 'collection' => true, - 'resource_class' => DummyOffer::class, - 'identifiers' => [ - 'id' => [DummyProduct::class, 'id', true], - 'offers' => [DummyAggregateOffer::class, 'id', true], - ], - 'path' => '/dummy_products/{id}/offers/{offers}/offers.{_format}', - ], - [ - 'id' => [ - 'from_class' => DummyProduct::class, - 'from_property' => null, - 'to_property' => 'product', - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - 'offers' => [ - 'from_class' => DummyAggregateOffer::class, - 'from_property' => null, - 'to_property' => 'aggregate', - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/dummy_aggregate_offers/{id}/offers' => [ - [ - 'property' => 'offers', - 'collection' => true, - 'resource_class' => DummyOffer::class, - 'identifiers' => [ - 'id' => [DummyAggregateOffer::class, 'id', true], - ], - 'path' => '/dummy_aggregate_offers/{id}/offers.{_format}', - ], - [ - 'id' => [ - 'from_class' => DummyAggregateOffer::class, - 'from_property' => null, - 'to_property' => 'aggregate', - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/people/{id}/sent_greetings' => [ - [ - 'property' => 'sentGreetings', - 'collection' => true, - 'resource_class' => Greeting::class, - 'identifiers' => [ - 'id' => [Person::class, 'id', true], - ], - 'path' => '/people/{id}/sent_greetings.{_format}', - ], - [ - 'id' => [ - 'from_class' => Person::class, - 'from_property' => null, - 'to_property' => 'sender', - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/related_owned_dummies/{id}/owning_dummy' => [ - [ - 'property' => 'owningDummy', - 'collection' => false, - 'resource_class' => Dummy::class, - 'identifiers' => [ - 'id' => [RelatedOwnedDummy::class, 'id', true], - ], - 'path' => '/related_owned_dummies/{id}/owned_dummy.{_format}', - ], - [ - 'id' => [ - 'from_class' => RelatedOwnedDummy::class, - 'from_property' => 'owningDummy', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - - yield '/related_owning_dummies/{id}/owned_dummy' => [ - [ - 'property' => 'ownedDummy', - 'collection' => false, - 'resource_class' => Dummy::class, - 'identifiers' => [ - 'id' => [RelatedOwningDummy::class, 'id', true], - ], - 'path' => '/related_owning_dummies/{id}/owned_dummy.{_format}', - ], - [ - 'id' => [ - 'from_class' => RelatedOwningDummy::class, - 'from_property' => 'ownedDummy', - 'to_property' => null, - 'identifiers' => ['id'], - 'composite_identifier' => false, - 'expanded_value' => null, - ], - ], - ]; - } -} diff --git a/tests/Core/Validator/EventListener/ValidateListenerTest.php b/tests/Core/Validator/EventListener/ValidateListenerTest.php deleted file mode 100644 index 4600840bc8c..00000000000 --- a/tests/Core/Validator/EventListener/ValidateListenerTest.php +++ /dev/null @@ -1,189 +0,0 @@ - - * - * 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\Validator\EventListener; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; -use ApiPlatform\Symfony\EventListener\ValidateListener; -use ApiPlatform\Tests\Fixtures\DummyEntity; -use ApiPlatform\Validator\Exception\ValidationException; -use ApiPlatform\Validator\ValidatorInterface; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * @author Samuel ROZE - * @author Kévin Dunglas - * - * @group legacy - */ -class ValidateListenerTest extends TestCase -{ - use ProphecyTrait; - - public function testNotAnApiPlatformRequest() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $request = new Request(); - $request->setMethod('POST'); - - $listener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - - $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, []); - $listener->onKernelView($event); - } - - public function testValidatorIsCalled() - { - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, ['groups' => $expectedValidationGroups])->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - public function testDoNotValidateWhenControllerResultIsResponse() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $dummy = new DummyEntity(); - - $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post', '_api_receive' => false]); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testDoNotValidateWhenReceiveFlagIsFalse() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $dummy = new DummyEntity(); - - $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post', '_api_receive' => false]); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testDoNotValidateWhenDisabledInOperationAttribute() - { - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate(Argument::cetera())->shouldNotBeCalled(); - - $resourceMetadata = new ResourceMetadata('DummyEntity', null, null, [], [ - 'post' => [ - 'validate' => false, - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata); - - $dummy = new DummyEntity(); - - $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post']); - $request->setMethod('POST'); - - $event = new ViewEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $dummy - ); - - $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($event); - } - - public function testThrowsValidationExceptionWithViolationsFound() - { - $this->expectException(ValidationException::class); - - $data = new DummyEntity(); - $expectedValidationGroups = ['a', 'b', 'c']; - - $validatorProphecy = $this->prophesize(ValidatorInterface::class); - $validatorProphecy->validate($data, ['groups' => $expectedValidationGroups])->willThrow(new ValidationException())->shouldBeCalled(); - $validator = $validatorProphecy->reveal(); - - [$resourceMetadataFactory, $event] = $this->createEventObject($expectedValidationGroups, $data); - - $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); - } - - private function createEventObject($expectedValidationGroups, $data, bool $receive = true): array - { - $resourceMetadata = new ResourceMetadata(null, null, null, [ - 'create' => ['validation_groups' => $expectedValidationGroups], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - if ($receive) { - $resourceMetadataFactoryProphecy->create(DummyEntity::class)->willReturn($resourceMetadata)->shouldBeCalled(); - } - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - - $kernel = $this->prophesize(HttpKernelInterface::class)->reveal(); - $request = new Request([], [], [ - '_api_resource_class' => DummyEntity::class, - '_api_item_operation_name' => 'create', - '_api_format' => 'json', - '_api_mime_type' => 'application/json', - '_api_receive' => $receive, - ]); - - $request->setMethod('POST'); - $event = new ViewEvent($kernel, $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $data); - - return [$resourceMetadataFactory, $event]; - } -} diff --git a/tests/Doctrine/Common/State/PersistProcessorTest.php b/tests/Doctrine/Common/State/PersistProcessorTest.php index bd10fdce00d..37598d5722a 100644 --- a/tests/Doctrine/Common/State/PersistProcessorTest.php +++ b/tests/Doctrine/Common/State/PersistProcessorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Common\State; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Metadata\Get; use ApiPlatform\State\ProcessorInterface; diff --git a/tests/Doctrine/Common/State/RemoveProcessorTest.php b/tests/Doctrine/Common/State/RemoveProcessorTest.php index c63d425693d..f0c51036f9b 100644 --- a/tests/Doctrine/Common/State/RemoveProcessorTest.php +++ b/tests/Doctrine/Common/State/RemoveProcessorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Common\State; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Metadata\Delete; use ApiPlatform\State\ProcessorInterface; diff --git a/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php b/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php index 483c450eca2..98eea28c858 100644 --- a/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php +++ b/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php @@ -17,7 +17,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\PublishMercureUpdatesListener; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface as GraphQlMercureSubscriptionIriGeneratorInterface; diff --git a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php index 06d6128faf0..161a6c7df0a 100644 --- a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php +++ b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ItemNotFoundException; diff --git a/tests/Doctrine/EventListener/WriteListenerTest.php b/tests/Doctrine/EventListener/WriteListenerTest.php index bd1c9bcfa41..d62c278be32 100644 --- a/tests/Doctrine/EventListener/WriteListenerTest.php +++ b/tests/Doctrine/EventListener/WriteListenerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\EventListener; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\WriteListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use Doctrine\Persistence\ManagerRegistry; diff --git a/tests/Doctrine/Odm/Extension/FilterExtensionTest.php b/tests/Doctrine/Odm/Extension/FilterExtensionTest.php index 330ffefa5c8..07bfac837cb 100644 --- a/tests/Doctrine/Odm/Extension/FilterExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/FilterExtensionTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; use ApiPlatform\Api\FilterInterface as ApiFilterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\FilterExtension; use ApiPlatform\Doctrine\Odm\Filter\FilterInterface; use ApiPlatform\Metadata\ApiResource; diff --git a/tests/Doctrine/Odm/Extension/OrderExtensionTest.php b/tests/Doctrine/Odm/Extension/OrderExtensionTest.php index 7b9b1532e68..72b5a6ce998 100644 --- a/tests/Doctrine/Odm/Extension/OrderExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/OrderExtensionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\OrderExtension; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; diff --git a/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php b/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php index 9729f1d6a52..0aea3fa64bf 100644 --- a/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\PaginationExtension; use ApiPlatform\Doctrine\Odm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; diff --git a/tests/Doctrine/Odm/Filter/SearchFilterTest.php b/tests/Doctrine/Odm/Filter/SearchFilterTest.php index 54b72fff03a..ee8ab9ccb8d 100644 --- a/tests/Doctrine/Odm/Filter/SearchFilterTest.php +++ b/tests/Doctrine/Odm/Filter/SearchFilterTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase; diff --git a/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php b/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php index 81be28b8e1f..19407630a2e 100644 --- a/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php +++ b/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Metadata\Property; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Metadata\Property\DoctrineMongoDbOdmPropertyMetadataFactory; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; diff --git a/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php b/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php index 5793373b06a..3c6ce45f078 100644 --- a/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php +++ b/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Metadata\Resource; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Odm\Metadata\Resource\DoctrineMongoDbOdmResourceCollectionMetadataFactory; diff --git a/tests/Doctrine/Odm/PaginatorTest.php b/tests/Doctrine/Odm/PaginatorTest.php index f12f71b9eb0..a9ff1a6aa55 100644 --- a/tests/Doctrine/Odm/PaginatorTest.php +++ b/tests/Doctrine/Odm/PaginatorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Test\DoctrineMongoDbOdmSetup; diff --git a/tests/Doctrine/Odm/State/CollectionProviderTest.php b/tests/Doctrine/Odm/State/CollectionProviderTest.php index c8e8920a376..ee76a8180dd 100644 --- a/tests/Doctrine/Odm/State/CollectionProviderTest.php +++ b/tests/Doctrine/Odm/State/CollectionProviderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm\State; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\State\CollectionProvider; diff --git a/tests/Doctrine/Odm/State/ItemProviderTest.php b/tests/Doctrine/Odm/State/ItemProviderTest.php index eda8b7bf0f4..d6d39d1ca12 100644 --- a/tests/Doctrine/Odm/State/ItemProviderTest.php +++ b/tests/Doctrine/Odm/State/ItemProviderTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm\State; use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; use ApiPlatform\Doctrine\Odm\State\ItemProvider; diff --git a/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php index 4879505f575..2b692f74b9d 100644 --- a/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php @@ -17,7 +17,7 @@ use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Exception\PropertyNotFoundException; diff --git a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php index 9b6162ead11..0d4ca4b2006 100644 --- a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\ResourceClassResolver; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; diff --git a/tests/Doctrine/Orm/Extension/FilterExtensionTest.php b/tests/Doctrine/Orm/Extension/FilterExtensionTest.php index 9ad978f6ecd..4b5d1200b81 100644 --- a/tests/Doctrine/Orm/Extension/FilterExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/FilterExtensionTest.php @@ -17,7 +17,7 @@ use ApiPlatform\Core\Api\FilterCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\FilterExtension; use ApiPlatform\Doctrine\Orm\Filter\FilterInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; diff --git a/tests/Doctrine/Orm/Extension/OrderExtensionTest.php b/tests/Doctrine/Orm/Extension/OrderExtensionTest.php index db811c33a5d..dd73de303b3 100644 --- a/tests/Doctrine/Orm/Extension/OrderExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/OrderExtensionTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\OrderExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; diff --git a/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php b/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php index 44982d9bcf8..c292582073d 100644 --- a/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\AbstractPaginator; use ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\PaginationExtension; diff --git a/tests/Doctrine/Orm/Filter/CommonFilterTest.php b/tests/Doctrine/Orm/Filter/CommonFilterTest.php index 2cb39aa7185..d3cd0007136 100644 --- a/tests/Doctrine/Orm/Filter/CommonFilterTest.php +++ b/tests/Doctrine/Orm/Filter/CommonFilterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Filter; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\Filter\DummyFilter; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Orm/Filter/SearchFilterTest.php b/tests/Doctrine/Orm/Filter/SearchFilterTest.php index 9872b3b1686..3ec15dcfe6f 100644 --- a/tests/Doctrine/Orm/Filter/SearchFilterTest.php +++ b/tests/Doctrine/Orm/Filter/SearchFilterTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Exception\InvalidArgumentException; diff --git a/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php b/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php index b3a474ffb19..e6da9c9ecb7 100644 --- a/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php +++ b/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Metadata\Property; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; diff --git a/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php b/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php index 7bce670e5cc..24e33ddabd3 100644 --- a/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php +++ b/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Metadata\Resource; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Orm\Metadata\Resource\DoctrineOrmResourceCollectionMetadataFactory; diff --git a/tests/Doctrine/Orm/PaginatorTest.php b/tests/Doctrine/Orm/PaginatorTest.php index 09ae2ac5fd6..ae46aafa424 100644 --- a/tests/Doctrine/Orm/PaginatorTest.php +++ b/tests/Doctrine/Orm/PaginatorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Orm; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Tests\Fixtures\Query; diff --git a/tests/Doctrine/Orm/State/CollectionProviderTest.php b/tests/Doctrine/Orm/State/CollectionProviderTest.php index 01e97627bfb..6eb1192e34e 100644 --- a/tests/Doctrine/Orm/State/CollectionProviderTest.php +++ b/tests/Doctrine/Orm/State/CollectionProviderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Orm\State; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\State\CollectionProvider; diff --git a/tests/Doctrine/Orm/State/ItemProviderTest.php b/tests/Doctrine/Orm/State/ItemProviderTest.php index a9e5b4e26ab..e9b81d19bd2 100644 --- a/tests/Doctrine/Orm/State/ItemProviderTest.php +++ b/tests/Doctrine/Orm/State/ItemProviderTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Doctrine\Orm\State; use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; use ApiPlatform\Doctrine\Orm\State\ItemProvider; diff --git a/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php b/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php index f3af0c0eddc..63b44cd1f40 100644 --- a/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php +++ b/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; diff --git a/tests/Doctrine/Orm/Util/QueryCheckerTest.php b/tests/Doctrine/Orm/Util/QueryCheckerTest.php index cce39743b12..e9baca238f8 100644 --- a/tests/Doctrine/Orm/Util/QueryCheckerTest.php +++ b/tests/Doctrine/Orm/Util/QueryCheckerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryChecker; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; diff --git a/tests/Doctrine/Orm/Util/QueryJoinParserTest.php b/tests/Doctrine/Orm/Util/QueryJoinParserTest.php index f2449bee92e..342e3c2052f 100644 --- a/tests/Doctrine/Orm/Util/QueryJoinParserTest.php +++ b/tests/Doctrine/Orm/Util/QueryJoinParserTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryJoinParser; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; diff --git a/tests/Documentation/Action/DocumentationActionTest.php b/tests/Documentation/Action/DocumentationActionTest.php index ce6aafefd6c..0a82e114719 100644 --- a/tests/Documentation/Action/DocumentationActionTest.php +++ b/tests/Documentation/Action/DocumentationActionTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Documentation\Action; use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\Action\DocumentationAction; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; diff --git a/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php b/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php index ecc963ee5f5..7aaed1922b3 100644 --- a/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php +++ b/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; diff --git a/tests/Elasticsearch/Extension/SortExtensionTest.php b/tests/Elasticsearch/Extension/SortExtensionTest.php index ede6bb3b793..36b321c77aa 100644 --- a/tests/Elasticsearch/Extension/SortExtensionTest.php +++ b/tests/Elasticsearch/Extension/SortExtensionTest.php @@ -17,7 +17,7 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Extension\SortExtension; use ApiPlatform\Metadata\ApiProperty; diff --git a/tests/Elasticsearch/Extension/SortFilterExtensionTest.php b/tests/Elasticsearch/Extension/SortFilterExtensionTest.php index 226ebd6d5e1..4013f362219 100644 --- a/tests/Elasticsearch/Extension/SortFilterExtensionTest.php +++ b/tests/Elasticsearch/Extension/SortFilterExtensionTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Extension\SortFilterExtension; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; diff --git a/tests/Elasticsearch/Filter/MatchFilterTest.php b/tests/Elasticsearch/Filter/MatchFilterTest.php index f0578f82c2d..379a8015e35 100644 --- a/tests/Elasticsearch/Filter/MatchFilterTest.php +++ b/tests/Elasticsearch/Filter/MatchFilterTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\MatchFilter; use ApiPlatform\Exception\InvalidArgumentException; diff --git a/tests/Elasticsearch/Filter/OrderFilterTest.php b/tests/Elasticsearch/Filter/OrderFilterTest.php index 250952257e8..3cd4bcc3f1c 100644 --- a/tests/Elasticsearch/Filter/OrderFilterTest.php +++ b/tests/Elasticsearch/Filter/OrderFilterTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\OrderFilter; use ApiPlatform\Elasticsearch\Filter\SortFilterInterface; use ApiPlatform\Metadata\ApiProperty; diff --git a/tests/Elasticsearch/Filter/TermFilterTest.php b/tests/Elasticsearch/Filter/TermFilterTest.php index e2cca9eb6f9..76b0d7c72bb 100644 --- a/tests/Elasticsearch/Filter/TermFilterTest.php +++ b/tests/Elasticsearch/Filter/TermFilterTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\TermFilter; use ApiPlatform\Exception\InvalidArgumentException; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php index 6f7a6392a7e..a252597bd6b 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php index 6501b6a261e..8eb4ca4cf12 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Elasticsearch\Metadata\Document\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php index 87cda14a0e7..808c9ec055b 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php index 33ed62e56e3..3d486390c6f 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Elasticsearch\Metadata\Document\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory; diff --git a/tests/Elasticsearch/PaginatorTest.php b/tests/Elasticsearch/PaginatorTest.php index 2b6090cb771..334238f0eb7 100644 --- a/tests/Elasticsearch/PaginatorTest.php +++ b/tests/Elasticsearch/PaginatorTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Core\Tests\Bridge\Elasticsearch\DataProvider; use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; diff --git a/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php b/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php index 109a1f4a3c4..cb3c139185f 100644 --- a/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php +++ b/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer; use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; use PHPUnit\Framework\TestCase; diff --git a/tests/Elasticsearch/Serializer/ItemNormalizerTest.php b/tests/Elasticsearch/Serializer/ItemNormalizerTest.php index 481f8ca6652..5a022ea1134 100644 --- a/tests/Elasticsearch/Serializer/ItemNormalizerTest.php +++ b/tests/Elasticsearch/Serializer/ItemNormalizerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\Elasticsearch\Serializer\ItemNormalizer; use PHPUnit\Framework\TestCase; diff --git a/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php b/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php index 97787c9a68b..e57b4af35b9 100644 --- a/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php +++ b/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer\NameConverter; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; diff --git a/tests/Elasticsearch/State/CollectionProviderTest.php b/tests/Elasticsearch/State/CollectionProviderTest.php index c38c5991e81..110530f5712 100644 --- a/tests/Elasticsearch/State/CollectionProviderTest.php +++ b/tests/Elasticsearch/State/CollectionProviderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\Elasticsearch\State; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; diff --git a/tests/Elasticsearch/State/ItemProviderTest.php b/tests/Elasticsearch/State/ItemProviderTest.php index fd0930289c7..c4e22dc2d99 100644 --- a/tests/Elasticsearch/State/ItemProviderTest.php +++ b/tests/Elasticsearch/State/ItemProviderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Elasticsearch\State; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; diff --git a/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php b/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php index 9a601359dcf..2b0a35d3e1f 100644 --- a/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php +++ b/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Elasticsearch\Util; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; diff --git a/tests/GraphQl/Action/EntrypointActionTest.php b/tests/GraphQl/Action/EntrypointActionTest.php index 6623de9fc6e..3d1b87eef39 100644 --- a/tests/GraphQl/Action/EntrypointActionTest.php +++ b/tests/GraphQl/Action/EntrypointActionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Action; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\EntrypointAction; use ApiPlatform\GraphQl\Action\GraphiQlAction; use ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction; diff --git a/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php b/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php index e1f785aafe7..8377aa6681e 100644 --- a/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php +++ b/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\GraphQl\Action; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Action/GraphiQlActionTest.php b/tests/GraphQl/Action/GraphiQlActionTest.php index bc0875287f7..987e4ead97b 100644 --- a/tests/GraphQl/Action/GraphiQlActionTest.php +++ b/tests/GraphQl/Action/GraphiQlActionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\GraphQl\Action; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\GraphiQlAction; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php index cb204b4c245..9b19e1917b4 100644 --- a/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\CollectionResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; diff --git a/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php index 2fc9c097096..e37611d40a8 100644 --- a/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemMutationResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\DeserializeStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; diff --git a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php index 4be983c4e31..88103347c66 100644 --- a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; diff --git a/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php index 848b02ccdbd..dea14a81db2 100644 --- a/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemSubscriptionResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityStageInterface; diff --git a/tests/GraphQl/Resolver/ResourceFieldResolverTest.php b/tests/GraphQl/Resolver/ResourceFieldResolverTest.php index 58462b82a1d..8bf6ce7fca3 100644 --- a/tests/GraphQl/Resolver/ResourceFieldResolverTest.php +++ b/tests/GraphQl/Resolver/ResourceFieldResolverTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\ResourceFieldResolver; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; diff --git a/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php b/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php index 288f2ee4847..8838a126ed1 100644 --- a/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\DeserializeStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; diff --git a/tests/GraphQl/Resolver/Stage/ReadStageTest.php b/tests/GraphQl/Resolver/Stage/ReadStageTest.php index 4ddc07510cc..93ed70d4cd9 100644 --- a/tests/GraphQl/Resolver/Stage/ReadStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ReadStageTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\GraphQl\Resolver\Stage\ReadStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php index 68df039c990..b6e70455b2c 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php index 1d02153b2a1..a2efb687ce6 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostValidationStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; diff --git a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php index 28d0b9c9d2b..10c7066086a 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; diff --git a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php index d9d1d057cde..e8280343e43 100644 --- a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SerializeStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; diff --git a/tests/GraphQl/Resolver/Stage/ValidateStageTest.php b/tests/GraphQl/Resolver/Stage/ValidateStageTest.php index 7cfdbc4ce10..e39395de638 100644 --- a/tests/GraphQl/Resolver/Stage/ValidateStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ValidateStageTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\ValidateStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; diff --git a/tests/GraphQl/Resolver/Stage/WriteStageTest.php b/tests/GraphQl/Resolver/Stage/WriteStageTest.php index 6551431ac11..d440234b3a2 100644 --- a/tests/GraphQl/Resolver/Stage/WriteStageTest.php +++ b/tests/GraphQl/Resolver/Stage/WriteStageTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\WriteStage; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Metadata\GraphQl\Mutation; diff --git a/tests/GraphQl/Serializer/ItemNormalizerTest.php b/tests/GraphQl/Serializer/ItemNormalizerTest.php index 5a85b9d7baa..2d37c8f3093 100644 --- a/tests/GraphQl/Serializer/ItemNormalizerTest.php +++ b/tests/GraphQl/Serializer/ItemNormalizerTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; diff --git a/tests/GraphQl/Serializer/SerializerContextBuilderTest.php b/tests/GraphQl/Serializer/SerializerContextBuilderTest.php index 2f88f1bcf1a..227bb6aadda 100644 --- a/tests/GraphQl/Serializer/SerializerContextBuilderTest.php +++ b/tests/GraphQl/Serializer/SerializerContextBuilderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\GraphQl\Serializer; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilder; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Mutation; diff --git a/tests/GraphQl/Subscription/SubscriptionManagerTest.php b/tests/GraphQl/Subscription/SubscriptionManagerTest.php index 2ee4cfcea29..ba7c21cac1f 100644 --- a/tests/GraphQl/Subscription/SubscriptionManagerTest.php +++ b/tests/GraphQl/Subscription/SubscriptionManagerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\GraphQl\Subscription; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\GraphQl\Subscription\SubscriptionIdentifierGeneratorInterface; use ApiPlatform\GraphQl\Subscription\SubscriptionManager; diff --git a/tests/GraphQl/Type/FieldsBuilderTest.php b/tests/GraphQl/Type/FieldsBuilderTest.php index ee2f4e2561d..5b105dc1f33 100644 --- a/tests/GraphQl/Type/FieldsBuilderTest.php +++ b/tests/GraphQl/Type/FieldsBuilderTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface; use ApiPlatform\GraphQl\Type\FieldsBuilder; use ApiPlatform\GraphQl\Type\TypeBuilderInterface; diff --git a/tests/GraphQl/Type/SchemaBuilderTest.php b/tests/GraphQl/Type/SchemaBuilderTest.php index 99ae40b0e9a..2da45dafb50 100644 --- a/tests/GraphQl/Type/SchemaBuilderTest.php +++ b/tests/GraphQl/Type/SchemaBuilderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\FieldsBuilderInterface; use ApiPlatform\GraphQl\Type\SchemaBuilder; use ApiPlatform\GraphQl\Type\TypesContainerInterface; diff --git a/tests/GraphQl/Type/TypeBuilderTest.php b/tests/GraphQl/Type/TypeBuilderTest.php index edb7fec75c7..8218bbba946 100644 --- a/tests/GraphQl/Type/TypeBuilderTest.php +++ b/tests/GraphQl/Type/TypeBuilderTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Type\FieldsBuilderInterface; use ApiPlatform\GraphQl\Type\TypeBuilder; diff --git a/tests/GraphQl/Type/TypeConverterTest.php b/tests/GraphQl/Type/TypeConverterTest.php index bb1c098444f..d29bb163312 100644 --- a/tests/GraphQl/Type/TypeConverterTest.php +++ b/tests/GraphQl/Type/TypeConverterTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\GraphQl\Type\TypeBuilderInterface; use ApiPlatform\GraphQl\Type\TypeConverter; diff --git a/tests/GraphQl/Type/TypesContainerTest.php b/tests/GraphQl/Type/TypesContainerTest.php index 9a98289028e..b03dafd16ec 100644 --- a/tests/GraphQl/Type/TypesContainerTest.php +++ b/tests/GraphQl/Type/TypesContainerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\TypeNotFoundException; use ApiPlatform\GraphQl\Type\TypesContainer; use GraphQL\Type\Definition\Type as GraphQLType; diff --git a/tests/GraphQl/Type/TypesFactoryTest.php b/tests/GraphQl/Type/TypesFactoryTest.php index 4af8c64a6bc..6d1cc811876 100644 --- a/tests/GraphQl/Type/TypesFactoryTest.php +++ b/tests/GraphQl/Type/TypesFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\Definition\TypeInterface; use ApiPlatform\GraphQl\Type\TypesFactory; use PHPUnit\Framework\TestCase; diff --git a/tests/Hal/JsonSchema/SchemaFactoryTest.php b/tests/Hal/JsonSchema/SchemaFactoryTest.php index 5317ea2666e..0f2171c5ad2 100644 --- a/tests/Hal/JsonSchema/SchemaFactoryTest.php +++ b/tests/Hal/JsonSchema/SchemaFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Hal\JsonSchema; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hal\JsonSchema\SchemaFactory; use ApiPlatform\Hydra\JsonSchema\SchemaFactory as HydraSchemaFactory; use ApiPlatform\JsonSchema\Schema; @@ -29,6 +28,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Hal/Serializer/CollectionNormalizerTest.php b/tests/Hal/Serializer/CollectionNormalizerTest.php index 618d3f1f846..4b78bd12862 100644 --- a/tests/Hal/Serializer/CollectionNormalizerTest.php +++ b/tests/Hal/Serializer/CollectionNormalizerTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\CollectionNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; diff --git a/tests/Hal/Serializer/EntrypointNormalizerTest.php b/tests/Hal/Serializer/EntrypointNormalizerTest.php index 49fa5282bc3..6f5d29bb483 100644 --- a/tests/Hal/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hal/Serializer/EntrypointNormalizerTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; diff --git a/tests/Hal/Serializer/ItemNormalizerTest.php b/tests/Hal/Serializer/ItemNormalizerTest.php index 80c31dc60c9..5eaa107bee3 100644 --- a/tests/Hal/Serializer/ItemNormalizerTest.php +++ b/tests/Hal/Serializer/ItemNormalizerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; diff --git a/tests/Hal/Serializer/ObjectNormalizerTest.php b/tests/Hal/Serializer/ObjectNormalizerTest.php index 5ff401e139f..2bb1ea22094 100644 --- a/tests/Hal/Serializer/ObjectNormalizerTest.php +++ b/tests/Hal/Serializer/ObjectNormalizerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Hal\Serializer; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\ObjectNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/HttpCache/EventListener/AddHeadersListenerTest.php b/tests/HttpCache/EventListener/AddHeadersListenerTest.php index 40abcd69676..b1de587fa7e 100644 --- a/tests/HttpCache/EventListener/AddHeadersListenerTest.php +++ b/tests/HttpCache/EventListener/AddHeadersListenerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\HttpCache\EventListener\AddHeadersListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/HttpCache/EventListener/AddTagsListenerTest.php b/tests/HttpCache/EventListener/AddTagsListenerTest.php index bbe3cffda76..523b814ce6e 100644 --- a/tests/HttpCache/EventListener/AddTagsListenerTest.php +++ b/tests/HttpCache/EventListener/AddTagsListenerTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\HttpCache\EventListener\AddTagsListener; use ApiPlatform\HttpCache\PurgerInterface; use ApiPlatform\Metadata\ApiResource; diff --git a/tests/HttpCache/VarnishPurgerTest.php b/tests/HttpCache/VarnishPurgerTest.php index c6ebe1c234c..eec02e90fa6 100644 --- a/tests/HttpCache/VarnishPurgerTest.php +++ b/tests/HttpCache/VarnishPurgerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\HttpCache; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\HttpCache\VarnishPurger; use GuzzleHttp\ClientInterface; use GuzzleHttp\Promise\PromiseInterface; diff --git a/tests/HttpCache/VarnishXKeyPurgerTest.php b/tests/HttpCache/VarnishXKeyPurgerTest.php index 4b720a7c30b..62773bfe9ce 100644 --- a/tests/HttpCache/VarnishXKeyPurgerTest.php +++ b/tests/HttpCache/VarnishXKeyPurgerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\HttpCache; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\HttpCache\VarnishXKeyPurger; use GuzzleHttp\ClientInterface; use GuzzleHttp\Promise\PromiseInterface; diff --git a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php index 9f6b19ed729..5ffa22d75b0 100644 --- a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Hydra\EventListener; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\EventListener\AddLinkHeaderListener; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; diff --git a/tests/Hydra/JsonSchema/SchemaFactoryTest.php b/tests/Hydra/JsonSchema/SchemaFactoryTest.php index ade1f37c8bd..d4cb02c82bd 100644 --- a/tests/Hydra/JsonSchema/SchemaFactoryTest.php +++ b/tests/Hydra/JsonSchema/SchemaFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Hydra\JsonSchema; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Hydra\JsonSchema\SchemaFactory; use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\JsonSchema\Schema; @@ -29,6 +28,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class SchemaFactoryTest extends TestCase diff --git a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php index 3738825a5d7..6fe154a5ec0 100644 --- a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\FilterInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer; diff --git a/tests/Hydra/Serializer/CollectionNormalizerTest.php b/tests/Hydra/Serializer/CollectionNormalizerTest.php index 666cb38b4ae..68b9f4afd0f 100644 --- a/tests/Hydra/Serializer/CollectionNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionNormalizerTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Hydra\Serializer\CollectionNormalizer; use ApiPlatform\JsonLd\ContextBuilderInterface; diff --git a/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php b/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php index 653edb38eda..5e788073c47 100644 --- a/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Hydra\Serializer; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index 282366f3ea0..e62d1426553 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -22,7 +22,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Hydra\Serializer\DocumentationNormalizer; use ApiPlatform\Metadata\ApiProperty; diff --git a/tests/Hydra/Serializer/EntrypointNormalizerTest.php b/tests/Hydra/Serializer/EntrypointNormalizerTest.php index 5d52dc8cd21..0d549ca32df 100644 --- a/tests/Hydra/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hydra/Serializer/EntrypointNormalizerTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; diff --git a/tests/Hydra/Serializer/ErrorNormalizerTest.php b/tests/Hydra/Serializer/ErrorNormalizerTest.php index 68111cc03f5..f99b0ed030d 100644 --- a/tests/Hydra/Serializer/ErrorNormalizerTest.php +++ b/tests/Hydra/Serializer/ErrorNormalizerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Hydra\Serializer; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\ErrorNormalizer; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\Exception\FlattenException; diff --git a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php index 88382552151..00e80239080 100644 --- a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php +++ b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; diff --git a/tests/JsonApi/Serializer/CollectionNormalizerTest.php b/tests/JsonApi/Serializer/CollectionNormalizerTest.php index 1d1ddb61932..5a7d46b5a74 100644 --- a/tests/JsonApi/Serializer/CollectionNormalizerTest.php +++ b/tests/JsonApi/Serializer/CollectionNormalizerTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonApi\Serializer\CollectionNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; diff --git a/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php b/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php index 19913dd6799..54cac5957dc 100644 --- a/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; diff --git a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php index f9575fcdece..37981f8b8ad 100644 --- a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php +++ b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\JsonApi\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\Resource\ResourceNameCollection; diff --git a/tests/JsonApi/Serializer/ErrorNormalizerTest.php b/tests/JsonApi/Serializer/ErrorNormalizerTest.php index 1803bd75e9d..d9060aa67e5 100644 --- a/tests/JsonApi/Serializer/ErrorNormalizerTest.php +++ b/tests/JsonApi/Serializer/ErrorNormalizerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; -use ApiPlatform\Core\Tests\Mock\Exception\ErrorCodeSerializable; +use ApiPlatform\Tests\Mock\Exception\ErrorCodeSerializable; use ApiPlatform\JsonApi\Serializer\ErrorNormalizer; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\Exception\FlattenException; diff --git a/tests/JsonApi/Serializer/ItemNormalizerTest.php b/tests/JsonApi/Serializer/ItemNormalizerTest.php index b2e8a31e463..ce7dab5fbc4 100644 --- a/tests/JsonApi/Serializer/ItemNormalizerTest.php +++ b/tests/JsonApi/Serializer/ItemNormalizerTest.php @@ -21,7 +21,7 @@ use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\JsonApi\Serializer\ItemNormalizer; diff --git a/tests/JsonLd/Action/ContextActionTest.php b/tests/JsonLd/Action/ContextActionTest.php index ca1ab6ab322..44cb8e9571d 100644 --- a/tests/JsonLd/Action/ContextActionTest.php +++ b/tests/JsonLd/Action/ContextActionTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonLd\Action\ContextAction; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; diff --git a/tests/JsonLd/ContextBuilderTest.php b/tests/JsonLd/ContextBuilderTest.php index 8b12d15c939..8e70cbe9d38 100644 --- a/tests/JsonLd/ContextBuilderTest.php +++ b/tests/JsonLd/ContextBuilderTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; diff --git a/tests/JsonLd/Serializer/ItemNormalizerTest.php b/tests/JsonLd/Serializer/ItemNormalizerTest.php index ab225838996..4ffbfcbfc2a 100644 --- a/tests/JsonLd/Serializer/ItemNormalizerTest.php +++ b/tests/JsonLd/Serializer/ItemNormalizerTest.php @@ -17,7 +17,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; diff --git a/tests/JsonLd/Serializer/ObjectNormalizerTest.php b/tests/JsonLd/Serializer/ObjectNormalizerTest.php index 9d242e29c00..23a0c3c4cd6 100644 --- a/tests/JsonLd/Serializer/ObjectNormalizerTest.php +++ b/tests/JsonLd/Serializer/ObjectNormalizerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\JsonLd\Serializer; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonLd\AnonymousContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\ObjectNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; diff --git a/tests/JsonSchema/SchemaFactoryTest.php b/tests/JsonSchema/SchemaFactoryTest.php index d6d94f8fac6..86b76332d9e 100644 --- a/tests/JsonSchema/SchemaFactoryTest.php +++ b/tests/JsonSchema/SchemaFactoryTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\JsonSchema; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactoryInterface; @@ -29,6 +28,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\NotAResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\OverriddenOperationDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/JsonSchema/TypeFactoryTest.php b/tests/JsonSchema/TypeFactoryTest.php index a1cbe190083..27c05b11800 100644 --- a/tests/JsonSchema/TypeFactoryTest.php +++ b/tests/JsonSchema/TypeFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\JsonSchema; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\JsonSchema\TypeFactory; diff --git a/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php index 8b3b53aaf1d..0b8a17181df 100644 --- a/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\AttributePropertyMetadataFactory; diff --git a/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php index d9a3177d841..37b97955388 100644 --- a/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\CachedPropertyMetadataFactory; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; diff --git a/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php b/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php index aaf1f4c7d6a..07c44bd30f0 100644 --- a/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php +++ b/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; diff --git a/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php index 5aa5cd755f9..18a3f00d8e7 100644 --- a/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\DefaultPropertyMetadataFactory; diff --git a/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php b/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php index 4cb24362a2b..8754df086d2 100644 --- a/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php +++ b/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory; diff --git a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php index 39049295f4d..9e7b159fdf0 100644 --- a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory; diff --git a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php index ac8bba952b6..56728eaa45f 100644 --- a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; diff --git a/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php index 1e1cd9660a3..b10e48b239c 100644 --- a/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; diff --git a/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php index 06902ca838b..948037d6cb5 100644 --- a/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\InputOutputResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; diff --git a/tests/Metadata/Resource/Factory/LinkFactoryTest.php b/tests/Metadata/Resource/Factory/LinkFactoryTest.php index 9073bc2f9ab..697cd997155 100644 --- a/tests/Metadata/Resource/Factory/LinkFactoryTest.php +++ b/tests/Metadata/Resource/Factory/LinkFactoryTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; diff --git a/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php index 0b28987a8e3..b324a6e4f78 100644 --- a/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Query; diff --git a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php index c6dc236dcfa..38ebc8e52d9 100644 --- a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\PhpDocResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; diff --git a/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php index 4b54258dd2d..ce944ae6f4b 100644 --- a/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; diff --git a/tests/Metadata/Resource/ResourceMetadataCollectionTest.php b/tests/Metadata/Resource/ResourceMetadataCollectionTest.php index d9c3b94cbde..640006fba84 100644 --- a/tests/Metadata/Resource/ResourceMetadataCollectionTest.php +++ b/tests/Metadata/Resource/ResourceMetadataCollectionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Resource; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; diff --git a/tests/Core/Mock/Exception/ErrorCodeSerializable.php b/tests/Mock/Exception/ErrorCodeSerializable.php similarity index 91% rename from tests/Core/Mock/Exception/ErrorCodeSerializable.php rename to tests/Mock/Exception/ErrorCodeSerializable.php index 2d1fb46371c..2531b33f207 100644 --- a/tests/Core/Mock/Exception/ErrorCodeSerializable.php +++ b/tests/Mock/Exception/ErrorCodeSerializable.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Mock\Exception; +namespace ApiPlatform\Tests\Mock\Exception; use ApiPlatform\Exception\ErrorCodeSerializableInterface; diff --git a/tests/OpenApi/Factory/OpenApiFactoryTest.php b/tests/OpenApi/Factory/OpenApiFactoryTest.php index 170e031134e..263df051cb1 100644 --- a/tests/OpenApi/Factory/OpenApiFactoryTest.php +++ b/tests/OpenApi/Factory/OpenApiFactoryTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\OpenApi\Factory; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; diff --git a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php index 113c90a232f..7e3996b70c1 100644 --- a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php +++ b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\OpenApi\Serializer; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; diff --git a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php index ff2ce34ce7b..71855b63764 100644 --- a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php +++ b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php @@ -24,7 +24,7 @@ use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory as LegacyOpenApiFactory; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; use ApiPlatform\Metadata\ApiProperty; diff --git a/tests/PathResolver/CustomOperationPathResolverTest.php b/tests/PathResolver/CustomOperationPathResolverTest.php index 55d9d2783f9..f486a00c93d 100644 --- a/tests/PathResolver/CustomOperationPathResolverTest.php +++ b/tests/PathResolver/CustomOperationPathResolverTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\PathResolver; use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\PathResolver\CustomOperationPathResolver; use ApiPlatform\PathResolver\OperationPathResolverInterface; use PHPUnit\Framework\TestCase; diff --git a/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php b/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php index 8bc6adc5fd3..248207daed7 100644 --- a/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Problem\Serializer; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Serializer/AbstractItemNormalizerTest.php b/tests/Serializer/AbstractItemNormalizerTest.php index a0a26cf4619..683cb29adb9 100644 --- a/tests/Serializer/AbstractItemNormalizerTest.php +++ b/tests/Serializer/AbstractItemNormalizerTest.php @@ -23,7 +23,7 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\Metadata\ApiProperty; diff --git a/tests/Serializer/ItemNormalizerTest.php b/tests/Serializer/ItemNormalizerTest.php index 462f78fcfd3..4dfcee3e340 100644 --- a/tests/Serializer/ItemNormalizerTest.php +++ b/tests/Serializer/ItemNormalizerTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Core\DataTransformer\DataTransformerInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; diff --git a/tests/Serializer/LegacySerializerContextBuilderTest.php b/tests/Serializer/LegacySerializerContextBuilderTest.php index dd0e95be199..e516c531a1a 100644 --- a/tests/Serializer/LegacySerializerContextBuilderTest.php +++ b/tests/Serializer/LegacySerializerContextBuilderTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Serializer\SerializerContextBuilder; use PHPUnit\Framework\TestCase; diff --git a/tests/Serializer/SerializerContextBuilderTest.php b/tests/Serializer/SerializerContextBuilderTest.php index 24926fb8a27..4c74636f37e 100644 --- a/tests/Serializer/SerializerContextBuilderTest.php +++ b/tests/Serializer/SerializerContextBuilderTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Serializer\SerializerContextBuilder; use PHPUnit\Framework\TestCase; diff --git a/tests/Serializer/SerializerFilterContextBuilderTest.php b/tests/Serializer/SerializerFilterContextBuilderTest.php index 0780f2279c7..b429d6c6b82 100644 --- a/tests/Serializer/SerializerFilterContextBuilderTest.php +++ b/tests/Serializer/SerializerFilterContextBuilderTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Serializer\Filter\FilterInterface as SerializerFilterInterface; use ApiPlatform\Serializer\SerializerContextBuilderInterface; diff --git a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php index 59df7d57e5c..ab58f4ddf11 100644 --- a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php +++ b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; diff --git a/tests/Symfony/Bundle/ApiPlatformBundleTest.php b/tests/Symfony/Bundle/ApiPlatformBundleTest.php index 8fcd90bcc8c..b8212639307 100644 --- a/tests/Symfony/Bundle/ApiPlatformBundleTest.php +++ b/tests/Symfony/Bundle/ApiPlatformBundleTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; diff --git a/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php b/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php index 51722ce4c1d..22eb66ebaf1 100644 --- a/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php +++ b/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\ArgumentResolver; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Post; diff --git a/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php b/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php index 09a0f859f60..8d6146a7f1d 100644 --- a/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php +++ b/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\Command; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory; use ApiPlatform\Symfony\Bundle\Command\DebugResourceCommand; diff --git a/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php b/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php index d2a26923157..361ee1b85e2 100644 --- a/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php +++ b/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php @@ -25,7 +25,7 @@ use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; diff --git a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index ad93e1fae27..234751ac9f0 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -21,7 +21,7 @@ use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php index e41f8f7dff1..0827f6feef0 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Serializer\Filter\GroupFilter; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php index ffa887ea47a..2c8e25fe0e9 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php index 791bcaebadc..bb90f141431 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\BaseNode; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php index 81d7fbcca3b..857f3c06dab 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass; use Elasticsearch\ClientBuilder; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php index 1cf1644045c..12268852108 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php index 5310dc5615e..c5beea4e75f 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php index 4f65c1cdec6..c35837cbb2a 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php index 4abb2bdb354..49dcecbd7ea 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php index cb6cee6dbcd..c09e1c41eaf 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Alias; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php index 1f87b5c3128..38597b36ed7 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; use ApiPlatform\Symfony\Bundle\Test\Client; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php b/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php index 080eaa62f64..82fe83b4f59 100644 --- a/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php +++ b/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Bundle\EventListener; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php b/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php index bf2795f4ae4..d077c4f9d59 100644 --- a/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php +++ b/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\DocumentationInterface; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Model\Info; diff --git a/tests/Symfony/EventListener/AddFormatListenerTest.php b/tests/Symfony/EventListener/AddFormatListenerTest.php index a353e505397..a1f9614ab6a 100644 --- a/tests/Symfony/EventListener/AddFormatListenerTest.php +++ b/tests/Symfony/EventListener/AddFormatListenerTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Api\FormatsProviderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\AddFormatListener; use Negotiation\Negotiator; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php index 455ab047a9b..1aaa4e2ea15 100644 --- a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\AddLinkHeaderListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use Fig\Link\GenericLinkProvider; diff --git a/tests/Symfony/EventListener/DenyAccessListenerTest.php b/tests/Symfony/EventListener/DenyAccessListenerTest.php index 2c4331d67e6..83fa7cf99ed 100644 --- a/tests/Symfony/EventListener/DenyAccessListenerTest.php +++ b/tests/Symfony/EventListener/DenyAccessListenerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\DenyAccessListener; use ApiPlatform\Symfony\Security\ExpressionLanguage; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; diff --git a/tests/Symfony/EventListener/DeserializeListenerTest.php b/tests/Symfony/EventListener/DeserializeListenerTest.php index 92598f22a5b..72639475b90 100644 --- a/tests/Symfony/EventListener/DeserializeListenerTest.php +++ b/tests/Symfony/EventListener/DeserializeListenerTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Api\FormatsProviderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\DeserializeListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; diff --git a/tests/Symfony/EventListener/ExceptionListenerTest.php b/tests/Symfony/EventListener/ExceptionListenerTest.php index afc5223240a..fc493db27db 100644 --- a/tests/Symfony/EventListener/ExceptionListenerTest.php +++ b/tests/Symfony/EventListener/ExceptionListenerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\ExceptionListener; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php index 472d75db8be..3eb0634c68e 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php index c3498dbe14e..fff92f5477c 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php index 551be244100..566c22d314c 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php index b1b42b05907..c938650f2fe 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php b/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php index 27885a58bdb..f7cba02b1ba 100644 --- a/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php +++ b/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php @@ -16,7 +16,7 @@ use ApiPlatform\Core\Filter\QueryParameterValidator; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Symfony\EventListener\QueryParameterValidateListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; diff --git a/tests/Symfony/EventListener/ReadListenerTest.php b/tests/Symfony/EventListener/ReadListenerTest.php index 5cbb87294ee..993b616dc04 100644 --- a/tests/Symfony/EventListener/ReadListenerTest.php +++ b/tests/Symfony/EventListener/ReadListenerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Symfony\EventListener; use ApiPlatform\Api\UriVariablesConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; diff --git a/tests/Symfony/EventListener/RespondListenerTest.php b/tests/Symfony/EventListener/RespondListenerTest.php index 5cc70487540..42b438c5e92 100644 --- a/tests/Symfony/EventListener/RespondListenerTest.php +++ b/tests/Symfony/EventListener/RespondListenerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\RespondListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/EventListener/SerializeListenerTest.php b/tests/Symfony/EventListener/SerializeListenerTest.php index d40463568e5..f97f90498f1 100644 --- a/tests/Symfony/EventListener/SerializeListenerTest.php +++ b/tests/Symfony/EventListener/SerializeListenerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Serializer\ResourceList; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\SerializeListener; diff --git a/tests/Symfony/EventListener/WriteListenerTest.php b/tests/Symfony/EventListener/WriteListenerTest.php index 8fe39dde264..c7fc05654d9 100644 --- a/tests/Symfony/EventListener/WriteListenerTest.php +++ b/tests/Symfony/EventListener/WriteListenerTest.php @@ -15,7 +15,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; diff --git a/tests/Symfony/Messenger/ProcessorTest.php b/tests/Symfony/Messenger/ProcessorTest.php index 6a6fe2f72f1..d73221f38ec 100644 --- a/tests/Symfony/Messenger/ProcessorTest.php +++ b/tests/Symfony/Messenger/ProcessorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Messenger; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; use ApiPlatform\Symfony\Messenger\ContextStamp; diff --git a/tests/Symfony/Routing/ApiLoaderTest.php b/tests/Symfony/Routing/ApiLoaderTest.php index 9f004247084..0cf4ff6177c 100644 --- a/tests/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Symfony/Routing/ApiLoaderTest.php @@ -18,7 +18,7 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; diff --git a/tests/Symfony/Routing/IriConverterTest.php b/tests/Symfony/Routing/IriConverterTest.php index 1e8674bc19d..d5a0ad25362 100644 --- a/tests/Symfony/Routing/IriConverterTest.php +++ b/tests/Symfony/Routing/IriConverterTest.php @@ -17,7 +17,7 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; diff --git a/tests/Symfony/Routing/RouterTest.php b/tests/Symfony/Routing/RouterTest.php index 89a859118a1..1581d262539 100644 --- a/tests/Symfony/Routing/RouterTest.php +++ b/tests/Symfony/Routing/RouterTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Symfony\Routing; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Routing\Router; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Security/ResourceAccessCheckerTest.php b/tests/Symfony/Security/ResourceAccessCheckerTest.php index f5d39f8717b..4ad3e77a64b 100644 --- a/tests/Symfony/Security/ResourceAccessCheckerTest.php +++ b/tests/Symfony/Security/ResourceAccessCheckerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Security; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Security\ExpressionLanguage; use ApiPlatform\Symfony\Security\ResourceAccessChecker; use ApiPlatform\Tests\Fixtures\Serializable; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php index 11a8694c595..1f84cd554d4 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php index c5a84217e24..ad3b94451de 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaCollectionRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php index 93b910e9a8c..16d29412e77 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaCountRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php index 9af541d34ee..a68f6f43301 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php index d88154c5b7c..077c1b46233 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaGreaterThanOrEqualRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php index f5341ff61b0..f2f55fd4a73 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaGreaterThanRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php index 7d0bf45a472..57d3bb16d06 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLessThanOrEqualRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php index 28ee8be5bed..ca9c984c781 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLessThanRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php index 9428b535f95..058d090a6d6 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLengthRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaOneOfRestriction; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php index bac30a00caf..c432bbe79ad 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRangeRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php index 5a92104fb64..1ccb9f209c0 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php index b9cc2945198..4fa6393e82c 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaUniqueRestriction; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php b/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php index 57c2bf2a113..5f261dbff53 100644 --- a/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php +++ b/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction; diff --git a/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php b/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php index 69e43938f4c..719c473a02c 100644 --- a/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php +++ b/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator\EventListener; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener; use ApiPlatform\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface; diff --git a/tests/Symfony/Validator/Metadata/ValidatorTest.php b/tests/Symfony/Validator/Metadata/ValidatorTest.php index 6fb6ff2ea0c..de1651acf04 100644 --- a/tests/Symfony/Validator/Metadata/ValidatorTest.php +++ b/tests/Symfony/Validator/Metadata/ValidatorTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Symfony\Validator; -use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Validator\Exception\ValidationException; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; use ApiPlatform\Symfony\Validator\Validator; From d6209e9e8fab6713c90f2ad4d8b0b1029d88eb03 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 3 May 2022 10:39:00 +0200 Subject: [PATCH 03/56] fix: update metadata for 3.0 (mongodb) --- .../TestBundle/Document/AbsoluteUrlDummy.php | 8 +-- .../Document/AbsoluteUrlRelationDummy.php | 7 +-- .../TestBundle/Document/AbstractDummy.php | 20 +++---- .../Fixtures/TestBundle/Document/Address.php | 7 +-- tests/Fixtures/TestBundle/Document/Answer.php | 19 +++---- .../Document/ArrayFilterValidator.php | 10 +--- tests/Fixtures/TestBundle/Document/Book.php | 11 ++-- .../TestBundle/Document/CircularReference.php | 7 +-- .../TestBundle/Document/CompositeItem.php | 6 +-- .../TestBundle/Document/CompositeLabel.php | 5 +- .../Document/CompositePrimitiveItem.php | 7 +-- .../TestBundle/Document/CompositeRelation.php | 7 +-- .../TestBundle/Document/ConcreteDummy.php | 5 +- .../Document/ContainNonResource.php | 14 +---- .../Fixtures/TestBundle/Document/Content.php | 21 ++------ .../TestBundle/Document/ConvertedBoolean.php | 7 ++- .../TestBundle/Document/ConvertedDate.php | 7 ++- .../TestBundle/Document/ConvertedInteger.php | 11 ++-- .../TestBundle/Document/ConvertedOwner.php | 7 ++- .../TestBundle/Document/ConvertedRelated.php | 5 +- .../TestBundle/Document/ConvertedString.php | 7 ++- .../TestBundle/Document/CustomActionDummy.php | 19 ++----- .../Document/CustomGeneratedIdentifier.php | 4 +- .../Document/CustomIdentifierDummy.php | 5 +- .../CustomMultipleIdentifierDummy.php | 7 ++- .../Document/CustomNormalizedDummy.php | 10 +--- .../CustomWritableIdentifierDummy.php | 5 +- .../Fixtures/TestBundle/Document/Customer.php | 8 +-- .../Document/DeprecatedResource.php | 5 +- .../Document/DisableItemOperation.php | 18 ++----- tests/Fixtures/TestBundle/Document/Dummy.php | 47 +++------------- .../Document/DummyAggregateOffer.php | 18 +++---- .../TestBundle/Document/DummyBoolean.php | 5 +- .../Fixtures/TestBundle/Document/DummyCar.php | 33 +++++------- .../TestBundle/Document/DummyCarColor.php | 6 +-- .../TestBundle/Document/DummyCustomFormat.php | 5 +- .../Document/DummyCustomMutation.php | 42 ++------------- .../TestBundle/Document/DummyCustomQuery.php | 53 ++----------------- .../TestBundle/Document/DummyDate.php | 17 ++---- ...ummyDifferentGraphQlSerializationGroup.php | 14 ++--- .../TestBundle/Document/DummyDtoCustom.php | 15 +++--- .../Document/DummyDtoInputOutput.php | 9 +--- .../TestBundle/Document/DummyDtoNoInput.php | 35 +++--------- .../TestBundle/Document/DummyDtoNoOutput.php | 13 +---- .../DummyDtoOutputFallbackToSameClass.php | 7 +-- .../Document/DummyDtoOutputSameClass.php | 7 +-- .../Document/DummyEntityWithConstructor.php | 19 +++---- .../TestBundle/Document/DummyFriend.php | 7 ++- .../TestBundle/Document/DummyGroup.php | 33 ++---------- .../Document/DummyImmutableDate.php | 9 ++-- .../TestBundle/Document/DummyMercure.php | 7 +-- .../TestBundle/Document/DummyOffer.php | 13 +++-- .../TestBundle/Document/DummyPassenger.php | 5 +- .../TestBundle/Document/DummyProduct.php | 22 +++----- .../TestBundle/Document/DummyProperty.php | 34 ++---------- .../Document/DummyTableInheritance.php | 12 ++--- .../Document/DummyTableInheritanceChild.php | 4 +- .../DummyTableInheritanceDifferentChild.php | 4 +- .../Document/DummyTableInheritanceRelated.php | 10 +--- .../TestBundle/Document/DummyTravel.php | 7 +-- .../TestBundle/Document/DummyValidation.php | 20 +++---- ...mmyWithEmbedManyOmittingTargetDocument.php | 5 +- .../TestBundle/Document/EmbeddedDummy.php | 17 +++--- .../TestBundle/Document/FilterValidator.php | 17 +----- tests/Fixtures/TestBundle/Document/Foo.php | 30 ++++------- .../Fixtures/TestBundle/Document/FooDummy.php | 15 ++---- .../TestBundle/Document/FourthLevel.php | 15 ++++-- .../Fixtures/TestBundle/Document/Greeting.php | 10 ++-- .../TestBundle/Document/InitializeInput.php | 6 +-- .../TestBundle/Document/IriOnlyDummy.php | 11 +--- .../Document/JsonldContextDummy.php | 5 +- .../Document/LegacySecuredDummy.php | 30 +++-------- .../TestBundle/Document/MaxDepthDummy.php | 13 ++--- .../Document/MaxDepthEagerDummy.php | 13 ++--- .../Document/MessengerWithInput.php | 7 ++- .../TestBundle/Document/NetworkPathDummy.php | 8 +-- .../Document/NetworkPathRelationDummy.php | 7 +-- .../TestBundle/Document/NoCollectionDummy.php | 8 ++- tests/Fixtures/TestBundle/Document/Order.php | 9 +--- .../Document/OverriddenOperationDummy.php | 43 +++------------ .../TestBundle/Document/PatchDummy.php | 15 +++--- .../Document/PatchDummyRelation.php | 19 +++---- .../Fixtures/TestBundle/Document/Payment.php | 21 ++------ tests/Fixtures/TestBundle/Document/Person.php | 10 +--- tests/Fixtures/TestBundle/Document/Pet.php | 7 +-- .../Fixtures/TestBundle/Document/Question.php | 13 ++--- tests/Fixtures/TestBundle/Document/RPC.php | 12 ++--- .../Document/ReadableOnlyProperty.php | 5 +- .../TestBundle/Document/RelatedDummy.php | 28 +++++----- .../Document/RelatedNormalizedDummy.php | 10 +--- .../TestBundle/Document/RelatedOwnedDummy.php | 13 ++--- .../Document/RelatedOwningDummy.php | 14 ++--- .../Document/RelatedSecuredDummy.php | 20 +++---- .../Document/RelatedToDummyFriend.php | 15 +++--- .../TestBundle/Document/RelationEmbedder.php | 28 +++------- .../Document/ResourceWithBoolean.php | 5 +- .../TestBundle/Document/ResourceWithFloat.php | 5 +- .../Document/ResourceWithInteger.php | 5 +- .../Document/ResourceWithString.php | 5 +- .../TestBundle/Document/SecuredDummy.php | 45 ++++------------ .../TestBundle/Document/SlugChildDummy.php | 13 +++-- .../TestBundle/Document/SlugParentDummy.php | 15 +++--- tests/Fixtures/TestBundle/Document/SoMany.php | 15 ++---- .../TestBundle/Document/ThirdLevel.php | 18 +++---- .../TestBundle/Document/UrlEncodedId.php | 16 ++---- tests/Fixtures/TestBundle/Document/User.php | 42 +++------------ .../Document/UuidIdentifierDummy.php | 5 +- .../TestBundle/Document/VoDummyCar.php | 18 ++----- .../TestBundle/Document/VoDummyDriver.php | 6 +-- .../TestBundle/Document/VoDummyInspection.php | 14 +---- .../Document/VoDummyInsuranceCompany.php | 5 +- .../TestBundle/Document/VoidPayment.php | 6 +-- .../TestBundle/Document/WithJsonDummy.php | 5 +- .../TestBundle/Document/WritableId.php | 6 +-- 114 files changed, 470 insertions(+), 1089 deletions(-) diff --git a/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php b/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php index 47af2b329fa..b2abc40bb2f 100644 --- a/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php @@ -14,20 +14,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::ABS_URL) * @ODM\Document */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] +#[ApiResource(uriTemplate: '/absolute_url_relation_dummies/{id}/absolute_url_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\AbsoluteUrlRelationDummy::class, identifiers: ['id'], toProperty: 'absoluteUrlRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::ABS_URL, operations: [new GetCollection()])] class AbsoluteUrlDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\ReferenceOne(targetDocument=AbsoluteUrlRelationDummy::class, inversedBy="absoluteUrlDummies", storeAs="id") */ diff --git a/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php b/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php index 1e80a1461ea..094858ae290 100644 --- a/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php @@ -14,25 +14,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::ABS_URL) * @ODM\Document */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] class AbsoluteUrlRelationDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\ReferenceMany(targetDocument=AbsoluteUrlDummy::class, mappedBy="absoluteUrlRelationDummy") - * @ApiSubresource */ public $absoluteUrlDummies; diff --git a/tests/Fixtures/TestBundle/Document/AbstractDummy.php b/tests/Fixtures/TestBundle/Document/AbstractDummy.php index eff751901a4..52209aee373 100644 --- a/tests/Fixtures/TestBundle/Document/AbstractDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbstractDummy.php @@ -14,7 +14,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; @@ -22,16 +27,12 @@ * Abstract Dummy. * * @author Jérémy Derussé - * @ApiResource( - * collectionOperations={"get", "post"}, - * itemOperations={"get", "put", "delete"}, - * attributes={"filters"={"my_dummy.mongodb.search", "my_dummy.mongodb.order", "my_dummy.mongodb.date"}} - * ) * @ODM\Document - * @ODM\InheritanceType("SINGLE_COLLECTION") - * @ODM\DiscriminatorField(value="discr") - * @ODM\DiscriminatorMap({"concrete"=ConcreteDummy::class}) + * @ODM\InheritanceType ("SINGLE_COLLECTION") + * @ODM\DiscriminatorField (value="discr") + * @ODM\DiscriminatorMap ({"concrete"=ConcreteDummy::class}) */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new GetCollection(), new Post()], filters: ['my_dummy.mongodb.search', 'my_dummy.mongodb.order', 'my_dummy.mongodb.date'])] abstract class AbstractDummy { /** @@ -40,7 +41,6 @@ abstract class AbstractDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Document/Address.php b/tests/Fixtures/TestBundle/Document/Address.php index 6d886bb79b7..165233bc2dc 100644 --- a/tests/Fixtures/TestBundle/Document/Address.php +++ b/tests/Fixtures/TestBundle/Document/Address.php @@ -13,16 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource( - * attributes={"normalization_context"={"groups"={"order_read"}}} - * ) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['order_read']])] class Address { /** @@ -32,7 +30,6 @@ class Address * @Groups({"order_read"}) */ private $id; - /** * @ODM\Field(type="string") * @Groups({"order_read"}) diff --git a/tests/Fixtures/TestBundle/Document/Answer.php b/tests/Fixtures/TestBundle/Document/Answer.php index 0710e32030c..35749ff7482 100644 --- a/tests/Fixtures/TestBundle/Document/Answer.php +++ b/tests/Fixtures/TestBundle/Document/Answer.php @@ -13,8 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -24,10 +29,10 @@ * Answer. * * @ODM\Document - * @ApiResource(collectionOperations={ - * "get_subresource_answer"={"method"="GET", "normalization_context"={"groups"={"foobar"}}} - * }) */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(normalizationContext: ['groups' => ['foobar']])])] +#[ApiResource(uriTemplate: '/answers/{id}/related_questions/{relatedQuestions}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], toProperty: 'answer'), 'relatedQuestions' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/questions/{id}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] class Answer { /** @@ -35,23 +40,19 @@ class Answer * @Serializer\Groups({"foobar"}) */ private $id; - /** * @ODM\Field(nullable=false) * @Serializer\Groups({"foobar"}) */ private $content; - /** * @ODM\ReferenceOne(targetDocument=Question::class, mappedBy="answer") * @Serializer\Groups({"foobar"}) */ private $question; - /** * @ODM\ReferenceMany(targetDocument=Question::class, mappedBy="answer") * @Serializer\Groups({"foobar"}) - * @ApiSubresource */ private $relatedQuestions; diff --git a/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php b/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php index 66445aeeb3a..15f3b16594c 100644 --- a/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php +++ b/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayRequiredFilter; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -23,14 +23,9 @@ * * @author Julien Deniau * @author Alan Poulain - * - * @ApiResource(attributes={ - * "filters"={ - * ArrayRequiredFilter::class - * } - * }) * @ODM\Document */ +#[ApiResource(filters: [ArrayRequiredFilter::class])] class ArrayFilterValidator { /** @@ -39,7 +34,6 @@ class ArrayFilterValidator * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string A name * diff --git a/tests/Fixtures/TestBundle/Document/Book.php b/tests/Fixtures/TestBundle/Document/Book.php index b9846f71b07..bdb4a82304e 100644 --- a/tests/Fixtures/TestBundle/Document/Book.php +++ b/tests/Fixtures/TestBundle/Document/Book.php @@ -13,32 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Book. * * @author Antoine Bluchet - * - * @ApiResource(collectionOperations={}, itemOperations={ - * "get", - * "get_by_isbn"={"method"="GET", "path"="/books/by_isbn/{isbn}.{_format}", "requirements"={"isbn"=".+"}, "identifiers"="isbn"} - * }) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Get(uriTemplate: '/books/by_isbn/{isbn}.{_format}', requirements: ['isbn' => '.+'], uriVariables: 'isbn')])] class Book { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(type="string", nullable=true) */ public $name; - /** * @ODM\Field(type="string") */ diff --git a/tests/Fixtures/TestBundle/Document/CircularReference.php b/tests/Fixtures/TestBundle/Document/CircularReference.php index f49deadd91f..49a7e7ea3e1 100644 --- a/tests/Fixtures/TestBundle/Document/CircularReference.php +++ b/tests/Fixtures/TestBundle/Document/CircularReference.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,24 +22,21 @@ * Circular Reference. * * @author Kévin Dunglas - * - * @ApiResource(attributes={"normalization_context"={"groups"={"circular"}}}) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['circular']])] class CircularReference { /** * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; - /** * @ODM\ReferenceOne(targetDocument=CircularReference::class, inversedBy="children") * * @Groups({"circular"}) */ public $parent; - /** * @ODM\ReferenceMany(targetDocument=CircularReference::class, mappedBy="parent") * diff --git a/tests/Fixtures/TestBundle/Document/CompositeItem.php b/tests/Fixtures/TestBundle/Document/CompositeItem.php index c20b6409b4c..ceb261691fd 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeItem.php +++ b/tests/Fixtures/TestBundle/Document/CompositeItem.php @@ -13,29 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Item. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class CompositeItem { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(type="string", nullable=true) * @Groups({"default"}) */ private $field1; - /** * @ODM\ReferenceMany(targetDocument=CompositeRelation::class, mappedBy="compositeItem") * @Groups({"default"}) diff --git a/tests/Fixtures/TestBundle/Document/CompositeLabel.php b/tests/Fixtures/TestBundle/Document/CompositeLabel.php index 76ca3463157..007c3460138 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeLabel.php +++ b/tests/Fixtures/TestBundle/Document/CompositeLabel.php @@ -13,23 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Label. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class CompositeLabel { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(type="string", nullable=true) * @Groups({"default"}) diff --git a/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php b/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php index 71d27234ca5..259caabbb30 100644 --- a/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php +++ b/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php @@ -13,32 +13,29 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Composite Primitive Item. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class CompositePrimitiveItem { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(type="string") */ private $name; - /** * @ODM\Field(type="int") */ private $year; - /** * @ODM\Field(type="string") */ diff --git a/tests/Fixtures/TestBundle/Document/CompositeRelation.php b/tests/Fixtures/TestBundle/Document/CompositeRelation.php index e061d544d57..883cb36450b 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeRelation.php +++ b/tests/Fixtures/TestBundle/Document/CompositeRelation.php @@ -13,35 +13,32 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Composite Relation. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class CompositeRelation { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(type="string", nullable=true) * @Groups({"default"}) */ private $value; - /** * @ODM\ReferenceOne(targetDocument=CompositeItem::class, inversedBy="compositeValues") * @Groups({"default"}) */ private $compositeItem; - /** * @ODM\ReferenceOne(targetDocument=CompositeLabel::class) * @Groups({"default"}) diff --git a/tests/Fixtures/TestBundle/Document/ConcreteDummy.php b/tests/Fixtures/TestBundle/Document/ConcreteDummy.php index a5adb8f9bfe..5947f6c5925 100644 --- a/tests/Fixtures/TestBundle/Document/ConcreteDummy.php +++ b/tests/Fixtures/TestBundle/Document/ConcreteDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; @@ -21,10 +21,9 @@ * Concrete Dummy. * * @author Jérémy Derusse - * - * @ApiResource * @ODM\Document */ +#[ApiResource] class ConcreteDummy extends AbstractDummy { /** diff --git a/tests/Fixtures/TestBundle/Document/ContainNonResource.php b/tests/Fixtures/TestBundle/Document/ContainNonResource.php index f328bb2f96c..fab00379d52 100644 --- a/tests/Fixtures/TestBundle/Document/ContainNonResource.php +++ b/tests/Fixtures/TestBundle/Document/ContainNonResource.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\NotAResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -23,17 +23,9 @@ * * @ODM\Document * - * @ApiResource( - * attributes={ - * "filters"={"my_dummy.property"} - * }, - * normalizationContext={ - * "groups"={"contain_non_resource"} - * } - * ) - * * @author Kévin Dunglas */ +#[ApiResource(filters: ['my_dummy.property'], normalizationContext: ['groups' => ['contain_non_resource']])] class ContainNonResource { /** @@ -42,14 +34,12 @@ class ContainNonResource * @Groups("contain_non_resource") */ public $id; - /** * @var ContainNonResource * * @Groups("contain_non_resource") */ public $nested; - /** * @var NotAResource * diff --git a/tests/Fixtures/TestBundle/Document/Content.php b/tests/Fixtures/TestBundle/Document/Content.php index 914bfc2d968..2d4dcb7ed54 100644 --- a/tests/Fixtures/TestBundle/Document/Content.php +++ b/tests/Fixtures/TestBundle/Document/Content.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use ApiPlatform\Tests\Fixtures\TestBundle\Enum\ContentStatus; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -21,14 +22,9 @@ use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource( - * normalizationContext={ - * "groups"={"get_content"}, - * }, - * ) - * * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['get_content']])] class Content implements \JsonSerializable { /** @@ -37,14 +33,12 @@ class Content implements \JsonSerializable * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null * * @ODM\Field(type="string") */ private $contentType; - /** * @var Collection * @@ -56,7 +50,6 @@ class Content implements \JsonSerializable * ) */ private $fields; - /** * @var string * @@ -109,7 +102,6 @@ public function addField(Field $field): void if ($this->hasField($field->getName())) { throw new \InvalidArgumentException(sprintf("Content already has '%s' field", $field->getName())); } - $this->fields[$field->getName()] = $field; $field->setContent($this); } @@ -117,7 +109,6 @@ public function addField(Field $field): void public function removeField(Field $field): void { unset($this->fields[$field->getName()]); - // set the owning side to null (unless already changed) if ($field->getContent() === $this) { $field->setContent(null); @@ -153,10 +144,6 @@ public function getStatus(): ContentStatus #[\ReturnTypeWillChange] public function jsonSerialize() { - return [ - 'id' => $this->id, - 'contentType' => $this->contentType, - 'fields' => $this->fields, - ]; + return ['id' => $this->id, 'contentType' => $this->contentType, 'fields' => $this->fields]; } } diff --git a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php index c0c2e660ac1..ae0a24b9ae8 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\BooleanFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document - * @ApiFilter(BooleanFilter::class) + * @ApiFilter (BooleanFilter::class) */ +#[ApiResource] class ConvertedBoolean { /** @@ -31,7 +31,6 @@ class ConvertedBoolean * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var bool * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedDate.php b/tests/Fixtures/TestBundle/Document/ConvertedDate.php index 4439ccf57e2..84c0cf4b54e 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedDate.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document - * @ApiFilter(DateFilter::class) + * @ApiFilter (DateFilter::class) */ +#[ApiResource] class ConvertedDate { /** @@ -31,7 +31,6 @@ class ConvertedDate * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var \DateTime * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php index 0b590cf004e..2e9f7358c9f 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php @@ -14,19 +14,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\NumericFilter; use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document - * @ApiFilter(NumericFilter::class, properties={"nameConverted"}) - * @ApiFilter(RangeFilter::class, properties={"nameConverted"}) - * @ApiFilter(OrderFilter::class, properties={"nameConverted"}) + * @ApiFilter (NumericFilter::class, properties={"nameConverted"}) + * @ApiFilter (RangeFilter::class, properties={"nameConverted"}) + * @ApiFilter (OrderFilter::class, properties={"nameConverted"}) */ +#[ApiResource] class ConvertedInteger { /** @@ -35,7 +35,6 @@ class ConvertedInteger * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var int * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php index cfebc9e52a1..c1d8121c03f 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document - * @ApiFilter(SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) + * @ApiFilter (SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) */ +#[ApiResource] class ConvertedOwner { /** @@ -31,7 +31,6 @@ class ConvertedOwner * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var ConvertedRelated * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedRelated.php b/tests/Fixtures/TestBundle/Document/ConvertedRelated.php index 01e3a7037a5..3e7c60b77c8 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedRelated.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedRelated.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class ConvertedRelated { /** @@ -28,7 +28,6 @@ class ConvertedRelated * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedString.php b/tests/Fixtures/TestBundle/Document/ConvertedString.php index 09186981079..398f09932d6 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedString.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\ExistsFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document - * @ApiFilter(ExistsFilter::class, properties={"nameConverted"}) + * @ApiFilter (ExistsFilter::class, properties={"nameConverted"}) */ +#[ApiResource] class ConvertedString { /** @@ -31,7 +31,6 @@ class ConvertedString * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Document/CustomActionDummy.php b/tests/Fixtures/TestBundle/Document/CustomActionDummy.php index d46f1dcb19d..48ea7078c7b 100644 --- a/tests/Fixtures/TestBundle/Document/CustomActionDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomActionDummy.php @@ -13,26 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiResource(itemOperations={ - * "get", - * "get_custom"={"method"="GET", "path"="custom_action_collection_dummies/{id}"}, - * "custom_normalization"={"method"="GET", "route_name"="custom_normalization"}, - * "short_custom_normalization"={"method"="GET", "route_name"="short_custom_normalization"}, - * }, - * collectionOperations={ - * "get", - * "get_custom"={"method"="GET", "path"="custom_action_collection_dummies"}, - * "custom_denormalization"={"method"="POST", "route_name"="custom_denormalization"}, - * "short_custom_denormalization"={"method"="GET", "route_name"="short_custom_denormalization"}, - * }) * * @author Kévin Dunglas */ +#[ApiResource(operations: [new Get(), new Get(uriTemplate: 'custom_action_collection_dummies/{id}'), new Get(routeName: 'custom_normalization'), new Get(routeName: 'short_custom_normalization'), new GetCollection(), new GetCollection(uriTemplate: 'custom_action_collection_dummies'), new Post(routeName: 'custom_denormalization'), new GetCollection(routeName: 'short_custom_denormalization')])] class CustomActionDummy { /** @@ -41,7 +33,6 @@ class CustomActionDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php b/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php index 8cf70fc25e0..e5fbe366b91 100644 --- a/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php +++ b/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php @@ -13,16 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom identifier. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class CustomGeneratedIdentifier { /** diff --git a/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php index 976ed067c8b..df3254ede88 100644 --- a/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom Identifier Dummy. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class CustomIdentifierDummy { /** @@ -30,7 +30,6 @@ class CustomIdentifierDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $customId; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php index f727d7dab6b..98e69d900fe 100644 --- a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php @@ -14,15 +14,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom Identifier Dummy. * - * @ApiResource(compositeIdentifier=false) * @ODM\Document */ +#[ApiResource(uriVariables: ['firstId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['firstId']), 'secondId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['secondId'])])] class CustomMultipleIdentifierDummy { /** @@ -31,7 +32,6 @@ class CustomMultipleIdentifierDummy * @ODM\Id(strategy="NONE", type="int") */ private $firstId; - /** * @var int The custom identifier * @@ -39,7 +39,6 @@ class CustomMultipleIdentifierDummy * @ODM\Field(type="int") */ private $secondId; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php b/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php index a64c74a0ec8..b4f773c056c 100644 --- a/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,13 +23,9 @@ * Custom Normalized Dummy. * * @author Mikaël Labrut - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"output"}}, - * "denormalization_context"={"groups"={"input"}} - * }) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['output']], denormalizationContext: ['groups' => ['input']])] class CustomNormalizedDummy { /** @@ -39,7 +35,6 @@ class CustomNormalizedDummy * @Groups({"input", "output"}) */ private $id; - /** * @var string|null The dummy name * @@ -49,7 +44,6 @@ class CustomNormalizedDummy * @Groups({"input", "output"}) */ private $name; - /** * @var string|null The dummy name alias * diff --git a/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php index 8cdf14a1597..4f4e4510c8e 100644 --- a/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom Writable Identifier Dummy. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class CustomWritableIdentifierDummy { /** @@ -30,7 +30,6 @@ class CustomWritableIdentifierDummy * @ODM\Id(strategy="NONE", type="string") */ private $slug; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Document/Customer.php b/tests/Fixtures/TestBundle/Document/Customer.php index 05a9f3a7802..cdf8ca7b11a 100644 --- a/tests/Fixtures/TestBundle/Document/Customer.php +++ b/tests/Fixtures/TestBundle/Document/Customer.php @@ -13,17 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource( - * attributes={"normalization_context"={"groups"={"order_read"}}} - * ) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['order_read']])] class Customer { /** @@ -33,13 +31,11 @@ class Customer * @Groups({"order_read"}) */ private $id; - /** * @ODM\Field(type="string") * @Groups({"order_read"}) */ public $name; - /** * @ODM\ReferenceMany(targetDocument=Address::class) * @Groups({"order_read"}) diff --git a/tests/Fixtures/TestBundle/Document/DeprecatedResource.php b/tests/Fixtures/TestBundle/Document/DeprecatedResource.php index c591eb5036c..b7f4dc30f2d 100644 --- a/tests/Fixtures/TestBundle/Document/DeprecatedResource.php +++ b/tests/Fixtures/TestBundle/Document/DeprecatedResource.php @@ -14,22 +14,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource(deprecationReason="This resource is deprecated") * @ODM\Document * * @author Kévin Dunglas */ +#[ApiResource(deprecationReason: 'This resource is deprecated')] class DeprecatedResource { /** * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DisableItemOperation.php b/tests/Fixtures/TestBundle/Document/DisableItemOperation.php index aa083412728..f5b8401e504 100644 --- a/tests/Fixtures/TestBundle/Document/DisableItemOperation.php +++ b/tests/Fixtures/TestBundle/Document/DisableItemOperation.php @@ -14,31 +14,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Action\NotFoundAction; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource( - * collectionOperations={ - * "get", - * }, - * itemOperations={ - * "get"={ - * "controller"=NotFoundAction::class, - * "read"=false, - * "output"=false, - * }, - * }, - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(controller: NotFoundAction::class, read: false, output: false), new GetCollection()])] class DisableItemOperation { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Document/Dummy.php b/tests/Fixtures/TestBundle/Document/Dummy.php index e9f58f3d5d5..713a6fcc889 100644 --- a/tests/Fixtures/TestBundle/Document/Dummy.php +++ b/tests/Fixtures/TestBundle/Document/Dummy.php @@ -14,8 +14,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -26,26 +27,11 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * - * @ApiResource(attributes={ - * "doctrine_mongodb"={ - * "execute_options"={ - * "allowDiskUse"=true - * } - * }, - * "filters"={ - * "my_dummy.mongodb.boolean", - * "my_dummy.mongodb.date", - * "my_dummy.mongodb.exists", - * "my_dummy.mongodb.numeric", - * "my_dummy.mongodb.order", - * "my_dummy.mongodb.range", - * "my_dummy.mongodb.search", - * "my_dummy.property" - * } - * }) * @ODM\Document */ +#[ApiResource(extraProperties: ['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]], filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])] class Dummy { /** @@ -54,7 +40,6 @@ class Dummy * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ private $id; - /** * @var string|null The dummy name * @@ -63,7 +48,6 @@ class Dummy * @ApiProperty(iri="http://schema.org/name") */ private $name; - /** * @var string|null The dummy name alias * @@ -71,12 +55,10 @@ class Dummy * @ApiProperty(iri="https://schema.org/alternateName") */ private $alias; - /** * @var array|null foo */ private $foo; - /** * @var string|null A short description of the item * @@ -84,21 +66,18 @@ class Dummy * @ApiProperty(iri="https://schema.org/description") */ public $description; - /** * @var string|null A dummy * * @ODM\Field(nullable=true) */ public $dummy; - /** * @var bool|null A dummy boolean * * @ODM\Field(type="bool", nullable=true) */ public $dummyBoolean; - /** * @var \DateTime|null A dummy date * @@ -106,64 +85,53 @@ class Dummy * @ApiProperty(iri="http://schema.org/DateTime") */ public $dummyDate; - /** * @var float|null A dummy float * * @ODM\Field(type="float", nullable=true) */ public $dummyFloat; - /** * @var float|null A dummy price * * @ODM\Field(type="float", nullable=true) */ public $dummyPrice; - /** * @var RelatedDummy|null A related dummy * * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ public $relatedDummy; - /** - * @var Collection Several dummies - * + * @var \Collection Several dummies * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) - * @ApiSubresource */ public $relatedDummies; - /** * @var array serialize data * * @ODM\Field(type="hash", nullable=true) */ public $jsonData; - /** * @var array * * @ODM\Field(type="collection", nullable=true) */ public $arrayData; - /** * @var string|null * * @ODM\Field(nullable=true) */ public $nameConverted; - /** * @var RelatedOwnedDummy|null * * @ODM\ReferenceOne(targetDocument=RelatedOwnedDummy::class, cascade={"persist"}, mappedBy="owningDummy", nullable=true) */ public $relatedOwnedDummy; - /** * @var RelatedOwningDummy|null * @@ -297,7 +265,6 @@ public function getRelatedOwnedDummy() public function setRelatedOwnedDummy(RelatedOwnedDummy $relatedOwnedDummy) { $this->relatedOwnedDummy = $relatedOwnedDummy; - if ($this !== $this->relatedOwnedDummy->getOwningDummy()) { $this->relatedOwnedDummy->setOwningDummy($this); } diff --git a/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php index f2be0264129..7741a626365 100644 --- a/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php @@ -13,20 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Aggregate Offer. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_products/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] class DummyAggregateOffer { /** @@ -35,22 +38,17 @@ class DummyAggregateOffer * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** - * @var ArrayCollection - * - * @ApiSubresource + * @var \ArrayCollection * @ODM\ReferenceMany(targetDocument=DummyOffer::class, mappedBy="aggregate", cascade={"persist"}) */ private $offers; - /** * @var DummyProduct The dummy product * * @ODM\ReferenceOne(targetDocument=DummyProduct::class, inversedBy="offers", storeAs="id") */ private $product; - /** * @var int The dummy aggregate offer value * diff --git a/tests/Fixtures/TestBundle/Document/DummyBoolean.php b/tests/Fixtures/TestBundle/Document/DummyBoolean.php index 7a3fe973deb..f60e664da4c 100644 --- a/tests/Fixtures/TestBundle/Document/DummyBoolean.php +++ b/tests/Fixtures/TestBundle/Document/DummyBoolean.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class DummyBoolean { /** @@ -28,7 +28,6 @@ class DummyBoolean * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ private $id; - /** * @var bool * diff --git a/tests/Fixtures/TestBundle/Document/DummyCar.php b/tests/Fixtures/TestBundle/Document/DummyCar.php index 8c8783d9905..9eae42c488e 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCar.php +++ b/tests/Fixtures/TestBundle/Document/DummyCar.php @@ -14,10 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Serializer\Filter\GroupFilter; use ApiPlatform\Serializer\Filter\PropertyFilter; use Doctrine\Common\Collections\ArrayCollection; @@ -25,20 +30,14 @@ use Symfony\Component\Serializer\Annotation as Serializer; /** - * @ApiResource( - * itemOperations={"get"={"swagger_context"={"tags"={}}, "openapi_context"={"tags"={}}}, "put", "delete"}, - * attributes={ - * "sunset"="2050-01-01", - * "normalization_context"={"groups"={"colors"}} - * } - * ) * @ODM\Document - * @ApiFilter(DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) - * @ApiFilter(BooleanFilter::class) - * @ApiFilter(PropertyFilter::class, arguments={"parameterName"="foobar"}) - * @ApiFilter(GroupFilter::class, arguments={"parameterName"="foobargroups"}) - * @ApiFilter(GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") + * @ApiFilter (DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) + * @ApiFilter (BooleanFilter::class) + * @ApiFilter (PropertyFilter::class, arguments={"parameterName"="foobar"}) + * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups"}) + * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") */ +#[ApiResource(operations: [new Get(openapiContext: ['tags' => []]), new Put(), new Delete(), new Post(), new GetCollection()], sunset: '2050-01-01', normalizationContext: ['groups' => ['colors']])] class DummyCar { /** @@ -47,7 +46,6 @@ class DummyCar * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var mixed Something else * @@ -57,7 +55,6 @@ class DummyCar * @ApiFilter(SearchFilter::class, properties={"colors.prop"="ipartial", "colors"="exact"}) */ private $colors; - /** * @var mixed Something else * @@ -67,7 +64,6 @@ class DummyCar * @ApiFilter(SearchFilter::class, strategy="exact") */ private $secondColors; - /** * @var mixed Something else * @@ -77,7 +73,6 @@ class DummyCar * @ApiFilter(SearchFilter::class, strategy="exact") */ private $thirdColors; - /** * @var mixed Something else * @@ -87,7 +82,6 @@ class DummyCar * @ApiFilter(SearchFilter::class, strategy="exact") */ private $uuid; - /** * @var string * @@ -95,21 +89,18 @@ class DummyCar * @ApiFilter(SearchFilter::class, strategy="partial") */ private $name; - /** * @var bool * * @ODM\Field(type="bool") */ private $canSell; - /** * @var \DateTime * * @ODM\Field(type="date") */ private $availableAt; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyCarColor.php b/tests/Fixtures/TestBundle/Document/DummyCarColor.php index d2f4e50d454..098bb012d9b 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Document/DummyCarColor.php @@ -14,16 +14,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class DummyCarColor { /** @@ -32,7 +32,6 @@ class DummyCarColor * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var DummyCar * @@ -40,7 +39,6 @@ class DummyCarColor * @Assert\NotBlank */ private $car; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php b/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php index 234c9b69a53..0340046b7c6 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; /** - * @ApiResource(attributes={"formats"={"xml", "jsonld", "csv"={"text/csv"}, "pdf"="application/pdf"}}) * @ODM\Document */ +#[ApiResource(formats: ['xml', 'jsonld', 'csv' => ['text/csv'], 'pdf' => 'application/pdf'])] class DummyCustomFormat { /** @@ -29,7 +29,6 @@ class DummyCustomFormat * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php index 1415f88fea3..3de558aff3b 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,44 +23,10 @@ * Dummy with a custom GraphQL mutation resolver. * * @ODM\Document - * @ApiResource(graphql={ - * "sum"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNotPersisted"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNoWriteCustomResult"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "write"=false - * }, - * "sumOnlyPersist"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist_document", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "read"=false, - * "deserialize"=false, - * "validate"=false, - * "serialize"=false - * }, - * "testCustomArguments"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "args"={"operandC"={"type"="Int!"}} - * }, - * "testOutput"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "output"=OutputDto::class - * } - * }) * * @author Raoul Clais */ +#[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist_document', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']]), new Mutation(name: 'testOutput', resolver: 'app.graphql.mutation_resolver.dummy_custom', output: OutputDto::class)])] class DummyCustomMutation { /** @@ -68,14 +35,12 @@ class DummyCustomMutation * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var int|null * * @ODM\Field(type="int") */ private $operandA; - /** * @var int|null * @@ -83,7 +48,6 @@ class DummyCustomMutation * @ODM\Field(type="int", nullable=true) */ private $operandB; - /** * @var int|null * diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php index d8590c32575..3a02cef3aab 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -21,54 +23,9 @@ * Dummy with custom GraphQL query resolvers. * * @author Lukas Lücke - * - * @ApiResource(graphql={ - * "testItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item" - * }, - * "testNotRetrievedItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item_document", - * "args"={} - * }, - * "testNoReadAndSerializeItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document", - * "read"=false, - * "serialize"=false - * }, - * "testItemCustomArguments"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item", - * "args"={ - * "id"={"type"="ID"}, - * "customArgumentNullableBool"={"type"="Boolean"}, - * "customArgumentBool"={"type"="Boolean!"}, - * "customArgumentInt"={"type"="Int!"}, - * "customArgumentString"={"type"="String!"}, - * "customArgumentFloat"={"type"="Float!"}, - * "customArgumentIntArray"={"type"="[Int!]!"}, - * "customArgumentCustomType"={"type"="DateTime!"} - * } - * }, - * "testItemOutput"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item", - * "output"=OutputDto::class - * }, - * "testCollection"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection" - * }, - * "testCollectionNoReadAndSerialize"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testCollectionCustomArguments"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection", - * "args"={ - * "customArgumentString"={"type"="String!"} - * } - * } - * }) * @ODM\Document */ +#[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item_document', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new Query(name: 'testItemOutput', resolver: 'app.graphql.query_resolver.dummy_custom_item', output: OutputDto::class), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])] class DummyCustomQuery { /** @@ -77,12 +34,10 @@ class DummyCustomQuery * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; - /** * @var string */ public $message; - /** * @var array */ diff --git a/tests/Fixtures/TestBundle/Document/DummyDate.php b/tests/Fixtures/TestBundle/Document/DummyDate.php index 047384ef83d..9a031d0263b 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyDate.php @@ -14,9 +14,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** @@ -24,19 +25,15 @@ * * @author Antoine Bluchet * @author Alan Poulain - * - * @ApiResource(attributes={ - * "filters"={"my_dummy_date.mongodb.date"} - * }) - * @ApiFilter(SearchFilter::class, properties={"dummyDate"}) - * @ApiFilter(DateFilter::class, properties={ + * @ApiFilter (SearchFilter::class, properties={"dummyDate"}) + * @ApiFilter (DateFilter::class, properties={ * "dateIncludeNullAfter"=DateFilter::INCLUDE_NULL_AFTER, * "dateIncludeNullBefore"=DateFilter::INCLUDE_NULL_BEFORE, * "dateIncludeNullBeforeAndAfter"=DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER * }) - * * @ODM\Document */ +#[ApiResource(filters: ['my_dummy_date.mongodb.date'])] class DummyDate { /** @@ -45,28 +42,24 @@ class DummyDate * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var \DateTime|null The dummy date * * @ODM\Field(type="date") */ public $dummyDate; - /** * @var \DateTime|null * * @ODM\Field(type="date") */ public $dateIncludeNullAfter; - /** * @var \DateTime|null * * @ODM\Field(type="date") */ public $dateIncludeNullBefore; - /** * @var \DateTime|null * diff --git a/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php b/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php index a31a1ca6ac7..432f52a6912 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php +++ b/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,15 +23,9 @@ * Dummy with different serialization groups for item_query and collection_query. * * @author Mahmood Bazdar - * - * @ApiResource( - * graphql={ - * "item_query"={"normalization_context"={"groups"={"item_query"}}}, - * "collection_query"={"normalization_context"={"groups"={"collection_query"}}} - * } - * ) * @ODM\Document */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['item_query']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['collection_query']])])] class DummyDifferentGraphQlSerializationGroup { /** @@ -39,7 +35,6 @@ class DummyDifferentGraphQlSerializationGroup * @Groups({"item_query", "collection_query"}) */ private $id; - /** * @var string|null The dummy name * @@ -47,7 +42,6 @@ class DummyDifferentGraphQlSerializationGroup * @Groups({"item_query", "collection_query"}) */ private $name; - /** * @var string|null The dummy title * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php index 804df82333e..19f0b0615b6 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomInputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomOutputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -22,12 +27,8 @@ * DummyDtoCustom. * * @ODM\Document - * - * @ApiResource( - * collectionOperations={"post"={"input"=CustomInputDto::class}, "get", "custom_output"={"output"=CustomOutputDto::class, "path"="dummy_dto_custom_output", "method"="GET"}, "post_without_output"={"output"=false, "method"="POST", "path"="dummy_dto_custom_post_without_output"}}, - * itemOperations={"get", "custom_output"={"output"=CustomOutputDto::class, "method"="GET", "path"="dummy_dto_custom_output/{id}"}, "put", "delete"} - * ) */ +#[ApiResource(operations: [new Get(), new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), new Put(), new Delete(), new Post(input: CustomInputDto::class), new GetCollection(), new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output')])] class DummyDtoCustom { /** @@ -36,14 +37,12 @@ class DummyDtoCustom * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string * * @ODM\Field */ public $lorem; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php b/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php index 3001d0901c6..d7a9831f9f4 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\InputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto; use Doctrine\Common\Collections\ArrayCollection; @@ -24,35 +24,30 @@ * Dummy InputOutput. * * @author Kévin Dunglas - * - * @ApiResource(attributes={"input"=InputDto::class, "output"=OutputDto::class}) * @ODM\Document */ +#[ApiResource(input: InputDto::class, output: OutputDto::class)] class DummyDtoInputOutput { public function __construct() { $this->relatedDummies = new ArrayCollection(); } - /** * @var int The id * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ public $id; - /** * @var string * @ODM\Field */ public $str; - /** * @var int * @ODM\Field(type="float") */ public $num; - /** * @var Collection * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php index 2166bf2a69a..3583477b161 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php @@ -13,7 +13,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\CreateItemAction; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\DoubleBatAction; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto; @@ -23,34 +27,9 @@ * DummyDtoNoInput. * * @author Vincent Chalamon - * * @ODM\Document - * - * @ApiResource( - * attributes={ - * "input"=false, - * "output"=OutputDto::class - * }, - * collectionOperations={ - * "post"={ - * "method"="POST", - * "path"="/dummy_dto_no_inputs", - * "controller"=CreateItemAction::class, - * }, - * "get", - * }, - * itemOperations={ - * "get", - * "delete", - * "post_double_bat"={ - * "method"="POST", - * "path"="/dummy_dto_no_inputs/{id}/double_bat", - * "controller"=DoubleBatAction::class, - * "status"=200, - * }, - * }, - * ) */ +#[ApiResource(operations: [new Get(), new Delete(), new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200), new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class), new GetCollection()], input: false, output: OutputDto::class)] class DummyDtoNoInput { /** @@ -59,14 +38,12 @@ class DummyDtoNoInput * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string * * @ODM\Field */ public $lorem; - /** * @var float * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php b/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php index ac627a8652f..dcc63c4762a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -21,16 +21,9 @@ * DummyDtoNoOutput. * * @author Vincent Chalamon - * * @ODM\Document - * - * @ApiResource( - * attributes={ - * "input"=InputDto::class, - * "output"=false - * } - * ) */ +#[ApiResource(input: InputDto::class, output: false)] class DummyDtoNoOutput { /** @@ -39,14 +32,12 @@ class DummyDtoNoOutput * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string * * @ODM\Field */ public $lorem; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php index 399bec0645b..a87f7192099 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDtoDummy; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -21,10 +21,9 @@ * Dummy InputOutput. * * @author Daniel West - * - * @ApiResource(attributes={"output"=OutputDtoDummy::class}) * @ODM\Document */ +#[ApiResource(output: OutputDtoDummy::class)] class DummyDtoOutputFallbackToSameClass { /** @@ -33,14 +32,12 @@ class DummyDtoOutputFallbackToSameClass * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ private $id; - /** * @var string * * @ODM\Field */ public $lorem; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php index b99988cba90..52608d96c90 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php @@ -13,17 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy InputOutput. * * @author Daniel West - * - * @ApiResource(attributes={"output"=DummyDtoOutputSameClass::class}) * @ODM\Document */ +#[ApiResource(output: DummyDtoOutputSameClass::class)] class DummyDtoOutputSameClass { /** @@ -32,14 +31,12 @@ class DummyDtoOutputSameClass * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ private $id; - /** * @var string * * @ODM\Field */ public $lorem; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php b/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php index e8ddbd35b51..83d1ce1984a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php +++ b/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php @@ -13,25 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\DummyObjectWithoutConstructor; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy entity built with constructor. + * * https://github.com/api-platform/core/issues/1747. * * @author Maxime Veber - * - * @ApiResource( - * itemOperations={ - * "get", - * "put"={"denormalization_context"={"groups"={"put"}}} - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(denormalizationContext: ['groups' => ['put']]), new Post(), new GetCollection()])] class DummyEntityWithConstructor { /** @@ -40,21 +39,18 @@ class DummyEntityWithConstructor * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string * * @ODM\Field */ private $foo; - /** * @var string * * @ODM\Field */ private $bar; - /** * @var string|null * @@ -62,7 +58,6 @@ class DummyEntityWithConstructor * @Groups({"put"}) */ private $baz; - /** * @var DummyObjectWithoutConstructor[] */ diff --git a/tests/Fixtures/TestBundle/Document/DummyFriend.php b/tests/Fixtures/TestBundle/Document/DummyFriend.php index 15c16f985a2..17264a8b247 100644 --- a/tests/Fixtures/TestBundle/Document/DummyFriend.php +++ b/tests/Fixtures/TestBundle/Document/DummyFriend.php @@ -14,7 +14,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -24,10 +25,9 @@ * * @author Kévin Dunglas * @author Alan Poulain - * - * @ApiResource * @ODM\Document */ +#[ApiResource] class DummyFriend { /** @@ -36,7 +36,6 @@ class DummyFriend * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null The dummy name * diff --git a/tests/Fixtures/TestBundle/Document/DummyGroup.php b/tests/Fixtures/TestBundle/Document/DummyGroup.php index dd3690af07a..f3a285851dd 100644 --- a/tests/Fixtures/TestBundle/Document/DummyGroup.php +++ b/tests/Fixtures/TestBundle/Document/DummyGroup.php @@ -13,7 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,31 +25,9 @@ * * @author Baptiste Meyer * @author Alan Poulain - * * @ODM\Document - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}}, - * "filters"={ - * "dummy_group.group", - * "dummy_group.override_group", - * "dummy_group.whitelist_group", - * "dummy_group.override_whitelist_group" - * } - * }, - * graphql={ - * "item_query"={"normalization_context"={"groups"={"dummy_foo"}}}, - * "collection_query"={"normalization_context"={"groups"={"dummy_foo"}}}, - * "delete", - * "create"={ - * "normalization_context"={"groups"={"dummy_bar"}}, - * "denormalization_context"={"groups"={"dummy_bar", "dummy_baz"}} - * } - * } - * ) */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['dummy_foo']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['dummy_foo']]), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_bar']], denormalizationContext: ['groups' => ['dummy_bar', 'dummy_baz']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_group.group', 'dummy_group.override_group', 'dummy_group.whitelist_group', 'dummy_group.override_whitelist_group'])] class DummyGroup { /** @@ -57,7 +38,6 @@ class DummyGroup * @Groups({"dummy", "dummy_read", "dummy_id"}) */ private $id; - /** * @var string|null * @@ -66,7 +46,6 @@ class DummyGroup * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_foo"}) */ public $foo; - /** * @var string|null * @@ -75,7 +54,6 @@ class DummyGroup * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_bar"}) */ public $bar; - /** * @var string|null * @@ -84,7 +62,6 @@ class DummyGroup * @Groups({"dummy", "dummy_read", "dummy_baz"}) */ public $baz; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php b/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php index a46d64b3cbb..bea42a31140 100644 --- a/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php @@ -13,18 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Date Immutable. * - * @ApiResource(attributes={ - * "filters"={"my_dummy_immutable_date.mongodb.date"} - * }) - * * @ODM\Document */ +#[ApiResource(filters: ['my_dummy_immutable_date.mongodb.date'])] class DummyImmutableDate { /** @@ -33,7 +31,6 @@ class DummyImmutableDate * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var \DateTimeImmutable The dummy date * diff --git a/tests/Fixtures/TestBundle/Document/DummyMercure.php b/tests/Fixtures/TestBundle/Document/DummyMercure.php index 728727a18c4..83b2af26f79 100644 --- a/tests/Fixtures/TestBundle/Document/DummyMercure.php +++ b/tests/Fixtures/TestBundle/Document/DummyMercure.php @@ -13,32 +13,29 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiResource(mercure=true) * * @author Kévin Dunglas */ +#[ApiResource(mercure: true)] class DummyMercure { /** * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; - /** * @ODM\Field(type="string") */ public $name; - /** * @ODM\Field(type="string") */ public $description; - /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ diff --git a/tests/Fixtures/TestBundle/Document/DummyOffer.php b/tests/Fixtures/TestBundle/Document/DummyOffer.php index 6d9be6aa65c..bd86f54cf3c 100644 --- a/tests/Fixtures/TestBundle/Document/DummyOffer.php +++ b/tests/Fixtures/TestBundle/Document/DummyOffer.php @@ -13,18 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Offer. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_aggregate_offers/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] class DummyOffer { /** @@ -33,14 +38,12 @@ class DummyOffer * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var int The dummy aggregate offer value * * @ODM\Field(type="int") */ private $value; - /** * @var DummyAggregateOffer The dummy aggregate offer value * diff --git a/tests/Fixtures/TestBundle/Document/DummyPassenger.php b/tests/Fixtures/TestBundle/Document/DummyPassenger.php index f66c1a079ce..28dc7353327 100644 --- a/tests/Fixtures/TestBundle/Document/DummyPassenger.php +++ b/tests/Fixtures/TestBundle/Document/DummyPassenger.php @@ -13,20 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class DummyPassenger { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(type="string") */ diff --git a/tests/Fixtures/TestBundle/Document/DummyProduct.php b/tests/Fixtures/TestBundle/Document/DummyProduct.php index 7d5dc130b61..f475f76f528 100644 --- a/tests/Fixtures/TestBundle/Document/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Document/DummyProduct.php @@ -13,21 +13,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy Product. + * * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * - * @ApiResource * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, operations: [new GetCollection()])] class DummyProduct { /** @@ -36,30 +38,22 @@ class DummyProduct * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** - * @var Collection - * - * @ApiSubresource + * @var \Collection * @ODM\ReferenceMany(targetDocument=DummyAggregateOffer::class, mappedBy="product", cascade={"persist"}) */ private $offers; - /** * @var string The tour name * * @ODM\Field */ private $name; - /** - * @var Collection - * - * @ApiSubresource + * @var \Collection * @ODM\ReferenceMany(targetDocument=DummyProduct::class, mappedBy="parent") */ private $relatedProducts; - /** * @ODM\ReferenceOne(targetDocument=DummyProduct::class, inversedBy="relatedProducts") */ diff --git a/tests/Fixtures/TestBundle/Document/DummyProperty.php b/tests/Fixtures/TestBundle/Document/DummyProperty.php index c3803c0c0de..23f56b8206f 100644 --- a/tests/Fixtures/TestBundle/Document/DummyProperty.php +++ b/tests/Fixtures/TestBundle/Document/DummyProperty.php @@ -13,7 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,30 +24,9 @@ * DummyProperty. * * @author Baptiste Meyer - * * @ODM\Document - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"dummy_read"}}, - * "denormalization_context"={"groups"={"dummy_write"}}, - * "filters"={ - * "dummy_property.property", - * "dummy_property.whitelist_property", - * "dummy_property.whitelisted_properties" - * } - * }, - * graphql={ - * "item_query", - * "collection_query", - * "update", - * "delete", - * "create"={ - * "normalization_context"={"groups"={"dummy_graphql_read"}}, - * } - * } - * ) */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query'), new Mutation(name: 'update'), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_graphql_read']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_property.property', 'dummy_property.whitelist_property', 'dummy_property.whitelisted_properties'])] class DummyProperty { /** @@ -55,7 +37,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read"}) */ private $id; - /** * @var string|null * @@ -64,7 +45,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_write"}) */ public $foo; - /** * @var string|null * @@ -73,7 +53,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ public $bar; - /** * @var string|null * @@ -82,7 +61,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ public $baz; - /** * @var DummyGroup|null * @@ -91,7 +69,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ public $group; - /** * @var DummyGroup[]|null * @@ -99,7 +76,6 @@ class DummyProperty * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ public $groups; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php index 4eaea82d145..97bf357a15b 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php @@ -13,22 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * @ODM\Document - * @ODM\InheritanceType("SINGLE_COLLECTION") - * @ODM\DiscriminatorField(value="discr") - * @ODM\DiscriminatorMap({ + * @ODM\InheritanceType ("SINGLE_COLLECTION") + * @ODM\DiscriminatorField (value="discr") + * @ODM\DiscriminatorMap ({ * "dummyTableInheritance"=DummyTableInheritance::class, * "dummyTableInheritanceChild"=DummyTableInheritanceChild::class, * "dummyTableInheritanceDifferentChild"=DummyTableInheritanceDifferentChild::class, * "dummyTableInheritanceNotApiResourceChild"=DummyTableInheritanceNotApiResourceChild::class * }) - * @ApiResource */ +#[ApiResource] class DummyTableInheritance { /** @@ -39,7 +39,6 @@ class DummyTableInheritance * @Groups({"default"}) */ private $id; - /** * @var string|null The dummy name * @@ -48,7 +47,6 @@ class DummyTableInheritance * @Groups({"default"}) */ private $name; - /** * @var DummyTableInheritanceRelated|null * diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php index 775a9357903..16233935104 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * @ODM\Document - * @ApiResource */ +#[ApiResource] class DummyTableInheritanceChild extends DummyTableInheritance { /** diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php index b738bd28c53..03eecfc2777 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * @ODM\Document - * @ApiResource */ +#[ApiResource] class DummyTableInheritanceDifferentChild extends DummyTableInheritance { /** diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php index 8ddf0f6714f..6435a8efccf 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -21,13 +21,8 @@ /** * @ODM\Document - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"default"}}, - * "denormalization_context"={"groups"={"default"}} - * } - * ) */ +#[ApiResource(normalizationContext: ['groups' => ['default']], denormalizationContext: ['groups' => ['default']])] class DummyTableInheritanceRelated { /** @@ -38,7 +33,6 @@ class DummyTableInheritanceRelated * @Groups({"default"}) */ private $id; - /** * @var Collection Related children * diff --git a/tests/Fixtures/TestBundle/Document/DummyTravel.php b/tests/Fixtures/TestBundle/Document/DummyTravel.php index 6fd7e5bd85d..ca6011029c2 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTravel.php +++ b/tests/Fixtures/TestBundle/Document/DummyTravel.php @@ -13,30 +13,27 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource(filters={"dummy_travel.property"}) * @ODM\Document */ +#[ApiResource(filters: ['dummy_travel.property'])] class DummyTravel { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\ReferenceOne(targetDocument=DummyCar::class) */ public $car; - /** * @ODM\Field(type="bool") */ public $confirmed; - /** * @ODM\ReferenceOne(targetDocument=DummyPassenger::class) */ diff --git a/tests/Fixtures/TestBundle/Document/DummyValidation.php b/tests/Fixtures/TestBundle/Document/DummyValidation.php index d042da0c952..69f62e67788 100644 --- a/tests/Fixtures/TestBundle/Document/DummyValidation.php +++ b/tests/Fixtures/TestBundle/Document/DummyValidation.php @@ -13,21 +13,20 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; /** * @ODM\Document - * @ApiResource( - * collectionOperations={ - * "get"={"method"="GET"}, - * "post"={"path"="dummy_validation.{_format}", "method"="POST"}, - * "post_validation_groups"={"route_name"="post_validation_groups", "validation_groups"={"a"}, "method"="GET"}, - * "post_validation_sequence"={"route_name"="post_validation_sequence", "validation_groups"="app.dummy_validation.group_generator", "method"="GET"} - * } - * ) */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new Post(uriTemplate: 'dummy_validation.{_format}'), new GetCollection(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]), new GetCollection(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator'])])] class DummyValidation { /** @@ -36,7 +35,6 @@ class DummyValidation * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null The dummy name * @@ -44,7 +42,6 @@ class DummyValidation * @Assert\NotNull(groups={"a"}) */ private $name; - /** * @var string|null The dummy title * @@ -52,7 +49,6 @@ class DummyValidation * @Assert\NotNull(groups={"b"}) */ private $title; - /** * @var string|null The dummy code * @ODM\Field diff --git a/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php b/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php index 60e40ae026e..1d53cd585eb 100644 --- a/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php +++ b/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class DummyWithEmbedManyOmittingTargetDocument { /** @@ -30,7 +30,6 @@ class DummyWithEmbedManyOmittingTargetDocument * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var EmbeddableDummy[]|Collection * diff --git a/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php b/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php index bb81f658554..ce0bb5fab40 100644 --- a/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php +++ b/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,13 +28,9 @@ * * @author Jordan Samouh * @author Alexandre Delplace - * - * @ApiResource( - * attributes={"filters"={"my_dummy.mongodb.search", "my_dummy.mongodb.order", "my_dummy.mongodb.date", "my_dummy.mongodb.boolean"}}, - * itemOperations={"get", "put", "delete", "groups"={"method"="GET", "path"="/embedded_dummies_groups/{id}", "normalization_context"={"groups"={"embed"}}}} - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(uriTemplate: '/embedded_dummies_groups/{id}', normalizationContext: ['groups' => ['embed']]), new Post(), new GetCollection()], filters: ['my_dummy.mongodb.search', 'my_dummy.mongodb.order', 'my_dummy.mongodb.date', 'my_dummy.mongodb.boolean'])] class EmbeddedDummy { /** @@ -38,7 +39,6 @@ class EmbeddedDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null The dummy name * @@ -46,7 +46,6 @@ class EmbeddedDummy * @Groups({"embed"}) */ private $name; - /** * @var \DateTime|null A dummy date * @@ -54,7 +53,6 @@ class EmbeddedDummy * @Assert\DateTime */ public $dummyDate; - /** * @var EmbeddableDummy * @@ -62,7 +60,6 @@ class EmbeddedDummy * @Groups({"embed"}) */ public $embeddedDummy; - /** * @var RelatedDummy|null A related dummy * diff --git a/tests/Fixtures/TestBundle/Document/FilterValidator.php b/tests/Fixtures/TestBundle/Document/FilterValidator.php index 8977d654295..e02b8b954e1 100644 --- a/tests/Fixtures/TestBundle/Document/FilterValidator.php +++ b/tests/Fixtures/TestBundle/Document/FilterValidator.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayItemsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\BoundsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\EnumFilter; @@ -30,21 +30,9 @@ * * @author Julien Deniau * @author Alan Poulain - * - * @ApiResource(attributes={ - * "filters"={ - * ArrayItemsFilter::class, - * BoundsFilter::class, - * EnumFilter::class, - * LengthFilter::class, - * MultipleOfFilter::class, - * PatternFilter::class, - * RequiredFilter::class, - * RequiredAllowEmptyFilter::class - * } - * }) * @ODM\Document */ +#[ApiResource(filters: [ArrayItemsFilter::class, BoundsFilter::class, EnumFilter::class, LengthFilter::class, MultipleOfFilter::class, PatternFilter::class, RequiredFilter::class, RequiredAllowEmptyFilter::class])] class FilterValidator { /** @@ -53,7 +41,6 @@ class FilterValidator * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string A name * diff --git a/tests/Fixtures/TestBundle/Document/Foo.php b/tests/Fixtures/TestBundle/Document/Foo.php index a514338d251..a79a8a1db60 100644 --- a/tests/Fixtures/TestBundle/Document/Foo.php +++ b/tests/Fixtures/TestBundle/Document/Foo.php @@ -13,32 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Foo. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={ - * "order"={"bar", "name"="DESC"} - * }, - * graphql={ - * "item_query", - * "collection_query"={"pagination_enabled"=false}, - * "create", - * "delete" - * }, - * collectionOperations={ - * "get", - * "get_desc_custom"={"method"="GET", "path"="custom_collection_desc_foos", "order"={"name"="DESC"}}, - * "get_asc_custom"={"method"="GET", "path"="custom_collection_asc_foos", "order"={ "name"="ASC"}}, - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new GetCollection(uriTemplate: 'custom_collection_desc_foos', order: ['name' => 'DESC']), new GetCollection(uriTemplate: 'custom_collection_asc_foos', order: ['name' => 'ASC'])], graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query', paginationEnabled: false), new Mutation(name: 'create'), new Mutation(name: 'delete')], order: ['bar', 'name' => 'DESC'])] class Foo { /** @@ -47,14 +39,12 @@ class Foo * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The foo name * * @ODM\Field */ private $name; - /** * @var string The foo bar * diff --git a/tests/Fixtures/TestBundle/Document/FooDummy.php b/tests/Fixtures/TestBundle/Document/FooDummy.php index 745ec75903f..351084cdbef 100644 --- a/tests/Fixtures/TestBundle/Document/FooDummy.php +++ b/tests/Fixtures/TestBundle/Document/FooDummy.php @@ -13,24 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * FooDummy. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={ - * "order"={"dummy.name"} - * }, - * graphql={ - * "collection_query"={"pagination_type"="page"} - * } - * ) * @ODM\Document */ +#[ApiResource(graphQlOperations: [new QueryCollection(name: 'collection_query', paginationType: 'page')], order: ['dummy.name'])] class FooDummy { /** @@ -39,14 +32,12 @@ class FooDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The foo name * * @ODM\Field */ private $name; - /** * @var Dummy The foo dummy * diff --git a/tests/Fixtures/TestBundle/Document/FourthLevel.php b/tests/Fixtures/TestBundle/Document/FourthLevel.php index 4d98d78339d..2856be2848e 100644 --- a/tests/Fixtures/TestBundle/Document/FourthLevel.php +++ b/tests/Fixtures/TestBundle/Document/FourthLevel.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,10 +23,15 @@ * Fourth Level. * * @author Alan Poulain - * - * @ApiResource * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/third_levels/{id}/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: ['id'], fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] class FourthLevel { /** @@ -33,7 +40,6 @@ class FourthLevel * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var int|null * @@ -41,7 +47,6 @@ class FourthLevel * @Groups({"barcelona", "chicago"}) */ private $level = 4; - /** * @ODM\ReferenceMany(targetDocument=ThirdLevel::class, cascade={"persist"}, mappedBy="badFourthLevel", storeAs="id") */ diff --git a/tests/Fixtures/TestBundle/Document/Greeting.php b/tests/Fixtures/TestBundle/Document/Greeting.php index 06b347281a4..0882ed1965e 100644 --- a/tests/Fixtures/TestBundle/Document/Greeting.php +++ b/tests/Fixtures/TestBundle/Document/Greeting.php @@ -13,30 +13,30 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/people/{id}/sent_greetings.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Person::class, identifiers: ['id'], toProperty: 'sender')], status: 200, operations: [new GetCollection()])] class Greeting { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field */ public $message = ''; - /** * @ODM\ReferenceOne(targetDocument=Person::class, inversedBy="sentGreetings", storeAs="id") */ public $sender; - /** * @ODM\ReferenceOne(targetDocument=Person::class) */ diff --git a/tests/Fixtures/TestBundle/Document/InitializeInput.php b/tests/Fixtures/TestBundle/Document/InitializeInput.php index 5b289212c74..dc661322ba9 100644 --- a/tests/Fixtures/TestBundle/Document/InitializeInput.php +++ b/tests/Fixtures/TestBundle/Document/InitializeInput.php @@ -13,26 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource(input=InitializeInputDto::class) * @ODM\Document */ +#[ApiResource(input: InitializeInputDto::class)] class InitializeInput { /** * @ODM\Id(strategy="NONE", type="int") */ public $id; - /** * @ODM\Field */ public $manager; - /** * @ODM\Field */ diff --git a/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php b/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php index 7ace4cfc07b..b47f9fb6f95 100644 --- a/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php +++ b/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php @@ -13,22 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy with iri_only. * * @author Pierre Thibaudeau - * - * @ApiResource( - * normalizationContext={ - * "iri_only"=true, - * "jsonld_embed_context"=true - * } - * ) * @ODM\Document */ +#[ApiResource(normalizationContext: ['iri_only' => true, 'jsonld_embed_context' => true])] class IriOnlyDummy { /** @@ -37,7 +31,6 @@ class IriOnlyDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php b/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php index 4e2085fcd04..5a062b79491 100644 --- a/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php +++ b/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php @@ -14,15 +14,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Jsonld Context Dummy. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class JsonldContextDummy { /** @@ -32,7 +32,6 @@ class JsonldContextDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The dummy person * diff --git a/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php b/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php index 0392dc42137..4b9bcbb96fc 100644 --- a/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php @@ -13,7 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; @@ -21,26 +27,9 @@ * Secured resource with legacy access_control attribute. * * @author Vincent Chalamon - * - * @ApiResource( - * attributes={"access_control"="is_granted('ROLE_USER')"}, - * collectionOperations={ - * "get", - * "post"={"access_control"="is_granted('ROLE_ADMIN')"} - * }, - * itemOperations={ - * "get"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "put"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * }, - * graphql={ - * "item_query"={"access_control"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "delete"={}, - * "update"={"access_control"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * "create"={"access_control"="is_granted('ROLE_ADMIN')", "access_control_message"="Only admins can create a secured dummy."} - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Mutation(name: 'delete'), new Mutation(name: 'update', security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] class LegacySecuredDummy { /** @@ -49,7 +38,6 @@ class LegacySecuredDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null The title * @@ -57,14 +45,12 @@ class LegacySecuredDummy * @Assert\NotBlank */ private $title; - /** * @var string The description * * @ODM\Field */ private $description = ''; - /** * @var string|null The owner * diff --git a/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php index 079c43c18a1..11c614bcb5d 100644 --- a/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php @@ -13,20 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; -/** * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"default"}, "enable_max_depth"=true}, - * "denormalization_context"={"groups"={"default"}, "enable_max_depth"=true} - * }) +/** + * * + * * @ODM\Document * * @author Brian Fox */ +#[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] class MaxDepthDummy { /** @@ -34,13 +33,11 @@ class MaxDepthDummy * @Groups({"default"}) */ private $id; - /** * @ODM\Field(name="name", type="string") * @Groups({"default"}) */ public $name; - /** * @ODM\ReferenceOne(targetDocument=MaxDepthDummy::class, cascade={"persist"}) * @Groups({"default"}) diff --git a/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php index f401a1ef6f9..445db6d627c 100644 --- a/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php @@ -13,20 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; -/** * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"default"}, "enable_max_depth"=true}, - * "denormalization_context"={"groups"={"default"}, "enable_max_depth"=true} - * }) +/** + * * + * * @ODM\Document * * @author Brian Fox */ +#[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] class MaxDepthEagerDummy { /** @@ -34,13 +33,11 @@ class MaxDepthEagerDummy * @Groups({"default"}) */ private $id; - /** * @ODM\Field(name="name", type="string") * @Groups({"default"}) */ public $name; - /** * @ODM\ReferenceOne(targetDocument=MaxDepthEagerDummy::class, cascade={"persist"}) * @Groups({"default"}) diff --git a/tests/Fixtures/TestBundle/Document/MessengerWithInput.php b/tests/Fixtures/TestBundle/Document/MessengerWithInput.php index eb61a226990..811408202b8 100644 --- a/tests/Fixtures/TestBundle/Document/MessengerWithInput.php +++ b/tests/Fixtures/TestBundle/Document/MessengerWithInput.php @@ -14,12 +14,11 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerInput; -/** - * @ApiResource(messenger="input", input=MessengerInput::class, graphql={"create"={"input"=MessengerInput::class, "messenger"="input"}}) - */ +#[ApiResource(graphQlOperations: [new Mutation(name: 'create', input: MessengerInput::class, messenger: 'input')], messenger: 'input', input: MessengerInput::class)] class MessengerWithInput { /** diff --git a/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php b/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php index 42bc81c93b4..4ba3625421b 100644 --- a/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php +++ b/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php @@ -14,20 +14,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::NET_PATH) * @ODM\Document */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] +#[ApiResource(uriTemplate: '/network_path_relation_dummies/{id}/network_path_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\NetworkPathRelationDummy::class, identifiers: ['id'], toProperty: 'networkPathRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::NET_PATH, operations: [new GetCollection()])] class NetworkPathDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\ReferenceOne(targetDocument=NetworkPathRelationDummy::class, inversedBy="networkPathDummies", storeAs="id") */ diff --git a/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php b/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php index f760fcb0427..28bdee658bf 100644 --- a/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php +++ b/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php @@ -14,25 +14,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource(urlGenerationStrategy=UrlGeneratorInterface::NET_PATH) * @ODM\Document */ +#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] class NetworkPathRelationDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\ReferenceMany(targetDocument=NetworkPathDummy::class, mappedBy="networkPathRelationDummy") - * @ApiSubresource */ public $networkPathDummies; diff --git a/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php b/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php index b0dd85e1130..79abbb2207b 100644 --- a/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php +++ b/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php @@ -13,15 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * No Collection Dummy. * - * @ApiResource(collectionOperations={}) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete()])] class NoCollectionDummy { /** diff --git a/tests/Fixtures/TestBundle/Document/Order.php b/tests/Fixtures/TestBundle/Document/Order.php index 15d4b02d990..e50f95b3a17 100644 --- a/tests/Fixtures/TestBundle/Document/Order.php +++ b/tests/Fixtures/TestBundle/Document/Order.php @@ -13,18 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; /** - * @ApiResource( - * attributes={"normalization_context"={"groups"={"order_read"}}}, - * forceEager=false - * ) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['order_read']], forceEager: false)] class Order { /** @@ -34,13 +31,11 @@ class Order * @Groups({"order_read"}) */ private $id; - /** * @ODM\ReferenceOne(targetDocument=Customer::class) * @Groups({"order_read"}) */ public $customer; - /** * @ODM\ReferenceOne(targetDocument=Customer::class) * @Assert\NotNull diff --git a/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php b/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php index eee6a993ce2..9c7b1210f6e 100644 --- a/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php +++ b/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php @@ -14,7 +14,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,39 +28,9 @@ * Overridden Operation Dummy. * * @author Amrouche Hamza - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"overridden_operation_dummy_read"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_write"}} - * }, - * collectionOperations={ - * "get"={"method"="GET"}, - * "post"={"method"="POST"}, - * "swagger"={ - * "path"="/override/swagger", - * "method"="GET", - * } - * }, - * itemOperations={ - * "swagger"={ - * "method"="GET", - * }, - * "get"={ - * "method"="GET", - * "normalization_context"={"groups"={"overridden_operation_dummy_get"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_get"}} - * }, - * "put"={ - * "method"="PUT", - * "normalization_context"={"groups"={"overridden_operation_dummy_put"}}, - * "denormalization_context"={"groups"={"overridden_operation_dummy_put"}} - * }, - * "delete"={"method"="DELETE"} - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Get(normalizationContext: ['groups' => ['overridden_operation_dummy_get']], denormalizationContext: ['groups' => ['overridden_operation_dummy_get']]), new Put(normalizationContext: ['groups' => ['overridden_operation_dummy_put']], denormalizationContext: ['groups' => ['overridden_operation_dummy_put']]), new Delete(), new GetCollection(), new Post(), new GetCollection(uriTemplate: '/override/swagger')], normalizationContext: ['groups' => ['overridden_operation_dummy_read']], denormalizationContext: ['groups' => ['overridden_operation_dummy_write']])] class OverriddenOperationDummy { /** @@ -64,7 +39,6 @@ class OverriddenOperationDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The dummy name * @@ -74,7 +48,6 @@ class OverriddenOperationDummy * @ApiProperty(iri="http://schema.org/name") */ private $name; - /** * @var string The dummy name alias * @@ -83,7 +56,6 @@ class OverriddenOperationDummy * @ApiProperty(iri="https://schema.org/alternateName") */ private $alias; - /** * @var string A short description of the item * @@ -92,7 +64,6 @@ class OverriddenOperationDummy * @ApiProperty(iri="https://schema.org/description") */ public $description; - /** * @ODM\Field(nullable=true) * @Groups({"overridden_operation_dummy_write"}) diff --git a/tests/Fixtures/TestBundle/Document/PatchDummy.php b/tests/Fixtures/TestBundle/Document/PatchDummy.php index 8a42bef9070..ea90fac19cc 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummy.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummy.php @@ -13,27 +13,24 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @author Kévin Dunglas - * - * @ApiResource( - * itemOperations={ - * "get", - * "patch"={"input_formats"={"json"={"application/merge-patch+json"}, "jsonapi"}} - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()])] class PatchDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; - /** * @ODM\Field(type="string") */ diff --git a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php index c2decdcf666..976b2d213d2 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php @@ -13,32 +13,25 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * @author Kévin Dunglas - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"chicago"}}, - * "denormalization_context"={"groups"={"chicago"}}, - * }, - * itemOperations={ - * "get", - * "patch"={"input_formats"={"json"={"application/merge-patch+json"}, "jsonapi"}} - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] class PatchDummyRelation { /** * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; - /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class) * @Groups({"chicago"}) diff --git a/tests/Fixtures/TestBundle/Document/Payment.php b/tests/Fixtures/TestBundle/Document/Payment.php index 83ef5f839bc..ca39349a066 100644 --- a/tests/Fixtures/TestBundle/Document/Payment.php +++ b/tests/Fixtures/TestBundle/Document/Payment.php @@ -13,25 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\Payment\VoidPaymentAction; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * - * @ApiResource( - * itemOperations={ - * "get", - * "post_void"={ - * "method"="POST", - * "path"="/payments/{id}/void", - * "controller"=VoidPaymentAction::class, - * "deserialize"=false, - * }, - * }, - * ) */ +#[ApiResource(operations: [new Get(), new Post(uriTemplate: '/payments/{id}/void', controller: VoidPaymentAction::class, deserialize: false), new Post(), new GetCollection()])] class Payment { /** @@ -40,12 +32,10 @@ class Payment * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null */ private $amount; - /** * @ODM\ReferenceOne(targetDocument=VoidPayment::class, mappedBy="payment") */ @@ -71,7 +61,6 @@ public function void(): void if (null !== $this->voidPayment) { return; } - $this->voidPayment = new VoidPayment($this); } diff --git a/tests/Fixtures/TestBundle/Document/Person.php b/tests/Fixtures/TestBundle/Document/Person.php index 873fb23df97..e40ae4ffdec 100644 --- a/tests/Fixtures/TestBundle/Document/Person.php +++ b/tests/Fixtures/TestBundle/Document/Person.php @@ -13,8 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -23,23 +22,20 @@ * Person. * * @author Antoine Bluchet - * - * @ApiResource(attributes={"normalization_context"={"groups"={"people.pets"}}}) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['people.pets']])] class Person { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(type="string") * @Groups({"people.pets"}) */ public $name; - /** * @ODM\ReferenceMany(targetDocument=PersonToPet::class, mappedBy="person") * @Groups({"people.pets"}) @@ -47,9 +43,7 @@ class Person * @var ArrayCollection */ public $pets; - /** - * @ApiSubresource * @ODM\ReferenceMany(targetDocument=Greeting::class, mappedBy="sender") */ public $sentGreetings; diff --git a/tests/Fixtures/TestBundle/Document/Pet.php b/tests/Fixtures/TestBundle/Document/Pet.php index 248d5d3738c..ef9fdf5c125 100644 --- a/tests/Fixtures/TestBundle/Document/Pet.php +++ b/tests/Fixtures/TestBundle/Document/Pet.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -22,23 +22,20 @@ * Pet. * * @author Antoine Bluchet - * - * @ApiResource * @ODM\Document */ +#[ApiResource] class Pet { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(type="string") * @Groups({"people.pets"}) */ public $name; - /** * @ODM\ReferenceMany(targetDocument=PersonToPet::class, mappedBy="pet") * diff --git a/tests/Fixtures/TestBundle/Document/Question.php b/tests/Fixtures/TestBundle/Document/Question.php index 730749e4db7..93e3db514f8 100644 --- a/tests/Fixtures/TestBundle/Document/Question.php +++ b/tests/Fixtures/TestBundle/Document/Question.php @@ -13,29 +13,30 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiResource */ +#[ApiResource] +#[ApiResource(uriTemplate: '/answers/{id}/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Answer::class, identifiers: ['id'], toProperty: 'answer')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/questions/{id}/answer/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], fromProperty: 'answer'), 'answer' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Answer::class, identifiers: [], expandedValue: 'answer', toProperty: 'answer')], status: 200, operations: [new GetCollection()])] class Question { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\Field(nullable=true) */ private $content; - /** * @ODM\ReferenceOne(targetDocument=Answer::class, inversedBy="question", storeAs="id") - * @ApiSubresource */ private $answer; diff --git a/tests/Fixtures/TestBundle/Document/RPC.php b/tests/Fixtures/TestBundle/Document/RPC.php index dbb93ab1606..d8767deb383 100644 --- a/tests/Fixtures/TestBundle/Document/RPC.php +++ b/tests/Fixtures/TestBundle/Document/RPC.php @@ -13,20 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RPCOutput; /** * RPC-like resource. - * - * @ApiResource( - * itemOperations={}, - * collectionOperations={ - * "post"={"status"=202, "messenger"=true, "path"="rpc", "output"=false}, - * "post_output"={"method"="POST", "status"=200, "path"="rpc_output", "output"=RPCOutput::class} - * }, - * ) */ +#[ApiResource(operations: [new Post(status: 202, messenger: true, uriTemplate: 'rpc', output: false), new Post(status: 200, uriTemplate: 'rpc_output', output: RPCOutput::class)])] class RPC { /** diff --git a/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php b/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php index d2e2164ad8f..ffe89563e5b 100644 --- a/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php +++ b/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php @@ -14,13 +14,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class ReadableOnlyProperty { /** @@ -29,7 +29,6 @@ class ReadableOnlyProperty * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The foo name * diff --git a/tests/Fixtures/TestBundle/Document/RelatedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedDummy.php index eb85808f17c..166e246a7b2 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedDummy.php @@ -14,8 +14,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -27,20 +31,24 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * - * @ApiResource(graphql={"item_query", "update"={"normalization_context"={"groups"={"chicago", "fakemanytomany"}}, "denormalization_context"={"groups"={"friends"}}}}, iri="https://schema.org/Product", attributes={"normalization_context"={"groups"={"friends"}}, "filters"={"related_dummy.mongodb.friends"}}) * @ODM\Document */ +#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.mongodb.friends'])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] class RelatedDummy extends ParentDummy { /** * @ApiProperty(writable=false) - * @ApiSubresource * @ODM\Id(strategy="INCREMENT", type="int") * @Groups({"chicago", "friends"}) */ private $id; - /** * @var string A name * @@ -48,13 +56,11 @@ class RelatedDummy extends ParentDummy * @Groups({"friends"}) */ public $name; - /** * @ODM\Field(type="string") * @Groups({"barcelona", "chicago", "friends"}) */ protected $symfony = 'symfony'; - /** * @var \DateTime A dummy date * @@ -63,21 +69,16 @@ class RelatedDummy extends ParentDummy * @Groups({"friends"}) */ public $dummyDate; - /** - * @ApiSubresource * @ODM\ReferenceOne(targetDocument=ThirdLevel::class, cascade={"persist"}, nullable=true, storeAs="id") * @Groups({"barcelona", "chicago", "friends"}) */ public $thirdLevel; - /** - * @ApiSubresource * @ODM\ReferenceMany(targetDocument=RelatedToDummyFriend::class, cascade={"persist"}, mappedBy="relatedDummy", storeAs="id") * @Groups({"fakemanytomany", "friends"}) */ public $relatedToDummyFriend; - /** * @var bool A dummy bool * @@ -85,7 +86,6 @@ class RelatedDummy extends ParentDummy * @Groups({"friends"}) */ public $dummyBoolean; - /** * @var EmbeddableDummy * diff --git a/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php index 61036cf30ee..6c43ab84734 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -25,13 +25,9 @@ * Related to Normalized Dummy. * * @author Amrouche Hamza - * - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"related_output", "output"}}, - * "denormalization_context"={"groups"={"related_input", "input"}} - * }) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['related_output', 'output']], denormalizationContext: ['groups' => ['related_input', 'input']])] class RelatedNormalizedDummy { /** @@ -41,7 +37,6 @@ class RelatedNormalizedDummy * @Groups({"related_output", "related_input"}) */ private $id; - /** * @var string|null The dummy name * @@ -51,7 +46,6 @@ class RelatedNormalizedDummy * @Groups({"related_output", "related_input"}) */ private $name; - /** * @var iterable Several Normalized dummies * diff --git a/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php index 2ce46d9fd78..cb12d783f6a 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** @@ -22,29 +22,24 @@ * * @author Sergey V. Ryabov * @author Alan Poulain - * - * @ApiResource(iri="https://schema.org/Product") * @ODM\Document */ +#[ApiResource(types: ['https://schema.org/Product'])] class RelatedOwnedDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null A name * * @ODM\Field(type="string") */ public $name; - /** - * @var Dummy|null - * + * @var \Dummy|null * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, inversedBy="relatedOwnedDummy", storeAs="id") - * @ApiSubresource */ public $owningDummy; diff --git a/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php b/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php index 4424ae71bc3..f59f6643609 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** @@ -22,29 +22,24 @@ * * @author Sergey V. Ryabov * @author Alan Poulain - * - * @ApiResource(iri="https://schema.org/Product") * @ODM\Document */ +#[ApiResource(types: ['https://schema.org/Product'])] class RelatedOwningDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string A name * * @ODM\Field(type="string") */ public $name; - /** - * @var Dummy - * + * @var \Dummy * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, mappedBy="relatedOwningDummy") - * @ApiSubresource */ public $ownedDummy; @@ -84,7 +79,6 @@ public function getOwnedDummy(): Dummy public function setOwnedDummy(Dummy $ownedDummy) { $this->ownedDummy = $ownedDummy; - if ($this !== $this->ownedDummy->getRelatedOwningDummy()) { $this->ownedDummy->setRelatedOwningDummy($this); } diff --git a/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php b/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php index f84b28ed002..4bcdd1ed222 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php @@ -13,25 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource( - * attributes={"security"="is_granted('ROLE_ADMIN')"}, - * collectionOperations={ - * "get"={"security"="is_granted('ROLE_ADMIN')"}, - * }, - * itemOperations={ - * "get"={"security"="is_granted('ROLE_ADMIN')"}, - * }, - * graphql={ - * "item_query"={"security"="is_granted('ROLE_ADMIN')"}, - * "collection_query"={"security"="is_granted('ROLE_ADMIN')"}, - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_ADMIN\')'), new GetCollection(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\')'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')')], security: 'is_granted(\'ROLE_ADMIN\')')] class RelatedSecuredDummy { /** diff --git a/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php b/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php index bfe438b35e0..21b62391da6 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php +++ b/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php @@ -14,7 +14,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -22,16 +24,20 @@ /** * Related To Dummy Friend represent an association table for a manytomany relation. * - * @ApiResource(attributes={"normalization_context"={"groups"={"fakemanytomany"}}, "filters"={"related_to_dummy_friend.mongodb.name"}}) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['fakemanytomany']], filters: ['related_to_dummy_friend.mongodb.name'])] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] class RelatedToDummyFriend { /** * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The dummy name * @@ -41,7 +47,6 @@ class RelatedToDummyFriend * @Groups({"fakemanytomany", "friends"}) */ private $name; - /** * @var string|null The dummy description * @@ -49,14 +54,12 @@ class RelatedToDummyFriend * @Groups({"fakemanytomany", "friends"}) */ private $description; - /** * @ODM\ReferenceOne(targetDocument=DummyFriend::class, storeAs="id") * @Groups({"fakemanytomany", "friends"}) * @Assert\NotNull */ private $dummyFriend; - /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, inversedBy="relatedToDummyFriend", storeAs="id") * @Assert\NotNull diff --git a/tests/Fixtures/TestBundle/Document/RelationEmbedder.php b/tests/Fixtures/TestBundle/Document/RelationEmbedder.php index 51ccb2ac60b..e85af880c73 100644 --- a/tests/Fixtures/TestBundle/Document/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Document/RelationEmbedder.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -21,49 +26,30 @@ * Relation Embedder. * * @author Kévin Dunglas - * - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"barcelona"}}, - * "denormalization_context"={"groups"={"chicago"}}, - * "hydra_context"={"@type"="hydra:Operation", "hydra:title"="A custom operation", "returns"="xmls:string"} - * }, - * itemOperations={ - * "get", - * "put"={}, - * "delete", - * "custom_get"={"route_name"="relation_embedded.custom_get", "method"="GET"}, - * "custom1"={"path"="/api/custom-call/{id}", "method"="GET"}, - * "custom2"={"path"="/api/custom-call/{id}", "method"="PUT"}, - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(routeName: 'relation_embedded.custom_get'), new Get(uriTemplate: '/api/custom-call/{id}'), new Put(uriTemplate: '/api/custom-call/{id}'), new Post(), new GetCollection()], normalizationContext: ['groups' => ['barcelona']], denormalizationContext: ['groups' => ['chicago']], hydraContext: ['@type' => 'hydra:Operation', 'hydra:title' => 'A custom operation', 'returns' => 'xmls:string'])] class RelationEmbedder { /** * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; - /** * @ODM\Field * @Groups({"chicago"}) */ public $paris = 'Paris'; - /** * @ODM\Field * @Groups({"barcelona", "chicago"}) */ public $krondstadt = 'Krondstadt'; - /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, cascade={"persist"}) * @Groups({"chicago", "barcelona"}) */ public $anotherRelated; - /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class) * @Groups({"barcelona", "chicago"}) diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php b/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php index dc13428b365..f90bb02fd32 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class ResourceWithBoolean { /** @@ -28,7 +28,6 @@ class ResourceWithBoolean * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var bool * diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php b/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php index ddd615aa7ad..520008f1692 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class ResourceWithFloat { /** @@ -28,7 +28,6 @@ class ResourceWithFloat * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var float * diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php b/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php index 4c6232a9142..b95bb3ca689 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class ResourceWithInteger { /** @@ -28,7 +28,6 @@ class ResourceWithInteger * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var int * diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithString.php b/tests/Fixtures/TestBundle/Document/ResourceWithString.php index 5d3c333436e..d79c4a13114 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithString.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithString.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class ResourceWithString { /** @@ -28,7 +28,6 @@ class ResourceWithString * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/SecuredDummy.php b/tests/Fixtures/TestBundle/Document/SecuredDummy.php index 0551d3b74a9..d7e3e492e34 100644 --- a/tests/Fixtures/TestBundle/Document/SecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/SecuredDummy.php @@ -14,7 +14,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -25,32 +32,9 @@ * * @author Kévin Dunglas * @author Alan Poulain - * - * @ApiResource( - * attributes={"security"="is_granted('ROLE_USER')"}, - * collectionOperations={ - * "get"={"security"="is_granted('ROLE_USER') or is_granted('ROLE_ADMIN')"}, - * "get_from_data_provider_generator"={ - * "method"="GET", - * "path"="custom_data_provider_generator", - * "security"="is_granted('ROLE_USER')" - * }, - * "post"={"security"="is_granted('ROLE_ADMIN')"} - * }, - * itemOperations={ - * "get"={"security"="is_granted('ROLE_USER') and object.getOwner() == user"}, - * "put"={"security_post_denormalize"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * }, - * graphql={ - * "item_query"={"security"="is_granted('ROLE_ADMIN') or (is_granted('ROLE_USER') and object.getOwner() == user)"}, - * "collection_query"={"security"="is_granted('ROLE_ADMIN')"}, - * "delete"={}, - * "update"={"security_post_denormalize"="is_granted('ROLE_USER') and previous_object.getOwner() == user"}, - * "create"={"security"="is_granted('ROLE_ADMIN')", "security_message"="Only admins can create a secured dummy."} - * } - * ) * @ODM\Document */ +#[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(security: 'is_granted(\'ROLE_USER\') or is_granted(\'ROLE_ADMIN\')'), new GetCollection(uriTemplate: 'custom_data_provider_generator', security: 'is_granted(\'ROLE_USER\')'), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\') or (is_granted(\'ROLE_USER\') and object.getOwner() == user)'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')'), new Mutation(name: 'delete'), new Mutation(name: 'update', securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] class SecuredDummy { /** @@ -59,7 +43,6 @@ class SecuredDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null The title * @@ -67,14 +50,12 @@ class SecuredDummy * @Assert\NotBlank */ private $title; - /** * @var string The description * * @ODM\Field */ private $description = ''; - /** * @var string The dummy secret property, only readable/writable by specific users * @@ -82,7 +63,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ private $adminOnlyProperty = ''; - /** * @var string Secret property, only readable/writable by owners * @@ -93,7 +73,6 @@ class SecuredDummy * ) */ private $ownerOnlyProperty = ''; - /** * @var string|null The owner * @@ -101,7 +80,6 @@ class SecuredDummy * @Assert\NotBlank */ private $owner; - /** * @var Collection Several dummies * @@ -109,7 +87,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ public $relatedDummies; - /** * @var RelatedDummy * @@ -117,7 +94,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ protected $relatedDummy; - /** * A collection of dummies that only users can access. The security on RelatedSecuredDummy shouldn't be run. * @@ -127,7 +103,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_USER')") */ public $relatedSecuredDummies; - /** * A dummy that only users can access. The security on RelatedSecuredDummy shouldn't be run. * @@ -137,7 +112,6 @@ class SecuredDummy * @ApiProperty(security="is_granted('ROLE_USER')") */ protected $relatedSecuredDummy; - /** * Collection of dummies that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * @@ -146,7 +120,6 @@ class SecuredDummy * @ODM\ReferenceMany(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) */ public $publicRelatedSecuredDummies; - /** * A dummy that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * diff --git a/tests/Fixtures/TestBundle/Document/SlugChildDummy.php b/tests/Fixtures/TestBundle/Document/SlugChildDummy.php index 2cf79bcc691..5124a07b852 100644 --- a/tests/Fixtures/TestBundle/Document/SlugChildDummy.php +++ b/tests/Fixtures/TestBundle/Document/SlugChildDummy.php @@ -14,14 +14,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugParentDummy::class, identifiers: ['slug'], toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] +#[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], fromProperty: 'parentDummy'), 'parentDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugParentDummy::class, identifiers: [], expandedValue: 'parent_dummy', toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] class SlugChildDummy { /** @@ -32,7 +35,6 @@ class SlugChildDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string The slug used as API identifier * @@ -41,11 +43,8 @@ class SlugChildDummy * @ODM\Field */ private $slug; - /** * @ODM\ReferenceOne(targetDocument=SlugParentDummy::class, inversedBy="childDummies", storeAs="id") - * - * @ApiSubresource */ private $parentDummy; diff --git a/tests/Fixtures/TestBundle/Document/SlugParentDummy.php b/tests/Fixtures/TestBundle/Document/SlugParentDummy.php index 641fff4ebbc..cb475db3f04 100644 --- a/tests/Fixtures/TestBundle/Document/SlugParentDummy.php +++ b/tests/Fixtures/TestBundle/Document/SlugParentDummy.php @@ -14,8 +14,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -23,9 +24,11 @@ /** * Custom Identifier Dummy With Subresource. * - * @ApiResource(attributes={"identifiers"="slug"}) * @ODM\Document */ +#[ApiResource(uriVariables: 'slug')] +#[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies/{childDummies}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], toProperty: 'parentDummy'), 'childDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] class SlugParentDummy { /** @@ -36,7 +39,6 @@ class SlugParentDummy * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var string|null The slug used a API identifier * @@ -45,13 +47,10 @@ class SlugParentDummy * @ODM\Field */ private $slug; - /** * @ODM\ReferenceMany(targetDocument=SlugChildDummy::class, mappedBy="parentDummy") * - * @var Collection - * - * @ApiSubresource + * @var \Collection */ private $childDummies; diff --git a/tests/Fixtures/TestBundle/Document/SoMany.php b/tests/Fixtures/TestBundle/Document/SoMany.php index 50fe29a985e..837472986ae 100644 --- a/tests/Fixtures/TestBundle/Document/SoMany.php +++ b/tests/Fixtures/TestBundle/Document/SoMany.php @@ -14,30 +14,23 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiResource(attributes={ - * "pagination_partial"=true, - * "pagination_via_cursor"={ - * {"field"="id", "direction"="DESC"} - * } - * }) - * - * @ApiFilter(RangeFilter::class, properties={"id"}) - * @ApiFilter(OrderFilter::class, properties={"id"="DESC"}) + * @ApiFilter (RangeFilter::class, properties={"id"}) + * @ApiFilter (OrderFilter::class, properties={"id"="DESC"}) */ +#[ApiResource(paginationPartial: true, paginationViaCursor: [['field' => 'id', 'direction' => 'DESC']])] class SoMany { /** * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; - /** * @ODM\Field(nullable=true) */ diff --git a/tests/Fixtures/TestBundle/Document/ThirdLevel.php b/tests/Fixtures/TestBundle/Document/ThirdLevel.php index 1ad880ff897..8b044829388 100644 --- a/tests/Fixtures/TestBundle/Document/ThirdLevel.php +++ b/tests/Fixtures/TestBundle/Document/ThirdLevel.php @@ -13,8 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Core\Annotation\ApiSubresource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -23,10 +24,14 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * - * @ApiResource * @ODM\Document */ +#[ApiResource] +#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] class ThirdLevel { /** @@ -35,7 +40,6 @@ class ThirdLevel * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @var int * @@ -43,21 +47,17 @@ class ThirdLevel * @Groups({"barcelona", "chicago"}) */ private $level = 3; - /** * @var bool * * @ODM\Field(type="bool") */ private $test = true; - /** - * @ApiSubresource * @ODM\ReferenceOne(targetDocument=FourthLevel::class, cascade={"persist"}, storeAs="id") * @Groups({"barcelona", "chicago", "friends"}) */ public $fourthLevel; - /** * @ODM\ReferenceOne(targetDocument=FourthLevel::class, cascade={"persist"}) */ diff --git a/tests/Fixtures/TestBundle/Document/UrlEncodedId.php b/tests/Fixtures/TestBundle/Document/UrlEncodedId.php index 029736d5d3b..7d5e3978159 100644 --- a/tests/Fixtures/TestBundle/Document/UrlEncodedId.php +++ b/tests/Fixtures/TestBundle/Document/UrlEncodedId.php @@ -13,25 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @author Daniel West * * Resource with an ID that will be URL encoded - * * @ODM\Document - * - * @ApiResource( - * itemOperations={ - * "get"={ - * "method"="GET", - * "requirements"={"id"=".+"} - * } - * } - * ) */ +#[ApiResource(operations: [new Get(requirements: ['id' => '.+']), new Post(), new GetCollection()])] class UrlEncodedId { /** diff --git a/tests/Fixtures/TestBundle/Document/User.php b/tests/Fixtures/TestBundle/Document/User.php index b148452a2f3..60762a38bb1 100644 --- a/tests/Fixtures/TestBundle/Document/User.php +++ b/tests/Fixtures/TestBundle/Document/User.php @@ -13,7 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\PasswordResetRequest; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\PasswordResetRequestResult; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; @@ -25,39 +30,12 @@ /** * A User. * - * @ODM\Document(collection="user_test") - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"user", "user-read"}}, - * "denormalization_context"={"groups"={"user", "user-write"}} - * }, - * collectionOperations={ - * "post", - * "get", - * "post_password_reset_request"={ - * "method"="POST", - * "path"="/users/password_reset_request", - * "messenger"="input", - * "input"=PasswordResetRequest::class, - * "output"=PasswordResetRequestResult::class, - * "normalization_context"={ - * "groups"={"user_password_reset_request"}, - * }, - * "denormalization_context"={ - * "groups"={"user_password_reset_request"}, - * }, - * }, - * }, - * itemOperations={"get", "put", "delete", - * "recover_password"={ - * "input"=RecoverPasswordInput::class, "output"=RecoverPasswordOutput::class, "method"="PUT", "path"="users/recover/{id}" - * } - * } - * ) + * @ODM\Document (collection="user_test") * * @author Théo FIDRY * @author Kévin Dunglas */ +#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Put(input: RecoverPasswordInput::class, output: RecoverPasswordOutput::class, uriTemplate: 'users/recover/{id}'), new Post(), new GetCollection(), new Post(uriTemplate: '/users/password_reset_request', messenger: 'input', input: PasswordResetRequest::class, output: PasswordResetRequestResult::class, normalizationContext: ['groups' => ['user_password_reset_request']], denormalizationContext: ['groups' => ['user_password_reset_request']])], normalizationContext: ['groups' => ['user', 'user-read']], denormalizationContext: ['groups' => ['user', 'user-write']])] class User extends AbstractSecurityUser { /** @@ -66,14 +44,12 @@ class User extends AbstractSecurityUser * @ODM\Id(strategy="INCREMENT", type="int") */ protected $id; - /** * @var string|null * * @Groups({"user"}) */ protected $email; - /** * @var string|null * @@ -81,14 +57,12 @@ class User extends AbstractSecurityUser * @Groups({"user"}) */ protected $fullname; - /** * @var string|null * * @Groups({"user-write"}) */ protected $plainPassword; - /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php index db914748f4d..2a9ba896ea9 100644 --- a/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Custom identifier dummy. * - * @ApiResource * @ODM\Document */ +#[ApiResource] class UuidIdentifierDummy { /** @@ -30,7 +30,6 @@ class UuidIdentifierDummy * @ODM\Id(strategy="UUID") */ private $uuid; - /** * @var string The dummy name * diff --git a/tests/Fixtures/TestBundle/Document/VoDummyCar.php b/tests/Fixtures/TestBundle/Document/VoDummyCar.php index e83de67299b..d3c247fe350 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyCar.php @@ -13,19 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource(attributes={ - * "normalization_context"={"groups"={"car_read"}}, - * "denormalization_context"={"groups"={"car_write"}} - * }) * @ODM\Document */ +#[ApiResource(normalizationContext: ['groups' => ['car_read']], denormalizationContext: ['groups' => ['car_write']])] class VoDummyCar extends VoDummyVehicle { /** @@ -35,7 +32,6 @@ class VoDummyCar extends VoDummyVehicle * @Groups({"car_read", "car_write"}) */ private $mileage; - /** * @var string * @@ -43,7 +39,6 @@ class VoDummyCar extends VoDummyVehicle * @Groups({"car_read", "car_write"}) */ private $bodyType; - /** * @var VoDummyInspection[]|Collection * @@ -52,13 +47,8 @@ class VoDummyCar extends VoDummyVehicle */ private $inspections; - public function __construct( - string $make, - VoDummyInsuranceCompany $insuranceCompany, - array $drivers, - int $mileage, - string $bodyType = 'coupe' - ) { + public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, int $mileage, string $bodyType = 'coupe') + { parent::__construct($make, $insuranceCompany, $drivers); $this->mileage = $mileage; $this->bodyType = $bodyType; diff --git a/tests/Fixtures/TestBundle/Document/VoDummyDriver.php b/tests/Fixtures/TestBundle/Document/VoDummyDriver.php index de206dc218b..53fcce13e9a 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyDriver.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyDriver.php @@ -13,18 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class VoDummyDriver { use VoDummyIdAwareTrait; - /** * @var string * @@ -32,7 +31,6 @@ class VoDummyDriver * @Groups({"car_read", "car_write"}) */ private $firstName; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/VoDummyInspection.php b/tests/Fixtures/TestBundle/Document/VoDummyInspection.php index ddc584d7a38..4cf835d8e43 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyInspection.php @@ -13,25 +13,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use DateTime; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource( - * attributes={ - * "normalization_context"={"groups"={"inspection_read"}}, - * "denormalization_context"={"groups"={"inspection_write"}} - * }, - * graphql={} - * ) * @ODM\Document */ +#[ApiResource(graphQlOperations: [], normalizationContext: ['groups' => ['inspection_read']], denormalizationContext: ['groups' => ['inspection_write']])] class VoDummyInspection { use VoDummyIdAwareTrait; - /** * @var bool * @@ -39,7 +32,6 @@ class VoDummyInspection * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) */ private $accepted; - /** * @var VoDummyCar * @@ -47,7 +39,6 @@ class VoDummyInspection * @Groups({"inspection_read", "inspection_write"}) */ private $car; - /** * @var DateTime * @@ -55,7 +46,6 @@ class VoDummyInspection * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) */ private $performed; - private $attributeWithoutConstructorEquivalent; public function __construct(bool $accepted, VoDummyCar $car, DateTime $performed = null, string $parameterWhichIsNotClassAttribute = '') diff --git a/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php b/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php index 387bd7dbaf0..0adc3acaa36 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php @@ -13,18 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class VoDummyInsuranceCompany { use VoDummyIdAwareTrait; - /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/VoidPayment.php b/tests/Fixtures/TestBundle/Document/VoidPayment.php index af1f7b6d82c..d8b9fb08979 100644 --- a/tests/Fixtures/TestBundle/Document/VoidPayment.php +++ b/tests/Fixtures/TestBundle/Document/VoidPayment.php @@ -13,14 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * - * @ApiResource */ +#[ApiResource] class VoidPayment { /** @@ -29,7 +28,6 @@ class VoidPayment * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** * @ODM\ReferenceOne(targetDocument=Payment::class, inversedBy="voidPayment") */ diff --git a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php index 323a8ef08a1..393fbc4b7d7 100644 --- a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php +++ b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ApiResource * @ODM\Document */ +#[ApiResource] class WithJsonDummy { /** @@ -28,7 +28,6 @@ class WithJsonDummy * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ private $id; - /** * @var array|null * diff --git a/tests/Fixtures/TestBundle/Document/WritableId.php b/tests/Fixtures/TestBundle/Document/WritableId.php index 1899ef30388..450670caf4f 100644 --- a/tests/Fixtures/TestBundle/Document/WritableId.php +++ b/tests/Fixtures/TestBundle/Document/WritableId.php @@ -13,16 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; /** * @author Kévin Dunglas - * - * @ApiResource * @ODM\Document */ +#[ApiResource] class WritableId { /** @@ -30,7 +29,6 @@ class WritableId * @Assert\Uuid */ public $id; - /** * @ODM\Field */ From 0821efd172abf2ad2b2b2a59c47d47779f4bd313 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 3 May 2022 15:48:54 +0200 Subject: [PATCH 04/56] fix apiproperty --- .../TestBundle/Action/ConfigCustom.php | 5 +- .../MongoDbOdm/CustomActionController.php | 46 +------- .../MongoDbOdm/DummyValidationController.php | 16 +-- .../Controller/Orm/CustomActionController.php | 46 +------- .../Orm/DummyValidationController.php | 16 +-- .../DummyDtoNoOutputDataPersister.php | 69 ------------ .../UserResetPasswordDataPersister.php | 40 ------- .../ContainNonResourceItemDataProvider.php | 51 --------- .../DummyDtoNoInputCollectionDataProvider.php | 62 ----------- .../DataProvider/GeneratorDataProvider.php | 33 ------ .../DataProvider/ProductItemDataProvider.php | 51 --------- ...rceInterfaceImplementationDataProvider.php | 43 -------- .../SerializableItemDataProvider.php | 51 --------- .../DataProvider/TaxonItemDataProvider.php | 51 --------- .../CustomInputDtoDataTransformer.php | 52 --------- .../CustomOutputDtoDataTransformer.php | 64 ----------- ...myDtoNoInputToOutputDtoDataTransformer.php | 50 --------- .../InitializeInputDataTransformer.php | 64 ----------- .../InputDtoDataTransformer.php | 56 ---------- .../OutputDtoDataTransformer.php | 53 --------- .../OutputDtoSameClassTransformer.php | 56 ---------- .../RPCOutputDataTransformer.php | 40 ------- .../RecoverPasswordInputDataTransformer.php | 46 -------- .../RecoverPasswordOutputDataTransformer.php | 44 -------- .../TestBundle/Doctrine/Generator/Uuid.php | 4 +- .../TestBundle/Doctrine/Orm/EntityManager.php | 6 +- .../TestBundle/Document/AbstractDummy.php | 8 +- .../Fixtures/TestBundle/Document/Address.php | 8 +- tests/Fixtures/TestBundle/Document/Answer.php | 8 +- .../Document/ArrayFilterValidator.php | 7 +- .../TestBundle/Document/CircularReference.php | 6 +- .../Fixtures/TestBundle/Document/Company.php | 2 +- .../TestBundle/Document/CompositeItem.php | 8 +- .../TestBundle/Document/CompositeLabel.php | 6 +- .../Document/CompositePrimitiveItem.php | 22 ++-- .../TestBundle/Document/CompositeRelation.php | 6 +- .../TestBundle/Document/ConcreteDummy.php | 2 +- .../Document/ContainNonResource.php | 9 +- .../Fixtures/TestBundle/Document/Content.php | 31 ++---- .../TestBundle/Document/ConvertedBoolean.php | 4 +- .../TestBundle/Document/ConvertedDate.php | 4 +- .../TestBundle/Document/ConvertedInteger.php | 4 +- .../TestBundle/Document/ConvertedOwner.php | 4 +- .../TestBundle/Document/ConvertedRelated.php | 4 +- .../TestBundle/Document/ConvertedString.php | 4 +- .../TestBundle/Document/CustomActionDummy.php | 8 +- .../Document/CustomGeneratedIdentifier.php | 5 +- .../Document/CustomIdentifierDummy.php | 4 +- .../CustomMultipleIdentifierDummy.php | 12 ++- .../Document/CustomNormalizedDummy.php | 22 ++-- .../CustomWritableIdentifierDummy.php | 4 +- .../Fixtures/TestBundle/Document/Customer.php | 10 +- .../Document/DeprecatedResource.php | 5 +- tests/Fixtures/TestBundle/Document/Dummy.php | 14 +-- .../Document/DummyAggregateOffer.php | 7 +- .../TestBundle/Document/DummyBoolean.php | 21 ++-- .../Fixtures/TestBundle/Document/DummyCar.php | 37 +++---- .../TestBundle/Document/DummyCarColor.php | 17 ++- .../TestBundle/Document/DummyCustomFormat.php | 2 +- .../Document/DummyCustomMutation.php | 20 ++-- .../TestBundle/Document/DummyDate.php | 2 +- ...ummyDifferentGraphQlSerializationGroup.php | 12 +-- .../TestBundle/Document/DummyDtoCustom.php | 2 +- .../TestBundle/Document/DummyDtoNoInput.php | 2 +- .../TestBundle/Document/DummyDtoNoOutput.php | 2 +- .../DummyDtoOutputFallbackToSameClass.php | 2 +- .../Document/DummyDtoOutputSameClass.php | 2 +- .../Document/DummyEntityWithConstructor.php | 40 +++---- .../TestBundle/Document/DummyFriend.php | 12 +-- .../TestBundle/Document/DummyGroup.php | 19 ++-- .../Document/DummyImmutableDate.php | 2 +- .../TestBundle/Document/DummyOffer.php | 6 +- .../TestBundle/Document/DummyProduct.php | 8 +- .../TestBundle/Document/DummyProperty.php | 24 ++--- .../Document/DummyTableInheritance.php | 14 +-- .../Document/DummyTableInheritanceChild.php | 3 +- .../DummyTableInheritanceDifferentChild.php | 3 +- ...mmyTableInheritanceNotApiResourceChild.php | 2 +- .../Document/DummyTableInheritanceRelated.php | 10 +- .../TestBundle/Document/DummyValidation.php | 12 +-- ...mmyWithEmbedManyOmittingTargetDocument.php | 4 +- .../TestBundle/Document/EmbeddableDummy.php | 8 +- .../TestBundle/Document/EmbeddedDummy.php | 10 +- tests/Fixtures/TestBundle/Document/Field.php | 16 +-- .../TestBundle/Document/FileConfigDummy.php | 4 +- .../TestBundle/Document/FilterValidator.php | 7 +- tests/Fixtures/TestBundle/Document/Foo.php | 2 +- .../Fixtures/TestBundle/Document/FooDummy.php | 4 +- .../TestBundle/Document/FourthLevel.php | 8 +- .../TestBundle/Document/IriOnlyDummy.php | 6 +- .../Document/JsonldContextDummy.php | 20 ++-- .../Document/LegacySecuredDummy.php | 14 ++- .../TestBundle/Document/MaxDepthDummy.php | 8 +- .../Document/MaxDepthEagerDummy.php | 8 +- .../Document/MessengerWithInput.php | 19 ++-- .../TestBundle/Document/NoCollectionDummy.php | 2 +- tests/Fixtures/TestBundle/Document/Order.php | 12 +-- .../Document/OverriddenOperationDummy.php | 24 +++-- .../TestBundle/Document/ParentDummy.php | 2 +- .../Document/PatchDummyRelation.php | 2 +- .../Fixtures/TestBundle/Document/Payment.php | 11 +- tests/Fixtures/TestBundle/Document/Person.php | 4 +- .../TestBundle/Document/PersonToPet.php | 2 +- tests/Fixtures/TestBundle/Document/Pet.php | 2 +- .../TestBundle/Document/ProcessorEntity.php | 10 +- .../Fixtures/TestBundle/Document/Product.php | 12 +-- .../TestBundle/Document/ProviderEntity.php | 10 +- .../Document/ReadableOnlyProperty.php | 11 +- .../TestBundle/Document/RelatedDummy.php | 22 ++-- .../Document/RelatedNormalizedDummy.php | 17 +-- .../Document/RelatedToDummyFriend.php | 18 ++-- .../TestBundle/Document/RelationEmbedder.php | 8 +- .../Document/ResourceWithBoolean.php | 6 +- .../TestBundle/Document/ResourceWithFloat.php | 6 +- .../Document/ResourceWithInteger.php | 6 +- .../Document/ResourceWithString.php | 6 +- .../TestBundle/Document/SecuredDummy.php | 44 ++++---- .../Document/SingleFileConfigDummy.php | 2 +- .../TestBundle/Document/SlugChildDummy.php | 14 +-- .../TestBundle/Document/SlugParentDummy.php | 16 +-- tests/Fixtures/TestBundle/Document/Taxon.php | 8 +- .../TestBundle/Document/ThirdLevel.php | 14 +-- .../TestBundle/Document/UrlEncodedId.php | 2 +- tests/Fixtures/TestBundle/Document/User.php | 11 +- .../Document/UuidIdentifierDummy.php | 4 +- .../TestBundle/Document/VoDummyCar.php | 28 ++--- .../TestBundle/Document/VoDummyDriver.php | 30 ++---- .../TestBundle/Document/VoDummyInspection.php | 30 ++---- .../Document/VoDummyInsuranceCompany.php | 16 ++- .../TestBundle/Document/VoDummyVehicle.php | 33 ++---- .../TestBundle/Document/VoidPayment.php | 19 ++-- .../TestBundle/Document/WithJsonDummy.php | 4 +- .../TestBundle/Document/WritableId.php | 2 +- .../TestBundle/Dto/NonResourceClass.php | 4 +- .../TestBundle/Dto/PasswordResetRequest.php | 8 +- .../Dto/PasswordResetRequestResult.php | 8 +- .../TestBundle/Dto/RecoverPasswordInput.php | 2 +- .../TestBundle/Dto/RecoverPasswordOutput.php | 2 +- .../TestBundle/Dto/UserResetPasswordDto.php | 4 +- .../TestBundle/Entity/AbsoluteUrlDummy.php | 16 +-- .../Entity/AbsoluteUrlRelationDummy.php | 16 +-- .../TestBundle/Entity/AbstractDummy.php | 27 +++-- .../TestBundle/Entity/AbstractUser.php | 26 ++--- tests/Fixtures/TestBundle/Entity/Address.php | 24 ++--- .../TestBundle/Entity/AlternateResource.php | 6 +- tests/Fixtures/TestBundle/Entity/Answer.php | 33 +++--- .../Entity/ArrayFilterValidator.php | 19 ++-- .../Entity/AttributeDefaultOperations.php | 8 +- .../TestBundle/Entity/AttributeResource.php | 12 +-- .../TestBundle/Entity/AttributeResources.php | 2 +- tests/Fixtures/TestBundle/Entity/Book.php | 18 ++-- .../TestBundle/Entity/CircularReference.php | 24 ++--- tests/Fixtures/TestBundle/Entity/Comment.php | 28 ++--- tests/Fixtures/TestBundle/Entity/Company.php | 16 ++- .../TestBundle/Entity/CompositeItem.php | 25 ++--- .../TestBundle/Entity/CompositeLabel.php | 19 ++-- .../Entity/CompositePrimitiveItem.php | 21 +--- .../TestBundle/Entity/CompositeRelation.php | 29 ++--- .../TestBundle/Entity/ConcreteDummy.php | 7 +- .../TestBundle/Entity/ContainNonResource.php | 20 ++-- tests/Fixtures/TestBundle/Entity/Content.php | 62 +++-------- .../TestBundle/Entity/ConvertedBoolean.php | 17 ++- .../TestBundle/Entity/ConvertedDate.php | 17 ++- .../TestBundle/Entity/ConvertedInteger.php | 17 ++- .../TestBundle/Entity/ConvertedOwner.php | 17 ++- .../TestBundle/Entity/ConvertedRelated.php | 19 ++-- .../TestBundle/Entity/ConvertedString.php | 17 ++- .../TestBundle/Entity/CustomActionDummy.php | 23 ++-- .../Entity/CustomGeneratedIdentifier.php | 17 ++- .../Entity/CustomIdentifierDummy.php | 17 ++- .../Entity/CustomMultipleIdentifierDummy.php | 22 ++-- .../Entity/CustomNormalizedDummy.php | 37 ++++--- .../Entity/CustomWritableIdentifierDummy.php | 15 ++- tests/Fixtures/TestBundle/Entity/Customer.php | 32 ++---- .../TestBundle/Entity/DeprecatedResource.php | 22 ++-- .../Entity/DisableItemOperation.php | 16 ++- tests/Fixtures/TestBundle/Entity/Dummy.php | 87 +++++++-------- .../TestBundle/Entity/DummyAggregateOffer.php | 23 ++-- .../TestBundle/Entity/DummyBoolean.php | 27 ++--- tests/Fixtures/TestBundle/Entity/DummyCar.php | 81 +++++--------- .../TestBundle/Entity/DummyCarColor.php | 36 +++---- .../TestBundle/Entity/DummyCarIdentifier.php | 16 ++- .../TestBundle/Entity/DummyCarInfo.php | 6 +- .../TestBundle/Entity/DummyCustomFormat.php | 16 ++- .../TestBundle/Entity/DummyCustomMutation.php | 43 +++----- .../TestBundle/Entity/DummyCustomQuery.php | 9 +- .../Fixtures/TestBundle/Entity/DummyDate.php | 23 ++-- ...ummyDifferentGraphQlSerializationGroup.php | 27 +++-- .../TestBundle/Entity/DummyDtoCustom.php | 18 ++-- .../TestBundle/Entity/DummyDtoInputOutput.php | 14 +-- .../TestBundle/Entity/DummyDtoNoInput.php | 17 ++- .../TestBundle/Entity/DummyDtoNoOutput.php | 17 ++- .../DummyDtoOutputFallbackToSameClass.php | 17 ++- .../Entity/DummyDtoOutputSameClass.php | 17 ++- .../Entity/DummyEntityWithConstructor.php | 42 ++------ .../Entity/DummyForAdditionalFields.php | 20 +--- .../Entity/DummyForAdditionalFieldsInput.php | 6 +- .../TestBundle/Entity/DummyFriend.php | 25 +++-- .../Fixtures/TestBundle/Entity/DummyGroup.php | 41 +++---- .../TestBundle/Entity/DummyImmutableDate.php | 15 ++- .../TestBundle/Entity/DummyMercure.php | 23 ++-- .../TestBundle/Entity/DummyNoGetOperation.php | 12 +-- .../Fixtures/TestBundle/Entity/DummyOffer.php | 21 ++-- .../TestBundle/Entity/DummyPassenger.php | 17 ++- .../Fixtures/TestBundle/Entity/DummyPhp8.php | 14 +-- .../Entity/DummyPhp8ApiPropertyAttribute.php | 14 +-- .../TestBundle/Entity/DummyProduct.php | 26 ++--- .../TestBundle/Entity/DummyProperty.php | 52 ++++----- .../Entity/DummyPropertyWithDefaultValue.php | 27 ++--- .../Entity/DummyTableInheritance.php | 45 +++----- .../Entity/DummyTableInheritanceChild.php | 10 +- .../DummyTableInheritanceDifferentChild.php | 10 +- ...mmyTableInheritanceNotApiResourceChild.php | 9 +- .../Entity/DummyTableInheritanceRelated.php | 26 ++--- .../TestBundle/Entity/DummyTravel.php | 28 ++--- .../TestBundle/Entity/DummyValidation.php | 31 +++--- .../TestBundle/Entity/EmbeddableDummy.php | 35 ++---- .../TestBundle/Entity/EmbeddedDummy.php | 31 +++--- tests/Fixtures/TestBundle/Entity/Employee.php | 20 ++-- .../TestBundle/Entity/ExternalUser.php | 8 +- tests/Fixtures/TestBundle/Entity/Field.php | 45 +++----- .../TestBundle/Entity/FileConfigDummy.php | 23 ++-- .../TestBundle/Entity/FilterValidator.php | 24 ++--- .../Fixtures/TestBundle/Entity/FlexConfig.php | 11 +- tests/Fixtures/TestBundle/Entity/Foo.php | 17 ++- tests/Fixtures/TestBundle/Entity/FooDummy.php | 19 ++-- .../TestBundle/Entity/FourthLevel.php | 25 ++--- tests/Fixtures/TestBundle/Entity/Greeting.php | 28 ++--- .../TestBundle/Entity/InitializeInput.php | 18 +--- .../TestBundle/Entity/InternalUser.php | 8 +- .../TestBundle/Entity/IriOnlyDummy.php | 19 ++-- .../TestBundle/Entity/JsonldContextDummy.php | 30 ++---- .../TestBundle/Entity/LegacySecuredDummy.php | 33 +++--- .../TestBundle/Entity/MaxDepthDummy.php | 35 +++--- .../TestBundle/Entity/MaxDepthEagerDummy.php | 26 ++--- .../TestBundle/Entity/MessengerWithInput.php | 19 ++-- .../Entity/MessengerWithResponse.php | 15 ++- .../TestBundle/Entity/NetworkPathDummy.php | 16 +-- .../Entity/NetworkPathRelationDummy.php | 16 +-- .../TestBundle/Entity/NoCollectionDummy.php | 12 +-- .../TestBundle/Entity/NonRelationResource.php | 12 +-- .../TestBundle/Entity/OperationResource.php | 21 +--- tests/Fixtures/TestBundle/Entity/Order.php | 38 +++---- .../Entity/OverriddenOperationDummy.php | 46 ++++---- .../TestBundle/Entity/PaginationEntity.php | 15 +-- .../TestBundle/Entity/ParentDummy.php | 8 +- .../Fixtures/TestBundle/Entity/PatchDummy.php | 14 +-- .../TestBundle/Entity/PatchDummyRelation.php | 16 ++- tests/Fixtures/TestBundle/Entity/Payment.php | 29 ++--- tests/Fixtures/TestBundle/Entity/Person.php | 25 ++--- .../TestBundle/Entity/PersonToPet.php | 19 ++-- tests/Fixtures/TestBundle/Entity/Pet.php | 19 ++-- .../TestBundle/Entity/PlainObjectDummy.php | 12 +-- .../TestBundle/Entity/ProcessorEntity.php | 27 ++--- tests/Fixtures/TestBundle/Entity/Product.php | 34 ++---- tests/Fixtures/TestBundle/Entity/Program.php | 28 ++--- .../TestBundle/Entity/ProviderEntity.php | 27 ++--- tests/Fixtures/TestBundle/Entity/Question.php | 24 ++--- .../TestBundle/Entity/RamseyUuidDummy.php | 22 ++-- .../Entity/ReadableOnlyProperty.php | 25 ++--- .../TestBundle/Entity/RelatedDummy.php | 63 +++++------ .../Entity/RelatedNormalizedDummy.php | 32 +++--- .../TestBundle/Entity/RelatedOwnedDummy.php | 17 ++- .../TestBundle/Entity/RelatedOwningDummy.php | 15 ++- .../TestBundle/Entity/RelatedSecuredDummy.php | 11 +- .../Entity/RelatedToDummyFriend.php | 43 ++++---- .../Fixtures/TestBundle/Entity/Relation1.php | 15 +-- .../Fixtures/TestBundle/Entity/Relation2.php | 15 +-- .../Fixtures/TestBundle/Entity/Relation3.php | 16 ++- .../TestBundle/Entity/RelationEmbedder.php | 34 +++--- .../TestBundle/Entity/ResourceWithBoolean.php | 21 ++-- .../TestBundle/Entity/ResourceWithFloat.php | 21 ++-- .../TestBundle/Entity/ResourceWithInteger.php | 21 ++-- .../TestBundle/Entity/ResourceWithString.php | 21 ++-- .../TestBundle/Entity/SecuredDummy.php | 101 ++++++++---------- .../Entity/SingleFileConfigDummy.php | 16 ++- tests/Fixtures/TestBundle/Entity/Site.php | 26 ++--- .../TestBundle/Entity/SlugChildDummy.php | 34 +++--- .../TestBundle/Entity/SlugParentDummy.php | 29 +++-- tests/Fixtures/TestBundle/Entity/SoMany.php | 14 +-- .../TestBundle/Entity/SymfonyUuidDummy.php | 15 +-- tests/Fixtures/TestBundle/Entity/Taxon.php | 25 ++--- .../Fixtures/TestBundle/Entity/ThirdLevel.php | 39 +++---- .../TestBundle/Entity/TruncatedDummy.php | 16 +-- .../TestBundle/Entity/UnknownDummy.php | 12 +-- .../Entity/UpperCaseIdentifierDummy.php | 14 ++- .../TestBundle/Entity/UrlEncodedId.php | 10 +- tests/Fixtures/TestBundle/Entity/User.php | 43 +++----- .../TestBundle/Entity/UserResource.php | 4 +- .../TestBundle/Entity/UuidIdentifierDummy.php | 15 ++- .../Fixtures/TestBundle/Entity/VoDummyCar.php | 29 +---- .../TestBundle/Entity/VoDummyDriver.php | 24 +---- .../TestBundle/Entity/VoDummyIdAwareTrait.php | 7 +- .../TestBundle/Entity/VoDummyInspection.php | 34 +----- .../Entity/VoDummyInsuranceCompany.php | 14 +-- .../TestBundle/Entity/VoDummyVehicle.php | 34 ++---- .../TestBundle/Entity/VoidPayment.php | 26 ++--- .../TestBundle/Entity/WithJsonDummy.php | 19 ++-- .../Fixtures/TestBundle/Entity/WritableId.php | 14 +-- .../TestBundle/Enum/ContentStatus.php | 12 +-- .../Filter/NoPropertiesArgumentFilter.php | 5 +- .../GraphQl/Type/Definition/DateTimeType.php | 2 +- .../TestBundle/GraphQl/Type/TypeConverter.php | 7 +- .../GraphQl/Type/TypeConverterLegacy.php | 59 ---------- ...iderResourceMetadatatCollectionFactory.php | 8 +- .../Fixtures/TestBundle/Model/MediaObject.php | 12 +-- .../TestBundle/Model/ProductInterface.php | 24 ++--- .../TestBundle/Model/ResourceBarInterface.php | 6 +- .../Model/ResourceInterfaceImplementation.php | 12 +-- .../TestBundle/Model/SerializableResource.php | 22 ++-- .../TestBundle/Model/TaxonInterface.php | 16 +-- .../Security/AuthenticationEntryPoint.php | 5 +- .../DummyPlainIdentifierDenormalizer.php | 15 +-- ...elatedDummyPlainIdentifierDenormalizer.php | 15 +-- .../OverrideDocumentationNormalizer.php | 5 +- .../State/DummyDtoNoOutputProcessor.php | 5 +- .../State/OperationResourceProcessor.php | 5 +- .../TestBundle/State/ProductProvider.php | 7 +- .../State/RelatedQuestionsProvider.php | 5 +- .../TestBundle/State/TaxonItemProvider.php | 7 +- .../Util/AnnotationFilterExtractor.php | 5 +- 321 files changed, 1849 insertions(+), 4399 deletions(-) delete mode 100644 tests/Fixtures/TestBundle/DataPersister/DummyDtoNoOutputDataPersister.php delete mode 100644 tests/Fixtures/TestBundle/DataPersister/UserResetPasswordDataPersister.php delete mode 100644 tests/Fixtures/TestBundle/DataProvider/ContainNonResourceItemDataProvider.php delete mode 100644 tests/Fixtures/TestBundle/DataProvider/DummyDtoNoInputCollectionDataProvider.php delete mode 100644 tests/Fixtures/TestBundle/DataProvider/GeneratorDataProvider.php delete mode 100644 tests/Fixtures/TestBundle/DataProvider/ProductItemDataProvider.php delete mode 100644 tests/Fixtures/TestBundle/DataProvider/ResourceInterfaceImplementationDataProvider.php delete mode 100644 tests/Fixtures/TestBundle/DataProvider/SerializableItemDataProvider.php delete mode 100644 tests/Fixtures/TestBundle/DataProvider/TaxonItemDataProvider.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/CustomInputDtoDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/CustomOutputDtoDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/DummyDtoNoInputToOutputDtoDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/InitializeInputDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/InputDtoDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/OutputDtoDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/OutputDtoSameClassTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/RPCOutputDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordInputDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordOutputDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/GraphQl/Type/TypeConverterLegacy.php diff --git a/tests/Fixtures/TestBundle/Action/ConfigCustom.php b/tests/Fixtures/TestBundle/Action/ConfigCustom.php index 580fe839e07..b9bb05f1127 100644 --- a/tests/Fixtures/TestBundle/Action/ConfigCustom.php +++ b/tests/Fixtures/TestBundle/Action/ConfigCustom.php @@ -24,11 +24,8 @@ */ class ConfigCustom { - private $dataProvider; - - public function __construct(ItemDataProviderInterface $dataProvider) + public function __construct(private readonly ItemDataProviderInterface $dataProvider) { - $this->dataProvider = $dataProvider; } public function __invoke(Request $request, $id) diff --git a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php index 86dab54944c..4091bb30db2 100644 --- a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php +++ b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php @@ -23,14 +23,7 @@ */ class CustomActionController extends AbstractController { - /** - * @Route( - * methods={"GET"}, - * name="custom_normalization", - * path="/custom/{id}/normalization", - * defaults={"_api_resource_class"=CustomActionDummy::class, "_api_item_operation_name"="custom_normalization"} - * ) - */ + #[Route(methods: ['GET'], name: 'custom_normalization', path: '/custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] public function customNormalizationAction(CustomActionDummy $data) { $data->setFoo('foo'); @@ -38,38 +31,19 @@ public function customNormalizationAction(CustomActionDummy $data) return $this->json($data); } - /** - * @Route( - * methods={"POST"}, - * name="custom_denormalization", - * path="/custom/denormalization", - * defaults={ - * "_api_resource_class"=CustomActionDummy::class, - * "_api_collection_operation_name"="custom_denormalization", - * "_api_receive"=false - * } - * ) - */ + #[Route(methods: ['POST'], name: 'custom_denormalization', path: '/custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function customDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { throw new \RuntimeException('The "data" attribute must not be set.'); } - $object = new CustomActionDummy(); $object->setFoo('custom!'); return $object; } - /** - * @Route( - * methods={"GET"}, - * name="short_custom_normalization", - * path="/short_custom/{id}/normalization", - * defaults={"_api_resource_class"=CustomActionDummy::class, "_api_item_operation_name"="custom_normalization"} - * ) - */ + #[Route(methods: ['GET'], name: 'short_custom_normalization', path: '/short_custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] public function shortCustomNormalizationAction(CustomActionDummy $data) { $data->setFoo('short'); @@ -77,24 +51,12 @@ public function shortCustomNormalizationAction(CustomActionDummy $data) return $this->json($data); } - /** - * @Route( - * methods={"POST"}, - * name="short_custom_denormalization", - * path="/short_custom/denormalization", - * defaults={ - * "_api_resource_class"=CustomActionDummy::class, - * "_api_collection_operation_name"="custom_denormalization", - * "_api_receive"=false - * } - * ) - */ + #[Route(methods: ['POST'], name: 'short_custom_denormalization', path: '/short_custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function shortCustomDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { throw new \RuntimeException('The "data" attribute must not be set.'); } - $object = new CustomActionDummy(); $object->setFoo('short declaration'); diff --git a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/DummyValidationController.php b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/DummyValidationController.php index c5023fd5853..7107416b3d5 100644 --- a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/DummyValidationController.php +++ b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/DummyValidationController.php @@ -19,30 +19,18 @@ class DummyValidationController { /** - * @Route( - * methods={"POST"}, - * name="post_validation_groups", - * path="/dummy_validation/validation_groups", - * defaults={"_api_resource_class"=DummyValidation::class, "_api_collection_operation_name"="post_validation_groups"} - * ) - * * @param mixed $data */ + #[Route(methods: ['POST'], name: 'post_validation_groups', path: '/dummy_validation/validation_groups', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_groups'])] public function postValidationGroups($data) { return $data; } /** - * @Route( - * methods={"POST"}, - * name="post_validation_sequence", - * path="/dummy_validation/validation_sequence", - * defaults={"_api_resource_class"=DummyValidation::class, "_api_collection_operation_name"="post_validation_sequence"} - * ) - * * @param mixed $data */ + #[Route(methods: ['POST'], name: 'post_validation_sequence', path: '/dummy_validation/validation_sequence', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_sequence'])] public function postValidationSequence($data) { return $data; diff --git a/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php b/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php index f638e3272fb..c9bea651d10 100644 --- a/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php +++ b/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php @@ -23,14 +23,7 @@ */ class CustomActionController extends AbstractController { - /** - * @Route( - * methods={"GET"}, - * name="custom_normalization", - * path="/custom/{id}/normalization", - * defaults={"_api_resource_class"=CustomActionDummy::class, "_api_item_operation_name"="custom_normalization"} - * ) - */ + #[Route(methods: ['GET'], name: 'custom_normalization', path: '/custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] public function customNormalizationAction(CustomActionDummy $data) { $data->setFoo('foo'); @@ -38,38 +31,19 @@ public function customNormalizationAction(CustomActionDummy $data) return $this->json($data); } - /** - * @Route( - * methods={"POST"}, - * name="custom_denormalization", - * path="/custom/denormalization", - * defaults={ - * "_api_resource_class"=CustomActionDummy::class, - * "_api_collection_operation_name"="custom_denormalization", - * "_api_receive"=false - * } - * ) - */ + #[Route(methods: ['POST'], name: 'custom_denormalization', path: '/custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function customDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { throw new \RuntimeException('The "data" attribute must not be set.'); } - $object = new CustomActionDummy(); $object->setFoo('custom!'); return $object; } - /** - * @Route( - * methods={"GET"}, - * name="short_custom_normalization", - * path="/short_custom/{id}/normalization", - * defaults={"_api_resource_class"=CustomActionDummy::class, "_api_item_operation_name"="custom_normalization"} - * ) - */ + #[Route(methods: ['GET'], name: 'short_custom_normalization', path: '/short_custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] public function shortCustomNormalizationAction(CustomActionDummy $data) { $data->setFoo('short'); @@ -77,24 +51,12 @@ public function shortCustomNormalizationAction(CustomActionDummy $data) return $this->json($data); } - /** - * @Route( - * methods={"POST"}, - * name="short_custom_denormalization", - * path="/short_custom/denormalization", - * defaults={ - * "_api_resource_class"=CustomActionDummy::class, - * "_api_collection_operation_name"="custom_denormalization", - * "_api_receive"=false - * } - * ) - */ + #[Route(methods: ['POST'], name: 'short_custom_denormalization', path: '/short_custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function shortCustomDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { throw new \RuntimeException('The "data" attribute must not be set.'); } - $object = new CustomActionDummy(); $object->setFoo('short declaration'); diff --git a/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php b/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php index 7c37df63dad..2b6d837d995 100644 --- a/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php +++ b/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php @@ -19,30 +19,18 @@ class DummyValidationController { /** - * @Route( - * methods={"POST"}, - * name="post_validation_groups", - * path="/dummy_validation/validation_groups", - * defaults={"_api_resource_class"=DummyValidation::class, "_api_collection_operation_name"="post_validation_groups"} - * ) - * * @param mixed $data */ + #[Route(methods: ['POST'], name: 'post_validation_groups', path: '/dummy_validation/validation_groups', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_groups'])] public function postValidationGroups($data) { return $data; } /** - * @Route( - * methods={"POST"}, - * name="post_validation_sequence", - * path="/dummy_validation/validation_sequence", - * defaults={"_api_resource_class"=DummyValidation::class, "_api_collection_operation_name"="post_validation_sequence"} - * ) - * * @param mixed $data */ + #[Route(methods: ['POST'], name: 'post_validation_sequence', path: '/dummy_validation/validation_sequence', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_sequence'])] public function postValidationSequence($data) { return $data; diff --git a/tests/Fixtures/TestBundle/DataPersister/DummyDtoNoOutputDataPersister.php b/tests/Fixtures/TestBundle/DataPersister/DummyDtoNoOutputDataPersister.php deleted file mode 100644 index 8b85c25e6b9..00000000000 --- a/tests/Fixtures/TestBundle/DataPersister/DummyDtoNoOutputDataPersister.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataPersister; - -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoNoOutput as DummyDtoNoOutputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\InputDto as InputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoNoOutput; -use Doctrine\Persistence\ManagerRegistry; - -class DummyDtoNoOutputDataPersister implements DataPersisterInterface -{ - private $registry; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - /** - * {@inheritdoc} - */ - public function supports($data): bool - { - return $data instanceof InputDto || $data instanceof InputDtoDocument; - } - - /** - * {@inheritdoc} - */ - public function persist($data) - { - $isOrm = true; - $em = $this->registry->getManagerForClass(DummyDtoNoOutput::class); - if (null === $em) { - $em = $this->registry->getManagerForClass(DummyDtoNoOutputDocument::class); - $isOrm = false; - } - - $output = $isOrm ? new DummyDtoNoOutput() : new DummyDtoNoOutputDocument(); - $output->lorem = $data->foo; - $output->ipsum = (string) $data->bar; - - $em->persist($output); - $em->flush(); - - return $output; - } - - /** - * {@inheritdoc} - */ - public function remove($data) - { - return null; - } -} diff --git a/tests/Fixtures/TestBundle/DataPersister/UserResetPasswordDataPersister.php b/tests/Fixtures/TestBundle/DataPersister/UserResetPasswordDataPersister.php deleted file mode 100644 index 1239ae9a0fb..00000000000 --- a/tests/Fixtures/TestBundle/DataPersister/UserResetPasswordDataPersister.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataPersister; - -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\UserResetPasswordDto; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -final class UserResetPasswordDataPersister implements DataPersisterInterface -{ - public function persist($data) - { - if ('user@example.com' === $data->email) { - return $data; - } - - throw new NotFoundHttpException(); - } - - public function remove($data) - { - throw new \LogicException(sprintf('Unexpected "%s()" call.', __METHOD__)); - } - - public function supports($data): bool - { - return $data instanceof UserResetPasswordDto; - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/ContainNonResourceItemDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/ContainNonResourceItemDataProvider.php deleted file mode 100644 index b09139bc5b6..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/ContainNonResourceItemDataProvider.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\NotAResource; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\ContainNonResource as ContainNonResourceDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ContainNonResource; - -/** - * @author Kévin Dunglas - */ -class ContainNonResourceItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return \in_array($resourceClass, [ContainNonResource::class, ContainNonResourceDocument::class], true); - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - if (!\is_scalar($id)) { - throw new \InvalidArgumentException('The id must be a scalar.'); - } - - // Retrieve the blog post item from somewhere - $cnr = new $resourceClass(); - $cnr->id = $id; - $cnr->notAResource = new NotAResource('f1', 'b1'); - $cnr->nested = new $resourceClass(); - $cnr->nested->id = "$id-nested"; - $cnr->nested->notAResource = new NotAResource('f2', 'b2'); - - return $cnr; - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/DummyDtoNoInputCollectionDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/DummyDtoNoInputCollectionDataProvider.php deleted file mode 100644 index 8b8ecb182ab..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/DummyDtoNoInputCollectionDataProvider.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\State\Pagination\ArrayPaginator; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoNoInput as DummyDtoNoInputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto as OutputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoNoInput; -use Doctrine\Persistence\ManagerRegistry; - -/** - * @author Vincent Chalamon - */ -final class DummyDtoNoInputCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface -{ - private $registry; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return \in_array($resourceClass, [DummyDtoNoInput::class, DummyDtoNoInputDocument::class], true); - } - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null, array $context = []) - { - /** @var DummyDtoNoInput[]|DummyDtoNoInputDocument[] $dummyDtos */ - $dummyDtos = $this->registry->getManagerForClass($resourceClass)->getRepository($resourceClass)->findAll(); - $objects = []; - foreach ($dummyDtos as $dummyDto) { - $object = DummyDtoNoInput::class === $resourceClass ? new OutputDto() : new OutputDtoDocument(); - $object->bat = $dummyDto->lorem; - $object->baz = $dummyDto->ipsum; - $objects[] = $object; - } - - return new ArrayPaginator($objects, 0, \count($objects)); - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/GeneratorDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/GeneratorDataProvider.php deleted file mode 100644 index 96658def507..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/GeneratorDataProvider.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SecuredDummy; - -class GeneratorDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface -{ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return SecuredDummy::class === $resourceClass && 'get_from_data_provider_generator' === $operationName; - } - - public function getCollection(string $resourceClass, string $operationName = null) - { - yield from [new class() { - }, new class() { - }]; - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/ProductItemDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/ProductItemDataProvider.php deleted file mode 100644 index 420d8148834..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/ProductItemDataProvider.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Product as ProductDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Product; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ProductInterface; -use Doctrine\Persistence\ManagerRegistry; - -class ProductItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - private $managerRegistry; - private $orm; - - public function __construct(ManagerRegistry $managerRegistry, bool $orm = true) - { - $this->managerRegistry = $managerRegistry; - $this->orm = $orm; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return is_a($resourceClass, ProductInterface::class, true); - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return $this->managerRegistry->getRepository($this->orm ? Product::class : ProductDocument::class)->findOneBy([ - 'code' => $id, - ]); - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/ResourceInterfaceImplementationDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/ResourceInterfaceImplementationDataProvider.php deleted file mode 100644 index 48f35338a5d..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/ResourceInterfaceImplementationDataProvider.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterfaceImplementation; - -class ResourceInterfaceImplementationDataProvider implements ItemDataProviderInterface, CollectionDataProviderInterface, RestrictedDataProviderInterface -{ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return ResourceInterface::class === $resourceClass; - } - - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - if ('some-id' === $id) { - return (new ResourceInterfaceImplementation())->setFoo('single item'); - } - - return null; - } - - public function getCollection(string $resourceClass, string $operationName = null): iterable - { - yield (new ResourceInterfaceImplementation())->setFoo('item1'); - yield (new ResourceInterfaceImplementation())->setFoo('item2'); - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/SerializableItemDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/SerializableItemDataProvider.php deleted file mode 100644 index 05e53b6a278..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/SerializableItemDataProvider.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderInterface; -use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderTrait; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\SerializableResource; - -/** - * @author Vincent Chalamon - */ -class SerializableItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface, SerializerAwareDataProviderInterface -{ - use SerializerAwareDataProviderTrait; - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return $this->getSerializer()->deserialize(<<<'JSON' -{ - "id": 1, - "foo": "Lorem", - "bar": "Ipsum" -} -JSON - , $resourceClass, 'json'); - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return SerializableResource::class === $resourceClass; - } -} diff --git a/tests/Fixtures/TestBundle/DataProvider/TaxonItemDataProvider.php b/tests/Fixtures/TestBundle/DataProvider/TaxonItemDataProvider.php deleted file mode 100644 index ee04570084f..00000000000 --- a/tests/Fixtures/TestBundle/DataProvider/TaxonItemDataProvider.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataProvider; - -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Taxon as TaxonDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Taxon; -use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; -use Doctrine\Persistence\ManagerRegistry; - -class TaxonItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface -{ - private $managerRegistry; - private $orm; - - public function __construct(ManagerRegistry $managerRegistry, bool $orm = true) - { - $this->managerRegistry = $managerRegistry; - $this->orm = $orm; - } - - /** - * {@inheritdoc} - */ - public function supports(string $resourceClass, string $operationName = null, array $context = []): bool - { - return is_a($resourceClass, TaxonInterface::class, true); - } - - /** - * {@inheritdoc} - */ - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return $this->managerRegistry->getRepository($this->orm ? Taxon::class : TaxonDocument::class)->findOneBy([ - 'code' => $id, - ]); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/CustomInputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/CustomInputDtoDataTransformer.php deleted file mode 100644 index 8374881e57b..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/CustomInputDtoDataTransformer.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Serializer\AbstractItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoCustom as DummyDtoCustomDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomInputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoCustom; - -final class CustomInputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if (!$object instanceof CustomInputDto) { - throw new \InvalidArgumentException(); - } - - /** - * @var \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoCustom - */ - $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); - $resourceObject->lorem = $object->foo; - $resourceObject->ipsum = (string) $object->bar; - - return $resourceObject; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - return (DummyDtoCustom::class === $to || DummyDtoCustomDocument::class === $to) && CustomInputDto::class === ($context['input']['class'] ?? null); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/CustomOutputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/CustomOutputDtoDataTransformer.php deleted file mode 100644 index 0e3586e10bf..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/CustomOutputDtoDataTransformer.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoCustom as DummyDtoCustomDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomOutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoCustom; - -final class CustomOutputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if ($object instanceof \Traversable) { - foreach ($object as &$value) { - $value = $this->doTransformation($value); - } - - return $object; - } - - return $this->doTransformation($object); - } - - private function doTransformation($object): CustomOutputDto - { - $output = new CustomOutputDto(); - $output->foo = $object->lorem; - $output->bar = (int) $object->ipsum; - - return $output; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - if ($object instanceof \IteratorAggregate) { - $iterator = $object->getIterator(); - if ($iterator instanceof \Iterator) { - $object = $iterator->current(); - } - } - - return ($object instanceof DummyDtoCustom || $object instanceof DummyDtoCustomDocument) && CustomOutputDto::class === $to; - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/DummyDtoNoInputToOutputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/DummyDtoNoInputToOutputDtoDataTransformer.php deleted file mode 100644 index e9eb4cb7d2e..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/DummyDtoNoInputToOutputDtoDataTransformer.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoNoInput as DummyDtoNoInputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto as OutputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoNoInput; - -final class DummyDtoNoInputToOutputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if (!$object instanceof DummyDtoNoInput && !$object instanceof DummyDtoNoInputDocument) { - throw new \InvalidArgumentException(); - } - - $output = $object instanceof DummyDtoNoInput ? new OutputDto() : new OutputDtoDocument(); - $output->id = $object->getId(); - $output->bat = (string) $object->lorem; - $output->baz = (float) $object->ipsum; - - return $output; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return ($data instanceof DummyDtoNoInput || $data instanceof DummyDtoNoInputDocument) && \in_array($to, [OutputDto::class, OutputDtoDocument::class], true); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/InitializeInputDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/InitializeInputDataTransformer.php deleted file mode 100644 index 122c13cd671..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/InitializeInputDataTransformer.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Serializer\AbstractItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\InitializeInput as InitializeInputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\InitializeInput; - -final class InitializeInputDataTransformer implements DataTransformerInitializerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - /** @var InitializeInputDto */ - $data = $object; - - /** @var InitializeInput|InitializeInputDocument */ - $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); - $resourceObject->name = $data->name; - - return $resourceObject; - } - - /** - * {@inheritdoc} - */ - public function initialize(string $inputClass, array $context = []) - { - $currentResource = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? null; - if (!$currentResource) { - return new InitializeInputDto(); - } - - $dto = new InitializeInputDto(); - $dto->manager = $currentResource->manager; - - return $dto; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return (InitializeInput::class === $to || InitializeInputDocument::class === $to) && InitializeInputDto::class === ($context['input']['class'] ?? null); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/InputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/InputDtoDataTransformer.php deleted file mode 100644 index 41f55532fb5..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/InputDtoDataTransformer.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Serializer\AbstractItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoInputOutput as DummyDtoInputOutputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\InputDto as InputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoInputOutput; - -final class InputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - /** @var InputDtoDocument|InputDto */ - $data = $object; - - /** @var DummyDtoInputOutputDocument|DummyDtoInputOutput */ - $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); - $resourceObject->str = $data->foo; - $resourceObject->num = $data->bar; - // @phpstan-ignore-next-line - $resourceObject->relatedDummies = $data->relatedDummies; - - return $resourceObject; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - if ($object instanceof DummyDtoInputOutput || $object instanceof DummyDtoInputOutputDocument) { - return false; - } - - return \in_array($to, [DummyDtoInputOutput::class, DummyDtoInputOutputDocument::class], true) && \in_array($context['input']['class'], [InputDto::class, InputDtoDocument::class], true); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/OutputDtoDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/OutputDtoDataTransformer.php deleted file mode 100644 index cfdec547e6a..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/OutputDtoDataTransformer.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\State\Pagination\ArrayPaginator; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoInputOutput as DummyDtoInputOutputDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto as OutputDtoDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoInputOutput; - -final class OutputDtoDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if (!$object instanceof DummyDtoInputOutput && !$object instanceof DummyDtoInputOutputDocument) { - throw new \InvalidArgumentException(); - } - - $output = $object instanceof DummyDtoInputOutput ? new OutputDto() : new OutputDtoDocument(); - $output->id = $object->id; - $output->bat = (string) $object->str; - $output->baz = (float) $object->num; - // @phpstan-ignore-next-line - $output->relatedDummies = new ArrayPaginator($object->relatedDummies->toArray(), 0, \count($object->relatedDummies->toArray())); - - return $output; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return ($data instanceof DummyDtoInputOutput || $data instanceof DummyDtoInputOutputDocument) && \in_array($to, [OutputDto::class, OutputDtoDocument::class], true); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/OutputDtoSameClassTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/OutputDtoSameClassTransformer.php deleted file mode 100644 index f8a776016c1..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/OutputDtoSameClassTransformer.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoOutputFallbackToSameClass as DummyDtoOutputFallbackToSameClassDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoOutputSameClass as DummyDtoOutputSameClassDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDtoDummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoOutputFallbackToSameClass; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoOutputSameClass; - -/** - * @author Daniel West - */ -final class OutputDtoSameClassTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - if ( - !$object instanceof DummyDtoOutputFallbackToSameClass && - !$object instanceof DummyDtoOutputFallbackToSameClassDocument && - !$object instanceof DummyDtoOutputSameClass && - !$object instanceof DummyDtoOutputSameClassDocument - ) { - throw new \InvalidArgumentException(); - } - $object->ipsum = 'modified'; - - return $object; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return (($data instanceof DummyDtoOutputFallbackToSameClass || $data instanceof DummyDtoOutputFallbackToSameClassDocument) && OutputDtoDummy::class === $to) || - (($data instanceof DummyDtoOutputSameClass || $data instanceof DummyDtoOutputSameClassDocument) && (DummyDtoOutputSameClass::class === $to || DummyDtoOutputSameClassDocument::class === $to)); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/RPCOutputDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/RPCOutputDataTransformer.php deleted file mode 100644 index 24d6bc442c0..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/RPCOutputDataTransformer.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\RPC as RPCDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RPCOutput; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RPC; - -final class RPCOutputDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - return new RPCOutput(); - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - return ($object instanceof RPC || $object instanceof RPCDocument) && RPCOutput::class === $to; - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordInputDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordInputDataTransformer.php deleted file mode 100644 index 30113044dd5..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordInputDataTransformer.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Serializer\AbstractItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\User as UserDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\User; - -final class RecoverPasswordInputDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($data, string $to, array $context = []) - { - // Because we're in a PUT operation, we will use the retrieved object... - $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); - // ...where we remove the credentials - $resourceObject->eraseCredentials(); - - return $resourceObject; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($data, string $to, array $context = []): bool - { - return (User::class === $to || UserDocument::class === $to) && RecoverPasswordInput::class === ($context['input']['class'] ?? null); - } -} diff --git a/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordOutputDataTransformer.php b/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordOutputDataTransformer.php deleted file mode 100644 index 5a19c76b525..00000000000 --- a/tests/Fixtures/TestBundle/DataTransformer/RecoverPasswordOutputDataTransformer.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\DataTransformer; - -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordOutput; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\User; - -final class RecoverPasswordOutputDataTransformer implements DataTransformerInterface -{ - /** - * {@inheritdoc} - * - * @return object - */ - public function transform($object, string $to, array $context = []) - { - $output = new RecoverPasswordOutput(); - $output->dummy = new Dummy(); - $output->dummy->setId(1); - - return $output; - } - - /** - * {@inheritdoc} - */ - public function supportsTransformation($object, string $to, array $context = []): bool - { - return $object instanceof User && RecoverPasswordOutput::class === $to; - } -} diff --git a/tests/Fixtures/TestBundle/Doctrine/Generator/Uuid.php b/tests/Fixtures/TestBundle/Doctrine/Generator/Uuid.php index 249af556bd0..d58d7675b6c 100644 --- a/tests/Fixtures/TestBundle/Doctrine/Generator/Uuid.php +++ b/tests/Fixtures/TestBundle/Doctrine/Generator/Uuid.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator; -class Uuid implements \JsonSerializable +class Uuid implements \JsonSerializable, \Stringable { private $id; @@ -22,7 +22,7 @@ public function __construct() $this->id = 'foo'; } - public function __toString() + public function __toString(): string { return $this->id; } diff --git a/tests/Fixtures/TestBundle/Doctrine/Orm/EntityManager.php b/tests/Fixtures/TestBundle/Doctrine/Orm/EntityManager.php index aca2035901a..1e66df65da3 100644 --- a/tests/Fixtures/TestBundle/Doctrine/Orm/EntityManager.php +++ b/tests/Fixtures/TestBundle/Doctrine/Orm/EntityManager.php @@ -24,13 +24,9 @@ final class EntityManager extends EntityManagerDecorator { public static $dql; - private $repositoryFactory; - - public function __construct(EntityManagerInterface $wrapped, RepositoryFactory $repositoryFactory) + public function __construct(EntityManagerInterface $wrapped, private readonly RepositoryFactory $repositoryFactory) { parent::__construct($wrapped); - - $this->repositoryFactory = $repositoryFactory; } public function getRepository($className): ObjectRepository diff --git a/tests/Fixtures/TestBundle/Document/AbstractDummy.php b/tests/Fixtures/TestBundle/Document/AbstractDummy.php index 52209aee373..fe958a27a1d 100644 --- a/tests/Fixtures/TestBundle/Document/AbstractDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbstractDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -40,14 +40,14 @@ abstract class AbstractDummy * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string The dummy name * * @ODM\Field - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[Assert\NotBlank] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Address.php b/tests/Fixtures/TestBundle/Document/Address.php index 165233bc2dc..fc51a941aab 100644 --- a/tests/Fixtures/TestBundle/Document/Address.php +++ b/tests/Fixtures/TestBundle/Document/Address.php @@ -24,16 +24,14 @@ class Address { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"order_read"}) */ - private $id; + #[Groups(['order_read'])] + private ?int $id = null; /** * @ODM\Field(type="string") - * @Groups({"order_read"}) */ + #[Groups(['order_read'])] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Answer.php b/tests/Fixtures/TestBundle/Document/Answer.php index 35749ff7482..ed3628b8762 100644 --- a/tests/Fixtures/TestBundle/Document/Answer.php +++ b/tests/Fixtures/TestBundle/Document/Answer.php @@ -37,23 +37,23 @@ class Answer { /** * @ODM\Id(strategy="INCREMENT", type="int") - * @Serializer\Groups({"foobar"}) */ + #[Serializer\Groups(['foobar'])] private $id; /** * @ODM\Field(nullable=false) - * @Serializer\Groups({"foobar"}) */ + #[Serializer\Groups(['foobar'])] private $content; /** * @ODM\ReferenceOne(targetDocument=Question::class, mappedBy="answer") - * @Serializer\Groups({"foobar"}) */ + #[Serializer\Groups(['foobar'])] private $question; /** * @ODM\ReferenceMany(targetDocument=Question::class, mappedBy="answer") - * @Serializer\Groups({"foobar"}) */ + #[Serializer\Groups(['foobar'])] private $relatedQuestions; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php b/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php index 15f3b16594c..e62e876b234 100644 --- a/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php +++ b/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayRequiredFilter; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -33,13 +33,14 @@ class ArrayFilterValidator * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; + /** * @var string A name * * @ODM\Field - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/CircularReference.php b/tests/Fixtures/TestBundle/Document/CircularReference.php index 49a7e7ea3e1..c52b4586bc3 100644 --- a/tests/Fixtures/TestBundle/Document/CircularReference.php +++ b/tests/Fixtures/TestBundle/Document/CircularReference.php @@ -33,15 +33,13 @@ class CircularReference public $id; /** * @ODM\ReferenceOne(targetDocument=CircularReference::class, inversedBy="children") - * - * @Groups({"circular"}) */ + #[Groups(['circular'])] public $parent; /** * @ODM\ReferenceMany(targetDocument=CircularReference::class, mappedBy="parent") - * - * @Groups({"circular"}) */ + #[Groups(['circular'])] public $children; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/Company.php b/tests/Fixtures/TestBundle/Document/Company.php index ea00a67ded2..f38341eaf07 100644 --- a/tests/Fixtures/TestBundle/Document/Company.php +++ b/tests/Fixtures/TestBundle/Document/Company.php @@ -35,7 +35,7 @@ class Company * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string The dummy name diff --git a/tests/Fixtures/TestBundle/Document/CompositeItem.php b/tests/Fixtures/TestBundle/Document/CompositeItem.php index ceb261691fd..6488716a36f 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeItem.php +++ b/tests/Fixtures/TestBundle/Document/CompositeItem.php @@ -23,7 +23,7 @@ * @ODM\Document */ #[ApiResource] -class CompositeItem +class CompositeItem implements \Stringable { /** * @ODM\Id(strategy="INCREMENT", type="int") @@ -31,13 +31,13 @@ class CompositeItem private $id; /** * @ODM\Field(type="string", nullable=true) - * @Groups({"default"}) */ + #[Groups(['default'])] private $field1; /** * @ODM\ReferenceMany(targetDocument=CompositeRelation::class, mappedBy="compositeItem") - * @Groups({"default"}) */ + #[Groups(['default'])] private $compositeValues; /** @@ -74,7 +74,7 @@ public function getCompositeValues(): ?CompositeRelation return $this->compositeValues; } - public function __toString() + public function __toString(): string { return (string) $this->id; } diff --git a/tests/Fixtures/TestBundle/Document/CompositeLabel.php b/tests/Fixtures/TestBundle/Document/CompositeLabel.php index 007c3460138..8ca472ef76c 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeLabel.php +++ b/tests/Fixtures/TestBundle/Document/CompositeLabel.php @@ -23,7 +23,7 @@ * @ODM\Document */ #[ApiResource] -class CompositeLabel +class CompositeLabel implements \Stringable { /** * @ODM\Id(strategy="INCREMENT", type="int") @@ -31,8 +31,8 @@ class CompositeLabel private $id; /** * @ODM\Field(type="string", nullable=true) - * @Groups({"default"}) */ + #[Groups(['default'])] private $value; /** @@ -61,7 +61,7 @@ public function setValue($value = null) $this->value = $value; } - public function __toString() + public function __toString(): string { return (string) $this->id; } diff --git a/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php b/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php index 259caabbb30..c1c04a10194 100644 --- a/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php +++ b/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php @@ -28,23 +28,21 @@ class CompositePrimitiveItem * @ODM\Id(strategy="INCREMENT", type="int") */ private $id; - /** - * @ODM\Field(type="string") - */ - private $name; - /** - * @ODM\Field(type="int") - */ - private $year; /** * @ODM\Field(type="string") */ private $description; - public function __construct(string $name, int $year) - { - $this->name = $name; - $this->year = $year; + public function __construct( + /** + * @ODM\Field(type="string") + */ + private readonly string $name, + /** + * @ODM\Field(type="int") + */ + private readonly int $year + ) { } /** diff --git a/tests/Fixtures/TestBundle/Document/CompositeRelation.php b/tests/Fixtures/TestBundle/Document/CompositeRelation.php index 883cb36450b..fd6fc8b3cde 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeRelation.php +++ b/tests/Fixtures/TestBundle/Document/CompositeRelation.php @@ -31,18 +31,18 @@ class CompositeRelation private $id; /** * @ODM\Field(type="string", nullable=true) - * @Groups({"default"}) */ + #[Groups(['default'])] private $value; /** * @ODM\ReferenceOne(targetDocument=CompositeItem::class, inversedBy="compositeValues") - * @Groups({"default"}) */ + #[Groups(['default'])] private $compositeItem; /** * @ODM\ReferenceOne(targetDocument=CompositeLabel::class) - * @Groups({"default"}) */ + #[Groups(['default'])] private $compositeLabel; /** diff --git a/tests/Fixtures/TestBundle/Document/ConcreteDummy.php b/tests/Fixtures/TestBundle/Document/ConcreteDummy.php index 5947f6c5925..c24bf00a2b8 100644 --- a/tests/Fixtures/TestBundle/Document/ConcreteDummy.php +++ b/tests/Fixtures/TestBundle/Document/ConcreteDummy.php @@ -30,8 +30,8 @@ class ConcreteDummy extends AbstractDummy * @var string a concrete thing * * @ODM\Field - * @Assert\NotBlank */ + #[Assert\NotBlank] private $instance; public function setInstance($instance) diff --git a/tests/Fixtures/TestBundle/Document/ContainNonResource.php b/tests/Fixtures/TestBundle/Document/ContainNonResource.php index fab00379d52..52147b7f4a4 100644 --- a/tests/Fixtures/TestBundle/Document/ContainNonResource.php +++ b/tests/Fixtures/TestBundle/Document/ContainNonResource.php @@ -30,20 +30,17 @@ class ContainNonResource { /** * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $id; /** * @var ContainNonResource - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $nested; /** * @var NotAResource - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $notAResource; } diff --git a/tests/Fixtures/TestBundle/Document/Content.php b/tests/Fixtures/TestBundle/Document/Content.php index 2d4dcb7ed54..b6a0802d561 100644 --- a/tests/Fixtures/TestBundle/Document/Content.php +++ b/tests/Fixtures/TestBundle/Document/Content.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Get; use ApiPlatform\Tests\Fixtures\TestBundle\Enum\ContentStatus; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -28,17 +27,13 @@ class Content implements \JsonSerializable { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string|null - * * @ODM\Field(type="string") */ - private $contentType; + private ?string $contentType = null; /** * @var Collection * @@ -49,13 +44,11 @@ class Content implements \JsonSerializable * cascade={"persist"}, * ) */ - private $fields; + private \Doctrine\Common\Collections\Collection & iterable $fields; /** - * @var string - * * @ODM\Field(type="string") */ - private $status; + private readonly string $status; public function __construct() { @@ -63,17 +56,13 @@ public function __construct() $this->status = ContentStatus::DRAFT; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getId(): ?int { return $this->id; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getContentType(): ?string { return $this->contentType; @@ -115,9 +104,7 @@ public function removeField(Field $field): void } } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getFieldValues(): array { $fieldValues = []; @@ -128,9 +115,7 @@ public function getFieldValues(): array return $fieldValues; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getStatus(): ContentStatus { return new ContentStatus($this->status); diff --git a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php index ae0a24b9ae8..47c41b4320e 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php @@ -26,11 +26,9 @@ class ConvertedBoolean { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var bool * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedDate.php b/tests/Fixtures/TestBundle/Document/ConvertedDate.php index 84c0cf4b54e..0fa64eba7f0 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedDate.php @@ -26,11 +26,9 @@ class ConvertedDate { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var \DateTime * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php index 2e9f7358c9f..2f2506254ca 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php @@ -30,11 +30,9 @@ class ConvertedInteger { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var int * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php index c1d8121c03f..494c426031a 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php @@ -26,11 +26,9 @@ class ConvertedOwner { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var ConvertedRelated * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedRelated.php b/tests/Fixtures/TestBundle/Document/ConvertedRelated.php index 3e7c60b77c8..4aa446cd698 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedRelated.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedRelated.php @@ -23,11 +23,9 @@ class ConvertedRelated { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/ConvertedString.php b/tests/Fixtures/TestBundle/Document/ConvertedString.php index 398f09932d6..fc1a48be85b 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedString.php @@ -26,11 +26,9 @@ class ConvertedString { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string|null * diff --git a/tests/Fixtures/TestBundle/Document/CustomActionDummy.php b/tests/Fixtures/TestBundle/Document/CustomActionDummy.php index 48ea7078c7b..27554a98ef6 100644 --- a/tests/Fixtures/TestBundle/Document/CustomActionDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomActionDummy.php @@ -28,17 +28,13 @@ class CustomActionDummy { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string - * * @ODM\Field */ - private $foo = ''; + private string $foo = ''; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php b/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php index e5fbe366b91..e5c19e2c381 100644 --- a/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php +++ b/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** @@ -26,11 +25,9 @@ class CustomGeneratedIdentifier { /** - * @var Uuid - * * @ODM\Id(strategy="CUSTOM", type="string", options={"class"="ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\DocumentUuidGenerator"}) */ - private $id; + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php index df3254ede88..5a8fa46c684 100644 --- a/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php @@ -29,13 +29,13 @@ class CustomIdentifierDummy * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $customId; + private ?int $customId = null; /** * @var string The dummy name * * @ODM\Field */ - private $name; + private ?string $name = null; public function getCustomId(): int { diff --git a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php index 98e69d900fe..3cf56a282a9 100644 --- a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -31,20 +31,22 @@ class CustomMultipleIdentifierDummy * * @ODM\Id(strategy="NONE", type="int") */ - private $firstId; + private ?int $firstId = null; + /** * @var int The custom identifier * - * @ApiProperty(identifier=true) * @ODM\Field(type="int") */ - private $secondId; + #[ApiProperty(identifier: true) + private ?int $secondId = null; + /** * @var string The dummy name * * @ODM\Field(type="string") */ - private $name; + private ?string $name = null; public function getFirstId(): int { diff --git a/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php b/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php index b4f773c056c..f6f054cb400 100644 --- a/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; @@ -32,26 +32,28 @@ class CustomNormalizedDummy * @var int|null The id * * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"input", "output"}) */ - private $id; + #[Groups(['input', 'output'])] + private ?int $id = null; + /** * @var string|null The dummy name * * @ODM\Field - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"input", "output"}) */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[Assert\NotBlank] + #[Groups(['input', 'output'])] + private ?string $name = null; + /** * @var string|null The dummy name alias * * @ODM\Field(nullable=true) - * @ApiProperty(iri="https://schema.org/alternateName") - * @Groups({"input", "output"}) */ - private $alias; + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[Groups(['input', 'output'])] + private ?string $alias = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php index 4f4e4510c8e..9f02150ba9b 100644 --- a/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php @@ -29,13 +29,13 @@ class CustomWritableIdentifierDummy * * @ODM\Id(strategy="NONE", type="string") */ - private $slug; + private ?string $slug = null; /** * @var string The dummy name * * @ODM\Field(name="name", type="string") */ - private $name; + private ?string $name = null; /** * @param string $slug diff --git a/tests/Fixtures/TestBundle/Document/Customer.php b/tests/Fixtures/TestBundle/Document/Customer.php index cdf8ca7b11a..5689df5fa4a 100644 --- a/tests/Fixtures/TestBundle/Document/Customer.php +++ b/tests/Fixtures/TestBundle/Document/Customer.php @@ -25,21 +25,19 @@ class Customer { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"order_read"}) */ - private $id; + #[Groups(['order_read'])] + private ?int $id = null; /** * @ODM\Field(type="string") - * @Groups({"order_read"}) */ + #[Groups(['order_read'])] public $name; /** * @ODM\ReferenceMany(targetDocument=Address::class) - * @Groups({"order_read"}) */ + #[Groups(['order_read'])] public $addresses; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DeprecatedResource.php b/tests/Fixtures/TestBundle/Document/DeprecatedResource.php index b7f4dc30f2d..c91d8cbc20f 100644 --- a/tests/Fixtures/TestBundle/Document/DeprecatedResource.php +++ b/tests/Fixtures/TestBundle/Document/DeprecatedResource.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -29,11 +29,12 @@ class DeprecatedResource * @ODM\Id(strategy="INCREMENT", type="int") */ public $id; + /** * @var string * - * @ApiProperty(attributes={"deprecation_reason"="This field is deprecated"}) * @ODM\Field */ + #[ApiProperty(deprecationReason: 'This field is deprecated')] public $deprecatedField; } diff --git a/tests/Fixtures/TestBundle/Document/Dummy.php b/tests/Fixtures/TestBundle/Document/Dummy.php index 713a6fcc889..ff73ba89e9f 100644 --- a/tests/Fixtures/TestBundle/Document/Dummy.php +++ b/tests/Fixtures/TestBundle/Document/Dummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; @@ -44,27 +44,27 @@ class Dummy * @var string|null The dummy name * * @ODM\Field(type="string") - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[Assert\NotBlank] private $name; /** * @var string|null The dummy name alias * * @ODM\Field(nullable=true) - * @ApiProperty(iri="https://schema.org/alternateName") */ + #[ApiProperty(types: ['http://schema.org/alternateName'])] private $alias; /** * @var array|null foo */ - private $foo; + private ?array $foo = null; /** * @var string|null A short description of the item * * @ODM\Field(type="string", nullable=true) - * @ApiProperty(iri="https://schema.org/description") */ + #[ApiProperty(types: ['http://schema.org/description'])] public $description; /** * @var string|null A dummy @@ -82,8 +82,8 @@ class Dummy * @var \DateTime|null A dummy date * * @ODM\Field(type="date", nullable=true) - * @ApiProperty(iri="http://schema.org/DateTime") */ + #[ApiProperty(types: ['http://schema.org/DateTime'])] public $dummyDate; /** * @var float|null A dummy float diff --git a/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php index 7741a626365..763a058a5e3 100644 --- a/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php @@ -37,18 +37,17 @@ class DummyAggregateOffer * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var \ArrayCollection * @ODM\ReferenceMany(targetDocument=DummyOffer::class, mappedBy="aggregate", cascade={"persist"}) */ - private $offers; + private \Doctrine\Common\Collections\ArrayCollection $offers; /** * @var DummyProduct The dummy product * * @ODM\ReferenceOne(targetDocument=DummyProduct::class, inversedBy="offers", storeAs="id") */ - private $product; + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct $product = null; /** * @var int The dummy aggregate offer value * diff --git a/tests/Fixtures/TestBundle/Document/DummyBoolean.php b/tests/Fixtures/TestBundle/Document/DummyBoolean.php index f60e664da4c..c5127b8d0d0 100644 --- a/tests/Fixtures/TestBundle/Document/DummyBoolean.php +++ b/tests/Fixtures/TestBundle/Document/DummyBoolean.php @@ -23,21 +23,16 @@ class DummyBoolean { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ - private $id; - /** - * @var bool - * - * @ODM\Field(type="bool", nullable=true) - */ - private $isDummyBoolean; - - public function __construct(bool $isDummyBoolean) - { - $this->isDummyBoolean = $isDummyBoolean; + private ?int $id = null; + + public function __construct( + /** + * @ODM\Field(type="bool", nullable=true) + */ + private readonly bool $isDummyBoolean + ) { } public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyCar.php b/tests/Fixtures/TestBundle/Document/DummyCar.php index 9eae42c488e..b51387b9c4b 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCar.php +++ b/tests/Fixtures/TestBundle/Document/DummyCar.php @@ -45,71 +45,62 @@ class DummyCar * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var mixed Something else * * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") * - * @Serializer\Groups({"colors"}) * @ApiFilter(SearchFilter::class, properties={"colors.prop"="ipartial", "colors"="exact"}) */ + #[Serializer\Groups(['colors'])] private $colors; /** * @var mixed Something else * * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") * - * @Serializer\Groups({"colors"}) * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $secondColors; + #[Serializer\Groups(['colors'])] + private ?mixed $secondColors = null; /** * @var mixed Something else * * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") * - * @Serializer\Groups({"colors"}) * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $thirdColors; + #[Serializer\Groups(['colors'])] + private ?mixed $thirdColors = null; /** * @var mixed Something else * * @ODM\ReferenceMany(targetDocument=UuidIdentifierDummy::class) * - * @Serializer\Groups({"colors"}) * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $uuid; + #[Serializer\Groups(['colors'])] + private ?mixed $uuid = null; /** - * @var string - * * @ODM\Field(type="string") * @ApiFilter(SearchFilter::class, strategy="partial") */ - private $name; + private ?string $name = null; /** - * @var bool - * * @ODM\Field(type="bool") */ - private $canSell; + private ?bool $canSell = null; /** - * @var \DateTime - * * @ODM\Field(type="date") */ - private $availableAt; + private ?\DateTime $availableAt = null; /** - * @var string - * - * @Serializer\Groups({"colors"}) - * @Serializer\SerializedName("carBrand") - * * @ODM\Field */ - private $brand = 'DummyBrand'; + #[Serializer\Groups(['colors'])] + #[Serializer\SerializedName('carBrand')] + private string $brand = 'DummyBrand'; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/DummyCarColor.php b/tests/Fixtures/TestBundle/Document/DummyCarColor.php index 098bb012d9b..3c639fa7430 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Document/DummyCarColor.php @@ -31,24 +31,19 @@ class DummyCarColor * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var DummyCar - * * @ODM\ReferenceOne(targetDocument=DummyCar::class, inversedBy="colors", storeAs="id") - * @Assert\NotBlank */ - private $car; + #[Assert\NotBlank] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyCar $car = null; /** - * @var string - * * @ODM\Field(nullable=false) * @ApiFilter(SearchFilter::class) - * @Assert\NotBlank - * - * @Serializer\Groups({"colors"}) */ - private $prop = ''; + #[Assert\NotBlank] + #[Serializer\Groups(['colors'])] + private string $prop = ''; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php b/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php index 0340046b7c6..81363bdb361 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php @@ -33,8 +33,8 @@ class DummyCustomFormat * @var string * * @ODM\Field - * @Assert\NotBlank */ + #[Assert\NotBlank] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php index 3de558aff3b..d7b915c0725 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php @@ -30,31 +30,23 @@ class DummyCustomMutation { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var int|null - * * @ODM\Field(type="int") */ - private $operandA; + private ?int $operandA = null; /** - * @var int|null - * - * @Groups({"sum"}) * @ODM\Field(type="int", nullable=true) */ - private $operandB; + #[Groups(['sum'])] + private ?int $operandB = null; /** - * @var int|null - * - * @Groups({"result"}) * @ODM\Field(type="int", nullable=true) */ - private $result; + #[Groups(['result'])] + private ?int $result = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/DummyDate.php b/tests/Fixtures/TestBundle/Document/DummyDate.php index 9a031d0263b..951031052b7 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyDate.php @@ -41,7 +41,7 @@ class DummyDate * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var \DateTime|null The dummy date * diff --git a/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php b/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php index 432f52a6912..ddb69430dfb 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php +++ b/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php @@ -32,23 +32,23 @@ class DummyDifferentGraphQlSerializationGroup * @var int|null The id * * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) - * @Groups({"item_query", "collection_query"}) */ - private $id; + #[Groups(['item_query', 'collection_query'])] + private ?int $id = null; /** * @var string|null The dummy name * * @ODM\Field(type="string") - * @Groups({"item_query", "collection_query"}) */ - private $name; + #[Groups(['item_query', 'collection_query'])] + private ?string $name = null; /** * @var string|null The dummy title * * @ODM\Field(nullable=true) - * @Groups({"item_query"}) */ - private $title; + #[Groups(['item_query'])] + private ?string $title = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php index 19f0b0615b6..93d1cfce581 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php @@ -36,7 +36,7 @@ class DummyDtoCustom * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php index 3583477b161..1e7f37bc8bf 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php @@ -37,7 +37,7 @@ class DummyDtoNoInput * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php b/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php index dcc63c4762a..f528ef166c0 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php @@ -31,7 +31,7 @@ class DummyDtoNoOutput * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php index a87f7192099..5257f79deee 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php @@ -31,7 +31,7 @@ class DummyDtoOutputFallbackToSameClass * * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ - private $id; + private ?int $id = null; /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php index 52608d96c90..79a5da53514 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php @@ -30,7 +30,7 @@ class DummyDtoOutputSameClass * * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ - private $id; + private ?int $id = null; /** * @var string * diff --git a/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php b/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php index 83d1ce1984a..133a9fb99e7 100644 --- a/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php +++ b/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php @@ -38,39 +38,27 @@ class DummyEntityWithConstructor * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string - * - * @ODM\Field - */ - private $foo; - /** - * @var string - * - * @ODM\Field - */ - private $bar; - /** - * @var string|null - * * @ODM\Field(nullable=true) - * @Groups({"put"}) */ - private $baz; - /** - * @var DummyObjectWithoutConstructor[] - */ - private $items; + #[Groups(['put'])] + private ?string $baz = null; /** * @param DummyObjectWithoutConstructor[] $items */ - public function __construct(string $foo, string $bar, array $items) - { - $this->foo = $foo; - $this->bar = $bar; - $this->items = $items; + public function __construct( + /** + * @ODM\Field + */ + private readonly string $foo, + /** + * @ODM\Field + */ + private readonly string $bar, + private readonly array $items + ) { } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyFriend.php b/tests/Fixtures/TestBundle/Document/DummyFriend.php index 17264a8b247..f1dfc27ebcb 100644 --- a/tests/Fixtures/TestBundle/Document/DummyFriend.php +++ b/tests/Fixtures/TestBundle/Document/DummyFriend.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -35,16 +35,16 @@ class DummyFriend * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string|null The dummy name * * @ODM\Field(type="string") - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"fakemanytomany", "friends"}) */ - private $name; + #[Assert\NotBlank] + #[ApiProperty(types: ['http://schema.org/name'])] + #[Groups(['fakemanytomany', 'friends'])] + private ?string $name = null; /** * Get id. diff --git a/tests/Fixtures/TestBundle/Document/DummyGroup.php b/tests/Fixtures/TestBundle/Document/DummyGroup.php index f3a285851dd..e1c29c1f6c0 100644 --- a/tests/Fixtures/TestBundle/Document/DummyGroup.php +++ b/tests/Fixtures/TestBundle/Document/DummyGroup.php @@ -31,44 +31,37 @@ class DummyGroup { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups({"dummy", "dummy_read", "dummy_id"}) */ - private $id; + #[Groups(['dummy', 'dummy_read', 'dummy_id'])] + private ?int $id = null; /** * @var string|null * * @ODM\Field(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_foo"}) */ + #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_foo'])] public $foo; /** * @var string|null * * @ODM\Field(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_bar"}) */ + #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_bar'])] public $bar; /** * @var string|null * * @ODM\Field(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_baz"}) */ + #[Groups(['dummy', 'dummy_read', 'dummy_baz'])] public $baz; /** * @var string|null * * @ODM\Field(nullable=true) - * - * @Groups({"dummy", "dummy_write", "dummy_qux"}) */ + #[Groups(['dummy', 'dummy_write', 'dummy_qux'])] public $qux; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php b/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php index bea42a31140..9f469df2334 100644 --- a/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php @@ -30,7 +30,7 @@ class DummyImmutableDate * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var \DateTimeImmutable The dummy date * diff --git a/tests/Fixtures/TestBundle/Document/DummyOffer.php b/tests/Fixtures/TestBundle/Document/DummyOffer.php index bd86f54cf3c..95e5cb4064a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyOffer.php +++ b/tests/Fixtures/TestBundle/Document/DummyOffer.php @@ -37,19 +37,19 @@ class DummyOffer * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var int The dummy aggregate offer value * * @ODM\Field(type="int") */ - private $value; + private ?int $value = null; /** * @var DummyAggregateOffer The dummy aggregate offer value * * @ODM\ReferenceOne(targetDocument=DummyAggregateOffer::class, inversedBy="offers", storeAs="id") */ - private $aggregate; + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer $aggregate = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/DummyProduct.php b/tests/Fixtures/TestBundle/Document/DummyProduct.php index f475f76f528..8741706e6b1 100644 --- a/tests/Fixtures/TestBundle/Document/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Document/DummyProduct.php @@ -37,12 +37,11 @@ class DummyProduct * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var \Collection * @ODM\ReferenceMany(targetDocument=DummyAggregateOffer::class, mappedBy="product", cascade={"persist"}) */ - private $offers; + private \Doctrine\Common\Collections\Collection $offers; /** * @var string The tour name * @@ -50,10 +49,9 @@ class DummyProduct */ private $name; /** - * @var \Collection * @ODM\ReferenceMany(targetDocument=DummyProduct::class, mappedBy="parent") */ - private $relatedProducts; + private \Doctrine\Common\Collections\Collection $relatedProducts; /** * @ODM\ReferenceOne(targetDocument=DummyProduct::class, inversedBy="relatedProducts") */ diff --git a/tests/Fixtures/TestBundle/Document/DummyProperty.php b/tests/Fixtures/TestBundle/Document/DummyProperty.php index 23f56b8206f..659da6e9c6d 100644 --- a/tests/Fixtures/TestBundle/Document/DummyProperty.php +++ b/tests/Fixtures/TestBundle/Document/DummyProperty.php @@ -30,59 +30,51 @@ class DummyProperty { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups({"dummy_read", "dummy_graphql_read"}) */ - private $id; + #[Groups(['dummy_read', 'dummy_graphql_read'])] + private ?int $id = null; /** * @var string|null * * @ODM\Field(nullable=true) - * - * @Groups({"dummy_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_write'])] public $foo; /** * @var string|null * * @ODM\Field(nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $bar; /** * @var string|null * * @ODM\Field(nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $baz; /** * @var DummyGroup|null * * @ODM\ReferenceOne(targetDocument=DummyGroup::class, cascade={"persist"}, nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $group; /** * @var DummyGroup[]|null * * @ODM\ReferenceMany(targetDocument=DummyGroup::class, cascade={"persist"}) - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $groups; /** * @var string|null * * @ODM\Field(nullable=true) - * - * @Groups({"dummy_read", "dummy_write"}) */ + #[Groups(['dummy_read', 'dummy_write'])] public $nameConverted; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php index 97bf357a15b..bf62359f031 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php @@ -35,24 +35,20 @@ class DummyTableInheritance * @var int|null The id * * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups({"default"}) */ - private $id; + #[Groups(['default'])] + private ?int $id = null; /** * @var string|null The dummy name * * @ODM\Field - * - * @Groups({"default"}) */ - private $name; + #[Groups(['default'])] + private ?string $name = null; /** - * @var DummyTableInheritanceRelated|null - * * @ODM\ReferenceOne(targetDocument=DummyTableInheritanceRelated::class, inversedBy="children") */ - private $parent; + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyTableInheritanceRelated $parent = null; public function getName(): ?string { diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php index 16233935104..f68d56d7303 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php @@ -27,9 +27,8 @@ class DummyTableInheritanceChild extends DummyTableInheritance * @var string The dummy nickname * * @ODM\Field - * - * @Groups({"default"}) */ + #[Groups(['default'])] private $nickname; public function getNickname() diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php index 03eecfc2777..d2d18663eed 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php @@ -27,9 +27,8 @@ class DummyTableInheritanceDifferentChild extends DummyTableInheritance * @var string The dummy email * * @ODM\Field - * - * @Groups({"default"}) */ + #[Groups(['default'])] private $email; public function getEmail() diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php index b0a65151c7c..e63abb37422 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php @@ -25,7 +25,7 @@ class DummyTableInheritanceNotApiResourceChild extends DummyTableInheritance * * @ODM\Field(type="bool") */ - private $swaggerThanParent; + private bool $swaggerThanParent; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php index 6435a8efccf..db7a6562e98 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php @@ -29,18 +29,16 @@ class DummyTableInheritanceRelated * @var int The id * * @ODM\Id(strategy="INCREMENT", type="int") - * - * @Groups({"default"}) */ - private $id; + #[Groups(['default'])] + private ?int $id = null; /** * @var Collection Related children * * @ODM\ReferenceMany(targetDocument=DummyTableInheritance::class, mappedBy="parent") - * - * @Groups({"default"}) */ - private $children; + #[Groups(['default'])] + private \Doctrine\Common\Collections\Collection $children; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/DummyValidation.php b/tests/Fixtures/TestBundle/Document/DummyValidation.php index 69f62e67788..ef67d1593c5 100644 --- a/tests/Fixtures/TestBundle/Document/DummyValidation.php +++ b/tests/Fixtures/TestBundle/Document/DummyValidation.php @@ -34,26 +34,26 @@ class DummyValidation * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string|null The dummy name * * @ODM\Field(nullable=true) - * @Assert\NotNull(groups={"a"}) */ - private $name; + #[Assert\NotNull(groups: ['a'])] + private ?string $name = null; /** * @var string|null The dummy title * * @ODM\Field(nullable=true) - * @Assert\NotNull(groups={"b"}) */ - private $title; + #[Assert\NotNull(groups: ['b'])] + private ?string $title = null; /** * @var string|null The dummy code * @ODM\Field */ - private $code; + private ?string $code = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php b/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php index 1d53cd585eb..d0445a6e86a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php +++ b/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php @@ -29,13 +29,13 @@ class DummyWithEmbedManyOmittingTargetDocument * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var EmbeddableDummy[]|Collection * * @ODM\EmbedMany */ - private $embeddedDummies; + private readonly array|\Doctrine\Common\Collections\Collection $embeddedDummies; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php b/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php index 180b6cf6fb9..8b519e37ed8 100644 --- a/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php +++ b/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php @@ -31,9 +31,9 @@ class EmbeddableDummy * @var string|null The dummy name * * @ODM\Field(type="string") - * @Groups({"embed"}) */ - private $dummyName; + #[Groups(['embed'])] + private ?string $dummyName = null; /** * @var bool|null A dummy boolean @@ -46,8 +46,8 @@ class EmbeddableDummy * @var \DateTime|null A dummy date * * @ODM\Field(type="date") - * @Assert\DateTime */ + #[Assert\DateTime] public $dummyDate; /** @@ -66,8 +66,8 @@ class EmbeddableDummy /** * @ODM\Field(type="string") - * @Groups({"barcelona", "chicago"}) */ + #[Groups(['barcelona', 'chicago'])] protected $symfony; public static function staticMethod(): void diff --git a/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php b/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php index ce0bb5fab40..7b76c81c608 100644 --- a/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php +++ b/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php @@ -38,27 +38,27 @@ class EmbeddedDummy * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string|null The dummy name * * @ODM\Field(type="string") - * @Groups({"embed"}) */ - private $name; + #[Groups(['embed'])] + private ?string $name = null; /** * @var \DateTime|null A dummy date * * @ODM\Field(type="date") - * @Assert\DateTime */ + #[Assert\DateTime] public $dummyDate; /** * @var EmbeddableDummy * * @ODM\EmbedOne(targetDocument=EmbeddableDummy::class) - * @Groups({"embed"}) */ + #[Groups(['embed'])] public $embeddedDummy; /** * @var RelatedDummy|null A related dummy diff --git a/tests/Fixtures/TestBundle/Document/Field.php b/tests/Fixtures/TestBundle/Document/Field.php index c9206c41f37..cb7961df786 100644 --- a/tests/Fixtures/TestBundle/Document/Field.php +++ b/tests/Fixtures/TestBundle/Document/Field.php @@ -21,32 +21,24 @@ class Field implements \JsonSerializable { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var Content|null - * * @ODM\ReferenceOne(targetDocument=Content::class, inversedBy="fields") */ - private $content; + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Content $content = null; /** - * @var string|null - * * @ODM\Field(type="string") */ - private $name; + private ?string $name = null; /** - * @var string|null - * * @ODM\Field(type="string") */ - private $value; + private ?string $value = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/FileConfigDummy.php b/tests/Fixtures/TestBundle/Document/FileConfigDummy.php index fa70962cdb2..2307c657e92 100644 --- a/tests/Fixtures/TestBundle/Document/FileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Document/FileConfigDummy.php @@ -22,14 +22,14 @@ */ class FileConfigDummy { - public const HYDRA_TITLE = 'File config Dummy'; + final public const HYDRA_TITLE = 'File config Dummy'; /** * @var int The id * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string The dummy name diff --git a/tests/Fixtures/TestBundle/Document/FilterValidator.php b/tests/Fixtures/TestBundle/Document/FilterValidator.php index e02b8b954e1..15aedd105ec 100644 --- a/tests/Fixtures/TestBundle/Document/FilterValidator.php +++ b/tests/Fixtures/TestBundle/Document/FilterValidator.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayItemsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\BoundsFilter; @@ -40,13 +40,14 @@ class FilterValidator * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; + /** * @var string A name * * @ODM\Field - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Foo.php b/tests/Fixtures/TestBundle/Document/Foo.php index a79a8a1db60..801bf16f4fa 100644 --- a/tests/Fixtures/TestBundle/Document/Foo.php +++ b/tests/Fixtures/TestBundle/Document/Foo.php @@ -38,7 +38,7 @@ class Foo * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string The foo name * diff --git a/tests/Fixtures/TestBundle/Document/FooDummy.php b/tests/Fixtures/TestBundle/Document/FooDummy.php index 351084cdbef..e0fd4cf8002 100644 --- a/tests/Fixtures/TestBundle/Document/FooDummy.php +++ b/tests/Fixtures/TestBundle/Document/FooDummy.php @@ -31,7 +31,7 @@ class FooDummy * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string The foo name * @@ -43,7 +43,7 @@ class FooDummy * * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, storeAs="id") */ - private $dummy; + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy $dummy = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/FourthLevel.php b/tests/Fixtures/TestBundle/Document/FourthLevel.php index 2856be2848e..1f21f6032cb 100644 --- a/tests/Fixtures/TestBundle/Document/FourthLevel.php +++ b/tests/Fixtures/TestBundle/Document/FourthLevel.php @@ -39,14 +39,12 @@ class FourthLevel * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var int|null - * * @ODM\Field(type="int") - * @Groups({"barcelona", "chicago"}) */ - private $level = 4; + #[Groups(['barcelona', 'chicago'])] + private ?int $level = 4; /** * @ODM\ReferenceMany(targetDocument=ThirdLevel::class, cascade={"persist"}, mappedBy="badFourthLevel", storeAs="id") */ diff --git a/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php b/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php index b47f9fb6f95..393f680037a 100644 --- a/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php +++ b/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php @@ -30,13 +30,11 @@ class IriOnlyDummy * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string|null - * * @ODM\Field(type="string") */ - private $foo; + private ?string $foo = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php b/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php index 5a062b79491..25004f56e97 100644 --- a/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php +++ b/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -28,23 +28,17 @@ class JsonldContextDummy /** * @var int The id * - * @ApiProperty(identifier=true) * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ApiProperty(identifier: true)] + private ?int $id = null; + /** * @var string The dummy person - * - * @ApiProperty( - * attributes={ - * "jsonld_context"={ - * "@id"="http://example.com/id", - * "@type"="@id", - * "foo"="bar" - * } - * }, - * ) */ + #[ApiProperty( + jsonldContext: ['@id' => 'https://example.com/id', '@type' => '@id', 'foo' => 'bar'] + )] private $person; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php b/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php index 4b9bcbb96fc..ba685fbb617 100644 --- a/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php @@ -33,31 +33,29 @@ class LegacySecuredDummy { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string|null The title * * @ODM\Field - * @Assert\NotBlank */ - private $title; + #[Assert\NotBlank] + private ?string $title = null; /** * @var string The description * * @ODM\Field */ - private $description = ''; + private string $description = ''; /** * @var string|null The owner * * @ODM\Field - * @Assert\NotBlank */ - private $owner; + #[Assert\NotBlank] + private ?string $owner = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php index 11c614bcb5d..70883456ac1 100644 --- a/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php @@ -30,19 +30,19 @@ class MaxDepthDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"default"}) */ + #[Groups(['default'])] private $id; /** * @ODM\Field(name="name", type="string") - * @Groups({"default"}) */ + #[Groups(['default'])] public $name; /** * @ODM\ReferenceOne(targetDocument=MaxDepthDummy::class, cascade={"persist"}) - * @Groups({"default"}) - * @MaxDepth(1) */ + #[Groups(['default'])] + #[MaxDepth(1)] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php index 445db6d627c..4fb93daeef0 100644 --- a/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php @@ -30,19 +30,19 @@ class MaxDepthEagerDummy { /** * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"default"}) */ + #[Groups(['default'])] private $id; /** * @ODM\Field(name="name", type="string") - * @Groups({"default"}) */ + #[Groups(['default'])] public $name; /** * @ODM\ReferenceOne(targetDocument=MaxDepthEagerDummy::class, cascade={"persist"}) - * @Groups({"default"}) - * @MaxDepth(1) */ + #[Groups(['default'])] + #[MaxDepth(1)] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/MessengerWithInput.php b/tests/Fixtures/TestBundle/Document/MessengerWithInput.php index 811408202b8..09f87095566 100644 --- a/tests/Fixtures/TestBundle/Document/MessengerWithInput.php +++ b/tests/Fixtures/TestBundle/Document/MessengerWithInput.php @@ -13,20 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Symfony\Messenger\Processor; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerInput; -#[ApiResource(graphQlOperations: [new Mutation(name: 'create', input: MessengerInput::class, messenger: 'input')], messenger: 'input', input: MessengerInput::class)] +#[ApiResource( + graphQlOperations: [new Mutation(name: 'create', input: MessengerInput::class, processor: Processor::class)], + processor: Processor::class, + input: MessengerInput::class +)] class MessengerWithInput { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public $id; - /** - * @var string - */ - public $name; + + public string $name; } diff --git a/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php b/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php index 79abbb2207b..1aa02e9ae12 100644 --- a/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php +++ b/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php @@ -33,7 +33,7 @@ class NoCollectionDummy * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/Order.php b/tests/Fixtures/TestBundle/Document/Order.php index e50f95b3a17..55f7a6f3326 100644 --- a/tests/Fixtures/TestBundle/Document/Order.php +++ b/tests/Fixtures/TestBundle/Document/Order.php @@ -25,22 +25,20 @@ class Order { /** - * @var int - * * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"order_read"}) */ - private $id; + #[Groups(['order_read'])] + private ?int $id = null; /** * @ODM\ReferenceOne(targetDocument=Customer::class) - * @Groups({"order_read"}) */ + #[Groups(['order_read'])] public $customer; /** * @ODM\ReferenceOne(targetDocument=Customer::class) - * @Assert\NotNull - * @Groups({"order_read"}) */ + #[Assert\NotNull] + #[Groups(['order_read'])] public $recipient; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php b/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php index 9c7b1210f6e..83a6be3eb57 100644 --- a/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php +++ b/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -38,36 +38,40 @@ class OverriddenOperationDummy * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; + /** * @var string The dummy name * * @ODM\Field - * @Assert\NotBlank - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_write", "overridden_operation_dummy_get"}) - * @ApiProperty(iri="http://schema.org/name") */ + #[Assert\NotBlank] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get'])] + #[ApiProperty(types: ['http://schema.org/name'])] private $name; + /** * @var string The dummy name alias * * @ODM\Field(nullable=true) - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_put", "overridden_operation_dummy_get"}) - * @ApiProperty(iri="https://schema.org/alternateName") */ + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_put', 'overridden_operation_dummy_get'])] private $alias; + /** * @var string A short description of the item * * @ODM\Field(nullable=true) - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_write", "overridden_operation_dummy_get", "overridden_operation_dummy_put"}) - * @ApiProperty(iri="https://schema.org/description") */ + #[ApiProperty(types: ['http://schema.org/description'])] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get', 'overridden_operation_dummy_put'])] public $description; + /** * @ODM\Field(nullable=true) - * @Groups({"overridden_operation_dummy_write"}) */ + #[Groups(['overridden_operation_dummy_write'])] public $notGettable; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ParentDummy.php b/tests/Fixtures/TestBundle/Document/ParentDummy.php index 8ed02ecba9c..a6f86f296fd 100644 --- a/tests/Fixtures/TestBundle/Document/ParentDummy.php +++ b/tests/Fixtures/TestBundle/Document/ParentDummy.php @@ -30,8 +30,8 @@ class ParentDummy * @var int The age * * @ODM\Field(type="int", nullable=true) - * @Groups({"friends"}) */ + #[Groups(['friends'])] private $age; public function getAge() diff --git a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php index 976b2d213d2..148369a30d9 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php @@ -34,8 +34,8 @@ class PatchDummyRelation public $id; /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class) - * @Groups({"chicago"}) */ + #[Groups(['chicago'])] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Document/Payment.php b/tests/Fixtures/TestBundle/Document/Payment.php index ca39349a066..01274b2536a 100644 --- a/tests/Fixtures/TestBundle/Document/Payment.php +++ b/tests/Fixtures/TestBundle/Document/Payment.php @@ -27,23 +27,16 @@ class Payment { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - /** - * @var string|null - */ - private $amount; + private ?int $id = null; /** * @ODM\ReferenceOne(targetDocument=VoidPayment::class, mappedBy="payment") */ private $voidPayment; - public function __construct(string $amount) + public function __construct(private readonly ?string $amount) { - $this->amount = $amount; } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/Person.php b/tests/Fixtures/TestBundle/Document/Person.php index e40ae4ffdec..707b50d18a0 100644 --- a/tests/Fixtures/TestBundle/Document/Person.php +++ b/tests/Fixtures/TestBundle/Document/Person.php @@ -33,15 +33,15 @@ class Person private $id; /** * @ODM\Field(type="string") - * @Groups({"people.pets"}) */ + #[Groups(['people.pets'])] public $name; /** * @ODM\ReferenceMany(targetDocument=PersonToPet::class, mappedBy="person") - * @Groups({"people.pets"}) * * @var ArrayCollection */ + #[Groups(['people.pets'])] public $pets; /** * @ODM\ReferenceMany(targetDocument=Greeting::class, mappedBy="sender") diff --git a/tests/Fixtures/TestBundle/Document/PersonToPet.php b/tests/Fixtures/TestBundle/Document/PersonToPet.php index 9e7cc7490cf..47733105272 100644 --- a/tests/Fixtures/TestBundle/Document/PersonToPet.php +++ b/tests/Fixtures/TestBundle/Document/PersonToPet.php @@ -31,10 +31,10 @@ class PersonToPet /** * @ODM\ReferenceOne(targetDocument=Pet::class) - * @Groups({"people.pets"}) * * @var Pet */ + #[Groups(['people.pets'])] public $pet; /** diff --git a/tests/Fixtures/TestBundle/Document/Pet.php b/tests/Fixtures/TestBundle/Document/Pet.php index ef9fdf5c125..5a23178a475 100644 --- a/tests/Fixtures/TestBundle/Document/Pet.php +++ b/tests/Fixtures/TestBundle/Document/Pet.php @@ -33,8 +33,8 @@ class Pet private $id; /** * @ODM\Field(type="string") - * @Groups({"people.pets"}) */ + #[Groups(['people.pets'])] public $name; /** * @ODM\ReferenceMany(targetDocument=PersonToPet::class, mappedBy="pet") diff --git a/tests/Fixtures/TestBundle/Document/ProcessorEntity.php b/tests/Fixtures/TestBundle/Document/ProcessorEntity.php index 4b56e753d6c..ed2d461cd2e 100644 --- a/tests/Fixtures/TestBundle/Document/ProcessorEntity.php +++ b/tests/Fixtures/TestBundle/Document/ProcessorEntity.php @@ -30,19 +30,15 @@ class ProcessorEntity { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string - * * @ODM\Field - * @Assert\NotBlank */ - private $foo; + #[Assert\NotBlank] + private ?string $foo = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Document/Product.php b/tests/Fixtures/TestBundle/Document/Product.php index d242787b045..bc7cc51651f 100644 --- a/tests/Fixtures/TestBundle/Document/Product.php +++ b/tests/Fixtures/TestBundle/Document/Product.php @@ -23,25 +23,19 @@ class Product implements ProductInterface { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string|null - * * @ODM\Field(type="string") */ - private $code; + private ?string $code = null; /** - * @var Taxon|null - * * @ODM\ReferenceOne(targetDocument=Taxon::class) */ - private $mainTaxon; + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Taxon $mainTaxon = null; /** * {@inheritdoc} diff --git a/tests/Fixtures/TestBundle/Document/ProviderEntity.php b/tests/Fixtures/TestBundle/Document/ProviderEntity.php index bd4063fbf63..35c28c9b6ea 100644 --- a/tests/Fixtures/TestBundle/Document/ProviderEntity.php +++ b/tests/Fixtures/TestBundle/Document/ProviderEntity.php @@ -32,19 +32,15 @@ class ProviderEntity { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string - * * @ODM\Field - * @Assert\NotBlank */ - private $foo; + #[Assert\NotBlank] + private ?string $foo = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php b/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php index ffe89563e5b..6541deb09a9 100644 --- a/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php +++ b/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -28,14 +28,15 @@ class ReadableOnlyProperty * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; + /** * @var string The foo name * * @ODM\Field - * @ApiProperty(writable=false) */ - private $name; + #[ApiProperty(writable: false)] + private readonly string $name; public function __construct() { @@ -47,7 +48,7 @@ public function getId() return $this->id; } - public function setName($name) + public function setName($name): never { throw new \Exception('Can not write name.'); } diff --git a/tests/Fixtures/TestBundle/Document/RelatedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedDummy.php index 166e246a7b2..7d24fbfbdfb 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; @@ -44,54 +44,54 @@ class RelatedDummy extends ParentDummy { /** - * @ApiProperty(writable=false) * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"chicago", "friends"}) */ + #[Groups(['chicago', 'friends'])] + #[ApiProperty(writable: false)] private $id; /** * @var string A name * * @ODM\Field(type="string", nullable=true) - * @Groups({"friends"}) */ + #[Groups(['friends'])] public $name; /** * @ODM\Field(type="string") - * @Groups({"barcelona", "chicago", "friends"}) */ + #[Groups(['barcelona', 'chicago', 'friends'])] protected $symfony = 'symfony'; /** * @var \DateTime A dummy date * * @ODM\Field(type="date", nullable=true) - * @Assert\DateTime - * @Groups({"friends"}) */ + #[Assert\DateTime] + #[Groups(['friends'])] public $dummyDate; /** * @ODM\ReferenceOne(targetDocument=ThirdLevel::class, cascade={"persist"}, nullable=true, storeAs="id") - * @Groups({"barcelona", "chicago", "friends"}) */ + #[Groups(['barcelona', 'chicago', 'friends'])] public $thirdLevel; /** * @ODM\ReferenceMany(targetDocument=RelatedToDummyFriend::class, cascade={"persist"}, mappedBy="relatedDummy", storeAs="id") - * @Groups({"fakemanytomany", "friends"}) */ + #[Groups(['fakemanytomany', 'friends'])] public $relatedToDummyFriend; /** * @var bool A dummy bool * * @ODM\Field(type="bool") - * @Groups({"friends"}) */ + #[Groups(['friends'])] public $dummyBoolean; /** * @var EmbeddableDummy * * @ODM\EmbedOne(targetDocument=EmbeddableDummy::class) - * @Groups({"friends"}) */ + #[Groups(['friends'])] public $embeddedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php index 6c43ab84734..95043bdb915 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -34,24 +34,25 @@ class RelatedNormalizedDummy * @var int|null The id * * @ODM\Id(strategy="INCREMENT", type="int") - * @Groups({"related_output", "related_input"}) */ - private $id; + #[Groups(['related_output', 'related_input'])] + private ?int $id = null; /** * @var string|null The dummy name * * @ODM\Field - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"related_output", "related_input"}) */ - private $name; + #[Assert\NotBlank] + #[ApiProperty(types: ['http://schema.org/name'])] + #[Groups(['related_output', 'related_input'])] + private ?string $name = null; + /** * @var iterable Several Normalized dummies * * @ODM\ReferenceMany(targetDocument=CustomNormalizedDummy::class) - * @Groups({"related_output", "related_input"}) */ + #[Groups(['related_output', 'related_input'])] public $customNormalizedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php b/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php index 21b62391da6..8ca0284f410 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php +++ b/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Link; @@ -42,28 +42,28 @@ class RelatedToDummyFriend * @var string The dummy name * * @ODM\Field(type="string") - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"fakemanytomany", "friends"}) */ + #[Assert\NotBlank] + #[ApiProperty(types: ['http://schema.org/name'])] + #[Groups(['fakemanytomany', 'friends'])] private $name; /** * @var string|null The dummy description * * @ODM\Field(type="string") - * @Groups({"fakemanytomany", "friends"}) */ - private $description; + #[Groups(['fakemanytomany', 'friends'])] + private ?string $description = null; /** * @ODM\ReferenceOne(targetDocument=DummyFriend::class, storeAs="id") - * @Groups({"fakemanytomany", "friends"}) - * @Assert\NotNull */ + #[Groups(['fakemanytomany', 'friends'])] + #[Assert\NotNull] private $dummyFriend; /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, inversedBy="relatedToDummyFriend", storeAs="id") - * @Assert\NotNull */ + #[Assert\NotNull] private $relatedDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/RelationEmbedder.php b/tests/Fixtures/TestBundle/Document/RelationEmbedder.php index e85af880c73..8220e596f4d 100644 --- a/tests/Fixtures/TestBundle/Document/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Document/RelationEmbedder.php @@ -37,23 +37,23 @@ class RelationEmbedder public $id; /** * @ODM\Field - * @Groups({"chicago"}) */ + #[Groups(['chicago'])] public $paris = 'Paris'; /** * @ODM\Field - * @Groups({"barcelona", "chicago"}) */ + #[Groups(['barcelona', 'chicago'])] public $krondstadt = 'Krondstadt'; /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, cascade={"persist"}) - * @Groups({"chicago", "barcelona"}) */ + #[Groups(['chicago', 'barcelona'])] public $anotherRelated; /** * @ODM\ReferenceOne(targetDocument=RelatedDummy::class) - * @Groups({"barcelona", "chicago"}) */ + #[Groups(['barcelona', 'chicago'])] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php b/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php index f90bb02fd32..d30e0561579 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php @@ -27,13 +27,11 @@ class ResourceWithBoolean * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var bool - * * @ODM\Field(type="bool") */ - private $myBooleanField = false; + private bool $myBooleanField = false; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php b/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php index 520008f1692..4ce1c0e0428 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php @@ -27,13 +27,11 @@ class ResourceWithFloat * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var float - * * @ODM\Field(type="float") */ - private $myFloatField = 0.0; + private float $myFloatField = 0.0; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php b/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php index b95bb3ca689..cd8c0ce3dd6 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php @@ -27,13 +27,11 @@ class ResourceWithInteger * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var int - * * @ODM\Field(type="int") */ - private $myIntegerField = 0; + private int $myIntegerField = 0; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithString.php b/tests/Fixtures/TestBundle/Document/ResourceWithString.php index d79c4a13114..902c6afd786 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithString.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithString.php @@ -27,13 +27,11 @@ class ResourceWithString * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string - * * @ODM\Field(type="string") */ - private $myStringField = ''; + private string $myStringField = ''; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/SecuredDummy.php b/tests/Fixtures/TestBundle/Document/SecuredDummy.php index d7e3e492e34..ba6d67d6506 100644 --- a/tests/Fixtures/TestBundle/Document/SecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/SecuredDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; @@ -38,79 +38,83 @@ class SecuredDummy { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; + /** * @var string|null The title * * @ODM\Field - * @Assert\NotBlank */ - private $title; + #[Assert\NotBlank] + private ?string $title = null; + /** * @var string The description * * @ODM\Field */ - private $description = ''; + private string $description = ''; + /** * @var string The dummy secret property, only readable/writable by specific users * * @ODM\Field - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ - private $adminOnlyProperty = ''; + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + private ?string $adminOnlyProperty = ''; + /** * @var string Secret property, only readable/writable by owners * * @ODM\Field - * @ApiProperty( - * security="object == null or object.getOwner() == user", - * securityPostDenormalize="object.getOwner() == user", - * ) */ - private $ownerOnlyProperty = ''; + #[ApiProperty(security: 'object == null or object.getOwner() == user', securityPostDenormalize: 'object.getOwner() == user')] + private ?string $ownerOnlyProperty = ''; + /** * @var string|null The owner * * @ODM\Field - * @Assert\NotBlank */ - private $owner; + #[Assert\NotBlank] + private ?string $owner = null; + /** * @var Collection Several dummies * * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] public $relatedDummies; + /** * @var RelatedDummy * * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] protected $relatedDummy; + /** * A collection of dummies that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies * * @ODM\ReferenceMany(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) - * @ApiProperty(security="is_granted('ROLE_USER')") */ + #[ApiProperty(security: "is_granted('ROLE_USER')")] public $relatedSecuredDummies; + /** * A dummy that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy * * @ODM\ReferenceOne(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) - * @ApiProperty(security="is_granted('ROLE_USER')") */ + #[ApiProperty(security: "is_granted('ROLE_USER')")] protected $relatedSecuredDummy; /** * Collection of dummies that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. diff --git a/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php b/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php index 5e74998802d..914446960cd 100644 --- a/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php @@ -27,7 +27,7 @@ class SingleFileConfigDummy * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** * @var string The dummy name diff --git a/tests/Fixtures/TestBundle/Document/SlugChildDummy.php b/tests/Fixtures/TestBundle/Document/SlugChildDummy.php index 5124a07b852..c5b4dfd058b 100644 --- a/tests/Fixtures/TestBundle/Document/SlugChildDummy.php +++ b/tests/Fixtures/TestBundle/Document/SlugChildDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Link; @@ -30,19 +30,19 @@ class SlugChildDummy /** * @var int The identifier * - * @ApiProperty(identifier=false) - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ApiProperty(identifier: false)] + private ?int $id = null; + /** * @var string The slug used as API identifier * - * @ApiProperty(identifier=true) - * * @ODM\Field */ - private $slug; + #[ApiProperty(identifier: true)] + private ?string $slug = null; + /** * @ODM\ReferenceOne(targetDocument=SlugParentDummy::class, inversedBy="childDummies", storeAs="id") */ diff --git a/tests/Fixtures/TestBundle/Document/SlugParentDummy.php b/tests/Fixtures/TestBundle/Document/SlugParentDummy.php index cb475db3f04..b6e093a2ecc 100644 --- a/tests/Fixtures/TestBundle/Document/SlugParentDummy.php +++ b/tests/Fixtures/TestBundle/Document/SlugParentDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; @@ -34,25 +34,25 @@ class SlugParentDummy /** * @var int|null The database identifier * - * @ApiProperty(identifier=false) - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + #[ApiProperty(identifier: false)] + private ?int $id = null; + /** * @var string|null The slug used a API identifier * - * @ApiProperty(identifier=true) - * * @ODM\Field */ - private $slug; + #[ApiProperty(identifier: true)] + private ?string $slug = null; + /** * @ODM\ReferenceMany(targetDocument=SlugChildDummy::class, mappedBy="parentDummy") * * @var \Collection */ - private $childDummies; + private \Collection $childDummies; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Document/Taxon.php b/tests/Fixtures/TestBundle/Document/Taxon.php index 501905d3f92..c3e491cd3ff 100644 --- a/tests/Fixtures/TestBundle/Document/Taxon.php +++ b/tests/Fixtures/TestBundle/Document/Taxon.php @@ -22,18 +22,14 @@ class Taxon implements TaxonInterface { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var string|null - * * @ODM\Field(type="string") */ - private $code; + private ?string $code = null; /** * {@inheritdoc} diff --git a/tests/Fixtures/TestBundle/Document/ThirdLevel.php b/tests/Fixtures/TestBundle/Document/ThirdLevel.php index 8b044829388..bd118b0b8cd 100644 --- a/tests/Fixtures/TestBundle/Document/ThirdLevel.php +++ b/tests/Fixtures/TestBundle/Document/ThirdLevel.php @@ -39,24 +39,20 @@ class ThirdLevel * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; + private ?int $id = null; /** - * @var int - * * @ODM\Field(type="int") - * @Groups({"barcelona", "chicago"}) */ - private $level = 3; + #[Groups(['barcelona', 'chicago'])] + private int $level = 3; /** - * @var bool - * * @ODM\Field(type="bool") */ - private $test = true; + private bool $test = true; /** * @ODM\ReferenceOne(targetDocument=FourthLevel::class, cascade={"persist"}, storeAs="id") - * @Groups({"barcelona", "chicago", "friends"}) */ + #[Groups(['barcelona', 'chicago', 'friends'])] public $fourthLevel; /** * @ODM\ReferenceOne(targetDocument=FourthLevel::class, cascade={"persist"}) diff --git a/tests/Fixtures/TestBundle/Document/UrlEncodedId.php b/tests/Fixtures/TestBundle/Document/UrlEncodedId.php index 7d5e3978159..c1f9227db5a 100644 --- a/tests/Fixtures/TestBundle/Document/UrlEncodedId.php +++ b/tests/Fixtures/TestBundle/Document/UrlEncodedId.php @@ -31,7 +31,7 @@ class UrlEncodedId /** * @ODM\Id(strategy="none") */ - private $id = '%encode:id'; + private string $id = '%encode:id'; public function getId() { diff --git a/tests/Fixtures/TestBundle/Document/User.php b/tests/Fixtures/TestBundle/Document/User.php index 60762a38bb1..c1781d0f0e0 100644 --- a/tests/Fixtures/TestBundle/Document/User.php +++ b/tests/Fixtures/TestBundle/Document/User.php @@ -46,28 +46,25 @@ class User extends AbstractSecurityUser protected $id; /** * @var string|null - * - * @Groups({"user"}) */ + #[Groups(['user'])] protected $email; /** * @var string|null * * @ODM\Field(type="string", nullable=true) - * @Groups({"user"}) */ + #[Groups(['user'])] protected $fullname; /** * @var string|null - * - * @Groups({"user-write"}) */ + #[Groups(['user-write'])] protected $plainPassword; /** * @var string|null - * - * @Groups({"user"}) */ + #[Groups(['user'])] protected $username; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php index 2a9ba896ea9..c68feacc570 100644 --- a/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php @@ -29,13 +29,13 @@ class UuidIdentifierDummy * * @ODM\Id(strategy="UUID") */ - private $uuid; + private ?string $uuid = null; /** * @var string The dummy name * * @ODM\Field */ - private $name; + private ?string $name = null; public function getUuid(): string { diff --git a/tests/Fixtures/TestBundle/Document/VoDummyCar.php b/tests/Fixtures/TestBundle/Document/VoDummyCar.php index d3c247fe350..a42225eba33 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyCar.php @@ -25,33 +25,23 @@ #[ApiResource(normalizationContext: ['groups' => ['car_read']], denormalizationContext: ['groups' => ['car_write']])] class VoDummyCar extends VoDummyVehicle { - /** - * @var int - * - * @ODM\Field(type="int") - * @Groups({"car_read", "car_write"}) - */ - private $mileage; - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $bodyType; /** * @var VoDummyInspection[]|Collection * * @ODM\ReferenceMany(targetDocument=VoDummyInspection::class, mappedBy="car", cascade={"persist"}) - * @Groups({"car_read", "car_write"}) */ - private $inspections; + #[Groups(['car_read', 'car_write'])] + private readonly array|\Doctrine\Common\Collections\Collection $inspections; - public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, int $mileage, string $bodyType = 'coupe') + public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, /** + * @ODM\Field(type="int") + */ + #[Groups(['car_read', 'car_write'])] private readonly int $mileage, /** + * @ODM\Field + */ + #[Groups(['car_read', 'car_write'])] private readonly string $bodyType = 'coupe') { parent::__construct($make, $insuranceCompany, $drivers); - $this->mileage = $mileage; - $this->bodyType = $bodyType; $this->inspections = new ArrayCollection(); } diff --git a/tests/Fixtures/TestBundle/Document/VoDummyDriver.php b/tests/Fixtures/TestBundle/Document/VoDummyDriver.php index 53fcce13e9a..441382771b2 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyDriver.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyDriver.php @@ -24,25 +24,17 @@ class VoDummyDriver { use VoDummyIdAwareTrait; - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $firstName; - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $lastName; - - public function __construct(string $firstName, string $lastName) - { - $this->firstName = $firstName; - $this->lastName = $lastName; + + public function __construct( + /** + * @ODM\Field + */ + #[Groups(['car_read', 'car_write'])] private readonly string $firstName, + /** + * @ODM\Field + */ + #[Groups(['car_read', 'car_write'])] private readonly string $lastName + ) { } public function getFirstName() diff --git a/tests/Fixtures/TestBundle/Document/VoDummyInspection.php b/tests/Fixtures/TestBundle/Document/VoDummyInspection.php index 4cf835d8e43..49572bf6c22 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyInspection.php @@ -26,34 +26,20 @@ class VoDummyInspection { use VoDummyIdAwareTrait; /** - * @var bool - * + * @ODM\Field(type="date") + */ + #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] + private \DateTime $performed; + + public function __construct(/** * @ODM\Field(type="bool") - * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) */ - private $accepted; - /** - * @var VoDummyCar - * + #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private readonly bool $accepted, /** * @ODM\ReferenceOne(targetDocument=VoDummyCar::class, inversedBy="inspections") - * @Groups({"inspection_read", "inspection_write"}) */ - private $car; - /** - * @var DateTime - * - * @ODM\Field(type="date") - * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) - */ - private $performed; - private $attributeWithoutConstructorEquivalent; - - public function __construct(bool $accepted, VoDummyCar $car, DateTime $performed = null, string $parameterWhichIsNotClassAttribute = '') + #[Groups(['inspection_read', 'inspection_write'])] private readonly VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') { - $this->accepted = $accepted; - $this->car = $car; $this->performed = $performed ?: new DateTime(); - $this->attributeWithoutConstructorEquivalent = $parameterWhichIsNotClassAttribute; } public function isAccepted() diff --git a/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php b/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php index 0adc3acaa36..22474225ef2 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php @@ -24,17 +24,13 @@ class VoDummyInsuranceCompany { use VoDummyIdAwareTrait; - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $name; - public function __construct(string $name) - { - $this->name = $name; + public function __construct( + /** + * @ODM\Field + */ + #[Groups(['car_read', 'car_write'])] private readonly string $name + ) { } public function getName() diff --git a/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php b/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php index e686c14b8bf..33c8fd1bc69 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php @@ -24,38 +24,25 @@ abstract class VoDummyVehicle { use VoDummyIdAwareTrait; - - /** - * @var string - * - * @ODM\Field - * @Groups({"car_read", "car_write"}) - */ - private $make; - - /** - * @var VoDummyInsuranceCompany - * - * @ODM\ReferenceOne(targetDocument=VoDummyInsuranceCompany::class, cascade={"persist"}) - * @Groups({"car_read", "car_write"}) - */ - private $insuranceCompany; - /** * @var VoDummyDriver[]|Collection * * @ODM\ReferenceMany(targetDocument=VoDummyDriver::class, cascade={"persist"}) - * @Groups({"car_read", "car_write"}) */ - private $drivers; + #[Groups(['car_read', 'car_write'])] + private readonly array|\Doctrine\Common\Collections\Collection $drivers; public function __construct( - string $make, - VoDummyInsuranceCompany $insuranceCompany, + /** + * @ODM\Field + */ + #[Groups(['car_read', 'car_write'])] private readonly string $make, + /** + * @ODM\ReferenceOne(targetDocument=VoDummyInsuranceCompany::class, cascade={"persist"}) + */ + #[Groups(['car_read', 'car_write'])] private readonly VoDummyInsuranceCompany $insuranceCompany, array $drivers ) { - $this->make = $make; - $this->insuranceCompany = $insuranceCompany; $this->drivers = new ArrayCollection($drivers); } diff --git a/tests/Fixtures/TestBundle/Document/VoidPayment.php b/tests/Fixtures/TestBundle/Document/VoidPayment.php index d8b9fb08979..6598bcccf67 100644 --- a/tests/Fixtures/TestBundle/Document/VoidPayment.php +++ b/tests/Fixtures/TestBundle/Document/VoidPayment.php @@ -23,19 +23,16 @@ class VoidPayment { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int") */ - private $id; - /** - * @ODM\ReferenceOne(targetDocument=Payment::class, inversedBy="voidPayment") - */ - private $payment; - - public function __construct(Payment $payment) - { - $this->payment = $payment; + private ?int $id = null; + + public function __construct( + /** + * @ODM\ReferenceOne(targetDocument=Payment::class, inversedBy="voidPayment") + */ + private readonly Payment $payment + ) { } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php index 393fbc4b7d7..492e5cb569c 100644 --- a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php +++ b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php @@ -23,11 +23,9 @@ class WithJsonDummy { /** - * @var int|null - * * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ - private $id; + private ?int $id = null; /** * @var array|null * diff --git a/tests/Fixtures/TestBundle/Document/WritableId.php b/tests/Fixtures/TestBundle/Document/WritableId.php index 450670caf4f..12e5ab24dfa 100644 --- a/tests/Fixtures/TestBundle/Document/WritableId.php +++ b/tests/Fixtures/TestBundle/Document/WritableId.php @@ -26,8 +26,8 @@ class WritableId { /** * @ODM\Id(strategy="UUID", type="string") - * @Assert\Uuid */ + #[Assert\Uuid] public $id; /** * @ODM\Field diff --git a/tests/Fixtures/TestBundle/Dto/NonResourceClass.php b/tests/Fixtures/TestBundle/Dto/NonResourceClass.php index 6acb6723490..f58bc080337 100644 --- a/tests/Fixtures/TestBundle/Dto/NonResourceClass.php +++ b/tests/Fixtures/TestBundle/Dto/NonResourceClass.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Dto; -class NonResourceClass +class NonResourceClass implements \Stringable { /** * @var string */ public $foo; - public function __toString() + public function __toString(): string { return $this->foo; } diff --git a/tests/Fixtures/TestBundle/Dto/PasswordResetRequest.php b/tests/Fixtures/TestBundle/Dto/PasswordResetRequest.php index df002e7e19a..5aabbac378d 100644 --- a/tests/Fixtures/TestBundle/Dto/PasswordResetRequest.php +++ b/tests/Fixtures/TestBundle/Dto/PasswordResetRequest.php @@ -17,14 +17,8 @@ final class PasswordResetRequest { - /** - * @Groups({"user_password_reset_request"}) - */ - private $email; - - public function __construct(string $email = '') + public function __construct(#[Groups(['user_password_reset_request'])] private readonly string $email = '') { - $this->email = $email; } public function getEmail(): string diff --git a/tests/Fixtures/TestBundle/Dto/PasswordResetRequestResult.php b/tests/Fixtures/TestBundle/Dto/PasswordResetRequestResult.php index 8f38f6a8221..97c37ce8b74 100644 --- a/tests/Fixtures/TestBundle/Dto/PasswordResetRequestResult.php +++ b/tests/Fixtures/TestBundle/Dto/PasswordResetRequestResult.php @@ -17,14 +17,8 @@ final class PasswordResetRequestResult { - /** - * @Groups({"user_password_reset_request"}) - */ - private $emailSentAt; - - public function __construct(\DateTimeInterface $emailSentAt) + public function __construct(#[Groups(['user_password_reset_request'])] private readonly \DateTimeInterface $emailSentAt) { - $this->emailSentAt = $emailSentAt; } public function getEmailSentAt(): \DateTimeInterface diff --git a/tests/Fixtures/TestBundle/Dto/RecoverPasswordInput.php b/tests/Fixtures/TestBundle/Dto/RecoverPasswordInput.php index e6ab58dffa1..cc3d2707d1f 100644 --- a/tests/Fixtures/TestBundle/Dto/RecoverPasswordInput.php +++ b/tests/Fixtures/TestBundle/Dto/RecoverPasswordInput.php @@ -19,7 +19,7 @@ class RecoverPasswordInput { /** * @var \ApiPlatform\Tests\Fixtures\TestBundle\Entity\User - * @Groups({"user"}) */ + #[Groups(['user'])] public $user; } diff --git a/tests/Fixtures/TestBundle/Dto/RecoverPasswordOutput.php b/tests/Fixtures/TestBundle/Dto/RecoverPasswordOutput.php index ef7e78488c7..b152c3b0564 100644 --- a/tests/Fixtures/TestBundle/Dto/RecoverPasswordOutput.php +++ b/tests/Fixtures/TestBundle/Dto/RecoverPasswordOutput.php @@ -19,7 +19,7 @@ class RecoverPasswordOutput { /** * @var \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy - * @Groups({"user"}) */ + #[Groups(['user'])] public $dummy; } diff --git a/tests/Fixtures/TestBundle/Dto/UserResetPasswordDto.php b/tests/Fixtures/TestBundle/Dto/UserResetPasswordDto.php index f8a85e11bb5..119d55b69c2 100644 --- a/tests/Fixtures/TestBundle/Dto/UserResetPasswordDto.php +++ b/tests/Fixtures/TestBundle/Dto/UserResetPasswordDto.php @@ -17,8 +17,6 @@ final class UserResetPasswordDto { - /** - * @Assert\Email - */ + #[Assert\Email] public $email; } diff --git a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php index 8104f04be7a..7e77c5a4885 100644 --- a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php @@ -19,22 +19,16 @@ use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] #[ApiResource(uriTemplate: '/absolute_url_relation_dummies/{id}/absolute_url_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\AbsoluteUrlRelationDummy::class, identifiers: ['id'], toProperty: 'absoluteUrlRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::ABS_URL, operations: [new GetCollection()])] +#[ORM\Entity] class AbsoluteUrlDummy { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** - * @ORM\ManyToOne(targetEntity="AbsoluteUrlRelationDummy", inversedBy="absoluteUrlDummies") - */ + #[ORM\ManyToOne(targetEntity: 'AbsoluteUrlRelationDummy', inversedBy: 'absoluteUrlDummies')] public $absoluteUrlRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php index b9a6447317c..325d559018f 100644 --- a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php @@ -18,21 +18,15 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] +#[ORM\Entity] class AbsoluteUrlRelationDummy { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** - * @ORM\OneToMany(targetEntity="AbsoluteUrlDummy", mappedBy="absoluteUrlRelationDummy") - */ + #[ORM\OneToMany(targetEntity: 'AbsoluteUrlDummy', mappedBy: 'absoluteUrlRelationDummy')] public $absoluteUrlDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/AbstractDummy.php b/tests/Fixtures/TestBundle/Entity/AbstractDummy.php index 9fe16ed35a3..0badb81e2ca 100644 --- a/tests/Fixtures/TestBundle/Entity/AbstractDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbstractDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -27,29 +27,28 @@ * Abstract Dummy. * * @author Jérémy Derussé - * @ORM\Entity - * @ORM\InheritanceType ("SINGLE_TABLE") - * @ORM\DiscriminatorColumn (name="discr", type="string", length=16) - * @ORM\DiscriminatorMap ({"concrete"="ConcreteDummy"}) */ #[ApiResource(operations: [new Get(), new Put(), new Delete(), new GetCollection(), new Post()], filters: ['my_dummy.search', 'my_dummy.order', 'my_dummy.date'])] +#[ORM\Entity] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'discr', type: 'string', length: 16)] +#[ORM\DiscriminatorMap(['concrete' => 'ConcreteDummy'])] abstract class AbstractDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AbstractUser.php b/tests/Fixtures/TestBundle/Entity/AbstractUser.php index 76ed5795795..ff0c7571c97 100644 --- a/tests/Fixtures/TestBundle/Entity/AbstractUser.php +++ b/tests/Fixtures/TestBundle/Entity/AbstractUser.php @@ -18,30 +18,20 @@ use ApiPlatform\Metadata\GetCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - * @ORM\InheritanceType ("JOINED") - */ #[ApiResource(operations: [new Get(uriTemplate: '/custom_users/{id}'), new GetCollection(uriTemplate: '/custom_users')])] +#[ORM\Entity] +#[ORM\InheritanceType('JOINED')] abstract class AbstractUser { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column - */ + #[ORM\Column] private $firstname; - /** - * @ORM\Column - */ + #[ORM\Column] private $lastname; - /** - * @ORM\Column - */ + #[ORM\Column] private $email; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/Address.php b/tests/Fixtures/TestBundle/Entity/Address.php index 6638c8f97e8..2b966107e09 100644 --- a/tests/Fixtures/TestBundle/Entity/Address.php +++ b/tests/Fixtures/TestBundle/Entity/Address.php @@ -17,25 +17,17 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class Address { - /** - * @var int - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"order_read"}) - */ - private $id; - /** - * @ORM\Column(type="string") - * @Groups({"order_read"}) - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['order_read'])] + private ?int $id = null; + #[ORM\Column(type: 'string')] + #[Groups(['order_read'])] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AlternateResource.php b/tests/Fixtures/TestBundle/Entity/AlternateResource.php index 95961030a7d..c7db685f8ab 100644 --- a/tests/Fixtures/TestBundle/Entity/AlternateResource.php +++ b/tests/Fixtures/TestBundle/Entity/AlternateResource.php @@ -21,12 +21,8 @@ #[Get('/alternate/{id}', uriVariables: ['id' => ['from_class' => AlternateResource::class, 'identifiers' => ['id']]])] final class AlternateResource { - #[ApiProperty(identifier: true)] - public string $id; - - public function __construct(string $id) + public function __construct(#[ApiProperty(identifier: true)] public string $id) { - $this->id = $id; } public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Answer.php b/tests/Fixtures/TestBundle/Entity/Answer.php index 9903f6abb9f..794abea9866 100644 --- a/tests/Fixtures/TestBundle/Entity/Answer.php +++ b/tests/Fixtures/TestBundle/Entity/Answer.php @@ -27,37 +27,30 @@ /** * Answer. - * - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(normalizationContext: ['groups' => ['foobar']])])] #[ApiResource(uriTemplate: '/answers/{id}/related_questions/{relatedQuestions}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], toProperty: 'answer'), 'relatedQuestions' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/questions/{id}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] +#[ORM\Entity] class Answer { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Serializer\Groups({"foobar"}) - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Serializer\Groups(['foobar'])] private $id; - /** - * @ORM\Column(nullable=false) - * @Serializer\Groups({"foobar"}) - */ + #[ORM\Column(nullable: false)] + #[Serializer\Groups(['foobar'])] private $content; - /** - * @ORM\OneToOne(targetEntity="Question", mappedBy="answer") - * @Serializer\Groups({"foobar"}) - */ + #[ORM\OneToOne(targetEntity: 'Question', mappedBy: 'answer')] + #[Serializer\Groups(['foobar'])] private $question; /** * @var \Collection - * @ORM\OneToMany(targetEntity="Question", mappedBy="answer") - * @Serializer\Groups({"foobar"}) */ - private $relatedQuestions; + #[ORM\OneToMany(targetEntity: 'Question', mappedBy: 'answer')] + #[Serializer\Groups(['foobar'])] + private readonly \Collection $relatedQuestions; public function __construct() { @@ -94,8 +87,6 @@ public function getContent(): ?string /** * Set question. - * - * @param Question $question */ public function setQuestion(Question $question = null): self { diff --git a/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php b/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php index 3e576798ec4..717a576017d 100644 --- a/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php +++ b/tests/Fixtures/TestBundle/Entity/ArrayFilterValidator.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayRequiredFilter; use Doctrine\ORM\Mapping as ORM; @@ -22,25 +22,24 @@ * Filter Validator entity. * * @author Julien Deniau - * @ORM\Entity */ #[ApiResource(filters: [ArrayRequiredFilter::class])] +#[ORM\Entity] class ArrayFilterValidator { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + /** * @var string A name - * - * @ORM\Column - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php b/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php index f4ea98bb512..ef54ab11855 100644 --- a/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php +++ b/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php @@ -19,14 +19,8 @@ #[ApiResource(paginationItemsPerPage: 10, graphQlOperations: [])] final class AttributeDefaultOperations { - #[ApiProperty(identifier: true)] - private $identifier; - private $name; - - public function __construct(int $identifier, string $name) + public function __construct(#[ApiProperty(identifier: true)] private readonly int $identifier, private readonly string $name) { - $this->identifier = $identifier; - $this->name = $name; } public function getIdentifier() diff --git a/tests/Fixtures/TestBundle/Entity/AttributeResource.php b/tests/Fixtures/TestBundle/Entity/AttributeResource.php index ca4f003a1cd..50f355d72cc 100644 --- a/tests/Fixtures/TestBundle/Entity/AttributeResource.php +++ b/tests/Fixtures/TestBundle/Entity/AttributeResource.php @@ -41,24 +41,14 @@ #[Patch] final class AttributeResource { - #[ApiProperty(identifier: true)] - private $identifier; - /** * @var ?Dummy */ #[Link('dummyId')] public $dummy = null; - /** - * @var string - */ - public $name; - - public function __construct(int $identifier, string $name) + public function __construct(#[ApiProperty(identifier: true)] private readonly int $identifier, public string $name) { - $this->identifier = $identifier; - $this->name = $name; } public function getIdentifier() diff --git a/tests/Fixtures/TestBundle/Entity/AttributeResources.php b/tests/Fixtures/TestBundle/Entity/AttributeResources.php index 235a99dc7bf..44ba83f2037 100644 --- a/tests/Fixtures/TestBundle/Entity/AttributeResources.php +++ b/tests/Fixtures/TestBundle/Entity/AttributeResources.php @@ -33,7 +33,7 @@ final class AttributeResources implements IteratorAggregate /** * @var AttributeResource[] */ - private $collection; + private readonly array $collection; public function __construct(AttributeResource ...$collection) { diff --git a/tests/Fixtures/TestBundle/Entity/Book.php b/tests/Fixtures/TestBundle/Entity/Book.php index dcce5c39915..45a30eb6807 100644 --- a/tests/Fixtures/TestBundle/Entity/Book.php +++ b/tests/Fixtures/TestBundle/Entity/Book.php @@ -21,24 +21,18 @@ * Book. * * @author Antoine Bluchet - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Get(uriTemplate: '/books/by_isbn/{isbn}.{_format}', requirements: ['isbn' => '.+'], uriVariables: 'isbn')])] +#[ORM\Entity] class Book { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column - */ + #[ORM\Column] public $name; - /** - * @ORM\Column(unique=true) - */ + #[ORM\Column(unique: true)] public $isbn; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/CircularReference.php b/tests/Fixtures/TestBundle/Entity/CircularReference.php index 75374e97114..fd39438fa51 100644 --- a/tests/Fixtures/TestBundle/Entity/CircularReference.php +++ b/tests/Fixtures/TestBundle/Entity/CircularReference.php @@ -22,28 +22,20 @@ * Circular Reference. * * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource(normalizationContext: ['groups' => ['circular']])] +#[ORM\Entity] class CircularReference { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - /** - * @ORM\ManyToOne(targetEntity="CircularReference", inversedBy="children") - * - * @Groups({"circular"}) - */ + #[ORM\ManyToOne(targetEntity: 'CircularReference', inversedBy: 'children')] + #[Groups(['circular'])] public $parent; - /** - * @ORM\OneToMany(targetEntity="CircularReference", mappedBy="parent") - * - * @Groups({"circular"}) - */ + #[ORM\OneToMany(targetEntity: 'CircularReference', mappedBy: 'parent')] + #[Groups(['circular'])] public $children; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/Comment.php b/tests/Fixtures/TestBundle/Entity/Comment.php index 2b98e5401a8..6191eee1dd8 100644 --- a/tests/Fixtures/TestBundle/Entity/Comment.php +++ b/tests/Fixtures/TestBundle/Entity/Comment.php @@ -17,32 +17,20 @@ /** * @author Vincent Chalamon - * - * @ORM\Entity */ +#[ORM\Entity] class Comment { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column(type="text") - */ + #[ORM\Column(type: 'text')] public $comment; - - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: 'datetime')] public $date; - - /** - * @ORM\ManyToOne(targetEntity=User::class) - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] public $author; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Company.php b/tests/Fixtures/TestBundle/Entity/Company.php index 690797d4338..151349ab9c9 100644 --- a/tests/Fixtures/TestBundle/Entity/Company.php +++ b/tests/Fixtures/TestBundle/Entity/Company.php @@ -19,9 +19,6 @@ use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] #[Get] #[Post] @@ -38,22 +35,21 @@ 'employeeId' => ['from_class' => Employee::class, 'from_property' => 'company'], ], )] +#[ORM\Entity] class Company { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] public string $name; /** @var Employee[] */ diff --git a/tests/Fixtures/TestBundle/Entity/CompositeItem.php b/tests/Fixtures/TestBundle/Entity/CompositeItem.php index f20fc8b4849..b3c3a3acd54 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeItem.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeItem.php @@ -20,27 +20,20 @@ /** * Composite Item. - * - * @ORM\Entity */ #[ApiResource] -class CompositeItem +#[ORM\Entity] +class CompositeItem implements \Stringable { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column(type="string", nullable=true) - * @Groups({"default"}) - */ + #[ORM\Column(type: 'string', nullable: true)] + #[Groups(['default'])] private $field1; - /** - * @ORM\OneToMany(targetEntity="CompositeRelation", mappedBy="compositeItem", fetch="EAGER") - * @Groups({"default"}) - */ + #[ORM\OneToMany(targetEntity: 'CompositeRelation', mappedBy: 'compositeItem', fetch: 'EAGER')] + #[Groups(['default'])] private $compositeValues; /** diff --git a/tests/Fixtures/TestBundle/Entity/CompositeLabel.php b/tests/Fixtures/TestBundle/Entity/CompositeLabel.php index d4f55e7d5b0..3d8b9624241 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeLabel.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeLabel.php @@ -19,22 +19,17 @@ /** * Composite Label. - * - * @ORM\Entity */ #[ApiResource] -class CompositeLabel +#[ORM\Entity] +class CompositeLabel implements \Stringable { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column(type="string", nullable=true) - * @Groups({"default"}) - */ + #[ORM\Column(type: 'string', nullable: true)] + #[Groups(['default'])] private $value; /** diff --git a/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php b/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php index 56cea9e5271..7953ed24e09 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php +++ b/tests/Fixtures/TestBundle/Entity/CompositePrimitiveItem.php @@ -18,31 +18,16 @@ /** * Composite Primitive Item. - * - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class CompositePrimitiveItem { - /** - * @ORM\Id - * @ORM\Column(type="string") - */ - private $name; - /** - * @ORM\Id - * @ORM\Column(type="integer") - */ - private $year; - /** - * @ORM\Column(type="text") - */ + #[ORM\Column(type: 'text')] private $description; - public function __construct(string $name, int $year) + public function __construct(#[ORM\Id] #[ORM\Column(type: 'string')] private readonly string $name, #[ORM\Id] #[ORM\Column(type: 'integer')] private readonly int $year) { - $this->name = $name; - $this->year = $year; } /** diff --git a/tests/Fixtures/TestBundle/Entity/CompositeRelation.php b/tests/Fixtures/TestBundle/Entity/CompositeRelation.php index 170e168fc6c..986190d039f 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeRelation.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeRelation.php @@ -19,30 +19,23 @@ /** * Composite Relation. - * - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class CompositeRelation { - /** - * @ORM\Column(type="string", nullable=true) - * @Groups({"default"}) - */ + #[ORM\Column(type: 'string', nullable: true)] + #[Groups(['default'])] private $value; - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="CompositeItem", inversedBy="compositeValues") - * @ORM\JoinColumn(name="composite_item_id", referencedColumnName="id", nullable=false) - * @Groups({"default"}) - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'CompositeItem', inversedBy: 'compositeValues')] + #[ORM\JoinColumn(name: 'composite_item_id', referencedColumnName: 'id', nullable: false)] + #[Groups(['default'])] private $compositeItem; - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="CompositeLabel") - * @ORM\JoinColumn(name="composite_label_id", referencedColumnName="id", nullable=false) - * @Groups({"default"}) - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'CompositeLabel')] + #[ORM\JoinColumn(name: 'composite_label_id', referencedColumnName: 'id', nullable: false)] + #[Groups(['default'])] private $compositeLabel; /** diff --git a/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php b/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php index 2ea8695b5ed..9ed6cc11c03 100644 --- a/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php +++ b/tests/Fixtures/TestBundle/Entity/ConcreteDummy.php @@ -21,17 +21,16 @@ * Concrete Dummy. * * @author Jérémy Derusse - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class ConcreteDummy extends AbstractDummy { /** * @var string a concrete thing - * - * @ORM\Column - * @Assert\NotBlank */ + #[ORM\Column] + #[Assert\NotBlank] private $instance; public function setInstance($instance) diff --git a/tests/Fixtures/TestBundle/Entity/ContainNonResource.php b/tests/Fixtures/TestBundle/Entity/ContainNonResource.php index 6f6e8421ed3..b1d0236609f 100644 --- a/tests/Fixtures/TestBundle/Entity/ContainNonResource.php +++ b/tests/Fixtures/TestBundle/Entity/ContainNonResource.php @@ -21,31 +21,25 @@ /** * Resource linked to a standard object. * - * @ORM\Entity - * * @author Kévin Dunglas */ #[ApiResource(filters: ['my_dummy.property'], normalizationContext: ['groups' => ['contain_non_resource']])] +#[ORM\Entity] class ContainNonResource { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups("contain_non_resource") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups('contain_non_resource')] public $id; /** * @var ContainNonResource - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $nested; /** * @var NotAResource - * - * @Groups("contain_non_resource") */ + #[Groups('contain_non_resource')] public $notAResource; } diff --git a/tests/Fixtures/TestBundle/Entity/Content.php b/tests/Fixtures/TestBundle/Entity/Content.php index d385f5035c5..b4281249992 100644 --- a/tests/Fixtures/TestBundle/Entity/Content.php +++ b/tests/Fixtures/TestBundle/Entity/Content.php @@ -14,52 +14,30 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Get; use ApiPlatform\Tests\Fixtures\TestBundle\Enum\ContentStatus; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource(normalizationContext: ['groups' => ['get_content']])] +#[ORM\Entity] class Content implements \JsonSerializable { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var string - * - * @ORM\Column(type="string") - */ - private $contentType; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string')] + private ?string $contentType = null; /** * @var Collection - * - * @ORM\OneToMany( - * targetEntity=Field::class, - * mappedBy="content", - * cascade={"persist"}, - * orphanRemoval=true, - * indexBy="name", - * ) - * @ORM\OrderBy({"id"="ASC"}) */ - private $fields; - /** - * @var string - * - * @ORM\Column(type="string") - */ - private $status; + #[ORM\OneToMany(targetEntity: Field::class, mappedBy: 'content', cascade: ['persist'], orphanRemoval: true, indexBy: 'name')] + #[ORM\OrderBy(['id' => 'ASC'])] + private \Doctrine\Common\Collections\Collection & iterable $fields; + #[ORM\Column(type: 'string')] + private readonly string $status; public function __construct() { @@ -67,17 +45,13 @@ public function __construct() $this->status = ContentStatus::DRAFT; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getId(): ?int { return $this->id; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getContentType(): ?string { return $this->contentType; @@ -119,9 +93,7 @@ public function removeField(Field $field): void } } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getFieldValues(): array { $fieldValues = []; @@ -132,9 +104,7 @@ public function getFieldValues(): array return $fieldValues; } - /** - * @Groups({"get_content"}) - */ + #[Groups(['get_content'])] public function getStatus(): ContentStatus { return new ContentStatus($this->status); diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php index 1668c0562e8..bdb6a73e285 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php @@ -19,25 +19,20 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity * @ApiFilter (BooleanFilter::class) */ #[ApiResource] +#[ORM\Entity] class ConvertedBoolean { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var bool - * - * @ORM\Column(type="boolean") */ + #[ORM\Column(type: 'boolean')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedDate.php b/tests/Fixtures/TestBundle/Entity/ConvertedDate.php index fb889fd4d07..0fc7b1a2e4a 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedDate.php @@ -19,25 +19,20 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity * @ApiFilter (DateFilter::class) */ #[ApiResource] +#[ORM\Entity] class ConvertedDate { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var \DateTime - * - * @ORM\Column(type="date") */ + #[ORM\Column(type: 'date')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php b/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php index 4ce32e42672..815b5d06af1 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php @@ -21,27 +21,22 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity * @ApiFilter (NumericFilter::class, properties={"nameConverted"}) * @ApiFilter (RangeFilter::class, properties={"nameConverted"}) * @ApiFilter (OrderFilter::class, properties={"nameConverted"}) */ #[ApiResource] +#[ORM\Entity] class ConvertedInteger { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var int - * - * @ORM\Column(type="integer") */ + #[ORM\Column(type: 'integer')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php index aa00a2bff82..6195b32db50 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php @@ -19,25 +19,20 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity * @ApiFilter (SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) */ #[ApiResource] +#[ORM\Entity] class ConvertedOwner { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var ConvertedRelated|null - * - * @ORM\ManyToOne(targetEntity="ConvertedRelated") */ + #[ORM\ManyToOne(targetEntity: 'ConvertedRelated')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php b/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php index feb36f8c6e2..44cd596f5ce 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedRelated.php @@ -16,25 +16,18 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class ConvertedRelated { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column(type="string") */ + #[ORM\Column(type: 'string')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedString.php b/tests/Fixtures/TestBundle/Entity/ConvertedString.php index b47bb947a5a..2d3bdcef148 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedString.php @@ -19,25 +19,20 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity * @ApiFilter (ExistsFilter::class, properties={"nameConverted"}) */ #[ApiResource] +#[ORM\Entity] class ConvertedString { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string|null - * - * @ORM\Column(type="string", nullable=true) */ + #[ORM\Column(type: 'string', nullable: true)] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php b/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php index af48d57ecc7..37aa3934d19 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomActionDummy.php @@ -20,27 +20,18 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity - * * @author Kévin Dunglas */ #[ApiResource(operations: [new Get(), new Get(uriTemplate: 'custom_action_collection_dummies/{id}'), new Get(routeName: 'custom_normalization'), new Get(routeName: 'short_custom_normalization'), new GetCollection(), new GetCollection(uriTemplate: 'custom_action_collection_dummies'), new Post(routeName: 'custom_denormalization'), new GetCollection(routeName: 'short_custom_denormalization')])] +#[ORM\Entity] class CustomActionDummy { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var string - * - * @ORM\Column - */ - private $foo = ''; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column] + private string $foo = ''; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php b/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php index 8fef0bef6d4..ccf9a7240b7 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php +++ b/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php @@ -18,21 +18,16 @@ /** * Custom identifier. - * - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class CustomGeneratedIdentifier { - /** - * @var mixed - * - * @ORM\Id - * @ORM\Column(type="string") - * @ORM\GeneratedValue(strategy="CUSTOM") - * @ORM\CustomIdGenerator(class="ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\UuidGenerator") - */ - private $id; + #[ORM\Id] + #[ORM\Column(type: 'string')] + #[ORM\GeneratedValue(strategy: 'CUSTOM')] + #[ORM\CustomIdGenerator(class: \ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\UuidGenerator::class)] + private ?mixed $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php index d0c03433049..e93ed077334 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomIdentifierDummy.php @@ -18,26 +18,23 @@ /** * Custom Identifier Dummy. - * - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class CustomIdentifierDummy { /** * @var int The custom identifier - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $customId; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $customId = null; /** * @var string The dummy name - * - * @ORM\Column(length=30) */ - private $name; + #[ORM\Column(length: 30)] + private ?string $name = null; public function getCustomId(): int { diff --git a/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php index ff01f25fac7..e9d777e2285 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomMultipleIdentifierDummy.php @@ -19,32 +19,28 @@ /** * Custom Identifier Dummy. - * - * @ORM\Entity */ #[ApiResource(uriVariables: ['firstId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['firstId']), 'secondId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['secondId'])])] +#[ORM\Entity] class CustomMultipleIdentifierDummy { /** * @var int The custom identifier - * - * @ORM\Column(type="integer") - * @ORM\Id */ - private $firstId; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + private ?int $firstId = null; /** * @var int The custom identifier - * - * @ORM\Column(type="integer") - * @ORM\Id */ - private $secondId; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + private ?int $secondId = null; /** * @var string The dummy name - * - * @ORM\Column(length=30) */ - private $name; + #[ORM\Column(length: 30)] + private ?string $name = null; public function getFirstId(): int { diff --git a/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php b/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php index e078bae5528..471c6375749 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomNormalizedDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -23,37 +23,36 @@ * Custom Normalized Dummy. * * @author Mikaël Labrut - * @ORM\Entity */ #[ApiResource(normalizationContext: ['groups' => ['output']], denormalizationContext: ['groups' => ['input']])] +#[ORM\Entity] class CustomNormalizedDummy { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"input", "output"}) */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['input', 'output'])] + private ?int $id = null; + /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"input", "output"}) */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['input', 'output'])] + private ?string $name = null; + /** * @var string|null The dummy name alias - * - * @ORM\Column(nullable=true) - * @ApiProperty(iri="https://schema.org/alternateName") - * @Groups({"input", "output"}) */ - private $alias; + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ORM\Column(nullable: true)] + #[Groups(['input', 'output'])] + private ?string $alias = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php index b01f9f122ce..15f6da268e1 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/CustomWritableIdentifierDummy.php @@ -18,25 +18,22 @@ /** * Custom Writable Identifier Dummy. - * - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class CustomWritableIdentifierDummy { /** * @var string The special identifier - * - * @ORM\Column(name="slug", type="string", length=30) - * @ORM\Id */ - private $slug; + #[ORM\Column(name: 'slug', type: 'string', length: 30)] + #[ORM\Id] + private ?string $slug = null; /** * @var string The dummy name - * - * @ORM\Column(name="name", type="string", length=30) */ - private $name; + #[ORM\Column(name: 'name', type: 'string', length: 30)] + private ?string $name = null; /** * @param string $slug diff --git a/tests/Fixtures/TestBundle/Entity/Customer.php b/tests/Fixtures/TestBundle/Entity/Customer.php index c598476479b..9b1cd169869 100644 --- a/tests/Fixtures/TestBundle/Entity/Customer.php +++ b/tests/Fixtures/TestBundle/Entity/Customer.php @@ -18,31 +18,21 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class Customer { - /** - * @var int - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"order_read"}) - */ - private $id; - /** - * @ORM\Column(type="string") - * @Groups({"order_read"}) - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['order_read'])] + private ?int $id = null; + #[ORM\Column(type: 'string')] + #[Groups(['order_read'])] public $name; - /** - * @ORM\ManyToMany(targetEntity="Address") - * @ORM\JoinColumn(nullable=false) - * @Groups({"order_read"}) - */ + #[ORM\ManyToMany(targetEntity: 'Address')] + #[ORM\JoinColumn(nullable: false)] + #[Groups(['order_read'])] public $addresses; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php b/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php index 80dc1b717ac..08a86a93c55 100644 --- a/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php +++ b/tests/Fixtures/TestBundle/Entity/DeprecatedResource.php @@ -13,28 +13,22 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity - * * @author Kévin Dunglas */ #[ApiResource(deprecationReason: 'This resource is deprecated')] +#[ORM\Entity] class DeprecatedResource { - /** - * @ORM\Id - * @ORM\Column - */ + #[ORM\Id] + #[ORM\Column] public $id; - /** - * @var string - * - * @ApiProperty(attributes={"deprecation_reason"="This field is deprecated"}) - * @ORM\Column - */ - public $deprecatedField; + + #[ApiProperty(deprecationReason: 'This field is deprecated')] + #[ORM\Column] + public string $deprecatedField; } diff --git a/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php b/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php index 4a4ad4ce141..9ef9fbcc74a 100644 --- a/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php +++ b/tests/Fixtures/TestBundle/Entity/DisableItemOperation.php @@ -19,25 +19,21 @@ use ApiPlatform\Metadata\GetCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(operations: [new Get(controller: NotFoundAction::class, read: false, output: false), new GetCollection()])] +#[ORM\Entity] class DisableItemOperation { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index 0b208cb8715..e0ec439d089 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; @@ -25,119 +25,120 @@ * Dummy. * * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource(filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'])] #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy')], status: 200, filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'], operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy')], status: 200, filters: ['my_dummy.boolean', 'my_dummy.date', 'my_dummy.exists', 'my_dummy.numeric', 'my_dummy.order', 'my_dummy.range', 'my_dummy.search', 'my_dummy.property'], operations: [new Get()])] +#[ORM\Entity] class Dummy { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; + /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + private ?string $name = null; + /** * @var string|null The dummy name alias - * - * @ORM\Column(nullable=true) - * @ApiProperty(iri="https://schema.org/alternateName") */ + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ORM\Column(nullable: true)] private $alias; + /** * @var array foo */ - private $foo; + private ?array $foo = null; + /** * @var string|null A short description of the item - * - * @ORM\Column(nullable=true) - * @ApiProperty(iri="https://schema.org/description") */ + #[ApiProperty(types: ['http://schema.org/description'])] + #[ORM\Column(nullable: true)] public $description; + /** * @var string|null A dummy - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $dummy; + /** * @var bool|null A dummy boolean - * - * @ORM\Column(type="boolean", nullable=true) */ + #[ORM\Column(type: 'boolean', nullable: true)] + public $dummyBoolean; /** * @var \DateTime|null A dummy date - * - * @ORM\Column(type="datetime", nullable=true) - * @ApiProperty(iri="http://schema.org/DateTime") */ + #[ApiProperty(types: ['http://schema.org/DateTime'])] + #[ORM\Column(type: 'datetime', nullable: true)] public $dummyDate; + /** * @var float|null A dummy float - * - * @ORM\Column(type="float", nullable=true) */ + #[ORM\Column(type: 'float', nullable: true)] public $dummyFloat; + /** * @var string|null A dummy price - * - * @ORM\Column(type="decimal", precision=10, scale=2, nullable=true) */ + #[ORM\Column(type: 'decimal', precision: 10, scale: 2, nullable: true)] public $dummyPrice; + /** * @var RelatedDummy|null A related dummy - * - * @ORM\ManyToOne(targetEntity="RelatedDummy") - * @ApiProperty(push=true) */ + #[ApiProperty(push: true)] + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] public $relatedDummy; + /** * @var \Collection Several dummies - * @ORM\ManyToMany(targetEntity="RelatedDummy") */ + #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] public $relatedDummies; + /** * @var array|null serialize data - * - * @ORM\Column(type="json", nullable=true) */ + #[ORM\Column(type: 'json', nullable: true)] public $jsonData; + /** * @var array|null - * - * @ORM\Column(type="simple_array", nullable=true) */ + #[ORM\Column(type: 'simple_array', nullable: true)] public $arrayData; + /** * @var string|null - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $nameConverted; + /** * @var RelatedOwnedDummy|null - * - * @ORM\OneToOne(targetEntity="RelatedOwnedDummy", cascade={"persist"}, mappedBy="owningDummy") */ + #[ORM\OneToOne(targetEntity: 'RelatedOwnedDummy', cascade: ['persist'], mappedBy: 'owningDummy')] public $relatedOwnedDummy; + /** * @var RelatedOwningDummy|null - * - * @ORM\OneToOne(targetEntity="RelatedOwningDummy", cascade={"persist"}, inversedBy="ownedDummy") */ + #[ORM\OneToOne(targetEntity: 'RelatedOwningDummy', cascade: ['persist'], inversedBy: 'ownedDummy')] public $relatedOwningDummy; public static function staticMethod() diff --git a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php index d3908219379..0170447827f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php @@ -25,37 +25,34 @@ * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * @ORM\Entity */ #[ApiResource] #[ApiResource(uriTemplate: '/dummy_products/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class DummyAggregateOffer { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var \Collection - * @ORM\OneToMany(targetEntity="DummyOffer", mappedBy="aggregate", cascade={"persist"}) */ - private $offers; + #[ORM\OneToMany(targetEntity: 'DummyOffer', mappedBy: 'aggregate', cascade: ['persist'])] + private \Collection $offers; /** * @var DummyProduct|null The dummy product - * - * @ORM\ManyToOne(targetEntity="DummyProduct", inversedBy="offers") */ - private $product; + #[ORM\ManyToOne(targetEntity: 'DummyProduct', inversedBy: 'offers')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct $product = null; /** * @var int The dummy aggregate offer value - * - * @ORM\Column(type="integer") */ + #[ORM\Column(type: 'integer')] private $value; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/DummyBoolean.php b/tests/Fixtures/TestBundle/Entity/DummyBoolean.php index 4e5103f93b9..27c4bcf237d 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/DummyBoolean.php @@ -16,30 +16,17 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class DummyBoolean { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var bool|null - * - * @ORM\Column(type="boolean", nullable=true) - */ - private $isDummyBoolean; - - public function __construct(bool $isDummyBoolean) + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + public function __construct(#[ORM\Column(type: 'boolean', nullable: true)] private readonly ?bool $isDummyBoolean) { - $this->isDummyBoolean = $isDummyBoolean; } public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyCar.php b/tests/Fixtures/TestBundle/Entity/DummyCar.php index b952db1b104..3a8587793d9 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCar.php @@ -30,7 +30,6 @@ use Symfony\Component\Serializer\Annotation as Serializer; /** - * @ORM\Entity * @ApiFilter (DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) * @ApiFilter (BooleanFilter::class) * @ApiFilter (PropertyFilter::class, arguments={"parameterName"="foobar"}) @@ -38,88 +37,62 @@ * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") */ #[ApiResource(operations: [new Get(openapiContext: ['tags' => []]), new Put(), new Delete(), new Post(), new GetCollection()], sunset: '2050-01-01', normalizationContext: ['groups' => ['colors']])] +#[ORM\Entity] class DummyCar { /** * @var DummyCarIdentifier The entity Id - * - * @ORM\Id - * @ORM\OneToOne(targetEntity="DummyCarIdentifier", cascade={"persist"}) */ - private $id; + #[ORM\Id] + #[ORM\OneToOne(targetEntity: 'DummyCarIdentifier', cascade: ['persist'])] + private readonly \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarIdentifier $id; /** * @var mixed Something else * - * @ORM\OneToMany(targetEntity="DummyCarColor", mappedBy="car") - * - * @Serializer\Groups({"colors"}) * @ApiFilter(SearchFilter::class, properties={"colors.prop"="ipartial", "colors"="exact"}) */ + #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[Serializer\Groups(['colors'])] private $colors; /** * @var mixed Something else * - * @ORM\OneToMany(targetEntity="DummyCarColor", mappedBy="car") - * - * @Serializer\Groups({"colors"}) * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $secondColors; + #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[Serializer\Groups(['colors'])] + private ?mixed $secondColors = null; /** * @var mixed Something else * - * @ORM\OneToMany(targetEntity="DummyCarColor", mappedBy="car") - * - * @Serializer\Groups({"colors"}) * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $thirdColors; + #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[Serializer\Groups(['colors'])] + private ?mixed $thirdColors = null; /** * @var mixed Something else * - * @ORM\ManyToMany(targetEntity="UuidIdentifierDummy", indexBy="uuid") - * * @ORM\JoinTable(name="uuid_cars", - * joinColumns={@ORM\JoinColumn(name="car_id", referencedColumnName="id_id")}, - * inverseJoinColumns={@ORM\JoinColumn(name="uuid_uuid", referencedColumnName="uuid")} - * ) - * @Serializer\Groups({"colors"}) * @ApiFilter(SearchFilter::class, strategy="exact") */ - private $uuid; + #[ORM\ManyToMany(targetEntity: 'UuidIdentifierDummy', indexBy: 'uuid')] + #[Serializer\Groups(['colors'])] + private ?mixed $uuid = null; /** - * @var string - * - * @ORM\Column(type="string") * @ApiFilter(SearchFilter::class, strategy="partial") */ - private $name; - /** - * @var bool - * - * @ORM\Column(type="boolean") - */ - private $canSell; - /** - * @var \DateTime - * - * @ORM\Column(type="datetime") - */ - private $availableAt; - /** - * @var string - * - * @Serializer\Groups({"colors"}) - * @Serializer\SerializedName("carBrand") - * - * @ORM\Column - */ - private $brand = 'DummyBrand'; - /** - * @var DummyCarInfo - * - * @ORM\Embedded(class="DummyCarInfo") - */ - private $info; + #[ORM\Column(type: 'string')] + private ?string $name = null; + #[ORM\Column(type: 'boolean')] + private ?bool $canSell = null; + #[ORM\Column(type: 'datetime')] + private ?\DateTime $availableAt = null; + #[Serializer\Groups(['colors'])] + #[Serializer\SerializedName('carBrand')] + #[ORM\Column] + private string $brand = 'DummyBrand'; + #[ORM\Embedded(class: 'DummyCarInfo')] + private \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarInfo $info; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php index 21dc53f7614..051f5476987 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php @@ -20,38 +20,28 @@ use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class DummyCarColor { /** * @var int The entity Id - * - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") */ - private $id; + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] + private ?int $id = null; + #[ORM\ManyToOne(targetEntity: 'DummyCar', inversedBy: 'colors')] + #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE', referencedColumnName: 'id_id')] + #[Assert\NotBlank] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar $car = null; /** - * @var DummyCar - * - * @ORM\ManyToOne(targetEntity="DummyCar", inversedBy="colors") - * @ORM\JoinColumn(nullable=false, onDelete="CASCADE", referencedColumnName="id_id") - * @Assert\NotBlank - */ - private $car; - /** - * @var string - * - * @ORM\Column(nullable=false) * @ApiFilter(SearchFilter::class) - * @Assert\NotBlank - * - * @Serializer\Groups({"colors"}) */ - private $prop = ''; + #[ORM\Column(nullable: false)] + #[Assert\NotBlank] + #[Serializer\Groups(['colors'])] + private string $prop = ''; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarIdentifier.php b/tests/Fixtures/TestBundle/Entity/DummyCarIdentifier.php index aa2b822ae46..89fe64e3699 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarIdentifier.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarIdentifier.php @@ -15,19 +15,15 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ -class DummyCarIdentifier +#[ORM\Entity] +class DummyCarIdentifier implements \Stringable { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - public function __toString() + public function __toString(): string { return (string) $this->id; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarInfo.php b/tests/Fixtures/TestBundle/Entity/DummyCarInfo.php index 51209343b30..9b789f873a3 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarInfo.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarInfo.php @@ -17,15 +17,13 @@ /** * @author Sergey Balasov - * - * @ORM\Embeddable */ +#[ORM\Embeddable] class DummyCarInfo { /** * @var string - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $name; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php b/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php index a1af67d71d1..9d85b7a94be 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomFormat.php @@ -17,26 +17,22 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - */ #[ApiResource(formats: ['xml', 'jsonld', 'csv' => ['text/csv'], 'pdf' => 'application/pdf'])] +#[ORM\Entity] class DummyCustomFormat { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** * @var string - * - * @ORM\Column - * @Assert\NotBlank */ + #[ORM\Column] + #[Assert\NotBlank] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php index fa9dcd0639d..afc9d79681b 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php @@ -22,41 +22,24 @@ /** * Dummy with a custom GraphQL mutation resolver. * - * @ORM\Entity - * * @author Raoul Clais */ #[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']]), new Mutation(name: 'testOutput', resolver: 'app.graphql.mutation_resolver.dummy_custom', output: OutputDto::class)])] +#[ORM\Entity] class DummyCustomMutation { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - */ - private $operandA; - /** - * @var int|null - * - * @Groups({"sum"}) - * @ORM\Column(type="integer", nullable=true) - */ - private $operandB; - /** - * @var int|null - * - * @Groups({"result"}) - * @ORM\Column(type="integer", nullable=true) - */ - private $result; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'integer', nullable: true)] + private ?int $operandA = null; + #[Groups(['sum'])] + #[ORM\Column(type: 'integer', nullable: true)] + private ?int $operandB = null; + #[Groups(['result'])] + #[ORM\Column(type: 'integer', nullable: true)] + private ?int $result = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php index d702a2822d2..53ef85c2944 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php @@ -23,18 +23,17 @@ * Dummy with custom GraphQL query resolvers. * * @author Lukas Lücke - * @ORM\Entity */ #[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new Query(name: 'testItemOutput', resolver: 'app.graphql.query_resolver.dummy_custom_item', output: OutputDto::class), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])] +#[ORM\Entity] class DummyCustomQuery { /** * @var int - * - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] public $id; /** * @var string diff --git a/tests/Fixtures/TestBundle/Entity/DummyDate.php b/tests/Fixtures/TestBundle/Entity/DummyDate.php index 60d0ea723bb..03d995eb750 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDate.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDate.php @@ -30,42 +30,37 @@ * "dateIncludeNullBefore"=DateFilter::INCLUDE_NULL_BEFORE, * "dateIncludeNullBeforeAndAfter"=DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER * }) - * @ORM\Entity */ #[ApiResource(filters: ['my_dummy_date.date'])] +#[ORM\Entity] class DummyDate { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var \DateTime The dummy date - * - * @ORM\Column(type="date") */ + #[ORM\Column(type: 'date')] public $dummyDate; /** * @var \DateTime|null - * - * @ORM\Column(type="date", nullable=true) */ + #[ORM\Column(type: 'date', nullable: true)] public $dateIncludeNullAfter; /** * @var \DateTime|null - * - * @ORM\Column(type="date", nullable=true) */ + #[ORM\Column(type: 'date', nullable: true)] public $dateIncludeNullBefore; /** * @var \DateTime|null - * - * @ORM\Column(type="date", nullable=true) */ + #[ORM\Column(type: 'date', nullable: true)] public $dateIncludeNullBeforeAndAfter; /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php b/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php index 114bbf7d42e..80219ba60eb 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDifferentGraphQlSerializationGroup.php @@ -23,34 +23,31 @@ * Dummy with different serialization groups for item_query and collection_query. * * @author Mahmood Bazdar - * @ORM\Entity */ #[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['item_query']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['collection_query']])])] +#[ORM\Entity] class DummyDifferentGraphQlSerializationGroup { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"item_query", "collection_query"}) */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['item_query', 'collection_query'])] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * @Groups({"item_query", "collection_query"}) */ - private $name; + #[ORM\Column] + #[Groups(['item_query', 'collection_query'])] + private ?string $name = null; /** * @var string|null The dummy title - * - * @ORM\Column(nullable=true) - * @Groups({"item_query"}) */ - private $title; + #[ORM\Column(nullable: true)] + #[Groups(['item_query'])] + private ?string $title = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php index f9960ebcf36..f6e3eae814b 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php @@ -25,31 +25,27 @@ /** * DummyDtoCustom. - * - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), new Put(), new Delete(), new Post(input: CustomInputDto::class), new GetCollection(), new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output')])] +#[ORM\Entity] class DummyDtoCustom { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php index 5890a676cad..fd64076d9df 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php @@ -24,9 +24,9 @@ * Dummy InputOutput. * * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource(input: InputDto::class, output: OutputDto::class)] +#[ORM\Entity] class DummyDtoInputOutput { public function __construct() @@ -35,24 +35,24 @@ public function __construct() } /** * @var int The id - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; /** * @var string - * @ORM\Column(type="string") */ + #[ORM\Column(type: 'string')] public $str; /** * @var float - * @ORM\Column(type="float") */ + #[ORM\Column(type: 'float')] public $num; /** * @var Collection - * @ORM\ManyToMany(targetEntity="RelatedDummy") */ + #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] public $relatedDummies; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php index 08b9137ec72..126627ce62f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php @@ -27,30 +27,27 @@ * DummyDtoNoInput. * * @author Vincent Chalamon - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Delete(), new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200), new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class), new GetCollection()], input: false, output: OutputDto::class)] +#[ORM\Entity] class DummyDtoNoInput { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; /** * @var float - * - * @ORM\Column(type="float") */ + #[ORM\Column(type: 'float')] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php index d1d1b1a034d..2b5e789f30c 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php @@ -21,30 +21,27 @@ * DummyDtoNoOutput. * * @author Vincent Chalamon - * @ORM\Entity */ #[ApiResource(input: InputDto::class, output: false)] +#[ORM\Entity] class DummyDtoNoOutput { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php index 8cce1b5b478..e1d647f57b8 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php @@ -21,30 +21,27 @@ * Dummy InputOutput. * * @author Daniel West - * @ORM\Entity */ #[ApiResource(output: OutputDtoDummy::class)] +#[ORM\Entity] class DummyDtoOutputFallbackToSameClass { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php index fa88497f8b0..277bdc9ba58 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php @@ -20,30 +20,27 @@ * Dummy InputOutput. * * @author Daniel West - * @ORM\Entity */ #[ApiResource(output: DummyDtoOutputSameClass::class)] +#[ORM\Entity] class DummyDtoOutputSameClass { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php b/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php index a6f2d3a41b3..d59b045f272 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php +++ b/tests/Fixtures/TestBundle/Entity/DummyEntityWithConstructor.php @@ -28,51 +28,27 @@ * https://github.com/api-platform/core/issues/1747. * * @author Maxime Veber - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Put(denormalizationContext: ['groups' => ['put']]), new Post(), new GetCollection()])] +#[ORM\Entity] class DummyEntityWithConstructor { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - /** - * @var string - * - * @ORM\Column - */ - private $foo; - /** - * @var string - * - * @ORM\Column - */ - private $bar; - /** - * @var string|null - * - * @ORM\Column(nullable=true) - * @Groups({"put"}) - */ - private $baz; - /** - * @var DummyObjectWithoutConstructor[] - */ - private $items; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(nullable: true)] + #[Groups(['put'])] + private ?string $baz = null; /** * @param DummyObjectWithoutConstructor[] $items */ - public function __construct(string $foo, string $bar, array $items) + public function __construct(#[ORM\Column] private readonly string $foo, #[ORM\Column] private readonly string $bar, private readonly array $items) { - $this->foo = $foo; - $this->bar = $bar; - $this->items = $items; } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php index 311fa7ab95a..4a946430e1a 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php +++ b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFields.php @@ -16,27 +16,17 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class DummyForAdditionalFields { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** @ORM\Column */ - private $name; - /** @ORM\Column */ - private $slug; - public function __construct(string $name, string $slug) + public function __construct(#[ORM\Column] private readonly string $name, #[ORM\Column] private readonly string $slug) { - $this->name = $name; - $this->slug = $slug; } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php index b546afa4415..25ade655161 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyForAdditionalFieldsInput.php @@ -20,14 +20,12 @@ final class DummyForAdditionalFieldsInput { /** - * @ApiProperty(identifier=true) + * #[ApiProperty(identifier: true)]. */ public $id; - private $dummyName; - public function __construct(string $dummyName) + public function __construct(private readonly string $dummyName) { - $this->dummyName = $dummyName; } public function getDummyName(): string diff --git a/tests/Fixtures/TestBundle/Entity/DummyFriend.php b/tests/Fixtures/TestBundle/Entity/DummyFriend.php index ee144c9ece9..bceb0b587ae 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyFriend.php +++ b/tests/Fixtures/TestBundle/Entity/DummyFriend.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; @@ -24,28 +24,27 @@ * Dummy Friend. * * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class DummyFriend { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"fakemanytomany", "friends"}) */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['fakemanytomany', 'friends'])] + private ?string $name = null; /** * Get id. diff --git a/tests/Fixtures/TestBundle/Entity/DummyGroup.php b/tests/Fixtures/TestBundle/Entity/DummyGroup.php index d6f2c60fea7..5586c0d1077 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyGroup.php +++ b/tests/Fixtures/TestBundle/Entity/DummyGroup.php @@ -24,52 +24,39 @@ * DummyGroup. * * @author Baptiste Meyer - * @ORM\Entity */ #[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['dummy_foo']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['dummy_foo']]), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_bar']], denormalizationContext: ['groups' => ['dummy_bar', 'dummy_baz']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_group.group', 'dummy_group.override_group', 'dummy_group.whitelist_group', 'dummy_group.override_whitelist_group'])] +#[ORM\Entity] class DummyGroup { - /** - * @var int|null - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"dummy", "dummy_read", "dummy_id"}) - */ - private $id; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['dummy', 'dummy_read', 'dummy_id'])] + private ?int $id = null; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_foo"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_foo'])] public $foo; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_write", "dummy_bar"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_bar'])] public $bar; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy", "dummy_read", "dummy_baz"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy', 'dummy_read', 'dummy_baz'])] public $baz; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy", "dummy_write", "dummy_qux"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy', 'dummy_write', 'dummy_qux'])] public $qux; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php b/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php index 3680e06f758..8bd65599afa 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php +++ b/tests/Fixtures/TestBundle/Entity/DummyImmutableDate.php @@ -19,25 +19,22 @@ /** * Dummy Immutable Date. - * - * @ORM\Entity */ #[ApiResource(filters: ['my_dummy_immutable_date.date'])] +#[ORM\Entity] class DummyImmutableDate { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var \DateTimeImmutable The dummy date - * - * @ORM\Column(type="date_immutable") */ + #[ORM\Column(type: 'date_immutable')] public $dummyDate; /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyMercure.php b/tests/Fixtures/TestBundle/Entity/DummyMercure.php index b20669366fe..a105d78c0ab 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyMercure.php +++ b/tests/Fixtures/TestBundle/Entity/DummyMercure.php @@ -17,29 +17,20 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity - * * @author Kévin Dunglas */ #[ApiResource(mercure: true)] +#[ORM\Entity] class DummyMercure { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - /** - * @ORM\Column - */ + #[ORM\Column] public $name; - /** - * @ORM\Column - */ + #[ORM\Column] public $description; - /** - * @ORM\ManyToOne(targetEntity="RelatedDummy") - */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] public $relatedDummy; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php b/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php index 4085bc8d1c5..6f6106b9539 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyNoGetOperation.php @@ -22,24 +22,22 @@ * DummyNoGetOperation. * * @author Grégoire Hébert gregoire@les-tilleuls.coop - * @ORM\Entity */ #[ApiResource(operations: [new Put(), new Post()])] +#[ORM\Entity] class DummyNoGetOperation { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** * @var string - * - * @ORM\Column */ + #[ORM\Column] public $lorem; public function setId($id) diff --git a/tests/Fixtures/TestBundle/Entity/DummyOffer.php b/tests/Fixtures/TestBundle/Entity/DummyOffer.php index 15b18d2332c..83ca3822670 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyOffer.php @@ -24,34 +24,31 @@ * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * @ORM\Entity */ #[ApiResource] #[ApiResource(uriTemplate: '/dummy_aggregate_offers/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/dummy_products/{id}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class DummyOffer { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var int The dummy aggregate offer value - * - * @ORM\Column(type="integer") */ - private $value; + #[ORM\Column(type: 'integer')] + private ?int $value = null; /** * @var DummyAggregateOffer|null The dummy aggregate offer value - * - * @ORM\ManyToOne(targetEntity="DummyAggregateOffer", inversedBy="offers") */ - private $aggregate; + #[ORM\ManyToOne(targetEntity: 'DummyAggregateOffer', inversedBy: 'offers')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer $aggregate = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyPassenger.php b/tests/Fixtures/TestBundle/Entity/DummyPassenger.php index e1499af768d..68f5271cfe1 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPassenger.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPassenger.php @@ -16,23 +16,18 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class DummyPassenger { /** * @var int The entity Id - * - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ - private $id; - /** - * @ORM\Column(type="string") */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] + private ?int $id = null; + #[ORM\Column(type: 'string')] public $nickname; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php index 23cd381535f..6e8233d1c09 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php @@ -24,22 +24,16 @@ use ApiPlatform\Core\Annotation\ApiProperty; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(description: 'Hey PHP 8')] +#[ORM\Entity] class DummyPhp8 { - /** - * @ORM\Id - * @ORM\Column(type="integer") - */ #[ApiProperty(identifier: true, description: 'the identifier')] + #[ORM\Id] + #[ORM\Column(type: 'integer')] public $id; - /** - * @ORM\Column - */ #[ApiFilter(SearchFilter::class)] + #[ORM\Column] public $filtered; #[ApiProperty(description: 'a foo')] public function getFoo() : int diff --git a/tests/Fixtures/TestBundle/Entity/DummyPhp8ApiPropertyAttribute.php b/tests/Fixtures/TestBundle/Entity/DummyPhp8ApiPropertyAttribute.php index f0ccca4b613..8f42706b746 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPhp8ApiPropertyAttribute.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPhp8ApiPropertyAttribute.php @@ -17,22 +17,16 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(description: 'Hey PHP 8')] +#[ORM\Entity] class DummyPhp8ApiPropertyAttribute { - /** - * @ORM\Id - * @ORM\Column(type="integer") - */ #[ApiProperty(identifier: true, description: 'the identifier')] + #[ORM\Id] + #[ORM\Column(type: 'integer')] public $id; - /** - * @ORM\Column - */ + #[ORM\Column] public $filtered; #[ApiProperty] diff --git a/tests/Fixtures/TestBundle/Entity/DummyProduct.php b/tests/Fixtures/TestBundle/Entity/DummyProduct.php index d4c154090e0..df599baa2bd 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Entity/DummyProduct.php @@ -26,39 +26,35 @@ * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * @ORM\Entity */ #[ApiResource] #[ApiResource(uriTemplate: '/dummy_products/{id}/related_products.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class DummyProduct { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var \Collection - * @ORM\OneToMany(targetEntity="DummyAggregateOffer", mappedBy="product", cascade={"persist"}) */ - private $offers; + #[ORM\OneToMany(targetEntity: 'DummyAggregateOffer', mappedBy: 'product', cascade: ['persist'])] + private \Collection $offers; /** * @var string The tour name - * - * @ORM\Column */ + #[ORM\Column] private $name; /** * @var \Collection - * @ORM\OneToMany(targetEntity="DummyProduct", mappedBy="parent") - */ - private $relatedProducts; - /** - * @ORM\ManyToOne(targetEntity="DummyProduct", inversedBy="relatedProducts") */ + #[ORM\OneToMany(targetEntity: 'DummyProduct', mappedBy: 'parent')] + private \Collection $relatedProducts; + #[ORM\ManyToOne(targetEntity: 'DummyProduct', inversedBy: 'relatedProducts')] private $parent; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/DummyProperty.php b/tests/Fixtures/TestBundle/Entity/DummyProperty.php index 3f8338113f1..7fd3cbd9c5b 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyProperty.php +++ b/tests/Fixtures/TestBundle/Entity/DummyProperty.php @@ -25,67 +25,51 @@ * DummyProperty. * * @author Baptiste Meyer - * @ORM\Entity */ #[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query'), new Mutation(name: 'update'), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_graphql_read']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_property.property', 'dummy_property.whitelist_property', 'dummy_property.whitelisted_properties'])] +#[ORM\Entity] class DummyProperty { - /** - * @var int|null - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"dummy_read", "dummy_graphql_read"}) - */ - private $id; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['dummy_read', 'dummy_graphql_read'])] + private ?int $id = null; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read", "dummy_write"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read', 'dummy_write'])] public $foo; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $bar; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $baz; /** * @var DummyGroup|null - * - * @ORM\ManyToOne(targetEntity=DummyGroup::class, cascade={"persist"}) - * - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[ORM\ManyToOne(targetEntity: DummyGroup::class, cascade: ['persist'])] + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $group; /** * @var Collection - * - * @ORM\ManyToMany(targetEntity=DummyGroup::class, cascade={"persist"}) - * @Groups({"dummy_read", "dummy_graphql_read", "dummy_write"}) */ + #[ORM\ManyToMany(targetEntity: DummyGroup::class, cascade: ['persist'])] + #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] public $groups; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read'])] public $nameConverted; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php b/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php index bc8a5b29dee..8aeed68c43a 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPropertyWithDefaultValue.php @@ -19,35 +19,26 @@ /** * DummyPropertyWithDefaultValue. - * - * @ORM\Entity */ #[ApiResource(normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']])] +#[ORM\Entity] class DummyPropertyWithDefaultValue { - /** - * @var int|null - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups("dummy_read") - */ - private $id; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups('dummy_read')] + private ?int $id = null; /** * @var string|null - * - * @ORM\Column(nullable=true) - * - * @Groups({"dummy_read", "dummy_write"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['dummy_read', 'dummy_write'])] public $foo = 'foo'; /** * @var string A dummy with a Doctrine default options - * - * @ORM\Column(options={"default"="default value"}) */ + #[ORM\Column(options: ['default' => 'default value'])] public $dummyDefaultOption; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php index 9ac1af3a3de..5ab4ee6d8a8 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php @@ -17,45 +17,30 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - * @ORM\InheritanceType ("JOINED") - * @ORM\DiscriminatorColumn (name="discr", type="string") - * @ORM\DiscriminatorMap ({ - * "dummyTableInheritance"="DummyTableInheritance", - * "dummyTableInheritanceChild"="DummyTableInheritanceChild", - * "dummyTableInheritanceDifferentChild"="DummyTableInheritanceDifferentChild", - * "dummyTableInheritanceNotApiResourceChild"="DummyTableInheritanceNotApiResourceChild" - * }) - */ #[ApiResource] +#[ORM\Entity] +#[ORM\InheritanceType('JOINED')] +#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')] +#[ORM\DiscriminatorMap(['dummyTableInheritance' => 'DummyTableInheritance', 'dummyTableInheritanceChild' => 'DummyTableInheritanceChild', 'dummyTableInheritanceDifferentChild' => 'DummyTableInheritanceDifferentChild', 'dummyTableInheritanceNotApiResourceChild' => 'DummyTableInheritanceNotApiResourceChild'])] class DummyTableInheritance { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"default"}) */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['default'])] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column - * - * @Groups({"default"}) - */ - private $name; - /** - * @var DummyTableInheritanceRelated|null - * - * @ORM\ManyToOne(targetEntity="DummyTableInheritanceRelated", inversedBy="children") - * @ORM\JoinColumn(nullable=true, onDelete="CASCADE") */ - private $parent; + #[ORM\Column] + #[Groups(['default'])] + private ?string $name = null; + #[ORM\ManyToOne(targetEntity: 'DummyTableInheritanceRelated', inversedBy: 'children')] + #[ORM\JoinColumn(nullable: true, onDelete: 'CASCADE')] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceRelated $parent = null; public function getName(): ?string { diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php index f78a24aa3b4..8564988a11f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceChild.php @@ -17,19 +17,15 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class DummyTableInheritanceChild extends DummyTableInheritance { /** * @var string The dummy nickname - * - * @ORM\Column - * - * @Groups({"default"}) */ + #[ORM\Column] + #[Groups(['default'])] private $nickname; public function getNickname() diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php index a3afcdf0cbf..0a8ba5c0f62 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceDifferentChild.php @@ -17,19 +17,15 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class DummyTableInheritanceDifferentChild extends DummyTableInheritance { /** * @var string The dummy email - * - * @ORM\Column - * - * @Groups({"default"}) */ + #[ORM\Column] + #[Groups(['default'])] private $email; public function getEmail() diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceNotApiResourceChild.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceNotApiResourceChild.php index 0cda91af305..1037906a912 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceNotApiResourceChild.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceNotApiResourceChild.php @@ -15,17 +15,14 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class DummyTableInheritanceNotApiResourceChild extends DummyTableInheritance { /** * @var bool The dummy swagg - * - * @ORM\Column(type="boolean") */ - private $swaggerThanParent; + #[ORM\Column(type: 'boolean')] + private bool $swaggerThanParent; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php index dc5886e194c..a363fbc1207 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php @@ -19,31 +19,25 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource(normalizationContext: ['groups' => ['default']], denormalizationContext: ['groups' => ['default']])] +#[ORM\Entity] class DummyTableInheritanceRelated { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * - * @Groups({"default"}) */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['default'])] + private ?int $id = null; /** * @var Collection Related children - * - * @ORM\OneToMany(targetEntity="DummyTableInheritance", mappedBy="parent") - * @ORM\OrderBy({"id"="ASC"}) - * - * @Groups({"default"}) */ - private $children; + #[ORM\OneToMany(targetEntity: 'DummyTableInheritance', mappedBy: 'parent')] + #[ORM\OrderBy(['id' => 'ASC'])] + #[Groups(['default'])] + private \Doctrine\Common\Collections\Collection $children; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyTravel.php b/tests/Fixtures/TestBundle/Entity/DummyTravel.php index 869704a0333..67e220ebbee 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTravel.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTravel.php @@ -16,31 +16,21 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(filters: ['dummy_travel.property'])] +#[ORM\Entity] class DummyTravel { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** - * @ORM\ManyToOne(targetEntity="DummyCar") - * @ORM\JoinColumn(name="car_id", referencedColumnName="id_id") - */ + #[ORM\ManyToOne(targetEntity: 'DummyCar')] + #[ORM\JoinColumn(name: 'car_id', referencedColumnName: 'id_id')] public $car; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: 'boolean')] public $confirmed; - /** - * @ORM\ManyToOne(targetEntity="DummyPassenger") - * @ORM\JoinColumn(name="passenger_id", referencedColumnName="id") - */ + #[ORM\ManyToOne(targetEntity: 'DummyPassenger')] + #[ORM\JoinColumn(name: 'passenger_id', referencedColumnName: 'id')] public $passenger; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyValidation.php b/tests/Fixtures/TestBundle/Entity/DummyValidation.php index 9b6b071c6f4..45e192a7247 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyValidation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyValidation.php @@ -23,39 +23,34 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - */ #[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new Post(uriTemplate: 'dummy_validation.{_format}'), new GetCollection(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]), new GetCollection(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator'])])] +#[ORM\Entity] class DummyValidation { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ORM\Column(nullable=true) - * @Assert\NotNull(groups={"a"}) */ - private $name; + #[ORM\Column(nullable: true)] + #[Assert\NotNull(groups: ['a'])] + private ?string $name = null; /** * @var string|null The dummy title - * - * @ORM\Column(nullable=true) - * @Assert\NotNull(groups={"b"}) */ - private $title; + #[ORM\Column(nullable: true)] + #[Assert\NotNull(groups: ['b'])] + private ?string $title = null; /** * @var string The dummy code - * @ORM\Column */ - private $code; + #[ORM\Column] + private ?string $code = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/EmbeddableDummy.php b/tests/Fixtures/TestBundle/Entity/EmbeddableDummy.php index 924b763a87b..54969d1acc7 100644 --- a/tests/Fixtures/TestBundle/Entity/EmbeddableDummy.php +++ b/tests/Fixtures/TestBundle/Entity/EmbeddableDummy.php @@ -21,52 +21,39 @@ * Embeddable Dummy. * * @author Jordan Samouh - * - * @ORM\Embeddable */ +#[ORM\Embeddable] class EmbeddableDummy { /** * @var string The dummy name - * - * @ORM\Column(nullable=true) - * @Groups({"embed"}) */ - private $dummyName; - + #[ORM\Column(nullable: true)] + #[Groups(['embed'])] + private ?string $dummyName = null; /** * @var bool|null A dummy boolean - * - * @ORM\Column(type="boolean", nullable=true) */ + #[ORM\Column(type: 'boolean', nullable: true)] public $dummyBoolean; - /** * @var \DateTime|null A dummy date - * - * @ORM\Column(type="datetime", nullable=true) - * @Assert\DateTime */ + #[ORM\Column(type: 'datetime', nullable: true)] + #[Assert\DateTime] public $dummyDate; - /** * @var float|null A dummy float - * - * @ORM\Column(type="float", nullable=true) */ + #[ORM\Column(type: 'float', nullable: true)] public $dummyFloat; - /** * @var string|null A dummy price - * - * @ORM\Column(type="decimal", precision=10, scale=2, nullable=true) */ + #[ORM\Column(type: 'decimal', precision: 10, scale: 2, nullable: true)] public $dummyPrice; - - /** - * @ORM\Column(type="string", nullable=true) - * @Groups({"barcelona", "chicago"}) - */ + #[ORM\Column(type: 'string', nullable: true)] + #[Groups(['barcelona', 'chicago'])] protected $symfony; public static function staticMethod() diff --git a/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php b/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php index e739543b2e3..962086052b6 100644 --- a/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php @@ -27,45 +27,40 @@ * Embedded Dummy. * * @author Jordan Samouh - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(uriTemplate: '/embedded_dummies_groups/{id}', normalizationContext: ['groups' => ['embed']]), new Post(), new GetCollection()], filters: ['my_dummy.search', 'my_dummy.order', 'my_dummy.date', 'my_dummy.range', 'my_dummy.boolean', 'my_dummy.numeric'])] +#[ORM\Entity] class EmbeddedDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string|null The dummy name - * - * @ORM\Column(nullable=true) - * @Groups({"embed"}) */ - private $name; + #[ORM\Column(nullable: true)] + #[Groups(['embed'])] + private ?string $name = null; /** * @var \DateTime|null A dummy date - * - * @ORM\Column(type="datetime", nullable=true) - * @Assert\DateTime */ + #[ORM\Column(type: 'datetime', nullable: true)] + #[Assert\DateTime] public $dummyDate; /** * @var EmbeddableDummy - * - * @ORM\Embedded(class="EmbeddableDummy") - * @Groups({"embed"}) */ + #[ORM\Embedded(class: 'EmbeddableDummy')] + #[Groups(['embed'])] public $embeddedDummy; /** * @var RelatedDummy|null A related dummy - * - * @ORM\ManyToOne(targetEntity="RelatedDummy") */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] public $relatedDummy; public static function staticMethod() diff --git a/tests/Fixtures/TestBundle/Entity/Employee.php b/tests/Fixtures/TestBundle/Entity/Employee.php index ca970b747fb..202ea51c2c8 100644 --- a/tests/Fixtures/TestBundle/Entity/Employee.php +++ b/tests/Fixtures/TestBundle/Entity/Employee.php @@ -19,9 +19,6 @@ use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] #[Post] #[ApiResource( @@ -39,28 +36,25 @@ ] )] #[GetCollection] +#[ORM\Entity] class Employee { /** * @var int|null The id - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] public string $name; - /** - * @ORM\ManyToOne(targetEntity="ApiPlatform\Tests\Fixtures\TestBundle\Entity\Company") - */ - public ?Company $company; + #[ORM\ManyToOne(targetEntity: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Company::class)] + public ?Company $company = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/ExternalUser.php b/tests/Fixtures/TestBundle/Entity/ExternalUser.php index 15534783054..ee8a7d39ee2 100644 --- a/tests/Fixtures/TestBundle/Entity/ExternalUser.php +++ b/tests/Fixtures/TestBundle/Entity/ExternalUser.php @@ -16,15 +16,11 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class ExternalUser extends AbstractUser { - /** - * @ORM\Column - */ + #[ORM\Column] private $externalId; public function getExternalId(): ?string diff --git a/tests/Fixtures/TestBundle/Entity/Field.php b/tests/Fixtures/TestBundle/Entity/Field.php index ddcc01f3c6f..b9df7e451ec 100644 --- a/tests/Fixtures/TestBundle/Entity/Field.php +++ b/tests/Fixtures/TestBundle/Entity/Field.php @@ -15,41 +15,20 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class Field implements \JsonSerializable { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var Content - * - * @ORM\ManyToOne(targetEntity=Content::class, inversedBy="fields") - * @ORM\JoinColumn(nullable=false) - */ - private $content; - - /** - * @var string - * - * @ORM\Column(type="string") - */ - private $name; - - /** - * @var string - * - * @ORM\Column(type="text") - */ - private $value; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\ManyToOne(targetEntity: Content::class, inversedBy: 'fields')] + #[ORM\JoinColumn(nullable: false)] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\Content $content = null; + #[ORM\Column(type: 'string')] + private ?string $name = null; + #[ORM\Column(type: 'text')] + private ?string $value = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/FileConfigDummy.php b/tests/Fixtures/TestBundle/Entity/FileConfigDummy.php index 64d2f4a9a5a..0cdd5053309 100644 --- a/tests/Fixtures/TestBundle/Entity/FileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Entity/FileConfigDummy.php @@ -17,34 +17,27 @@ /** * File Config Dummy. - * - * @ORM\Entity */ +#[ORM\Entity] class FileConfigDummy { - public const HYDRA_TITLE = 'File config Dummy'; - + final public const HYDRA_TITLE = 'File config Dummy'; /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] private $name; - /** * @var string - * - * @ORM\Column */ + #[ORM\Column] private $foo; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/FilterValidator.php b/tests/Fixtures/TestBundle/Entity/FilterValidator.php index 19c4df9d3f8..df13aaf2028 100644 --- a/tests/Fixtures/TestBundle/Entity/FilterValidator.php +++ b/tests/Fixtures/TestBundle/Entity/FilterValidator.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\ArrayItemsFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\BoundsFilter; @@ -29,26 +29,22 @@ * Filter Validator entity. * * @author Julien Deniau - * @ORM\Entity */ #[ApiResource(filters: [ArrayItemsFilter::class, BoundsFilter::class, EnumFilter::class, LengthFilter::class, MultipleOfFilter::class, PatternFilter::class, RequiredFilter::class, RequiredAllowEmptyFilter::class])] +#[ORM\Entity] class FilterValidator { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - /** - * @var string A name - * - * @ORM\Column - * @ApiProperty(iri="http://schema.org/name") - */ - private $name; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + #[ApiProperty(types: ["http://schema.org/name"]) + #[ORM\Column] + private string $name; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/FlexConfig.php b/tests/Fixtures/TestBundle/Entity/FlexConfig.php index 7a3a33f8ebd..88669290ebd 100644 --- a/tests/Fixtures/TestBundle/Entity/FlexConfig.php +++ b/tests/Fixtures/TestBundle/Entity/FlexConfig.php @@ -17,16 +17,13 @@ /** * This entity is configure in tests/Fixtures/app/config/api_platform/flex.yaml. - * - * @ORM\Entity */ +#[ORM\Entity] class FlexConfig { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Foo.php b/tests/Fixtures/TestBundle/Entity/Foo.php index a05d8231630..242a4b3180f 100644 --- a/tests/Fixtures/TestBundle/Entity/Foo.php +++ b/tests/Fixtures/TestBundle/Entity/Foo.php @@ -28,30 +28,27 @@ * Foo. * * @author Vincent Chalamon - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new GetCollection(uriTemplate: 'custom_collection_desc_foos', order: ['name' => 'DESC']), new GetCollection(uriTemplate: 'custom_collection_asc_foos', order: ['name' => 'ASC'])], graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query', paginationEnabled: false), new Mutation(name: 'create'), new Mutation(name: 'delete')], order: ['bar', 'name' => 'DESC'])] +#[ORM\Entity] class Foo { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The foo name - * - * @ORM\Column */ + #[ORM\Column] private $name; /** * @var string The foo bar - * - * @ORM\Column */ + #[ORM\Column] private $bar; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/FooDummy.php b/tests/Fixtures/TestBundle/Entity/FooDummy.php index dc552de8858..f86d52590a0 100644 --- a/tests/Fixtures/TestBundle/Entity/FooDummy.php +++ b/tests/Fixtures/TestBundle/Entity/FooDummy.php @@ -21,31 +21,28 @@ * FooDummy. * * @author Vincent Chalamon - * @ORM\Entity */ #[ApiResource(graphQlOperations: [new QueryCollection(name: 'collection_query', paginationType: 'page')], order: ['dummy.name'])] +#[ORM\Entity] class FooDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The foo name - * - * @ORM\Column */ + #[ORM\Column] private $name; /** * @var Dummy|null The foo dummy - * - * @ORM\ManyToOne(targetEntity="Dummy", cascade={"persist"}) */ - private $dummy; + #[ORM\ManyToOne(targetEntity: 'Dummy', cascade: ['persist'])] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy $dummy = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/FourthLevel.php b/tests/Fixtures/TestBundle/Entity/FourthLevel.php index 025483000cb..40bdbe77ef8 100644 --- a/tests/Fixtures/TestBundle/Entity/FourthLevel.php +++ b/tests/Fixtures/TestBundle/Entity/FourthLevel.php @@ -23,7 +23,6 @@ * Fourth Level. * * @author Alan Poulain - * @ORM\Entity */ #[ApiResource] #[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] @@ -32,26 +31,20 @@ #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/third_levels/{id}/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel::class, identifiers: ['id'], fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ORM\Entity] class FourthLevel { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ - private $id; - /** - * @var int - * - * @ORM\Column(type="integer") - * @Groups({"barcelona", "chicago"}) - */ - private $level = 4; - /** - * @ORM\OneToMany(targetEntity=ThirdLevel::class, cascade={"persist"}, mappedBy="badFourthLevel") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] + private ?int $id = null; + #[ORM\Column(type: 'integer')] + #[Groups(['barcelona', 'chicago'])] + private int $level = 4; + #[ORM\OneToMany(targetEntity: ThirdLevel::class, cascade: ['persist'], mappedBy: 'badFourthLevel')] public $badThirdLevel; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/Greeting.php b/tests/Fixtures/TestBundle/Entity/Greeting.php index 43ee83c3c84..bb837e60f26 100644 --- a/tests/Fixtures/TestBundle/Entity/Greeting.php +++ b/tests/Fixtures/TestBundle/Entity/Greeting.php @@ -18,32 +18,22 @@ use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] #[ApiResource(uriTemplate: '/people/{id}/sent_greetings.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Person::class, identifiers: ['id'], toProperty: 'sender')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class Greeting { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** - * @ORM\Column - */ + #[ORM\Column] public $message = ''; - /** - * @ORM\ManyToOne(targetEntity="Person", inversedBy="sentGreetings") - * @ORM\JoinColumn(name="sender_id") - */ + #[ORM\ManyToOne(targetEntity: 'Person', inversedBy: 'sentGreetings')] + #[ORM\JoinColumn(name: 'sender_id')] public $sender; - /** - * @ORM\ManyToOne(targetEntity="Person") - * @ORM\JoinColumn(name="recipient_id", nullable=true) - */ + #[ORM\ManyToOne(targetEntity: 'Person')] + #[ORM\JoinColumn(name: 'recipient_id', nullable: true)] public $recipient; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/InitializeInput.php b/tests/Fixtures/TestBundle/Entity/InitializeInput.php index 1390c990f90..6e571a53a50 100644 --- a/tests/Fixtures/TestBundle/Entity/InitializeInput.php +++ b/tests/Fixtures/TestBundle/Entity/InitializeInput.php @@ -17,23 +17,15 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(input: InitializeInputDto::class)] +#[ORM\Entity] class InitializeInput { - /** - * @ORM\Id - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] public $id; - /** - * @ORM\Column - */ + #[ORM\Column] public $manager; - /** - * @ORM\Column - */ + #[ORM\Column] public $name; } diff --git a/tests/Fixtures/TestBundle/Entity/InternalUser.php b/tests/Fixtures/TestBundle/Entity/InternalUser.php index a5cebccf664..065545f6787 100644 --- a/tests/Fixtures/TestBundle/Entity/InternalUser.php +++ b/tests/Fixtures/TestBundle/Entity/InternalUser.php @@ -15,14 +15,10 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class InternalUser extends AbstractUser { - /** - * @ORM\Column - */ + #[ORM\Column] private $internalId; public function getInternalId(): ?string diff --git a/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php b/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php index a1daec613d4..a944232e7da 100644 --- a/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php +++ b/tests/Fixtures/TestBundle/Entity/IriOnlyDummy.php @@ -20,25 +20,20 @@ * Dummy with iri_only. * * @author Pierre Thibaudeau - * @ORM\Entity */ #[ApiResource(normalizationContext: ['iri_only' => true, 'jsonld_embed_context' => true])] +#[ORM\Entity] class IriOnlyDummy { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - /** - * @var string - * - * @ORM\Column(type="string") - */ - private $foo; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string')] + private ?string $foo = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php b/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php index b1fc55f356b..8058c9a9714 100644 --- a/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php +++ b/tests/Fixtures/TestBundle/Entity/JsonldContextDummy.php @@ -13,40 +13,32 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Jsonld Context Dummy. - * - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class JsonldContextDummy { /** * @var int The id - * - * @ApiProperty(identifier=true) - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ApiProperty(identifier: true)] + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + /** * @var string The dummy person - * - * @ApiProperty( - * attributes={ - * "jsonld_context"={ - * "@id"="http://example.com/id", - * "@type"="@id", - * "foo"="bar" - * } - * }, - * ) */ + #[ApiProperty( + jsonldContext: ['@id' => 'https://example.com/id', '@type' => '@id', 'foo' => 'bar'] + )] private $person; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php b/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php index 634d8cf2324..9818381d137 100644 --- a/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/LegacySecuredDummy.php @@ -27,39 +27,32 @@ * Secured resource with legacy access_control attribute. * * @author Vincent Chalamon - * @ORM\Entity */ #[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Mutation(name: 'delete'), new Mutation(name: 'update', security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] +#[ORM\Entity] class LegacySecuredDummy { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The title - * - * @ORM\Column - * @Assert\NotBlank */ - private $title; + #[ORM\Column] + #[Assert\NotBlank] + private ?string $title = null; /** * @var string The description - * - * @ORM\Column */ - private $description = ''; + #[ORM\Column] + private string $description = ''; /** * @var string The owner - * - * @ORM\Column - * @Assert\NotBlank */ - private $owner; + #[ORM\Column] + #[Assert\NotBlank] + private ?string $owner = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php index d3fdda9dabf..68145c42e65 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php @@ -13,40 +13,33 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\MaxDepth; /** - * * - * - * @ORM\Entity - * * @author Brian Fox */ #[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] +#[ORM\Entity] class MaxDepthDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"default"}) - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['default'])] private $id; - /** - * @ORM\Column(name="name", type="string", length=30) - * @Groups({"default"}) - */ + + #[ORM\Column(name: 'name', type: 'string', length: 30)] + #[Groups(['default'])] public $name; - /** - * @ORM\ManyToOne(targetEntity="MaxDepthDummy", cascade={"persist"}) - * @ApiProperty(attributes={"fetch_eager"=false}) - * @Groups({"default"}) - * @MaxDepth(1) - */ + + #[ApiProperty(fetchEager: false)] + #[ORM\ManyToOne(targetEntity: 'MaxDepthDummy', cascade: ['persist'])] + #[Groups(['default'])] + #[MaxDepth(1)] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php index 4b53f92f044..decfa604b06 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php @@ -21,30 +21,24 @@ /** * * * - * @ORM\Entity * * @author Brian Fox */ #[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] +#[ORM\Entity] class MaxDepthEagerDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"default"}) - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['default'])] private $id; - /** - * @ORM\Column(name="name", type="string", length=30) - * @Groups({"default"}) - */ + #[ORM\Column(name: 'name', type: 'string', length: 30)] + #[Groups(['default'])] public $name; - /** - * @ORM\ManyToOne(targetEntity="MaxDepthEagerDummy", cascade={"persist"}) - * @Groups({"default"}) - * @MaxDepth(1) - */ + #[ORM\ManyToOne(targetEntity: 'MaxDepthEagerDummy', cascade: ['persist'])] + #[Groups(['default'])] + #[MaxDepth(1)] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php b/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php index fd620196e76..9b3ba1d9bd7 100644 --- a/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php +++ b/tests/Fixtures/TestBundle/Entity/MessengerWithInput.php @@ -13,20 +13,21 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Mutation; +use ApiPlatform\Symfony\Messenger\Processor; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerInput; -#[ApiResource(graphQlOperations: [new Mutation(name: 'create', input: MessengerInput::class, messenger: 'input')], messenger: 'input', input: MessengerInput::class)] +#[ApiResource( + graphQlOperations: [new Mutation(name: 'create', input: MessengerInput::class, processor: Processor::class)], + processor: Processor::class, + input: MessengerInput::class +)] class MessengerWithInput { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public $id; - /** - * @var string - */ - public $name; + + public string $name; } diff --git a/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php b/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php index ad646783331..8086fbadc26 100644 --- a/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php +++ b/tests/Fixtures/TestBundle/Entity/MessengerWithResponse.php @@ -13,19 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Symfony\Messenger\Processor; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\MessengerResponseInput; -#[ApiResource(messenger: 'input', input: MessengerResponseInput::class)] +#[ApiResource(processor: Processor::class, input: MessengerResponseInput::class)] class MessengerWithResponse { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public $id; - /** - * @var string - */ - public $name; + + public string $name; } diff --git a/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php b/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php index ff50defbe9c..a53282c9343 100644 --- a/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php @@ -19,22 +19,16 @@ use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] #[ApiResource(uriTemplate: '/network_path_relation_dummies/{id}/network_path_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\NetworkPathRelationDummy::class, identifiers: ['id'], toProperty: 'networkPathRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::NET_PATH, operations: [new GetCollection()])] +#[ORM\Entity] class NetworkPathDummy { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** - * @ORM\ManyToOne(targetEntity="NetworkPathRelationDummy", inversedBy="networkPathDummies") - */ + #[ORM\ManyToOne(targetEntity: 'NetworkPathRelationDummy', inversedBy: 'networkPathDummies')] public $networkPathRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php b/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php index 18beb3cb3da..aaef9ffd342 100644 --- a/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php @@ -18,21 +18,15 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] +#[ORM\Entity] class NetworkPathRelationDummy { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** - * @ORM\OneToMany(targetEntity="NetworkPathDummy", mappedBy="networkPathRelationDummy") - */ + #[ORM\OneToMany(targetEntity: 'NetworkPathDummy', mappedBy: 'networkPathRelationDummy')] public $networkPathDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php b/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php index 41a31d1a036..267c42a88ac 100644 --- a/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NoCollectionDummy.php @@ -22,20 +22,18 @@ /** * No Collection Dummy. - * - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete()])] +#[ORM\Entity] class NoCollectionDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/NonRelationResource.php b/tests/Fixtures/TestBundle/Entity/NonRelationResource.php index c2660b9cb74..00b4d656b20 100644 --- a/tests/Fixtures/TestBundle/Entity/NonRelationResource.php +++ b/tests/Fixtures/TestBundle/Entity/NonRelationResource.php @@ -17,17 +17,13 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Dto\NonResourceClass; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class NonRelationResource { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** * @var NonResourceClass diff --git a/tests/Fixtures/TestBundle/Entity/OperationResource.php b/tests/Fixtures/TestBundle/Entity/OperationResource.php index 5fe30a480c9..955a72d204f 100644 --- a/tests/Fixtures/TestBundle/Entity/OperationResource.php +++ b/tests/Fixtures/TestBundle/Entity/OperationResource.php @@ -23,34 +23,17 @@ use ApiPlatform\Tests\Fixtures\TestBundle\State\OperationResourceProcessor; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(normalizationContext: ['skip_null_values' => true], processor: OperationResourceProcessor::class)] #[Get] #[Patch(inputFormats: ['json' => ['application/merge-patch+json']])] #[Post] #[Put] #[Delete] +#[ORM\Entity] class OperationResource { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ - #[ApiProperty(identifier: true)] - private $identifier; - - /** - * @var string - */ - public $name; - - public function __construct(int $identifier, string $name) + public function __construct(#[ApiProperty(identifier: true)] #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private readonly int $identifier, public string $name) { - $this->identifier = $identifier; - $this->name = $name; } public function getIdentifier() diff --git a/tests/Fixtures/TestBundle/Entity/Order.php b/tests/Fixtures/TestBundle/Entity/Order.php index 14ab8e8095d..ef60d9fc4a8 100644 --- a/tests/Fixtures/TestBundle/Entity/Order.php +++ b/tests/Fixtures/TestBundle/Entity/Order.php @@ -18,34 +18,24 @@ use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ORM\Entity - * @ORM\Table (name="`order`") - */ #[ApiResource(normalizationContext: ['groups' => ['order_read']], forceEager: false)] +#[ORM\Entity] +#[ORM\Table(name: '`order`')] class Order { - /** - * @var int - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"order_read"}) - */ - private $id; - /** - * @ORM\ManyToOne(targetEntity="Customer") - * @ORM\JoinColumn(nullable=false) - * @Groups({"order_read"}) - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['order_read'])] + private ?int $id = null; + #[ORM\ManyToOne(targetEntity: 'Customer')] + #[ORM\JoinColumn(nullable: false)] + #[Groups(['order_read'])] public $customer; - /** - * @ORM\ManyToOne(targetEntity="Customer") - * @ORM\JoinColumn(nullable=false) - * @Assert\NotNull - * @Groups({"order_read"}) - */ + #[ORM\ManyToOne(targetEntity: 'Customer')] + #[ORM\JoinColumn(nullable: false)] + #[Assert\NotNull] + #[Groups(['order_read'])] public $recipient; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php b/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php index 56cb3521d79..5e4c28c9f96 100644 --- a/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/OverriddenOperationDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -28,48 +28,46 @@ * Overridden Operation Dummy. * * @author Amrouche Hamza - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Get(normalizationContext: ['groups' => ['overridden_operation_dummy_get']], denormalizationContext: ['groups' => ['overridden_operation_dummy_get']]), new Put(normalizationContext: ['groups' => ['overridden_operation_dummy_put']], denormalizationContext: ['groups' => ['overridden_operation_dummy_put']]), new Delete(), new GetCollection(), new Post(), new GetCollection(uriTemplate: '/override/swagger')], normalizationContext: ['groups' => ['overridden_operation_dummy_read']], denormalizationContext: ['groups' => ['overridden_operation_dummy_write']])] +#[ORM\Entity] class OverriddenOperationDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_write", "overridden_operation_dummy_get"}) - * @ApiProperty(iri="http://schema.org/name") */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get'])] private $name; + /** * @var string|null The dummy name alias - * - * @ORM\Column(nullable=true) - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_put", "overridden_operation_dummy_get"}) - * @ApiProperty(iri="https://schema.org/alternateName") */ + #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ORM\Column(nullable: true)] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_put', 'overridden_operation_dummy_get'])] private $alias; + /** * @var string|null A short description of the item - * - * @ORM\Column(nullable=true) - * @Groups({"overridden_operation_dummy_read", "overridden_operation_dummy_write", "overridden_operation_dummy_get", "overridden_operation_dummy_put"}) - * @ApiProperty(iri="https://schema.org/description") */ + #[ApiProperty(types: ['http://schema.org/description'])] + #[ORM\Column(nullable: true)] + #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get', 'overridden_operation_dummy_put'])] public $description; - /** - * @ORM\Column(nullable=true) - * @Groups({"overridden_operation_dummy_write"}) - */ + + #[ORM\Column(nullable: true)] + #[Groups(['overridden_operation_dummy_write'])] public $notGettable; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/PaginationEntity.php b/tests/Fixtures/TestBundle/Entity/PaginationEntity.php index 4f586bdf8d6..5281ca038d0 100644 --- a/tests/Fixtures/TestBundle/Entity/PaginationEntity.php +++ b/tests/Fixtures/TestBundle/Entity/PaginationEntity.php @@ -20,8 +20,6 @@ /** * ProviderEntity. - * - * @ORM\Entity */ #[ApiResource] #[Get] @@ -30,16 +28,13 @@ paginationItemsPerPage: 5, paginationMaximumItemsPerPage: 30 )] +#[ORM\Entity] class PaginationEntity { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Entity/ParentDummy.php b/tests/Fixtures/TestBundle/Entity/ParentDummy.php index 21f9c890a9b..185830f8cb0 100644 --- a/tests/Fixtures/TestBundle/Entity/ParentDummy.php +++ b/tests/Fixtures/TestBundle/Entity/ParentDummy.php @@ -20,17 +20,15 @@ * Parent Dummy. * * @author Kévin Dunglas - * - * @ORM\MappedSuperclass */ +#[ORM\MappedSuperclass] class ParentDummy { /** * @var int|null The age - * - * @ORM\Column(type="integer", nullable=true) - * @Groups({"friends"}) */ + #[ORM\Column(type: 'integer', nullable: true)] + #[Groups(['friends'])] private $age; public function getAge() diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummy.php b/tests/Fixtures/TestBundle/Entity/PatchDummy.php index b2adbd69c95..aaa4bb7c718 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummy.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummy.php @@ -22,19 +22,15 @@ /** * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()])] +#[ORM\Entity] class PatchDummy { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - /** - * @ORM\Column(nullable=true) - */ + #[ORM\Column(nullable: true)] public $name; } diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php index 1f0d8c2f103..221e39fc8af 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php @@ -23,21 +23,17 @@ /** * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] +#[ORM\Entity] class PatchDummyRelation { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - /** - * @ORM\ManyToOne(targetEntity="RelatedDummy") - * @Groups({"chicago"}) - */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[Groups(['chicago'])] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Entity/Payment.php b/tests/Fixtures/TestBundle/Entity/Payment.php index e800ac595e1..21d728d7d9a 100644 --- a/tests/Fixtures/TestBundle/Entity/Payment.php +++ b/tests/Fixtures/TestBundle/Entity/Payment.php @@ -20,34 +20,19 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Controller\Payment\VoidPaymentAction; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(operations: [new Get(), new Post(uriTemplate: '/payments/{id}/void', controller: VoidPaymentAction::class, deserialize: false), new Post(), new GetCollection()])] +#[ORM\Entity] class Payment { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var string - * - * @ORM\Column(type="decimal", precision=6, scale=2) - */ - private $amount; - /** - * @ORM\OneToOne(targetEntity=VoidPayment::class, mappedBy="payment") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\OneToOne(targetEntity: VoidPayment::class, mappedBy: 'payment')] private $voidPayment; - public function __construct(string $amount) + public function __construct(#[ORM\Column(type: 'decimal', precision: 6, scale: 2)] private readonly string $amount) { - $this->amount = $amount; } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/Person.php b/tests/Fixtures/TestBundle/Entity/Person.php index cde3eafc1c0..f53b1b484a6 100644 --- a/tests/Fixtures/TestBundle/Entity/Person.php +++ b/tests/Fixtures/TestBundle/Entity/Person.php @@ -23,32 +23,25 @@ * Person. * * @author Antoine Bluchet - * @ORM\Entity */ #[ApiResource(normalizationContext: ['groups' => ['people.pets']])] +#[ORM\Entity] class Person { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column(type="string") - * @Groups({"people.pets"}) - */ + #[ORM\Column(type: 'string')] + #[Groups(['people.pets'])] public $name; /** - * @ORM\OneToMany(targetEntity="PersonToPet", mappedBy="person") - * @Groups({"people.pets"}) - * * @var Collection */ + #[ORM\OneToMany(targetEntity: 'PersonToPet', mappedBy: 'person')] + #[Groups(['people.pets'])] public $pets; - /** - * @ORM\OneToMany(targetEntity="Greeting", mappedBy="sender") - */ + #[ORM\OneToMany(targetEntity: 'Greeting', mappedBy: 'sender')] public $sentGreetings; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/PersonToPet.php b/tests/Fixtures/TestBundle/Entity/PersonToPet.php index 9c9876577bd..8e098f5f91d 100644 --- a/tests/Fixtures/TestBundle/Entity/PersonToPet.php +++ b/tests/Fixtures/TestBundle/Entity/PersonToPet.php @@ -20,26 +20,23 @@ * PersonToPet. * * @author Antoine Bluchet - * @ORM\Entity */ +#[ORM\Entity] class PersonToPet { /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="Pet") - * @ORM\JoinColumn(referencedColumnName="id") - * @Groups({"people.pets"}) - * * @var Pet */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'Pet')] + #[ORM\JoinColumn(referencedColumnName: 'id')] + #[Groups(['people.pets'])] public $pet; - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="Person") - * @ORM\JoinColumn(referencedColumnName="id") - * * @var Person */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'Person')] + #[ORM\JoinColumn(referencedColumnName: 'id')] public $person; } diff --git a/tests/Fixtures/TestBundle/Entity/Pet.php b/tests/Fixtures/TestBundle/Entity/Pet.php index 6f3da59de4c..27ed27166c2 100644 --- a/tests/Fixtures/TestBundle/Entity/Pet.php +++ b/tests/Fixtures/TestBundle/Entity/Pet.php @@ -23,27 +23,22 @@ * Pet. * * @author Antoine Bluchet - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class Pet { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column(type="string") - * @Groups({"people.pets"}) - */ + #[ORM\Column(type: 'string')] + #[Groups(['people.pets'])] public $name; /** - * @ORM\OneToMany(targetEntity="PersonToPet", mappedBy="pet") - * * @var Collection */ + #[ORM\OneToMany(targetEntity: 'PersonToPet', mappedBy: 'pet')] public $people; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php b/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php index aa117fc2746..398460c59a0 100644 --- a/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php +++ b/tests/Fixtures/TestBundle/Entity/PlainObjectDummy.php @@ -20,16 +20,14 @@ * Regression test for https://github.com/api-platform/api-platform/issues/1085. * * @author Antoine Bluchet - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class PlainObjectDummy { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** * @var string @@ -43,7 +41,7 @@ class PlainObjectDummy public function setContent($content) { $this->content = $content; - $this->data = (array) json_decode($content); + $this->data = (array) json_decode($content, null, 512, \JSON_THROW_ON_ERROR); } public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ProcessorEntity.php b/tests/Fixtures/TestBundle/Entity/ProcessorEntity.php index 8264bbb95cd..76e8a3d737a 100644 --- a/tests/Fixtures/TestBundle/Entity/ProcessorEntity.php +++ b/tests/Fixtures/TestBundle/Entity/ProcessorEntity.php @@ -21,30 +21,21 @@ /** * ProcessorEntity. - * - * @ORM\Entity */ #[ApiResource] #[Get] #[Post] +#[ORM\Entity] class ProcessorEntity { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column - * @Assert\NotBlank - */ - private $foo; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + #[ORM\Column] + #[Assert\NotBlank] + private ?string $foo = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Entity/Product.php b/tests/Fixtures/TestBundle/Entity/Product.php index 5d101978b2f..f1c75a2ec0b 100644 --- a/tests/Fixtures/TestBundle/Entity/Product.php +++ b/tests/Fixtures/TestBundle/Entity/Product.php @@ -17,33 +17,17 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class Product implements ProductInterface { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column(type="string", unique=true) - */ - private $code; - - /** - * @var Taxon|null - * - * @ORM\ManyToOne(targetEntity=Taxon::class) - */ - private $mainTaxon; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string', unique: true)] + private ?string $code = null; + #[ORM\ManyToOne(targetEntity: Taxon::class)] + private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\Taxon $mainTaxon = null; /** * {@inheritdoc} diff --git a/tests/Fixtures/TestBundle/Entity/Program.php b/tests/Fixtures/TestBundle/Entity/Program.php index 5a6f3ea60ef..fc87e7ad4cc 100644 --- a/tests/Fixtures/TestBundle/Entity/Program.php +++ b/tests/Fixtures/TestBundle/Entity/Program.php @@ -17,32 +17,20 @@ /** * @author Vincent Chalamon - * - * @ORM\Entity */ +#[ORM\Entity] class Program { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - - /** - * @ORM\Column - */ + #[ORM\Column] public $name; - - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: 'datetime')] public $date; - - /** - * @ORM\ManyToOne(targetEntity=User::class) - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: User::class)] + #[ORM\JoinColumn(nullable: false)] public $author; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/ProviderEntity.php b/tests/Fixtures/TestBundle/Entity/ProviderEntity.php index cfa498dbdbc..f5a1c4012a5 100644 --- a/tests/Fixtures/TestBundle/Entity/ProviderEntity.php +++ b/tests/Fixtures/TestBundle/Entity/ProviderEntity.php @@ -22,31 +22,22 @@ /** * ProviderEntity. - * - * @ORM\Entity */ #[ApiResource] #[Get] #[GetCollection] #[Post] +#[ORM\Entity] class ProviderEntity { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column - * @Assert\NotBlank - */ - private $foo; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + #[ORM\Column] + #[Assert\NotBlank] + private ?string $foo = null; /** * @return int diff --git a/tests/Fixtures/TestBundle/Entity/Question.php b/tests/Fixtures/TestBundle/Entity/Question.php index 50f6ac0f549..09949775e3b 100644 --- a/tests/Fixtures/TestBundle/Entity/Question.php +++ b/tests/Fixtures/TestBundle/Entity/Question.php @@ -19,28 +19,20 @@ use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] #[ApiResource(uriTemplate: '/answers/{id}/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer::class, identifiers: ['id'], toProperty: 'answer')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/questions/{id}/answer/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], fromProperty: 'answer'), 'answer' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Answer::class, identifiers: [], expandedValue: 'answer', toProperty: 'answer')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class Question { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column(nullable=true) - */ + #[ORM\Column(nullable: true)] private $content; - /** - * @ORM\OneToOne(targetEntity="Answer", inversedBy="question") - * @ORM\JoinColumn(name="answer_id", referencedColumnName="id", unique=true) - */ + #[ORM\OneToOne(targetEntity: 'Answer', inversedBy: 'question')] + #[ORM\JoinColumn(name: 'answer_id', referencedColumnName: 'id', unique: true)] private $answer; /** @@ -73,8 +65,6 @@ public function getId(): ?int /** * Set answer. - * - * @param Answer $answer */ public function setAnswer(Answer $answer = null): self { diff --git a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php index d19baeadecb..b42c9236a82 100644 --- a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php @@ -18,25 +18,15 @@ use Ramsey\Uuid\Uuid; use Ramsey\Uuid\UuidInterface; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class RamseyUuidDummy { - /** - * @var \Ramsey\Uuid\UuidInterface - * - * @ORM\Id - * @ORM\Column(type="uuid", unique=true) - */ - private $id; - /** - * @var \Ramsey\Uuid\UuidInterface|null - * - * @ORM\Column(type="uuid", nullable=true) - */ - private $other; + #[ORM\Id] + #[ORM\Column(type: 'uuid', unique: true)] + private readonly \Ramsey\Uuid\UuidInterface $id; + #[ORM\Column(type: 'uuid', nullable: true)] + private ?\Ramsey\Uuid\UuidInterface $other = null; public function __construct(?UuidInterface $id = null) { diff --git a/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php b/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php index f6fe92e3676..7e3d5832441 100644 --- a/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php +++ b/tests/Fixtures/TestBundle/Entity/ReadableOnlyProperty.php @@ -13,31 +13,28 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class ReadableOnlyProperty { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + /** * @var string The foo name - * - * @ORM\Column - * @ApiProperty(writable=false) */ - private $name; + #[ApiProperty(writable: false)] + #[ORM\Column] + private readonly string $name; public function __construct() { @@ -49,7 +46,7 @@ public function getId() return $this->id; } - public function setName($name) + public function setName($name): never { throw new \Exception('Can not write name.'); } diff --git a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php index 42b742ed381..5cbbf05a777 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; @@ -30,7 +30,6 @@ * Related Dummy. * * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'])] #[ApiResource(uriTemplate: '/dummies/{id}/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] @@ -40,59 +39,55 @@ #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ORM\Entity] class RelatedDummy extends ParentDummy { - /** - * @ApiProperty(writable=false) - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"chicago", "friends"}) - */ + #[ApiProperty(writable: false)] + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['chicago', 'friends'])] private $id; + /** * @var string|null A name - * - * @ORM\Column(nullable=true) - * @Groups({"friends"}) */ + #[ORM\Column(nullable: true)] + #[Groups(['friends'])] public $name; - /** - * @ORM\Column - * @Groups({"barcelona", "chicago", "friends"}) - */ + + #[ORM\Column] + #[Groups(['barcelona', 'chicago', 'friends'])] protected $symfony = 'symfony'; + /** * @var \DateTime|null A dummy date - * - * @ORM\Column(type="datetime", nullable=true) - * @Assert\DateTime - * @Groups({"friends"}) */ + #[ORM\Column(type: 'datetime', nullable: true)] + #[Assert\DateTime] + #[Groups(['friends'])] public $dummyDate; - /** - * @ORM\ManyToOne(targetEntity="ThirdLevel", cascade={"persist"}) - * @Groups({"barcelona", "chicago", "friends"}) - */ + + #[ORM\ManyToOne(targetEntity: 'ThirdLevel', cascade: ['persist'])] + #[Groups(['barcelona', 'chicago', 'friends'])] public $thirdLevel; - /** - * @ORM\OneToMany(targetEntity="RelatedToDummyFriend", cascade={"persist"}, mappedBy="relatedDummy") - * @Groups({"fakemanytomany", "friends"}) - */ + + #[ORM\OneToMany(targetEntity: 'RelatedToDummyFriend', cascade: ['persist'], mappedBy: 'relatedDummy')] + #[Groups(['fakemanytomany', 'friends'])] public $relatedToDummyFriend; + /** * @var bool|null A dummy bool - * - * @ORM\Column(type="boolean", nullable=true) - * @Groups({"friends"}) */ + #[ORM\Column(type: 'boolean', nullable: true)] + #[Groups(['friends'])] public $dummyBoolean; + /** * @var EmbeddableDummy - * - * @ORM\Embedded(class="EmbeddableDummy") - * @Groups({"friends"}) */ + #[ORM\Embedded(class: 'EmbeddableDummy')] + #[Groups(['friends'])] public $embeddedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php index 4582a2a3da6..56216cdd0a1 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -25,35 +25,33 @@ * Related to Normalized Dummy. * * @author Amrouche Hamza - * @ORM\Entity */ #[ApiResource(normalizationContext: ['groups' => ['related_output', 'output']], denormalizationContext: ['groups' => ['related_input', 'input']])] +#[ORM\Entity] class RelatedNormalizedDummy { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"related_output", "related_input"}) */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + #[Groups(['related_output', 'related_input'])] + private ?int $id = null; + /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"related_output", "related_input"}) */ - private $name; + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['related_output', 'related_input'])] + private ?string $name = null; /** * @var Collection Several Normalized dummies - * - * @ORM\ManyToMany(targetEntity="CustomNormalizedDummy") - * @Groups({"related_output", "related_input"}) */ + #[ORM\ManyToMany(targetEntity: 'CustomNormalizedDummy')] + #[Groups(['related_output', 'related_input'])] public $customNormalizedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php index f2ebf4bfc81..f13139a6150 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php @@ -21,28 +21,25 @@ * Related Owned Dummy. * * @author Sergey V. Ryabov - * @ORM\Entity */ #[ApiResource(types: ['https://schema.org/Product'])] +#[ORM\Entity] class RelatedOwnedDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** * @var string|null A name - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $name; /** * @var \Dummy - * @ORM\OneToOne(targetEntity="Dummy", cascade={"persist"}, inversedBy="relatedOwnedDummy") - * @ORM\JoinColumn(nullable=false) */ + #[ORM\OneToOne(targetEntity: 'Dummy', cascade: ['persist'], inversedBy: 'relatedOwnedDummy')] + #[ORM\JoinColumn(nullable: false)] public $owningDummy; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php index 13c7aa45f51..b11b684a2f0 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php @@ -21,27 +21,24 @@ * Related Owning Dummy. * * @author Sergey V. Ryabov - * @ORM\Entity */ #[ApiResource(types: ['https://schema.org/Product'])] +#[ORM\Entity] class RelatedOwningDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** * @var string|null A name - * - * @ORM\Column(nullable=true) */ + #[ORM\Column(nullable: true)] public $name; /** * @var \Dummy|null - * @ORM\OneToOne(targetEntity="Dummy", cascade={"persist"}, mappedBy="relatedOwningDummy") */ + #[ORM\OneToOne(targetEntity: 'Dummy', cascade: ['persist'], mappedBy: 'relatedOwningDummy')] public $ownedDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php index 07c8ec01f1c..f18abb68506 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedSecuredDummy.php @@ -20,19 +20,16 @@ use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_ADMIN\')'), new GetCollection(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\')'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')')], security: 'is_granted(\'ROLE_ADMIN\')')] +#[ORM\Entity] class RelatedSecuredDummy { /** * @var int - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php b/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php index df9155b59f1..108c343108a 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Link; @@ -23,8 +23,6 @@ /** * Related To Dummy Friend represent an association table for a manytomany relation. - * - * @ORM\Entity */ #[ApiResource(normalizationContext: ['groups' => ['fakemanytomany']], filters: ['related_to_dummy_friend.name'])] #[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] @@ -32,38 +30,33 @@ #[ApiResource(uriTemplate: '/related_dummies/{id}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ORM\Entity] class RelatedToDummyFriend { /** * @var string The dummy name - * - * @ORM\Column - * @Assert\NotBlank - * @ApiProperty(iri="http://schema.org/name") - * @Groups({"fakemanytomany", "friends"}) */ + #[ApiProperty(types: ['http://schema.org/name'])] + #[ORM\Column] + #[Assert\NotBlank] + #[Groups(['fakemanytomany', 'friends'])] private $name; /** * @var string|null The dummy description - * - * @ORM\Column(nullable=true) - * @Groups({"fakemanytomany", "friends"}) - */ - private $description; - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="DummyFriend") - * @ORM\JoinColumn(name="dummyfriend_id", referencedColumnName="id", nullable=false) - * @Groups({"fakemanytomany", "friends"}) - * @Assert\NotNull */ + #[ORM\Column(nullable: true)] + #[Groups(['fakemanytomany', 'friends'])] + private ?string $description = null; + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'DummyFriend')] + #[ORM\JoinColumn(name: 'dummyfriend_id', referencedColumnName: 'id', nullable: false)] + #[Groups(['fakemanytomany', 'friends'])] + #[Assert\NotNull] private $dummyFriend; - /** - * @ORM\Id - * @ORM\ManyToOne(targetEntity="RelatedDummy", inversedBy="relatedToDummyFriend") - * @ORM\JoinColumn(name="relateddummy_id", referencedColumnName="id", nullable=false, onDelete="CASCADE") - * @Assert\NotNull - */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: 'RelatedDummy', inversedBy: 'relatedToDummyFriend')] + #[ORM\JoinColumn(name: 'relateddummy_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] + #[Assert\NotNull] private $relatedDummy; public function setName($name) diff --git a/tests/Fixtures/TestBundle/Entity/Relation1.php b/tests/Fixtures/TestBundle/Entity/Relation1.php index 91a7ca1025f..501347320b5 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation1.php +++ b/tests/Fixtures/TestBundle/Entity/Relation1.php @@ -17,21 +17,16 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity - * * @author Kévin Dunglas */ #[ApiResource] +#[ORM\Entity] class Relation1 { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] public $id; - /** - * @ORM\ManyToOne(targetEntity="Relation2", inversedBy="relation1s") - */ + #[ORM\ManyToOne(targetEntity: 'Relation2', inversedBy: 'relation1s')] public $relation2; } diff --git a/tests/Fixtures/TestBundle/Entity/Relation2.php b/tests/Fixtures/TestBundle/Entity/Relation2.php index 61eba9f2c37..61597d71a30 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation2.php +++ b/tests/Fixtures/TestBundle/Entity/Relation2.php @@ -18,22 +18,17 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity - * * @author Kévin Dunglas */ #[ApiResource] +#[ORM\Entity] class Relation2 { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] public $id; - /** - * @ORM\OneToMany(targetEntity="Relation1", mappedBy="relation2") - */ + #[ORM\OneToMany(targetEntity: 'Relation1', mappedBy: 'relation2')] public $relation1s; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/Relation3.php b/tests/Fixtures/TestBundle/Entity/Relation3.php index dd73e75f8ac..dd7acd4e412 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation3.php +++ b/tests/Fixtures/TestBundle/Entity/Relation3.php @@ -18,23 +18,19 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class Relation3 { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] public $id; /** * @var Collection - * @ORM\ManyToMany(targetEntity="Relation2", orphanRemoval=true) */ - private $relation2s; + #[ORM\ManyToMany(targetEntity: 'Relation2', orphanRemoval: true)] + private readonly \Doctrine\Common\Collections\Collection $relation2s; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php index 050719faf69..8eb6cc79e06 100644 --- a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php @@ -26,36 +26,26 @@ * Relation Embedder. * * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(routeName: 'relation_embedded.custom_get'), new Get(uriTemplate: '/api/custom-call/{id}'), new Put(uriTemplate: '/api/custom-call/{id}'), new Post(), new GetCollection()], normalizationContext: ['groups' => ['barcelona']], denormalizationContext: ['groups' => ['chicago']], hydraContext: ['@type' => 'hydra:Operation', 'hydra:title' => 'A custom operation', 'returns' => 'xmls:string'])] +#[ORM\Entity] class RelationEmbedder { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - /** - * @ORM\Column - * @Groups({"chicago"}) - */ + #[ORM\Column] + #[Groups(['chicago'])] public $paris = 'Paris'; - /** - * @ORM\Column - * @Groups({"barcelona", "chicago"}) - */ + #[ORM\Column] + #[Groups(['barcelona', 'chicago'])] public $krondstadt = 'Krondstadt'; - /** - * @ORM\ManyToOne(targetEntity="RelatedDummy", cascade={"persist"}) - * @Groups({"chicago", "barcelona"}) - */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy', cascade: ['persist'])] + #[Groups(['chicago', 'barcelona'])] public $anotherRelated; - /** - * @ORM\ManyToOne(targetEntity="RelatedDummy") - * @Groups({"barcelona", "chicago"}) - */ + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[Groups(['barcelona', 'chicago'])] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php b/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php index 9de3fa686f6..c4c65f0b1fa 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithBoolean.php @@ -16,26 +16,19 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class ResourceWithBoolean { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var bool - * - * @ORM\Column(type="boolean") */ - private $myBooleanField = false; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'boolean')] + private bool $myBooleanField = false; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php b/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php index 1d7233deab2..026263a354d 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithFloat.php @@ -16,26 +16,19 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class ResourceWithFloat { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var float - * - * @ORM\Column(type="float") */ - private $myFloatField = 0.0; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'float')] + private float $myFloatField = 0.0; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php b/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php index bdb495bbd62..c9221df653a 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithInteger.php @@ -16,26 +16,19 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class ResourceWithInteger { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var int - * - * @ORM\Column(type="integer") */ - private $myIntegerField = 0; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'integer')] + private int $myIntegerField = 0; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/ResourceWithString.php b/tests/Fixtures/TestBundle/Entity/ResourceWithString.php index 0bd096ed0de..731edc28985 100644 --- a/tests/Fixtures/TestBundle/Entity/ResourceWithString.php +++ b/tests/Fixtures/TestBundle/Entity/ResourceWithString.php @@ -16,26 +16,19 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class ResourceWithString { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var string - * - * @ORM\Column(type="string") */ - private $myStringField = ''; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string')] + private string $myStringField = ''; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/SecuredDummy.php b/tests/Fixtures/TestBundle/Entity/SecuredDummy.php index 19010291638..c82f789baaa 100644 --- a/tests/Fixtures/TestBundle/Entity/SecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SecuredDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; @@ -31,113 +31,106 @@ * Secured resource. * * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(security: 'is_granted(\'ROLE_USER\') or is_granted(\'ROLE_ADMIN\')'), new GetCollection(uriTemplate: 'custom_data_provider_generator', security: 'is_granted(\'ROLE_USER\')'), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\') or (is_granted(\'ROLE_USER\') and object.getOwner() == user)'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')'), new Mutation(name: 'delete'), new Mutation(name: 'update', securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] +#[ORM\Entity] class SecuredDummy { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + /** * @var string The title - * - * @ORM\Column - * @Assert\NotBlank */ - private $title; + #[ORM\Column] + #[Assert\NotBlank] + private ?string $title = null; + /** * @var string The description - * - * @ORM\Column */ - private $description = ''; + #[ORM\Column] + private string $description = ''; + /** * @var string The dummy secret property, only readable/writable by specific users - * - * @ORM\Column - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ - private $adminOnlyProperty = ''; + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ORM\Column] + private ?string $adminOnlyProperty = ''; + /** * @var string Secret property, only readable/writable by owners - * - * @ORM\Column - * @ApiProperty( - * security="object == null or object.getOwner() == user", - * securityPostDenormalize="object.getOwner() == user", - * ) */ - private $ownerOnlyProperty = ''; + #[ApiProperty(security: 'object == null or object.getOwner() == user', securityPostDenormalize: 'object.getOwner() == user')] + #[ORM\Column] + private ?string $ownerOnlyProperty = ''; + /** * @var string The owner - * - * @ORM\Column - * @Assert\NotBlank */ - private $owner; + #[ORM\Column] + #[Assert\NotBlank] + private ?string $owner = null; + /** * A collection of dummies that only admins can access. * * @var Collection Several dummies - * - * @ORM\ManyToMany(targetEntity="RelatedDummy") - * @ORM\JoinTable(name="secured_dummy_related_dummy") - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] + #[ORM\JoinTable(name: 'secured_dummy_related_dummy')] public $relatedDummies; + /** * A dummy that only admins can access. * * @var RelatedDummy|null - * - * @ORM\ManyToOne(targetEntity="RelatedDummy") - * @ORM\JoinColumn(name="related_dummy_id") - * @ApiProperty(security="is_granted('ROLE_ADMIN')") */ + #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[ORM\JoinColumn(name: 'related_dummy_id')] protected $relatedDummy; + /** * A collection of dummies that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies - * - * @ORM\ManyToMany(targetEntity="RelatedSecuredDummy") - * @ORM\JoinTable(name="secured_dummy_related_secured_dummy") - * @ApiProperty(security="is_granted('ROLE_USER')") */ + #[ApiProperty(security: "is_granted('ROLE_USER')")] + #[ORM\ManyToMany(targetEntity: 'RelatedSecuredDummy')] + #[ORM\JoinTable(name: 'secured_dummy_related_secured_dummy')] public $relatedSecuredDummies; + /** * A dummy that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy|null - * - * @ORM\ManyToOne(targetEntity="RelatedSecuredDummy") - * @ORM\JoinColumn(name="related_secured_dummy_id") - * @ApiProperty(security="is_granted('ROLE_USER')") */ + #[ApiProperty(security: "is_granted('ROLE_USER')")] + #[ORM\ManyToOne(targetEntity: 'RelatedSecuredDummy')] + #[ORM\JoinColumn(name: 'related_secured_dummy_id')] protected $relatedSecuredDummy; + /** * Collection of dummies that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies - * - * @ORM\ManyToMany(targetEntity="RelatedSecuredDummy") - * @ORM\JoinTable(name="secured_dummy_public_related_secured_dummy") */ + #[ORM\ManyToMany(targetEntity: 'RelatedSecuredDummy')] + #[ORM\JoinTable(name: 'secured_dummy_public_related_secured_dummy')] public $publicRelatedSecuredDummies; + /** * A dummy that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy|null - * - * @ORM\ManyToOne(targetEntity="RelatedSecuredDummy") - * @ORM\JoinColumn(name="public_related_secured_dummy_id") */ + #[ORM\ManyToOne(targetEntity: 'RelatedSecuredDummy')] + #[ORM\JoinColumn(name: 'public_related_secured_dummy_id')] protected $publicRelatedSecuredDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/SingleFileConfigDummy.php b/tests/Fixtures/TestBundle/Entity/SingleFileConfigDummy.php index b139fadd149..1299c20bd56 100644 --- a/tests/Fixtures/TestBundle/Entity/SingleFileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SingleFileConfigDummy.php @@ -17,25 +17,21 @@ /** * File Config Dummy. - * - * @ORM\Entity */ +#[ORM\Entity] class SingleFileConfigDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; - + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The dummy name - * - * @ORM\Column */ + #[ORM\Column] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Site.php b/tests/Fixtures/TestBundle/Entity/Site.php index 40963c1edf7..1dcfdd5d35f 100644 --- a/tests/Fixtures/TestBundle/Entity/Site.php +++ b/tests/Fixtures/TestBundle/Entity/Site.php @@ -16,30 +16,20 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class Site { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column - */ + #[ORM\Column] private $title; - /** - * @ORM\Column - */ + #[ORM\Column] private $description; - /** - * @ORM\OneToOne(targetEntity="AbstractUser", cascade={"persist", "remove"}) - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\OneToOne(targetEntity: 'AbstractUser', cascade: ['persist', 'remove'])] + #[ORM\JoinColumn(nullable: false)] private $owner; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php b/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php index 4578916b183..eb326ad96c8 100644 --- a/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SlugChildDummy.php @@ -13,42 +13,36 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Link; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] #[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy::class, identifiers: ['slug'], toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], fromProperty: 'parentDummy'), 'parentDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy::class, identifiers: [], expandedValue: 'parent_dummy', toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] +#[ORM\Entity] class SlugChildDummy { /** * @var int|null The identifier - * - * @ApiProperty(identifier=false) - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ApiProperty(identifier: false)] + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + /** * @var string The slug used as API identifier - * - * @ApiProperty(identifier=true) - * - * @ORM\Column(type="string", length=255, unique=true) - */ - private $slug; - /** - * @ORM\ManyToOne(targetEntity="ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy", inversedBy="childDummies") - * @ORM\JoinColumn(name="parent_dummy_id", referencedColumnName="id") */ + #[ApiProperty(identifier: true)] + #[ORM\Column(type: 'string', length: 255, unique: true)] + private ?string $slug = null; + + #[ORM\ManyToOne(targetEntity: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugParentDummy::class, inversedBy: 'childDummies')] + #[ORM\JoinColumn(name: 'parent_dummy_id', referencedColumnName: 'id')] private $parentDummy; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php b/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php index c7a220a4861..9d48c141ad3 100644 --- a/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; @@ -23,37 +23,32 @@ /** * Custom Identifier Dummy With Subresource. - * - * @ORM\Entity */ #[ApiResource(uriVariables: 'slug')] #[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies/{childDummies}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], toProperty: 'parentDummy'), 'childDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] +#[ORM\Entity] class SlugParentDummy { /** * @var int|null The database identifier - * - * @ApiProperty(identifier=false) - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ApiProperty(identifier: false)] + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var string The slug used a API identifier - * - * @ApiProperty(identifier=true) - * - * @ORM\Column(type="string", length=255, unique=true) */ - private $slug; + #[ApiProperty(identifier: true)] + #[ORM\Column(type: 'string', length: 255, unique: true)] + private ?string $slug = null; /** * @var \Collection - * @ORM\OneToMany(targetEntity="ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy", mappedBy="parentDummy") */ - private $childDummies; + #[ORM\OneToMany(targetEntity: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, mappedBy: 'parentDummy')] + private \Collection $childDummies; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/SoMany.php b/tests/Fixtures/TestBundle/Entity/SoMany.php index 4c0c37f5c03..64198ec211c 100644 --- a/tests/Fixtures/TestBundle/Entity/SoMany.php +++ b/tests/Fixtures/TestBundle/Entity/SoMany.php @@ -20,21 +20,17 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity * @ApiFilter (RangeFilter::class, properties={"id"}) * @ApiFilter (OrderFilter::class, properties={"id"="DESC"}) */ #[ApiResource(paginationPartial: true, paginationViaCursor: [['field' => 'id', 'direction' => 'DESC']])] +#[ORM\Entity] class SoMany { - /** - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - /** - * @ORM\Column(nullable=true) - */ + #[ORM\Column(nullable: true)] public $content; } diff --git a/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php b/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php index 531f9a2ed3c..663224cde77 100644 --- a/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SymfonyUuidDummy.php @@ -21,22 +21,17 @@ /* @TODO remove this check in 3.0 */ if (\PHP_VERSION_ID >= 70200 && class_exists(Uuid::class) && class_exists(UuidType::class)) { /** - * @ORM\Entity - * * @author Vincent Chalamon */ #[ApiResource] + #[ORM\Entity] class SymfonyUuidDummy { - /** - * @ORM\Id - * @ORM\Column(type="symfony_uuid", unique=true) - * @ORM\GeneratedValue(strategy="NONE") - */ + #[ORM\Id] + #[ORM\Column(type: 'symfony_uuid', unique: true)] + #[ORM\GeneratedValue(strategy: 'NONE')] private $id; - /** - * @ORM\Column(nullable=true) - */ + #[ORM\Column(nullable: true)] private $number; public function __construct(?Uuid $id = null) diff --git a/tests/Fixtures/TestBundle/Entity/Taxon.php b/tests/Fixtures/TestBundle/Entity/Taxon.php index 251f5485daf..da820734dd6 100644 --- a/tests/Fixtures/TestBundle/Entity/Taxon.php +++ b/tests/Fixtures/TestBundle/Entity/Taxon.php @@ -16,26 +16,15 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ +#[ORM\Entity] class Taxon implements TaxonInterface { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - - /** - * @var string - * - * @ORM\Column(type="string", unique=true) - */ - private $code; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'string', unique: true)] + private ?string $code = null; /** * {@inheritdoc} diff --git a/tests/Fixtures/TestBundle/Entity/ThirdLevel.php b/tests/Fixtures/TestBundle/Entity/ThirdLevel.php index 1b20b32d95d..67502e04e43 100644 --- a/tests/Fixtures/TestBundle/Entity/ThirdLevel.php +++ b/tests/Fixtures/TestBundle/Entity/ThirdLevel.php @@ -23,7 +23,6 @@ * Third Level. * * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource] #[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] @@ -31,37 +30,25 @@ #[ApiResource(uriTemplate: '/related_dummies/{id}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ORM\Entity] class ThirdLevel { /** * @var int|null The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var int - * - * @ORM\Column(type="integer") - * @Groups({"barcelona", "chicago"}) - */ - private $level = 3; - /** - * @var bool - * - * @ORM\Column(type="boolean") - */ - private $test = true; - /** - * @ORM\ManyToOne(targetEntity="FourthLevel", cascade={"persist"}) - * @Groups({"barcelona", "chicago", "friends"}) */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[ORM\Column(type: 'integer')] + #[Groups(['barcelona', 'chicago'])] + private int $level = 3; + #[ORM\Column(type: 'boolean')] + private bool $test = true; + #[ORM\ManyToOne(targetEntity: 'FourthLevel', cascade: ['persist'])] + #[Groups(['barcelona', 'chicago', 'friends'])] public $fourthLevel; - /** - * @ORM\ManyToOne(targetEntity=FourthLevel::class, cascade={"persist"}) - */ + #[ORM\ManyToOne(targetEntity: FourthLevel::class, cascade: ['persist'])] public $badFourthLevel; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php b/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php index c18027b75f8..6051b7537ed 100644 --- a/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/TruncatedDummy.php @@ -17,21 +17,15 @@ use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class TruncatedDummy { - /** - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; - /** - * @ORM\Column(type="decimal", precision=4, scale=1, nullable=false) - */ + #[ORM\Column(type: 'decimal', precision: 4, scale: 1, nullable: false)] public $value; /** diff --git a/tests/Fixtures/TestBundle/Entity/UnknownDummy.php b/tests/Fixtures/TestBundle/Entity/UnknownDummy.php index 5d23654b4da..18719eb85dd 100644 --- a/tests/Fixtures/TestBundle/Entity/UnknownDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UnknownDummy.php @@ -17,19 +17,17 @@ /** * Unknown dummy. - * - * @ORM\Entity */ +#[ORM\Entity] class UnknownDummy { /** * @var int The id - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php index 863376fd762..6c329b47d2c 100644 --- a/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UpperCaseIdentifierDummy.php @@ -20,24 +20,22 @@ * UpperCaseIdentifier dummy. * * @author Exploit.cz - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class UpperCaseIdentifierDummy { /** * @var string The custom identifier - * - * @ORM\Column(type="guid") - * @ORM\Id */ - private $Uuid; + #[ORM\Column(type: 'guid')] + #[ORM\Id] + private ?string $Uuid = null; /** * @var string The dummy name - * - * @ORM\Column(length=30) */ - private $name; + #[ORM\Column(length: 30)] + private ?string $name = null; public function getUuid(): string { diff --git a/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php b/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php index d4dfb52a051..04eb01dcb56 100644 --- a/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php +++ b/tests/Fixtures/TestBundle/Entity/UrlEncodedId.php @@ -23,16 +23,14 @@ * @author Daniel West * * Resource with an ID that will be URL encoded - * @ORM\Entity */ #[ApiResource(operations: [new Get(requirements: ['id' => '.+']), new Post(), new GetCollection()])] +#[ORM\Entity] class UrlEncodedId { - /** - * @ORM\Column(type="string") - * @ORM\Id - */ - private $id = '%encode:id'; + #[ORM\Column(type: 'string')] + #[ORM\Id] + private string $id = '%encode:id'; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/User.php b/tests/Fixtures/TestBundle/Entity/User.php index 4fc45f1af3a..b9c6f8d6a47 100644 --- a/tests/Fixtures/TestBundle/Entity/User.php +++ b/tests/Fixtures/TestBundle/Entity/User.php @@ -30,42 +30,25 @@ /** * A User. * - * @ORM\Entity - * @ORM\Table (name="user_test") - * * @author Théo FIDRY * @author Kévin Dunglas */ #[ApiResource(operations: [new Get(), new Put(), new Delete(), new Put(input: RecoverPasswordInput::class, output: RecoverPasswordOutput::class, uriTemplate: 'users/recover/{id}'), new Post(), new GetCollection(), new Post(uriTemplate: '/users/password_reset_request', messenger: 'input', input: PasswordResetRequest::class, output: PasswordResetRequestResult::class, normalizationContext: ['groups' => ['user_password_reset_request']], denormalizationContext: ['groups' => ['user_password_reset_request']])], normalizationContext: ['groups' => ['user', 'user-read']], denormalizationContext: ['groups' => ['user', 'user-write']])] +#[ORM\Entity] +#[ORM\Table(name: 'user_test')] class User extends AbstractSecurityUser { - /** - * @var int|null - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @var string|null - * - * @Groups({"user"}) - */ - private $email; - /** - * @var string|null - * - * @ORM\Column(type="string", length=255, nullable=true) - * @Groups({"user"}) - */ - private $fullname; - /** - * @var string|null - * - * @Groups({"user-write"}) - */ - private $plainPassword; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + #[Groups(['user'])] + private ?string $email = null; + #[ORM\Column(type: 'string', length: 255, nullable: true)] + #[Groups(['user'])] + private ?string $fullname = null; + #[Groups(['user-write'])] + private ?string $plainPassword = null; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/UserResource.php b/tests/Fixtures/TestBundle/Entity/UserResource.php index cee2bc9c954..84abe0dd338 100644 --- a/tests/Fixtures/TestBundle/Entity/UserResource.php +++ b/tests/Fixtures/TestBundle/Entity/UserResource.php @@ -21,8 +21,6 @@ #[ApiResource(operations: [new Post(uriTemplate: '/user-reset-password', input: UserResetPasswordDto::class)])] final class UserResource { - /** - * @Assert\NotBlank - */ + #[Assert\NotBlank] public $username; } diff --git a/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php index 2f90db78aff..1723be3103e 100644 --- a/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php @@ -18,25 +18,22 @@ /** * Custom identifier dummy. - * - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class UuidIdentifierDummy { /** * @var string The custom identifier - * - * @ORM\Column(type="guid") - * @ORM\Id */ - private $uuid; + #[ORM\Column(type: 'guid')] + #[ORM\Id] + private ?string $uuid = null; /** * @var string The dummy name - * - * @ORM\Column(length=30) */ - private $name; + #[ORM\Column(length: 30)] + private ?string $name = null; public function getUuid(): string { diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php index c8f84f4ba20..228618067b5 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php @@ -19,39 +19,20 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource(normalizationContext: ['groups' => ['car_read']], denormalizationContext: ['groups' => ['car_write']])] +#[ORM\Entity] class VoDummyCar extends VoDummyVehicle { - /** - * @var int - * - * @ORM\Column(type="integer") - * @Groups({"car_read", "car_write"}) - */ - private $mileage; - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $bodyType; /** * @var VoDummyInspection[]|Collection - * - * @ORM\OneToMany(targetEntity="VoDummyInspection", mappedBy="car", cascade={"persist"}) - * @Groups({"car_read", "car_write"}) */ - private $inspections; + #[ORM\OneToMany(targetEntity: 'VoDummyInspection', mappedBy: 'car', cascade: ['persist'])] + #[Groups(['car_read', 'car_write'])] + private readonly array|\Doctrine\Common\Collections\Collection $inspections; - public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, int $mileage, string $bodyType = 'coupe') + public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, #[ORM\Column(type: 'integer')] #[Groups(['car_read', 'car_write'])] private readonly int $mileage, #[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $bodyType = 'coupe') { parent::__construct($make, $insuranceCompany, $drivers); - $this->mileage = $mileage; - $this->bodyType = $bodyType; $this->inspections = new ArrayCollection(); } diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php b/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php index 88b7347a524..0d558eb74d7 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyDriver.php @@ -17,32 +17,14 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class VoDummyDriver { use VoDummyIdAwareTrait; - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $firstName; - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $lastName; - - public function __construct(string $firstName, string $lastName) + + public function __construct(#[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $firstName, #[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $lastName) { - $this->firstName = $firstName; - $this->lastName = $lastName; } public function getFirstName() diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyIdAwareTrait.php b/tests/Fixtures/TestBundle/Entity/VoDummyIdAwareTrait.php index c2b07790bf5..0c6ac5dff14 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyIdAwareTrait.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyIdAwareTrait.php @@ -19,11 +19,10 @@ trait VoDummyIdAwareTrait { /** * @var int - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue] protected $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php index bedd0aa3f25..21aac8dc940 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php @@ -18,42 +18,18 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource(graphQlOperations: [], normalizationContext: ['groups' => ['inspection_read']], denormalizationContext: ['groups' => ['inspection_write']])] +#[ORM\Entity] class VoDummyInspection { use VoDummyIdAwareTrait; - /** - * @var bool - * - * @ORM\Column(type="boolean") - * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) - */ - private $accepted; - /** - * @var VoDummyCar|null - * - * @ORM\ManyToOne(targetEntity="VoDummyCar", inversedBy="inspections") - * @Groups({"inspection_read", "inspection_write"}) - */ - private $car; - /** - * @var DateTime - * - * @ORM\Column(type="datetime") - * @Groups({"car_read", "car_write", "inspection_read", "inspection_write"}) - */ - private $performed; - private $attributeWithoutConstructorEquivalent; + #[ORM\Column(type: 'datetime')] + #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] + private \DateTime $performed; - public function __construct(bool $accepted, VoDummyCar $car, DateTime $performed = null, string $parameterWhichIsNotClassAttribute = '') + public function __construct(#[ORM\Column(type: 'boolean')] #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private readonly bool $accepted, #[ORM\ManyToOne(targetEntity: 'VoDummyCar', inversedBy: 'inspections')] #[Groups(['inspection_read', 'inspection_write'])] private readonly ?VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') { - $this->accepted = $accepted; - $this->car = $car; $this->performed = $performed ?: new DateTime(); - $this->attributeWithoutConstructorEquivalent = $parameterWhichIsNotClassAttribute; } public function isAccepted() diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php b/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php index eb639f5e7fa..be7e55e7ae6 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyInsuranceCompany.php @@ -17,24 +17,14 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class VoDummyInsuranceCompany { use VoDummyIdAwareTrait; - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $name; - public function __construct(string $name) + public function __construct(#[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $name) { - $this->name = $name; } public function getName() diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php b/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php index 4e74857a052..0ae2c6a2125 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php @@ -18,44 +18,22 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ORM\MappedSuperclass - */ +#[ORM\MappedSuperclass] abstract class VoDummyVehicle { use VoDummyIdAwareTrait; - - /** - * @var string - * - * @ORM\Column - * @Groups({"car_read", "car_write"}) - */ - private $make; - - /** - * @var VoDummyInsuranceCompany|null - * - * @ORM\ManyToOne(targetEntity="VoDummyInsuranceCompany", cascade={"persist"}) - * @Groups({"car_read", "car_write"}) - */ - private $insuranceCompany; - /** * @var VoDummyDriver[]|Collection - * - * @ORM\ManyToMany(targetEntity="VoDummyDriver", cascade={"persist"}) - * @Groups({"car_read", "car_write"}) */ - private $drivers; + #[ORM\ManyToMany(targetEntity: 'VoDummyDriver', cascade: ['persist'])] + #[Groups(['car_read', 'car_write'])] + private readonly array|\Doctrine\Common\Collections\Collection $drivers; public function __construct( - string $make, - VoDummyInsuranceCompany $insuranceCompany, + #[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $make, + #[ORM\ManyToOne(targetEntity: 'VoDummyInsuranceCompany', cascade: ['persist'])] #[Groups(['car_read', 'car_write'])] private readonly ?VoDummyInsuranceCompany $insuranceCompany, array $drivers ) { - $this->make = $make; - $this->insuranceCompany = $insuranceCompany; $this->drivers = new ArrayCollection($drivers); } diff --git a/tests/Fixtures/TestBundle/Entity/VoidPayment.php b/tests/Fixtures/TestBundle/Entity/VoidPayment.php index 089da723146..30ccff469c9 100644 --- a/tests/Fixtures/TestBundle/Entity/VoidPayment.php +++ b/tests/Fixtures/TestBundle/Entity/VoidPayment.php @@ -16,29 +16,17 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class VoidPayment { - /** - * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; - /** - * @ORM\OneToOne(targetEntity=Payment::class, inversedBy="voidPayment") - * @ORM\JoinColumn(nullable=false) - */ - private $payment; - - public function __construct(Payment $payment) + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + public function __construct(#[ORM\OneToOne(targetEntity: Payment::class, inversedBy: 'voidPayment')] #[ORM\JoinColumn(nullable: false)] private readonly Payment $payment) { - $this->payment = $payment; } public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php index a1d926b5ff0..0e6913ded2c 100644 --- a/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php +++ b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php @@ -16,25 +16,18 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity - */ #[ApiResource] +#[ORM\Entity] class WithJsonDummy { - /** - * @var int|null - * - * @ORM\Column(type="integer", nullable=true) - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - private $id; + #[ORM\Column(type: 'integer', nullable: true)] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; /** * @var array|null - * - * @ORM\Column(type="json", nullable=true) */ + #[ORM\Column(type: 'json', nullable: true)] public $json; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/WritableId.php b/tests/Fixtures/TestBundle/Entity/WritableId.php index 53c7b167653..98f114f1463 100644 --- a/tests/Fixtures/TestBundle/Entity/WritableId.php +++ b/tests/Fixtures/TestBundle/Entity/WritableId.php @@ -19,19 +19,15 @@ /** * @author Kévin Dunglas - * @ORM\Entity */ #[ApiResource] +#[ORM\Entity] class WritableId { - /** - * @ORM\Id - * @Assert\Uuid - * @ORM\Column(type="guid") - */ + #[ORM\Id] + #[Assert\Uuid] + #[ORM\Column(type: 'guid')] public $id; - /** - * @ORM\Column - */ + #[ORM\Column] public $name; } diff --git a/tests/Fixtures/TestBundle/Enum/ContentStatus.php b/tests/Fixtures/TestBundle/Enum/ContentStatus.php index 2ef678e51e0..3f61ff16df5 100644 --- a/tests/Fixtures/TestBundle/Enum/ContentStatus.php +++ b/tests/Fixtures/TestBundle/Enum/ContentStatus.php @@ -23,16 +23,13 @@ final class ContentStatus implements \JsonSerializable public function __construct(string $value) { if (!self::isValid($value)) { - throw new \UnexpectedValueException("Value '$value' is not part of the enum ".__CLASS__); + throw new \UnexpectedValueException("Value '$value' is not part of the enum ".self::class); } $this->value = $value; } - /** - * @return string|bool - */ - public function getKey() + public function getKey(): string|bool { return static::search($this->value); } @@ -58,10 +55,7 @@ public static function isValid(string $value): bool return \in_array($value, self::toArray(), true); } - /** - * @return string|bool - */ - public static function search(string $value) + public static function search(string $value): string|bool { return array_search($value, self::toArray(), true); } diff --git a/tests/Fixtures/TestBundle/Filter/NoPropertiesArgumentFilter.php b/tests/Fixtures/TestBundle/Filter/NoPropertiesArgumentFilter.php index 02fc55e4f6d..3a4cb58399a 100644 --- a/tests/Fixtures/TestBundle/Filter/NoPropertiesArgumentFilter.php +++ b/tests/Fixtures/TestBundle/Filter/NoPropertiesArgumentFilter.php @@ -17,11 +17,8 @@ final class NoPropertiesArgumentFilter implements FilterInterface { - private $foo; - - public function __construct(string $foo = 'bar') + public function __construct(private readonly string $foo = 'bar') { - $this->foo = $foo; } /** diff --git a/tests/Fixtures/TestBundle/GraphQl/Type/Definition/DateTimeType.php b/tests/Fixtures/TestBundle/GraphQl/Type/Definition/DateTimeType.php index 553b5703883..08748c72a89 100644 --- a/tests/Fixtures/TestBundle/GraphQl/Type/Definition/DateTimeType.php +++ b/tests/Fixtures/TestBundle/GraphQl/Type/Definition/DateTimeType.php @@ -29,7 +29,7 @@ final class DateTimeType extends ScalarType implements TypeInterface { public function __construct() { - $this->name = 'DateTime'; + $this->name = \DateTime::class; $this->description = 'The `DateTime` scalar type represents time data.'; parent::__construct(); diff --git a/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverter.php b/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverter.php index 58d473a24c4..c9b4bd36d8e 100644 --- a/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverter.php +++ b/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverter.php @@ -27,11 +27,8 @@ */ final class TypeConverter implements TypeConverterInterface { - private $defaultTypeConverter; - - public function __construct(TypeConverterInterface $defaultTypeConverter) + public function __construct(private readonly TypeConverterInterface $defaultTypeConverter) { - $this->defaultTypeConverter = $defaultTypeConverter; } /** @@ -44,7 +41,7 @@ public function convertType(Type $type, bool $input, Operation $rootOperation, s && Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType() && is_a($type->getClassName(), \DateTimeInterface::class, true) ) { - return 'DateTime'; + return \DateTime::class; } return $this->defaultTypeConverter->convertType($type, $input, $rootOperation, $resourceClass, $rootResource, $property, $depth); diff --git a/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverterLegacy.php b/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverterLegacy.php deleted file mode 100644 index 8f5319b3619..00000000000 --- a/tests/Fixtures/TestBundle/GraphQl/Type/TypeConverterLegacy.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\GraphQl\Type; - -use ApiPlatform\Core\GraphQl\Type\TypeConverterInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy as DummyDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use GraphQL\Type\Definition\Type as GraphQLType; -use Symfony\Component\PropertyInfo\Type; - -/** - * Converts a built-in type to its GraphQL equivalent. - * - * @author Alan Poulain - */ -final class TypeConverterLegacy implements TypeConverterInterface -{ - private $defaultTypeConverter; - - public function __construct(TypeConverterInterface $defaultTypeConverter) - { - $this->defaultTypeConverter = $defaultTypeConverter; - } - - /** - * {@inheritdoc} - */ - public function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, ?string $subscriptionName, string $resourceClass, string $rootResource, ?string $property, int $depth) - { - if ('dummyDate' === $property - && \in_array($rootResource, [Dummy::class, DummyDocument::class], true) - && Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType() - && is_a($type->getClassName(), \DateTimeInterface::class, true) - ) { - return 'DateTime'; - } - - return $this->defaultTypeConverter->convertType($type, $input, $queryName, $mutationName, $subscriptionName, $resourceClass, $rootResource, $property, $depth); - } - - /** - * {@inheritdoc} - */ - public function resolveType(string $type): ?GraphQLType - { - return $this->defaultTypeConverter->resolveType($type); - } -} diff --git a/tests/Fixtures/TestBundle/Metadata/ProviderResourceMetadatatCollectionFactory.php b/tests/Fixtures/TestBundle/Metadata/ProviderResourceMetadatatCollectionFactory.php index c415d3ec1f8..95bcbea3682 100644 --- a/tests/Fixtures/TestBundle/Metadata/ProviderResourceMetadatatCollectionFactory.php +++ b/tests/Fixtures/TestBundle/Metadata/ProviderResourceMetadatatCollectionFactory.php @@ -30,14 +30,8 @@ class ProviderResourceMetadatatCollectionFactory implements ResourceMetadataCollectionFactoryInterface { - /** - * @var ResourceMetadataCollectionFactoryInterface - */ - private $decorated; - - public function __construct(ResourceMetadataCollectionFactoryInterface $decorated) + public function __construct(private readonly ResourceMetadataCollectionFactoryInterface $decorated) { - $this->decorated = $decorated; } /** diff --git a/tests/Fixtures/TestBundle/Model/MediaObject.php b/tests/Fixtures/TestBundle/Model/MediaObject.php index 53c3aa557d0..1cd289180c5 100644 --- a/tests/Fixtures/TestBundle/Model/MediaObject.php +++ b/tests/Fixtures/TestBundle/Model/MediaObject.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Mutation; @@ -23,12 +23,8 @@ #[ApiResource(graphQlOperations: [new Mutation(name: 'upload', resolver: 'app.graphql.mutation_resolver.upload_media_object', args: ['file' => ['type' => 'Upload!', 'description' => 'Upload a file']]), new Mutation(name: 'uploadMultiple', resolver: 'app.graphql.mutation_resolver.upload_multiple_media_object', args: ['files' => ['type' => '[Upload!]!', 'description' => 'Upload multiple files']])], types: ['http://schema.org/MediaObject'])] class MediaObject { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public $id; - /** - * @var string - */ - public $contentUrl; + + public string $contentUrl; } diff --git a/tests/Fixtures/TestBundle/Model/ProductInterface.php b/tests/Fixtures/TestBundle/Model/ProductInterface.php index 70b2451c6e8..05f1c9f67d8 100644 --- a/tests/Fixtures/TestBundle/Model/ProductInterface.php +++ b/tests/Fixtures/TestBundle/Model/ProductInterface.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider; use Symfony\Component\Serializer\Annotation\Groups; @@ -24,27 +24,17 @@ interface ProductInterface { public function getId(); - /** - * @ApiProperty(identifier=true) - * - * @Groups({"product_read"}) - * - * @Assert\NotBlank - */ + #[ApiProperty(identifier: true)] + #[Groups(['product_read'])] + #[Assert\NotBlank] public function getCode(): ?string; - /** - * @Groups({"product_write"}) - */ + #[Groups(['product_write'])] public function setCode(?string $code): void; - /** - * @Groups({"product_read"}) - */ + #[Groups(['product_read'])] public function getMainTaxon(): ?TaxonInterface; - /** - * @Groups({"product_write"}) - */ + #[Groups(['product_write'])] public function setMainTaxon(?TaxonInterface $mainTaxon): void; } diff --git a/tests/Fixtures/TestBundle/Model/ResourceBarInterface.php b/tests/Fixtures/TestBundle/Model/ResourceBarInterface.php index ec79c8e6ce5..9094d397c60 100644 --- a/tests/Fixtures/TestBundle/Model/ResourceBarInterface.php +++ b/tests/Fixtures/TestBundle/Model/ResourceBarInterface.php @@ -13,12 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; interface ResourceBarInterface { - /** - * @ApiProperty(identifier=true) - */ + #[ApiProperty(identifier: true)] public function getBar(): ?string; } diff --git a/tests/Fixtures/TestBundle/Model/ResourceInterfaceImplementation.php b/tests/Fixtures/TestBundle/Model/ResourceInterfaceImplementation.php index 1b9c87c273c..5969df5fc0b 100644 --- a/tests/Fixtures/TestBundle/Model/ResourceInterfaceImplementation.php +++ b/tests/Fixtures/TestBundle/Model/ResourceInterfaceImplementation.php @@ -18,15 +18,9 @@ */ class ResourceInterfaceImplementation implements ResourceInterface, ResourceBarInterface { - /** - * @var string - */ - private $foo; - - /** - * @var ?string - */ - private $bar; + private ?string $foo = null; + + private ?string $bar = null; public function setFoo(string $foo) { diff --git a/tests/Fixtures/TestBundle/Model/SerializableResource.php b/tests/Fixtures/TestBundle/Model/SerializableResource.php index 5c2e2639979..fdc6d549121 100644 --- a/tests/Fixtures/TestBundle/Model/SerializableResource.php +++ b/tests/Fixtures/TestBundle/Model/SerializableResource.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; /** @@ -24,18 +24,10 @@ #[ApiResource] class SerializableResource { - /** - * @var int - * - * @ApiProperty(identifier=true) - */ - public $id; - /** - * @var string - */ - public $foo; - /** - * @var string - */ - public $bar; + #[ApiProperty(identifier: true)] + public int $id; + + public string $foo; + + public string $bar; } diff --git a/tests/Fixtures/TestBundle/Model/TaxonInterface.php b/tests/Fixtures/TestBundle/Model/TaxonInterface.php index a13531eb99d..23ce666d0e5 100644 --- a/tests/Fixtures/TestBundle/Model/TaxonInterface.php +++ b/tests/Fixtures/TestBundle/Model/TaxonInterface.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Model; -use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -23,17 +23,11 @@ interface TaxonInterface { public function getId(); - /** - * @ApiProperty(identifier=true) - * - * @Groups({"product_read", "taxon_read"}) - * - * @Assert\NotBlank - */ + #[ApiProperty(identifier: true)] + #[Groups(['product_read', 'taxon_read'])] + #[Assert\NotBlank] public function getCode(): ?string; - /** - * @Groups({"taxon_write"}) - */ + #[Groups(['taxon_write'])] public function setCode(?string $code): void; } diff --git a/tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php b/tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php index 125bd0d9e45..7ce006e4e3e 100644 --- a/tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php +++ b/tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php @@ -24,11 +24,8 @@ final class AuthenticationEntryPoint implements AuthenticationEntryPointInterface { - private $router; - - public function __construct(RouterInterface $router) + public function __construct(private readonly RouterInterface $router) { - $this->router = $router; } public function start(Request $request, AuthenticationException $authException = null): Response diff --git a/tests/Fixtures/TestBundle/Serializer/Denormalizer/DummyPlainIdentifierDenormalizer.php b/tests/Fixtures/TestBundle/Serializer/Denormalizer/DummyPlainIdentifierDenormalizer.php index bc28865946c..fe7fbb4ef5c 100644 --- a/tests/Fixtures/TestBundle/Serializer/Denormalizer/DummyPlainIdentifierDenormalizer.php +++ b/tests/Fixtures/TestBundle/Serializer/Denormalizer/DummyPlainIdentifierDenormalizer.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Denormalizer; -use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use ApiPlatform\Metadata\Get; @@ -35,14 +34,8 @@ class DummyPlainIdentifierDenormalizer implements ContextAwareDenormalizerInterf { use DenormalizerAwareTrait; - /** - * @var IriConverterInterface|LegacyIriConverterInterface - */ - private $iriConverter; - - public function __construct($iriConverter) + public function __construct(private $iriConverter) { - $this->iriConverter = $iriConverter; } /** @@ -63,7 +56,7 @@ public function denormalize($data, $class, $format = null, array $context = []) } } - return $this->denormalizer->denormalize($data, $class, $format, $context + [__CLASS__ => true]); + return $this->denormalizer->denormalize($data, $class, $format, $context + [self::class => true]); } $relatedDummyClass = DummyEntity::class === $class ? RelatedDummyEntity::class : RelatedDummyDocument::class; @@ -81,7 +74,7 @@ public function denormalize($data, $class, $format = null, array $context = []) } } - return $this->denormalizer->denormalize($data, $class, $format, $context + [__CLASS__ => true]); + return $this->denormalizer->denormalize($data, $class, $format, $context + [self::class => true]); } /** @@ -92,6 +85,6 @@ public function supportsDenormalization($data, $type, $format = null, array $con return 'json' === $format && (is_a($type, DummyEntity::class, true) || is_a($type, DummyDocument::class, true)) && ('1' === ($data['relatedDummy'] ?? null) || ['1'] === ($data['relatedDummies'] ?? null)) - && !isset($context[__CLASS__]); + && !isset($context[self::class]); } } diff --git a/tests/Fixtures/TestBundle/Serializer/Denormalizer/RelatedDummyPlainIdentifierDenormalizer.php b/tests/Fixtures/TestBundle/Serializer/Denormalizer/RelatedDummyPlainIdentifierDenormalizer.php index a72e1bf7b87..2f52bad8cc6 100644 --- a/tests/Fixtures/TestBundle/Serializer/Denormalizer/RelatedDummyPlainIdentifierDenormalizer.php +++ b/tests/Fixtures/TestBundle/Serializer/Denormalizer/RelatedDummyPlainIdentifierDenormalizer.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Denormalizer; -use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use ApiPlatform\Metadata\Get; @@ -35,14 +34,8 @@ class RelatedDummyPlainIdentifierDenormalizer implements ContextAwareDenormalize { use DenormalizerAwareTrait; - /** - * @var IriConverterInterface|LegacyIriConverterInterface - */ - private $iriConverter; - - public function __construct($iriConverter) + public function __construct(private $iriConverter) { - $this->iriConverter = $iriConverter; } /** @@ -55,7 +48,7 @@ public function denormalize($data, $class, $format = null, array $context = []) if ($this->iriConverter instanceof LegacyIriConverterInterface) { $data['thirdLevel'] = '/third_levels/'.$data['thirdLevel']; - return $this->denormalizer->denormalize($data, $class, $format, $context + [__CLASS__ => true]); + return $this->denormalizer->denormalize($data, $class, $format, $context + [self::class => true]); } $iriConverterContext = ['uri_variables' => ['id' => $data['thirdLevel']]] + $context; @@ -67,7 +60,7 @@ public function denormalize($data, $class, $format = null, array $context = []) $iriConverterContext ); - return $this->denormalizer->denormalize($data, $class, $format, $context + [__CLASS__ => true]); + return $this->denormalizer->denormalize($data, $class, $format, $context + [self::class => true]); } /** @@ -78,6 +71,6 @@ public function supportsDenormalization($data, $type, $format = null, array $con return 'json' === $format && (is_a($type, RelatedDummyEntity::class, true) || is_a($type, RelatedDummyDocument::class, true)) && '1' === ($data['thirdLevel'] ?? null) - && !isset($context[__CLASS__]); + && !isset($context[self::class]); } } diff --git a/tests/Fixtures/TestBundle/Serializer/Normalizer/OverrideDocumentationNormalizer.php b/tests/Fixtures/TestBundle/Serializer/Normalizer/OverrideDocumentationNormalizer.php index f33cd420e41..3dc6a8fb9ad 100644 --- a/tests/Fixtures/TestBundle/Serializer/Normalizer/OverrideDocumentationNormalizer.php +++ b/tests/Fixtures/TestBundle/Serializer/Normalizer/OverrideDocumentationNormalizer.php @@ -21,11 +21,8 @@ */ final class OverrideDocumentationNormalizer implements NormalizerInterface { - private $documentationNormalizer; - - public function __construct(NormalizerInterface $documentationNormalizer) + public function __construct(private readonly NormalizerInterface $documentationNormalizer) { - $this->documentationNormalizer = $documentationNormalizer; } /** diff --git a/tests/Fixtures/TestBundle/State/DummyDtoNoOutputProcessor.php b/tests/Fixtures/TestBundle/State/DummyDtoNoOutputProcessor.php index e613766edbc..fca74c8265f 100644 --- a/tests/Fixtures/TestBundle/State/DummyDtoNoOutputProcessor.php +++ b/tests/Fixtures/TestBundle/State/DummyDtoNoOutputProcessor.php @@ -23,11 +23,8 @@ class DummyDtoNoOutputProcessor implements ProcessorInterface { - private $registry; - - public function __construct(ManagerRegistry $registry) + public function __construct(private readonly ManagerRegistry $registry) { - $this->registry = $registry; } /** diff --git a/tests/Fixtures/TestBundle/State/OperationResourceProcessor.php b/tests/Fixtures/TestBundle/State/OperationResourceProcessor.php index 26739e258d4..f723534e888 100644 --- a/tests/Fixtures/TestBundle/State/OperationResourceProcessor.php +++ b/tests/Fixtures/TestBundle/State/OperationResourceProcessor.php @@ -26,11 +26,8 @@ final class OperationResourceProcessor implements ProcessorInterface { use ClassInfoTrait; - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry) + public function __construct(private readonly ManagerRegistry $managerRegistry) { - $this->managerRegistry = $managerRegistry; } private function persist($data, array $context = []) diff --git a/tests/Fixtures/TestBundle/State/ProductProvider.php b/tests/Fixtures/TestBundle/State/ProductProvider.php index 9f02ffa7a67..bc86477c501 100644 --- a/tests/Fixtures/TestBundle/State/ProductProvider.php +++ b/tests/Fixtures/TestBundle/State/ProductProvider.php @@ -22,13 +22,8 @@ class ProductProvider implements ProviderInterface { - private $managerRegistry; - private $orm; - - public function __construct(ManagerRegistry $managerRegistry, bool $orm = true) + public function __construct(private readonly ManagerRegistry $managerRegistry, private readonly bool $orm = true) { - $this->managerRegistry = $managerRegistry; - $this->orm = $orm; } /** diff --git a/tests/Fixtures/TestBundle/State/RelatedQuestionsProvider.php b/tests/Fixtures/TestBundle/State/RelatedQuestionsProvider.php index b21ad5ce54c..c5d4b4c3c7f 100644 --- a/tests/Fixtures/TestBundle/State/RelatedQuestionsProvider.php +++ b/tests/Fixtures/TestBundle/State/RelatedQuestionsProvider.php @@ -21,11 +21,8 @@ class RelatedQuestionsProvider implements ProviderInterface { - private $registry; - - public function __construct(ManagerRegistry $registry) + public function __construct(private readonly ManagerRegistry $registry) { - $this->registry = $registry; } public function provide(Operation $operation, array $uriVariables = [], array $context = []) diff --git a/tests/Fixtures/TestBundle/State/TaxonItemProvider.php b/tests/Fixtures/TestBundle/State/TaxonItemProvider.php index 29b34f0cd63..e71808a78a8 100644 --- a/tests/Fixtures/TestBundle/State/TaxonItemProvider.php +++ b/tests/Fixtures/TestBundle/State/TaxonItemProvider.php @@ -21,13 +21,8 @@ class TaxonItemProvider implements ProviderInterface { - private $managerRegistry; - private $orm; - - public function __construct(ManagerRegistry $managerRegistry, bool $orm = true) + public function __construct(private readonly ManagerRegistry $managerRegistry, private readonly bool $orm = true) { - $this->managerRegistry = $managerRegistry; - $this->orm = $orm; } /** diff --git a/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php b/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php index 9e2e4dbcc72..20f4f42628c 100644 --- a/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php +++ b/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php @@ -20,11 +20,8 @@ class AnnotationFilterExtractor { use AnnotationFilterExtractorTrait; - private $reader; - - public function __construct(?Reader $reader = null) + public function __construct(private readonly ?Reader $reader = null) { - $this->reader = $reader; } public function getFilters(\ReflectionClass $reflectionClass) From 92ca04d594953f2aab1a39d51a701054e7df2487 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 12 May 2022 16:34:34 +0200 Subject: [PATCH 05/56] fix apifilter --- .../Fixtures/TestBundle/Document/Content.php | 2 +- .../TestBundle/Document/ConvertedBoolean.php | 4 +- .../TestBundle/Document/ConvertedDate.php | 4 +- .../TestBundle/Document/ConvertedInteger.php | 8 ++-- .../TestBundle/Document/ConvertedOwner.php | 2 +- .../TestBundle/Document/ConvertedString.php | 4 +- .../CustomMultipleIdentifierDummy.php | 2 +- .../Fixtures/TestBundle/Document/DummyCar.php | 32 +++++++--------- .../TestBundle/Document/DummyCarColor.php | 4 +- .../TestBundle/Document/DummyDate.php | 15 ++++---- tests/Fixtures/TestBundle/Document/SoMany.php | 6 +-- tests/Fixtures/TestBundle/Entity/Content.php | 2 +- .../TestBundle/Entity/ConvertedBoolean.php | 6 +-- .../TestBundle/Entity/ConvertedDate.php | 6 +-- .../TestBundle/Entity/ConvertedInteger.php | 10 ++--- .../TestBundle/Entity/ConvertedOwner.php | 8 ++-- .../TestBundle/Entity/ConvertedString.php | 6 +-- .../Entity/CustomGeneratedIdentifier.php | 2 +- tests/Fixtures/TestBundle/Entity/DummyCar.php | 38 ++++++++----------- .../TestBundle/Entity/DummyCarColor.php | 8 ++-- .../Fixtures/TestBundle/Entity/DummyDate.php | 16 ++++---- .../Fixtures/TestBundle/Entity/DummyPhp8.php | 6 +-- tests/Fixtures/TestBundle/Entity/SoMany.php | 8 ++-- 23 files changed, 86 insertions(+), 113 deletions(-) diff --git a/tests/Fixtures/TestBundle/Document/Content.php b/tests/Fixtures/TestBundle/Document/Content.php index b6a0802d561..5783f66e55c 100644 --- a/tests/Fixtures/TestBundle/Document/Content.php +++ b/tests/Fixtures/TestBundle/Document/Content.php @@ -44,7 +44,7 @@ class Content implements \JsonSerializable * cascade={"persist"}, * ) */ - private \Doctrine\Common\Collections\Collection & iterable $fields; + private $fields; /** * @ODM\Field(type="string") */ diff --git a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php index 47c41b4320e..8d0a6babd95 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Odm\Filter\BooleanFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiFilter (BooleanFilter::class) */ +#[ApiFilter(BooleanFilter::class)] #[ApiResource] class ConvertedBoolean { diff --git a/tests/Fixtures/TestBundle/Document/ConvertedDate.php b/tests/Fixtures/TestBundle/Document/ConvertedDate.php index 0fa64eba7f0..8800e575059 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedDate.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiFilter (DateFilter::class) */ +#[ApiFilter(DateFilter::class)] #[ApiResource] class ConvertedDate { diff --git a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php index 2f2506254ca..406e3798ec1 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php @@ -13,19 +13,19 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Odm\Filter\NumericFilter; use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiFilter (NumericFilter::class, properties={"nameConverted"}) - * @ApiFilter (RangeFilter::class, properties={"nameConverted"}) - * @ApiFilter (OrderFilter::class, properties={"nameConverted"}) */ +#[ApiFilter(NumericFilter::class, properties: ['nameConverted'])] +#[ApiFilter(RangeFilter::class, properties: ['nameConverted'])] +#[ApiFilter(OrderFilter::class, properties: ['nameConverted'])] #[ApiResource] class ConvertedInteger { diff --git a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php index 494c426031a..791c30a1714 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php @@ -20,8 +20,8 @@ /** * @ODM\Document - * @ApiFilter (SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) */ +#[ApiFilter(SearchFilter::class, properties: ['nameConverted.nameConverted' => 'partial'])] #[ApiResource] class ConvertedOwner { diff --git a/tests/Fixtures/TestBundle/Document/ConvertedString.php b/tests/Fixtures/TestBundle/Document/ConvertedString.php index fc1a48be85b..526c7faccd8 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedString.php @@ -13,15 +13,15 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Odm\Filter\ExistsFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiFilter (ExistsFilter::class, properties={"nameConverted"}) */ +#[ApiFilter(ExistsFilter::class, properties: ['nameConverted'])] #[ApiResource] class ConvertedString { diff --git a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php index 3cf56a282a9..146a9be0a25 100644 --- a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php @@ -38,7 +38,7 @@ class CustomMultipleIdentifierDummy * * @ODM\Field(type="int") */ - #[ApiProperty(identifier: true) + #[ApiProperty(identifier: true)] private ?int $secondId = null; /** diff --git a/tests/Fixtures/TestBundle/Document/DummyCar.php b/tests/Fixtures/TestBundle/Document/DummyCar.php index b51387b9c4b..0ba862c56de 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCar.php +++ b/tests/Fixtures/TestBundle/Document/DummyCar.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Odm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -31,12 +31,12 @@ /** * @ODM\Document - * @ApiFilter (DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) - * @ApiFilter (BooleanFilter::class) - * @ApiFilter (PropertyFilter::class, arguments={"parameterName"="foobar"}) - * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups"}) - * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") */ +#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)] +#[ApiFilter(BooleanFilter::class)] +#[ApiFilter(PropertyFilter::class, arguments: ['parameterName' => 'foobar'])] +#[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups'])] +#[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups_override'], id: 'override')] #[ApiResource(operations: [new Get(openapiContext: ['tags' => []]), new Put(), new Delete(), new Post(), new GetCollection()], sunset: '2050-01-01', normalizationContext: ['groups' => ['colors']])] class DummyCar { @@ -50,42 +50,38 @@ class DummyCar * @var mixed Something else * * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") - * - * @ApiFilter(SearchFilter::class, properties={"colors.prop"="ipartial", "colors"="exact"}) */ + #[ApiFilter(SearchFilter::class, properties: ['colors.prop' => 'ipartial', 'colors' => 'exact'])] #[Serializer\Groups(['colors'])] private $colors; /** * @var mixed Something else * * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") - * - * @ApiFilter(SearchFilter::class, strategy="exact") */ + #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[Serializer\Groups(['colors'])] - private ?mixed $secondColors = null; + private mixed $secondColors = null; /** * @var mixed Something else * * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") - * - * @ApiFilter(SearchFilter::class, strategy="exact") */ + #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[Serializer\Groups(['colors'])] - private ?mixed $thirdColors = null; + private mixed $thirdColors = null; /** * @var mixed Something else * * @ODM\ReferenceMany(targetDocument=UuidIdentifierDummy::class) - * - * @ApiFilter(SearchFilter::class, strategy="exact") */ + #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[Serializer\Groups(['colors'])] - private ?mixed $uuid = null; + private mixed $uuid = null; /** * @ODM\Field(type="string") - * @ApiFilter(SearchFilter::class, strategy="partial") */ + #[ApiFilter(SearchFilter::class, strategy: 'partial')] private ?string $name = null; /** * @ODM\Field(type="bool") diff --git a/tests/Fixtures/TestBundle/Document/DummyCarColor.php b/tests/Fixtures/TestBundle/Document/DummyCarColor.php index 3c639fa7430..df8d7c6a31e 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Document/DummyCarColor.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation as Serializer; @@ -39,8 +39,8 @@ class DummyCarColor private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyCar $car = null; /** * @ODM\Field(nullable=false) - * @ApiFilter(SearchFilter::class) */ + #[ApiFilter(SearchFilter::class)] #[Assert\NotBlank] #[Serializer\Groups(['colors'])] private string $prop = ''; diff --git a/tests/Fixtures/TestBundle/Document/DummyDate.php b/tests/Fixtures/TestBundle/Document/DummyDate.php index 951031052b7..b61c056ffb1 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyDate.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Odm\Filter\DateFilter; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; @@ -23,16 +23,15 @@ /** * Dummy Date. * - * @author Antoine Bluchet * @author Alan Poulain - * @ApiFilter (SearchFilter::class, properties={"dummyDate"}) - * @ApiFilter (DateFilter::class, properties={ - * "dateIncludeNullAfter"=DateFilter::INCLUDE_NULL_AFTER, - * "dateIncludeNullBefore"=DateFilter::INCLUDE_NULL_BEFORE, - * "dateIncludeNullBeforeAndAfter"=DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER - * }) * @ODM\Document */ +#[ApiFilter(DateFilter::class, properties: [ + 'dateIncludeNullAfter' => DateFilter::INCLUDE_NULL_AFTER, + 'dateIncludeNullBefore' => DateFilter::INCLUDE_NULL_BEFORE, + 'dateIncludeNullBeforeAndAfter' => DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER, +])] +#[ApiFilter(SearchFilter::class, properties: ['dummyDate'])] #[ApiResource(filters: ['my_dummy_date.mongodb.date'])] class DummyDate { diff --git a/tests/Fixtures/TestBundle/Document/SoMany.php b/tests/Fixtures/TestBundle/Document/SoMany.php index 837472986ae..fa56e94f4d1 100644 --- a/tests/Fixtures/TestBundle/Document/SoMany.php +++ b/tests/Fixtures/TestBundle/Document/SoMany.php @@ -13,17 +13,17 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * @ODM\Document - * @ApiFilter (RangeFilter::class, properties={"id"}) - * @ApiFilter (OrderFilter::class, properties={"id"="DESC"}) */ +#[ApiFilter(RangeFilter::class, properties: ['id'])] +#[ApiFilter(OrderFilter::class, properties: ['id' => 'DESC'])] #[ApiResource(paginationPartial: true, paginationViaCursor: [['field' => 'id', 'direction' => 'DESC']])] class SoMany { diff --git a/tests/Fixtures/TestBundle/Entity/Content.php b/tests/Fixtures/TestBundle/Entity/Content.php index b4281249992..21eb1f0430b 100644 --- a/tests/Fixtures/TestBundle/Entity/Content.php +++ b/tests/Fixtures/TestBundle/Entity/Content.php @@ -35,7 +35,7 @@ class Content implements \JsonSerializable */ #[ORM\OneToMany(targetEntity: Field::class, mappedBy: 'content', cascade: ['persist'], orphanRemoval: true, indexBy: 'name')] #[ORM\OrderBy(['id' => 'ASC'])] - private \Doctrine\Common\Collections\Collection & iterable $fields; + private \Doctrine\Common\Collections\Collection $fields; #[ORM\Column(type: 'string')] private readonly string $status; diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php index bdb6a73e285..fc3d59a0395 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedBoolean.php @@ -13,14 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiFilter (BooleanFilter::class) - */ +#[ApiFilter(BooleanFilter::class)] #[ApiResource] #[ORM\Entity] class ConvertedBoolean diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedDate.php b/tests/Fixtures/TestBundle/Entity/ConvertedDate.php index 0fc7b1a2e4a..c160926efc4 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedDate.php @@ -13,14 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiFilter (DateFilter::class) - */ +#[ApiFilter(DateFilter::class)] #[ApiResource] #[ORM\Entity] class ConvertedDate diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php b/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php index 815b5d06af1..73f2f1f98e6 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedInteger.php @@ -13,18 +13,16 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Orm\Filter\NumericFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiFilter (NumericFilter::class, properties={"nameConverted"}) - * @ApiFilter (RangeFilter::class, properties={"nameConverted"}) - * @ApiFilter (OrderFilter::class, properties={"nameConverted"}) - */ +#[ApiFilter(NumericFilter::class, properties: ['nameConverted'])] +#[ApiFilter(RangeFilter::class, properties: ['nameConverted'])] +#[ApiFilter(OrderFilter::class, properties: ['nameConverted'])] #[ApiResource] #[ORM\Entity] class ConvertedInteger diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php index 6195b32db50..527bfa3e1b0 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php @@ -13,14 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiFilter (SearchFilter::class, properties={"nameConverted.nameConverted"="partial"}) - */ +#[ApiFilter(SearchFilter::class, properties: ['nameConverted.nameConverted' => 'partial'])] #[ApiResource] #[ORM\Entity] class ConvertedOwner diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedString.php b/tests/Fixtures/TestBundle/Entity/ConvertedString.php index 2d3bdcef148..e74d72f4e61 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedString.php @@ -13,14 +13,12 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Orm\Filter\ExistsFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiFilter (ExistsFilter::class, properties={"nameConverted"}) - */ +#[ApiFilter(ExistsFilter::class, properties: ['nameConverted'])] #[ApiResource] #[ORM\Entity] class ConvertedString diff --git a/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php b/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php index ccf9a7240b7..b37d968a25d 100644 --- a/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php +++ b/tests/Fixtures/TestBundle/Entity/CustomGeneratedIdentifier.php @@ -27,7 +27,7 @@ class CustomGeneratedIdentifier #[ORM\Column(type: 'string')] #[ORM\GeneratedValue(strategy: 'CUSTOM')] #[ORM\CustomIdGenerator(class: \ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\UuidGenerator::class)] - private ?mixed $id = null; + private ?string $id = null; public function getId() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCar.php b/tests/Fixtures/TestBundle/Entity/DummyCar.php index 3a8587793d9..602626d8caf 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCar.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -29,13 +29,11 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ApiFilter (DateFilter::class, strategy=DateFilter::EXCLUDE_NULL) - * @ApiFilter (BooleanFilter::class) - * @ApiFilter (PropertyFilter::class, arguments={"parameterName"="foobar"}) - * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups"}) - * @ApiFilter (GroupFilter::class, arguments={"parameterName"="foobargroups_override"}, id="override") - */ +#[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)] +#[ApiFilter(BooleanFilter::class)] +#[ApiFilter(PropertyFilter::class, arguments: ['parameterName' => 'foobar'])] +#[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups'])] +#[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups_override'], id: 'override')] #[ApiResource(operations: [new Get(openapiContext: ['tags' => []]), new Put(), new Delete(), new Post(), new GetCollection()], sunset: '2050-01-01', normalizationContext: ['groups' => ['colors']])] #[ORM\Entity] class DummyCar @@ -48,39 +46,33 @@ class DummyCar private readonly \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarIdentifier $id; /** * @var mixed Something else - * - * @ApiFilter(SearchFilter::class, properties={"colors.prop"="ipartial", "colors"="exact"}) */ + #[ApiFilter(SearchFilter::class, properties: ['colors.prop' => 'ipartial', 'colors' => 'exact'])] #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] #[Serializer\Groups(['colors'])] private $colors; /** * @var mixed Something else - * - * @ApiFilter(SearchFilter::class, strategy="exact") */ + #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] #[Serializer\Groups(['colors'])] - private ?mixed $secondColors = null; + private mixed $secondColors = null; /** * @var mixed Something else - * - * @ApiFilter(SearchFilter::class, strategy="exact") */ + #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] #[Serializer\Groups(['colors'])] - private ?mixed $thirdColors = null; + private mixed $thirdColors = null; /** * @var mixed Something else - * - * @ApiFilter(SearchFilter::class, strategy="exact") */ + #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[ORM\ManyToMany(targetEntity: 'UuidIdentifierDummy', indexBy: 'uuid')] #[Serializer\Groups(['colors'])] - private ?mixed $uuid = null; - /** - * @ApiFilter(SearchFilter::class, strategy="partial") - */ + private mixed $uuid = null; + #[ApiFilter(SearchFilter::class, strategy: 'partial')] #[ORM\Column(type: 'string')] private ?string $name = null; #[ORM\Column(type: 'boolean')] diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php index 051f5476987..70bf44e4563 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; @@ -35,9 +35,7 @@ class DummyCarColor #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE', referencedColumnName: 'id_id')] #[Assert\NotBlank] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar $car = null; - /** - * @ApiFilter(SearchFilter::class) - */ + #[ApiFilter(SearchFilter::class)] #[ORM\Column(nullable: false)] #[Assert\NotBlank] #[Serializer\Groups(['colors'])] diff --git a/tests/Fixtures/TestBundle/Entity/DummyDate.php b/tests/Fixtures/TestBundle/Entity/DummyDate.php index 03d995eb750..899b92fde20 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDate.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDate.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use Doctrine\ORM\Mapping as ORM; @@ -24,13 +24,13 @@ * Dummy Date. * * @author Antoine Bluchet - * @ApiFilter (SearchFilter::class, properties={"dummyDate"}) - * @ApiFilter (DateFilter::class, properties={ - * "dateIncludeNullAfter"=DateFilter::INCLUDE_NULL_AFTER, - * "dateIncludeNullBefore"=DateFilter::INCLUDE_NULL_BEFORE, - * "dateIncludeNullBeforeAndAfter"=DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER - * }) */ +#[ApiFilter(DateFilter::class, properties: [ + 'dateIncludeNullAfter' => DateFilter::INCLUDE_NULL_AFTER, + 'dateIncludeNullBefore' => DateFilter::INCLUDE_NULL_BEFORE, + 'dateIncludeNullBeforeAndAfter' => DateFilter::INCLUDE_NULL_BEFORE_AND_AFTER, +])] +#[ApiFilter(SearchFilter::class, properties: ['dummyDate'])] #[ApiResource(filters: ['my_dummy_date.date'])] #[ORM\Entity] class DummyDate diff --git a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php index 6e8233d1c09..811bc29f14f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php @@ -20,9 +20,9 @@ use ApiPlatform\Metadata\Put; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use Doctrine\ORM\Mapping as ORM; #[ApiResource(description: 'Hey PHP 8')] #[ORM\Entity] diff --git a/tests/Fixtures/TestBundle/Entity/SoMany.php b/tests/Fixtures/TestBundle/Entity/SoMany.php index 64198ec211c..65a2ad93790 100644 --- a/tests/Fixtures/TestBundle/Entity/SoMany.php +++ b/tests/Fixtures/TestBundle/Entity/SoMany.php @@ -13,16 +13,14 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; -/** - * @ApiFilter (RangeFilter::class, properties={"id"}) - * @ApiFilter (OrderFilter::class, properties={"id"="DESC"}) - */ +#[ApiFilter(RangeFilter::class, properties: ['id'])] +#[ApiFilter(OrderFilter::class, properties: ['id' => 'DESC'])] #[ApiResource(paginationPartial: true, paginationViaCursor: [['field' => 'id', 'direction' => 'DESC']])] #[ORM\Entity] class SoMany From cc2bba0694778c1626592cf38845ea51cc945064 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 12 May 2022 16:35:36 +0200 Subject: [PATCH 06/56] remove all core stuff --- src/Action/EntrypointAction.php | 2 - src/Action/ExceptionAction.php | 2 - src/Action/NotFoundAction.php | 2 - src/Action/PlaceholderAction.php | 2 - src/Api/Entrypoint.php | 2 - src/Api/FilterLocatorTrait.php | 2 - src/Api/FormatMatcher.php | 2 - .../QueryParameterValidator.php | 2 - .../Validator/ArrayItems.php | 2 - .../Validator/Bounds.php | 2 - .../Validator/Enum.php | 2 - .../Validator/Length.php | 2 - .../Validator/MultipleOf.php | 2 - .../Validator/Pattern.php | 2 - .../Validator/Required.php | 2 - src/Api/ResourceClassResolver.php | 2 - .../Common/Filter/BooleanFilterTrait.php | 2 - .../Common/Filter/DateFilterTrait.php | 2 - .../Common/Filter/ExistsFilterTrait.php | 2 - .../Common/Filter/NumericFilterTrait.php | 2 - .../Common/Filter/OrderFilterTrait.php | 2 - .../Common/Filter/RangeFilterTrait.php | 2 - .../Common/Filter/SearchFilterTrait.php | 2 - src/Doctrine/Common/PropertyHelperTrait.php | 2 - .../EventListener/PurgeHttpCacheListener.php | 2 - src/Doctrine/EventListener/WriteListener.php | 2 - .../Odm/Extension/FilterExtension.php | 2 - src/Doctrine/Odm/Filter/AbstractFilter.php | 2 - src/Doctrine/Odm/Filter/BooleanFilter.php | 2 - src/Doctrine/Odm/Filter/DateFilter.php | 2 - src/Doctrine/Odm/Filter/ExistsFilter.php | 2 - src/Doctrine/Odm/Filter/NumericFilter.php | 2 - src/Doctrine/Odm/Filter/OrderFilter.php | 2 - src/Doctrine/Odm/Filter/RangeFilter.php | 2 - src/Doctrine/Odm/Paginator.php | 2 - src/Doctrine/Odm/PropertyHelperTrait.php | 2 - .../Odm/PropertyInfo/DoctrineExtractor.php | 2 - src/Doctrine/Orm/AbstractPaginator.php | 2 - .../Orm/Extension/EagerLoadingExtension.php | 89 +--- .../Extension/FilterEagerLoadingExtension.php | 2 - .../Orm/Extension/FilterExtension.php | 2 - src/Doctrine/Orm/Extension/OrderExtension.php | 3 - .../Orm/Extension/PaginationExtension.php | 3 - .../Orm/Filter/AbstractContextAwareFilter.php | 2 - src/Doctrine/Orm/Filter/AbstractFilter.php | 2 - src/Doctrine/Orm/Filter/BooleanFilter.php | 2 - src/Doctrine/Orm/Filter/DateFilter.php | 2 - src/Doctrine/Orm/Filter/ExistsFilter.php | 2 - src/Doctrine/Orm/Filter/NumericFilter.php | 2 - src/Doctrine/Orm/Filter/OrderFilter.php | 2 - src/Doctrine/Orm/Filter/RangeFilter.php | 2 - src/Doctrine/Orm/Paginator.php | 2 - src/Doctrine/Orm/PropertyHelperTrait.php | 2 - src/Doctrine/Orm/Util/EagerLoadingTrait.php | 2 - src/Doctrine/Orm/Util/QueryBuilderHelper.php | 2 - src/Doctrine/Orm/Util/QueryChecker.php | 2 - src/Doctrine/Orm/Util/QueryJoinParser.php | 2 - src/Doctrine/Orm/Util/QueryNameGenerator.php | 2 - .../Action/DocumentationAction.php | 26 +- src/Documentation/Documentation.php | 2 - .../Exception/IndexNotFoundException.php | 2 - .../NonUniqueIdentifierException.php | 2 - .../Extension/AbstractFilterExtension.php | 2 - .../ConstantScoreFilterExtension.php | 2 - src/Elasticsearch/Extension/SortExtension.php | 2 - .../Extension/SortFilterExtension.php | 2 - .../Metadata/Document/DocumentMetadata.php | 2 - .../AttributeDocumentMetadataFactory.php | 2 - .../Factory/CachedDocumentMetadataFactory.php | 2 - .../Factory/CatDocumentMetadataFactory.php | 2 - .../ConfiguredDocumentMetadataFactory.php | 2 - src/Elasticsearch/Paginator.php | 2 - .../Serializer/DocumentNormalizer.php | 2 - .../Serializer/ItemNormalizer.php | 2 - .../InnerFieldsNameConverter.php | 2 - src/Elasticsearch/Util/FieldDatatypeTrait.php | 2 - src/Exception/DeserializationException.php | 2 - src/Exception/FilterValidationException.php | 2 - src/Exception/InvalidArgumentException.php | 2 - src/Exception/InvalidIdentifierException.php | 2 - src/Exception/InvalidResourceException.php | 2 - src/Exception/InvalidValueException.php | 2 - src/Exception/ItemNotFoundException.php | 2 - src/Exception/PropertyNotFoundException.php | 2 - .../ResourceClassNotFoundException.php | 2 - .../ResourceClassNotSupportedException.php | 2 - src/Exception/RuntimeException.php | 2 - src/GraphQl/Action/EntrypointAction.php | 2 - .../Action/GraphQlPlaygroundAction.php | 2 - src/GraphQl/Action/GraphiQlAction.php | 2 - src/GraphQl/Error/ErrorHandler.php | 2 - src/GraphQl/Executor.php | 2 - src/GraphQl/Resolver/Util/IdentifierTrait.php | 2 - src/GraphQl/Serializer/ItemNormalizer.php | 11 +- src/GraphQl/Type/Definition/IterableType.php | 2 - src/GraphQl/Type/Definition/UploadType.php | 2 - src/GraphQl/Type/TypeNotFoundException.php | 2 - src/GraphQl/Type/TypesContainer.php | 2 - src/GraphQl/Type/TypesFactory.php | 2 - src/Hal/Serializer/CollectionNormalizer.php | 2 - src/Hal/Serializer/EntrypointNormalizer.php | 2 - src/Hal/Serializer/ItemNormalizer.php | 10 +- src/Hal/Serializer/ObjectNormalizer.php | 2 - .../EventListener/AddHeadersListener.php | 2 - .../EventListener/AddTagsListener.php | 2 - src/HttpCache/VarnishPurger.php | 2 - src/HttpCache/VarnishXKeyPurger.php | 2 - .../EventListener/AddLinkHeaderListener.php | 2 - .../CollectionFiltersNormalizer.php | 2 - src/Hydra/Serializer/CollectionNormalizer.php | 2 - .../ConstraintViolationListNormalizer.php | 2 - .../Serializer/DocumentationNormalizer.php | 2 - src/Hydra/Serializer/EntrypointNormalizer.php | 2 - src/Hydra/Serializer/ErrorNormalizer.php | 2 - .../PartialCollectionViewNormalizer.php | 2 - .../Serializer/CollectionNormalizer.php | 2 - .../ConstraintViolationListNormalizer.php | 2 - .../Serializer/EntrypointNormalizer.php | 2 - src/JsonApi/Serializer/ErrorNormalizer.php | 2 - src/JsonApi/Serializer/ItemNormalizer.php | 32 +- src/JsonApi/Serializer/ObjectNormalizer.php | 2 - .../ReservedAttributeNameConverter.php | 2 - src/JsonLd/Action/ContextAction.php | 2 - src/JsonLd/ContextBuilder.php | 2 - src/JsonLd/Serializer/ItemNormalizer.php | 39 +- src/JsonLd/Serializer/JsonLdContextTrait.php | 2 - src/JsonLd/Serializer/ObjectNormalizer.php | 2 - .../Command/JsonSchemaGenerateCommand.php | 2 - src/JsonSchema/Schema.php | 2 - src/JsonSchema/TypeFactory.php | 2 - .../CachedPropertyNameCollectionFactory.php | 2 - ...ExtractorPropertyNameCollectionFactory.php | 2 - ...pertyInfoPropertyNameCollectionFactory.php | 2 - .../Property/PropertyNameCollection.php | 2 - .../Resource/ResourceMetadataCollection.php | 5 + src/OpenApi/Factory/OpenApiFactory.php | 13 +- src/OpenApi/Model/Components.php | 2 - src/OpenApi/Model/Contact.php | 2 - src/OpenApi/Model/Encoding.php | 2 - src/OpenApi/Model/ExtensionTrait.php | 2 - src/OpenApi/Model/ExternalDocumentation.php | 2 - src/OpenApi/Model/Info.php | 2 - src/OpenApi/Model/License.php | 2 - src/OpenApi/Model/Link.php | 2 - src/OpenApi/Model/MediaType.php | 2 - src/OpenApi/Model/OAuthFlow.php | 2 - src/OpenApi/Model/OAuthFlows.php | 2 - src/OpenApi/Model/Operation.php | 2 - src/OpenApi/Model/Parameter.php | 2 - src/OpenApi/Model/PathItem.php | 2 - src/OpenApi/Model/Paths.php | 2 - src/OpenApi/Model/RequestBody.php | 2 - src/OpenApi/Model/Response.php | 2 - src/OpenApi/Model/Schema.php | 2 - src/OpenApi/Model/SecurityScheme.php | 2 - src/OpenApi/Model/Server.php | 2 - src/OpenApi/OpenApi.php | 2 - src/OpenApi/Options.php | 2 - .../Serializer/ApiGatewayNormalizer.php | 2 - src/OpenApi/Serializer/OpenApiNormalizer.php | 2 - .../DashPathSegmentNameGenerator.php | 2 - .../UnderscorePathSegmentNameGenerator.php | 2 - .../CustomOperationPathResolver.php | 49 -- src/PathResolver/OperationPathResolver.php | 68 --- .../OperationPathResolverInterface.php | 32 -- .../ConstraintViolationListNormalizer.php | 2 - src/Problem/Serializer/ErrorNormalizer.php | 2 - .../Serializer/ErrorNormalizerTrait.php | 2 - .../Serializer/UuidDenormalizer.php | 2 - .../AbstractCollectionNormalizer.php | 2 - ...tractConstraintViolationListNormalizer.php | 2 - src/Serializer/AbstractItemNormalizer.php | 185 +------ src/Serializer/CacheKeyTrait.php | 2 - src/Serializer/ContextTrait.php | 2 - src/Serializer/Filter/GroupFilter.php | 2 - src/Serializer/Filter/PropertyFilter.php | 2 - src/Serializer/InputOutputMetadataTrait.php | 2 - src/Serializer/ItemNormalizer.php | 47 +- src/Serializer/JsonEncoder.php | 2 - .../Mapping/Factory/ClassMetadataFactory.php | 2 - src/Serializer/ResourceList.php | 2 - src/Serializer/SerializerContextBuilder.php | 146 +----- .../SerializerFilterContextBuilder.php | 2 - src/State/Pagination/ArrayPaginator.php | 2 - src/State/Pagination/PaginationOptions.php | 2 - src/State/Pagination/TraversablePaginator.php | 2 - src/Symfony/Bundle/ApiPlatformBundle.php | 2 - .../PayloadArgumentResolver.php | 2 - .../CachePoolClearerCacheWarmer.php | 2 - .../Bundle/Command/GraphQlExportCommand.php | 2 - src/Symfony/Bundle/Command/OpenApiCommand.php | 2 - .../DataCollector/RequestDataCollector.php | 79 --- .../ApiPlatformExtension.php | 272 +--------- .../Compiler/AnnotationFilterPass.php | 2 - .../Compiler/AuthenticatorManagerPass.php | 2 - .../Compiler/DataProviderPass.php | 20 - .../DeprecateMercurePublisherPass.php | 2 - .../Compiler/ElasticsearchClientPass.php | 2 - .../Compiler/FilterPass.php | 2 - .../Compiler/GraphQlMutationResolverPass.php | 2 - .../Compiler/GraphQlQueryResolverPass.php | 2 - .../Compiler/GraphQlTypePass.php | 2 - .../MetadataAwareNameConverterPass.php | 2 - .../Compiler/TestClientPass.php | 2 - .../DependencyInjection/Configuration.php | 1 - .../EventListener/SwaggerUiListener.php | 2 - src/Symfony/Bundle/Resources/config/api.xml | 65 ++- .../config/{v3 => }/data_collector.xml | 4 - .../Resources/config/data_persister.xml | 14 - src/Symfony/Bundle/Resources/config/debug.xml | 7 + .../Resources/config/doctrine_mongodb_odm.xml | 48 ++ .../doctrine_odm_mercure_publisher.xml | 0 .../Bundle/Resources/config/doctrine_orm.xml | 43 ++ .../doctrine_orm_mercure_publisher.xml | 0 .../Bundle/Resources/config/elasticsearch.xml | 24 + .../Bundle/Resources/config/fos_user.xml | 15 - .../Bundle/Resources/config/graphql.xml | 189 +++++++ .../Bundle/Resources/config/legacy/README | 1 - .../Bundle/Resources/config/legacy/api.xml | 143 ------ .../config/legacy/backward_compatibility.xml | 30 -- .../config/legacy/data_collector.xml | 25 - .../Resources/config/legacy/data_provider.xml | 29 -- .../Bundle/Resources/config/legacy/debug.xml | 26 - .../Resources/config/legacy/doctrine_odm.xml | 72 --- .../legacy/doctrine_odm_mercure_publisher.xml | 28 - .../Resources/config/legacy/doctrine_orm.xml | 64 --- .../legacy/doctrine_orm_mercure_publisher.xml | 28 - .../Resources/config/legacy/graphql.xml | 283 ----------- .../config/legacy/graphql_mercure.xml | 16 - .../Resources/config/legacy/identifiers.xml | 34 -- .../Resources/config/legacy/metadata.xml | 106 ---- .../config/legacy/metadata_annotation.xml | 34 -- .../metadata_backward_compatibility.xml | 11 - .../config/legacy/metadata_php_doc.xml | 11 - .../Resources/config/legacy/metadata_yaml.xml | 29 -- .../metadata_yaml_backward_compatibility.xml | 7 - .../Resources/config/legacy/openapi.xml | 23 - .../Resources/config/legacy/swagger.xml | 71 --- .../Resources/config/legacy/swagger_ui.xml | 20 - .../Resources/config/legacy/upgrade.xml | 20 - .../Resources/config/legacy/validator.xml | 92 ---- src/Symfony/Bundle/Resources/config/maker.xml | 18 +- .../Bundle/Resources/config/messenger.xml | 12 +- .../Resources/config/metadata/property.xml | 7 +- .../config/metadata/resource_name.xml | 4 + .../Resources/config/nelmio_api_doc.xml | 28 - .../Bundle/Resources/config/openapi.xml | 16 + .../config/{data_provider.xml => state.xml} | 21 +- .../Bundle/Resources/config/swagger_ui.xml | 29 +- .../{symfony.xml => symfony/events.xml} | 0 .../{symfony_uid.xml => symfony/uid.xml} | 0 .../Bundle/Resources/config/v3/api.xml | 65 --- .../config/v3/backward_compatibility.xml | 49 -- .../Bundle/Resources/config/v3/debug.xml | 15 - .../Resources/config/v3/doctrine_odm.xml | 57 --- .../Resources/config/v3/doctrine_orm.xml | 48 -- .../Resources/config/v3/elasticsearch.xml | 33 -- .../Bundle/Resources/config/v3/graphql.xml | 196 ------- .../Resources/config/v3/graphql_mercure.xml | 15 - .../Bundle/Resources/config/v3/messenger.xml | 11 - .../Bundle/Resources/config/v3/metadata.xml | 13 - .../Bundle/Resources/config/v3/openapi.xml | 25 - .../Bundle/Resources/config/v3/state.xml | 25 - .../Bundle/Resources/config/v3/swagger_ui.xml | 21 - .../Bundle/SwaggerUi/SwaggerUiAction.php | 2 - .../Bundle/SwaggerUi/SwaggerUiContext.php | 2 - .../Bundle/Test/ApiTestAssertionsTrait.php | 2 - src/Symfony/Bundle/Test/ApiTestCase.php | 2 - src/Symfony/Bundle/Test/Client.php | 2 - .../Bundle/Test/Constraint/ArraySubset.php | 4 - src/Symfony/Bundle/Test/Response.php | 2 - .../EventListener/AddFormatListener.php | 2 - .../EventListener/AddLinkHeaderListener.php | 2 - .../EventListener/DenyAccessListener.php | 2 - .../EventListener/DeserializeListener.php | 61 +-- src/Symfony/EventListener/EventPriorities.php | 2 - .../EventListener/ExceptionListener.php | 2 - .../TransformFieldsetsParametersListener.php | 2 - .../TransformFilteringParametersListener.php | 2 - .../TransformPaginationParametersListener.php | 2 - .../TransformSortingParametersListener.php | 2 - .../QueryParameterValidateListener.php | 43 +- src/Symfony/EventListener/RespondListener.php | 2 - .../EventListener/SerializeListener.php | 31 +- .../EventListener/ValidateListener.php | 39 +- src/Symfony/Messenger/ContextStamp.php | 2 - src/Symfony/Messenger/DispatchTrait.php | 2 - src/Symfony/Messenger/RemoveStamp.php | 2 - src/Symfony/Routing/ApiLoader.php | 208 +------- src/Symfony/Routing/Router.php | 2 - .../ExpressionLanguageProvider.php | 2 - src/Symfony/Security/ExpressionLanguage.php | 2 - .../Security/ResourceAccessChecker.php | 2 - .../ValidationExceptionListener.php | 2 - .../Exception/ValidationException.php | 2 - src/Symfony/Validator/Validator.php | 2 - src/Test/DoctrineMongoDbOdmFilterTestCase.php | 2 - src/Test/DoctrineMongoDbOdmSetup.php | 2 - src/Test/DoctrineMongoDbOdmTestCase.php | 2 - src/Test/DoctrineOrmFilterTestCase.php | 2 - src/Util/AnnotationFilterExtractorTrait.php | 2 - src/Util/ArrayTrait.php | 2 - src/Util/AttributesExtractor.php | 40 +- src/Util/CachedTrait.php | 2 - src/Util/ClassInfoTrait.php | 2 - src/Util/ClientTrait.php | 2 - src/Util/CloneTrait.php | 2 - src/Util/CorsTrait.php | 2 - src/Util/ErrorFormatGuesser.php | 2 - src/Util/Inflector.php | 2 - src/Util/IriHelper.php | 2 - src/Util/Reflection.php | 2 - src/Util/ReflectionClassRecursiveIterator.php | 2 - src/Util/RequestAttributesExtractor.php | 2 - src/Util/RequestParser.php | 2 - src/Util/ResourceClassInfoTrait.php | 2 - src/Util/ResponseTrait.php | 2 - src/Util/SortTrait.php | 2 - .../Exception/ValidationException.php | 2 - src/deprecated_interfaces.php | 121 ----- src/deprecation.php | 478 ------------------ 321 files changed, 593 insertions(+), 4350 deletions(-) delete mode 100644 src/PathResolver/CustomOperationPathResolver.php delete mode 100644 src/PathResolver/OperationPathResolver.php delete mode 100644 src/PathResolver/OperationPathResolverInterface.php rename src/Symfony/Bundle/Resources/config/{v3 => }/data_collector.xml (75%) delete mode 100644 src/Symfony/Bundle/Resources/config/data_persister.xml rename src/Symfony/Bundle/Resources/config/{v3 => }/doctrine_odm_mercure_publisher.xml (100%) rename src/Symfony/Bundle/Resources/config/{v3 => }/doctrine_orm_mercure_publisher.xml (100%) delete mode 100644 src/Symfony/Bundle/Resources/config/fos_user.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/README delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/api.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/backward_compatibility.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/data_collector.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/data_provider.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/debug.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/doctrine_odm.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/doctrine_odm_mercure_publisher.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/doctrine_orm.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/doctrine_orm_mercure_publisher.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/graphql.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/graphql_mercure.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/identifiers.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/metadata.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/metadata_annotation.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/metadata_backward_compatibility.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/metadata_php_doc.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/metadata_yaml.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/metadata_yaml_backward_compatibility.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/openapi.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/swagger.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/swagger_ui.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/upgrade.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/validator.xml delete mode 100644 src/Symfony/Bundle/Resources/config/nelmio_api_doc.xml rename src/Symfony/Bundle/Resources/config/{data_provider.xml => state.xml} (61%) rename src/Symfony/Bundle/Resources/config/{symfony.xml => symfony/events.xml} (100%) rename src/Symfony/Bundle/Resources/config/{symfony_uid.xml => symfony/uid.xml} (100%) delete mode 100644 src/Symfony/Bundle/Resources/config/v3/api.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/backward_compatibility.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/debug.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/elasticsearch.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/graphql.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/graphql_mercure.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/messenger.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/metadata.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/openapi.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/state.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml delete mode 100644 src/deprecated_interfaces.php delete mode 100644 src/deprecation.php diff --git a/src/Action/EntrypointAction.php b/src/Action/EntrypointAction.php index 1771db220d3..c256865f35a 100644 --- a/src/Action/EntrypointAction.php +++ b/src/Action/EntrypointAction.php @@ -35,5 +35,3 @@ public function __invoke(): Entrypoint return new Entrypoint($this->resourceNameCollectionFactory->create()); } } - -class_alias(EntrypointAction::class, \ApiPlatform\Core\Action\EntrypointAction::class); diff --git a/src/Action/ExceptionAction.php b/src/Action/ExceptionAction.php index b5fd5f63ef9..ac9d4106fc3 100644 --- a/src/Action/ExceptionAction.php +++ b/src/Action/ExceptionAction.php @@ -116,5 +116,3 @@ private function getOperationExceptionToStatus(Request $request): array ); } } - -class_alias(ExceptionAction::class, \ApiPlatform\Core\Action\ExceptionAction::class); diff --git a/src/Action/NotFoundAction.php b/src/Action/NotFoundAction.php index 2e5e1d2cf95..546811fee66 100644 --- a/src/Action/NotFoundAction.php +++ b/src/Action/NotFoundAction.php @@ -25,5 +25,3 @@ public function __invoke() throw new NotFoundHttpException(); } } - -class_alias(NotFoundAction::class, \ApiPlatform\Core\Action\NotFoundAction::class); diff --git a/src/Action/PlaceholderAction.php b/src/Action/PlaceholderAction.php index 5ed07426db2..79cc83f8371 100644 --- a/src/Action/PlaceholderAction.php +++ b/src/Action/PlaceholderAction.php @@ -30,5 +30,3 @@ public function __invoke($data) return $data; } } - -class_alias(PlaceholderAction::class, \ApiPlatform\Core\Action\PlaceholderAction::class); diff --git a/src/Api/Entrypoint.php b/src/Api/Entrypoint.php index e3289f62559..ed654c01cdb 100644 --- a/src/Api/Entrypoint.php +++ b/src/Api/Entrypoint.php @@ -34,5 +34,3 @@ public function getResourceNameCollection(): ResourceNameCollection return $this->resourceNameCollection; } } - -class_alias(Entrypoint::class, \ApiPlatform\Core\Api\Entrypoint::class); diff --git a/src/Api/FilterLocatorTrait.php b/src/Api/FilterLocatorTrait.php index 10f3ab96d2d..f7281f92003 100644 --- a/src/Api/FilterLocatorTrait.php +++ b/src/Api/FilterLocatorTrait.php @@ -62,5 +62,3 @@ private function getFilter(string $filterId): ?FilterInterface return null; } } - -class_alias(FilterLocatorTrait::class, \ApiPlatform\Core\Api\FilterLocatorTrait::class); diff --git a/src/Api/FormatMatcher.php b/src/Api/FormatMatcher.php index a5aed0185ab..c86270c10de 100644 --- a/src/Api/FormatMatcher.php +++ b/src/Api/FormatMatcher.php @@ -62,5 +62,3 @@ public function getFormat(string $mimeType): ?string return null; } } - -class_alias(FormatMatcher::class, \ApiPlatform\Core\Api\FormatMatcher::class); diff --git a/src/Api/QueryParameterValidator/QueryParameterValidator.php b/src/Api/QueryParameterValidator/QueryParameterValidator.php index 67f3c725209..53c0d8c73d0 100644 --- a/src/Api/QueryParameterValidator/QueryParameterValidator.php +++ b/src/Api/QueryParameterValidator/QueryParameterValidator.php @@ -64,5 +64,3 @@ public function validateFilters(string $resourceClass, array $resourceFilters, a } } } - -class_alias(QueryParameterValidator::class, \ApiPlatform\Core\Filter\QueryParameterValidator::class); diff --git a/src/Api/QueryParameterValidator/Validator/ArrayItems.php b/src/Api/QueryParameterValidator/Validator/ArrayItems.php index c2e65758de1..af8851377ef 100644 --- a/src/Api/QueryParameterValidator/Validator/ArrayItems.php +++ b/src/Api/QueryParameterValidator/Validator/ArrayItems.php @@ -84,5 +84,3 @@ private static function getSeparator(string $collectionFormat): string } } } - -class_alias(ArrayItems::class, \ApiPlatform\Core\Filter\Validator\ArrayItems::class); diff --git a/src/Api/QueryParameterValidator/Validator/Bounds.php b/src/Api/QueryParameterValidator/Validator/Bounds.php index 1cef0ba9ad4..eebc40b3eca 100644 --- a/src/Api/QueryParameterValidator/Validator/Bounds.php +++ b/src/Api/QueryParameterValidator/Validator/Bounds.php @@ -49,5 +49,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return $errorList; } } - -class_alias(Bounds::class, \ApiPlatform\Core\Filter\Validator\Bounds::class); diff --git a/src/Api/QueryParameterValidator/Validator/Enum.php b/src/Api/QueryParameterValidator/Validator/Enum.php index 72ad2056268..2e0bf5c277b 100644 --- a/src/Api/QueryParameterValidator/Validator/Enum.php +++ b/src/Api/QueryParameterValidator/Validator/Enum.php @@ -36,5 +36,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } } - -class_alias(Enum::class, \ApiPlatform\Core\Filter\Validator\Enum::class); diff --git a/src/Api/QueryParameterValidator/Validator/Length.php b/src/Api/QueryParameterValidator/Validator/Length.php index 4d658898bdd..0b0c67e5595 100644 --- a/src/Api/QueryParameterValidator/Validator/Length.php +++ b/src/Api/QueryParameterValidator/Validator/Length.php @@ -41,5 +41,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return $errorList; } } - -class_alias(Length::class, \ApiPlatform\Core\Filter\Validator\Length::class); diff --git a/src/Api/QueryParameterValidator/Validator/MultipleOf.php b/src/Api/QueryParameterValidator/Validator/MultipleOf.php index 197d081bcd0..6da33972688 100644 --- a/src/Api/QueryParameterValidator/Validator/MultipleOf.php +++ b/src/Api/QueryParameterValidator/Validator/MultipleOf.php @@ -36,5 +36,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } } - -class_alias(MultipleOf::class, \ApiPlatform\Core\Filter\Validator\MultipleOf::class); diff --git a/src/Api/QueryParameterValidator/Validator/Pattern.php b/src/Api/QueryParameterValidator/Validator/Pattern.php index 414b7cc8da8..a585fd8b321 100644 --- a/src/Api/QueryParameterValidator/Validator/Pattern.php +++ b/src/Api/QueryParameterValidator/Validator/Pattern.php @@ -36,5 +36,3 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } } - -class_alias(Pattern::class, \ApiPlatform\Core\Filter\Validator\Pattern::class); diff --git a/src/Api/QueryParameterValidator/Validator/Required.php b/src/Api/QueryParameterValidator/Validator/Required.php index 308bdbf354d..0045b0513b4 100644 --- a/src/Api/QueryParameterValidator/Validator/Required.php +++ b/src/Api/QueryParameterValidator/Validator/Required.php @@ -100,5 +100,3 @@ private function requestGetQueryParameter(array $queryParameters, string $name) return $queryParameters[(string) $rootName]; } } - -class_alias(Required::class, \ApiPlatform\Core\Filter\Validator\Required::class); diff --git a/src/Api/ResourceClassResolver.php b/src/Api/ResourceClassResolver.php index e0f9243458c..b1bec160917 100644 --- a/src/Api/ResourceClassResolver.php +++ b/src/Api/ResourceClassResolver.php @@ -109,5 +109,3 @@ public function isResourceClass(string $type): bool return $this->localIsResourceClassCache[$type] = false; } } - -class_alias(ResourceClassResolver::class, \ApiPlatform\Core\Api\ResourceClassResolver::class); diff --git a/src/Doctrine/Common/Filter/BooleanFilterTrait.php b/src/Doctrine/Common/Filter/BooleanFilterTrait.php index 41173d4fe46..199dc54763d 100644 --- a/src/Doctrine/Common/Filter/BooleanFilterTrait.php +++ b/src/Doctrine/Common/Filter/BooleanFilterTrait.php @@ -97,5 +97,3 @@ private function normalizeValue($value, string $property): ?bool return null; } } - -class_alias(BooleanFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\BooleanFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/DateFilterTrait.php b/src/Doctrine/Common/Filter/DateFilterTrait.php index 11f9c5aa10d..958af548aca 100644 --- a/src/Doctrine/Common/Filter/DateFilterTrait.php +++ b/src/Doctrine/Common/Filter/DateFilterTrait.php @@ -94,5 +94,3 @@ private function normalizeValue($value, string $operator): ?string return $value; } } - -class_alias(DateFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\DateFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/ExistsFilterTrait.php b/src/Doctrine/Common/Filter/ExistsFilterTrait.php index 25895f4f158..41cfe4a36a0 100644 --- a/src/Doctrine/Common/Filter/ExistsFilterTrait.php +++ b/src/Doctrine/Common/Filter/ExistsFilterTrait.php @@ -100,5 +100,3 @@ private function normalizeValue($value, string $property): ?bool return null; } } - -class_alias(ExistsFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\ExistsFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/NumericFilterTrait.php b/src/Doctrine/Common/Filter/NumericFilterTrait.php index 0a946372c8a..5d4850d6644 100644 --- a/src/Doctrine/Common/Filter/NumericFilterTrait.php +++ b/src/Doctrine/Common/Filter/NumericFilterTrait.php @@ -122,5 +122,3 @@ protected function isNumericArray(array $values): bool return true; } } - -class_alias(NumericFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\NumericFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/OrderFilterTrait.php b/src/Doctrine/Common/Filter/OrderFilterTrait.php index faf92372523..8d7ad9d302f 100644 --- a/src/Doctrine/Common/Filter/OrderFilterTrait.php +++ b/src/Doctrine/Common/Filter/OrderFilterTrait.php @@ -84,5 +84,3 @@ private function normalizeValue($value, string $property): ?string return $value; } } - -class_alias(OrderFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\OrderFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index 007d59f0db6..6051ac48efd 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -139,5 +139,3 @@ private function normalizeValue(string $value, string $operator) return $value + 0; // coerce $value to the right type. } } - -class_alias(RangeFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\RangeFilterTrait::class); diff --git a/src/Doctrine/Common/Filter/SearchFilterTrait.php b/src/Doctrine/Common/Filter/SearchFilterTrait.php index f74a0a4b90a..1aa89b8ab8b 100644 --- a/src/Doctrine/Common/Filter/SearchFilterTrait.php +++ b/src/Doctrine/Common/Filter/SearchFilterTrait.php @@ -176,5 +176,3 @@ protected function hasValidValues(array $values, $type = null): bool return true; } } - -class_alias(SearchFilterTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterTrait::class); diff --git a/src/Doctrine/Common/PropertyHelperTrait.php b/src/Doctrine/Common/PropertyHelperTrait.php index 573e30baac5..21ec57b8be2 100644 --- a/src/Doctrine/Common/PropertyHelperTrait.php +++ b/src/Doctrine/Common/PropertyHelperTrait.php @@ -169,5 +169,3 @@ protected function getClassMetadata(string $resourceClass): ClassMetadata ->getClassMetadata($resourceClass); } } - -class_alias(PropertyHelperTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Common\PropertyHelperTrait::class); diff --git a/src/Doctrine/EventListener/PurgeHttpCacheListener.php b/src/Doctrine/EventListener/PurgeHttpCacheListener.php index 7fa2b10eb8a..59534ee8985 100644 --- a/src/Doctrine/EventListener/PurgeHttpCacheListener.php +++ b/src/Doctrine/EventListener/PurgeHttpCacheListener.php @@ -171,5 +171,3 @@ private function addTagForItem($value): void } } } - -class_alias(PurgeHttpCacheListener::class, \ApiPlatform\Core\Bridge\Doctrine\EventListener\PurgeHttpCacheListener::class); diff --git a/src/Doctrine/EventListener/WriteListener.php b/src/Doctrine/EventListener/WriteListener.php index 5938b6223ba..808d298f34f 100644 --- a/src/Doctrine/EventListener/WriteListener.php +++ b/src/Doctrine/EventListener/WriteListener.php @@ -84,5 +84,3 @@ private function getManager(string $resourceClass, $data): ?ObjectManager return $objectManager; } } - -class_alias(WriteListener::class, \ApiPlatform\Core\Bridge\Doctrine\EventListener\WriteListener::class); diff --git a/src/Doctrine/Odm/Extension/FilterExtension.php b/src/Doctrine/Odm/Extension/FilterExtension.php index b5442791c67..b5df5addbc1 100644 --- a/src/Doctrine/Odm/Extension/FilterExtension.php +++ b/src/Doctrine/Odm/Extension/FilterExtension.php @@ -77,5 +77,3 @@ public function applyToCollection(Builder $aggregationBuilder, string $resourceC } } } - -class_alias(FilterExtension::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\FilterExtension::class); diff --git a/src/Doctrine/Odm/Filter/AbstractFilter.php b/src/Doctrine/Odm/Filter/AbstractFilter.php index b568ebfb3b8..567d9a8a1fb 100644 --- a/src/Doctrine/Odm/Filter/AbstractFilter.php +++ b/src/Doctrine/Odm/Filter/AbstractFilter.php @@ -111,5 +111,3 @@ protected function normalizePropertyName($property) return implode('.', array_map([$this->nameConverter, 'normalize'], explode('.', (string) $property))); } } - -class_alias(AbstractFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\AbstractFilter::class); diff --git a/src/Doctrine/Odm/Filter/BooleanFilter.php b/src/Doctrine/Odm/Filter/BooleanFilter.php index 1e295ab76da..111760aa251 100644 --- a/src/Doctrine/Odm/Filter/BooleanFilter.php +++ b/src/Doctrine/Odm/Filter/BooleanFilter.php @@ -68,5 +68,3 @@ protected function filterProperty(string $property, $value, Builder $aggregation $aggregationBuilder->match()->field($matchField)->equals($value); } } - -class_alias(BooleanFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\BooleanFilter::class); diff --git a/src/Doctrine/Odm/Filter/DateFilter.php b/src/Doctrine/Odm/Filter/DateFilter.php index 92a48f7674f..9b64b4b4a56 100644 --- a/src/Doctrine/Odm/Filter/DateFilter.php +++ b/src/Doctrine/Odm/Filter/DateFilter.php @@ -151,5 +151,3 @@ private function addMatch(Builder $aggregationBuilder, string $field, string $op $aggregationBuilder->match()->addAnd($aggregationBuilder->matchExpr()->field($field)->operator($operatorValue[$operator], $value)); } } - -class_alias(DateFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\DateFilter::class); diff --git a/src/Doctrine/Odm/Filter/ExistsFilter.php b/src/Doctrine/Odm/Filter/ExistsFilter.php index 0e723437604..829d60315d5 100644 --- a/src/Doctrine/Odm/Filter/ExistsFilter.php +++ b/src/Doctrine/Odm/Filter/ExistsFilter.php @@ -105,5 +105,3 @@ protected function isNullableField(string $property, string $resourceClass): boo return $metadata instanceof ClassMetadata && $metadata->hasField($field) ? $metadata->isNullable($field) : false; } } - -class_alias(ExistsFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\ExistsFilter::class); diff --git a/src/Doctrine/Odm/Filter/NumericFilter.php b/src/Doctrine/Odm/Filter/NumericFilter.php index 84f1517b7ee..e6766af8a98 100644 --- a/src/Doctrine/Odm/Filter/NumericFilter.php +++ b/src/Doctrine/Odm/Filter/NumericFilter.php @@ -91,5 +91,3 @@ protected function getType(string $doctrineType = null): string return 'int'; } } - -class_alias(NumericFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\NumericFilter::class); diff --git a/src/Doctrine/Odm/Filter/OrderFilter.php b/src/Doctrine/Odm/Filter/OrderFilter.php index 02d31b9c011..60c6df2f7cd 100644 --- a/src/Doctrine/Odm/Filter/OrderFilter.php +++ b/src/Doctrine/Odm/Filter/OrderFilter.php @@ -105,5 +105,3 @@ protected function filterProperty(string $property, $direction, Builder $aggrega ); } } - -class_alias(OrderFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\OrderFilter::class); diff --git a/src/Doctrine/Odm/Filter/RangeFilter.php b/src/Doctrine/Odm/Filter/RangeFilter.php index 9dbcf22318d..b6c1c7d9d48 100644 --- a/src/Doctrine/Odm/Filter/RangeFilter.php +++ b/src/Doctrine/Odm/Filter/RangeFilter.php @@ -126,5 +126,3 @@ protected function addMatch(Builder $aggregationBuilder, string $field, string $ } } } - -class_alias(RangeFilter::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\RangeFilter::class); diff --git a/src/Doctrine/Odm/Paginator.php b/src/Doctrine/Odm/Paginator.php index 11ff2ae9411..69efc1baf86 100644 --- a/src/Doctrine/Odm/Paginator.php +++ b/src/Doctrine/Odm/Paginator.php @@ -184,5 +184,3 @@ private function hasLimitZeroStage(array $resultsFacetInfo): bool return false; } } - -class_alias(Paginator::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator::class); diff --git a/src/Doctrine/Odm/PropertyHelperTrait.php b/src/Doctrine/Odm/PropertyHelperTrait.php index ca8f20715b5..436293cf694 100644 --- a/src/Doctrine/Odm/PropertyHelperTrait.php +++ b/src/Doctrine/Odm/PropertyHelperTrait.php @@ -105,5 +105,3 @@ protected function addLookupsForNestedProperty(string $property, Builder $aggreg return [$property, $propertyParts['field'], $propertyParts['associations']]; } } - -class_alias(PropertyHelperTrait::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyHelperTrait::class); diff --git a/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php b/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php index d6c22d3f185..511d5adb10d 100644 --- a/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php +++ b/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php @@ -183,5 +183,3 @@ private function getPhpType(string $doctrineType): ?string return null; } } - -class_alias(DoctrineExtractor::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyInfo\DoctrineExtractor::class); diff --git a/src/Doctrine/Orm/AbstractPaginator.php b/src/Doctrine/Orm/AbstractPaginator.php index 258ab792de9..f024925012b 100644 --- a/src/Doctrine/Orm/AbstractPaginator.php +++ b/src/Doctrine/Orm/AbstractPaginator.php @@ -77,5 +77,3 @@ public function count(): int return iterator_count($this->getIterator()); } } - -class_alias(AbstractPaginator::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\AbstractPaginator::class); diff --git a/src/Doctrine/Orm/Extension/EagerLoadingExtension.php b/src/Doctrine/Orm/Extension/EagerLoadingExtension.php index bac34438d46..a3f224bfd3e 100644 --- a/src/Doctrine/Orm/Extension/EagerLoadingExtension.php +++ b/src/Doctrine/Orm/Extension/EagerLoadingExtension.php @@ -13,10 +13,6 @@ namespace ApiPlatform\Doctrine\Orm\Extension; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; @@ -27,14 +23,14 @@ use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyMetadata; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\Query\Expr\Select; use Doctrine\ORM\QueryBuilder; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; @@ -55,38 +51,16 @@ final class EagerLoadingExtension implements ContextAwareQueryCollectionExtensio private $propertyMetadataFactory; private $classMetadataFactory; private $maxJoins; - private $serializerContextBuilder; - private $requestStack; - /** - * @TODO move $fetchPartial after $forceEager (@soyuka) in 3.0 - * - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - * @param PropertyMetadataFactoryInterface|LegacyPropertyMetadataFactory $propertyMetadataFactory - */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory, int $maxJoins = 30, bool $forceEager = true, RequestStack $requestStack = null, SerializerContextBuilderInterface $serializerContextBuilder = null, bool $fetchPartial = false, ClassMetadataFactoryInterface $classMetadataFactory = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, int $maxJoins = 30, bool $forceEager = true, bool $fetchPartial = false, ClassMetadataFactoryInterface $classMetadataFactory = null) { - if (null !== $this->requestStack) { - @trigger_error(sprintf('Passing an instance of "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the data provider\'s context instead.', RequestStack::class), \E_USER_DEPRECATED); - } - if (null !== $this->serializerContextBuilder) { - @trigger_error(sprintf('Passing an instance of "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the data provider\'s context instead.', SerializerContextBuilderInterface::class), \E_USER_DEPRECATED); - } - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->classMetadataFactory = $classMetadataFactory; $this->maxJoins = $maxJoins; $this->forceEager = $forceEager; $this->fetchPartial = $fetchPartial; - $this->serializerContextBuilder = $serializerContextBuilder; - $this->requestStack = $requestStack; } /** @@ -122,29 +96,19 @@ private function apply(bool $collection, QueryBuilder $queryBuilder, QueryNameGe $operation = null; $forceEager = $this->forceEager; $fetchPartial = $this->fetchPartial; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $resourceMetadataCollection->getOperation($operationName); - $forceEager = $operation->getForceEager() ?? $this->forceEager; - $fetchPartial = $operation->getFetchPartial() ?? $this->fetchPartial; - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - } - } else { - $forceEager = $this->shouldOperationForceEager($resourceClass, $options); - $fetchPartial = $this->shouldOperationFetchPartial($resourceClass, $options); + $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); + try { + $operation = $resourceMetadataCollection->getOperation($operationName); + $forceEager = $operation->getForceEager() ?? $this->forceEager; + $fetchPartial = $operation->getFetchPartial() ?? $this->fetchPartial; + } catch (OperationNotFoundException $e) { + // In some cases the operation may not exist } if (!isset($context['groups']) && !isset($context['attributes'])) { $contextType = isset($context['api_denormalize']) ? 'denormalization_context' : 'normalization_context'; - if (null !== $this->requestStack && null !== $this->serializerContextBuilder && null !== $request = $this->requestStack->getCurrentRequest()) { - $context += $this->serializerContextBuilder->createFromRequest($request, 'normalization_context' === $contextType); - } elseif ($operation) { + if ($operation) { $context += 'denormalization_context' === $contextType ? ($operation->getDenormalizationContext() ?? []) : ($operation->getNormalizationContext() ?? []); - } elseif (!$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - // TODO: remove in 3.0 - $context += $this->getNormalizationContext($context['resource_class'] ?? $resourceClass, $contextType, $options); } } @@ -156,9 +120,12 @@ private function apply(bool $collection, QueryBuilder $queryBuilder, QueryNameGe $options['serializer_groups'] = (array) $context[AbstractNormalizer::GROUPS]; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $options['normalization_groups'] = $operation ? ($operation->getNormalizationContext()['groups'] ?? null) : null; - $options['denormalization_groups'] = $operation ? ($operation->getDenormalizationContext()['groups'] ?? null) : null; + if ($operation && $normalizationGroups = $operation->getNormalizationContext()['groups'] ?? null) { + $options['normalization_groups'] = $normalizationGroups; + } + + if ($operation && $denormalizationGroups = $operation->getDenormalizationContext()['groups'] ?? null) { + $options['denormalization_groups'] = $denormalizationGroups; } $this->joinRelations($queryBuilder, $queryNameGenerator, $resourceClass, $forceEager, $fetchPartial, $queryBuilder->getRootAliases()[0], $options, $context); @@ -191,7 +158,6 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt } try { - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $association, $options); } catch (PropertyNotFoundException $propertyNotFoundException) { // skip properties not found @@ -221,16 +187,7 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt $inAttributes = null; } - $fetchEager = null; - if ($propertyMetadata instanceof ApiProperty) { - $fetchEager = $propertyMetadata->getFetchEager(); - } elseif ( - $propertyMetadata instanceof PropertyMetadata && - (null === $fetchEager = $propertyMetadata->getAttribute('fetch_eager')) && - (null !== $fetchEager = $propertyMetadata->getAttribute('fetchEager')) - ) { - @trigger_error('The "fetchEager" attribute is deprecated since 2.3. Please use "fetch_eager" instead.', \E_USER_DEPRECATED); - } + $fetchEager = $propertyMetadata->getFetchEager(); if (false === $fetchEager) { continue; @@ -320,7 +277,7 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a // If it's an embedded property see below if (!\array_key_exists($property, $targetClassMetadata->embeddedClasses)) { - $isFetchable = $propertyMetadata instanceof ApiProperty ? $propertyMetadata->isFetchable() : $propertyMetadata->getAttribute('fetchable'); + $isFetchable = $propertyMetadata->isFetchable(); // the field test allows to add methods to a Resource which do not reflect real database fields if ($targetClassMetadata->hasField($property) && (true === $isFetchable || $propertyMetadata->isReadable())) { $select[] = $property; @@ -331,7 +288,7 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a // It's an embedded property, select relevant subfields foreach ($this->propertyNameCollectionFactory->create($targetClassMetadata->embeddedClasses[$property]['class']) as $embeddedProperty) { - $isFetchable = $propertyMetadata instanceof ApiProperty ? $propertyMetadata->isFetchable() : $propertyMetadata->getAttribute('fetchable'); + $isFetchable = $propertyMetadata->isFetchable(); $propertyMetadata = $this->propertyMetadataFactory->create($entity, $property, $propertyMetadataOptions); $propertyName = "$property.$embeddedProperty"; if ($targetClassMetadata->hasField($propertyName) && (true === $isFetchable || $propertyMetadata->isReadable())) { @@ -362,10 +319,6 @@ private function addSelectOnce(QueryBuilder $queryBuilder, string $alias) */ private function getNormalizationContext(string $resourceClass, string $contextType, array $options): array { - if (null !== $this->requestStack && null !== $this->serializerContextBuilder && null !== $request = $this->requestStack->getCurrentRequest()) { - return $this->serializerContextBuilder->createFromRequest($request, 'normalization_context' === $contextType); - } - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); if (isset($options['collection_operation_name'])) { $context = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], $contextType, null, true); @@ -378,5 +331,3 @@ private function getNormalizationContext(string $resourceClass, string $contextT return $context ?? []; } } - -class_alias(EagerLoadingExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\EagerLoadingExtension::class); diff --git a/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php b/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php index 6c867abd2c6..453f1146c73 100644 --- a/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php +++ b/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php @@ -202,5 +202,3 @@ private function buildReplacePatterns(array $aliases): array }, $aliases); } } - -class_alias(FilterEagerLoadingExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterEagerLoadingExtension::class); diff --git a/src/Doctrine/Orm/Extension/FilterExtension.php b/src/Doctrine/Orm/Extension/FilterExtension.php index 4a02d630dcd..ceb898ad47f 100644 --- a/src/Doctrine/Orm/Extension/FilterExtension.php +++ b/src/Doctrine/Orm/Extension/FilterExtension.php @@ -106,5 +106,3 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator } } } - -class_alias(FilterExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterExtension::class); diff --git a/src/Doctrine/Orm/Extension/OrderExtension.php b/src/Doctrine/Orm/Extension/OrderExtension.php index 894ccfb2884..b8a29f4e0d5 100644 --- a/src/Doctrine/Orm/Extension/OrderExtension.php +++ b/src/Doctrine/Orm/Extension/OrderExtension.php @@ -115,6 +115,3 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator } } } - -class_alias(OrderExtension::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\OrderExtension::class); -class_alias(OrderExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\OrderExtension::class); diff --git a/src/Doctrine/Orm/Extension/PaginationExtension.php b/src/Doctrine/Orm/Extension/PaginationExtension.php index 8eebdc8707d..10259f41b27 100644 --- a/src/Doctrine/Orm/Extension/PaginationExtension.php +++ b/src/Doctrine/Orm/Extension/PaginationExtension.php @@ -488,6 +488,3 @@ private function shouldDoctrinePaginatorUseOutputWalkers(QueryBuilder $queryBuil return false; } } - -class_alias(PaginationExtension::class, \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\PaginationExtension::class); -class_alias(PaginationExtension::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension::class); diff --git a/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php b/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php index 70ab6c0af51..4385d8f5a95 100644 --- a/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php +++ b/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php @@ -34,5 +34,3 @@ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $q } } } - -class_alias(AbstractContextAwareFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter::class); diff --git a/src/Doctrine/Orm/Filter/AbstractFilter.php b/src/Doctrine/Orm/Filter/AbstractFilter.php index 3781664f73e..68d8cc61c30 100644 --- a/src/Doctrine/Orm/Filter/AbstractFilter.php +++ b/src/Doctrine/Orm/Filter/AbstractFilter.php @@ -162,5 +162,3 @@ protected function normalizePropertyName($property) return implode('.', array_map([$this->nameConverter, 'normalize'], explode('.', (string) $property))); } } - -class_alias(AbstractFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter::class); diff --git a/src/Doctrine/Orm/Filter/BooleanFilter.php b/src/Doctrine/Orm/Filter/BooleanFilter.php index 162bcc064c9..4f2bacc3257 100644 --- a/src/Doctrine/Orm/Filter/BooleanFilter.php +++ b/src/Doctrine/Orm/Filter/BooleanFilter.php @@ -72,5 +72,3 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB ->setParameter($valueParameter, $value); } } - -class_alias(BooleanFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\BooleanFilter::class); diff --git a/src/Doctrine/Orm/Filter/DateFilter.php b/src/Doctrine/Orm/Filter/DateFilter.php index 0031cad1af2..5d63a1a94e0 100644 --- a/src/Doctrine/Orm/Filter/DateFilter.php +++ b/src/Doctrine/Orm/Filter/DateFilter.php @@ -182,5 +182,3 @@ protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterf $queryBuilder->setParameter($valueParameter, $value, $type); } } - -class_alias(DateFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\DateFilter::class); diff --git a/src/Doctrine/Orm/Filter/ExistsFilter.php b/src/Doctrine/Orm/Filter/ExistsFilter.php index 3a17f44f7bb..854461d7b6d 100644 --- a/src/Doctrine/Orm/Filter/ExistsFilter.php +++ b/src/Doctrine/Orm/Filter/ExistsFilter.php @@ -211,5 +211,3 @@ protected function extractProperties(Request $request/* , string $resourceClass return \is_array($properties) ? $properties : []; } } - -class_alias(ExistsFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\ExistsFilter::class); diff --git a/src/Doctrine/Orm/Filter/NumericFilter.php b/src/Doctrine/Orm/Filter/NumericFilter.php index f0b487fe961..f32e16f0771 100644 --- a/src/Doctrine/Orm/Filter/NumericFilter.php +++ b/src/Doctrine/Orm/Filter/NumericFilter.php @@ -102,5 +102,3 @@ protected function getType(string $doctrineType = null): string return 'int'; } } - -class_alias(NumericFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\NumericFilter::class); diff --git a/src/Doctrine/Orm/Filter/OrderFilter.php b/src/Doctrine/Orm/Filter/OrderFilter.php index 9f17e2e5433..8241b52e1b3 100644 --- a/src/Doctrine/Orm/Filter/OrderFilter.php +++ b/src/Doctrine/Orm/Filter/OrderFilter.php @@ -131,5 +131,3 @@ protected function extractProperties(Request $request/* , string $resourceClass return \is_array($properties) ? $properties : []; } } - -class_alias(OrderFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter::class); diff --git a/src/Doctrine/Orm/Filter/RangeFilter.php b/src/Doctrine/Orm/Filter/RangeFilter.php index edd5b95afb0..e8738bb00bd 100644 --- a/src/Doctrine/Orm/Filter/RangeFilter.php +++ b/src/Doctrine/Orm/Filter/RangeFilter.php @@ -148,5 +148,3 @@ protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterf } } } - -class_alias(RangeFilter::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\RangeFilter::class); diff --git a/src/Doctrine/Orm/Paginator.php b/src/Doctrine/Orm/Paginator.php index 21a3d18d22b..92f8265b66e 100644 --- a/src/Doctrine/Orm/Paginator.php +++ b/src/Doctrine/Orm/Paginator.php @@ -56,5 +56,3 @@ public function getQuery(): Query return $this->paginator->getQuery(); } } - -class_alias(Paginator::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator::class); diff --git a/src/Doctrine/Orm/PropertyHelperTrait.php b/src/Doctrine/Orm/PropertyHelperTrait.php index 88da7b02059..d29f586bcab 100644 --- a/src/Doctrine/Orm/PropertyHelperTrait.php +++ b/src/Doctrine/Orm/PropertyHelperTrait.php @@ -82,5 +82,3 @@ protected function addJoinsForNestedProperty(string $property, string $rootAlias return [$alias, $propertyParts['field'], $propertyParts['associations']]; } } - -class_alias(PropertyHelperTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\PropertyHelperTrait::class); diff --git a/src/Doctrine/Orm/Util/EagerLoadingTrait.php b/src/Doctrine/Orm/Util/EagerLoadingTrait.php index 6853288a642..12d125fd3f4 100644 --- a/src/Doctrine/Orm/Util/EagerLoadingTrait.php +++ b/src/Doctrine/Orm/Util/EagerLoadingTrait.php @@ -106,5 +106,3 @@ private function hasFetchEagerAssociation(EntityManagerInterface $em, ClassMetad return false; } } - -class_alias(EagerLoadingTrait::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\EagerLoadingTrait::class); diff --git a/src/Doctrine/Orm/Util/QueryBuilderHelper.php b/src/Doctrine/Orm/Util/QueryBuilderHelper.php index 2d6790da33c..b22d5e5d87a 100644 --- a/src/Doctrine/Orm/Util/QueryBuilderHelper.php +++ b/src/Doctrine/Orm/Util/QueryBuilderHelper.php @@ -218,5 +218,3 @@ private static function mapJoinAliases(iterable $joins): array return $aliasMap; } } - -class_alias(QueryBuilderHelper::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryBuilderHelper::class); diff --git a/src/Doctrine/Orm/Util/QueryChecker.php b/src/Doctrine/Orm/Util/QueryChecker.php index d5b449168ec..ce8dd718a5c 100644 --- a/src/Doctrine/Orm/Util/QueryChecker.php +++ b/src/Doctrine/Orm/Util/QueryChecker.php @@ -205,5 +205,3 @@ public static function hasJoinedToManyAssociation(QueryBuilder $queryBuilder, Ma return false; } } - -class_alias(QueryChecker::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryChecker::class); diff --git a/src/Doctrine/Orm/Util/QueryJoinParser.php b/src/Doctrine/Orm/Util/QueryJoinParser.php index 861efc00e52..abe9bf2fd01 100644 --- a/src/Doctrine/Orm/Util/QueryJoinParser.php +++ b/src/Doctrine/Orm/Util/QueryJoinParser.php @@ -89,5 +89,3 @@ public static function getOrderByParts(OrderBy $orderBy): array return $orderBy->getParts(); } } - -class_alias(QueryJoinParser::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryJoinParser::class); diff --git a/src/Doctrine/Orm/Util/QueryNameGenerator.php b/src/Doctrine/Orm/Util/QueryNameGenerator.php index bf049615c7d..9bf85b1581d 100644 --- a/src/Doctrine/Orm/Util/QueryNameGenerator.php +++ b/src/Doctrine/Orm/Util/QueryNameGenerator.php @@ -41,5 +41,3 @@ public function generateParameterName(string $name): string return sprintf('%s_p%d', str_replace('.', '_', $name), $this->incrementedName++); } } - -class_alias(QueryNameGenerator::class, \ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator::class); diff --git a/src/Documentation/Action/DocumentationAction.php b/src/Documentation/Action/DocumentationAction.php index b470f185cd8..34177f31cbe 100644 --- a/src/Documentation/Action/DocumentationAction.php +++ b/src/Documentation/Action/DocumentationAction.php @@ -43,7 +43,7 @@ final class DocumentationAction * @param mixed|array|FormatsProviderInterface $formatsProvider * @param LegacyOpenApiFactoryInterface|OpenApiFactoryInterface $openApiFactory */ - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, string $title = '', string $description = '', string $version = '', $formatsProvider = null, array $swaggerVersions = [2, 3], $openApiFactory = null) + public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, string $title = '', string $description = '', string $version = '', array $swaggerVersions = [2, 3], OpenApiFactoryInterface $openApiFactory = null) { $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; $this->title = $title; @@ -51,23 +51,6 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName $this->version = $version; $this->swaggerVersions = $swaggerVersions; $this->openApiFactory = $openApiFactory; - - if (null === $openApiFactory) { - @trigger_error(sprintf('Not passing an instance of "%s" as 7th parameter of the constructor of "%s" is deprecated since API Platform 2.6', OpenApiFactoryInterface::class, __CLASS__), \E_USER_DEPRECATED); - } - - if (null === $formatsProvider) { - return; - } - - @trigger_error(sprintf('Passing an array or an instance of "%s" as 5th parameter of the constructor of "%s" is deprecated since API Platform 2.5', FormatsProviderInterface::class, __CLASS__), \E_USER_DEPRECATED); - if (\is_array($formatsProvider)) { - $this->formats = $formatsProvider; - - return; - } - - $this->formatsProvider = $formatsProvider; } public function __invoke(Request $request = null): DocumentationInterface @@ -82,11 +65,6 @@ public function __invoke(Request $request = null): DocumentationInterface $attributes = RequestAttributesExtractor::extractAttributes($request); } - // BC check to be removed in 3.0 - if (null !== $this->formatsProvider) { - $this->formats = $this->formatsProvider->getFormatsFromAttributes($attributes ?? []); - } - if ('json' === $request->getRequestFormat() && null !== $this->openApiFactory && 3 === ($context['spec_version'] ?? null)) { return $this->openApiFactory->__invoke($context ?? []); } @@ -94,5 +72,3 @@ public function __invoke(Request $request = null): DocumentationInterface return new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version, $this->formats); } } - -class_alias(DocumentationAction::class, \ApiPlatform\Core\Documentation\Action\DocumentationAction::class); diff --git a/src/Documentation/Documentation.php b/src/Documentation/Documentation.php index fdc2cd3b8b0..8f674167489 100644 --- a/src/Documentation/Documentation.php +++ b/src/Documentation/Documentation.php @@ -75,5 +75,3 @@ public function getResourceNameCollection(): ResourceNameCollection return $this->resourceNameCollection; } } - -class_alias(Documentation::class, \ApiPlatform\Core\Documentation\Documentation::class); diff --git a/src/Elasticsearch/Exception/IndexNotFoundException.php b/src/Elasticsearch/Exception/IndexNotFoundException.php index 13ccd4846b2..c12ca5d6b9e 100644 --- a/src/Elasticsearch/Exception/IndexNotFoundException.php +++ b/src/Elasticsearch/Exception/IndexNotFoundException.php @@ -25,5 +25,3 @@ final class IndexNotFoundException extends \Exception implements ExceptionInterface { } - -class_alias(IndexNotFoundException::class, \ApiPlatform\Core\Bridge\Elasticsearch\Exception\IndexNotFoundException::class); diff --git a/src/Elasticsearch/Exception/NonUniqueIdentifierException.php b/src/Elasticsearch/Exception/NonUniqueIdentifierException.php index 6851f208cee..e2d007b1f70 100644 --- a/src/Elasticsearch/Exception/NonUniqueIdentifierException.php +++ b/src/Elasticsearch/Exception/NonUniqueIdentifierException.php @@ -25,5 +25,3 @@ final class NonUniqueIdentifierException extends \Exception implements ExceptionInterface { } - -class_alias(NonUniqueIdentifierException::class, \ApiPlatform\Core\Bridge\Elasticsearch\Exception\NonUniqueIdentifierException::class); diff --git a/src/Elasticsearch/Extension/AbstractFilterExtension.php b/src/Elasticsearch/Extension/AbstractFilterExtension.php index 45d334a1c98..da139632bc8 100644 --- a/src/Elasticsearch/Extension/AbstractFilterExtension.php +++ b/src/Elasticsearch/Extension/AbstractFilterExtension.php @@ -72,5 +72,3 @@ abstract protected function getFilterInterface(): string; */ abstract protected function alterRequestBody(array $requestBody, array $clauseBody): array; } - -class_alias(AbstractFilterExtension::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\AbstractFilterExtension::class); diff --git a/src/Elasticsearch/Extension/ConstantScoreFilterExtension.php b/src/Elasticsearch/Extension/ConstantScoreFilterExtension.php index 69e85cbb37f..bb5a5819151 100644 --- a/src/Elasticsearch/Extension/ConstantScoreFilterExtension.php +++ b/src/Elasticsearch/Extension/ConstantScoreFilterExtension.php @@ -49,5 +49,3 @@ protected function alterRequestBody(array $requestBody, array $clauseBody): arra return $requestBody; } } - -class_alias(ConstantScoreFilterExtension::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\ConstantScoreFilterExtension::class); diff --git a/src/Elasticsearch/Extension/SortExtension.php b/src/Elasticsearch/Extension/SortExtension.php index 8d98e8bc7ba..627663e8018 100644 --- a/src/Elasticsearch/Extension/SortExtension.php +++ b/src/Elasticsearch/Extension/SortExtension.php @@ -97,5 +97,3 @@ private function getOrder(string $resourceClass, string $property, string $direc return [$property => $order]; } } - -class_alias(SortExtension::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\SortExtension::class); diff --git a/src/Elasticsearch/Extension/SortFilterExtension.php b/src/Elasticsearch/Extension/SortFilterExtension.php index e9d50486f11..84aec9efe6c 100644 --- a/src/Elasticsearch/Extension/SortFilterExtension.php +++ b/src/Elasticsearch/Extension/SortFilterExtension.php @@ -44,5 +44,3 @@ protected function alterRequestBody(array $requestBody, array $clauseBody): arra return $requestBody; } } - -class_alias(SortFilterExtension::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\SortFilterExtension::class); diff --git a/src/Elasticsearch/Metadata/Document/DocumentMetadata.php b/src/Elasticsearch/Metadata/Document/DocumentMetadata.php index c035862c97a..c6197da4ffb 100644 --- a/src/Elasticsearch/Metadata/Document/DocumentMetadata.php +++ b/src/Elasticsearch/Metadata/Document/DocumentMetadata.php @@ -73,5 +73,3 @@ public function getType(): string return $this->type; } } - -class_alias(DocumentMetadata::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\DocumentMetadata::class); diff --git a/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php index 0bd6c20fa44..3b4f9647af5 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php @@ -88,5 +88,3 @@ public function create(string $resourceClass): DocumentMetadata throw new IndexNotFoundException(sprintf('No index associated with the "%s" resource class.', $resourceClass)); } } - -class_alias(AttributeDocumentMetadataFactory::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory::class); diff --git a/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php index 6f28aa420e3..08316964138 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php @@ -78,5 +78,3 @@ private function handleNotFound(DocumentMetadata $documentMetadata, string $reso return $documentMetadata; } } - -class_alias(CachedDocumentMetadataFactory::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory::class); diff --git a/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php index 6f89047ff93..2a7a8f60f3a 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php @@ -104,5 +104,3 @@ private function handleNotFound(?DocumentMetadata $documentMetadata, string $res throw new IndexNotFoundException(sprintf('No index associated with the "%s" resource class.', $resourceClass)); } } - -class_alias(CatDocumentMetadataFactory::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory::class); diff --git a/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php index d194d46576e..fb1d1da7098 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php @@ -69,5 +69,3 @@ public function create(string $resourceClass): DocumentMetadata return $documentMetadata; } } - -class_alias(ConfiguredDocumentMetadataFactory::class, \ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory::class); diff --git a/src/Elasticsearch/Paginator.php b/src/Elasticsearch/Paginator.php index 87837e5eb64..f04504f7e8f 100644 --- a/src/Elasticsearch/Paginator.php +++ b/src/Elasticsearch/Paginator.php @@ -128,5 +128,3 @@ public function getIterator(): \Traversable } } } - -class_alias(Paginator::class, \ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator::class); diff --git a/src/Elasticsearch/Serializer/DocumentNormalizer.php b/src/Elasticsearch/Serializer/DocumentNormalizer.php index e4040990b81..7400c5e27f3 100644 --- a/src/Elasticsearch/Serializer/DocumentNormalizer.php +++ b/src/Elasticsearch/Serializer/DocumentNormalizer.php @@ -100,5 +100,3 @@ private function populateIdentifier(array $data, string $class): array return $data; } } - -class_alias(DocumentNormalizer::class, \ApiPlatform\Core\Bridge\Elasticsearch\Serializer\DocumentNormalizer::class); diff --git a/src/Elasticsearch/Serializer/ItemNormalizer.php b/src/Elasticsearch/Serializer/ItemNormalizer.php index f88d1637d66..86cf5f3090d 100644 --- a/src/Elasticsearch/Serializer/ItemNormalizer.php +++ b/src/Elasticsearch/Serializer/ItemNormalizer.php @@ -111,5 +111,3 @@ public function setSerializer(SerializerInterface $serializer) $this->decorated->setSerializer($serializer); } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\Bridge\Elasticsearch\Serializer\ItemNormalizer::class); diff --git a/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php b/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php index 8c469cfd87e..a408a1181ad 100644 --- a/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php +++ b/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php @@ -60,5 +60,3 @@ private function convertInnerFields(string $propertyName, bool $normalization, s return implode('.', $convertedProperties); } } - -class_alias(InnerFieldsNameConverter::class, \ApiPlatform\Core\Bridge\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter::class); diff --git a/src/Elasticsearch/Util/FieldDatatypeTrait.php b/src/Elasticsearch/Util/FieldDatatypeTrait.php index a944623d706..e5fec39bb45 100644 --- a/src/Elasticsearch/Util/FieldDatatypeTrait.php +++ b/src/Elasticsearch/Util/FieldDatatypeTrait.php @@ -104,5 +104,3 @@ private function getNestedFieldPath(string $resourceClass, string $property): ?s return null; } } - -class_alias(FieldDatatypeTrait::class, \ApiPlatform\Core\Bridge\Elasticsearch\Util\FieldDatatypeTrait::class); diff --git a/src/Exception/DeserializationException.php b/src/Exception/DeserializationException.php index 21e719cf410..37dfcb55772 100644 --- a/src/Exception/DeserializationException.php +++ b/src/Exception/DeserializationException.php @@ -24,5 +24,3 @@ class DeserializationException extends \Exception implements ExceptionInterface, SerializerExceptionInterface { } - -class_alias(DeserializationException::class, \ApiPlatform\Core\Exception\DeserializationException::class); diff --git a/src/Exception/FilterValidationException.php b/src/Exception/FilterValidationException.php index b350f14c9d9..4fe0cbb1c7f 100644 --- a/src/Exception/FilterValidationException.php +++ b/src/Exception/FilterValidationException.php @@ -34,5 +34,3 @@ public function __toString(): string return implode("\n", $this->constraintViolationList); } } - -class_alias(FilterValidationException::class, \ApiPlatform\Core\Exception\FilterValidationException::class); diff --git a/src/Exception/InvalidArgumentException.php b/src/Exception/InvalidArgumentException.php index f691a1e94c8..bddf0a57112 100644 --- a/src/Exception/InvalidArgumentException.php +++ b/src/Exception/InvalidArgumentException.php @@ -21,5 +21,3 @@ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } - -class_alias(InvalidArgumentException::class, \ApiPlatform\Core\Exception\InvalidArgumentException::class); diff --git a/src/Exception/InvalidIdentifierException.php b/src/Exception/InvalidIdentifierException.php index f7ae0c6d851..961aad89db1 100644 --- a/src/Exception/InvalidIdentifierException.php +++ b/src/Exception/InvalidIdentifierException.php @@ -21,5 +21,3 @@ final class InvalidIdentifierException extends \Exception implements ExceptionInterface { } - -class_alias(InvalidIdentifierException::class, \ApiPlatform\Core\Exception\InvalidIdentifierException::class); diff --git a/src/Exception/InvalidResourceException.php b/src/Exception/InvalidResourceException.php index 580ad5ac473..a69543355d7 100644 --- a/src/Exception/InvalidResourceException.php +++ b/src/Exception/InvalidResourceException.php @@ -21,5 +21,3 @@ class InvalidResourceException extends \Exception implements ExceptionInterface { } - -class_alias(InvalidResourceException::class, \ApiPlatform\Core\Exception\InvalidResourceException::class); diff --git a/src/Exception/InvalidValueException.php b/src/Exception/InvalidValueException.php index 74e93c00417..96b023fdbae 100644 --- a/src/Exception/InvalidValueException.php +++ b/src/Exception/InvalidValueException.php @@ -16,5 +16,3 @@ class InvalidValueException extends InvalidArgumentException { } - -class_alias(InvalidValueException::class, \ApiPlatform\Core\Exception\InvalidValueException::class); diff --git a/src/Exception/ItemNotFoundException.php b/src/Exception/ItemNotFoundException.php index 43c017fd364..a66f39965d8 100644 --- a/src/Exception/ItemNotFoundException.php +++ b/src/Exception/ItemNotFoundException.php @@ -21,5 +21,3 @@ class ItemNotFoundException extends InvalidArgumentException { } - -class_alias(ItemNotFoundException::class, \ApiPlatform\Core\Exception\ItemNotFoundException::class); diff --git a/src/Exception/PropertyNotFoundException.php b/src/Exception/PropertyNotFoundException.php index 80146c5ffce..44df7ee03ec 100644 --- a/src/Exception/PropertyNotFoundException.php +++ b/src/Exception/PropertyNotFoundException.php @@ -21,5 +21,3 @@ class PropertyNotFoundException extends \Exception implements ExceptionInterface { } - -class_alias(PropertyNotFoundException::class, \ApiPlatform\Core\Exception\PropertyNotFoundException::class); diff --git a/src/Exception/ResourceClassNotFoundException.php b/src/Exception/ResourceClassNotFoundException.php index a1ee01887ce..0a0f0eaa9c4 100644 --- a/src/Exception/ResourceClassNotFoundException.php +++ b/src/Exception/ResourceClassNotFoundException.php @@ -21,5 +21,3 @@ class ResourceClassNotFoundException extends \Exception implements ExceptionInterface { } - -class_alias(ResourceClassNotFoundException::class, \ApiPlatform\Core\Exception\ResourceClassNotFoundException::class); diff --git a/src/Exception/ResourceClassNotSupportedException.php b/src/Exception/ResourceClassNotSupportedException.php index b45fea4183f..9d291d1ae09 100644 --- a/src/Exception/ResourceClassNotSupportedException.php +++ b/src/Exception/ResourceClassNotSupportedException.php @@ -21,5 +21,3 @@ class ResourceClassNotSupportedException extends \Exception implements ExceptionInterface { } - -class_alias(ResourceClassNotSupportedException::class, \ApiPlatform\Core\Exception\ResourceClassNotSupportedException::class); diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php index ae09346244f..7eba6481b10 100644 --- a/src/Exception/RuntimeException.php +++ b/src/Exception/RuntimeException.php @@ -21,5 +21,3 @@ class RuntimeException extends \RuntimeException implements ExceptionInterface { } - -class_alias(RuntimeException::class, \ApiPlatform\Core\Exception\RuntimeException::class); diff --git a/src/GraphQl/Action/EntrypointAction.php b/src/GraphQl/Action/EntrypointAction.php index 6eb558a9883..ca03ed6a43f 100644 --- a/src/GraphQl/Action/EntrypointAction.php +++ b/src/GraphQl/Action/EntrypointAction.php @@ -221,5 +221,3 @@ private function decodeVariables(string $variables): array return $decoded; } } - -class_alias(EntrypointAction::class, \ApiPlatform\Core\GraphQl\Action\EntrypointAction::class); diff --git a/src/GraphQl/Action/GraphQlPlaygroundAction.php b/src/GraphQl/Action/GraphQlPlaygroundAction.php index 1c4650c9b13..7216ef7bb01 100644 --- a/src/GraphQl/Action/GraphQlPlaygroundAction.php +++ b/src/GraphQl/Action/GraphQlPlaygroundAction.php @@ -54,5 +54,3 @@ public function __invoke(Request $request): Response throw new BadRequestHttpException('GraphQL Playground is not enabled.'); } } - -class_alias(GraphQlPlaygroundAction::class, \ApiPlatform\Core\GraphQl\Action\GraphQlPlaygroundAction::class); diff --git a/src/GraphQl/Action/GraphiQlAction.php b/src/GraphQl/Action/GraphiQlAction.php index 0b548b99331..985edc615a8 100644 --- a/src/GraphQl/Action/GraphiQlAction.php +++ b/src/GraphQl/Action/GraphiQlAction.php @@ -54,5 +54,3 @@ public function __invoke(Request $request): Response throw new BadRequestHttpException('GraphiQL is not enabled.'); } } - -class_alias(GraphiQlAction::class, \ApiPlatform\Core\GraphQl\Action\GraphiQlAction::class); diff --git a/src/GraphQl/Error/ErrorHandler.php b/src/GraphQl/Error/ErrorHandler.php index dc04eb50954..9979ea118d5 100644 --- a/src/GraphQl/Error/ErrorHandler.php +++ b/src/GraphQl/Error/ErrorHandler.php @@ -28,5 +28,3 @@ public function __invoke(array $errors, callable $formatter): array return array_map($formatter, $errors); } } - -class_alias(ErrorHandler::class, \ApiPlatform\Core\GraphQl\Error\ErrorHandler::class); diff --git a/src/GraphQl/Executor.php b/src/GraphQl/Executor.php index f423d85edf5..d1b5f7736da 100644 --- a/src/GraphQl/Executor.php +++ b/src/GraphQl/Executor.php @@ -32,5 +32,3 @@ public function executeQuery(Schema $schema, $source, $rootValue = null, $contex return GraphQL::executeQuery($schema, $source, $rootValue, $context, $variableValues, $operationName, $fieldResolver, $validationRules); } } - -class_alias(Executor::class, \ApiPlatform\Core\GraphQl\Executor::class); diff --git a/src/GraphQl/Resolver/Util/IdentifierTrait.php b/src/GraphQl/Resolver/Util/IdentifierTrait.php index deb00fc0d67..8ec7c0c6d8d 100644 --- a/src/GraphQl/Resolver/Util/IdentifierTrait.php +++ b/src/GraphQl/Resolver/Util/IdentifierTrait.php @@ -33,5 +33,3 @@ private function getIdentifierFromContext(array $context): ?string return $args['id'] ?? null; } } - -class_alias(IdentifierTrait::class, \ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait::class); diff --git a/src/GraphQl/Serializer/ItemNormalizer.php b/src/GraphQl/Serializer/ItemNormalizer.php index 529d57b02eb..af94b85127c 100644 --- a/src/GraphQl/Serializer/ItemNormalizer.php +++ b/src/GraphQl/Serializer/ItemNormalizer.php @@ -15,9 +15,8 @@ use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface as LegacyIdentifiersExtractorInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\ItemNormalizer as BaseItemNormalizer; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; @@ -43,13 +42,13 @@ final class ItemNormalizer extends BaseItemNormalizer public const ITEM_IDENTIFIERS_KEY = '#itemIdentifiers'; /** - * @var IdentifiersExtractorInterface|LegacyIdentifiersExtractorInterface + * @var IdentifiersExtractorInterface */ private $identifiersExtractor; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $identifiersExtractor, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, LoggerInterface $logger = null, iterable $dataTransformers = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, $identifiersExtractor, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, LoggerInterface $logger = null, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $itemDataProvider, $allowPlainIdentifiers, $logger ?: new NullLogger(), $dataTransformers, $resourceMetadataCollectionFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $logger ?: new NullLogger(), $resourceMetadataCollectionFactory, $resourceAccessChecker); $this->identifiersExtractor = $identifiersExtractor; } diff --git a/src/GraphQl/Type/Definition/IterableType.php b/src/GraphQl/Type/Definition/IterableType.php index 300b872978c..717af8b066f 100644 --- a/src/GraphQl/Type/Definition/IterableType.php +++ b/src/GraphQl/Type/Definition/IterableType.php @@ -148,5 +148,3 @@ private function parseIterableLiteral($valueNode) } } } - -class_alias(IterableType::class, \ApiPlatform\Core\GraphQl\Type\Definition\IterableType::class); diff --git a/src/GraphQl/Type/Definition/UploadType.php b/src/GraphQl/Type/Definition/UploadType.php index bfe3bac45cf..d0f90c351e2 100644 --- a/src/GraphQl/Type/Definition/UploadType.php +++ b/src/GraphQl/Type/Definition/UploadType.php @@ -89,5 +89,3 @@ public function parseValue($value): UploadedFile return $value; } } - -class_alias(UploadType::class, \ApiPlatform\Core\GraphQl\Type\Definition\UploadType::class); diff --git a/src/GraphQl/Type/TypeNotFoundException.php b/src/GraphQl/Type/TypeNotFoundException.php index 404c6d54cff..96cb3c26eab 100644 --- a/src/GraphQl/Type/TypeNotFoundException.php +++ b/src/GraphQl/Type/TypeNotFoundException.php @@ -39,5 +39,3 @@ public function getTypeId(): string return $this->typeId; } } - -class_alias(TypeNotFoundException::class, \ApiPlatform\Core\GraphQl\Type\TypeNotFoundException::class); diff --git a/src/GraphQl/Type/TypesContainer.php b/src/GraphQl/Type/TypesContainer.php index 9e53f295f8b..d389bd7cb76 100644 --- a/src/GraphQl/Type/TypesContainer.php +++ b/src/GraphQl/Type/TypesContainer.php @@ -60,5 +60,3 @@ public function has($id): bool return \array_key_exists($id, $this->graphqlTypes); } } - -class_alias(TypesContainer::class, \ApiPlatform\Core\GraphQl\Type\TypesContainer::class); diff --git a/src/GraphQl/Type/TypesFactory.php b/src/GraphQl/Type/TypesFactory.php index 57a6e1b30b8..64fd466e470 100644 --- a/src/GraphQl/Type/TypesFactory.php +++ b/src/GraphQl/Type/TypesFactory.php @@ -48,5 +48,3 @@ public function getTypes(): array return $types; } } - -class_alias(TypesFactory::class, \ApiPlatform\Core\GraphQl\Type\TypesFactory::class); diff --git a/src/Hal/Serializer/CollectionNormalizer.php b/src/Hal/Serializer/CollectionNormalizer.php index 7b420645ab4..b1688595dc6 100644 --- a/src/Hal/Serializer/CollectionNormalizer.php +++ b/src/Hal/Serializer/CollectionNormalizer.php @@ -105,5 +105,3 @@ protected function getItemsData($object, string $format = null, array $context = return $data; } } - -class_alias(CollectionNormalizer::class, \ApiPlatform\Core\Hal\Serializer\CollectionNormalizer::class); diff --git a/src/Hal/Serializer/EntrypointNormalizer.php b/src/Hal/Serializer/EntrypointNormalizer.php index ffa09cce83b..391516df21a 100644 --- a/src/Hal/Serializer/EntrypointNormalizer.php +++ b/src/Hal/Serializer/EntrypointNormalizer.php @@ -118,5 +118,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(EntrypointNormalizer::class, \ApiPlatform\Core\Hal\Serializer\EntrypointNormalizer::class); diff --git a/src/Hal/Serializer/ItemNormalizer.php b/src/Hal/Serializer/ItemNormalizer.php index bce69d7092b..444dbe26e54 100644 --- a/src/Hal/Serializer/ItemNormalizer.php +++ b/src/Hal/Serializer/ItemNormalizer.php @@ -13,9 +13,6 @@ namespace ApiPlatform\Hal\Serializer; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Serializer\CacheKeyTrait; use ApiPlatform\Serializer\ContextTrait; @@ -66,7 +63,7 @@ public function normalize($object, $format = null, array $context = []) $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); $context = $this->initContext($resourceClass, $context); - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object); + $iri = $this->iriConverter->getIriFromResource($object); $context['iri'] = $iri; $context['api_normalize'] = true; @@ -141,11 +138,10 @@ private function getComponents($object, ?string $format, array $context): array ]; foreach ($attributes as $attribute) { - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $options); // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : ($propertyMetadata->getBuiltinTypes()[0] ?? null); + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; $isOne = $isMany = false; if (null !== $type) { @@ -278,5 +274,3 @@ private function isMaxDepthReached(array $attributesMetadata, string $class, str return false; } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\Hal\Serializer\ItemNormalizer::class); diff --git a/src/Hal/Serializer/ObjectNormalizer.php b/src/Hal/Serializer/ObjectNormalizer.php index 4130716aba3..a05c3561169 100644 --- a/src/Hal/Serializer/ObjectNormalizer.php +++ b/src/Hal/Serializer/ObjectNormalizer.php @@ -110,5 +110,3 @@ public function denormalize($data, $class, $format = null, array $context = []) throw new LogicException(sprintf('%s is a read-only format.', self::FORMAT)); } } - -class_alias(ObjectNormalizer::class, \ApiPlatform\Core\Hal\Serializer\ObjectNormalizer::class); diff --git a/src/HttpCache/EventListener/AddHeadersListener.php b/src/HttpCache/EventListener/AddHeadersListener.php index 1c185192784..12d5cf780e3 100644 --- a/src/HttpCache/EventListener/AddHeadersListener.php +++ b/src/HttpCache/EventListener/AddHeadersListener.php @@ -115,5 +115,3 @@ public function onKernelResponse(ResponseEvent $event): void } } } - -class_alias(AddHeadersListener::class, \ApiPlatform\Core\HttpCache\EventListener\AddHeadersListener::class); diff --git a/src/HttpCache/EventListener/AddTagsListener.php b/src/HttpCache/EventListener/AddTagsListener.php index f52f691c1ac..67eac1b5a64 100644 --- a/src/HttpCache/EventListener/AddTagsListener.php +++ b/src/HttpCache/EventListener/AddTagsListener.php @@ -108,5 +108,3 @@ public function onKernelResponse(ResponseEvent $event): void } } } - -class_alias(AddTagsListener::class, \ApiPlatform\Core\HttpCache\EventListener\AddTagsListener::class); diff --git a/src/HttpCache/VarnishPurger.php b/src/HttpCache/VarnishPurger.php index 23fb74d99e7..f35abec27e0 100644 --- a/src/HttpCache/VarnishPurger.php +++ b/src/HttpCache/VarnishPurger.php @@ -139,5 +139,3 @@ private function chunkRegexParts(array $parts): iterable yield from $this->chunkRegexParts($nextParts); } } - -class_alias(VarnishPurger::class, \ApiPlatform\Core\HttpCache\VarnishPurger::class); diff --git a/src/HttpCache/VarnishXKeyPurger.php b/src/HttpCache/VarnishXKeyPurger.php index 1b6e0ca1249..32f7523af0f 100644 --- a/src/HttpCache/VarnishXKeyPurger.php +++ b/src/HttpCache/VarnishXKeyPurger.php @@ -112,5 +112,3 @@ private function chunkKeys(array $keys): iterable } } } - -class_alias(VarnishXKeyPurger::class, \ApiPlatform\Core\HttpCache\VarnishXKeyPurger::class); diff --git a/src/Hydra/EventListener/AddLinkHeaderListener.php b/src/Hydra/EventListener/AddLinkHeaderListener.php index 18b100a3873..ecf15d120c2 100644 --- a/src/Hydra/EventListener/AddLinkHeaderListener.php +++ b/src/Hydra/EventListener/AddLinkHeaderListener.php @@ -58,5 +58,3 @@ public function onKernelResponse(ResponseEvent $event): void $request->attributes->set('_links', $linkProvider->withLink($link)); } } - -class_alias(AddLinkHeaderListener::class, \ApiPlatform\Core\Hydra\EventListener\AddLinkHeaderListener::class); diff --git a/src/Hydra/Serializer/CollectionFiltersNormalizer.php b/src/Hydra/Serializer/CollectionFiltersNormalizer.php index 9c5c7135909..43c3453e8e5 100644 --- a/src/Hydra/Serializer/CollectionFiltersNormalizer.php +++ b/src/Hydra/Serializer/CollectionFiltersNormalizer.php @@ -147,5 +147,3 @@ private function getSearch(string $resourceClass, array $parts, array $filters): return ['@type' => 'hydra:IriTemplate', 'hydra:template' => sprintf('%s{?%s}', $parts['path'], implode(',', $variables)), 'hydra:variableRepresentation' => 'BasicRepresentation', 'hydra:mapping' => $mapping]; } } - -class_alias(CollectionFiltersNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\CollectionFiltersNormalizer::class); diff --git a/src/Hydra/Serializer/CollectionNormalizer.php b/src/Hydra/Serializer/CollectionNormalizer.php index f2f49304b56..36b335cb821 100644 --- a/src/Hydra/Serializer/CollectionNormalizer.php +++ b/src/Hydra/Serializer/CollectionNormalizer.php @@ -136,5 +136,3 @@ private function normalizeRawCollection(iterable $object, ?string $format, array return $data; } } - -class_alias(CollectionNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\CollectionNormalizer::class); diff --git a/src/Hydra/Serializer/ConstraintViolationListNormalizer.php b/src/Hydra/Serializer/ConstraintViolationListNormalizer.php index c988f0fd734..6fd05d74ba7 100644 --- a/src/Hydra/Serializer/ConstraintViolationListNormalizer.php +++ b/src/Hydra/Serializer/ConstraintViolationListNormalizer.php @@ -53,5 +53,3 @@ public function normalize($object, $format = null, array $context = []) ]; } } - -class_alias(ConstraintViolationListNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\ConstraintViolationListNormalizer::class); diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index ed072965c89..3b3c154b5c3 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -730,5 +730,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(DocumentationNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\DocumentationNormalizer::class); diff --git a/src/Hydra/Serializer/EntrypointNormalizer.php b/src/Hydra/Serializer/EntrypointNormalizer.php index cc8aafacbee..12b738b21d5 100644 --- a/src/Hydra/Serializer/EntrypointNormalizer.php +++ b/src/Hydra/Serializer/EntrypointNormalizer.php @@ -123,5 +123,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(EntrypointNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\EntrypointNormalizer::class); diff --git a/src/Hydra/Serializer/ErrorNormalizer.php b/src/Hydra/Serializer/ErrorNormalizer.php index b7beef065ae..d63b7f2b550 100644 --- a/src/Hydra/Serializer/ErrorNormalizer.php +++ b/src/Hydra/Serializer/ErrorNormalizer.php @@ -81,5 +81,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(ErrorNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\ErrorNormalizer::class); diff --git a/src/Hydra/Serializer/PartialCollectionViewNormalizer.php b/src/Hydra/Serializer/PartialCollectionViewNormalizer.php index 7cbe5d45ca5..f5c902e843b 100644 --- a/src/Hydra/Serializer/PartialCollectionViewNormalizer.php +++ b/src/Hydra/Serializer/PartialCollectionViewNormalizer.php @@ -195,5 +195,3 @@ private function populateDataWithPagination(array $data, array $parsed, ?float $ return $data; } } - -class_alias(PartialCollectionViewNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\PartialCollectionViewNormalizer::class); diff --git a/src/JsonApi/Serializer/CollectionNormalizer.php b/src/JsonApi/Serializer/CollectionNormalizer.php index 38dd3044f68..34a727befd2 100644 --- a/src/JsonApi/Serializer/CollectionNormalizer.php +++ b/src/JsonApi/Serializer/CollectionNormalizer.php @@ -117,5 +117,3 @@ protected function getItemsData($object, string $format = null, array $context = return $data; } } - -class_alias(CollectionNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\CollectionNormalizer::class); diff --git a/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php b/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php index 899bc471e3b..d93514f146b 100644 --- a/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php +++ b/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php @@ -111,5 +111,3 @@ private function getSourcePointerFromViolation(ConstraintViolationInterface $vio return "data/attributes/$fieldName"; } } - -class_alias(ConstraintViolationListNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\ConstraintViolationListNormalizer::class); diff --git a/src/JsonApi/Serializer/EntrypointNormalizer.php b/src/JsonApi/Serializer/EntrypointNormalizer.php index a385107ef40..f0e2cd76ae6 100644 --- a/src/JsonApi/Serializer/EntrypointNormalizer.php +++ b/src/JsonApi/Serializer/EntrypointNormalizer.php @@ -121,5 +121,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(EntrypointNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\EntrypointNormalizer::class); diff --git a/src/JsonApi/Serializer/ErrorNormalizer.php b/src/JsonApi/Serializer/ErrorNormalizer.php index e856f660081..316a6b62620 100644 --- a/src/JsonApi/Serializer/ErrorNormalizer.php +++ b/src/JsonApi/Serializer/ErrorNormalizer.php @@ -82,5 +82,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(ErrorNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\ErrorNormalizer::class); diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index 48cad34d2b9..c32c49131ee 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -14,13 +14,9 @@ namespace ApiPlatform\JsonApi\Serializer; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Serializer\CacheKeyTrait; use ApiPlatform\Serializer\ContextTrait; @@ -52,9 +48,9 @@ final class ItemNormalizer extends AbstractItemNormalizer private $componentsCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter, $resourceMetadataFactory, array $defaultContext = [], iterable $dataTransformers = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter, $resourceMetadataFactory, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, null, null, false, $defaultContext, $dataTransformers, $resourceMetadataFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, null, $defaultContext, $resourceMetadataFactory, $resourceAccessChecker); } /** @@ -82,7 +78,7 @@ public function normalize($object, $format = null, array $context = []) $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); $context = $this->initContext($resourceClass, $context); - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object); + $iri = $this->iriConverter->getIriFromResource($object); $context['iri'] = $iri; $context['api_normalize'] = true; @@ -146,10 +142,7 @@ public function denormalize($data, $class, $format = null, array $context = []) throw new NotNormalizableValueException('Update is not allowed for this operation.'); } - $context[self::OBJECT_TO_POPULATE] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri( - $data['data']['id'], - $context + ['fetch_data' => false] - ) : $this->iriConverter->getResourceFromIri( + $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri( $data['data']['id'], $context + ['fetch_data' => false] ); @@ -202,7 +195,7 @@ protected function denormalizeRelation(string $attributeName, $propertyMetadata, } try { - return $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($value['id'], $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($value['id'], $context + ['fetch_data' => true]); + return $this->iriConverter->getResourceFromIri($value['id'], $context + ['fetch_data' => true]); } catch (ItemNotFoundException $e) { throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } @@ -218,7 +211,7 @@ protected function denormalizeRelation(string $attributeName, $propertyMetadata, protected function normalizeRelation($propertyMetadata, $relatedObject, string $resourceClass, ?string $format, array $context) { if (null !== $relatedObject) { - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($relatedObject) : $this->iriConverter->getIriFromResource($relatedObject); + $iri = $this->iriConverter->getIriFromResource($relatedObject); $context['iri'] = $iri; if (isset($context['resources'])) { @@ -281,13 +274,12 @@ private function getComponents($object, ?string $format, array $context): array ]; foreach ($attributes as $attribute) { - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this ->propertyMetadataFactory ->create($context['resource_class'], $attribute, $options); // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : ($propertyMetadata->getBuiltinTypes()[0] ?? null); + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; $isOne = $isMany = false; if (null !== $type) { @@ -463,18 +455,10 @@ private function getIncludedNestedResources(string $relationshipName, array $con }, $filtered); } - // TODO: 3.0 remove private function getResourceShortName(string $resourceClass): string { - /** @var ResourceMetadata|ResourceMetadataCollection */ $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if ($resourceMetadata instanceof ResourceMetadata) { - return $resourceMetadata->getShortName(); - } - return $resourceMetadata->getOperation()->getShortName(); } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\ItemNormalizer::class); diff --git a/src/JsonApi/Serializer/ObjectNormalizer.php b/src/JsonApi/Serializer/ObjectNormalizer.php index 5b017e5d7fc..6c7e0cf5331 100644 --- a/src/JsonApi/Serializer/ObjectNormalizer.php +++ b/src/JsonApi/Serializer/ObjectNormalizer.php @@ -127,5 +127,3 @@ private function getResourceShortName(string $resourceClass): string return $resourceMetadata->getOperation()->getShortName(); } } - -class_alias(ObjectNormalizer::class, \ApiPlatform\Core\JsonApi\Serializer\ObjectNormalizer::class); diff --git a/src/JsonApi/Serializer/ReservedAttributeNameConverter.php b/src/JsonApi/Serializer/ReservedAttributeNameConverter.php index 402b4402dad..750d6a76635 100644 --- a/src/JsonApi/Serializer/ReservedAttributeNameConverter.php +++ b/src/JsonApi/Serializer/ReservedAttributeNameConverter.php @@ -70,5 +70,3 @@ public function denormalize($propertyName, string $class = null, string $format return $propertyName; } } - -class_alias(ReservedAttributeNameConverter::class, \ApiPlatform\Core\JsonApi\Serializer\ReservedAttributeNameConverter::class); diff --git a/src/JsonLd/Action/ContextAction.php b/src/JsonLd/Action/ContextAction.php index 593b87e8270..bbb21fa781a 100644 --- a/src/JsonLd/Action/ContextAction.php +++ b/src/JsonLd/Action/ContextAction.php @@ -87,5 +87,3 @@ public function __invoke(string $shortName): array throw new NotFoundHttpException(); } } - -class_alias(ContextAction::class, \ApiPlatform\Core\JsonLd\Action\ContextAction::class); diff --git a/src/JsonLd/ContextBuilder.php b/src/JsonLd/ContextBuilder.php index 3b14141db8d..a458dda7a3e 100644 --- a/src/JsonLd/ContextBuilder.php +++ b/src/JsonLd/ContextBuilder.php @@ -259,5 +259,3 @@ private function getResourceContextWithShortname(string $resourceClass, int $ref return $context; } } - -class_alias(ContextBuilder::class, \ApiPlatform\Core\JsonLd\ContextBuilder::class); diff --git a/src/JsonLd/Serializer/ItemNormalizer.php b/src/JsonLd/Serializer/ItemNormalizer.php index cc487ac271c..7fd4828fcc4 100644 --- a/src/JsonLd/Serializer/ItemNormalizer.php +++ b/src/JsonLd/Serializer/ItemNormalizer.php @@ -16,11 +16,11 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\HttpOperation; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Serializer\ContextTrait; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; @@ -46,14 +46,10 @@ final class ItemNormalizer extends AbstractItemNormalizer private $contextBuilder; - public function __construct($resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ContextBuilderInterface $contextBuilder, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], iterable $dataTransformers = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ContextBuilderInterface $contextBuilder, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) { parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, null, false, $defaultContext, $dataTransformers, $resourceMetadataFactory, $resourceAccessChecker); - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - $this->contextBuilder = $contextBuilder; } @@ -90,12 +86,7 @@ public function normalize($object, $format = null, array $context = []) unset($context['operation'], $context['operation_name']); } - if ($this->iriConverter instanceof LegacyIriConverterInterface) { - $iri = $this->iriConverter->getIriFromItem($object); - } else { - $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); - } - + $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); $context['iri'] = $iri; $metadata['@id'] = $iri; $context['api_normalize'] = true; @@ -105,18 +96,12 @@ public function normalize($object, $format = null, array $context = []) return $data; } - // TODO: remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $metadata['@type'] = $resourceMetadata->getIri() ?: $resourceMetadata->getShortName(); - } elseif ($this->resourceMetadataFactory) { - $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation(); - $types = $operation instanceof HttpOperation ? $operation->getTypes() : null; - if (null === $types) { - $types = [$operation->getShortName()]; - } - $metadata['@type'] = 1 === \count($types) ? $types[0] : $types; + $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation(); + $types = $operation instanceof HttpOperation ? $operation->getTypes() : null; + if (null === $types) { + $types = [$operation->getShortName()]; } + $metadata['@type'] = 1 === \count($types) ? $types[0] : $types; return $metadata + $data; } @@ -144,11 +129,9 @@ public function denormalize($data, $class, $format = null, array $context = []) throw new NotNormalizableValueException('Update is not allowed for this operation.'); } - $context[self::OBJECT_TO_POPULATE] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($data['@id'], $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($data['@id'], $context + ['fetch_data' => true]); + $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri($data['@id'], $context + ['fetch_data' => true]); } return parent::denormalize($data, $class, $format, $context); } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\JsonLd\Serializer\ItemNormalizer::class); diff --git a/src/JsonLd/Serializer/JsonLdContextTrait.php b/src/JsonLd/Serializer/JsonLdContextTrait.php index 296c6476143..fcbe98206c2 100644 --- a/src/JsonLd/Serializer/JsonLdContextTrait.php +++ b/src/JsonLd/Serializer/JsonLdContextTrait.php @@ -59,5 +59,3 @@ private function createJsonLdContext(AnonymousContextBuilderInterface $contextBu return $contextBuilder->getAnonymousResourceContext($object, ($context['output'] ?? []) + ['api_resource' => $context['api_resource'] ?? null]); } } - -class_alias(JsonLdContextTrait::class, \ApiPlatform\Core\JsonLd\Serializer\JsonLdContextTrait::class); diff --git a/src/JsonLd/Serializer/ObjectNormalizer.php b/src/JsonLd/Serializer/ObjectNormalizer.php index 3bfe72d97f6..93b064ed261 100644 --- a/src/JsonLd/Serializer/ObjectNormalizer.php +++ b/src/JsonLd/Serializer/ObjectNormalizer.php @@ -104,5 +104,3 @@ public function normalize($object, $format = null, array $context = []) return $metadata + $data; } } - -class_alias(ObjectNormalizer::class, \ApiPlatform\Core\JsonLd\Serializer\ObjectNormalizer::class); diff --git a/src/JsonSchema/Command/JsonSchemaGenerateCommand.php b/src/JsonSchema/Command/JsonSchemaGenerateCommand.php index d637a06723d..4cdd7e9a941 100644 --- a/src/JsonSchema/Command/JsonSchemaGenerateCommand.php +++ b/src/JsonSchema/Command/JsonSchemaGenerateCommand.php @@ -124,5 +124,3 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } } - -class_alias(JsonSchemaGenerateCommand::class, \ApiPlatform\Core\JsonSchema\Command\JsonSchemaGenerateCommand::class); diff --git a/src/JsonSchema/Schema.php b/src/JsonSchema/Schema.php index 1a8f48bf795..4a840bd0d38 100644 --- a/src/JsonSchema/Schema.php +++ b/src/JsonSchema/Schema.php @@ -133,5 +133,3 @@ private function removeDefinitionKeyPrefix(string $definitionKey): string return substr($definitionKey, $prefix); } } - -class_alias(Schema::class, \ApiPlatform\Core\JsonSchema\Schema::class); diff --git a/src/JsonSchema/TypeFactory.php b/src/JsonSchema/TypeFactory.php index 4e008ec134d..45754f5eca1 100644 --- a/src/JsonSchema/TypeFactory.php +++ b/src/JsonSchema/TypeFactory.php @@ -201,5 +201,3 @@ private function addNullabilityToTypeDefinition(array $jsonSchema, Type $type, ? return array_merge($jsonSchema, ['nullable' => true]); } } - -class_alias(TypeFactory::class, \ApiPlatform\Core\JsonSchema\TypeFactory::class); diff --git a/src/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php b/src/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php index 02aabedee40..58884ea4821 100644 --- a/src/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php +++ b/src/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php @@ -48,5 +48,3 @@ public function create(string $resourceClass, array $options = []): PropertyName }); } } - -class_alias(CachedPropertyNameCollectionFactory::class, \ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class); diff --git a/src/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php b/src/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php index 6e9708421d4..27df8c93881 100644 --- a/src/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php +++ b/src/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php @@ -75,5 +75,3 @@ public function create(string $resourceClass, array $options = []): PropertyName return new PropertyNameCollection(array_values($propertyNames)); } } - -class_alias(ExtractorPropertyNameCollectionFactory::class, \ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class); diff --git a/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php b/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php index bad805cc564..02c16235a7e 100644 --- a/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php +++ b/src/Metadata/Property/Factory/PropertyInfoPropertyNameCollectionFactory.php @@ -42,5 +42,3 @@ public function create(string $resourceClass, array $options = []): PropertyName return new PropertyNameCollection($properties ?? []); } } - -class_alias(PropertyInfoPropertyNameCollectionFactory::class, \ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory::class); diff --git a/src/Metadata/Property/PropertyNameCollection.php b/src/Metadata/Property/PropertyNameCollection.php index de52f141b7a..c72dec5d879 100644 --- a/src/Metadata/Property/PropertyNameCollection.php +++ b/src/Metadata/Property/PropertyNameCollection.php @@ -51,5 +51,3 @@ public function count(): int return \count($this->properties); } } - -class_alias(PropertyNameCollection::class, \ApiPlatform\Core\Metadata\Property\PropertyNameCollection::class); diff --git a/src/Metadata/Resource/ResourceMetadataCollection.php b/src/Metadata/Resource/ResourceMetadataCollection.php index 383c12a47d2..aead554dc68 100644 --- a/src/Metadata/Resource/ResourceMetadataCollection.php +++ b/src/Metadata/Resource/ResourceMetadataCollection.php @@ -77,6 +77,11 @@ public function getOperation(?string $operationName = null, bool $forceCollectio $it->next(); } + // Idea: + // if ($metadata) { + // return (new class extends HttpOperation {})->withResource($metadata); + // } + $this->handleNotFound($operationName, $metadata); } diff --git a/src/OpenApi/Factory/OpenApiFactory.php b/src/OpenApi/Factory/OpenApiFactory.php index 6997c374cc2..c0608089733 100644 --- a/src/OpenApi/Factory/OpenApiFactory.php +++ b/src/OpenApi/Factory/OpenApiFactory.php @@ -14,8 +14,6 @@ namespace ApiPlatform\OpenApi\Factory; use ApiPlatform\Api\FilterLocatorTrait; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\JsonSchema\TypeFactoryInterface; @@ -33,7 +31,6 @@ use ApiPlatform\OpenApi\Model\ExternalDocumentation; use ApiPlatform\OpenApi\OpenApi; use ApiPlatform\OpenApi\Options; -use ApiPlatform\PathResolver\OperationPathResolverInterface; use ApiPlatform\State\Pagination\PaginationOptions; use Psr\Container\ContainerInterface; use Symfony\Component\PropertyInfo\Type; @@ -51,15 +48,8 @@ final class OpenApiFactory implements OpenApiFactoryInterface private $resourceNameCollectionFactory; private $resourceMetadataFactory; - /** - * @var LegacyPropertyNameCollectionFactoryInterface|PropertyNameCollectionFactoryInterface - */ private $propertyNameCollectionFactory; - /** - * @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface - */ private $propertyMetadataFactory; - private $operationPathResolver; private $formats; private $jsonSchemaFactory; private $jsonSchemaTypeFactory; @@ -68,7 +58,7 @@ final class OpenApiFactory implements OpenApiFactoryInterface private $router; private $routeCollection; - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, SchemaFactoryInterface $jsonSchemaFactory, TypeFactoryInterface $jsonSchemaTypeFactory, OperationPathResolverInterface $operationPathResolver, ContainerInterface $filterLocator, array $formats = [], Options $openApiOptions = null, PaginationOptions $paginationOptions = null, RouterInterface $router = null) + public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, SchemaFactoryInterface $jsonSchemaFactory, TypeFactoryInterface $jsonSchemaTypeFactory, ContainerInterface $filterLocator, array $formats = [], Options $openApiOptions = null, PaginationOptions $paginationOptions = null, RouterInterface $router = null) { $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; $this->jsonSchemaFactory = $jsonSchemaFactory; @@ -78,7 +68,6 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName $this->resourceMetadataFactory = $resourceMetadataFactory; $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->operationPathResolver = $operationPathResolver; $this->openApiOptions = $openApiOptions ?: new Options('API Platform'); $this->paginationOptions = $paginationOptions ?: new PaginationOptions(); $this->router = $router; diff --git a/src/OpenApi/Model/Components.php b/src/OpenApi/Model/Components.php index 698ad5f752e..681996bccb0 100644 --- a/src/OpenApi/Model/Components.php +++ b/src/OpenApi/Model/Components.php @@ -176,5 +176,3 @@ public function withPathItems(\ArrayObject $pathItems): self return $clone; } } - -class_alias(Components::class, \ApiPlatform\Core\OpenApi\Model\Components::class); diff --git a/src/OpenApi/Model/Contact.php b/src/OpenApi/Model/Contact.php index 3f008a75e14..81437ef0081 100644 --- a/src/OpenApi/Model/Contact.php +++ b/src/OpenApi/Model/Contact.php @@ -67,5 +67,3 @@ public function withEmail(?string $email): self return $clone; } } - -class_alias(Contact::class, \ApiPlatform\Core\OpenApi\Model\Contact::class); diff --git a/src/OpenApi/Model/Encoding.php b/src/OpenApi/Model/Encoding.php index 8ab44514058..8b83f4c71ba 100644 --- a/src/OpenApi/Model/Encoding.php +++ b/src/OpenApi/Model/Encoding.php @@ -107,5 +107,3 @@ public function withAllowReserved(bool $allowReserved): self return $clone; } } - -class_alias(Encoding::class, \ApiPlatform\Core\OpenApi\Model\Encoding::class); diff --git a/src/OpenApi/Model/ExtensionTrait.php b/src/OpenApi/Model/ExtensionTrait.php index 97724a0ae83..0033241e373 100644 --- a/src/OpenApi/Model/ExtensionTrait.php +++ b/src/OpenApi/Model/ExtensionTrait.php @@ -34,5 +34,3 @@ public function getExtensionProperties(): array return $this->extensionProperties; } } - -class_alias(ExtensionTrait::class, \ApiPlatform\Core\OpenApi\Model\ExtensionTrait::class); diff --git a/src/OpenApi/Model/ExternalDocumentation.php b/src/OpenApi/Model/ExternalDocumentation.php index 83153e42918..5c0c5b97d12 100644 --- a/src/OpenApi/Model/ExternalDocumentation.php +++ b/src/OpenApi/Model/ExternalDocumentation.php @@ -52,5 +52,3 @@ public function withUrl(string $url): self return $clone; } } - -class_alias(ExternalDocumentation::class, \ApiPlatform\Core\OpenApi\Model\ExternalDocumentation::class); diff --git a/src/OpenApi/Model/Info.php b/src/OpenApi/Model/Info.php index 947e3e39cef..aab2a0e4d65 100644 --- a/src/OpenApi/Model/Info.php +++ b/src/OpenApi/Model/Info.php @@ -127,5 +127,3 @@ public function withSummary(string $summary): self return $clone; } } - -class_alias(Info::class, \ApiPlatform\Core\OpenApi\Model\Info::class); diff --git a/src/OpenApi/Model/License.php b/src/OpenApi/Model/License.php index f856d603bb9..b103fc7fa11 100644 --- a/src/OpenApi/Model/License.php +++ b/src/OpenApi/Model/License.php @@ -67,5 +67,3 @@ public function withIdentifier(?string $identifier): self return $clone; } } - -class_alias(License::class, \ApiPlatform\Core\OpenApi\Model\License::class); diff --git a/src/OpenApi/Model/Link.php b/src/OpenApi/Model/Link.php index 9021e3e10c2..edd7180d221 100644 --- a/src/OpenApi/Model/Link.php +++ b/src/OpenApi/Model/Link.php @@ -97,5 +97,3 @@ public function withServer(Server $server): self return $clone; } } - -class_alias(Link::class, \ApiPlatform\Core\OpenApi\Model\Link::class); diff --git a/src/OpenApi/Model/MediaType.php b/src/OpenApi/Model/MediaType.php index b982360ef13..ae97fec3583 100644 --- a/src/OpenApi/Model/MediaType.php +++ b/src/OpenApi/Model/MediaType.php @@ -82,5 +82,3 @@ public function withEncoding(Encoding $encoding): self return $clone; } } - -class_alias(MediaType::class, \ApiPlatform\Core\OpenApi\Model\MediaType::class); diff --git a/src/OpenApi/Model/OAuthFlow.php b/src/OpenApi/Model/OAuthFlow.php index 884bbfe96f8..e8e6b35c1f6 100644 --- a/src/OpenApi/Model/OAuthFlow.php +++ b/src/OpenApi/Model/OAuthFlow.php @@ -82,5 +82,3 @@ public function withScopes(\ArrayObject $scopes): self return $clone; } } - -class_alias(OAuthFlow::class, \ApiPlatform\Core\OpenApi\Model\OAuthFlow::class); diff --git a/src/OpenApi/Model/OAuthFlows.php b/src/OpenApi/Model/OAuthFlows.php index f68e678ceea..0e0cc02db5c 100644 --- a/src/OpenApi/Model/OAuthFlows.php +++ b/src/OpenApi/Model/OAuthFlows.php @@ -82,5 +82,3 @@ public function withAuthorizationCode(OAuthFlow $authorizationCode): self return $clone; } } - -class_alias(OAuthFlows::class, \ApiPlatform\Core\OpenApi\Model\OAuthFlows::class); diff --git a/src/OpenApi/Model/Operation.php b/src/OpenApi/Model/Operation.php index e16bdf3d99b..d829f1d7a01 100644 --- a/src/OpenApi/Model/Operation.php +++ b/src/OpenApi/Model/Operation.php @@ -210,5 +210,3 @@ public function withServers(?array $servers = null): self return $clone; } } - -class_alias(Operation::class, \ApiPlatform\Core\OpenApi\Model\Operation::class); diff --git a/src/OpenApi/Model/Parameter.php b/src/OpenApi/Model/Parameter.php index eddf887f1f8..9965704db78 100644 --- a/src/OpenApi/Model/Parameter.php +++ b/src/OpenApi/Model/Parameter.php @@ -242,5 +242,3 @@ public function withContent(\ArrayObject $content): self return $clone; } } - -class_alias(Parameter::class, \ApiPlatform\Core\OpenApi\Model\Parameter::class); diff --git a/src/OpenApi/Model/PathItem.php b/src/OpenApi/Model/PathItem.php index de173a8518f..5f08abde98a 100644 --- a/src/OpenApi/Model/PathItem.php +++ b/src/OpenApi/Model/PathItem.php @@ -218,5 +218,3 @@ public function withParameters(array $parameters): self return $clone; } } - -class_alias(PathItem::class, \ApiPlatform\Core\OpenApi\Model\PathItem::class); diff --git a/src/OpenApi/Model/Paths.php b/src/OpenApi/Model/Paths.php index 7d0cae6c3ae..babfdb82cb0 100644 --- a/src/OpenApi/Model/Paths.php +++ b/src/OpenApi/Model/Paths.php @@ -34,5 +34,3 @@ public function getPaths(): array return $this->paths ?? []; } } - -class_alias(Paths::class, \ApiPlatform\Core\OpenApi\Model\Paths::class); diff --git a/src/OpenApi/Model/RequestBody.php b/src/OpenApi/Model/RequestBody.php index 3703ecd8b5b..350136faf70 100644 --- a/src/OpenApi/Model/RequestBody.php +++ b/src/OpenApi/Model/RequestBody.php @@ -67,5 +67,3 @@ public function withRequired(bool $required): self return $clone; } } - -class_alias(RequestBody::class, \ApiPlatform\Core\OpenApi\Model\RequestBody::class); diff --git a/src/OpenApi/Model/Response.php b/src/OpenApi/Model/Response.php index 29ed33ac79f..54c7326a2fc 100644 --- a/src/OpenApi/Model/Response.php +++ b/src/OpenApi/Model/Response.php @@ -82,5 +82,3 @@ public function withLinks(\ArrayObject $links): self return $clone; } } - -class_alias(Response::class, \ApiPlatform\Core\OpenApi\Model\Response::class); diff --git a/src/OpenApi/Model/Schema.php b/src/OpenApi/Model/Schema.php index 487049a4e4d..68a31abf779 100644 --- a/src/OpenApi/Model/Schema.php +++ b/src/OpenApi/Model/Schema.php @@ -172,5 +172,3 @@ public function withDeprecated(bool $deprecated): self return $clone; } } - -class_alias(Schema::class, \ApiPlatform\Core\OpenApi\Model\Schema::class); diff --git a/src/OpenApi/Model/SecurityScheme.php b/src/OpenApi/Model/SecurityScheme.php index bf255ccdb43..600770f257f 100644 --- a/src/OpenApi/Model/SecurityScheme.php +++ b/src/OpenApi/Model/SecurityScheme.php @@ -142,5 +142,3 @@ public function withOpenIdConnectUrl(string $openIdConnectUrl): self return $clone; } } - -class_alias(SecurityScheme::class, \ApiPlatform\Core\OpenApi\Model\SecurityScheme::class); diff --git a/src/OpenApi/Model/Server.php b/src/OpenApi/Model/Server.php index 1baa0c8aea2..35eaafe6b28 100644 --- a/src/OpenApi/Model/Server.php +++ b/src/OpenApi/Model/Server.php @@ -67,5 +67,3 @@ public function withVariables(\ArrayObject $variables): self return $clone; } } - -class_alias(Server::class, \ApiPlatform\Core\OpenApi\Model\Server::class); diff --git a/src/OpenApi/OpenApi.php b/src/OpenApi/OpenApi.php index 09e9d1a2b55..2efede9b088 100644 --- a/src/OpenApi/OpenApi.php +++ b/src/OpenApi/OpenApi.php @@ -174,5 +174,3 @@ public function withJsonSchemaDialect(?string $jsonSchemaDialect): self return $clone; } } - -class_alias(OpenApi::class, \ApiPlatform\Core\OpenApi\OpenApi::class); diff --git a/src/OpenApi/Options.php b/src/OpenApi/Options.php index a7ba9e871a3..65a66293e1d 100644 --- a/src/OpenApi/Options.php +++ b/src/OpenApi/Options.php @@ -139,5 +139,3 @@ public function getLicenseUrl(): ?string return $this->licenseUrl; } } - -class_alias(Options::class, \ApiPlatform\Core\OpenApi\Options::class); diff --git a/src/OpenApi/Serializer/ApiGatewayNormalizer.php b/src/OpenApi/Serializer/ApiGatewayNormalizer.php index 78b3d099f9a..c904208a51f 100644 --- a/src/OpenApi/Serializer/ApiGatewayNormalizer.php +++ b/src/OpenApi/Serializer/ApiGatewayNormalizer.php @@ -149,5 +149,3 @@ private function normalizeRef(string $ref): string return implode('/', $refParts); } } - -class_alias(ApiGatewayNormalizer::class, \ApiPlatform\Core\Swagger\Serializer\ApiGatewayNormalizer::class); diff --git a/src/OpenApi/Serializer/OpenApiNormalizer.php b/src/OpenApi/Serializer/OpenApiNormalizer.php index 489d3c9123a..86991992af2 100644 --- a/src/OpenApi/Serializer/OpenApiNormalizer.php +++ b/src/OpenApi/Serializer/OpenApiNormalizer.php @@ -87,5 +87,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(OpenApiNormalizer::class, \ApiPlatform\Core\OpenApi\Serializer\OpenApiNormalizer::class); diff --git a/src/Operation/DashPathSegmentNameGenerator.php b/src/Operation/DashPathSegmentNameGenerator.php index 8d320e12528..3cac090173f 100644 --- a/src/Operation/DashPathSegmentNameGenerator.php +++ b/src/Operation/DashPathSegmentNameGenerator.php @@ -35,5 +35,3 @@ private function dashize(string $string): string return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '-$1', $string)); } } - -class_alias(DashPathSegmentNameGenerator::class, \ApiPlatform\Core\Operation\DashPathSegmentNameGenerator::class); diff --git a/src/Operation/UnderscorePathSegmentNameGenerator.php b/src/Operation/UnderscorePathSegmentNameGenerator.php index 09d75ec1fdf..c045cad6991 100644 --- a/src/Operation/UnderscorePathSegmentNameGenerator.php +++ b/src/Operation/UnderscorePathSegmentNameGenerator.php @@ -32,5 +32,3 @@ public function getSegmentName(string $name, bool $collection = true): string return $collection ? Inflector::pluralize($name) : $name; } } - -class_alias(UnderscorePathSegmentNameGenerator::class, \ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator::class); diff --git a/src/PathResolver/CustomOperationPathResolver.php b/src/PathResolver/CustomOperationPathResolver.php deleted file mode 100644 index 11b8f2f52c1..00000000000 --- a/src/PathResolver/CustomOperationPathResolver.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * 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\PathResolver; - -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; - -/** - * Resolves the custom operations path. - * - * @author Guilhem N. - */ -final class CustomOperationPathResolver implements OperationPathResolverInterface -{ - private $deferred; - - public function __construct(OperationPathResolverInterface $deferred) - { - $this->deferred = $deferred; - } - - /** - * {@inheritdoc} - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() >= 4) { - $operationName = func_get_arg(3); - } else { - @trigger_error(sprintf('Method %s() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1.', __METHOD__), \E_USER_DEPRECATED); - - $operationName = null; - } - - return $operation['path'] ?? $this->deferred->resolveOperationPath($resourceShortName, $operation, OperationTypeDeprecationHelper::getOperationType($operationType), $operationName); - } -} - -class_alias(CustomOperationPathResolver::class, \ApiPlatform\Core\PathResolver\CustomOperationPathResolver::class); diff --git a/src/PathResolver/OperationPathResolver.php b/src/PathResolver/OperationPathResolver.php deleted file mode 100644 index a08957bb31d..00000000000 --- a/src/PathResolver/OperationPathResolver.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * 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\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Api\OperationTypeDeprecationHelper; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Operation\PathSegmentNameGeneratorInterface; - -/** - * Generates an operation path. - * - * @author Antoine Bluchet - */ -final class OperationPathResolver implements OperationPathResolverInterface -{ - private $pathSegmentNameGenerator; - - public function __construct(PathSegmentNameGeneratorInterface $pathSegmentNameGenerator) - { - $this->pathSegmentNameGenerator = $pathSegmentNameGenerator; - } - - /** - * {@inheritdoc} - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string - { - if (\func_num_args() < 4) { - @trigger_error(sprintf('Method %s() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1.', __METHOD__), \E_USER_DEPRECATED); - } - - $operationType = OperationTypeDeprecationHelper::getOperationType($operationType); - - if (OperationType::SUBRESOURCE === $operationType) { - throw new InvalidArgumentException('Subresource operations are not supported by the OperationPathResolver.'); - } - - $path = '/'.$this->pathSegmentNameGenerator->getSegmentName($resourceShortName); - - if (OperationType::ITEM === $operationType) { - if (isset($operation['identifiers']) && (\count($operation['identifiers']) <= 1 || false === ($operation['has_composite_identifier'] ?? true))) { - foreach ($operation['identifiers'] as $parameterName => $identifier) { - $path .= sprintf('/{%s}', \is_string($parameterName) ? $parameterName : $identifier); - } - } else { - $path .= '/{id}'; - } - } - - $path .= '.{_format}'; - - return $path; - } -} - -class_alias(OperationPathResolver::class, \ApiPlatform\Core\PathResolver\OperationPathResolver::class); diff --git a/src/PathResolver/OperationPathResolverInterface.php b/src/PathResolver/OperationPathResolverInterface.php deleted file mode 100644 index a447dff270e..00000000000 --- a/src/PathResolver/OperationPathResolverInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * 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\PathResolver; - -/** - * Resolves the path of a resource operation. - * - * @author Paul Le Corre - */ -interface OperationPathResolverInterface -{ - /** - * Resolves the operation path. - * - * @param string $resourceShortName When the operation type is a subresource and the operation has more than one identifier, this value is the previous operation path - * @param array $operation The operation metadata - * @param string|bool $operationType One of the constants defined in ApiPlatform\Core\Api\OperationType - * If the property is a boolean, true represents OperationType::COLLECTION, false is for OperationType::ITEM - */ - public function resolveOperationPath(string $resourceShortName, array $operation, $operationType/* , string $operationName = null */): string; -} diff --git a/src/Problem/Serializer/ConstraintViolationListNormalizer.php b/src/Problem/Serializer/ConstraintViolationListNormalizer.php index e4935bb828d..70325c06227 100644 --- a/src/Problem/Serializer/ConstraintViolationListNormalizer.php +++ b/src/Problem/Serializer/ConstraintViolationListNormalizer.php @@ -56,5 +56,3 @@ public function normalize($object, $format = null, array $context = []): array ]; } } - -class_alias(ConstraintViolationListNormalizer::class, \ApiPlatform\Core\Problem\Serializer\ConstraintViolationListNormalizer::class); diff --git a/src/Problem/Serializer/ErrorNormalizer.php b/src/Problem/Serializer/ErrorNormalizer.php index b819a1282a9..2d424d58ea2 100644 --- a/src/Problem/Serializer/ErrorNormalizer.php +++ b/src/Problem/Serializer/ErrorNormalizer.php @@ -78,5 +78,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(ErrorNormalizer::class, \ApiPlatform\Core\Problem\Serializer\ErrorNormalizer::class); diff --git a/src/Problem/Serializer/ErrorNormalizerTrait.php b/src/Problem/Serializer/ErrorNormalizerTrait.php index 18c373db33e..773fade6bcf 100644 --- a/src/Problem/Serializer/ErrorNormalizerTrait.php +++ b/src/Problem/Serializer/ErrorNormalizerTrait.php @@ -53,5 +53,3 @@ private function getErrorCode($object): ?string return null; } } - -class_alias(ErrorNormalizerTrait::class, \ApiPlatform\Core\Problem\Serializer\ErrorNormalizerTrait::class); diff --git a/src/RamseyUuid/Serializer/UuidDenormalizer.php b/src/RamseyUuid/Serializer/UuidDenormalizer.php index 5d691261504..9df2f011c66 100644 --- a/src/RamseyUuid/Serializer/UuidDenormalizer.php +++ b/src/RamseyUuid/Serializer/UuidDenormalizer.php @@ -42,5 +42,3 @@ public function supportsDenormalization($data, $type, $format = null): bool return \is_string($data) && is_a($type, UuidInterface::class, true); } } - -class_alias(UuidDenormalizer::class, \ApiPlatform\Core\Bridge\RamseyUuid\Serializer\UuidDenormalizer::class); diff --git a/src/Serializer/AbstractCollectionNormalizer.php b/src/Serializer/AbstractCollectionNormalizer.php index 41c09dd820b..d4aa8f41042 100644 --- a/src/Serializer/AbstractCollectionNormalizer.php +++ b/src/Serializer/AbstractCollectionNormalizer.php @@ -155,5 +155,3 @@ abstract protected function getPaginationData($object, array $context = []): arr */ abstract protected function getItemsData($object, string $format = null, array $context = []): array; } - -class_alias(AbstractCollectionNormalizer::class, \ApiPlatform\Core\Serializer\AbstractCollectionNormalizer::class); diff --git a/src/Serializer/AbstractConstraintViolationListNormalizer.php b/src/Serializer/AbstractConstraintViolationListNormalizer.php index ba898d12fc9..fcc9f4f1430 100644 --- a/src/Serializer/AbstractConstraintViolationListNormalizer.php +++ b/src/Serializer/AbstractConstraintViolationListNormalizer.php @@ -85,5 +85,3 @@ protected function getMessagesAndViolations(ConstraintViolationListInterface $co return [$messages, $violations]; } } - -class_alias(AbstractConstraintViolationListNormalizer::class, \ApiPlatform\Core\Serializer\AbstractConstraintViolationListNormalizer::class); diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 7a366579c50..e28f997e269 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -15,14 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Bridge\Symfony\Messenger\DataTransformer as MessengerDataTransformer; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\InvalidValueException; use ApiPlatform\Exception\ItemNotFoundException; @@ -78,16 +70,15 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer protected $resourceClassResolver; protected $resourceAccessChecker; protected $propertyAccessor; - protected $itemDataProvider; protected $allowPlainIdentifiers; protected $dataTransformers = []; protected $localCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, array $defaultContext = [], iterable $dataTransformers = [], $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { if (!isset($defaultContext['circular_reference_handler'])) { $defaultContext['circular_reference_handler'] = function ($object) { - return $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object); + return $this->iriConverter->getIriFromResource($object); }; } if (!interface_exists(AdvancedNameConverterInterface::class) && method_exists($this, 'setCircularReferenceHandler')) { @@ -98,36 +89,9 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; - - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - $this->iriConverter = $iriConverter; $this->resourceClassResolver = $resourceClassResolver; $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - $this->itemDataProvider = $itemDataProvider; - - if (true === $allowPlainIdentifiers) { - @trigger_error(sprintf('Allowing plain identifiers as argument of "%s" is deprecated since API Platform 2.7 and will not be possible anymore in API Platform 3.', self::class), \E_USER_DEPRECATED); - } - $this->allowPlainIdentifiers = $allowPlainIdentifiers; - - $this->dataTransformers = $dataTransformers; - - // Just skip our data transformer to trigger a proper deprecation - $customDataTransformers = array_filter(\is_array($dataTransformers) ? $dataTransformers : iterator_to_array($dataTransformers), function ($dataTransformer) { - return !$dataTransformer instanceof MessengerDataTransformer; - }); - - if (\count($customDataTransformers)) { - trigger_deprecation('api-platform/core', '2.7', 'The DataTransformer pattern is deprecated, use a Provider or a Processor and either use your input or return a new output there.'); - } - - if ($resourceMetadataFactory && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->resourceAccessChecker = $resourceAccessChecker; } @@ -188,7 +152,7 @@ public function normalize($object, $format = null, array $context = []) if (isset($context['iri'])) { $iri = $context['iri']; } else { - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_URL, $context['operation'] ?? null, $context); + $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_URL, $context['operation'] ?? null, $context); } $context['iri'] = $iri; @@ -245,71 +209,25 @@ public function denormalize($data, $class, $format = null, array $context = []) $context['api_denormalize'] = true; $context['resource_class'] = $resourceClass; - if (null !== $inputClass = $this->getInputClass($resourceClass, $context)) { - if (null !== $dataTransformer = $this->getDataTransformer($data, $resourceClass, $context)) { - $dataTransformerContext = $context; - - unset($context['input']); - unset($context['resource_class']); - - if (!$this->serializer instanceof DenormalizerInterface) { - throw new LogicException('Cannot denormalize the input because the injected serializer is not a denormalizer'); - } - - if ($dataTransformer instanceof DataTransformerInitializerInterface) { - $context[AbstractObjectNormalizer::OBJECT_TO_POPULATE] = $dataTransformer->initialize($inputClass, $context); - $context[AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE] = true; - } - - try { - $denormalizedInput = $this->serializer->denormalize($data, $inputClass, $format, $context); - } catch (NotNormalizableValueException $e) { - throw new UnexpectedValueException('The input data is misformatted.', $e->getCode(), $e); - } - - if (!\is_object($denormalizedInput)) { - throw new UnexpectedValueException('Expected denormalized input to be an object.'); - } - - return $dataTransformer->transform($denormalizedInput, $resourceClass, $dataTransformerContext); - } - - // Are we in a Request context? - if ($context['operation'] ?? $context['operation_type'] ?? false) { - $resourceClass = $inputClass; - $context['resource_class'] = $inputClass; - } + if ( + $inputClass = $this->getInputClass($resourceClass, $context) + && + ($context['operation'] ?? $context['operation_type'] ?? false) // Are we in a Request context? + ) { + $resourceClass = $inputClass; + $context['resource_class'] = $inputClass; } - $supportsPlainIdentifiers = $this->supportsPlainIdentifiers(); - if (\is_string($data)) { try { - return $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($data, $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($data, $context + ['fetch_data' => true]); + return $this->iriConverter->getResourceFromIri($data, $context + ['fetch_data' => true]); } catch (ItemNotFoundException $e) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); - } + throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); } catch (InvalidArgumentException $e) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException(sprintf('Invalid IRI "%s".', $data), $e->getCode(), $e); - } + throw new UnexpectedValueException(sprintf('Invalid IRI "%s".', $data), $e->getCode(), $e); } } - if (!\is_array($data)) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException(sprintf('Expected IRI or document for resource "%s", "%s" given.', $resourceClass, \gettype($data))); - } - - $item = $this->itemDataProvider->getItem($resourceClass, $data, null, $context + ['fetch_data' => true]); - if (null === $item) { - throw new ItemNotFoundException(sprintf('Item not found for resource "%s" with id "%s".', $resourceClass, $data)); - } - - return $item; - } - $previousObject = null !== $objectToPopulate ? clone $objectToPopulate : null; $object = parent::denormalize($data, $resourceClass, $format, $context); @@ -598,19 +516,13 @@ protected function denormalizeCollection(string $attribute, $propertyMetadata, T */ protected function denormalizeRelation(string $attributeName, $propertyMetadata, string $className, $value, ?string $format, array $context) { - $supportsPlainIdentifiers = $this->supportsPlainIdentifiers(); - if (\is_string($value)) { try { - return $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($value, $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($value, $context + ['fetch_data' => true]); + return $this->iriConverter->getResourceFromIri($value, $context + ['fetch_data' => true]); } catch (ItemNotFoundException $e) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); - } + throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); } catch (InvalidArgumentException $e) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException(sprintf('Invalid IRI "%s".', $value), $e->getCode(), $e); - } + throw new UnexpectedValueException(sprintf('Invalid IRI "%s".', $value), $e->getCode(), $e); } } @@ -629,23 +541,12 @@ protected function denormalizeRelation(string $attributeName, $propertyMetadata, return $item; } catch (InvalidValueException $e) { - if (!$supportsPlainIdentifiers) { - throw $e; - } + throw $e; } } if (!\is_array($value)) { - if (!$supportsPlainIdentifiers) { - throw new UnexpectedValueException(sprintf('Expected IRI or nested document for attribute "%s", "%s" given.', $attributeName, \gettype($value))); - } - - $item = $this->itemDataProvider->getItem($className, $value, null, $context + ['fetch_data' => true]); - if (null === $item) { - throw new ItemNotFoundException(sprintf('Item not found for resource "%s" with id "%s".', $className, $value)); - } - - return $item; + throw new UnexpectedValueException(sprintf('Expected IRI or nested document for attribute "%s", "%s" given.', $attributeName, \gettype($value))); } throw new UnexpectedValueException(sprintf('Nested documents for attribute "%s" are not allowed. Use IRIs instead.', $attributeName)); @@ -859,50 +760,14 @@ protected function normalizeRelation($propertyMetadata, $relatedObject, string $ return $iri; } - /** - * Finds the first supported data transformer if any. - * - * @param object|array $data object on normalize / array on denormalize - */ - protected function getDataTransformer($data, string $to, array $context = []): ?DataTransformerInterface - { - foreach ($this->dataTransformers as $dataTransformer) { - if ($dataTransformer->supportsTransformation($data, $to, $context)) { - return $dataTransformer; - } - } - - return null; - } - - /** - * For a given resource, it returns an output representation if any - * If not, the resource is returned. - * - * @param mixed $object - */ - protected function transformOutput($object, array $context = [], string $outputClass = null) - { - if (null === $outputClass) { - $outputClass = $this->getOutputClass($this->getObjectClass($object), $context); - } - - if (null !== $outputClass && null !== $dataTransformer = $this->getDataTransformer($object, $outputClass, $context)) { - return $dataTransformer->transform($object, $outputClass, $context); - } - - return $object; - } - private function createAttributeValue($attribute, $value, $format = null, array $context = []) { if (!$this->resourceClassResolver->isResourceClass($context['resource_class'])) { return $value; } - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context)); - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : ($propertyMetadata->getBuiltinTypes()[0] ?? null); + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; if (null === $type) { // No type provided, blindly return the value @@ -1040,16 +905,4 @@ private function setValue($object, string $attributeName, $value) // Properties not found are ignored } } - - /** - * TODO: to remove in 3.0. - * - * @deprecated since 2.7 - */ - private function supportsPlainIdentifiers(): bool - { - return $this->allowPlainIdentifiers && null !== $this->itemDataProvider; - } } - -class_alias(AbstractItemNormalizer::class, \ApiPlatform\Core\Serializer\AbstractItemNormalizer::class); diff --git a/src/Serializer/CacheKeyTrait.php b/src/Serializer/CacheKeyTrait.php index 56c9823c660..51cb44952d9 100644 --- a/src/Serializer/CacheKeyTrait.php +++ b/src/Serializer/CacheKeyTrait.php @@ -34,5 +34,3 @@ private function getCacheKey(?string $format, array $context) } } } - -class_alias(CacheKeyTrait::class, \ApiPlatform\Core\Serializer\CacheKeyTrait::class); diff --git a/src/Serializer/ContextTrait.php b/src/Serializer/ContextTrait.php index 90fe49392a4..daf67498f62 100644 --- a/src/Serializer/ContextTrait.php +++ b/src/Serializer/ContextTrait.php @@ -31,5 +31,3 @@ private function initContext(string $resourceClass, array $context): array ]); } } - -class_alias(ContextTrait::class, \ApiPlatform\Core\Serializer\ContextTrait::class); diff --git a/src/Serializer/Filter/GroupFilter.php b/src/Serializer/Filter/GroupFilter.php index e297ac4cfba..24999cab313 100644 --- a/src/Serializer/Filter/GroupFilter.php +++ b/src/Serializer/Filter/GroupFilter.php @@ -75,5 +75,3 @@ public function getDescription(string $resourceClass): array ]; } } - -class_alias(GroupFilter::class, \ApiPlatform\Core\Serializer\Filter\GroupFilter::class); diff --git a/src/Serializer/Filter/PropertyFilter.php b/src/Serializer/Filter/PropertyFilter.php index a5f34449af0..41e1e86ecff 100644 --- a/src/Serializer/Filter/PropertyFilter.php +++ b/src/Serializer/Filter/PropertyFilter.php @@ -168,5 +168,3 @@ private function denormalizePropertyName($property) return null !== $this->nameConverter ? $this->nameConverter->denormalize($property) : $property; } } - -class_alias(PropertyFilter::class, \ApiPlatform\Core\Serializer\Filter\PropertyFilter::class); diff --git a/src/Serializer/InputOutputMetadataTrait.php b/src/Serializer/InputOutputMetadataTrait.php index 66bbb61b71e..8c7758053cf 100644 --- a/src/Serializer/InputOutputMetadataTrait.php +++ b/src/Serializer/InputOutputMetadataTrait.php @@ -85,5 +85,3 @@ private function getInputOutputMetadata(string $class, string $inputOrOutput, ar return $metadata->getAttribute($inputOrOutput)['class'] ?? null; } } - -class_alias(InputOutputMetadataTrait::class, \ApiPlatform\Core\Serializer\InputOutputMetadataTrait::class); diff --git a/src/Serializer/ItemNormalizer.php b/src/Serializer/ItemNormalizer.php index e97c6daedbf..80390d98afd 100644 --- a/src/Serializer/ItemNormalizer.php +++ b/src/Serializer/ItemNormalizer.php @@ -14,11 +14,12 @@ namespace ApiPlatform\Serializer; use ApiPlatform\Api\IriConverterInterface; +use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; @@ -36,15 +37,9 @@ class ItemNormalizer extends AbstractItemNormalizer { private $logger; - /** - * @param mixed $propertyMetadataFactory - * @param LegacyIriConverterInterface|IriConverterInterface $iriConverter - * @param mixed $resourceClassResolver - * @param mixed|null $resourceMetadataFactory - */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, ItemDataProviderInterface $itemDataProvider = null, bool $allowPlainIdentifiers = false, LoggerInterface $logger = null, iterable $dataTransformers = [], $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, LoggerInterface $logger = null, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $itemDataProvider, $allowPlainIdentifiers, [], $dataTransformers, $resourceMetadataFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, [], $resourceMetadataFactory, $resourceAccessChecker); $this->logger = $logger ?: new NullLogger(); } @@ -80,33 +75,13 @@ public function denormalize($data, $class, $format = null, array $context = []) private function updateObjectToPopulate(array $data, array &$context): void { try { - $context[self::OBJECT_TO_POPULATE] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri((string) $data['id'], $context + ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri((string) $data['id'], $context + ['fetch_data' => true]); + $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri((string) $data['id'], $context + ['fetch_data' => true]); } catch (InvalidArgumentException $e) { - if ($this->iriConverter instanceof LegacyIriConverterInterface) { - // remove in 3.0 - $identifier = null; - $options = $this->getFactoryOptions($context); + $operation = $this->resourceMetadataFactory->create($context['resource_class'])->getOperation(); + // todo: we could guess uri variables with the operation and the data instead of hardcoding id + $iri = $this->iriConverter->getIriFromResource($context['resource_class'], UrlGeneratorInterface::ABS_PATH, $operation, ['uri_variables' => ['id' => $data['id']]]); - foreach ($this->propertyNameCollectionFactory->create($context['resource_class'], $options) as $propertyName) { - if (true === $this->propertyMetadataFactory->create($context['resource_class'], $propertyName)->isIdentifier()) { - $identifier = $propertyName; - break; - } - } - - if (null === $identifier) { - throw $e; - } - $iri = sprintf('%s/%s', $this->iriConverter->getIriFromResourceClass($context['resource_class']), $data[$identifier]); - } else { - $operation = $this->resourceMetadataFactory->create($context['resource_class'])->getOperation(); - // todo: we could guess uri variables with the operation and the data instead of hardcoding id - $iri = $this->iriConverter->getIriFromResource($context['resource_class'], UrlGeneratorInterface::ABS_PATH, $operation, ['uri_variables' => ['id' => $data['id']]]); - } - - $context[self::OBJECT_TO_POPULATE] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getItemFromIri($iri, ['fetch_data' => true]) : $this->iriConverter->getResourceFromIri($iri, ['fetch_data' => true]); + $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri($iri, ['fetch_data' => true]); } } } - -class_alias(ItemNormalizer::class, \ApiPlatform\Core\Serializer\ItemNormalizer::class); diff --git a/src/Serializer/JsonEncoder.php b/src/Serializer/JsonEncoder.php index 2a95e510bb0..a336ae787a9 100644 --- a/src/Serializer/JsonEncoder.php +++ b/src/Serializer/JsonEncoder.php @@ -86,5 +86,3 @@ public function decode($data, $format, array $context = []) return $this->jsonEncoder->decode($data, $format, $context); } } - -class_alias(JsonEncoder::class, \ApiPlatform\Core\Serializer\JsonEncoder::class); diff --git a/src/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Serializer/Mapping/Factory/ClassMetadataFactory.php index fb2b29ee391..954c8bdb8dc 100644 --- a/src/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ b/src/Serializer/Mapping/Factory/ClassMetadataFactory.php @@ -44,5 +44,3 @@ public function hasMetadataFor($value): bool return $this->decorated->hasMetadataFor(\is_object($value) ? $this->getObjectClass($value) : $this->getRealClassName($value)); } } - -class_alias(ClassMetadataFactory::class, \ApiPlatform\Core\Serializer\Mapping\Factory\ClassMetadataFactory::class); diff --git a/src/Serializer/ResourceList.php b/src/Serializer/ResourceList.php index caba8d0d6c0..3817529da26 100644 --- a/src/Serializer/ResourceList.php +++ b/src/Serializer/ResourceList.php @@ -19,5 +19,3 @@ class ResourceList extends \ArrayObject { } - -class_alias(ResourceList::class, \ApiPlatform\Core\Serializer\ResourceList::class); diff --git a/src/Serializer/SerializerContextBuilder.php b/src/Serializer/SerializerContextBuilder.php index e5d97ec8d7c..6f5ae3a4b96 100644 --- a/src/Serializer/SerializerContextBuilder.php +++ b/src/Serializer/SerializerContextBuilder.php @@ -13,12 +13,7 @@ namespace ApiPlatform\Serializer; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Request; @@ -33,13 +28,9 @@ final class SerializerContextBuilder implements SerializerContextBuilderInterfac { private $resourceMetadataFactory; - public function __construct($resourceMetadataFactory) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -51,70 +42,30 @@ public function createFromRequest(Request $request, bool $normalization, array $ throw new RuntimeException('Request attributes are not valid.'); } - // TODO: 3.0 change the condition to remove the ResourceMetadataFactorym only used to skip null values - if ( - $this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface - && (isset($attributes['operation_name']) || isset($attributes['operation'])) - ) { - $operation = $attributes['operation'] ?? $this->resourceMetadataFactory->create($attributes['resource_class'])->getOperation($attributes['operation_name']); - $context = $normalization ? ($operation->getNormalizationContext() ?? []) : ($operation->getDenormalizationContext() ?? []); - $context['operation_name'] = $operation->getName(); - $context['operation'] = $operation; - $context['resource_class'] = $attributes['resource_class']; - // TODO: 3.0 becomes true by default - $context['skip_null_values'] = $context['skip_null_values'] ?? $this->shouldSkipNullValues($attributes['resource_class'], $context['operation_name']); - // TODO: remove in 3.0, operation type will not exist anymore - $context['operation_type'] = $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM; - $context['iri_only'] = $context['iri_only'] ?? false; - $context['request_uri'] = $request->getRequestUri(); - $context['uri'] = $request->getUri(); - $context['input'] = $operation->getInput(); - $context['output'] = $operation->getOutput(); + $operation = $attributes['operation'] ?? $this->resourceMetadataFactory->create($attributes['resource_class'])->getOperation($attributes['operation_name']); + $context = $normalization ? ($operation->getNormalizationContext() ?? []) : ($operation->getDenormalizationContext() ?? []); + $context['operation_name'] = $operation->getName(); + $context['operation'] = $operation; + $context['resource_class'] = $attributes['resource_class']; + $context['skip_null_values'] = $context['skip_null_values'] ?? true; + $context['iri_only'] = $context['iri_only'] ?? false; + $context['request_uri'] = $request->getRequestUri(); + $context['uri'] = $request->getUri(); + $context['input'] = $operation->getInput(); + $context['output'] = $operation->getOutput(); + + if ($operation->getTypes()) { $context['types'] = $operation->getTypes(); + } + + if ($operation->getUriVariables()) { $context['uri_variables'] = []; foreach (array_keys($operation->getUriVariables() ?? []) as $parameterName) { $context['uri_variables'][$parameterName] = $request->attributes->get($parameterName); } - - if (!$normalization) { - if (!isset($context['api_allow_update'])) { - $context['api_allow_update'] = \in_array($method = $request->getMethod(), ['PUT', 'PATCH'], true); - - if ($context['api_allow_update'] && 'PATCH' === $method) { - $context['deep_object_to_populate'] = $context['deep_object_to_populate'] ?? true; - } - } - - if ('csv' === $request->getContentType()) { - $context[CsvEncoder::AS_COLLECTION_KEY] = false; - } - } - - return $context; - } - - /** @var ResourceMetadata $resourceMetadata */ - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - $key = $normalization ? 'normalization_context' : 'denormalization_context'; - if (isset($attributes['collection_operation_name'])) { - $operationKey = 'collection_operation_name'; - $operationType = OperationType::COLLECTION; - } elseif (isset($attributes['item_operation_name'])) { - $operationKey = 'item_operation_name'; - $operationType = OperationType::ITEM; - } else { - $operationKey = 'subresource_operation_name'; - $operationType = OperationType::SUBRESOURCE; } - $context = $resourceMetadata->getTypedOperationAttribute($operationType, $attributes[$operationKey], $key, [], true); - $context['operation_type'] = $operationType; - $context[$operationKey] = $attributes[$operationKey]; - $context['iri_only'] = $resourceMetadata->getAttribute('normalization_context')['iri_only'] ?? false; - $context['input'] = $resourceMetadata->getTypedOperationAttribute($operationType, $attributes[$operationKey], 'input', null, true); - $context['output'] = $resourceMetadata->getTypedOperationAttribute($operationType, $attributes[$operationKey], 'output', null, true); - if (!$normalization) { if (!isset($context['api_allow_update'])) { $context['api_allow_update'] = \in_array($method = $request->getMethod(), ['PUT', 'PATCH'], true); @@ -129,69 +80,6 @@ public function createFromRequest(Request $request, bool $normalization, array $ } } - $context['resource_class'] = $attributes['resource_class']; - $context['request_uri'] = $request->getRequestUri(); - $context['uri'] = $request->getUri(); - - if (isset($attributes['subresource_context'])) { - $context['subresource_identifiers'] = []; - - foreach ($attributes['subresource_context']['identifiers'] as $parameterName => [$resourceClass]) { - if (!isset($context['subresource_resources'][$resourceClass])) { - $context['subresource_resources'][$resourceClass] = []; - } - - $context['subresource_identifiers'][$parameterName] = $context['subresource_resources'][$resourceClass][$parameterName] = $request->attributes->get($parameterName); - } - } - - if (isset($attributes['subresource_property'])) { - $context['subresource_property'] = $attributes['subresource_property']; - $context['subresource_resource_class'] = $attributes['subresource_resource_class'] ?? null; - } - - unset($context[DocumentationNormalizer::SWAGGER_DEFINITION_NAME]); - - if (isset($context['skip_null_values'])) { - return $context; - } - - // TODO: We should always use `skip_null_values` but changing this would be a BC break, for now use it only when `merge-patch+json` is activated on a Resource - if (!$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - foreach ($resourceMetadata->getItemOperations() as $operation) { - if ('PATCH' === ($operation['method'] ?? '') && \in_array('application/merge-patch+json', $operation['input_formats']['json'] ?? [], true)) { - $context['skip_null_values'] = true; - - break; - } - } - } else { - $context['skip_null_values'] = $this->shouldSkipNullValues($attributes['resource_class'], $attributes['operation_name']); - } - return $context; } - - /** - * TODO: remove in 3.0, this will have no impact and skip_null_values will be default, no more resourceMetadataFactory call in this class. - */ - private function shouldSkipNullValues(string $class, string $operationName): bool - { - if (!$this->resourceMetadataFactory) { - return false; - } - - $collection = $this->resourceMetadataFactory->create($class); - foreach ($collection as $metadata) { - foreach ($metadata->getOperations() as $operation) { - if ('PATCH' === ($operation->getMethod() ?? '') && \in_array('application/merge-patch+json', $operation->getInputFormats()['json'] ?? [], true)) { - return true; - } - } - } - - return false; - } } - -class_alias(SerializerContextBuilder::class, \ApiPlatform\Core\Serializer\SerializerContextBuilder::class); diff --git a/src/Serializer/SerializerFilterContextBuilder.php b/src/Serializer/SerializerFilterContextBuilder.php index 234bdc841a8..3132861b8af 100644 --- a/src/Serializer/SerializerFilterContextBuilder.php +++ b/src/Serializer/SerializerFilterContextBuilder.php @@ -75,5 +75,3 @@ public function createFromRequest(Request $request, bool $normalization, array $ return $context; } } - -class_alias(SerializerFilterContextBuilder::class, \ApiPlatform\Core\Serializer\SerializerFilterContextBuilder::class); diff --git a/src/State/Pagination/ArrayPaginator.php b/src/State/Pagination/ArrayPaginator.php index d20f2ede837..94adbcea280 100644 --- a/src/State/Pagination/ArrayPaginator.php +++ b/src/State/Pagination/ArrayPaginator.php @@ -93,5 +93,3 @@ public function getIterator(): \Traversable return $this->iterator; } } - -class_alias(ArrayPaginator::class, \ApiPlatform\Core\DataProvider\ArrayPaginator::class); diff --git a/src/State/Pagination/PaginationOptions.php b/src/State/Pagination/PaginationOptions.php index 72fa7988a8a..2e62cc58926 100644 --- a/src/State/Pagination/PaginationOptions.php +++ b/src/State/Pagination/PaginationOptions.php @@ -102,5 +102,3 @@ public function getPartialPaginationParameterName(): string return $this->partialPaginationParameterName; } } - -class_alias(PaginationOptions::class, \ApiPlatform\Core\DataProvider\PaginationOptions::class); diff --git a/src/State/Pagination/TraversablePaginator.php b/src/State/Pagination/TraversablePaginator.php index bb5713de8f7..9b40f517804 100644 --- a/src/State/Pagination/TraversablePaginator.php +++ b/src/State/Pagination/TraversablePaginator.php @@ -88,5 +88,3 @@ public function getIterator(): \Traversable return $this->traversable; } } - -class_alias(TraversablePaginator::class, \ApiPlatform\Core\DataProvider\TraversablePaginator::class); diff --git a/src/Symfony/Bundle/ApiPlatformBundle.php b/src/Symfony/Bundle/ApiPlatformBundle.php index 9fe0c17db3e..6c7462f6c13 100644 --- a/src/Symfony/Bundle/ApiPlatformBundle.php +++ b/src/Symfony/Bundle/ApiPlatformBundle.php @@ -56,5 +56,3 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new AuthenticatorManagerPass()); } } - -class_alias(ApiPlatformBundle::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class); diff --git a/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php b/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php index 83f0aa495c6..2681a94748a 100644 --- a/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php +++ b/src/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php @@ -76,5 +76,3 @@ private function getExpectedInputClass(Request $request): ?string return $context['input'] ?? $context['resource_class']; } } - -class_alias(PayloadArgumentResolver::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver::class); diff --git a/src/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php b/src/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php index f6974680a9d..d9ead7ef527 100644 --- a/src/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php +++ b/src/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php @@ -59,5 +59,3 @@ public function isOptional(): bool return false; } } - -class_alias(CachePoolClearerCacheWarmer::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer::class); diff --git a/src/Symfony/Bundle/Command/GraphQlExportCommand.php b/src/Symfony/Bundle/Command/GraphQlExportCommand.php index 84db8778593..a0ce0797c78 100644 --- a/src/Symfony/Bundle/Command/GraphQlExportCommand.php +++ b/src/Symfony/Bundle/Command/GraphQlExportCommand.php @@ -80,5 +80,3 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } } - -class_alias(GraphQlExportCommand::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Command\GraphQlExportCommand::class); diff --git a/src/Symfony/Bundle/Command/OpenApiCommand.php b/src/Symfony/Bundle/Command/OpenApiCommand.php index de02f179acc..e27f083d63c 100644 --- a/src/Symfony/Bundle/Command/OpenApiCommand.php +++ b/src/Symfony/Bundle/Command/OpenApiCommand.php @@ -96,5 +96,3 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } } - -class_alias(OpenApiCommand::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Command\OpenApiCommand::class); diff --git a/src/Symfony/Bundle/DataCollector/RequestDataCollector.php b/src/Symfony/Bundle/DataCollector/RequestDataCollector.php index eaef3f46595..cf2901766ac 100644 --- a/src/Symfony/Bundle/DataCollector/RequestDataCollector.php +++ b/src/Symfony/Bundle/DataCollector/RequestDataCollector.php @@ -13,18 +13,7 @@ namespace ApiPlatform\Symfony\Bundle\DataCollector; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister\TraceableChainDataPersister; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainCollectionDataProvider; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainItemDataProvider; -use ApiPlatform\Core\Bridge\Symfony\Bundle\DataProvider\TraceableChainSubresourceDataProvider; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\Metadata\Resource\ApiResourceToLegacyResourceMetadataTrait; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\RequestAttributesExtractor; use PackageVersions\Versions; use Psr\Container\ContainerInterface; @@ -38,36 +27,15 @@ */ final class RequestDataCollector extends DataCollector { - use ApiResourceToLegacyResourceMetadataTrait; - - /** - * @var ResourceMetadataCollectionFactoryInterface - */ private $metadataFactory; private $filterLocator; - private $collectionDataProvider; - private $itemDataProvider; - private $subresourceDataProvider; - private $dataPersister; public function __construct( $metadataFactory, ContainerInterface $filterLocator, - CollectionDataProviderInterface $collectionDataProvider = null, - ItemDataProviderInterface $itemDataProvider = null, - SubresourceDataProviderInterface $subresourceDataProvider = null, - DataPersisterInterface $dataPersister = null ) { $this->metadataFactory = $metadataFactory; $this->filterLocator = $filterLocator; - $this->collectionDataProvider = $collectionDataProvider; - $this->itemDataProvider = $itemDataProvider; - $this->subresourceDataProvider = $subresourceDataProvider; - $this->dataPersister = $dataPersister; - - if (!$metadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -102,35 +70,8 @@ public function collect(Request $request, Response $response, \Throwable $except 'acceptable_content_types' => $request->getAcceptableContentTypes(), 'filters' => $filters, 'counters' => $counters, - 'dataProviders' => [], - 'dataPersisters' => ['responses' => []], 'request_attributes' => $requestAttributes, ]; - - if ($this->collectionDataProvider instanceof TraceableChainCollectionDataProvider) { - $this->data['dataProviders']['collection'] = [ - 'context' => $this->cloneVar($this->collectionDataProvider->getContext()), - 'responses' => $this->collectionDataProvider->getProvidersResponse(), - ]; - } - - if ($this->itemDataProvider instanceof TraceableChainItemDataProvider) { - $this->data['dataProviders']['item'] = [ - 'context' => $this->cloneVar($this->itemDataProvider->getContext()), - 'responses' => $this->itemDataProvider->getProvidersResponse(), - ]; - } - - if ($this->subresourceDataProvider instanceof TraceableChainSubresourceDataProvider) { - $this->data['dataProviders']['subresource'] = [ - 'context' => $this->cloneVar($this->subresourceDataProvider->getContext()), - 'responses' => $this->subresourceDataProvider->getProvidersResponse(), - ]; - } - - if ($this->dataPersister instanceof TraceableChainDataPersister) { - $this->data['dataPersisters']['responses'] = $this->dataPersister->getPersistersResponse(); - } } private function setFilters(ApiResource $resourceMetadata, int $index, array &$filters, array &$counters): void @@ -176,26 +117,6 @@ public function getCounters(): array return $this->data['counters'] ?? []; } - public function getCollectionDataProviders(): array - { - return $this->data['dataProviders']['collection'] ?? ['context' => [], 'responses' => []]; - } - - public function getItemDataProviders(): array - { - return $this->data['dataProviders']['item'] ?? ['context' => [], 'responses' => []]; - } - - public function getSubresourceDataProviders(): array - { - return $this->data['dataProviders']['subresource'] ?? ['context' => [], 'responses' => []]; - } - - public function getDataPersisters(): array - { - return $this->data['dataPersisters'] ?? ['responses' => []]; - } - public function getVersion(): ?string { if (!class_exists(Versions::class)) { diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index bc949d170b7..920d809bfe6 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -15,13 +15,6 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Annotation\ApiResource as ApiResourceAnnotation; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; use ApiPlatform\Doctrine\Odm\Filter\AbstractFilter as DoctrineMongoDbOdmAbstractFilter; @@ -41,10 +34,8 @@ use ApiPlatform\State\ProviderInterface; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; -use Doctrine\Common\Annotations\Annotation; use phpDocumentor\Reflection\DocBlockFactoryInterface; use Ramsey\Uuid\Uuid; -use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -118,7 +109,6 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerJsonHalConfiguration($formats, $loader, $config); $this->registerJsonProblemConfiguration($errorFormats, $loader); $this->registerGraphQlConfiguration($container, $config, $loader); - $this->registerLegacyBundlesConfiguration($container, $config, $loader); $this->registerCacheConfiguration($container); $this->registerDoctrineOrmConfiguration($container, $config, $loader); $this->registerDoctrineMongoDbOdmConfiguration($container, $config, $loader); @@ -132,18 +122,6 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerSecurityConfiguration($container, $loader, $config); $this->registerMakerConfiguration($container, $config, $loader); $this->registerArgumentResolverConfiguration($container, $loader, $config); - $this->registerLegacyServices($container, $config, $loader); - $this->registerUpgradeCommandConfiguration($container, $loader, $config); - - // TODO: remove in 3.x - $container->registerForAutoconfiguration(DataPersisterInterface::class) - ->addTag('api_platform.data_persister'); - $container->registerForAutoconfiguration(ItemDataProviderInterface::class) - ->addTag('api_platform.item_data_provider'); - $container->registerForAutoconfiguration(CollectionDataProviderInterface::class) - ->addTag('api_platform.collection_data_provider'); - $container->registerForAutoconfiguration(SubresourceDataProviderInterface::class) - ->addTag('api_platform.subresource_data_provider'); $container->registerForAutoconfiguration(FilterInterface::class) ->addTag('api_platform.filter'); @@ -155,57 +133,19 @@ public function load(array $configs, ContainerBuilder $container): void private function registerCommonConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader, array $formats, array $patchFormats, array $errorFormats): void { + $loader->load('symfony/events.xml'); $loader->load('api.xml'); - - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/api.xml'); - $loader->load('legacy/data_provider.xml'); - $loader->load('legacy/backward_compatibility.xml'); - } else { - $loader->load('v3/api.xml'); - $loader->load('legacy/data_provider.xml'); - $loader->load('v3/state.xml'); - $loader->load('v3/backward_compatibility.xml'); - } - - $loader->load('data_persister.xml'); - $loader->load('data_provider.xml'); + $loader->load('state.xml'); $loader->load('filter.xml'); - if ($container->hasDefinition('api_platform.operation_method_resolver')) { - $container->getDefinition('api_platform.operation_method_resolver') - ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%service_id%" service is deprecated since API Platform 2.5.')); - } - - if ($container->hasDefinition('api_platform.formats_provider')) { - $container->getDefinition('api_platform.formats_provider') - ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%service_id%" service is deprecated since API Platform 2.5.')); - $container->getAlias('ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface') - ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%alias_id%" alias is deprecated since API Platform 2.5.')); - } - - if ($container->hasDefinition('api_platform.operation_path_resolver.underscore')) { - $container->getDefinition('api_platform.operation_path_resolver.underscore') - ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since API Platform 2.1 and will be removed in 3.0. Use "api_platform.path_segment_name_generator.underscore" instead.')); - } - - if ($container->hasDefinition('api_platform.operation_path_resolver.underscore')) { - $container->getDefinition('api_platform.operation_path_resolver.dash') - ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since API Platform 2.1 and will be removed in 3.0. Use "api_platform.path_segment_name_generator.dash" instead.')); - } - - $container->getDefinition('api_platform.filters') - ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since 2.1 and will be removed in 3.0. Use the "api_platform.filter_locator" service instead.')); - if (class_exists(Uuid::class)) { $loader->load('ramsey_uuid.xml'); } if (class_exists(AbstractUid::class)) { - $loader->load('symfony_uid.xml'); + $loader->load('symfony/uid.xml'); } - $container->setParameter('api_platform.metadata_backward_compatibility_layer', $config['metadata_backward_compatibility_layer']); $container->setParameter('api_platform.enable_entrypoint', $config['enable_entrypoint']); $container->setParameter('api_platform.enable_docs', $config['enable_docs']); $container->setParameter('api_platform.title', $config['title']); @@ -277,19 +217,13 @@ private function getPaginationDefaults(array $defaults, array $collectionPaginat private function normalizeDefaults(array $defaults, bool $compatibility = false): array { - $key = $compatibility ? 'attributes' : 'extra_properties'; - $normalizedDefaults = [$key => $defaults[$key] ?? []]; - unset($defaults[$key]); + $normalizedDefaults = ['extra_properties' => $defaults['extra_properties'] ?? []]; + unset($defaults['extra_properties']); + $rc = new \ReflectionClass(ApiResource::class); $publicProperties = []; - - if ($compatibility) { - [$publicProperties,] = ApiResourceAnnotation::getConfigMetadata(); - } else { - $rc = new \ReflectionClass(ApiResource::class); - foreach ($rc->getConstructor()->getParameters() as $param) { - $publicProperties[$param->getName()] = true; - } + foreach ($rc->getConstructor()->getParameters() as $param) { + $publicProperties[$param->getName()] = true; } $nameConverter = new CamelCaseToSnakeCaseNameConverter(); @@ -300,7 +234,7 @@ private function normalizeDefaults(array $defaults, bool $compatibility = false) continue; } - $normalizedDefaults[$key][$option] = $value; + $normalizedDefaults['extra_properties'][$option] = $value; } return $normalizedDefaults; @@ -319,39 +253,11 @@ private function registerMetadataConfiguration(ContainerBuilder $container, arra )); } - $loader->load('legacy/metadata.xml'); - $container->getDefinition('api_platform.metadata.extractor.xml.legacy')->replaceArgument(0, $xmlResources); - - if (class_exists(Annotation::class)) { - $loader->load('legacy/metadata_annotation.xml'); - } - - if (interface_exists(DocBlockFactoryInterface::class)) { - $loader->load('legacy/metadata_php_doc.xml'); - } - - if (class_exists(Yaml::class)) { - $loader->load('legacy/metadata_yaml.xml'); - $container->getDefinition('api_platform.metadata.extractor.yaml.legacy')->replaceArgument(0, $yamlResources); - - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/metadata_yaml_backward_compatibility.xml'); - } - } - - // Load the legacy metadata as well - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/metadata_backward_compatibility.xml'); - - return; - } - // V3 metadata $loader->load('metadata/xml.xml'); $loader->load('metadata/links.xml'); $loader->load('metadata/property.xml'); $loader->load('metadata/resource.xml'); - $loader->load('v3/metadata.xml'); $container->getDefinition('api_platform.metadata.resource_extractor.xml')->replaceArgument(0, $xmlResources); $container->getDefinition('api_platform.metadata.property_extractor.xml')->replaceArgument(0, $xmlResources); @@ -492,22 +398,9 @@ private function registerSwaggerConfiguration(ContainerBuilder $container, array } $container->setParameter('api_platform.swagger_ui.extra_configuration', $config['openapi']['swagger_ui_extra_configuration'] ?: $config['swagger']['swagger_ui_extra_configuration']); - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/swagger.xml'); - $loader->load('legacy/openapi.xml'); - $loader->load('legacy/swagger_ui.xml'); - - if (true === $config['openapi']['backward_compatibility_layer']) { - $container->getDefinition('api_platform.swagger.normalizer.documentation')->addArgument($container->getDefinition('api_platform.openapi.normalizer')); - } - - return; - } - // for swagger 2 support - $loader->load('legacy/swagger.xml'); - $loader->load('v3/openapi.xml'); - $loader->load('v3/swagger_ui.xml'); + $loader->load('openapi.xml'); + $loader->load('swagger_ui.xml'); } private function registerJsonApiConfiguration(array $formats, XmlFileLoader $loader): void @@ -585,12 +478,6 @@ private function registerGraphQlConfiguration(ContainerBuilder $container, array $loader->load('graphql.xml'); - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/graphql.xml'); - } else { - $loader->load('v3/graphql.xml'); - } - $container->registerForAutoconfiguration(QueryItemResolverInterface::class) ->addTag('api_platform.graphql.query_resolver'); $container->registerForAutoconfiguration(QueryCollectionResolverInterface::class) @@ -603,51 +490,11 @@ private function registerGraphQlConfiguration(ContainerBuilder $container, array ->addTag('api_platform.graphql.error_handler'); } - private function registerLegacyBundlesConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void - { - /** @var string[] $bundles */ - $bundles = $container->getParameter('kernel.bundles'); - - if (isset($bundles['FOSUserBundle']) && $config['enable_fos_user']) { - $loader->load('fos_user.xml'); - } - - if (isset($bundles['NelmioApiDocBundle']) && $config['enable_nelmio_api_doc']) { - $loader->load('nelmio_api_doc.xml'); - - $container->getDefinition('api_platform.nelmio_api_doc.annotations_provider') - ->setDeprecated(...$this->buildDeprecationArgs('2.2', 'The "%service_id%" service is deprecated since API Platform 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.')); - $container->getDefinition('api_platform.nelmio_api_doc.parser') - ->setDeprecated(...$this->buildDeprecationArgs('2.2', 'The "%service_id%" service is deprecated since API Platform 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.')); - } - } - private function registerCacheConfiguration(ContainerBuilder $container): void { if (!$container->hasParameter('kernel.debug') || !$container->getParameter('kernel.debug')) { $container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer'); } - - if (!$container->hasParameter('api_platform.metadata_cache')) { - return; - } - - @trigger_error('The "api_platform.metadata_cache" parameter is deprecated since version 2.4 and will have no effect in 3.0.', \E_USER_DEPRECATED); - - // BC - if (!$container->getParameter('api_platform.metadata_cache')) { - $container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer'); - - $container->register('api_platform.cache.metadata.property', ArrayAdapter::class); - $container->register('api_platform.cache.metadata.property.legacy', ArrayAdapter::class); - $container->register('api_platform.cache.metadata.resource', ArrayAdapter::class); - $container->register('api_platform.cache.metadata.resource.legacy', ArrayAdapter::class); - $container->register('api_platform.cache.metadata.resource_collection', ArrayAdapter::class); - $container->register('api_platform.cache.route_name_resolver', ArrayAdapter::class); - $container->register('api_platform.cache.identifiers_extractor', ArrayAdapter::class); - $container->register('api_platform.cache.subresource_operation_factory', ArrayAdapter::class); - $container->register('api_platform.elasticsearch.cache.metadata.document', ArrayAdapter::class); - } } private function registerDoctrineOrmConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -664,11 +511,6 @@ private function registerDoctrineOrmConfiguration(ContainerBuilder $container, a ->setBindings(['$requestStack' => null]); $loader->load('doctrine_orm.xml'); - $loader->load('legacy/doctrine_orm.xml'); - - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('v3/doctrine_orm.xml'); - } if ($this->isConfigEnabled($container, $config['eager_loading'])) { return; @@ -694,11 +536,6 @@ private function registerDoctrineMongoDbOdmConfiguration(ContainerBuilder $conta ->setBindings(['$managerRegistry' => new Reference('doctrine_mongodb')]); $loader->load('doctrine_mongodb_odm.xml'); - $loader->load('legacy/doctrine_odm.xml'); - - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('v3/doctrine_odm.xml'); - } } private function registerHttpCacheConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -752,12 +589,8 @@ private function getFormats(array $configFormats): array private function registerValidatorConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void { if (interface_exists(ValidatorInterface::class)) { - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/validator.xml'); - } else { - $loader->load('metadata/validator.xml'); - $loader->load('symfony/validator.xml'); - } + $loader->load('metadata/validator.xml'); + $loader->load('symfony/validator.xml'); $container->registerForAutoconfiguration(ValidationGroupsGeneratorInterface::class) ->addTag('api_platform.validation_groups_generator') @@ -785,20 +618,10 @@ private function registerDataCollectorConfiguration(ContainerBuilder $container, return; } - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/data_collector.xml'); - } else { - $loader->load('v3/data_collector.xml'); - } + $loader->load('data_collector.xml'); if ($container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) { $loader->load('debug.xml'); - - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/debug.xml'); - } else { - $loader->load('v3/debug.xml'); - } } } @@ -814,43 +637,27 @@ private function registerMercureConfiguration(ContainerBuilder $container, array } if ($this->isConfigEnabled($container, $config['doctrine'])) { - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/doctrine_orm_mercure_publisher.xml'); - } else { - $loader->load('v3/doctrine_orm_mercure_publisher.xml'); - } + $loader->load('doctrine_orm_mercure_publisher.xml'); if (class_exists(HubRegistry::class)) { $container->getDefinition('api_platform.doctrine.orm.listener.mercure.publish')->setArgument(6, new Reference(HubRegistry::class)); } } if ($this->isConfigEnabled($container, $config['doctrine_mongodb_odm'])) { - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/doctrine_odm_mercure_publisher.xml'); - } else { - $loader->load('v3/doctrine_odm_mercure_publisher.xml'); - } + $loader->load('doctrine_odm_mercure_publisher.xml'); if (class_exists(HubRegistry::class)) { $container->getDefinition('api_platform.doctrine_mongodb.odm.listener.mercure.publish')->setArgument(6, new Reference(HubRegistry::class)); } } if ($this->isConfigEnabled($container, $config['graphql'])) { - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/graphql_mercure.xml'); - } else { - $loader->load('v3/graphql_mercure.xml'); - } + $loader->load('graphql_mercure.xml'); if (class_exists(HubRegistry::class)) { $container->getDefinition('api_platform.graphql.subscription.mercure_iri_generator')->addArgument(new Reference(HubRegistry::class)); } else { $container->getDefinition('api_platform.graphql.subscription.mercure_iri_generator')->addArgument($config['mercure']['hub_url'] ?? '%mercure.default_hub%'); } } - - if ($config['metadata_backward_compatibility_layer']) { - $container->getDefinition('api_platform.mercure.listener.response.add_link_header')->setArgument(0, new Reference('api_platform.metadata.resource.metadata_factory')); - } } private function registerMessengerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -860,10 +667,6 @@ private function registerMessengerConfiguration(ContainerBuilder $container, arr } $loader->load('messenger.xml'); - - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('v3/messenger.xml'); - } } private function registerElasticsearchConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -878,10 +681,6 @@ private function registerElasticsearchConfiguration(ContainerBuilder $container, $loader->load('elasticsearch.xml'); - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('v3/elasticsearch.xml'); - } - $container->registerForAutoconfiguration(RequestBodySearchCollectionExtensionInterface::class) ->addTag('api_platform.elasticsearch.request_body_search_extension.collection'); @@ -908,10 +707,6 @@ private function registerSecurityConfiguration(ContainerBuilder $container, XmlF } $loader->load('security.xml'); - - if ($config['metadata_backward_compatibility_layer']) { - $container->getDefinition('api_platform.security.listener.request.deny_access')->setArgument(0, new Reference('api_platform.metadata.resource.metadata_factory')); - } } private function registerOpenApiConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void @@ -943,39 +738,6 @@ private function registerMakerConfiguration(ContainerBuilder $container, array $ private function registerArgumentResolverConfiguration(ContainerBuilder $container, XmlFileLoader $loader, array $config): void { - if ($config['metadata_backward_compatibility_layer']) { - return; - } - $loader->load('argument_resolver.xml'); } - - private function registerLegacyServices(ContainerBuilder $container, array $config, XmlFileLoader $loader): void - { - $container->setParameter('api_platform.metadata_backward_compatibility_layer', $config['metadata_backward_compatibility_layer']); - - $loader->load('legacy/identifiers.xml'); - - if (!$config['metadata_backward_compatibility_layer']) { - $loader->load('symfony.xml'); - - return; - } - - $loader->load('legacy/api.xml'); - } - - private function registerUpgradeCommandConfiguration(ContainerBuilder $container, XmlFileLoader $loader, array $config): void - { - $loader->load('legacy/upgrade.xml'); - } - - private function buildDeprecationArgs(string $version, string $message): array - { - return method_exists(Definition::class, 'getDeprecation') - ? ['api-platform/core', $version, $message] - : [true, $message]; - } } - -class_alias(ApiPlatformExtension::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php index 16e0669fa14..8f072fb4f21 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php @@ -100,5 +100,3 @@ private function createFilterDefinitions(\ReflectionClass $resourceReflectionCla } } } - -class_alias(AnnotationFilterPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php index bf18c829ecf..772d370c794 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php @@ -35,5 +35,3 @@ public function process(ContainerBuilder $container): void } } } - -class_alias(AuthenticatorManagerPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php index 05e93aa07a5..f1be702b296 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\DataProvider\SerializerAwareDataProviderInterface; use ApiPlatform\State\SerializerAwareProviderInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -35,10 +33,6 @@ final class DataProviderPass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { - foreach (OperationType::TYPES as $type) { - $this->addSerializerLocator($container, $type); - } - $services = $container->findTaggedServiceIds('api_platform.state_provider', true); foreach ($services as $id => $tags) { @@ -48,18 +42,4 @@ public function process(ContainerBuilder $container) } } } - - private function addSerializerLocator(ContainerBuilder $container, string $type): void - { - $services = $container->findTaggedServiceIds("api_platform.{$type}_data_provider", true); - - foreach ($services as $id => $tags) { - $definition = $container->getDefinition((string) $id); - if (is_a($definition->getClass(), SerializerAwareDataProviderInterface::class, true)) { - $definition->addMethodCall('setSerializerLocator', [new Reference('api_platform.serializer_locator')]); - } - } - } } - -class_alias(DataProviderPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php index b2e426b2f23..afa28c12a42 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php @@ -39,5 +39,3 @@ private function buildDeprecationArgs(string $version, string $message): array : [$message]; } } - -class_alias(DeprecateMercurePublisherPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php index 22cb662bf4e..0d99dd7468c 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php @@ -55,5 +55,3 @@ public function process(ContainerBuilder $container) } } } - -class_alias(ElasticsearchClientPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php index b77616418e0..2897b0c4e30 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php @@ -49,5 +49,3 @@ public function process(ContainerBuilder $container) $container->getDefinition('api_platform.filter_collection_factory')->addArgument(array_keys($filters)); } } - -class_alias(FilterPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\FilterPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php index 2cbcbba15bf..cb032239ece 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php @@ -45,5 +45,3 @@ public function process(ContainerBuilder $container) $container->getDefinition('api_platform.graphql.mutation_resolver_locator')->addArgument($mutations); } } - -class_alias(GraphQlMutationResolverPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php index bc00d4aaabf..882a3510317 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php @@ -45,5 +45,3 @@ public function process(ContainerBuilder $container) $container->getDefinition('api_platform.graphql.query_resolver_locator')->addArgument($resolvers); } } - -class_alias(GraphQlQueryResolverPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php index ada87331f64..3c412b33123 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php @@ -46,5 +46,3 @@ public function process(ContainerBuilder $container) $container->getDefinition('api_platform.graphql.types_factory')->addArgument(array_keys($types)); } } - -class_alias(GraphQlTypePass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php index 42454ff26dd..aee2cbf109d 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php @@ -53,5 +53,3 @@ public function process(ContainerBuilder $container) $container->setAlias('api_platform.name_converter', 'serializer.name_converter.metadata_aware'); } } - -class_alias(MetadataAwareNameConverterPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php index da6d9593436..c2812085e03 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php @@ -41,5 +41,3 @@ public function process(ContainerBuilder $container) ); } } - -class_alias(TestClientPass::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass::class); diff --git a/src/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/DependencyInjection/Configuration.php index a8595ce6a91..26d0f402d33 100644 --- a/src/Symfony/Bundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/DependencyInjection/Configuration.php @@ -678,4 +678,3 @@ private function buildDeprecationArgs(string $version, string $message): array } } -class_alias(Configuration::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Configuration::class); diff --git a/src/Symfony/Bundle/EventListener/SwaggerUiListener.php b/src/Symfony/Bundle/EventListener/SwaggerUiListener.php index 09020c02486..65d58468fb9 100644 --- a/src/Symfony/Bundle/EventListener/SwaggerUiListener.php +++ b/src/Symfony/Bundle/EventListener/SwaggerUiListener.php @@ -33,5 +33,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_controller', 'api_platform.swagger.action.ui'); } } - -class_alias(SwaggerUiListener::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener::class); diff --git a/src/Symfony/Bundle/Resources/config/api.xml b/src/Symfony/Bundle/Resources/config/api.xml index 77ceaa9df87..def9586dbe3 100644 --- a/src/Symfony/Bundle/Resources/config/api.xml +++ b/src/Symfony/Bundle/Resources/config/api.xml @@ -80,16 +80,6 @@ - - - - - - - - - - @@ -131,5 +121,60 @@ + + + + + + + %api_platform.formats% + %api_platform.resource_class_directories% + %api_platform.graphql.enabled% + %api_platform.enable_entrypoint% + %api_platform.enable_docs% + %api_platform.graphql.graphiql.enabled% + %api_platform.graphql.graphql_playground.enabled% + null + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + null + + diff --git a/src/Symfony/Bundle/Resources/config/v3/data_collector.xml b/src/Symfony/Bundle/Resources/config/data_collector.xml similarity index 75% rename from src/Symfony/Bundle/Resources/config/v3/data_collector.xml rename to src/Symfony/Bundle/Resources/config/data_collector.xml index b4456561b1e..689561d3f41 100644 --- a/src/Symfony/Bundle/Resources/config/v3/data_collector.xml +++ b/src/Symfony/Bundle/Resources/config/data_collector.xml @@ -8,10 +8,6 @@ - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/debug.xml b/src/Symfony/Bundle/Resources/config/debug.xml index d8becbdbb92..df1ad13979e 100644 --- a/src/Symfony/Bundle/Resources/config/debug.xml +++ b/src/Symfony/Bundle/Resources/config/debug.xml @@ -8,5 +8,12 @@ + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml b/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml index e06c5094b55..6ce17d97ba9 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml @@ -108,6 +108,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_odm_mercure_publisher.xml b/src/Symfony/Bundle/Resources/config/doctrine_odm_mercure_publisher.xml similarity index 100% rename from src/Symfony/Bundle/Resources/config/v3/doctrine_odm_mercure_publisher.xml rename to src/Symfony/Bundle/Resources/config/doctrine_odm_mercure_publisher.xml diff --git a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml index 3b783508aa8..ed332e74fa1 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml @@ -128,6 +128,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + null + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_orm_mercure_publisher.xml b/src/Symfony/Bundle/Resources/config/doctrine_orm_mercure_publisher.xml similarity index 100% rename from src/Symfony/Bundle/Resources/config/v3/doctrine_orm_mercure_publisher.xml rename to src/Symfony/Bundle/Resources/config/doctrine_orm_mercure_publisher.xml diff --git a/src/Symfony/Bundle/Resources/config/elasticsearch.xml b/src/Symfony/Bundle/Resources/config/elasticsearch.xml index 910d80ea5ff..c74b5231aed 100644 --- a/src/Symfony/Bundle/Resources/config/elasticsearch.xml +++ b/src/Symfony/Bundle/Resources/config/elasticsearch.xml @@ -134,6 +134,30 @@ %api_platform.collection.order_parameter_name% + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/fos_user.xml b/src/Symfony/Bundle/Resources/config/fos_user.xml deleted file mode 100644 index 30c0141e64a..00000000000 --- a/src/Symfony/Bundle/Resources/config/fos_user.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/graphql.xml b/src/Symfony/Bundle/Resources/config/graphql.xml index e4781353ebf..05e0f868368 100644 --- a/src/Symfony/Bundle/Resources/config/graphql.xml +++ b/src/Symfony/Bundle/Resources/config/graphql.xml @@ -91,6 +91,195 @@ + + + + + + + + + + %api_platform.graphql.nesting_separator% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %api_platform.graphql.nesting_separator% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %api_platform.allow_plain_identifiers% + null + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %api_platform.exception_to_status% + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/legacy/README b/src/Symfony/Bundle/Resources/config/legacy/README deleted file mode 100644 index b90488053fa..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/README +++ /dev/null @@ -1 +0,0 @@ -The `legacy` directory declares API Platform 2.x services. This directory will be removed in 3.0 but kept in 2.7. diff --git a/src/Symfony/Bundle/Resources/config/legacy/api.xml b/src/Symfony/Bundle/Resources/config/legacy/api.xml deleted file mode 100644 index cceb903baa5..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/api.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - - - - %api_platform.formats% - %api_platform.resource_class_directories% - - %api_platform.graphql.enabled% - %api_platform.enable_entrypoint% - %api_platform.enable_docs% - %api_platform.graphql.graphiql.enabled% - %api_platform.graphql.graphql_playground.enabled% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - %api_platform.error_formats% - %api_platform.exception_to_status% - - - - - - api_platform.action.exception - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/backward_compatibility.xml b/src/Symfony/Bundle/Resources/config/legacy/backward_compatibility.xml deleted file mode 100644 index 00562814160..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/backward_compatibility.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/data_collector.xml b/src/Symfony/Bundle/Resources/config/legacy/data_collector.xml deleted file mode 100644 index 3e484801f45..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/data_collector.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/data_provider.xml b/src/Symfony/Bundle/Resources/config/legacy/data_provider.xml deleted file mode 100644 index 78458553729..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/data_provider.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - %api_platform.collection.pagination% - %api_platform.graphql.collection.pagination% - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/debug.xml b/src/Symfony/Bundle/Resources/config/legacy/debug.xml deleted file mode 100644 index 65045e79405..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/debug.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm.xml b/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm.xml deleted file mode 100644 index 430f5d7974f..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm_mercure_publisher.xml b/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm_mercure_publisher.xml deleted file mode 100644 index 8d7c9672b12..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/doctrine_odm_mercure_publisher.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm.xml deleted file mode 100644 index 0b135d72ad3..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm_mercure_publisher.xml b/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm_mercure_publisher.xml deleted file mode 100644 index fbd3d138618..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/doctrine_orm_mercure_publisher.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/graphql.xml b/src/Symfony/Bundle/Resources/config/legacy/graphql.xml deleted file mode 100644 index 4403fc2f7d8..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/graphql.xml +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.graphql.nesting_separator% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.graphql.nesting_separator% - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.debug% - %api_platform.graphql.graphiql.enabled% - %api_platform.graphql.graphql_playground.enabled% - %api_platform.graphql.default_ide% - - - - - - %api_platform.graphql.graphiql.enabled% - %api_platform.title% - %api_platform.asset_package% - - - - - - %api_platform.graphql.graphql_playground.enabled% - %api_platform.title% - %api_platform.asset_package% - - - - - - - - - - - - - - - %api_platform.allow_plain_identifiers% - null - - - - - - - - - - - - - - - - - - - - - - %api_platform.exception_to_status% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/graphql_mercure.xml b/src/Symfony/Bundle/Resources/config/legacy/graphql_mercure.xml deleted file mode 100644 index cc7249aed7a..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/graphql_mercure.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/identifiers.xml b/src/Symfony/Bundle/Resources/config/legacy/identifiers.xml deleted file mode 100644 index 80eed2426af..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/identifiers.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - %api_platform.metadata_backward_compatibility_layer% - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata.xml deleted file mode 100644 index 94f4449f4d0..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - %api_platform.patch_formats% - - - - - %api_platform.formats% - %api_platform.patch_formats% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_annotation.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_annotation.xml deleted file mode 100644 index 880407eaf77..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_annotation.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - %api_platform.resource_class_directories% - - - - - - - %api_platform.defaults% - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_backward_compatibility.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_backward_compatibility.xml deleted file mode 100644 index 36c90c2c795..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_backward_compatibility.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_php_doc.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_php_doc.xml deleted file mode 100644 index 5865e92dd93..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_php_doc.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml.xml deleted file mode 100644 index cfb76ecbe08..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - %api_platform.defaults% - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml_backward_compatibility.xml b/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml_backward_compatibility.xml deleted file mode 100644 index 0dd363e5cfe..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/metadata_yaml_backward_compatibility.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/openapi.xml b/src/Symfony/Bundle/Resources/config/legacy/openapi.xml deleted file mode 100644 index 68b0df9f725..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/openapi.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - %api_platform.formats% - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/swagger.xml b/src/Symfony/Bundle/Resources/config/legacy/swagger.xml deleted file mode 100644 index 3bd9b39e36d..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/swagger.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - null - - null - %api_platform.oauth.enabled% - %api_platform.oauth.type% - %api_platform.oauth.flow% - %api_platform.oauth.tokenUrl% - %api_platform.oauth.authorizationUrl% - %api_platform.oauth.scopes% - %api_platform.swagger.api_keys% - - %api_platform.collection.pagination.enabled% - %api_platform.collection.pagination.page_parameter_name% - %api_platform.collection.pagination.client_items_per_page% - %api_platform.collection.pagination.items_per_page_parameter_name% - %api_platform.formats% - %api_platform.collection.pagination.client_enabled% - %api_platform.collection.pagination.enabled_parameter_name% - - %api_platform.swagger.versions% - - null - %api_platform.metadata_backward_compatibility_layer% - - - - - - - - - - - - %api_platform.title% - %api_platform.description% - %api_platform.version% - null - %api_platform.swagger.versions% - %api_platform.metadata_backward_compatibility_layer% - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/swagger_ui.xml b/src/Symfony/Bundle/Resources/config/legacy/swagger_ui.xml deleted file mode 100644 index c9739cc0f4c..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/swagger_ui.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - %api_platform.formats% - %api_platform.oauth.clientId% - %api_platform.oauth.clientSecret% - %api_platform.oauth.pkce% - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/upgrade.xml b/src/Symfony/Bundle/Resources/config/legacy/upgrade.xml deleted file mode 100644 index 33f0b6094fb..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/upgrade.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/validator.xml b/src/Symfony/Bundle/Resources/config/legacy/validator.xml deleted file mode 100644 index 9cf8d42f5e2..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/validator.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.validator.query_parameter_validation% - - - - - diff --git a/src/Symfony/Bundle/Resources/config/maker.xml b/src/Symfony/Bundle/Resources/config/maker.xml index f829cf3af09..5b6be1706b0 100644 --- a/src/Symfony/Bundle/Resources/config/maker.xml +++ b/src/Symfony/Bundle/Resources/config/maker.xml @@ -5,15 +5,15 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - - - - - - - - + + + + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/messenger.xml b/src/Symfony/Bundle/Resources/config/messenger.xml index 69eacad40db..8e80e617450 100644 --- a/src/Symfony/Bundle/Resources/config/messenger.xml +++ b/src/Symfony/Bundle/Resources/config/messenger.xml @@ -7,11 +7,8 @@ - - - - - + + @@ -20,11 +17,6 @@ - - - - - diff --git a/src/Symfony/Bundle/Resources/config/metadata/property.xml b/src/Symfony/Bundle/Resources/config/metadata/property.xml index 82fe8b3c984..05498db2f5f 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/property.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/property.xml @@ -5,6 +5,8 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + @@ -52,11 +54,6 @@ - - - - - diff --git a/src/Symfony/Bundle/Resources/config/metadata/resource_name.xml b/src/Symfony/Bundle/Resources/config/metadata/resource_name.xml index 2613336d50d..df4e7f3a425 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/resource_name.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/resource_name.xml @@ -23,5 +23,9 @@ + + %api_platform.resource_class_directories% + + diff --git a/src/Symfony/Bundle/Resources/config/nelmio_api_doc.xml b/src/Symfony/Bundle/Resources/config/nelmio_api_doc.xml deleted file mode 100644 index 9bfd8a8f6d6..00000000000 --- a/src/Symfony/Bundle/Resources/config/nelmio_api_doc.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/openapi.xml b/src/Symfony/Bundle/Resources/config/openapi.xml index b35d80da872..c54481d2095 100644 --- a/src/Symfony/Bundle/Resources/config/openapi.xml +++ b/src/Symfony/Bundle/Resources/config/openapi.xml @@ -61,6 +61,22 @@ + + + + + + + + + + %api_platform.formats% + + + + + + diff --git a/src/Symfony/Bundle/Resources/config/data_provider.xml b/src/Symfony/Bundle/Resources/config/state.xml similarity index 61% rename from src/Symfony/Bundle/Resources/config/data_provider.xml rename to src/Symfony/Bundle/Resources/config/state.xml index edbe31d3d2e..b18400712f7 100644 --- a/src/Symfony/Bundle/Resources/config/data_provider.xml +++ b/src/Symfony/Bundle/Resources/config/state.xml @@ -3,15 +3,31 @@ - + + + + + + + + %api_platform.collection.pagination% + %api_platform.graphql.collection.pagination% + + + + + + + + + - %api_platform.collection.pagination.enabled% %api_platform.collection.pagination.page_parameter_name% @@ -27,5 +43,4 @@ - diff --git a/src/Symfony/Bundle/Resources/config/swagger_ui.xml b/src/Symfony/Bundle/Resources/config/swagger_ui.xml index dd7c83de602..e60682f7fef 100644 --- a/src/Symfony/Bundle/Resources/config/swagger_ui.xml +++ b/src/Symfony/Bundle/Resources/config/swagger_ui.xml @@ -19,34 +19,17 @@ %api_platform.swagger_ui.extra_configuration% - - - - + + - %api_platform.title% - %api_platform.description% - %api_platform.version% + + + + %api_platform.formats% - %api_platform.oauth.enabled% %api_platform.oauth.clientId% %api_platform.oauth.clientSecret% - %api_platform.oauth.type% - %api_platform.oauth.flow% - %api_platform.oauth.tokenUrl% - %api_platform.oauth.authorizationUrl% - %api_platform.oauth.scopes% - %api_platform.show_webby% - %api_platform.enable_swagger_ui% - %api_platform.enable_re_doc% - %api_platform.graphql.enabled% - %api_platform.graphql.graphiql.enabled% - %api_platform.graphql.graphql_playground.enabled% - %api_platform.swagger.versions% - - %api_platform.asset_package% - %api_platform.swagger_ui.extra_configuration% %api_platform.oauth.pkce% diff --git a/src/Symfony/Bundle/Resources/config/symfony.xml b/src/Symfony/Bundle/Resources/config/symfony/events.xml similarity index 100% rename from src/Symfony/Bundle/Resources/config/symfony.xml rename to src/Symfony/Bundle/Resources/config/symfony/events.xml diff --git a/src/Symfony/Bundle/Resources/config/symfony_uid.xml b/src/Symfony/Bundle/Resources/config/symfony/uid.xml similarity index 100% rename from src/Symfony/Bundle/Resources/config/symfony_uid.xml rename to src/Symfony/Bundle/Resources/config/symfony/uid.xml diff --git a/src/Symfony/Bundle/Resources/config/v3/api.xml b/src/Symfony/Bundle/Resources/config/v3/api.xml deleted file mode 100644 index 630eb93e364..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/api.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - %api_platform.formats% - %api_platform.resource_class_directories% - null - %api_platform.graphql.enabled% - %api_platform.enable_entrypoint% - %api_platform.enable_docs% - %api_platform.graphql.graphiql.enabled% - %api_platform.graphql.graphql_playground.enabled% - null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/backward_compatibility.xml b/src/Symfony/Bundle/Resources/config/v3/backward_compatibility.xml deleted file mode 100644 index c242414a4aa..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/backward_compatibility.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - %api_platform.defaults% - - - - - - - - - - - - - - - - - - - - %api_platform.metadata_backward_compatibility_layer% - - - - - - - - - - - - null - %api_platform.metadata_backward_compatibility_layer% - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/debug.xml b/src/Symfony/Bundle/Resources/config/v3/debug.xml deleted file mode 100644 index 412f179d7d8..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/debug.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml b/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml deleted file mode 100644 index 7870a67a3da..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/doctrine_odm.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml deleted file mode 100644 index e3d8c6da9a3..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/doctrine_orm.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/elasticsearch.xml b/src/Symfony/Bundle/Resources/config/v3/elasticsearch.xml deleted file mode 100644 index c04b5eaa882..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/elasticsearch.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/graphql.xml b/src/Symfony/Bundle/Resources/config/v3/graphql.xml deleted file mode 100644 index 180cba84b0e..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/graphql.xml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - %api_platform.graphql.nesting_separator% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.graphql.nesting_separator% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.allow_plain_identifiers% - null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %api_platform.exception_to_status% - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/graphql_mercure.xml b/src/Symfony/Bundle/Resources/config/v3/graphql_mercure.xml deleted file mode 100644 index f682291900e..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/graphql_mercure.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/messenger.xml b/src/Symfony/Bundle/Resources/config/v3/messenger.xml deleted file mode 100644 index de581cca87e..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/messenger.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/metadata.xml b/src/Symfony/Bundle/Resources/config/v3/metadata.xml deleted file mode 100644 index 76885ef83ea..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/metadata.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - %api_platform.resource_class_directories% - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/openapi.xml b/src/Symfony/Bundle/Resources/config/v3/openapi.xml deleted file mode 100644 index 819742bf4d8..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/openapi.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - %api_platform.formats% - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/state.xml b/src/Symfony/Bundle/Resources/config/v3/state.xml deleted file mode 100644 index 9004bdd9d5d..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/state.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - %api_platform.collection.pagination% - %api_platform.graphql.collection.pagination% - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml b/src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml deleted file mode 100644 index 228cf725bdc..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/swagger_ui.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - %api_platform.formats% - %api_platform.oauth.clientId% - %api_platform.oauth.clientSecret% - %api_platform.oauth.pkce% - - - diff --git a/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php b/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php index ca84d92ee1a..0a87bb126fa 100644 --- a/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php +++ b/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php @@ -135,5 +135,3 @@ private function getPathAndMethod(array $swaggerData): array throw new RuntimeException(sprintf('The operation "%s" cannot be found in the Swagger specification.', $swaggerData['operationId'])); } } - -class_alias(SwaggerUiAction::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiAction::class); diff --git a/src/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php b/src/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php index 5b113ed8b22..f8e4cd347af 100644 --- a/src/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php +++ b/src/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php @@ -76,5 +76,3 @@ public function getExtraConfiguration(): array return $this->extraConfiguration; } } - -class_alias(SwaggerUiContext::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiContext::class); diff --git a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php b/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php index c141c828617..dc7150c2067 100644 --- a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php +++ b/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php @@ -182,5 +182,3 @@ private static function getSchemaFactory() return $schemaFactory; } } - -class_alias(ApiTestAssertionsTrait::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestAssertionsTrait::class); diff --git a/src/Symfony/Bundle/Test/ApiTestCase.php b/src/Symfony/Bundle/Test/ApiTestCase.php index 94b121f285e..ae251ecdc13 100644 --- a/src/Symfony/Bundle/Test/ApiTestCase.php +++ b/src/Symfony/Bundle/Test/ApiTestCase.php @@ -105,5 +105,3 @@ protected function findIriBy(string $resourceClass, array $criteria): ?string return $iriConverter instanceof LegacyIriConverterInterface ? $iriConverter->getIriFromItem($item) : $iriConverter->getIriFromResource($item); } } - -class_alias(ApiTestCase::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase::class); diff --git a/src/Symfony/Bundle/Test/Client.php b/src/Symfony/Bundle/Test/Client.php index f7b45308104..aaae8e5c3f3 100644 --- a/src/Symfony/Bundle/Test/Client.php +++ b/src/Symfony/Bundle/Test/Client.php @@ -256,5 +256,3 @@ public function loginUser(UserInterface $user, string $firewallContext = 'main') return $this; } } - -class_alias(Client::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client::class); diff --git a/src/Symfony/Bundle/Test/Constraint/ArraySubset.php b/src/Symfony/Bundle/Test/Constraint/ArraySubset.php index 1eae632d5d6..758e4063b58 100644 --- a/src/Symfony/Bundle/Test/Constraint/ArraySubset.php +++ b/src/Symfony/Bundle/Test/Constraint/ArraySubset.php @@ -18,12 +18,8 @@ use SebastianBergmann\Comparator\ComparisonFailure as LegacyComparisonFailure; if (!class_exists(ComparisonFailure::class) && class_exists(LegacyComparisonFailure::class)) { - class_alias(LegacyComparisonFailure::class, 'PHPUnit\SebastianBergmann\Comparator\ComparisonFailure'); } // Aliases as string to avoid loading the class if (\PHP_VERSION_ID >= 80000 || (float) Version::series() >= 9) { - class_alias('ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubsetV9', 'ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubset'); -} else { - class_alias('ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubsetLegacy', 'ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubset'); } diff --git a/src/Symfony/Bundle/Test/Response.php b/src/Symfony/Bundle/Test/Response.php index e96ee96c100..4f06632ce64 100644 --- a/src/Symfony/Bundle/Test/Response.php +++ b/src/Symfony/Bundle/Test/Response.php @@ -180,5 +180,3 @@ public function cancel(): void $this->info['error'] = 'Response has been canceled.'; } } - -class_alias(Response::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Response::class); diff --git a/src/Symfony/EventListener/AddFormatListener.php b/src/Symfony/EventListener/AddFormatListener.php index b85c1f1cf29..f4896f59b03 100644 --- a/src/Symfony/EventListener/AddFormatListener.php +++ b/src/Symfony/EventListener/AddFormatListener.php @@ -188,5 +188,3 @@ private function getNotAcceptableHttpException(string $accept, array $mimeTypes) )); } } - -class_alias(AddFormatListener::class, \ApiPlatform\Core\EventListener\AddFormatListener::class); diff --git a/src/Symfony/EventListener/AddLinkHeaderListener.php b/src/Symfony/EventListener/AddLinkHeaderListener.php index 88f16c383ed..18b8ce1ed8c 100644 --- a/src/Symfony/EventListener/AddLinkHeaderListener.php +++ b/src/Symfony/EventListener/AddLinkHeaderListener.php @@ -104,5 +104,3 @@ public function onKernelResponse(ResponseEvent $event): void $this->discovery->addLink($request, $hub); } } - -class_alias(AddLinkHeaderListener::class, \ApiPlatform\Core\Mercure\EventListener\AddLinkHeaderListener::class); diff --git a/src/Symfony/EventListener/DenyAccessListener.php b/src/Symfony/EventListener/DenyAccessListener.php index 9852c172947..e40ca7cd4dc 100644 --- a/src/Symfony/EventListener/DenyAccessListener.php +++ b/src/Symfony/EventListener/DenyAccessListener.php @@ -155,5 +155,3 @@ private function checkSecurity(Request $request, string $attribute, bool $backwa } } } - -class_alias(DenyAccessListener::class, \ApiPlatform\Core\Security\EventListener\DenyAccessListener::class); diff --git a/src/Symfony/EventListener/DeserializeListener.php b/src/Symfony/EventListener/DeserializeListener.php index ab29409842e..44049bf7c3e 100644 --- a/src/Symfony/EventListener/DeserializeListener.php +++ b/src/Symfony/EventListener/DeserializeListener.php @@ -14,9 +14,6 @@ namespace ApiPlatform\Symfony\EventListener; use ApiPlatform\Api\FormatMatcher; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; @@ -35,44 +32,17 @@ final class DeserializeListener { use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; public const OPERATION_ATTRIBUTE_KEY = 'deserialize'; private $serializer; private $serializerContextBuilder; - private $formats; - private $formatsProvider; - /** - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface|FormatsProviderInterface|array $resourceMetadataFactory - */ - public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, $resourceMetadataFactory) + public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->serializer = $serializer; $this->serializerContextBuilder = $serializerContextBuilder; - - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if ($resourceMetadataFactory) { - if (!$resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - @trigger_error(sprintf('Passing an array or an instance of "%s" as 3rd parameter of the constructor of "%s" is deprecated since API Platform 2.5, pass an instance of "%s" instead', FormatsProviderInterface::class, __CLASS__, ResourceMetadataFactoryInterface::class), \E_USER_DEPRECATED); - } - - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - if ($resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } - } - - if (\is_array($resourceMetadataFactory)) { - $this->formats = $resourceMetadataFactory; - } elseif ($resourceMetadataFactory instanceof FormatsProviderInterface) { - $this->formatsProvider = $resourceMetadataFactory; - } + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; } /** @@ -101,32 +71,9 @@ public function onKernelRequest(RequestEvent $event): void return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && ( - !$attributes['receive'] - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) - )) { - return; - } - $context = $this->serializerContextBuilder->createFromRequest($request, false, $attributes); - $formats = $operation ? $operation->getInputFormats() ?? null : null; - - if (!$formats) { - // BC check to be removed in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - @trigger_error('When using a "route_name", be sure to define the "_api_operation" route defaults as we will not rely on metadata in API Platform 3.0.', \E_USER_DEPRECATED); - $formats = $this->resourceMetadataFactory - ->create($attributes['resource_class']) - ->getOperationAttribute($attributes, 'input_formats', [], true); - } elseif ($this->formatsProvider instanceof FormatsProviderInterface) { - $formats = $this->formatsProvider->getFormatsFromAttributes($attributes); - } else { - $formats = $this->formats; - } - } - - $format = $this->getFormat($request, $formats); + $format = $this->getFormat($request, $operation->getInputFormats() ?? []); $data = $request->attributes->get('data'); if (null !== $data) { $context[AbstractNormalizer::OBJECT_TO_POPULATE] = $data; @@ -169,5 +116,3 @@ private function getFormat(Request $request, array $formats): string return $format; } } - -class_alias(DeserializeListener::class, \ApiPlatform\Core\EventListener\DeserializeListener::class); diff --git a/src/Symfony/EventListener/EventPriorities.php b/src/Symfony/EventListener/EventPriorities.php index 3ec8faa4c65..bfa958a26e7 100644 --- a/src/Symfony/EventListener/EventPriorities.php +++ b/src/Symfony/EventListener/EventPriorities.php @@ -36,5 +36,3 @@ final class EventPriorities // kernel.response public const POST_RESPOND = 0; } - -class_alias(EventPriorities::class, \ApiPlatform\Core\EventListener\EventPriorities::class); diff --git a/src/Symfony/EventListener/ExceptionListener.php b/src/Symfony/EventListener/ExceptionListener.php index 8afdb5b4cea..58e1efb367f 100644 --- a/src/Symfony/EventListener/ExceptionListener.php +++ b/src/Symfony/EventListener/ExceptionListener.php @@ -51,5 +51,3 @@ public function onKernelException(ExceptionEvent $event): void $this->exceptionListener->onKernelException($event); } } - -class_alias(ExceptionListener::class, \ApiPlatform\Core\EventListener\ExceptionListener::class); diff --git a/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php index 58b9e5eeb82..6716d8a49fd 100644 --- a/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php @@ -88,5 +88,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_api_filter_property', $properties); } } - -class_alias(TransformFieldsetsParametersListener::class, \ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener::class); diff --git a/src/Symfony/EventListener/JsonApi/TransformFilteringParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformFilteringParametersListener.php index a683dabde86..18efa74852d 100644 --- a/src/Symfony/EventListener/JsonApi/TransformFilteringParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformFilteringParametersListener.php @@ -41,5 +41,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_api_filters', array_merge($filterParameter, $filters)); } } - -class_alias(TransformFilteringParametersListener::class, \ApiPlatform\Core\JsonApi\EventListener\TransformFilteringParametersListener::class); diff --git a/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php index 0c33f88edbf..ec5cd2fd49f 100644 --- a/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php @@ -43,5 +43,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_api_pagination', $pageParameter); } } - -class_alias(TransformPaginationParametersListener::class, \ApiPlatform\Core\JsonApi\EventListener\TransformPaginationParametersListener::class); diff --git a/src/Symfony/EventListener/JsonApi/TransformSortingParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformSortingParametersListener.php index 70e87d9b0ec..fc732b80107 100644 --- a/src/Symfony/EventListener/JsonApi/TransformSortingParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformSortingParametersListener.php @@ -63,5 +63,3 @@ public function onKernelRequest(RequestEvent $event): void $request->attributes->set('_api_filters', $filters); } } - -class_alias(TransformSortingParametersListener::class, \ApiPlatform\Core\JsonApi\EventListener\TransformSortingParametersListener::class); diff --git a/src/Symfony/EventListener/QueryParameterValidateListener.php b/src/Symfony/EventListener/QueryParameterValidateListener.php index 17c1ec5a4c7..ed6445416fe 100644 --- a/src/Symfony/EventListener/QueryParameterValidateListener.php +++ b/src/Symfony/EventListener/QueryParameterValidateListener.php @@ -14,9 +14,6 @@ namespace ApiPlatform\Symfony\EventListener; use ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator; -use ApiPlatform\Core\Filter\QueryParameterValidator as LegacyQueryParameterValidator; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; @@ -32,7 +29,6 @@ final class QueryParameterValidateListener { use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; public const OPERATION_ATTRIBUTE_KEY = 'query_parameter_validate'; @@ -42,19 +38,9 @@ final class QueryParameterValidateListener private $enabled; - /** - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface $resourceMetadataFactory - * @param QueryParameterValidator|LegacyQueryParameterValidator $queryParameterValidator - */ - public function __construct($resourceMetadataFactory, $queryParameterValidator, bool $enabled = true) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, QueryParameterValidator $queryParameterValidator, bool $enabled = true) { - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } else { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; $this->queryParameterValidator = $queryParameterValidator; $this->enabled = $enabled; } @@ -72,33 +58,12 @@ public function onKernelRequest(RequestEvent $event) return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - (!$operation || !($operation->getQueryParameterValidationEnabled() ?? true) || !$operation instanceof CollectionOperationInterface) - ) { - return; - } - - // TODO: remove in 3.0 - $operationName = $attributes['collection_operation_name'] ?? null; - if (!$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - ( - null === $operationName - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY, !$this->enabled) - ) - ) { + if (!$operation || !($operation->getQueryParameterValidationEnabled() ?? true) || !$operation instanceof CollectionOperationInterface) { return; } $queryString = RequestParser::getQueryString($request); $queryParameters = $queryString ? RequestParser::parseRequestParams($queryString) : []; - $resourceFilters = []; - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceFilters = $this->resourceMetadataFactory->create($attributes['resource_class'])->getCollectionOperationAttribute($operationName, 'filters', [], true); - } elseif ($operation) { - $resourceFilters = $operation->getFilters() ?? []; - } - $this->queryParameterValidator->validateFilters($attributes['resource_class'], $resourceFilters, $queryParameters); + $this->queryParameterValidator->validateFilters($attributes['resource_class'], $operation->getFilters() ?? [], $queryParameters); } } - -class_alias(QueryParameterValidateListener::class, \ApiPlatform\Core\EventListener\QueryParameterValidateListener::class); diff --git a/src/Symfony/EventListener/RespondListener.php b/src/Symfony/EventListener/RespondListener.php index 1dbd7ed09f7..6e8645808d2 100644 --- a/src/Symfony/EventListener/RespondListener.php +++ b/src/Symfony/EventListener/RespondListener.php @@ -156,5 +156,3 @@ private function addAcceptPatchHeader(array $headers, array $attributes, Resourc return $headers; } } - -class_alias(RespondListener::class, \ApiPlatform\Core\EventListener\RespondListener::class); diff --git a/src/Symfony/EventListener/SerializeListener.php b/src/Symfony/EventListener/SerializeListener.php index d9789078711..07fcb569e2f 100644 --- a/src/Symfony/EventListener/SerializeListener.php +++ b/src/Symfony/EventListener/SerializeListener.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\ResourceList; @@ -38,26 +36,17 @@ final class SerializeListener { use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; public const OPERATION_ATTRIBUTE_KEY = 'serialize'; private $serializer; private $serializerContextBuilder; - public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, $resourceMetadataFactory = null) + public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->serializer = $serializer; $this->serializerContextBuilder = $serializerContextBuilder; - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if ($resourceMetadataFactory && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - if ($resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; } /** @@ -75,21 +64,11 @@ public function onKernelView(ViewEvent $event): void $attributes = RequestAttributesExtractor::extractAttributes($request); - // TODO: 3.0 remove condition - if ( - (!$this->resourceMetadataFactory || $this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) - && - ( - !($attributes['respond'] ?? $request->attributes->getBoolean('_api_respond', false)) - || ($attributes && $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY)) - ) - ) { + if (!($attributes['respond'] ?? $request->attributes->getBoolean('_api_respond', false))) { return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - ($operation && !($operation->canSerialize() ?? true)) - ) { + if (!$operation || !($operation->canSerialize() ?? true)) { return; } @@ -154,5 +133,3 @@ private function serializeRawData(ViewEvent $event, Request $request, $controlle $event->setControllerResult($this->serializer->encode($controllerResult, $request->getRequestFormat())); } } - -class_alias(SerializeListener::class, \ApiPlatform\Core\EventListener\SerializeListener::class); diff --git a/src/Symfony/EventListener/ValidateListener.php b/src/Symfony/EventListener/ValidateListener.php index e610814a048..61bfe23f86f 100644 --- a/src/Symfony/EventListener/ValidateListener.php +++ b/src/Symfony/EventListener/ValidateListener.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ToggleableOperationAttributeTrait; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; @@ -31,23 +29,16 @@ final class ValidateListener { use OperationRequestInitiatorTrait; - use ToggleableOperationAttributeTrait; public const OPERATION_ATTRIBUTE_KEY = 'validate'; private $validator; private $resourceMetadataFactory; - public function __construct(ValidatorInterface $validator, $resourceMetadataFactory) + public function __construct(ValidatorInterface $validator, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->validator = $validator; - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } else { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; } /** @@ -70,32 +61,10 @@ public function onKernelView(ViewEvent $event): void return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - (!$operation || !($operation->canValidate() ?? true)) - ) { - return; - } - - // TODO: 3.0 remove condition - if ( - $this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && ( - !$attributes['receive'] - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) - ) - ) { + if (!$operation || !($operation->canValidate() ?? true)) { return; } - $validationContext = $operation ? ($operation->getValidationContext() ?? []) : []; - - if (!$validationContext && $this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - $validationGroups = $resourceMetadata->getOperationAttribute($attributes, 'validation_groups', null, true); - $validationContext = ['groups' => $validationGroups]; - } - - $this->validator->validate($controllerResult, $validationContext); + $this->validator->validate($controllerResult, $operation->getValidationContext() ?? []); } } - -class_alias(ValidateListener::class, \ApiPlatform\Core\Validator\EventListener\ValidateListener::class); diff --git a/src/Symfony/Messenger/ContextStamp.php b/src/Symfony/Messenger/ContextStamp.php index c49268ea9a7..11be14f7ab8 100644 --- a/src/Symfony/Messenger/ContextStamp.php +++ b/src/Symfony/Messenger/ContextStamp.php @@ -39,5 +39,3 @@ public function getContext(): array return $this->context; } } - -class_alias(ContextStamp::class, \ApiPlatform\Core\Bridge\Symfony\Messenger\ContextStamp::class); diff --git a/src/Symfony/Messenger/DispatchTrait.php b/src/Symfony/Messenger/DispatchTrait.php index f60329b8b0e..0502be7a40f 100644 --- a/src/Symfony/Messenger/DispatchTrait.php +++ b/src/Symfony/Messenger/DispatchTrait.php @@ -53,5 +53,3 @@ private function dispatch($message) } } } - -class_alias(DispatchTrait::class, \ApiPlatform\Core\Bridge\Symfony\Messenger\DispatchTrait::class); diff --git a/src/Symfony/Messenger/RemoveStamp.php b/src/Symfony/Messenger/RemoveStamp.php index 4e7f690c428..dc12d1b2166 100644 --- a/src/Symfony/Messenger/RemoveStamp.php +++ b/src/Symfony/Messenger/RemoveStamp.php @@ -25,5 +25,3 @@ final class RemoveStamp implements StampInterface { } - -class_alias(RemoveStamp::class, \ApiPlatform\Core\Bridge\Symfony\Messenger\RemoveStamp::class); diff --git a/src/Symfony/Routing/ApiLoader.php b/src/Symfony/Routing/ApiLoader.php index 5a7459efdd6..ed6fb74d821 100644 --- a/src/Symfony/Routing/ApiLoader.php +++ b/src/Symfony/Routing/ApiLoader.php @@ -13,19 +13,10 @@ namespace ApiPlatform\Symfony\Routing; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Exception\InvalidResourceException; -use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\PathResolver\OperationPathResolverInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Config\Resource\DirectoryResource; @@ -51,11 +42,9 @@ final class ApiLoader extends Loader private $fileLoader; private $resourceNameCollectionFactory; private $resourceMetadataFactory; - private $operationPathResolver; private $container; private $formats; private $resourceClassDirectories; - private $subresourceOperationFactory; private $graphqlEnabled; private $graphiQlEnabled; private $graphQlPlaygroundEnabled; @@ -63,28 +52,21 @@ final class ApiLoader extends Loader private $docsEnabled; private $identifiersExtractor; - public function __construct(KernelInterface $kernel, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, $resourceMetadataFactory, OperationPathResolverInterface $operationPathResolver, ContainerInterface $container, array $formats, array $resourceClassDirectories = [], SubresourceOperationFactoryInterface $subresourceOperationFactory = null, bool $graphqlEnabled = false, bool $entrypointEnabled = true, bool $docsEnabled = true, bool $graphiQlEnabled = false, bool $graphQlPlaygroundEnabled = false, IdentifiersExtractorInterface $identifiersExtractor = null) + public function __construct(KernelInterface $kernel, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ContainerInterface $container, array $formats, array $resourceClassDirectories = [], bool $graphqlEnabled = false, bool $entrypointEnabled = true, bool $docsEnabled = true, bool $graphiQlEnabled = false, bool $graphQlPlaygroundEnabled = false) { /** @var string[]|string $paths */ $paths = $kernel->locateResource('@ApiPlatformBundle/Resources/config/routing'); $this->fileLoader = new XmlFileLoader(new FileLocator($paths)); $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->operationPathResolver = $operationPathResolver; $this->container = $container; $this->formats = $formats; $this->resourceClassDirectories = $resourceClassDirectories; - $this->subresourceOperationFactory = $subresourceOperationFactory; $this->graphqlEnabled = $graphqlEnabled; $this->graphiQlEnabled = $graphiQlEnabled; $this->graphQlPlaygroundEnabled = $graphQlPlaygroundEnabled; $this->entrypointEnabled = $entrypointEnabled; $this->docsEnabled = $docsEnabled; - $this->identifiersExtractor = $identifiersExtractor; } /** @@ -99,42 +81,36 @@ public function load($data, $type = null): RouteCollection $this->loadExternalFiles($routeCollection); foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $this->loadLegacyMetadata($routeCollection, $resourceClass); - $this->loadLegacySubresources($routeCollection, $resourceClass); - continue; - } - foreach ($this->resourceMetadataFactory->create($resourceClass) as $resourceMetadata) { foreach ($resourceMetadata->getOperations() as $operationName => $operation) { if ($operation->getRouteName()) { continue; } - $legacyDefaults = []; - - if ($operation->getExtraProperties()['is_legacy_subresource'] ?? false) { - $legacyDefaults['_api_subresource_operation_name'] = $operationName; - $legacyDefaults['_api_subresource_context'] = [ - 'property' => $operation->getExtraProperties()['legacy_subresource_property'], - 'identifiers' => $operation->getExtraProperties()['legacy_subresource_identifiers'], - 'collection' => $operation instanceof CollectionOperationInterface, - 'operationId' => $operation->getExtraProperties()['legacy_subresource_operation_name'] ?? null, - ]; - $legacyDefaults['_api_identifiers'] = $operation->getExtraProperties()['legacy_subresource_identifiers']; - } elseif ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) { - $legacyDefaults[sprintf('_api_%s_operation_name', $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM)] = $operationName; - $legacyDefaults['_api_identifiers'] = []; - // Legacy identifiers - $hasCompositeIdentifier = false; - foreach ($operation->getUriVariables() ?? [] as $parameterName => $identifiedBy) { - $hasCompositeIdentifier = $identifiedBy->getCompositeIdentifier(); - foreach ($identifiedBy->getIdentifiers() ?? [] as $identifier) { - $legacyDefaults['_api_identifiers'][] = $identifier; - } - } - $legacyDefaults['_api_has_composite_identifier'] = $hasCompositeIdentifier; - } + // $legacyDefaults = []; + + // if ($operation->getExtraProperties()['is_legacy_subresource'] ?? false) { + // $legacyDefaults['_api_subresource_operation_name'] = $operationName; + // $legacyDefaults['_api_subresource_context'] = [ + // 'property' => $operation->getExtraProperties()['legacy_subresource_property'], + // 'identifiers' => $operation->getExtraProperties()['legacy_subresource_identifiers'], + // 'collection' => $operation instanceof CollectionOperationInterface, + // 'operationId' => $operation->getExtraProperties()['legacy_subresource_operation_name'] ?? null, + // ]; + // $legacyDefaults['_api_identifiers'] = $operation->getExtraProperties()['legacy_subresource_identifiers']; + // } elseif ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) { + // $legacyDefaults[sprintf('_api_%s_operation_name', $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM)] = $operationName; + // $legacyDefaults['_api_identifiers'] = []; + // // Legacy identifiers + // $hasCompositeIdentifier = false; + // foreach ($operation->getUriVariables() ?? [] as $parameterName => $identifiedBy) { + // $hasCompositeIdentifier = $identifiedBy->getCompositeIdentifier(); + // foreach ($identifiedBy->getIdentifiers() ?? [] as $identifier) { + // $legacyDefaults['_api_identifiers'][] = $identifier; + // } + // } + // $legacyDefaults['_api_has_composite_identifier'] = $hasCompositeIdentifier; + // } $path = ($operation->getRoutePrefix() ?? '').$operation->getUriTemplate(); foreach ($operation->getUriVariables() ?? [] as $parameterName => $link) { @@ -147,7 +123,7 @@ public function load($data, $type = null): RouteCollection $route = new Route( $path, - $legacyDefaults + [ + [ '_controller' => $operation->getController() ?? 'api_platform.action.placeholder', '_format' => null, '_stateless' => $operation->getStateless(), @@ -213,136 +189,4 @@ private function loadExternalFiles(RouteCollection $routeCollection): void $routeCollection->addCollection($this->fileLoader->load('jsonld.xml')); } } - - /** - * TODO: remove in 3.0. - */ - private function loadLegacyMetadata(RouteCollection $routeCollection, string $resourceClass) - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $resourceShortName = $resourceMetadata->getShortName(); - - if (null === $resourceShortName) { - throw new InvalidResourceException(sprintf('Resource %s has no short name defined.', $resourceClass)); - } - - if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) { - foreach ($collectionOperations as $operationName => $operation) { - $this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceMetadata, OperationType::COLLECTION); - } - } - - if (null !== $itemOperations = $resourceMetadata->getItemOperations()) { - foreach ($itemOperations as $operationName => $operation) { - $this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceMetadata, OperationType::ITEM); - } - } - } - - /** - * TODO: remove in 3.0. - */ - private function loadLegacySubresources(RouteCollection $routeCollection, string $resourceClass) - { - if (null === $this->subresourceOperationFactory) { - return; - } - - foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) { - if (null === $controller = $operation['controller'] ?? null) { - $controller = self::DEFAULT_ACTION_PATTERN.'get_subresource'; - - if (!$this->container->has($controller)) { - throw new RuntimeException(sprintf('There is no builtin action for the %s %s operation. You need to define the controller yourself.', OperationType::SUBRESOURCE, 'GET')); - } - } - - $routeCollection->add($operation['route_name'], new Route( - $operation['path'], - [ - '_controller' => $controller, - '_format' => $operation['defaults']['_format'] ?? null, - '_stateless' => $operation['stateless'] ?? null, - '_api_resource_class' => $operation['resource_class'], - '_api_identifiers' => $operation['identifiers'], - '_api_has_composite_identifier' => false, - '_api_subresource_operation_name' => $operation['route_name'], - '_api_subresource_context' => [ - 'property' => $operation['property'], - 'identifiers' => $operation['identifiers'], - 'collection' => $operation['collection'], - 'operationId' => $operationId, - ], - ] + ($operation['defaults'] ?? []), - $operation['requirements'] ?? [], - $operation['options'] ?? [], - $operation['host'] ?? '', - $operation['schemes'] ?? [], - ['GET'], - $operation['condition'] ?? '' - )); - } - } - - /** - * Creates and adds a route for the given operation to the route collection. - * - * @throws RuntimeException - */ - private function addRoute(RouteCollection $routeCollection, string $resourceClass, string $operationName, array $operation, ResourceMetadata $resourceMetadata, string $operationType): void - { - $resourceShortName = $resourceMetadata->getShortName(); - - if (isset($operation['route_name'])) { - if (!isset($operation['method'])) { - @trigger_error(sprintf('Not setting the "method" attribute is deprecated and will not be supported anymore in API Platform 3.0, set it for the %s operation "%s" of the class "%s".', OperationType::COLLECTION === $operationType ? 'collection' : 'item', $operationName, $resourceClass), \E_USER_DEPRECATED); - } - - return; - } - - if (!isset($operation['method'])) { - throw new RuntimeException(sprintf('Either a "route_name" or a "method" operation attribute must exist for the operation "%s" of the resource "%s".', $operationName, $resourceClass)); - } - - if (null === $controller = $operation['controller'] ?? null) { - $controller = sprintf('%s%s_%s', self::DEFAULT_ACTION_PATTERN, strtolower($operation['method']), $operationType); - - if (!$this->container->has($controller)) { - throw new RuntimeException(sprintf('There is no builtin action for the %s %s operation. You need to define the controller yourself.', $operationType, $operation['method'])); - } - } - - if ($resourceMetadata->getItemOperations()) { - $operation['identifiers'] = (array) ($operation['identifiers'] ?? $resourceMetadata->getAttribute('identifiers', $this->identifiersExtractor ? $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass) : ['id'])); - } - - $operation['has_composite_identifier'] = isset($operation['identifiers']) && \count($operation['identifiers']) > 1 ? $resourceMetadata->getAttribute('composite_identifier', true) : false; - $path = trim(trim($resourceMetadata->getAttribute('route_prefix', '')), '/'); - $path .= $this->operationPathResolver->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName); - - $route = new Route( - $path, - [ - '_controller' => $controller, - '_format' => $operation['defaults']['_format'] ?? null, - '_stateless' => $operation['stateless'] ?? null, - '_api_resource_class' => $resourceClass, - '_api_identifiers' => $operation['identifiers'] ?? [], - '_api_has_composite_identifier' => $operation['has_composite_identifier'] ?? true, - '_api_operation_name' => RouteNameGenerator::generate($operationName, $resourceShortName, $operationType), - sprintf('_api_%s_operation_name', $operationType) => $operationName, - ] + ($operation['defaults'] ?? []), - $operation['requirements'] ?? [], - $operation['options'] ?? [], - $operation['host'] ?? '', - $operation['schemes'] ?? [], - [$operation['method']], - $operation['condition'] ?? '' - ); - - $routeCollection->add(RouteNameGenerator::generate($operationName, $resourceShortName, $operationType), $route); - } } - -class_alias(ApiLoader::class, \ApiPlatform\Core\Bridge\Symfony\Routing\ApiLoader::class); diff --git a/src/Symfony/Routing/Router.php b/src/Symfony/Routing/Router.php index 14f70c5d81a..c2f73563d28 100644 --- a/src/Symfony/Routing/Router.php +++ b/src/Symfony/Routing/Router.php @@ -107,5 +107,3 @@ public function generate($name, $parameters = [], $referenceType = null): string return $this->router->generate($name, $parameters, self::CONST_MAP[$referenceType ?? $this->urlGenerationStrategy]); } } - -class_alias(Router::class, \ApiPlatform\Core\Bridge\Symfony\Routing\Router::class); diff --git a/src/Symfony/Security/Core/Authorization/ExpressionLanguageProvider.php b/src/Symfony/Security/Core/Authorization/ExpressionLanguageProvider.php index 2d7e46a3c92..5ff56fb9d2a 100644 --- a/src/Symfony/Security/Core/Authorization/ExpressionLanguageProvider.php +++ b/src/Symfony/Security/Core/Authorization/ExpressionLanguageProvider.php @@ -34,5 +34,3 @@ public function getFunctions(): array ]; } } - -class_alias(ExpressionLanguageProvider::class, \ApiPlatform\Core\Security\Core\Authorization\ExpressionLanguageProvider::class); diff --git a/src/Symfony/Security/ExpressionLanguage.php b/src/Symfony/Security/ExpressionLanguage.php index 97db8549416..172f8d9c6fe 100644 --- a/src/Symfony/Security/ExpressionLanguage.php +++ b/src/Symfony/Security/ExpressionLanguage.php @@ -47,5 +47,3 @@ protected function registerFunctions() }); } } - -class_alias(ExpressionLanguage::class, \ApiPlatform\Core\Security\ExpressionLanguage::class); diff --git a/src/Symfony/Security/ResourceAccessChecker.php b/src/Symfony/Security/ResourceAccessChecker.php index 15ac6db8d3e..c6a3c5f350a 100644 --- a/src/Symfony/Security/ResourceAccessChecker.php +++ b/src/Symfony/Security/ResourceAccessChecker.php @@ -108,5 +108,3 @@ private function getEffectiveRoles(TokenInterface $token): array }, $this->roleHierarchy->getReachableRoles($token->getRoles())); // @phpstan-ignore-line } } - -class_alias(ResourceAccessChecker::class, \ApiPlatform\Core\Security\ResourceAccessChecker::class); diff --git a/src/Symfony/Validator/EventListener/ValidationExceptionListener.php b/src/Symfony/Validator/EventListener/ValidationExceptionListener.php index d66df684cb2..a34d0b4186e 100644 --- a/src/Symfony/Validator/EventListener/ValidationExceptionListener.php +++ b/src/Symfony/Validator/EventListener/ValidationExceptionListener.php @@ -71,5 +71,3 @@ public function onKernelException(ExceptionEvent $event): void )); } } - -class_alias(ValidationExceptionListener::class, \ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidationExceptionListener::class); diff --git a/src/Symfony/Validator/Exception/ValidationException.php b/src/Symfony/Validator/Exception/ValidationException.php index 3b2417271f8..269d6503396 100644 --- a/src/Symfony/Validator/Exception/ValidationException.php +++ b/src/Symfony/Validator/Exception/ValidationException.php @@ -54,5 +54,3 @@ public function __toString(): string return $message; } } - -class_alias(ValidationException::class, \ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException::class); diff --git a/src/Symfony/Validator/Validator.php b/src/Symfony/Validator/Validator.php index 7b96123a258..5631872a282 100644 --- a/src/Symfony/Validator/Validator.php +++ b/src/Symfony/Validator/Validator.php @@ -70,5 +70,3 @@ public function validate($data, array $context = []) } } } - -class_alias(Validator::class, \ApiPlatform\Core\Bridge\Symfony\Validator\Validator::class); diff --git a/src/Test/DoctrineMongoDbOdmFilterTestCase.php b/src/Test/DoctrineMongoDbOdmFilterTestCase.php index 54f0173a611..705d82d3cb5 100644 --- a/src/Test/DoctrineMongoDbOdmFilterTestCase.php +++ b/src/Test/DoctrineMongoDbOdmFilterTestCase.php @@ -103,5 +103,3 @@ protected function buildFilter(?array $properties = null) abstract public function provideApplyTestData(): array; } - -class_alias(DoctrineMongoDbOdmFilterTestCase::class, \ApiPlatform\Core\Test\DoctrineMongoDbOdmFilterTestCase::class); diff --git a/src/Test/DoctrineMongoDbOdmSetup.php b/src/Test/DoctrineMongoDbOdmSetup.php index ed23666aef4..6806f33f955 100644 --- a/src/Test/DoctrineMongoDbOdmSetup.php +++ b/src/Test/DoctrineMongoDbOdmSetup.php @@ -119,5 +119,3 @@ private static function createCacheInstance(bool $isDevMode, ?Cache $cache) return class_exists(ArrayCache::class) ? new ArrayCache() : new ArrayAdapter(); } } - -class_alias(DoctrineMongoDbOdmSetup::class, \ApiPlatform\Core\Test\DoctrineMongoDbOdmSetup::class); diff --git a/src/Test/DoctrineMongoDbOdmTestCase.php b/src/Test/DoctrineMongoDbOdmTestCase.php index e426d4ff0c1..455afd00545 100644 --- a/src/Test/DoctrineMongoDbOdmTestCase.php +++ b/src/Test/DoctrineMongoDbOdmTestCase.php @@ -51,5 +51,3 @@ public static function createTestDocumentManager($paths = []) return DocumentManager::create(null, $config); } } - -class_alias(DoctrineMongoDbOdmTestCase::class, \ApiPlatform\Core\Test\DoctrineMongoDbOdmTestCase::class); diff --git a/src/Test/DoctrineOrmFilterTestCase.php b/src/Test/DoctrineOrmFilterTestCase.php index 3bc1d6e07db..242b094ca21 100644 --- a/src/Test/DoctrineOrmFilterTestCase.php +++ b/src/Test/DoctrineOrmFilterTestCase.php @@ -126,5 +126,3 @@ protected function buildFilter(?array $properties = null) abstract public function provideApplyTestData(): array; } - -class_alias(DoctrineOrmFilterTestCase::class, \ApiPlatform\Core\Test\DoctrineOrmFilterTestCase::class); diff --git a/src/Util/AnnotationFilterExtractorTrait.php b/src/Util/AnnotationFilterExtractorTrait.php index f4f9d3bb31d..2ff621d2570 100644 --- a/src/Util/AnnotationFilterExtractorTrait.php +++ b/src/Util/AnnotationFilterExtractorTrait.php @@ -155,5 +155,3 @@ private function generateFilterId(\ReflectionClass $reflectionClass, string $fil return 'annotated_'.Inflector::tableize(str_replace('\\', '', $reflectionClass->getName().(new \ReflectionClass($filterClass))->getName().$suffix)); } } - -class_alias(AnnotationFilterExtractorTrait::class, \ApiPlatform\Core\Util\AnnotationFilterExtractorTrait::class); diff --git a/src/Util/ArrayTrait.php b/src/Util/ArrayTrait.php index 2f0cebd6b5b..f17486cd9f8 100644 --- a/src/Util/ArrayTrait.php +++ b/src/Util/ArrayTrait.php @@ -40,5 +40,3 @@ public function arrayContainsOnly(array $array, string $type): bool }); } } - -class_alias(ArrayTrait::class, \ApiPlatform\Core\Util\ArrayTrait::class); diff --git a/src/Util/AttributesExtractor.php b/src/Util/AttributesExtractor.php index e4c63b6dff2..6225c7fc170 100644 --- a/src/Util/AttributesExtractor.php +++ b/src/Util/AttributesExtractor.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Util; -use ApiPlatform\Core\Api\OperationType; - /** * Extracts data used by the library form given attributes. * @@ -39,18 +37,18 @@ public static function extractAttributes(array $attributes): array $result['subresource_context'] = $subresourceContext; } - // Normalizing identifiers tuples - // TODO: 3.0 remove - $identifiers = []; - foreach (($attributes['_api_identifiers'] ?? ['id']) as $parameterName => $identifiedBy) { - if (\is_string($identifiedBy)) { - $identifiers[$identifiedBy] = [$result['resource_class'], $identifiedBy]; - } else { - $identifiers[$parameterName] = $identifiedBy; - } - } - - $result['identifiers'] = $identifiers; + // // Normalizing identifiers tuples + // // TODO: 3.0 remove + // $identifiers = []; + // foreach (($attributes['_api_identifiers'] ?? ['id']) as $parameterName => $identifiedBy) { + // if (\is_string($identifiedBy)) { + // $identifiers[$identifiedBy] = [$result['resource_class'], $identifiedBy]; + // } else { + // $identifiers[$parameterName] = $identifiedBy; + // } + // } + // + // $result['identifiers'] = $identifiers; if (null === $result['resource_class']) { return []; @@ -65,18 +63,6 @@ public static function extractAttributes(array $attributes): array $result['operation'] = $attributes['_api_operation']; } - // TODO: remove in 3.0 - if (!isset($result['operation']) || ($result['operation']->getExtraProperties()['is_legacy_resource_metadata'] ?? false) || ($result['operation']->getExtraProperties()['is_legacy_subresource'] ?? false)) { - foreach (OperationType::TYPES as $operationType) { - $attribute = "_api_{$operationType}_operation_name"; - if (isset($attributes[$attribute])) { - $result["{$operationType}_operation_name"] = $attributes[$attribute]; - $hasRequestAttributeKey = true; - break; - } - } - } - if ($previousObject = $attributes['previous_data'] ?? null) { $result['previous_data'] = $previousObject; } @@ -94,5 +80,3 @@ public static function extractAttributes(array $attributes): array return $result; } } - -class_alias(AttributesExtractor::class, \ApiPlatform\Core\Util\AttributesExtractor::class); diff --git a/src/Util/CachedTrait.php b/src/Util/CachedTrait.php index 831a4c6a041..abe06aca934 100644 --- a/src/Util/CachedTrait.php +++ b/src/Util/CachedTrait.php @@ -49,5 +49,3 @@ private function getCached(string $cacheKey, callable $getValue) return $this->localCache[$cacheKey] = $value; } } - -class_alias(CachedTrait::class, \ApiPlatform\Core\Cache\CachedTrait::class); diff --git a/src/Util/ClassInfoTrait.php b/src/Util/ClassInfoTrait.php index a481f901ab7..9bb039ec863 100644 --- a/src/Util/ClassInfoTrait.php +++ b/src/Util/ClassInfoTrait.php @@ -59,5 +59,3 @@ private function getRealClassName(string $className): string ); } } - -class_alias(ClassInfoTrait::class, \ApiPlatform\Core\Util\ClassInfoTrait::class); diff --git a/src/Util/ClientTrait.php b/src/Util/ClientTrait.php index ab88472f0cb..01fc07bc253 100644 --- a/src/Util/ClientTrait.php +++ b/src/Util/ClientTrait.php @@ -24,5 +24,3 @@ trait ClientTrait use ClientTrait72; } } - -class_alias(ClientTrait::class, \ApiPlatform\Core\Util\ClientTrait::class); diff --git a/src/Util/CloneTrait.php b/src/Util/CloneTrait.php index 24760cc763f..51623aecb41 100644 --- a/src/Util/CloneTrait.php +++ b/src/Util/CloneTrait.php @@ -35,5 +35,3 @@ public function clone($data) } } } - -class_alias(CloneTrait::class, \ApiPlatform\Core\Util\CloneTrait::class); diff --git a/src/Util/CorsTrait.php b/src/Util/CorsTrait.php index 1595a1fab77..c55ce2584c0 100644 --- a/src/Util/CorsTrait.php +++ b/src/Util/CorsTrait.php @@ -31,5 +31,3 @@ public function isPreflightRequest(Request $request): bool return $request->isMethod('OPTIONS') && $request->headers->has('Access-Control-Request-Method'); } } - -class_alias(CorsTrait::class, \ApiPlatform\Core\Util\CorsTrait::class); diff --git a/src/Util/ErrorFormatGuesser.php b/src/Util/ErrorFormatGuesser.php index a8163333308..a42e1fb5b34 100644 --- a/src/Util/ErrorFormatGuesser.php +++ b/src/Util/ErrorFormatGuesser.php @@ -53,5 +53,3 @@ public static function guessErrorFormat(Request $request, array $errorFormats): return $defaultFormat; } } - -class_alias(ErrorFormatGuesser::class, \ApiPlatform\Core\Util\ErrorFormatGuesser::class); diff --git a/src/Util/Inflector.php b/src/Util/Inflector.php index 412547054b2..85fdf60f0e2 100644 --- a/src/Util/Inflector.php +++ b/src/Util/Inflector.php @@ -53,5 +53,3 @@ public static function pluralize(string $word): string return class_exists(InflectorFactory::class) ? self::getInstance()->pluralize($word) : LegacyInflector::pluralize($word); // @phpstan-ignore-line } } - -class_alias(Inflector::class, \ApiPlatform\Core\Util\Inflector::class); diff --git a/src/Util/IriHelper.php b/src/Util/IriHelper.php index db6970b4388..8c6a6a24591 100644 --- a/src/Util/IriHelper.php +++ b/src/Util/IriHelper.php @@ -113,5 +113,3 @@ public static function createIri(array $parts, array $parameters, string $pagePa return $url; } } - -class_alias(IriHelper::class, \ApiPlatform\Core\Util\IriHelper::class); diff --git a/src/Util/Reflection.php b/src/Util/Reflection.php index 5029011cb2a..97a6880b41a 100644 --- a/src/Util/Reflection.php +++ b/src/Util/Reflection.php @@ -39,5 +39,3 @@ public function getProperty(string $methodName): ?string return null; } } - -class_alias(Reflection::class, \ApiPlatform\Core\Util\Reflection::class); diff --git a/src/Util/ReflectionClassRecursiveIterator.php b/src/Util/ReflectionClassRecursiveIterator.php index 10957a432ad..8215c532c11 100644 --- a/src/Util/ReflectionClassRecursiveIterator.php +++ b/src/Util/ReflectionClassRecursiveIterator.php @@ -66,5 +66,3 @@ public static function getReflectionClassesFromDirectories(array $directories): } } } - -class_alias(ReflectionClassRecursiveIterator::class, \ApiPlatform\Core\Util\ReflectionClassRecursiveIterator::class); diff --git a/src/Util/RequestAttributesExtractor.php b/src/Util/RequestAttributesExtractor.php index 47b041c8e91..8565e922e92 100644 --- a/src/Util/RequestAttributesExtractor.php +++ b/src/Util/RequestAttributesExtractor.php @@ -35,5 +35,3 @@ public static function extractAttributes(Request $request): array return AttributesExtractor::extractAttributes($request->attributes->all()); } } - -class_alias(RequestAttributesExtractor::class, \ApiPlatform\Core\Util\RequestAttributesExtractor::class); diff --git a/src/Util/RequestParser.php b/src/Util/RequestParser.php index bbaf41477d5..5d76abca243 100644 --- a/src/Util/RequestParser.php +++ b/src/Util/RequestParser.php @@ -103,5 +103,3 @@ public static function getQueryString(Request $request): ?string return implode('&', $parts); } } - -class_alias(RequestParser::class, \ApiPlatform\Core\Util\RequestParser::class); diff --git a/src/Util/ResourceClassInfoTrait.php b/src/Util/ResourceClassInfoTrait.php index cf43b091641..fa5bec30697 100644 --- a/src/Util/ResourceClassInfoTrait.php +++ b/src/Util/ResourceClassInfoTrait.php @@ -83,5 +83,3 @@ private function isResourceClass(string $class): bool return true; } } - -class_alias(ResourceClassInfoTrait::class, \ApiPlatform\Core\Util\ResourceClassInfoTrait::class); diff --git a/src/Util/ResponseTrait.php b/src/Util/ResponseTrait.php index fbd0957f18d..5932b944e23 100644 --- a/src/Util/ResponseTrait.php +++ b/src/Util/ResponseTrait.php @@ -24,5 +24,3 @@ trait ResponseTrait use ResponseTrait80; } } - -class_alias(ResponseTrait::class, \ApiPlatform\Core\Util\ResponseTrait::class); diff --git a/src/Util/SortTrait.php b/src/Util/SortTrait.php index 97e20eb7d94..04a8a31917c 100644 --- a/src/Util/SortTrait.php +++ b/src/Util/SortTrait.php @@ -33,5 +33,3 @@ private function arrayRecursiveSort(array &$array, callable $sortFunction): void $sortFunction($array); } } - -class_alias(SortTrait::class, \ApiPlatform\Core\Util\SortTrait::class); diff --git a/src/Validator/Exception/ValidationException.php b/src/Validator/Exception/ValidationException.php index d7838312a3c..361eb200485 100644 --- a/src/Validator/Exception/ValidationException.php +++ b/src/Validator/Exception/ValidationException.php @@ -23,5 +23,3 @@ class ValidationException extends RuntimeException { } - -class_alias(ValidationException::class, \ApiPlatform\Core\Validator\Exception\ValidationException::class); diff --git a/src/deprecated_interfaces.php b/src/deprecated_interfaces.php deleted file mode 100644 index 8f1c66a5dfc..00000000000 --- a/src/deprecated_interfaces.php +++ /dev/null @@ -1,121 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -return [ - ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface::class => ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface::class, - ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface::class => ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface::class, - ApiPlatform\Core\Metadata\Extractor\ExtractorInterface::class => ApiPlatform\Metadata\Extractor\ResourceExtractorInterface::class, - - // Bridge\Doctrine => Doctrine - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\DateFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\DateFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\ExistsFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\ExistsFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\OrderFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\RangeFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\RangeFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterInterface::class => ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface::class, - - // Bridge\Doctrine\MongoDbOdm => Doctrine\Odm - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationCollectionExtensionInterface::class => ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationItemExtensionInterface::class => ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultCollectionExtensionInterface::class => ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\AggregationResultItemExtensionInterface::class => ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\FilterInterface::class => ApiPlatform\Doctrine\Odm\Filter\FilterInterface::class, - - // Bridge\Doctrine\Orm => Doctrine\Orm - ApiPlatform\Core\Bridge\Doctrine\Orm\QueryAwareInterface::class => ApiPlatform\Doctrine\Orm\QueryAwareInterface::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\ContextAwareQueryCollectionExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\ContextAwareQueryResultCollectionExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryResultCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\ContextAwareQueryResultItemExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryResultItemExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface::class => ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\ContextAwareFilterInterface::class => ApiPlatform\Doctrine\Orm\Filter\ContextAwareFilterInterface::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\FilterInterface::class => ApiPlatform\Doctrine\Orm\Filter\FilterInterface::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface::class => ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface::class, - - // Bridge\Elasticsearch => Elasticsearch - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\RequestBodySearchCollectionExtensionInterface::class => ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface::class, - - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\ConstantScoreFilterInterface::class => ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\FilterInterface::class => ApiPlatform\Elasticsearch\Filter\FilterInterface::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\SortFilterInterface::class => ApiPlatform\Elasticsearch\Filter\SortFilterInterface::class, - - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface::class, - - // Bridge\Symfony\Validator - ApiPlatform\Core\Bridge\Symfony\Validator\ValidationGroupsGeneratorInterface::class => ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface::class, - ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface::class => ApiPlatform\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface::class, - ApiPlatform\Core\Bridge\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface::class => ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface::class, - - // DataProvider => State/Pagination - ApiPlatform\Core\DataProvider\PaginatorInterface::class => ApiPlatform\State\Pagination\PaginatorInterface::class, - ApiPlatform\Core\DataProvider\PartialPaginatorInterface::class => ApiPlatform\State\Pagination\PartialPaginatorInterface::class, - - // Documentation - ApiPlatform\Core\Documentation\DocumentationInterface::class => ApiPlatform\Documentation\DocumentationInterface::class, - - // JsonLd - ApiPlatform\Core\JsonLd\AnonymousContextBuilderInterface::class => ApiPlatform\JsonLd\AnonymousContextBuilderInterface::class, - ApiPlatform\Core\JsonLd\ContextBuilderInterface::class => ApiPlatform\JsonLd\ContextBuilderInterface::class, - - // JsonSchema - ApiPlatform\Core\JsonSchema\SchemaFactoryInterface::class => ApiPlatform\JsonSchema\SchemaFactoryInterface::class, - ApiPlatform\Core\JsonSchema\TypeFactoryInterface::class => ApiPlatform\JsonSchema\TypeFactoryInterface::class, - - // OpenApi - ApiPlatform\Core\OpenApi\Factory\OpenApiFactoryInterface::class => ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface::class, - - // PathResolver - ApiPlatform\Core\PathResolver\OperationPathResolverInterface::class => ApiPlatform\PathResolver\OperationPathResolverInterface::class, - - // Security => Symfony/Security - ApiPlatform\Core\Security\ResourceAccessCheckerInterface::class => ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface::class, - - // Serializer - ApiPlatform\Core\Serializer\Filter\FilterInterface::class => ApiPlatform\Serializer\Filter\FilterInterface::class, - ApiPlatform\Core\Serializer\SerializerContextBuilderInterface::class => ApiPlatform\Serializer\SerializerContextBuilderInterface::class, - - ApiPlatform\Core\Validator\ValidatorInterface::class => ApiPlatform\Validator\ValidatorInterface::class, - - // API: - ApiPlatform\Core\Api\ResourceClassResolverInterface::class => ApiPlatform\Api\ResourceClassResolverInterface::class, - ApiPlatform\Core\Api\UrlGeneratorInterface::class => ApiPlatform\Api\UrlGeneratorInterface::class, - - // GraphQl - ApiPlatform\Core\GraphQl\ExecutorInterface::class => ApiPlatform\GraphQl\ExecutorInterface::class, - ApiPlatform\Core\GraphQl\Error\ErrorHandlerInterface::class => ApiPlatform\GraphQl\Error\ErrorHandlerInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\ValidateStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\ValidateStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\SecurityStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\WriteStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\WriteStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\DeserializeStageInterface::class => ApiPlatform\GraphQl\Resolver\Stage\DeserializeStageInterface::class, - ApiPlatform\Core\GraphQl\Resolver\QueryItemResolverInterface::class => ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface::class, - ApiPlatform\Core\GraphQl\Resolver\QueryCollectionResolverInterface::class => ApiPlatform\GraphQl\Resolver\QueryCollectionResolverInterface::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\ResolverFactoryInterface::class => ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface::class, - ApiPlatform\Core\GraphQl\Resolver\MutationResolverInterface::class => ApiPlatform\GraphQl\Resolver\MutationResolverInterface::class, - ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface::class => ApiPlatform\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface::class, - ApiPlatform\Core\GraphQl\Subscription\SubscriptionIdentifierGeneratorInterface::class => ApiPlatform\GraphQl\Subscription\SubscriptionIdentifierGeneratorInterface::class, - ApiPlatform\Core\GraphQl\Subscription\SubscriptionManagerInterface::class => ApiPlatform\GraphQl\Subscription\SubscriptionManagerInterface::class, - ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilderInterface::class => ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface::class, - ApiPlatform\Core\GraphQl\Type\TypesFactoryInterface::class => ApiPlatform\GraphQl\Type\TypesFactoryInterface::class, - ApiPlatform\Core\GraphQl\Type\Definition\TypeInterface::class => ApiPlatform\GraphQl\Type\Definition\TypeInterface::class, - ApiPlatform\Core\GraphQl\Type\TypesContainerInterface::class => ApiPlatform\GraphQl\Type\TypesContainerInterface::class, - - ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface::class => ApiPlatform\Operation\PathSegmentNameGeneratorInterface::class, -]; diff --git a/src/deprecation.php b/src/deprecation.php deleted file mode 100644 index 0a7226b0789..00000000000 --- a/src/deprecation.php +++ /dev/null @@ -1,478 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -// Must be declared first! -class_alias(ApiPlatform\Api\FilterInterface::class, ApiPlatform\Core\Api\FilterInterface::class); -class_alias(ApiPlatform\Api\ResourceClassResolverInterface::class, ApiPlatform\Core\Api\ResourceClassResolverInterface::class); - -$deprecatedInterfaces = include 'deprecated_interfaces.php'; -foreach ($deprecatedInterfaces as $oldInterfaceName => $interfaceName) { - // Do not replace existing interface - if (interface_exists($oldInterfaceName)) { - continue; - } - - if (!interface_exists($interfaceName)) { - dump("interface $interfaceName does not exist, replacement $oldInterfaceName neither"); - continue; - } - - class_alias($interfaceName, $oldInterfaceName); -} - -$deprecatedClassesWithAliases = [ - ApiPlatform\Core\Api\Entrypoint::class => ApiPlatform\Api\Entrypoint::class, - ApiPlatform\Core\Api\FilterLocatorTrait::class => ApiPlatform\Api\FilterLocatorTrait::class, - ApiPlatform\Core\Api\FormatMatcher::class => ApiPlatform\Api\FormatMatcher::class, - ApiPlatform\Core\Api\ResourceClassResolver::class => ApiPlatform\Api\ResourceClassResolver::class, - - ApiPlatform\Core\Metadata\Property\PropertyNameCollection::class => ApiPlatform\Metadata\Property\PropertyNameCollection::class, - ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory::class, - ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory::class, - - // Test cases - ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase::class => ApiPlatform\Symfony\Bundle\Test\ApiTestCase::class, - ApiPlatform\Core\Test\DoctrineMongoDbOdmFilterTestCase::class => ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase::class, - ApiPlatform\Core\Test\DoctrineMongoDbOdmTestCase::class => ApiPlatform\Test\DoctrineMongoDbOdmTestCase::class, - ApiPlatform\Core\Test\DoctrineOrmFilterTestCase::class => ApiPlatform\Test\DoctrineOrmFilterTestCase::class, - - // Exceptions - ApiPlatform\Core\Exception\DeserializationException::class => ApiPlatform\Exception\DeserializationException::class, - ApiPlatform\Core\Exception\FilterValidationException::class => ApiPlatform\Exception\FilterValidationException::class, - ApiPlatform\Core\Exception\InvalidArgumentException::class => ApiPlatform\Exception\InvalidArgumentException::class, - ApiPlatform\Core\Exception\InvalidIdentifierException::class => ApiPlatform\Exception\InvalidIdentifierException::class, - ApiPlatform\Core\Exception\InvalidResourceException::class => ApiPlatform\Exception\InvalidResourceException::class, - ApiPlatform\Core\Exception\InvalidValueException::class => ApiPlatform\Exception\InvalidValueException::class, - ApiPlatform\Core\Exception\PropertyNotFoundException::class => ApiPlatform\Exception\PropertyNotFoundException::class, - ApiPlatform\Core\Exception\RuntimeException::class => ApiPlatform\Exception\RuntimeException::class, - ApiPlatform\Core\Exception\ResourceClassNotFoundException::class => ApiPlatform\Exception\ResourceClassNotFoundException::class, - ApiPlatform\Core\Exception\ResourceClassNotSupportedException::class => ApiPlatform\Exception\ResourceClassNotSupportedException::class, - ApiPlatform\Core\Exception\ItemNotFoundException::class => ApiPlatform\Exception\ItemNotFoundException::class, - - // Action - ApiPlatform\Core\Action\EntrypointAction::class => ApiPlatform\Action\EntrypointAction::class, - ApiPlatform\Core\Action\ExceptionAction::class => ApiPlatform\Action\ExceptionAction::class, - ApiPlatform\Core\Action\NotFoundAction::class => ApiPlatform\Action\NotFoundAction::class, - ApiPlatform\Core\Action\PlaceholderAction::class => ApiPlatform\Action\PlaceholderAction::class, - - // Bridge\Doctrine - ApiPlatform\Core\Bridge\Doctrine\Common\PropertyHelperTrait::class => ApiPlatform\Doctrine\Common\PropertyHelperTrait::class, - - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\BooleanFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\BooleanFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\DateFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\DateFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\ExistsFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\ExistsFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\NumericFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\NumericFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\OrderFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\RangeFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\RangeFilterTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterTrait::class => ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait::class, - - // Bridge\Doctrine\EventListener - ApiPlatform\Core\Bridge\Doctrine\EventListener\PurgeHttpCacheListener::class => ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener::class, - ApiPlatform\Core\Bridge\Doctrine\EventListener\WriteListener::class => ApiPlatform\Doctrine\EventListener\WriteListener::class, - - // Bridge\Doctrine\MongoDbOdm - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\FilterExtension::class => ApiPlatform\Doctrine\Odm\Extension\FilterExtension::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\OrderExtension::class => ApiPlatform\Doctrine\Orm\Extension\OrderExtension::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension\PaginationExtension::class => ApiPlatform\Doctrine\Orm\Extension\PaginationExtension::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\AbstractFilter::class => ApiPlatform\Doctrine\Odm\Filter\AbstractFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\BooleanFilter::class => ApiPlatform\Doctrine\Odm\Filter\BooleanFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\DateFilter::class => ApiPlatform\Doctrine\Odm\Filter\DateFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\ExistsFilter::class => ApiPlatform\Doctrine\Odm\Filter\ExistsFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\NumericFilter::class => ApiPlatform\Doctrine\Odm\Filter\NumericFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\OrderFilter::class => ApiPlatform\Doctrine\Odm\Filter\OrderFilter::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\RangeFilter::class => ApiPlatform\Doctrine\Odm\Filter\RangeFilter::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyInfo\DoctrineExtractor::class => ApiPlatform\Doctrine\Odm\PropertyInfo\DoctrineExtractor::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator::class => ApiPlatform\Doctrine\Odm\Paginator::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\PropertyHelperTrait::class => ApiPlatform\Doctrine\Odm\PropertyHelperTrait::class, - - // Bridge\Doctrine\Orm - ApiPlatform\Core\Bridge\Doctrine\Orm\AbstractPaginator::class => ApiPlatform\Doctrine\Orm\AbstractPaginator::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator::class => ApiPlatform\Doctrine\Orm\Paginator::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\PropertyHelperTrait::class => ApiPlatform\Doctrine\Orm\PropertyHelperTrait::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\EagerLoadingExtension::class => ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterEagerLoadingExtension::class => ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterExtension::class => ApiPlatform\Doctrine\Orm\Extension\FilterExtension::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\OrderExtension::class => ApiPlatform\Doctrine\Orm\Extension\OrderExtension::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension::class => ApiPlatform\Doctrine\Orm\Extension\PaginationExtension::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter::class => ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter::class => ApiPlatform\Doctrine\Orm\Filter\AbstractFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\BooleanFilter::class => ApiPlatform\Doctrine\Orm\Filter\BooleanFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\DateFilter::class => ApiPlatform\Doctrine\Orm\Filter\DateFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\ExistsFilter::class => ApiPlatform\Doctrine\Orm\Filter\ExistsFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\NumericFilter::class => ApiPlatform\Doctrine\Orm\Filter\NumericFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter::class => ApiPlatform\Doctrine\Orm\Filter\OrderFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\RangeFilter::class => ApiPlatform\Doctrine\Orm\Filter\RangeFilter::class, - - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\EagerLoadingTrait::class => ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryBuilderHelper::class => ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryChecker::class => ApiPlatform\Doctrine\Orm\Util\QueryChecker::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryJoinParser::class => ApiPlatform\Doctrine\Orm\Util\QueryJoinParser::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator::class => ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator::class, - - // Bridge\Elasticsearch - ApiPlatform\Core\Bridge\Elasticsearch\Exception\IndexNotFoundException::class => ApiPlatform\Elasticsearch\Exception\IndexNotFoundException::class, - ApiPlatform\Core\Bridge\Elasticsearch\Exception\NonUniqueIdentifierException::class => ApiPlatform\Elasticsearch\Exception\NonUniqueIdentifierException::class, - - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\AbstractFilterExtension::class => ApiPlatform\Elasticsearch\Extension\AbstractFilterExtension::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\ConstantScoreFilterExtension::class => ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\SortExtension::class => ApiPlatform\Elasticsearch\Extension\SortExtension::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\SortFilterExtension::class => ApiPlatform\Elasticsearch\Extension\SortFilterExtension::class, - - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory::class, - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory::class, - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory::class, - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory::class => ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory::class, - ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\DocumentMetadata::class => ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata::class, - - ApiPlatform\Core\Bridge\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter::class => ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter::class, - ApiPlatform\Core\Bridge\Elasticsearch\Serializer\DocumentNormalizer::class => ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer::class, - ApiPlatform\Core\Bridge\Elasticsearch\Serializer\ItemNormalizer::class => ApiPlatform\Elasticsearch\Serializer\ItemNormalizer::class, - ApiPlatform\Core\Bridge\Elasticsearch\Util\FieldDatatypeTrait::class => ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait::class, - - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator::class => ApiPlatform\Elasticsearch\Paginator::class, - - // Bridge\RamseyUuid - ApiPlatform\Core\Bridge\RamseyUuid\Serializer\UuidDenormalizer::class => ApiPlatform\RamseyUuid\Serializer\UuidDenormalizer::class, - - // Bridge\Symfony\Bundle - ApiPlatform\Core\Bridge\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver::class => ApiPlatform\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer::class => ApiPlatform\Symfony\Bundle\CacheWarmer\CachePoolClearerCacheWarmer::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\Command\GraphQlExportCommand::class => ApiPlatform\Symfony\Bundle\Command\GraphQlExportCommand::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\Command\OpenApiCommand::class => ApiPlatform\Symfony\Bundle\Command\OpenApiCommand::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\FilterPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class => ApiPlatform\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\Configuration::class => ApiPlatform\Symfony\Bundle\DependencyInjection\Configuration::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener::class => ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiAction::class => ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\SwaggerUi\SwaggerUiContext::class => ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiContext::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestAssertionsTrait::class => ApiPlatform\Symfony\Bundle\Test\ApiTestAssertionsTrait::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client::class => ApiPlatform\Symfony\Bundle\Test\Client::class, - ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Response::class => ApiPlatform\Symfony\Bundle\Test\Response::class, - - ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class, - - // Bridge\Symfony\Messenger - ApiPlatform\Core\Bridge\Symfony\Messenger\ContextStamp::class => ApiPlatform\Symfony\Messenger\ContextStamp::class, - ApiPlatform\Core\Bridge\Symfony\Messenger\DispatchTrait::class => ApiPlatform\Symfony\Messenger\DispatchTrait::class, - ApiPlatform\Core\Bridge\Symfony\Messenger\RemoveStamp::class => ApiPlatform\Symfony\Messenger\RemoveStamp::class, - - // Bridge\Symfony\PropertyInfo\Metadata\Property => Metadata\Property - ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory::class => ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory::class, - - // Bridge\Symfony\Routing - ApiPlatform\Core\Bridge\Symfony\Routing\ApiLoader::class => ApiPlatform\Symfony\Routing\ApiLoader::class, - ApiPlatform\Core\Bridge\Symfony\Routing\Router::class => ApiPlatform\Symfony\Routing\Router::class, - - // Bridge\Symfony\Validator - ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidationExceptionListener::class => ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener::class, - ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException::class => ApiPlatform\Symfony\Validator\Exception\ValidationException::class, - ApiPlatform\Core\Bridge\Symfony\Validator\Validator::class => ApiPlatform\Symfony\Validator\Validator::class, - - // Cache - ApiPlatform\Core\Cache\CachedTrait::class => ApiPlatform\Util\CachedTrait::class, - - // DataProvider => State/Pagination - ApiPlatform\Core\DataProvider\ArrayPaginator::class => ApiPlatform\State\Pagination\ArrayPaginator::class, - ApiPlatform\Core\DataProvider\PaginationOptions::class => ApiPlatform\State\Pagination\PaginationOptions::class, - ApiPlatform\Core\DataProvider\TraversablePaginator::class => ApiPlatform\State\Pagination\TraversablePaginator::class, - - // Documentation - ApiPlatform\Core\Documentation\Action\DocumentationAction::class => ApiPlatform\Documentation\Action\DocumentationAction::class, - ApiPlatform\Core\Documentation\Documentation::class => ApiPlatform\Documentation\Documentation::class, - - // EventListener => Symfony/EventListener - ApiPlatform\Core\EventListener\AddFormatListener::class => ApiPlatform\Symfony\EventListener\AddFormatListener::class, - ApiPlatform\Core\EventListener\DeserializeListener::class => ApiPlatform\Symfony\EventListener\DeserializeListener::class, - ApiPlatform\Core\EventListener\EventPriorities::class => ApiPlatform\Symfony\EventListener\EventPriorities::class, - ApiPlatform\Core\EventListener\ExceptionListener::class => ApiPlatform\Symfony\EventListener\ExceptionListener::class, - ApiPlatform\Core\EventListener\QueryParameterValidateListener::class => ApiPlatform\Symfony\EventListener\QueryParameterValidateListener::class, - ApiPlatform\Core\EventListener\RespondListener::class => ApiPlatform\Symfony\EventListener\RespondListener::class, - ApiPlatform\Core\EventListener\SerializeListener::class => ApiPlatform\Symfony\EventListener\SerializeListener::class, - - // Hal - ApiPlatform\Core\Hal\Serializer\CollectionNormalizer::class => ApiPlatform\Hal\Serializer\CollectionNormalizer::class, - ApiPlatform\Core\Hal\Serializer\EntrypointNormalizer::class => ApiPlatform\Hal\Serializer\EntrypointNormalizer::class, - ApiPlatform\Core\Hal\Serializer\ItemNormalizer::class => ApiPlatform\Hal\Serializer\ItemNormalizer::class, - ApiPlatform\Core\Hal\Serializer\ObjectNormalizer::class => ApiPlatform\Hal\Serializer\ObjectNormalizer::class, - - // HttpCache - ApiPlatform\Core\HttpCache\EventListener\AddHeadersListener::class => ApiPlatform\HttpCache\EventListener\AddHeadersListener::class, - ApiPlatform\Core\HttpCache\EventListener\AddTagsListener::class => ApiPlatform\HttpCache\EventListener\AddTagsListener::class, - ApiPlatform\Core\HttpCache\VarnishPurger::class => ApiPlatform\HttpCache\VarnishPurger::class, - ApiPlatform\Core\HttpCache\VarnishXKeyPurger::class => ApiPlatform\HttpCache\VarnishXKeyPurger::class, - - // Hydra - ApiPlatform\Core\Hydra\EventListener\AddLinkHeaderListener::class => ApiPlatform\Hydra\EventListener\AddLinkHeaderListener::class, - ApiPlatform\Core\Hydra\JsonSchema\SchemaFactory::class => ApiPlatform\Hydra\JsonSchema\SchemaFactory::class, - ApiPlatform\Core\Hydra\Serializer\CollectionFiltersNormalizer::class => ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\CollectionNormalizer::class => ApiPlatform\Hydra\Serializer\CollectionNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\ConstraintViolationListNormalizer::class => ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\DocumentationNormalizer::class => ApiPlatform\Hydra\Serializer\DocumentationNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\EntrypointNormalizer::class => ApiPlatform\Hydra\Serializer\EntrypointNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\ErrorNormalizer::class => ApiPlatform\Hydra\Serializer\ErrorNormalizer::class, - ApiPlatform\Core\Hydra\Serializer\PartialCollectionViewNormalizer::class => ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer::class, - - // JsonApi/EventListener => Symfony/EventListener - ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener::class => ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener::class, - ApiPlatform\Core\JsonApi\EventListener\TransformFilteringParametersListener::class => ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener::class, - ApiPlatform\Core\JsonApi\EventListener\TransformPaginationParametersListener::class => ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener::class, - ApiPlatform\Core\JsonApi\EventListener\TransformSortingParametersListener::class => ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener::class, - - // JsonApi/Serializer - ApiPlatform\Core\JsonApi\Serializer\CollectionNormalizer::class => ApiPlatform\JsonApi\Serializer\CollectionNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ConstraintViolationListNormalizer::class => ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\EntrypointNormalizer::class => ApiPlatform\JsonApi\Serializer\EntrypointNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ErrorNormalizer::class => ApiPlatform\JsonApi\Serializer\ErrorNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ItemNormalizer::class => ApiPlatform\JsonApi\Serializer\ItemNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ObjectNormalizer::class => ApiPlatform\JsonApi\Serializer\ObjectNormalizer::class, - ApiPlatform\Core\JsonApi\Serializer\ReservedAttributeNameConverter::class => ApiPlatform\JsonApi\Serializer\ReservedAttributeNameConverter::class, - - // JsonLd - ApiPlatform\Core\JsonLd\Action\ContextAction::class => ApiPlatform\JsonLd\Action\ContextAction::class, - ApiPlatform\Core\JsonLd\Serializer\ItemNormalizer::class => ApiPlatform\JsonLd\Serializer\ItemNormalizer::class, - ApiPlatform\Core\JsonLd\Serializer\JsonLdContextTrait::class => ApiPlatform\JsonLd\Serializer\JsonLdContextTrait::class, - ApiPlatform\Core\JsonLd\Serializer\ObjectNormalizer::class => ApiPlatform\JsonLd\Serializer\ObjectNormalizer::class, - ApiPlatform\Core\JsonLd\ContextBuilder::class => ApiPlatform\JsonLd\ContextBuilder::class, - - // JsonSchema - ApiPlatform\Core\JsonSchema\Command\JsonSchemaGenerateCommand::class => ApiPlatform\JsonSchema\Command\JsonSchemaGenerateCommand::class, - ApiPlatform\Core\JsonSchema\Schema::class => ApiPlatform\JsonSchema\Schema::class, - ApiPlatform\Core\JsonSchema\SchemaFactory::class => ApiPlatform\JsonSchema\SchemaFactory::class, - ApiPlatform\Core\JsonSchema\TypeFactory::class => ApiPlatform\JsonSchema\TypeFactory::class, - - // Mercure/EventListener => Symfony/EventListener - ApiPlatform\Core\Mercure\EventListener\AddLinkHeaderListener::class => ApiPlatform\Symfony\EventListener\AddLinkHeaderListener::class, - - // OpenApi - ApiPlatform\Core\OpenApi\Model\Components::class => ApiPlatform\OpenApi\Model\Components::class, - ApiPlatform\Core\OpenApi\Model\Contact::class => ApiPlatform\OpenApi\Model\Contact::class, - ApiPlatform\Core\OpenApi\Model\Encoding::class => ApiPlatform\OpenApi\Model\Encoding::class, - ApiPlatform\Core\OpenApi\Model\ExtensionTrait::class => ApiPlatform\OpenApi\Model\ExtensionTrait::class, - ApiPlatform\Core\OpenApi\Model\ExternalDocumentation::class => ApiPlatform\OpenApi\Model\ExternalDocumentation::class, - ApiPlatform\Core\OpenApi\Model\Info::class => ApiPlatform\OpenApi\Model\Info::class, - ApiPlatform\Core\OpenApi\Model\License::class => ApiPlatform\OpenApi\Model\License::class, - ApiPlatform\Core\OpenApi\Model\Link::class => ApiPlatform\OpenApi\Model\Link::class, - ApiPlatform\Core\OpenApi\Model\MediaType::class => ApiPlatform\OpenApi\Model\MediaType::class, - ApiPlatform\Core\OpenApi\Model\OAuthFlow::class => ApiPlatform\OpenApi\Model\OAuthFlow::class, - ApiPlatform\Core\OpenApi\Model\OAuthFlows::class => ApiPlatform\OpenApi\Model\OAuthFlows::class, - ApiPlatform\Core\OpenApi\Model\Parameter::class => ApiPlatform\OpenApi\Model\Parameter::class, - ApiPlatform\Core\OpenApi\Model\Paths::class => ApiPlatform\OpenApi\Model\Paths::class, - ApiPlatform\Core\OpenApi\Model\PathItem::class => ApiPlatform\OpenApi\Model\PathItem::class, - ApiPlatform\Core\OpenApi\Model\Operation::class => ApiPlatform\OpenApi\Model\Operation::class, - ApiPlatform\Core\OpenApi\Model\RequestBody::class => ApiPlatform\OpenApi\Model\RequestBody::class, - ApiPlatform\Core\OpenApi\Model\Response::class => ApiPlatform\OpenApi\Model\Response::class, - ApiPlatform\Core\OpenApi\Model\Schema::class => ApiPlatform\OpenApi\Model\Schema::class, - ApiPlatform\Core\OpenApi\Model\SecurityScheme::class => ApiPlatform\OpenApi\Model\SecurityScheme::class, - ApiPlatform\Core\OpenApi\Model\Server::class => ApiPlatform\OpenApi\Model\Server::class, - ApiPlatform\Core\OpenApi\Serializer\OpenApiNormalizer::class => ApiPlatform\OpenApi\Serializer\OpenApiNormalizer::class, - ApiPlatform\Core\OpenApi\OpenApi::class => ApiPlatform\OpenApi\OpenApi::class, - ApiPlatform\Core\OpenApi\Options::class => ApiPlatform\OpenApi\Options::class, - - // PathResolver - ApiPlatform\Core\PathResolver\CustomOperationPathResolver::class => ApiPlatform\PathResolver\CustomOperationPathResolver::class, - ApiPlatform\Core\PathResolver\OperationPathResolver::class => ApiPlatform\PathResolver\OperationPathResolver::class, - - // Problem - ApiPlatform\Core\Problem\Serializer\ConstraintViolationListNormalizer::class => ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer::class, - ApiPlatform\Core\Problem\Serializer\ErrorNormalizer::class => ApiPlatform\Problem\Serializer\ErrorNormalizer::class, - ApiPlatform\Core\Problem\Serializer\ErrorNormalizerTrait::class => ApiPlatform\Problem\Serializer\ErrorNormalizerTrait::class, - - // Security => Symfony/Security - ApiPlatform\Core\Security\Core\Authorization\ExpressionLanguageProvider::class => ApiPlatform\Symfony\Security\Core\Authorization\ExpressionLanguageProvider::class, - ApiPlatform\Core\Security\ExpressionLanguage::class => ApiPlatform\Symfony\Security\ExpressionLanguage::class, - ApiPlatform\Core\Security\ResourceAccessChecker::class => ApiPlatform\Symfony\Security\ResourceAccessChecker::class, - - // Security/EventListener => Symfony/EventListener - ApiPlatform\Core\Security\EventListener\DenyAccessListener::class => ApiPlatform\Symfony\EventListener\DenyAccessListener::class, - - // Serializer - ApiPlatform\Core\Serializer\Filter\GroupFilter::class => ApiPlatform\Serializer\Filter\GroupFilter::class, - ApiPlatform\Core\Serializer\Filter\PropertyFilter::class => ApiPlatform\Serializer\Filter\PropertyFilter::class, - ApiPlatform\Core\Serializer\Mapping\Factory\ClassMetadataFactory::class => ApiPlatform\Serializer\Mapping\Factory\ClassMetadataFactory::class, - ApiPlatform\Core\Serializer\AbstractCollectionNormalizer::class => ApiPlatform\Serializer\AbstractCollectionNormalizer::class, - ApiPlatform\Core\Serializer\AbstractConstraintViolationListNormalizer::class => ApiPlatform\Serializer\AbstractConstraintViolationListNormalizer::class, - ApiPlatform\Core\Serializer\AbstractItemNormalizer::class => ApiPlatform\Serializer\AbstractItemNormalizer::class, - ApiPlatform\Core\Serializer\CacheKeyTrait::class => ApiPlatform\Serializer\CacheKeyTrait::class, - ApiPlatform\Core\Serializer\ContextTrait::class => ApiPlatform\Serializer\ContextTrait::class, - ApiPlatform\Core\Serializer\InputOutputMetadataTrait::class => ApiPlatform\Serializer\InputOutputMetadataTrait::class, - ApiPlatform\Core\Serializer\ItemNormalizer::class => ApiPlatform\Serializer\ItemNormalizer::class, - ApiPlatform\Core\Serializer\JsonEncoder::class => ApiPlatform\Serializer\JsonEncoder::class, - ApiPlatform\Core\Serializer\ResourceList::class => ApiPlatform\Serializer\ResourceList::class, - ApiPlatform\Core\Serializer\SerializerContextBuilder::class => ApiPlatform\Serializer\SerializerContextBuilder::class, - ApiPlatform\Core\Serializer\SerializerFilterContextBuilder::class => ApiPlatform\Serializer\SerializerFilterContextBuilder::class, - - // Swagger/Serializer => OpenApi/Serializer - ApiPlatform\Core\Swagger\Serializer\ApiGatewayNormalizer::class => ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer::class, - - // Test - ApiPlatform\Core\Test\DoctrineMongoDbOdmSetup::class => ApiPlatform\Test\DoctrineMongoDbOdmSetup::class, - - // Util - ApiPlatform\Core\Util\AnnotationFilterExtractorTrait::class => ApiPlatform\Util\AnnotationFilterExtractorTrait::class, - ApiPlatform\Core\Util\ArrayTrait::class => ApiPlatform\Util\ArrayTrait::class, - ApiPlatform\Core\Util\AttributesExtractor::class => ApiPlatform\Util\AttributesExtractor::class, - ApiPlatform\Core\Util\ClassInfoTrait::class => ApiPlatform\Util\ClassInfoTrait::class, - ApiPlatform\Core\Util\ClientTrait::class => ApiPlatform\Util\ClientTrait::class, - ApiPlatform\Core\Util\CloneTrait::class => ApiPlatform\Util\CloneTrait::class, - ApiPlatform\Core\Util\CorsTrait::class => ApiPlatform\Util\CorsTrait::class, - ApiPlatform\Core\Util\ErrorFormatGuesser::class => ApiPlatform\Util\ErrorFormatGuesser::class, - ApiPlatform\Core\Util\Inflector::class => ApiPlatform\Util\Inflector::class, - ApiPlatform\Core\Util\IriHelper::class => ApiPlatform\Util\IriHelper::class, - ApiPlatform\Core\Util\Reflection::class => ApiPlatform\Util\Reflection::class, - ApiPlatform\Core\Util\ReflectionClassRecursiveIterator::class => ApiPlatform\Util\ReflectionClassRecursiveIterator::class, - ApiPlatform\Core\Util\RequestAttributesExtractor::class => ApiPlatform\Util\RequestAttributesExtractor::class, - ApiPlatform\Core\Util\RequestParser::class => ApiPlatform\Util\RequestParser::class, - ApiPlatform\Core\Util\ResourceClassInfoTrait::class => ApiPlatform\Util\ResourceClassInfoTrait::class, - ApiPlatform\Core\Util\ResponseTrait::class => ApiPlatform\Util\ResponseTrait::class, - ApiPlatform\Core\Util\SortTrait::class => ApiPlatform\Util\SortTrait::class, - - // Validator - ApiPlatform\Core\Validator\EventListener\ValidateListener::class => ApiPlatform\Symfony\EventListener\ValidateListener::class, - ApiPlatform\Core\Validator\Exception\ValidationException::class => ApiPlatform\Validator\Exception\ValidationException::class, - - ApiPlatform\Core\Filter\QueryParameterValidator::class => ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator::class, - ApiPlatform\Core\Filter\Validator\ArrayItems::class => ApiPlatform\Api\QueryParameterValidator\Validator\ArrayItems::class, - ApiPlatform\Core\Filter\Validator\Bounds::class => ApiPlatform\Api\QueryParameterValidator\Validator\Bounds::class, - ApiPlatform\Core\Filter\Validator\Enum::class => ApiPlatform\Api\QueryParameterValidator\Validator\Enum::class, - ApiPlatform\Core\Filter\Validator\Length::class => ApiPlatform\Api\QueryParameterValidator\Validator\Length::class, - ApiPlatform\Core\Filter\Validator\MultipleOf::class => ApiPlatform\Api\QueryParameterValidator\Validator\MultipleOf::class, - ApiPlatform\Core\Filter\Validator\Pattern::class => ApiPlatform\Api\QueryParameterValidator\Validator\Pattern::class, - ApiPlatform\Core\Filter\Validator\Required::class => ApiPlatform\Api\QueryParameterValidator\Validator\Required::class, - ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator::class => ApiPlatform\Operation\UnderscorePathSegmentNameGenerator::class, - ApiPlatform\Core\Operation\DashPathSegmentNameGenerator::class => ApiPlatform\Operation\DashPathSegmentNameGenerator::class, - - // GraphQl - ApiPlatform\Core\GraphQl\Executor::class => ApiPlatform\GraphQl\Executor::class, - ApiPlatform\Core\GraphQl\Error\ErrorHandler::class => ApiPlatform\GraphQl\Error\ErrorHandler::class, - ApiPlatform\Core\GraphQl\Resolver\Util\IdentifierTrait::class => ApiPlatform\GraphQl\Resolver\Util\IdentifierTrait::class, - ApiPlatform\Core\GraphQl\Action\EntrypointAction::class => ApiPlatform\GraphQl\Action\EntrypointAction::class, - ApiPlatform\Core\GraphQl\Action\GraphiQlAction::class => ApiPlatform\GraphQl\Action\GraphiQlAction::class, - ApiPlatform\Core\GraphQl\Action\GraphQlPlaygroundAction::class => ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction::class, - ApiPlatform\Core\GraphQl\Type\TypeNotFoundException::class => ApiPlatform\GraphQl\Type\TypeNotFoundException::class, - ApiPlatform\Core\GraphQl\Type\TypesFactory::class => ApiPlatform\GraphQl\Type\TypesFactory::class, - ApiPlatform\Core\GraphQl\Type\Definition\UploadType::class => ApiPlatform\GraphQl\Type\Definition\UploadType::class, - ApiPlatform\Core\GraphQl\Type\Definition\IterableType::class => ApiPlatform\GraphQl\Type\Definition\IterableType::class, - ApiPlatform\Core\GraphQl\Type\TypesContainer::class => ApiPlatform\GraphQl\Type\TypesContainer::class, -]; - -// These classes are deprecated but we don't want aliases as the interfaces changed -$deprecatedClassesWithoutAliases = [ - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\AbstractFilter::class => ApiPlatform\Elasticsearch\Filter\AbstractFilter::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\AbstractSearchFilter::class => ApiPlatform\Elasticsearch\Filter\AbstractSearchFilter::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\MatchFilter::class => ApiPlatform\Elasticsearch\Filter\MatchFilter::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\OrderFilter::class => ApiPlatform\Elasticsearch\Filter\OrderFilter::class, - ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\TermFilter::class => ApiPlatform\Elasticsearch\Filter\TermFilter::class, - - ApiPlatform\Core\DataProvider\Pagination::class => ApiPlatform\State\Pagination\Pagination::class, - - ApiPlatform\Core\Metadata\Property\Factory\SerializerPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory::class, - ApiPlatform\Core\Metadata\Property\Factory\CachedPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\CachedPropertyMetadataFactory::class, - ApiPlatform\Core\Metadata\Property\Factory\ExtractorPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\ExtractorPropertyMetadataFactory::class, - ApiPlatform\Core\Metadata\Property\Factory\DefaultPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\DefaultPropertyMetadataFactory::class, - - ApiPlatform\Core\Metadata\Extractor\XmlExtractor::class => ApiPlatform\Metadata\Extractor\XmlResourceExtractor::class, - ApiPlatform\Core\Metadata\Extractor\YamlExtractor::class => ApiPlatform\Metadata\Extractor\YamlResourceExtractor::class, - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Metadata\Property\DoctrineMongoDbOdmPropertyMetadataFactory::class => ApiPlatform\Doctrine\Odm\Metadata\Property\DoctrineMongoDbOdmPropertyMetadataFactory::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory::class => ApiPlatform\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory::class, - ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyMetadataFactory::class => ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory::class, - ApiPlatform\Core\Metadata\Property\PropertyMetadata::class => ApiPlatform\Metadata\ApiProperty::class, - - ApiPlatform\Core\GraphQl\Resolver\Stage\ReadStage::class => ApiPlatform\GraphQl\Resolver\Stage\ReadStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\WriteStage::class => ApiPlatform\GraphQl\Resolver\Stage\WriteStage::class, - ApiPlatform\Core\GraphQl\Type\TypeConverter::class => ApiPlatform\GraphQl\Type\TypeConverter::class, - ApiPlatform\Core\GraphQl\Type\TypeBuilder::class => ApiPlatform\GraphQl\Type\TypeBuilder::class, - ApiPlatform\Core\GraphQl\Type\FieldsBuilder::class => ApiPlatform\GraphQl\Type\FieldsBuilder::class, - ApiPlatform\Core\GraphQl\Type\SchemaBuilder::class => ApiPlatform\GraphQl\Type\SchemaBuilder::class, - ApiPlatform\Core\GraphQl\Serializer\SerializerContextBuilder::class => ApiPlatform\GraphQl\Serializer\SerializerContextBuilder::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\ItemResolverFactory::class => ApiPlatform\GraphQl\Resolver\Factory\ItemResolverFactory::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\CollectionResolverFactory::class => ApiPlatform\GraphQl\Resolver\Factory\CollectionResolverFactory::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\ItemMutationResolverFactory::class => ApiPlatform\GraphQl\Resolver\Factory\ItemMutationResolverFactory::class, - ApiPlatform\Core\GraphQl\Resolver\Factory\ItemSubscriptionResolverFactory::class => ApiPlatform\GraphQl\Resolver\Factory\ItemSubscriptionResolverFactory::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityStage::class => ApiPlatform\GraphQl\Resolver\Stage\SecurityStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SecurityPostDenormalizeStage::class => ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\SerializeStage::class => ApiPlatform\GraphQl\Resolver\Stage\SerializeStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\DeserializeStage::class => ApiPlatform\GraphQl\Resolver\Stage\DeserializeStage::class, - ApiPlatform\Core\GraphQl\Resolver\Stage\ValidateStage::class => ApiPlatform\GraphQl\Resolver\Stage\ValidateStage::class, - ApiPlatform\Core\GraphQl\Resolver\ResourceFieldResolver::class => ApiPlatform\GraphQl\Resolver\ResourceFieldResolver::class, - ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer::class => ApiPlatform\GraphQl\Serializer\ItemNormalizer::class, - ApiPlatform\Core\GraphQl\Serializer\ObjectNormalizer::class => ApiPlatform\GraphQl\Serializer\ObjectNormalizer::class, - ApiPlatform\Core\GraphQl\Subscription\SubscriptionManager::class => ApiPlatform\GraphQl\Subscription\SubscriptionManager::class, - ApiPlatform\Core\GraphQl\Serializer\Exception\ErrorNormalizer::class => ApiPlatform\GraphQl\Serializer\Exception\ErrorNormalizer::class, - ApiPlatform\Core\GraphQl\Serializer\Exception\ValidationExceptionNormalizer::class => ApiPlatform\GraphQl\Serializer\Exception\ValidationExceptionNormalizer::class, - ApiPlatform\Core\GraphQl\Serializer\Exception\HttpExceptionNormalizer::class => ApiPlatform\GraphQl\Serializer\Exception\HttpExceptionNormalizer::class, - ApiPlatform\Core\GraphQl\Serializer\Exception\RuntimeExceptionNormalizer::class => ApiPlatform\GraphQl\Serializer\Exception\RuntimeExceptionNormalizer::class, - ApiPlatform\Core\GraphQl\Subscription\SubscriptionIdentifierGenerator::class => ApiPlatform\GraphQl\Subscription\SubscriptionIdentifierGenerator::class, - ApiPlatform\Core\GraphQl\Subscription\MercureSubscriptionIriGenerator::class => ApiPlatform\GraphQl\Subscription\MercureSubscriptionIriGenerator::class, - - ApiPlatform\Core\Bridge\Doctrine\EventListener\PublishMercureUpdatesListener::class => ApiPlatform\Doctrine\EventListener\PublishMercureUpdatesListener::class, - - ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Filter\SearchFilter::class => ApiPlatform\Doctrine\Odm\Filter\SearchFilter::class, - ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter::class => ApiPlatform\Doctrine\Orm\Filter\SearchFilter::class, - ApiPlatform\Core\HttpCache\PurgerInterface::class => ApiPlatform\HttpCache\PurgerInterface::class, -]; - -spl_autoload_register(function ($className) use ($deprecatedInterfaces, $deprecatedClassesWithoutAliases, $deprecatedClassesWithAliases) { - // We can not class alias when working with doctrine annotations - static $deprecatedAnnotations = [ - 'ApiResource' => [ApiPlatform\Core\Annotation\ApiResource::class, ApiPlatform\Metadata\ApiResource::class], - 'ApiProperty' => [ApiPlatform\Core\Annotation\ApiProperty::class, ApiPlatform\Metadata\ApiProperty::class], - 'ApiFilter' => [ApiPlatform\Core\Annotation\ApiFilter::class, ApiPlatform\Metadata\ApiFilter::class], - ]; - - if (isset($deprecatedClassesWithoutAliases[$className])) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The class %s is deprecated, use %s instead.', $className, $deprecatedClassesWithoutAliases[$className])); - - return; - } - - if (isset($deprecatedClassesWithAliases[$className])) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The class %s is deprecated, use %s instead.', $className, $deprecatedClassesWithAliases[$className])); - - class_alias($deprecatedClassesWithAliases[$className], $className); - - return; - } - - if (isset($deprecatedAnnotations[$className])) { - [$annotationClassName, $attributeClassName] = $deprecatedAnnotations[$className]; - trigger_deprecation('api-platform/core', '2.7', sprintf('The Doctrine annotation %s is deprecated, use the PHP attribute %s instead.', $annotationClassName, $attributeClassName)); - - return; - } - - if (isset($deprecatedInterfaces[$className])) { - trigger_deprecation('api-platform/core', '2.7', sprintf('The interface %s is deprecated, use %s instead.', $className, $deprecatedInterfaces[$className])); - } -}); From 00a8ebb5c481e9aa531dff9c9a7d3e3489d2a045 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 12 May 2022 16:35:46 +0200 Subject: [PATCH 07/56] start working on tests --- tests/Action/EntrypointActionTest.php | 2 +- tests/Action/ExceptionActionTest.php | 61 +- tests/Api/IdentifiersExtractorTest.php | 2 +- .../QueryParameterValidatorTest.php | 2 +- .../Common/State/PersistProcessorTest.php | 2 +- .../Common/State/RemoveProcessorTest.php | 2 +- .../PublishMercureUpdatesListenerTest.php | 7 +- .../PurgeHttpCacheListenerTest.php | 2 +- .../EventListener/WriteListenerTest.php | 2 +- .../Odm/Extension/FilterExtensionTest.php | 2 +- .../Odm/Extension/OrderExtensionTest.php | 2 +- .../Odm/Extension/PaginationExtensionTest.php | 2 +- .../Doctrine/Odm/Filter/SearchFilterTest.php | 2 +- ...eMongoDbOdmPropertyMetadataFactoryTest.php | 2 +- ...mResourceCollectionMetadataFactoryTest.php | 2 +- tests/Doctrine/Odm/PaginatorTest.php | 2 +- .../Odm/State/CollectionProviderTest.php | 2 +- tests/Doctrine/Odm/State/ItemProviderTest.php | 2 +- .../Extension/EagerLoadingExtensionTest.php | 254 ++------ .../FilterEagerLoadingExtensionTest.php | 2 +- .../Orm/Extension/FilterExtensionTest.php | 2 +- .../Orm/Extension/OrderExtensionTest.php | 2 +- .../Orm/Extension/PaginationExtensionTest.php | 2 +- .../Doctrine/Orm/Filter/CommonFilterTest.php | 2 +- .../Doctrine/Orm/Filter/SearchFilterTest.php | 2 +- ...DoctrineOrmPropertyMetadataFactoryTest.php | 2 +- ...mResourceCollectionMetadataFactoryTest.php | 2 +- tests/Doctrine/Orm/PaginatorTest.php | 2 +- .../Orm/State/CollectionProviderTest.php | 2 +- tests/Doctrine/Orm/State/ItemProviderTest.php | 2 +- .../Orm/Util/QueryBuilderHelperTest.php | 2 +- tests/Doctrine/Orm/Util/QueryCheckerTest.php | 2 +- .../Doctrine/Orm/Util/QueryJoinParserTest.php | 2 +- .../Action/DocumentationActionTest.php | 66 +- .../ConstantScoreFilterExtensionTest.php | 2 +- .../Extension/SortExtensionTest.php | 2 +- .../Extension/SortFilterExtensionTest.php | 2 +- .../Elasticsearch/Filter/MatchFilterTest.php | 2 +- .../Elasticsearch/Filter/OrderFilterTest.php | 2 +- tests/Elasticsearch/Filter/TermFilterTest.php | 2 +- .../AttributeDocumentMetadataFactoryTest.php | 2 +- .../CachedDocumentMetadataFactoryTest.php | 2 +- .../CatDocumentMetadataFactoryTest.php | 2 +- .../ConfiguredDocumentMetadataFactoryTest.php | 2 +- tests/Elasticsearch/PaginatorTest.php | 2 +- .../Serializer/DocumentNormalizerTest.php | 2 +- .../Serializer/ItemNormalizerTest.php | 2 +- .../InnerFieldsNameConverterTest.php | 2 +- .../State/CollectionProviderTest.php | 2 +- .../Elasticsearch/State/ItemProviderTest.php | 2 +- .../Util/FieldDatatypeTraitTest.php | 2 +- tests/Fixtures/DummyEntityFilterAnnotated.php | 4 +- tests/Fixtures/Elasticsearch/Model/Tweet.php | 37 +- tests/Fixtures/Elasticsearch/Model/User.php | 47 +- .../TestBundle/Action/ConfigCustom.php | 7 +- tests/Fixtures/app/AppKernel.php | 2 +- .../app/config/config_behat_mongodb.yml | 14 +- .../Fixtures/app/config/config_behat_orm.yml | 14 +- tests/Fixtures/app/config/config_common.yml | 12 +- tests/Fixtures/app/config/config_mongodb.yml | 42 +- tests/Fixtures/app/config/config_test.yml | 40 +- tests/GraphQl/Action/EntrypointActionTest.php | 2 +- .../Action/GraphQlPlaygroundActionTest.php | 2 +- tests/GraphQl/Action/GraphiQlActionTest.php | 2 +- .../Factory/CollectionResolverFactoryTest.php | 2 +- .../ItemMutationResolverFactoryTest.php | 2 +- .../Factory/ItemResolverFactoryTest.php | 2 +- .../ItemSubscriptionResolverFactoryTest.php | 2 +- .../Resolver/ResourceFieldResolverTest.php | 2 +- .../Resolver/Stage/DeserializeStageTest.php | 2 +- .../GraphQl/Resolver/Stage/ReadStageTest.php | 2 +- .../SecurityPostDenormalizeStageTest.php | 2 +- .../Stage/SecurityPostValidationStageTest.php | 2 +- .../Resolver/Stage/SecurityStageTest.php | 2 +- .../Resolver/Stage/SerializeStageTest.php | 2 +- .../Resolver/Stage/ValidateStageTest.php | 2 +- .../GraphQl/Resolver/Stage/WriteStageTest.php | 2 +- .../GraphQl/Serializer/ItemNormalizerTest.php | 6 +- .../SerializerContextBuilderTest.php | 2 +- .../Subscription/SubscriptionManagerTest.php | 2 +- tests/GraphQl/Type/FieldsBuilderTest.php | 2 +- tests/GraphQl/Type/SchemaBuilderTest.php | 2 +- tests/GraphQl/Type/TypeBuilderTest.php | 2 +- tests/GraphQl/Type/TypeConverterTest.php | 2 +- tests/GraphQl/Type/TypesContainerTest.php | 2 +- tests/GraphQl/Type/TypesFactoryTest.php | 2 +- .../Serializer/CollectionNormalizerTest.php | 2 +- .../Serializer/EntrypointNormalizerTest.php | 2 +- tests/Hal/Serializer/ItemNormalizerTest.php | 2 +- tests/Hal/Serializer/ObjectNormalizerTest.php | 2 +- .../EventListener/AddHeadersListenerTest.php | 2 +- .../EventListener/AddTagsListenerTest.php | 2 +- tests/HttpCache/VarnishPurgerTest.php | 2 +- tests/HttpCache/VarnishXKeyPurgerTest.php | 2 +- .../AddLinkHeaderListenerTest.php | 2 +- .../CollectionFiltersNormalizerTest.php | 2 +- .../Serializer/CollectionNormalizerTest.php | 2 +- .../ConstraintViolationNormalizerTest.php | 2 +- .../DocumentationNormalizerTest.php | 2 +- .../Serializer/EntrypointNormalizerTest.php | 2 +- .../Hydra/Serializer/ErrorNormalizerTest.php | 2 +- .../PartialCollectionViewNormalizerTest.php | 2 +- .../Serializer/CollectionNormalizerTest.php | 2 +- .../ConstraintViolationNormalizerTest.php | 2 +- .../Serializer/EntrypointNormalizerTest.php | 2 +- .../Serializer/ErrorNormalizerTest.php | 2 +- .../JsonApi/Serializer/ItemNormalizerTest.php | 2 +- tests/JsonLd/Action/ContextActionTest.php | 2 +- tests/JsonLd/ContextBuilderTest.php | 2 +- .../JsonLd/Serializer/ItemNormalizerTest.php | 2 +- .../Serializer/ObjectNormalizerTest.php | 2 +- tests/JsonSchema/TypeFactoryTest.php | 2 +- .../AttributePropertyMetadataFactoryTest.php | 2 +- .../CachedPropertyMetadataFactoryTest.php | 2 +- ...achedPropertyNameCollectionFactoryTest.php | 2 +- .../DefaultPropertyMetadataFactoryTest.php | 2 +- ...actorPropertyNameCollectionFactoryTest.php | 2 +- .../SerializerPropertyMetadataFactoryTest.php | 2 +- ...sResourceMetadataCollectionFactoryTest.php | 2 +- ...sResourceMetadataCollectionFactoryTest.php | 2 +- ...tResourceMetadataCollectionFactoryTest.php | 2 +- .../Resource/Factory/LinkFactoryTest.php | 2 +- ...kResourceMetadataCollectionFactoryTest.php | 2 +- ...cResourceMetadataCollectionFactoryTest.php | 2 +- ...eResourceMetadataCollectionFactoryTest.php | 2 +- .../ResourceMetadataCollectionTest.php | 2 +- tests/OpenApi/Factory/OpenApiFactoryTest.php | 2 +- .../Serializer/ApiGatewayNormalizerTest.php | 2 +- .../Serializer/OpenApiNormalizerTest.php | 2 +- .../CustomOperationPathResolverTest.php | 56 -- .../OperationPathResolverTest.php | 34 - .../ConstraintViolationNormalizerTest.php | 2 +- tests/ProphecyTrait.php | 135 ++++ .../Serializer/AbstractItemNormalizerTest.php | 583 ++---------------- tests/Serializer/ItemNormalizerTest.php | 114 +--- .../LegacySerializerContextBuilderTest.php | 122 ---- .../SerializerContextBuilderTest.php | 94 ++- .../SerializerFilterContextBuilderTest.php | 74 +-- .../Bundle/Action/SwaggerUiActionTest.php | 2 +- .../Symfony/Bundle/ApiPlatformBundleTest.php | 2 +- .../PayloadArgumentResolverTest.php | 2 +- .../Command/DebugResourceCommandTest.php | 2 +- .../RequestDataCollectorTest.php | 2 +- .../ApiPlatformExtensionTest.php | 2 +- .../Compiler/AnnotationFilterPassTest.php | 2 +- .../Compiler/AuthenticatorManagerPassTest.php | 2 +- .../DeprecateMercurePublisherPassTest.php | 2 +- .../Compiler/ElasticsearchClientPassTest.php | 2 +- .../Compiler/FilterPassTest.php | 2 +- .../GraphQlMutationResolverPassTest.php | 2 +- .../Compiler/GraphQlQueryResolverPassTest.php | 2 +- .../Compiler/GraphQlTypePassTest.php | 2 +- .../MetadataAwareNameConverterPassTest.php | 2 +- .../Compiler/TestClientPassTest.php | 2 +- .../EventListener/SwaggerUiListenerTest.php | 2 +- .../Bundle/SwaggerUi/SwaggerUiActionTest.php | 2 +- .../EventListener/AddFormatListenerTest.php | 2 +- .../AddLinkHeaderListenerTest.php | 2 +- .../EventListener/DenyAccessListenerTest.php | 2 +- .../EventListener/DeserializeListenerTest.php | 2 +- .../EventListener/ExceptionListenerTest.php | 2 +- ...ansformFieldsetsParametersListenerTest.php | 2 +- ...ansformFilteringParametersListenerTest.php | 2 +- ...nsformPaginationParametersListenerTest.php | 2 +- ...TransformSortingParametersListenerTest.php | 2 +- .../QueryParameterValidateListenerTest.php | 2 +- .../EventListener/ReadListenerTest.php | 2 +- .../EventListener/RespondListenerTest.php | 2 +- .../EventListener/SerializeListenerTest.php | 2 +- .../EventListener/WriteListenerTest.php | 2 +- tests/Symfony/Messenger/ProcessorTest.php | 2 +- tests/Symfony/Routing/ApiLoaderTest.php | 2 +- tests/Symfony/Routing/IriConverterTest.php | 2 +- tests/Symfony/Routing/RouterTest.php | 2 +- .../Security/ResourceAccessCheckerTest.php | 2 +- .../PropertySchemaChoiceRestrictionTest.php | 2 +- ...ropertySchemaCollectionRestrictionTest.php | 2 +- .../PropertySchemaCountRestrictionTest.php | 2 +- .../Restriction/PropertySchemaFormatTest.php | 2 +- ...chemaGreaterThanOrEqualRestrictionTest.php | 2 +- ...opertySchemaGreaterThanRestrictionTest.php | 2 +- ...tySchemaLessThanOrEqualRestrictionTest.php | 2 +- .../PropertySchemaLessThanRestrictionTest.php | 2 +- .../PropertySchemaOneOfRestrictionTest.php | 2 +- .../PropertySchemaRangeRestrictionTest.php | 2 +- .../PropertySchemaRegexRestrictionTest.php | 2 +- .../PropertySchemaUniqueRestrictionTest.php | 2 +- .../ValidatorPropertyMetadataFactoryTest.php | 2 +- .../ValidationExceptionListenerTest.php | 2 +- .../Validator/Metadata/ValidatorTest.php | 2 +- 190 files changed, 599 insertions(+), 1560 deletions(-) delete mode 100644 tests/PathResolver/CustomOperationPathResolverTest.php delete mode 100644 tests/PathResolver/OperationPathResolverTest.php create mode 100644 tests/ProphecyTrait.php delete mode 100644 tests/Serializer/LegacySerializerContextBuilderTest.php diff --git a/tests/Action/EntrypointActionTest.php b/tests/Action/EntrypointActionTest.php index 102dd38fd3d..048aa110d5c 100644 --- a/tests/Action/EntrypointActionTest.php +++ b/tests/Action/EntrypointActionTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Action\EntrypointAction; use ApiPlatform\Api\Entrypoint; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Action/ExceptionActionTest.php b/tests/Action/ExceptionActionTest.php index 3431d32f4dc..f3d28abedaf 100644 --- a/tests/Action/ExceptionActionTest.php +++ b/tests/Action/ExceptionActionTest.php @@ -14,9 +14,6 @@ namespace ApiPlatform\Tests\Action; use ApiPlatform\Action\ExceptionAction; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; @@ -24,6 +21,7 @@ use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Tests\ProphecyTrait; use DomainException; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; @@ -38,7 +36,6 @@ * @author Amrouche Hamza * @author Baptiste Meyer * - * @group legacy * @group time-sensitive */ class ExceptionActionTest extends TestCase @@ -69,62 +66,6 @@ public function testActionWithCatchableException() $this->assertTrue($response->headers->contains('X-Frame-Options', 'deny')); } - /** - * @dataProvider provideOperationExceptionToStatusCases - * @group legacy - */ - public function testLegacyActionWithOperationExceptionToStatus( - array $globalExceptionToStatus, - ?array $resourceExceptionToStatus, - ?array $operationExceptionToStatus, - int $expectedStatusCode - ) { - $this->expectDeprecation('Since api-platform/core 2.7: Use "ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface" instead of "ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface".'); - - $exception = new DomainException(); - $flattenException = FlattenException::create($exception); - - $serializer = $this->prophesize(SerializerInterface::class); - $serializer->serialize($flattenException, 'jsonproblem', ['statusCode' => $expectedStatusCode])->willReturn(''); - - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create('Foo')->willReturn(new ResourceMetadata( - 'Foo', - null, - null, - [ - 'operation' => null !== $operationExceptionToStatus ? ['exception_to_status' => $operationExceptionToStatus] : [], - ], - null, - null !== $resourceExceptionToStatus ? ['exception_to_status' => $resourceExceptionToStatus] : [] - )); - - $exceptionAction = new ExceptionAction( - $serializer->reveal(), - [ - 'jsonproblem' => ['application/problem+json'], - 'jsonld' => ['application/ld+json'], - ], - $globalExceptionToStatus, - $resourceMetadataFactory->reveal() - ); - - $request = new Request(); - $request->setFormat('jsonproblem', 'application/problem+json'); - $request->attributes->replace([ - '_api_resource_class' => 'Foo', - '_api_item_operation_name' => 'operation', - ]); - - $response = $exceptionAction($flattenException, $request); - - $this->assertSame('', $response->getContent()); - $this->assertSame($expectedStatusCode, $response->getStatusCode()); - $this->assertTrue($response->headers->contains('Content-Type', 'application/problem+json; charset=utf-8')); - $this->assertTrue($response->headers->contains('X-Content-Type-Options', 'nosniff')); - $this->assertTrue($response->headers->contains('X-Frame-Options', 'deny')); - } - /** * @dataProvider provideOperationExceptionToStatusCases */ diff --git a/tests/Api/IdentifiersExtractorTest.php b/tests/Api/IdentifiersExtractorTest.php index 72baaea9662..0c4f194e0f9 100644 --- a/tests/Api/IdentifiersExtractorTest.php +++ b/tests/Api/IdentifiersExtractorTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IdentifiersExtractor; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Link; @@ -23,6 +22,7 @@ use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php b/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php index 746e64a844e..fa33da2bf0c 100644 --- a/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php +++ b/tests/Api/QueryParameterValidator/QueryParameterValidatorTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Doctrine/Common/State/PersistProcessorTest.php b/tests/Doctrine/Common/State/PersistProcessorTest.php index 37598d5722a..0881f65e3e1 100644 --- a/tests/Doctrine/Common/State/PersistProcessorTest.php +++ b/tests/Doctrine/Common/State/PersistProcessorTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Common\State; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Metadata\Get; use ApiPlatform\State\ProcessorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\Persistence\ManagerRegistry; diff --git a/tests/Doctrine/Common/State/RemoveProcessorTest.php b/tests/Doctrine/Common/State/RemoveProcessorTest.php index f0c51036f9b..420b96a4e9e 100644 --- a/tests/Doctrine/Common/State/RemoveProcessorTest.php +++ b/tests/Doctrine/Common/State/RemoveProcessorTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Common\State; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Metadata\Delete; use ApiPlatform\State\ProcessorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ObjectManager; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php b/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php index 98eea28c858..772b12851cd 100644 --- a/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php +++ b/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php @@ -16,8 +16,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\PublishMercureUpdatesListener; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\GraphQl\Subscription\MercureSubscriptionIriGeneratorInterface as GraphQlMercureSubscriptionIriGeneratorInterface; @@ -33,6 +31,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyFriend; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyMercure; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyOffer; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\UnitOfWork; @@ -309,7 +308,9 @@ public function testPublishUpdate(): void $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyMercure::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => []])); + $resourceMetadataFactoryProphecy->create(DummyMercure::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations([ + 'get' => (new Get())->withMercure([]), + ]))])); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations([ 'get' => (new Get())->withMercure(['hub' => 'managed', 'enable_async_update' => false])->withNormalizationContext(['groups' => ['foo', 'bar']]), diff --git a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php index 161a6c7df0a..23429e167b8 100644 --- a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php +++ b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\PurgeHttpCacheListener; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ItemNotFoundException; @@ -25,6 +24,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyNoGetOperation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Event\PreUpdateEventArgs; diff --git a/tests/Doctrine/EventListener/WriteListenerTest.php b/tests/Doctrine/EventListener/WriteListenerTest.php index d62c278be32..0e4cad1aa2a 100644 --- a/tests/Doctrine/EventListener/WriteListenerTest.php +++ b/tests/Doctrine/EventListener/WriteListenerTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Doctrine\EventListener; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\EventListener\WriteListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ObjectManager; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Odm/Extension/FilterExtensionTest.php b/tests/Doctrine/Odm/Extension/FilterExtensionTest.php index 07bfac837cb..06a4bb6e431 100644 --- a/tests/Doctrine/Odm/Extension/FilterExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/FilterExtensionTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; use ApiPlatform\Api\FilterInterface as ApiFilterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\FilterExtension; use ApiPlatform\Doctrine\Odm\Filter\FilterInterface; use ApiPlatform\Metadata\ApiResource; @@ -23,6 +22,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Doctrine/Odm/Extension/OrderExtensionTest.php b/tests/Doctrine/Odm/Extension/OrderExtensionTest.php index 72b5a6ce998..9354f2ea689 100644 --- a/tests/Doctrine/Odm/Extension/OrderExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/OrderExtensionTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\OrderExtension; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; @@ -21,6 +20,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\Lookup; use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort; diff --git a/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php b/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php index 0aea3fa64bf..237254611db 100644 --- a/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\PaginationExtension; use ApiPlatform\Doctrine\Odm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; @@ -27,6 +26,7 @@ use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Test\DoctrineMongoDbOdmSetup; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\Count; use Doctrine\ODM\MongoDB\Aggregation\Stage\Facet; diff --git a/tests/Doctrine/Odm/Filter/SearchFilterTest.php b/tests/Doctrine/Odm/Filter/SearchFilterTest.php index ee8ab9ccb8d..67fa41815c4 100644 --- a/tests/Doctrine/Odm/Filter/SearchFilterTest.php +++ b/tests/Doctrine/Odm/Filter/SearchFilterTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase; @@ -23,6 +22,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use MongoDB\BSON\Regex; use Prophecy\Argument; diff --git a/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php b/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php index 19407630a2e..075f169d731 100644 --- a/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php +++ b/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Metadata\Property; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Metadata\Property\DoctrineMongoDbOdmPropertyMetadataFactory; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\Persistence\ManagerRegistry; diff --git a/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php b/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php index 3c6ce45f078..2dc7ac2a522 100644 --- a/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php +++ b/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Metadata\Resource; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Odm\Metadata\Resource\DoctrineMongoDbOdmResourceCollectionMetadataFactory; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Odm/PaginatorTest.php b/tests/Doctrine/Odm/PaginatorTest.php index a9ff1a6aa55..a6f447a47c3 100644 --- a/tests/Doctrine/Odm/PaginatorTest.php +++ b/tests/Doctrine/Odm/PaginatorTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Odm; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Test\DoctrineMongoDbOdmSetup; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Iterator\Iterator; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Odm/State/CollectionProviderTest.php b/tests/Doctrine/Odm/State/CollectionProviderTest.php index ee76a8180dd..bd976a3102f 100644 --- a/tests/Doctrine/Odm/State/CollectionProviderTest.php +++ b/tests/Doctrine/Odm/State/CollectionProviderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\State; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\State\CollectionProvider; @@ -24,6 +23,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ProviderEntity; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Iterator\Iterator; diff --git a/tests/Doctrine/Odm/State/ItemProviderTest.php b/tests/Doctrine/Odm/State/ItemProviderTest.php index d6d39d1ca12..3c1f43f237e 100644 --- a/tests/Doctrine/Odm/State/ItemProviderTest.php +++ b/tests/Doctrine/Odm/State/ItemProviderTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\State; use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; use ApiPlatform\Doctrine\Odm\State\ItemProvider; @@ -26,6 +25,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ProviderEntity; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\MatchStage as AggregationMatch; use Doctrine\ODM\MongoDB\DocumentManager; diff --git a/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php index 2b692f74b9d..6a3ee4d8049 100644 --- a/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php @@ -13,27 +13,26 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Extension; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Serializer\SerializerContextBuilderInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AbstractDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ConcreteDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\EmbeddableDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\UnknownDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; @@ -42,7 +41,6 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\Mapping\AttributeMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadataInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; @@ -51,8 +49,6 @@ /** * @author Amrouche Hamza * @author Antoine Bluchet - * - * @group legacy */ class EagerLoadingExtensionTest extends TestCase { @@ -62,8 +58,8 @@ public function testApplyToCollection() { $context = ['groups' => ['foo']]; $callContext = ['serializer_groups' => ['foo']]; - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -132,7 +128,7 @@ public function testApplyToCollection() $queryBuilderProphecy->getDQLPart('join')->willReturn([]); $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, null, $context); } @@ -141,8 +137,8 @@ public function testApplyToItem() $context = ['groups' => ['foo']]; $callContext = ['serializer_groups' => ['foo']]; - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -240,15 +236,15 @@ public function testApplyToItem() $queryBuilderProphecy->getDQLPart('select')->willReturn([]); $queryBuilder = $queryBuilderProphecy->reveal(); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $orderExtensionTest->applyToItem($queryBuilder, new QueryNameGenerator(), Dummy::class, [], null, $context); } public function testCreateItemWithOperationName() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -265,14 +261,14 @@ public function testCreateItemWithOperationName() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], 'item_operation', ['groups' => ['foo']]); } public function testCreateCollectionWithOperationName() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -289,17 +285,16 @@ public function testCreateCollectionWithOperationName() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, 'collection_operation', ['groups' => ['foo']]); } public function testDenormalizeItemWithCorrectResourceClass() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); // Dummy is the correct class for the denormalization context serialization groups, and we're fetching RelatedDummy - $resourceMetadata = (new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]]); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($resourceMetadata)->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata)->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($this->getMetadataWithNormalizationContext(RelatedDummy::class, ['groups' => ['foo']]))->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldNotBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -312,15 +307,15 @@ public function testDenormalizeItemWithCorrectResourceClass() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); - $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], 'item_operation', ['resource_class' => Dummy::class]); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], 'get', ['resource_class' => Dummy::class]); } public function testDenormalizeItemWithExistingGroups() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); // groups exist from the context, we don't need to compute them again - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($this->getMetadataWithNormalizationContext(RelatedDummy::class, ['groups' => ['foo']]))->shouldBeCalled(); $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldNotBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -334,7 +329,7 @@ public function testDenormalizeItemWithExistingGroups() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], 'item_operation', [AbstractNormalizer::GROUPS => 'some_groups']); } @@ -343,8 +338,8 @@ public function testMaxJoinsReached() $this->expectException(RuntimeException::class); $this->expectExceptionMessage('The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary with the "api_platform.eager_loading.max_joins" configuration key (https://api-platform.com/docs/core/performance/#eager-loading), or limit the maximum serialization depth using the "enable_max_depth" option of the Symfony serializer (https://symfony.com/doc/current/components/serializer.html#handling-serialization-depth).'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class))->shouldBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -387,17 +382,14 @@ public function testMaxJoinsReached() $queryBuilderProphecy->addSelect(Argument::type('string'))->shouldBeCalled(); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, null, ['groups' => ['foo']]); } public function testMaxDepth() { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => ['enable_max_depth' => 'true', 'groups' => ['foo']]]); - - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, ['enable_max_depth' => 'true', 'groups' => ['foo']])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -411,12 +403,12 @@ public function testMaxDepth() $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo'], 'normalization_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $relatedPropertyMetadata = new ApiProperty(); $relatedPropertyMetadata = $relatedPropertyMetadata->withReadableLink(true); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'dummy', ['serializer_groups' => ['foo']])->willReturn($relatedPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'dummy', ['serializer_groups' => ['foo'], 'normalization_groups' => ['foo']])->willReturn($relatedPropertyMetadata)->shouldBeCalled(); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = [ @@ -456,16 +448,14 @@ public function testMaxDepth() $queryBuilderProphecy->addSelect(Argument::type('string'))->shouldBeCalled(); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, null, null, true, $classMetadataFactoryProphecy->reveal()); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true, $classMetadataFactoryProphecy->reveal()); $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class); } public function testForceEager() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, [AbstractNormalizer::GROUPS => 'foobar'])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); @@ -477,8 +467,8 @@ public function testForceEager() $idPropertyMetadata = new ApiProperty(); $idPropertyMetadata = $idPropertyMetadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create(UnknownDummy::class, 'id', ['serializer_groups' => ['foobar']])->willReturn($idPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foobar']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(UnknownDummy::class, 'id', ['serializer_groups' => ['foobar'], 'normalization_groups' => 'foobar'])->willReturn($idPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foobar'], 'normalization_groups' => 'foobar'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -501,16 +491,14 @@ public function testForceEager() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } public function testExtraLazy() { - $resourceMetadata = new ResourceMetadata(); - $resourceMetadata = $resourceMetadata->withAttributes(['normalization_context' => [AbstractNormalizer::GROUPS => 'foobar']]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, [AbstractNormalizer::GROUPS => 'foobar'])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); // $propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); @@ -519,7 +507,7 @@ public function testExtraLazy() $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foobar']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foobar'], 'normalization_groups' => 'foobar'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -537,7 +525,7 @@ public function testExtraLazy() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } @@ -561,7 +549,7 @@ public function testResourceClassNotFoundException() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } @@ -585,7 +573,7 @@ public function testPropertyNotFoundException() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } @@ -615,75 +603,10 @@ public function testResourceClassNotFoundExceptionPropertyNameCollection() $queryBuilderProphecy->innerJoin('o.relation', 'relation_a1')->shouldBeCalledTimes(1); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, null, null, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); } - public function testApplyToCollectionWithSerializerContextBuilder() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - - $relatedNameCollection = new PropertyNameCollection(['id', 'name']); - $propertyNameCollectionFactoryProphecy->create(RelatedDummy::class)->willReturn($relatedNameCollection)->shouldBeCalled(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new ApiProperty(); - $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); - - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); - - $idPropertyMetadata = new ApiProperty(); - $idPropertyMetadata = $idPropertyMetadata->withIdentifier(true); - $namePropertyMetadata = new ApiProperty(); - $namePropertyMetadata = $namePropertyMetadata->withReadable(true); - - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'id', ['serializer_groups' => ['foo']])->willReturn($idPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', ['serializer_groups' => ['foo']])->willReturn($namePropertyMetadata)->shouldBeCalled(); - - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); - - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->associationMappings = [ - 'relatedDummy' => ['fetch' => ClassMetadataInfo::FETCH_EAGER, 'joinColumns' => [['nullable' => true]], 'targetEntity' => RelatedDummy::class], - ]; - - $relatedClassMetadataProphecy = $this->prophesize(ClassMetadata::class); - - foreach ($relatedNameCollection as $property) { - if ('id' !== $property) { - $relatedClassMetadataProphecy->hasField($property)->willReturn(true)->shouldBeCalled(); - } - } - - $relatedClassMetadataProphecy->associationMappings = []; - - $emProphecy = $this->prophesize(EntityManager::class); - $emProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); - $emProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($relatedClassMetadataProphecy->reveal()); - - $queryBuilderProphecy->getRootAliases()->willReturn(['o']); - $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - - $queryBuilderProphecy->leftJoin('o.relatedDummy', 'relatedDummy_a1')->shouldBeCalledTimes(1); - $queryBuilderProphecy->addSelect('partial relatedDummy_a1.{id,name}')->shouldBeCalledTimes(1); - $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - - $request = Request::create('/api/dummies', 'GET', []); - - $requestStack = new RequestStack(); - $requestStack->push($request); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest($request, true)->shouldBeCalled()->willReturn([AbstractNormalizer::GROUPS => ['foo']]); - - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, $requestStack, $serializerContextBuilderProphecy->reveal(), true); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); - } - public function testAttributes() { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); @@ -742,14 +665,8 @@ public function testAttributes() $request = Request::create('/api/dummies', 'GET', []); - $requestStack = new RequestStack(); - $requestStack->push($request); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest($request, true)->shouldBeCalled()->willReturn([AbstractNormalizer::GROUPS => ['foo'], AbstractNormalizer::ATTRIBUTES => ['relatedDummies' => ['id', 'name'], 'relatedDummy' => ['id', 'name']]]); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, $requestStack, $serializerContextBuilderProphecy->reveal(), true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); } @@ -783,14 +700,8 @@ public function testNotInAttributes() $request = Request::create('/api/dummies', 'GET', []); - $requestStack = new RequestStack(); - $requestStack->push($request); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest($request, true)->shouldBeCalled()->willReturn([AbstractNormalizer::GROUPS => ['foo'], AbstractNormalizer::ATTRIBUTES => ['relatedDummy']]); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, $requestStack, $serializerContextBuilderProphecy->reveal(), true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); } @@ -850,14 +761,8 @@ public function testOnlyOneRelationNotInAttributes() $request = Request::create('/api/dummies', 'GET', []); - $requestStack = new RequestStack(); - $requestStack->push($request); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest($request, true)->shouldBeCalled()->willReturn([AbstractNormalizer::GROUPS => ['foo'], AbstractNormalizer::ATTRIBUTES => ['relatedDummy' => ['id', 'name']]]); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, $requestStack, $serializerContextBuilderProphecy->reveal(), true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); } @@ -905,36 +810,17 @@ public function testApplyToCollectionNoPartial() } public function testApplyToCollectionWithANonReadableButFetchEagerProperty() - { - $this->doTestApplyToCollectionWithANonReadableButFetchEagerProperty(false); - } - - /** - * @group legacy - */ - public function testLegacyApplyToCollectionWithANonReadableButFetchEagerProperty() - { - $this->doTestApplyToCollectionWithANonReadableButFetchEagerProperty(true); - } - - private function doTestApplyToCollectionWithANonReadableButFetchEagerProperty(bool $legacy) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - if ($legacy) { - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new PropertyMetadata(); - $relationPropertyMetadata = $relationPropertyMetadata->withAttributes(['fetchEager' => true]); - } else { - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new ApiProperty(); - $relationPropertyMetadata = $relationPropertyMetadata->withFetchEager(true); - $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); - $relationPropertyMetadata = $relationPropertyMetadata->withReadable(false); - } + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $relationPropertyMetadata = new ApiProperty(); + $relationPropertyMetadata = $relationPropertyMetadata->withFetchEager(true); + $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); + $relationPropertyMetadata = $relationPropertyMetadata->withReadable(false); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); $relationPropertyMetadata = $relationPropertyMetadata->withReadable(false); @@ -1024,34 +910,15 @@ public function provideExistingJoinCases(): iterable } public function testApplyToCollectionWithAReadableButNotFetchEagerProperty() - { - $this->doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(false); - } - - /** - * @group legacy - */ - public function testLegacyApplyToCollectionWithAReadableButNotFetchEagerProperty() - { - $this->doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(true); - } - - private function doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(bool $legacy) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - if ($legacy) { - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new PropertyMetadata(); - $relationPropertyMetadata = $relationPropertyMetadata->withAttributes(['fetchEager' => false]); - } else { - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $relationPropertyMetadata = new ApiProperty(); - $relationPropertyMetadata = $relationPropertyMetadata->withFetchEager(false); - } + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $relationPropertyMetadata = new ApiProperty(); + $relationPropertyMetadata = $relationPropertyMetadata->withFetchEager(false); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); $relationPropertyMetadata = $relationPropertyMetadata->withReadable(true); @@ -1082,4 +949,13 @@ private function doTestApplyToCollectionWithAReadableButNotFetchEagerProperty(bo $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); } + + private function getMetadataWithNormalizationContext(string $class, array $context = []): ResourceMetadataCollection + { + return new ResourceMetadataCollection($class, [ + new ApiResource(operations: [ + 'get' => new Get(name: 'get', normalizationContext: $context), + ]), + ]); + } } diff --git a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php index 0d4ca4b2006..3381dc26c72 100644 --- a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\ResourceClassResolver; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; @@ -26,6 +25,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeRelation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTravel; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Query\Expr; diff --git a/tests/Doctrine/Orm/Extension/FilterExtensionTest.php b/tests/Doctrine/Orm/Extension/FilterExtensionTest.php index 4b5d1200b81..23d7f3ed36a 100644 --- a/tests/Doctrine/Orm/Extension/FilterExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/FilterExtensionTest.php @@ -17,12 +17,12 @@ use ApiPlatform\Core\Api\FilterCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\FilterExtension; use ApiPlatform\Doctrine\Orm\Filter\FilterInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\QueryBuilder; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Doctrine/Orm/Extension/OrderExtensionTest.php b/tests/Doctrine/Orm/Extension/OrderExtensionTest.php index dd73de303b3..083052490ca 100644 --- a/tests/Doctrine/Orm/Extension/OrderExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/OrderExtensionTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\OrderExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\EmbeddedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr\OrderBy; diff --git a/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php b/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php index c292582073d..e8505d3ac07 100644 --- a/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/PaginationExtensionTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\AbstractPaginator; use ApiPlatform\Doctrine\Orm\Extension\ContextAwareQueryResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\PaginationExtension; @@ -25,6 +24,7 @@ use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; diff --git a/tests/Doctrine/Orm/Filter/CommonFilterTest.php b/tests/Doctrine/Orm/Filter/CommonFilterTest.php index d3cd0007136..4547721dbfd 100644 --- a/tests/Doctrine/Orm/Filter/CommonFilterTest.php +++ b/tests/Doctrine/Orm/Filter/CommonFilterTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Filter; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\Filter\DummyFilter; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Orm/Filter/SearchFilterTest.php b/tests/Doctrine/Orm/Filter/SearchFilterTest.php index 3ec15dcfe6f..fb9939e9714 100644 --- a/tests/Doctrine/Orm/Filter/SearchFilterTest.php +++ b/tests/Doctrine/Orm/Filter/SearchFilterTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Exception\InvalidArgumentException; @@ -24,6 +23,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Persistence\ManagerRegistry; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php b/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php index e6da9c9ecb7..5ac12c8d7e5 100644 --- a/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php +++ b/tests/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Metadata\Property; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Metadata\Property\DoctrineOrmPropertyMetadataFactory; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPropertyWithDefaultValue; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\Mapping\ClassMetadata; diff --git a/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php b/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php index 24e33ddabd3..cc44706dcfd 100644 --- a/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php +++ b/tests/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Metadata\Resource; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Orm\Metadata\Resource\DoctrineOrmResourceCollectionMetadataFactory; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ManagerRegistry; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Orm/PaginatorTest.php b/tests/Doctrine/Orm/PaginatorTest.php index ae46aafa424..a18336bc92d 100644 --- a/tests/Doctrine/Orm/PaginatorTest.php +++ b/tests/Doctrine/Orm/PaginatorTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Core\Tests\Bridge\Doctrine\Orm; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Tests\Fixtures\Query; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator; use PHPUnit\Framework\TestCase; diff --git a/tests/Doctrine/Orm/State/CollectionProviderTest.php b/tests/Doctrine/Orm/State/CollectionProviderTest.php index 6eb1192e34e..192d436abd3 100644 --- a/tests/Doctrine/Orm/State/CollectionProviderTest.php +++ b/tests/Doctrine/Orm/State/CollectionProviderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Doctrine\Orm\State; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\State\CollectionProvider; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\OperationResource; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Mapping\ClassMetadata; diff --git a/tests/Doctrine/Orm/State/ItemProviderTest.php b/tests/Doctrine/Orm/State/ItemProviderTest.php index e9b81d19bd2..1081a492e08 100644 --- a/tests/Doctrine/Orm/State/ItemProviderTest.php +++ b/tests/Doctrine/Orm/State/ItemProviderTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Doctrine\Orm\State; use ApiPlatform\Core\Identifier\IdentifierConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; use ApiPlatform\Doctrine\Orm\State\ItemProvider; @@ -30,6 +29,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Company; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Employee; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\OperationResource; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Types; diff --git a/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php b/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php index 63b44cd1f40..d983c0aaa4f 100644 --- a/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php +++ b/tests/Doctrine/Orm/Util/QueryBuilderHelperTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\QueryBuilder; diff --git a/tests/Doctrine/Orm/Util/QueryCheckerTest.php b/tests/Doctrine/Orm/Util/QueryCheckerTest.php index e9baca238f8..677e572e660 100644 --- a/tests/Doctrine/Orm/Util/QueryCheckerTest.php +++ b/tests/Doctrine/Orm/Util/QueryCheckerTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryChecker; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\QueryBuilder; diff --git a/tests/Doctrine/Orm/Util/QueryJoinParserTest.php b/tests/Doctrine/Orm/Util/QueryJoinParserTest.php index 342e3c2052f..7c945d35c92 100644 --- a/tests/Doctrine/Orm/Util/QueryJoinParserTest.php +++ b/tests/Doctrine/Orm/Util/QueryJoinParserTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Util; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Util\QueryJoinParser; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr\Join; diff --git a/tests/Documentation/Action/DocumentationActionTest.php b/tests/Documentation/Action/DocumentationActionTest.php index 0a82e114719..184c6a2fc2c 100644 --- a/tests/Documentation/Action/DocumentationActionTest.php +++ b/tests/Documentation/Action/DocumentationActionTest.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Tests\Documentation\Action; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\Action\DocumentationAction; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; @@ -23,6 +21,7 @@ use ApiPlatform\OpenApi\Model\Info; use ApiPlatform\OpenApi\Model\Paths; use ApiPlatform\OpenApi\OpenApi; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; @@ -36,65 +35,6 @@ class DocumentationActionTest extends TestCase { use ProphecyTrait; - /** - * @group legacy - * @expectedDeprecation Not passing an instance of "ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface" as 7th parameter of the constructor of "ApiPlatform\Documentation\Action\DocumentationAction" is deprecated since API Platform 2.6 - */ - public function testDocumentationAction(): void - { - $requestProphecy = $this->prophesize(Request::class); - $requestProphecy->getRequestFormat()->willReturn('json'); - $attributesProphecy = $this->prophesize(ParameterBagInterface::class); - $queryProphecy = $this->prophesize(ParameterBag::class); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummies'])); - $requestProphecy->attributes = $attributesProphecy->reveal(); - $requestProphecy->query = $queryProphecy->reveal(); - $requestProphecy->getBaseUrl()->willReturn('/api')->shouldBeCalledTimes(1); - $queryProphecy->getBoolean('api_gateway')->willReturn(true)->shouldBeCalledTimes(1); - $queryProphecy->getInt('spec_version', 2)->willReturn(2)->shouldBeCalledTimes(1); - $attributesProphecy->all()->willReturn(['_api_normalization_context' => ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2]])->shouldBeCalledTimes(1); - $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); - $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2])->shouldBeCalledTimes(1); - - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0'); - $this->assertEquals(new Documentation(new ResourceNameCollection(['dummies']), 'My happy hippie api', 'lots of chocolate', '1.0.0'), $documentation($requestProphecy->reveal())); - } - - public function testLegacyDocumentationAction(): void - { - $requestProphecy = $this->prophesize(Request::class); - $requestProphecy->getRequestFormat()->willReturn('json'); - $attributesProphecy = $this->prophesize(ParameterBagInterface::class); - $queryProphecy = $this->prophesize(ParameterBag::class); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummies'])); - $requestProphecy->attributes = $attributesProphecy->reveal(); - $requestProphecy->query = $queryProphecy->reveal(); - $requestProphecy->getBaseUrl()->willReturn('/api')->shouldBeCalledTimes(1); - $queryProphecy->getBoolean('api_gateway')->willReturn(true)->shouldBeCalledTimes(1); - $queryProphecy->getInt('spec_version', 2)->willReturn(2)->shouldBeCalledTimes(1); - $attributesProphecy->all()->willReturn(['_api_normalization_context' => ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2]])->shouldBeCalledTimes(1); - $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); - $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2])->shouldBeCalledTimes(1); - $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); - $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->willReturn(['formats' => ['jsonld' => 'application/ld+json']])->shouldBeCalled(); - - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', $formatsProviderProphecy->reveal()); - $this->assertEquals(new Documentation(new ResourceNameCollection(['dummies']), 'My happy hippie api', 'lots of chocolate', '1.0.0', ['formats' => ['jsonld' => 'application/ld+json']]), $documentation($requestProphecy->reveal())); - } - - /** - * @group legacy - * @expectedDeprecation Passing an array or an instance of "ApiPlatform\Core\Api\FormatsProviderInterface" as 5th parameter of the constructor of "ApiPlatform\Documentation\Action\DocumentationAction" is deprecated since API Platform 2.5 - */ - public function testDocumentationActionFormatDeprecation() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummies'])); - new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), '', '', '', ['formats' => ['jsonld' => 'application/ld+json']]); - } - public function testDocumentationActionV2(): void { $openApiFactoryProphecy = $this->prophesize(OpenApiFactoryInterface::class); @@ -113,7 +53,7 @@ public function testDocumentationActionV2(): void $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2])->shouldBeCalledTimes(1); - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', null, [2, 3], $openApiFactoryProphecy->reveal()); + $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', [2, 3], $openApiFactoryProphecy->reveal()); $this->assertEquals(new Documentation(new ResourceNameCollection(['dummies']), 'My happy hippie api', 'lots of chocolate', '1.0.0'), $documentation($requestProphecy->reveal())); } @@ -137,7 +77,7 @@ public function testDocumentationActionV3(): void $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 3])->shouldBeCalledTimes(1); - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', null, [2, 3], $openApiFactoryProphecy->reveal()); + $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', [2, 3], $openApiFactoryProphecy->reveal()); $this->assertInstanceOf(OpenApi::class, $documentation($requestProphecy->reveal())); } } diff --git a/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php b/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php index 7aaed1922b3..8d65f918be5 100644 --- a/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php +++ b/tests/Elasticsearch/Extension/ConstantScoreFilterExtensionTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\SortFilterInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Elasticsearch/Extension/SortExtensionTest.php b/tests/Elasticsearch/Extension/SortExtensionTest.php index 36b321c77aa..84ac48264d2 100644 --- a/tests/Elasticsearch/Extension/SortExtensionTest.php +++ b/tests/Elasticsearch/Extension/SortExtensionTest.php @@ -17,12 +17,12 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Extension\SortExtension; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/tests/Elasticsearch/Extension/SortFilterExtensionTest.php b/tests/Elasticsearch/Extension/SortFilterExtensionTest.php index 4013f362219..96c71761466 100644 --- a/tests/Elasticsearch/Extension/SortFilterExtensionTest.php +++ b/tests/Elasticsearch/Extension/SortFilterExtensionTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Extension\SortFilterExtension; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\SortFilterInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Elasticsearch/Filter/MatchFilterTest.php b/tests/Elasticsearch/Filter/MatchFilterTest.php index 379a8015e35..6e3bf334b14 100644 --- a/tests/Elasticsearch/Filter/MatchFilterTest.php +++ b/tests/Elasticsearch/Filter/MatchFilterTest.php @@ -18,13 +18,13 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\MatchFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; diff --git a/tests/Elasticsearch/Filter/OrderFilterTest.php b/tests/Elasticsearch/Filter/OrderFilterTest.php index 3cd4bcc3f1c..d63b92f5b62 100644 --- a/tests/Elasticsearch/Filter/OrderFilterTest.php +++ b/tests/Elasticsearch/Filter/OrderFilterTest.php @@ -16,12 +16,12 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\OrderFilter; use ApiPlatform\Elasticsearch\Filter\SortFilterInterface; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Elasticsearch/Filter/TermFilterTest.php b/tests/Elasticsearch/Filter/TermFilterTest.php index 76b0d7c72bb..b46194e119f 100644 --- a/tests/Elasticsearch/Filter/TermFilterTest.php +++ b/tests/Elasticsearch/Filter/TermFilterTest.php @@ -18,13 +18,13 @@ use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; use ApiPlatform\Elasticsearch\Filter\TermFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php index a252597bd6b..aa9be8d45af 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactoryTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\AttributeDocumentMetadataFactory; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php index 8eb4ca4cf12..0d3f2ce7d3a 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Elasticsearch\Metadata\Document\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\CachedDocumentMetadataFactory; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Cache\CacheItemInterface; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php index 808c9ec055b..ed64686c209 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactoryTest.php @@ -15,12 +15,12 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\CatDocumentMetadataFactory; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use Elasticsearch\Client; use Elasticsearch\Common\Exceptions\Missing404Exception; use Elasticsearch\Namespaces\CatNamespace; diff --git a/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php b/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php index 3d486390c6f..6b67b56549a 100644 --- a/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php +++ b/tests/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Elasticsearch\Metadata\Document\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\ConfiguredDocumentMetadataFactory; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class ConfiguredDocumentMetadataFactoryTest extends TestCase diff --git a/tests/Elasticsearch/PaginatorTest.php b/tests/Elasticsearch/PaginatorTest.php index 334238f0eb7..0fa19ade210 100644 --- a/tests/Elasticsearch/PaginatorTest.php +++ b/tests/Elasticsearch/PaginatorTest.php @@ -14,10 +14,10 @@ namespace ApiPlatform\Core\Tests\Bridge\Elasticsearch\DataProvider; use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Paginator; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; diff --git a/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php b/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php index cb3c139185f..375ec6bfaa0 100644 --- a/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php +++ b/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php @@ -14,9 +14,9 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer; use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; diff --git a/tests/Elasticsearch/Serializer/ItemNormalizerTest.php b/tests/Elasticsearch/Serializer/ItemNormalizerTest.php index 5a022ea1134..3c682ac785f 100644 --- a/tests/Elasticsearch/Serializer/ItemNormalizerTest.php +++ b/tests/Elasticsearch/Serializer/ItemNormalizerTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; use ApiPlatform\Elasticsearch\Serializer\ItemNormalizer; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; diff --git a/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php b/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php index e57b4af35b9..42a8a12abee 100644 --- a/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php +++ b/tests/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverterTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer\NameConverter; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Serializer\NameConverter\InnerFieldsNameConverter; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; diff --git a/tests/Elasticsearch/State/CollectionProviderTest.php b/tests/Elasticsearch/State/CollectionProviderTest.php index 110530f5712..e8e1f07b5a3 100644 --- a/tests/Elasticsearch/State/CollectionProviderTest.php +++ b/tests/Elasticsearch/State/CollectionProviderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Core\Tests\Elasticsearch\State; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; @@ -24,6 +23,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use Elasticsearch\Client; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Elasticsearch/State/ItemProviderTest.php b/tests/Elasticsearch/State/ItemProviderTest.php index c4e22dc2d99..6d98fb67f80 100644 --- a/tests/Elasticsearch/State/ItemProviderTest.php +++ b/tests/Elasticsearch/State/ItemProviderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Elasticsearch\State; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; @@ -21,6 +20,7 @@ use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use Elasticsearch\Client; use Elasticsearch\Common\Exceptions\Missing404Exception; use PHPUnit\Framework\TestCase; diff --git a/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php b/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php index 2b0a35d3e1f..fa1b82ea24f 100644 --- a/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php +++ b/tests/Elasticsearch/Util/FieldDatatypeTraitTest.php @@ -14,12 +14,12 @@ namespace ApiPlatform\Tests\Elasticsearch\Util; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Fixtures/DummyEntityFilterAnnotated.php b/tests/Fixtures/DummyEntityFilterAnnotated.php index 3801ff315e1..d0c7d9c7710 100644 --- a/tests/Fixtures/DummyEntityFilterAnnotated.php +++ b/tests/Fixtures/DummyEntityFilterAnnotated.php @@ -16,9 +16,7 @@ use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; -/** - * @ApiFilter(OrderFilter::class, arguments={"orderParameterName"="positionOrder"}, properties={"position"}) - */ +#[ApiFilter(OrderFilter::class, arguments: ['orderParameterName' => 'positionOrder'], properties: ['position'])] class DummyEntityFilterAnnotated { public $position; diff --git a/tests/Fixtures/Elasticsearch/Model/Tweet.php b/tests/Fixtures/Elasticsearch/Model/Tweet.php index d75f7d37a7e..af691d3473d 100644 --- a/tests/Fixtures/Elasticsearch/Model/Tweet.php +++ b/tests/Fixtures/Elasticsearch/Model/Tweet.php @@ -13,44 +13,29 @@ namespace ApiPlatform\Tests\Fixtures\Elasticsearch\Model; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Elasticsearch\Filter\MatchFilter; use ApiPlatform\Elasticsearch\Filter\OrderFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * normalizationContext={ - * "groups"={"tweet:read"} - * } - * ) - * @ApiFilter(OrderFilter::class, properties={"id", "author.id"}) - * @ApiFilter(MatchFilter::class, properties={"message", "author.firstName"}) - */ +#[ApiResource(normalizationContext: ['groups' => ['tweet:read']])] +#[ApiFilter(OrderFilter::class, properties: ['id', 'author.id'])] +#[ApiFilter(MatchFilter::class, properties: ['message', 'author.firstName'])] class Tweet { - /** - * @ApiProperty(identifier=true) - * - * @Groups({"tweet:read", "user:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] + #[ApiProperty(identifier: true)] private $id; - /** - * @Groups({"tweet:read"}) - */ + #[Groups(['tweet:read'])] private $author; - /** - * @Groups({"tweet:read", "user:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $date; - /** - * @Groups({"tweet:read", "user:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $message; public function getId(): ?string diff --git a/tests/Fixtures/Elasticsearch/Model/User.php b/tests/Fixtures/Elasticsearch/Model/User.php index 8f0dc9c4d0a..309ffa8f4a4 100644 --- a/tests/Fixtures/Elasticsearch/Model/User.php +++ b/tests/Fixtures/Elasticsearch/Model/User.php @@ -13,57 +13,36 @@ namespace ApiPlatform\Tests\Fixtures\Elasticsearch\Model; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Elasticsearch\Filter\TermFilter; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ApiResource( - * normalizationContext={ - * "groups"={"user:read"} - * } - * ) - * @ApiFilter(TermFilter::class, properties={"id", "gender", "age", "firstName", "tweets.id", "tweets.date"}) - */ +#[ApiResource(normalizationContext: ['groups' => ['user:read']])] +#[ApiFilter(TermFilter::class, properties: ['id', 'gender', 'age', 'firstName', 'tweets.id', 'tweets.date'])] class User { - /** - * @ApiProperty(identifier=true) - * - * @Groups({"user:read", "tweet:read"}) - */ + #[ApiProperty(identifier: true)] + #[Groups(['tweet:read', 'user:read'])] private $id; - /** - * @Groups({"user:read", "tweet:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $gender; - /** - * @Groups({"user:read", "tweet:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $age; - /** - * @Groups({"user:read", "tweet:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $firstName; - /** - * @Groups({"user:read", "tweet:read"}) - */ + #[Groups(['tweet:read', 'user:read'])] private $lastName; - /** - * @Groups({"user:read"}) - */ + #[Groups(['user:read'])] private $registeredAt; - /** - * @Groups({"user:read"}) - */ + #[Groups(['user:read'])] private $tweets = []; public function getId(): ?string diff --git a/tests/Fixtures/TestBundle/Action/ConfigCustom.php b/tests/Fixtures/TestBundle/Action/ConfigCustom.php index b9bb05f1127..d0666149a82 100644 --- a/tests/Fixtures/TestBundle/Action/ConfigCustom.php +++ b/tests/Fixtures/TestBundle/Action/ConfigCustom.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Action; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; +use ApiPlatform\Metadata\Get; +use ApiPlatform\State\ProviderInterface; use ApiPlatform\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Request; @@ -24,7 +25,7 @@ */ class ConfigCustom { - public function __construct(private readonly ItemDataProviderInterface $dataProvider) + public function __construct(private readonly ProviderInterface $provider) { } @@ -32,6 +33,6 @@ public function __invoke(Request $request, $id) { $attributes = RequestAttributesExtractor::extractAttributes($request); - return $this->dataProvider->getItem($attributes['resource_class'], $id); + return $this->provider->provide(new Get(class: $attributes['resource_class']), ['id' => $id]); } } diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index 1348cfc0c0d..31eb496bd97 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -11,8 +11,8 @@ declare(strict_types=1); -use ApiPlatform\Core\Tests\Behat\DoctrineContext; use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; +use ApiPlatform\Tests\Behat\DoctrineContext; use ApiPlatform\Tests\Fixtures\TestBundle\Document\User as UserDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\User; use ApiPlatform\Tests\Fixtures\TestBundle\TestBundle; diff --git a/tests/Fixtures/app/config/config_behat_mongodb.yml b/tests/Fixtures/app/config/config_behat_mongodb.yml index a8e05c132d1..d5974d086ca 100644 --- a/tests/Fixtures/app/config/config_behat_mongodb.yml +++ b/tests/Fixtures/app/config/config_behat_mongodb.yml @@ -3,15 +3,15 @@ services: autowire: true autoconfigure: true - ApiPlatform\Core\Tests\Behat\CommandContext: ~ - ApiPlatform\Core\Tests\Behat\DoctrineContext: + ApiPlatform\Tests\Behat\CommandContext: ~ + ApiPlatform\Tests\Behat\DoctrineContext: $doctrine: '@doctrine_mongodb' - ApiPlatform\Core\Tests\Behat\HttpCacheContext: ~ - ApiPlatform\Core\Tests\Behat\HydraContext: ~ - ApiPlatform\Core\Tests\Behat\JsonApiContext: + ApiPlatform\Tests\Behat\HttpCacheContext: ~ + ApiPlatform\Tests\Behat\HydraContext: ~ + ApiPlatform\Tests\Behat\JsonApiContext: $doctrine: '@doctrine_mongodb' $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' - ApiPlatform\Core\Tests\Behat\JsonHalContext: + ApiPlatform\Tests\Behat\JsonHalContext: $schemaFile: '%kernel.project_dir%/../JsonHal/jsonhal.json' - ApiPlatform\Core\Tests\Behat\MercureContext: + ApiPlatform\Tests\Behat\MercureContext: $driverContainer: '@behat.driver.service_container' diff --git a/tests/Fixtures/app/config/config_behat_orm.yml b/tests/Fixtures/app/config/config_behat_orm.yml index b053ac286c8..071ade50e0c 100644 --- a/tests/Fixtures/app/config/config_behat_orm.yml +++ b/tests/Fixtures/app/config/config_behat_orm.yml @@ -3,15 +3,15 @@ services: autowire: true autoconfigure: true - ApiPlatform\Core\Tests\Behat\CommandContext: ~ - ApiPlatform\Core\Tests\Behat\DoctrineContext: + ApiPlatform\Tests\Behat\CommandContext: ~ + ApiPlatform\Tests\Behat\DoctrineContext: $doctrine: '@doctrine' - ApiPlatform\Core\Tests\Behat\HttpCacheContext: ~ - ApiPlatform\Core\Tests\Behat\HydraContext: ~ - ApiPlatform\Core\Tests\Behat\JsonApiContext: + ApiPlatform\Tests\Behat\HttpCacheContext: ~ + ApiPlatform\Tests\Behat\HydraContext: ~ + ApiPlatform\Tests\Behat\JsonApiContext: $doctrine: '@doctrine' $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' - ApiPlatform\Core\Tests\Behat\JsonHalContext: + ApiPlatform\Tests\Behat\JsonHalContext: $schemaFile: '%kernel.project_dir%/../JsonHal/jsonhal.json' - ApiPlatform\Core\Tests\Behat\MercureContext: + ApiPlatform\Tests\Behat\MercureContext: $driverContainer: '@behat.driver.service_container' diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index 9f3d95e2651..4c674726ef6 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -230,7 +230,7 @@ services: app.config_dummy_resource.action: class: 'ApiPlatform\Tests\Fixtures\TestBundle\Action\ConfigCustom' - arguments: ['@api_platform.item_data_provider'] + arguments: ['@api_platform.state_provider'] public: true app.entity.filter.dummy_property.property: @@ -437,8 +437,8 @@ services: arguments: $router: '@router' - app.serializer.normalizer.override_documentation: - class: ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Normalizer\OverrideDocumentationNormalizer - decorates: api_platform.swagger.normalizer.documentation - public: false - arguments: ['@app.serializer.normalizer.override_documentation.inner'] + # app.serializer.normalizer.override_documentation: + # class: ApiPlatform\Tests\Fixtures\TestBundle\Serializer\Normalizer\OverrideDocumentationNormalizer + # decorates: api_platform.swagger.normalizer.documentation + # public: false + # arguments: ['@app.serializer.normalizer.override_documentation.inner'] diff --git a/tests/Fixtures/app/config/config_mongodb.yml b/tests/Fixtures/app/config/config_mongodb.yml index 86283b057d2..dcea3511ae8 100644 --- a/tests/Fixtures/app/config/config_mongodb.yml +++ b/tests/Fixtures/app/config/config_mongodb.yml @@ -72,14 +72,6 @@ services: arguments: [ { 'name': 'ipartial', 'description': 'ipartial' } ] tags: [ { name: 'api_platform.filter', id: 'related_to_dummy_friend.mongodb.name' } ] - ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ProductItemDataProvider: - public: false - arguments: - $managerRegistry: '@doctrine_mongodb' - $orm: false - tags: - - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider' public: false @@ -89,14 +81,6 @@ services: tags: - name: 'api_platform.state_provider' - ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\TaxonItemDataProvider: - public: false - arguments: - $managerRegistry: '@doctrine_mongodb' - $orm: false - tags: - - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider' public: false @@ -113,19 +97,19 @@ services: tags: - { name: 'api_platform.state_provider' } - app.dummy_dto_no_input.data_provider: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' - public: false - arguments: ['@doctrine_mongodb'] - tags: - - { name: 'api_platform.collection_data_provider' } - - app.dummy_dto_no_output_data_persister: - class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\DummyDtoNoOutputDataPersister - arguments: ['@doctrine_mongodb'] - public: false - tags: - - { name: 'api_platform.data_persister' } + # app.dummy_dto_no_input.data_provider: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' + # public: false + # arguments: ['@doctrine_mongodb'] + # tags: + # - { name: 'api_platform.collection_data_provider' } + # + # app.dummy_dto_no_output_data_persister: + # class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\DummyDtoNoOutputDataPersister + # arguments: ['@doctrine_mongodb'] + # public: false + # tags: + # - { name: 'api_platform.data_persister' } app.graphql.query_resolver.dummy_custom_not_retrieved_item_document: class: 'ApiPlatform\Tests\Fixtures\TestBundle\GraphQl\Resolver\DummyCustomQueryNotRetrievedItemDocumentResolver' diff --git a/tests/Fixtures/app/config/config_test.yml b/tests/Fixtures/app/config/config_test.yml index 6ae4f627efa..d1e00619e7c 100644 --- a/tests/Fixtures/app/config/config_test.yml +++ b/tests/Fixtures/app/config/config_test.yml @@ -81,13 +81,6 @@ services: tags: - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ProductItemDataProvider: - public: false - arguments: - $managerRegistry: '@doctrine' - tags: - - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider' public: false @@ -96,13 +89,6 @@ services: tags: - name: 'api_platform.state_provider' - ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\TaxonItemDataProvider: - public: false - arguments: - $managerRegistry: '@doctrine' - tags: - - name: 'api_platform.item_data_provider' - ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider' public: false @@ -111,19 +97,19 @@ services: tags: - name: 'api_platform.state_provider' - app.dummy_dto_no_input.data_provider: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' - public: false - arguments: ['@doctrine'] - tags: - - { name: 'api_platform.collection_data_provider' } - - app.dummy_dto_no_output_data_persister: - class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\DummyDtoNoOutputDataPersister - arguments: ['@doctrine'] - public: false - tags: - - { name: 'api_platform.data_persister' } + # app.dummy_dto_no_input.data_provider: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' + # public: false + # arguments: ['@doctrine'] + # tags: + # - { name: 'api_platform.collection_data_provider' } + + # app.dummy_dto_no_output_data_persister: + # class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\DummyDtoNoOutputDataPersister + # arguments: ['@doctrine'] + # public: false + # tags: + # - { name: 'api_platform.data_persister' } app.user_reset_password_data_persister: class: ApiPlatform\Tests\Fixtures\TestBundle\DataPersister\UserResetPasswordDataPersister diff --git a/tests/GraphQl/Action/EntrypointActionTest.php b/tests/GraphQl/Action/EntrypointActionTest.php index 3d1b87eef39..f0dc0651ac3 100644 --- a/tests/GraphQl/Action/EntrypointActionTest.php +++ b/tests/GraphQl/Action/EntrypointActionTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Action; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\EntrypointAction; use ApiPlatform\GraphQl\Action\GraphiQlAction; use ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction; @@ -22,6 +21,7 @@ use ApiPlatform\GraphQl\Serializer\Exception\ErrorNormalizer; use ApiPlatform\GraphQl\Serializer\Exception\HttpExceptionNormalizer; use ApiPlatform\GraphQl\Type\SchemaBuilderInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Error\DebugFlag; use GraphQL\Executor\ExecutionResult; use GraphQL\Type\Schema; diff --git a/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php b/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php index 8377aa6681e..a4d2de46c90 100644 --- a/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php +++ b/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Core\Tests\GraphQl\Action; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\GraphQlPlaygroundAction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/GraphQl/Action/GraphiQlActionTest.php b/tests/GraphQl/Action/GraphiQlActionTest.php index 987e4ead97b..a436d34bcda 100644 --- a/tests/GraphQl/Action/GraphiQlActionTest.php +++ b/tests/GraphQl/Action/GraphiQlActionTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Core\Tests\GraphQl\Action; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Action\GraphiQlAction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php index 9b19e1917b4..40d03b83a97 100644 --- a/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\CollectionResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\Metadata\GraphQl\QueryCollection; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php index e37611d40a8..26cfda051e1 100644 --- a/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemMutationResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\DeserializeStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; @@ -25,6 +24,7 @@ use ApiPlatform\GraphQl\Resolver\Stage\WriteStageInterface; use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php index 88103347c66..fdf0ecc3bfc 100644 --- a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Core\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface; @@ -21,6 +20,7 @@ use ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php index dea14a81db2..3faa06e802b 100644 --- a/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemSubscriptionResolverFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ItemSubscriptionResolverFactory; use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface; use ApiPlatform\GraphQl\Resolver\Stage\SecurityStageInterface; @@ -22,6 +21,7 @@ use ApiPlatform\GraphQl\Subscription\SubscriptionManagerInterface; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Subscription; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/ResourceFieldResolverTest.php b/tests/GraphQl/Resolver/ResourceFieldResolverTest.php index 8bf6ce7fca3..af0b9eb7fb0 100644 --- a/tests/GraphQl/Resolver/ResourceFieldResolverTest.php +++ b/tests/GraphQl/Resolver/ResourceFieldResolverTest.php @@ -15,10 +15,10 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\ResourceFieldResolver; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\FieldDefinition; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ResolveInfo; diff --git a/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php b/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php index 8838a126ed1..5d153fc349d 100644 --- a/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/DeserializeStageTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\DeserializeStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; diff --git a/tests/GraphQl/Resolver/Stage/ReadStageTest.php b/tests/GraphQl/Resolver/Stage/ReadStageTest.php index 93ed70d4cd9..29f34cd7dd2 100644 --- a/tests/GraphQl/Resolver/Stage/ReadStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ReadStageTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\GraphQl\Resolver\Stage\ReadStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\State\ProviderInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php index b6e70455b2c..47254665c7c 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php index a2efb687ce6..2d169ccb1be 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityPostValidationStageTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostValidationStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php index 10c7066086a..ebf4225c657 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SecurityStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php index e8280343e43..6bfcb44d63c 100644 --- a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SerializeStage; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; @@ -27,6 +26,7 @@ use ApiPlatform\State\Pagination\ArrayPaginator; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\State\Pagination\PartialPaginatorInterface; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Resolver/Stage/ValidateStageTest.php b/tests/GraphQl/Resolver/Stage/ValidateStageTest.php index e39395de638..e725cb47b7d 100644 --- a/tests/GraphQl/Resolver/Stage/ValidateStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ValidateStageTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\ValidateStage; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Validator\Exception\ValidationException; use ApiPlatform\Validator\ValidatorInterface; use GraphQL\Type\Definition\ResolveInfo; diff --git a/tests/GraphQl/Resolver/Stage/WriteStageTest.php b/tests/GraphQl/Resolver/Stage/WriteStageTest.php index d440234b3a2..1027eec74a4 100644 --- a/tests/GraphQl/Resolver/Stage/WriteStageTest.php +++ b/tests/GraphQl/Resolver/Stage/WriteStageTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Core\Tests\GraphQl\Resolver\Stage; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\WriteStage; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/GraphQl/Serializer/ItemNormalizerTest.php b/tests/GraphQl/Serializer/ItemNormalizerTest.php index 2d37c8f3093..7911bbbc9fd 100644 --- a/tests/GraphQl/Serializer/ItemNormalizerTest.php +++ b/tests/GraphQl/Serializer/ItemNormalizerTest.php @@ -18,12 +18,12 @@ use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; @@ -164,8 +164,6 @@ public function testNormalizeNoResolverData(): void null, null, null, - false, - null, [], null ); @@ -213,8 +211,6 @@ public function testDenormalize() null, null, null, - false, - null, [], null ); diff --git a/tests/GraphQl/Serializer/SerializerContextBuilderTest.php b/tests/GraphQl/Serializer/SerializerContextBuilderTest.php index 227bb6aadda..e5227b0ee1d 100644 --- a/tests/GraphQl/Serializer/SerializerContextBuilderTest.php +++ b/tests/GraphQl/Serializer/SerializerContextBuilderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Core\Tests\GraphQl\Serializer; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\SerializerContextBuilder; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Mutation; @@ -22,6 +21,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/GraphQl/Subscription/SubscriptionManagerTest.php b/tests/GraphQl/Subscription/SubscriptionManagerTest.php index ba7c21cac1f..376220d6d68 100644 --- a/tests/GraphQl/Subscription/SubscriptionManagerTest.php +++ b/tests/GraphQl/Subscription/SubscriptionManagerTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\GraphQl\Subscription; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface; use ApiPlatform\GraphQl\Subscription\SubscriptionIdentifierGeneratorInterface; use ApiPlatform\GraphQl\Subscription\SubscriptionManager; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheItemInterface; diff --git a/tests/GraphQl/Type/FieldsBuilderTest.php b/tests/GraphQl/Type/FieldsBuilderTest.php index 5b105dc1f33..86cc2d45d25 100644 --- a/tests/GraphQl/Type/FieldsBuilderTest.php +++ b/tests/GraphQl/Type/FieldsBuilderTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface; use ApiPlatform\GraphQl\Type\FieldsBuilder; use ApiPlatform\GraphQl\Type\TypeBuilderInterface; @@ -35,6 +34,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\ListOfType; diff --git a/tests/GraphQl/Type/SchemaBuilderTest.php b/tests/GraphQl/Type/SchemaBuilderTest.php index 2da45dafb50..3ef4c6cafaf 100644 --- a/tests/GraphQl/Type/SchemaBuilderTest.php +++ b/tests/GraphQl/Type/SchemaBuilderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Type; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\FieldsBuilderInterface; use ApiPlatform\GraphQl\Type\SchemaBuilder; use ApiPlatform\GraphQl\Type\TypesContainerInterface; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type as GraphQLType; use PHPUnit\Framework\TestCase; diff --git a/tests/GraphQl/Type/TypeBuilderTest.php b/tests/GraphQl/Type/TypeBuilderTest.php index 8218bbba946..f2436be513c 100644 --- a/tests/GraphQl/Type/TypeBuilderTest.php +++ b/tests/GraphQl/Type/TypeBuilderTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Type\FieldsBuilderInterface; use ApiPlatform\GraphQl\Type\TypeBuilder; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\ListOfType; diff --git a/tests/GraphQl/Type/TypeConverterTest.php b/tests/GraphQl/Type/TypeConverterTest.php index d29bb163312..1a8b20aedb3 100644 --- a/tests/GraphQl/Type/TypeConverterTest.php +++ b/tests/GraphQl/Type/TypeConverterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\GraphQl\Type; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\GraphQl\Type\TypeBuilderInterface; use ApiPlatform\GraphQl\Type\TypeConverter; @@ -26,6 +25,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\GraphQl\Type\Definition\DateTimeType; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type as GraphQLType; use PHPUnit\Framework\TestCase; diff --git a/tests/GraphQl/Type/TypesContainerTest.php b/tests/GraphQl/Type/TypesContainerTest.php index b03dafd16ec..da2c68fe345 100644 --- a/tests/GraphQl/Type/TypesContainerTest.php +++ b/tests/GraphQl/Type/TypesContainerTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\TypeNotFoundException; use ApiPlatform\GraphQl\Type\TypesContainer; +use ApiPlatform\Tests\ProphecyTrait; use GraphQL\Type\Definition\Type as GraphQLType; use PHPUnit\Framework\TestCase; diff --git a/tests/GraphQl/Type/TypesFactoryTest.php b/tests/GraphQl/Type/TypesFactoryTest.php index 6d1cc811876..42d5f407ffb 100644 --- a/tests/GraphQl/Type/TypesFactoryTest.php +++ b/tests/GraphQl/Type/TypesFactoryTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Core\Tests\GraphQl\Type; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\GraphQl\Type\Definition\TypeInterface; use ApiPlatform\GraphQl\Type\TypesFactory; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Hal/Serializer/CollectionNormalizerTest.php b/tests/Hal/Serializer/CollectionNormalizerTest.php index 4b78bd12862..b1bc4d57954 100644 --- a/tests/Hal/Serializer/CollectionNormalizerTest.php +++ b/tests/Hal/Serializer/CollectionNormalizerTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\CollectionNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/Hal/Serializer/EntrypointNormalizerTest.php b/tests/Hal/Serializer/EntrypointNormalizerTest.php index 6f5d29bb483..788ec6fea2a 100644 --- a/tests/Hal/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hal/Serializer/EntrypointNormalizerTest.php @@ -18,10 +18,10 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Hal/Serializer/ItemNormalizerTest.php b/tests/Hal/Serializer/ItemNormalizerTest.php index 5eaa107bee3..00e1740a226 100644 --- a/tests/Hal/Serializer/ItemNormalizerTest.php +++ b/tests/Hal/Serializer/ItemNormalizerTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; @@ -24,6 +23,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MaxDepthDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Hal/Serializer/ObjectNormalizerTest.php b/tests/Hal/Serializer/ObjectNormalizerTest.php index 2bb1ea22094..375a326466a 100644 --- a/tests/Hal/Serializer/ObjectNormalizerTest.php +++ b/tests/Hal/Serializer/ObjectNormalizerTest.php @@ -14,9 +14,9 @@ namespace ApiPlatform\Tests\Hal\Serializer; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hal\Serializer\ObjectNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/HttpCache/EventListener/AddHeadersListenerTest.php b/tests/HttpCache/EventListener/AddHeadersListenerTest.php index b1de587fa7e..e2807f27d8d 100644 --- a/tests/HttpCache/EventListener/AddHeadersListenerTest.php +++ b/tests/HttpCache/EventListener/AddHeadersListenerTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\HttpCache\EventListener\AddHeadersListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/HttpCache/EventListener/AddTagsListenerTest.php b/tests/HttpCache/EventListener/AddTagsListenerTest.php index 523b814ce6e..93bfd0dd341 100644 --- a/tests/HttpCache/EventListener/AddTagsListenerTest.php +++ b/tests/HttpCache/EventListener/AddTagsListenerTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\HttpCache\EventListener\AddTagsListener; use ApiPlatform\HttpCache\PurgerInterface; use ApiPlatform\Metadata\ApiResource; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/HttpCache/VarnishPurgerTest.php b/tests/HttpCache/VarnishPurgerTest.php index eec02e90fa6..c1d590b87e4 100644 --- a/tests/HttpCache/VarnishPurgerTest.php +++ b/tests/HttpCache/VarnishPurgerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\HttpCache; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\HttpCache\VarnishPurger; +use ApiPlatform\Tests\ProphecyTrait; use GuzzleHttp\ClientInterface; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7\Response; diff --git a/tests/HttpCache/VarnishXKeyPurgerTest.php b/tests/HttpCache/VarnishXKeyPurgerTest.php index 62773bfe9ce..89334a55673 100644 --- a/tests/HttpCache/VarnishXKeyPurgerTest.php +++ b/tests/HttpCache/VarnishXKeyPurgerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\HttpCache; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\HttpCache\VarnishXKeyPurger; +use ApiPlatform\Tests\ProphecyTrait; use GuzzleHttp\ClientInterface; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7\Response; diff --git a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php index 5ffa22d75b0..59328f7018b 100644 --- a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php @@ -14,8 +14,8 @@ namespace ApiPlatform\Tests\Hydra\EventListener; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\EventListener\AddLinkHeaderListener; +use ApiPlatform\Tests\ProphecyTrait; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; use PHPUnit\Framework\TestCase; diff --git a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php index 6fe154a5ec0..af309bea518 100644 --- a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php @@ -18,7 +18,6 @@ use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\FilterInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer; @@ -26,6 +25,7 @@ use ApiPlatform\Tests\Fixtures\Foo; use ApiPlatform\Tests\Fixtures\NotAResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Container\ContainerInterface; diff --git a/tests/Hydra/Serializer/CollectionNormalizerTest.php b/tests/Hydra/Serializer/CollectionNormalizerTest.php index 68b9f4afd0f..3b025f1b3d6 100644 --- a/tests/Hydra/Serializer/CollectionNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionNormalizerTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Hydra\Serializer\CollectionNormalizer; use ApiPlatform\JsonLd\ContextBuilderInterface; @@ -25,6 +24,7 @@ use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\Fixtures\Foo; use ApiPlatform\Tests\Fixtures\NotAResource; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php b/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php index 5e788073c47..70a46f22fbd 100644 --- a/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/Hydra/Serializer/ConstraintViolationNormalizerTest.php @@ -14,8 +14,8 @@ namespace ApiPlatform\Tests\Hydra\Serializer; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\ConstraintViolationListNormalizer; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index e62d1426553..784c7a946bf 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -22,7 +22,6 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Hydra\Serializer\DocumentationNormalizer; use ApiPlatform\Metadata\ApiProperty; @@ -39,6 +38,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Hydra/Serializer/EntrypointNormalizerTest.php b/tests/Hydra/Serializer/EntrypointNormalizerTest.php index 0d549ca32df..69ef89c04ec 100644 --- a/tests/Hydra/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hydra/Serializer/EntrypointNormalizerTest.php @@ -18,7 +18,6 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FooDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Hydra/Serializer/ErrorNormalizerTest.php b/tests/Hydra/Serializer/ErrorNormalizerTest.php index f99b0ed030d..ac132633020 100644 --- a/tests/Hydra/Serializer/ErrorNormalizerTest.php +++ b/tests/Hydra/Serializer/ErrorNormalizerTest.php @@ -14,8 +14,8 @@ namespace ApiPlatform\Tests\Hydra\Serializer; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\ErrorNormalizer; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php index 00e80239080..0501963ca1c 100644 --- a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php +++ b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SoMany; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; diff --git a/tests/JsonApi/Serializer/CollectionNormalizerTest.php b/tests/JsonApi/Serializer/CollectionNormalizerTest.php index 5a7d46b5a74..37348e9fd54 100644 --- a/tests/JsonApi/Serializer/CollectionNormalizerTest.php +++ b/tests/JsonApi/Serializer/CollectionNormalizerTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonApi\Serializer\CollectionNormalizer; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php b/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php index 54cac5957dc..c8324818684 100644 --- a/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/JsonApi/Serializer/ConstraintViolationNormalizerTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonApi\Serializer\ConstraintViolationListNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php index 37981f8b8ad..17e65def0f6 100644 --- a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php +++ b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php @@ -18,13 +18,13 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\JsonApi\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/JsonApi/Serializer/ErrorNormalizerTest.php b/tests/JsonApi/Serializer/ErrorNormalizerTest.php index d9060aa67e5..d3688d50308 100644 --- a/tests/JsonApi/Serializer/ErrorNormalizerTest.php +++ b/tests/JsonApi/Serializer/ErrorNormalizerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; -use ApiPlatform\Tests\Mock\Exception\ErrorCodeSerializable; use ApiPlatform\JsonApi\Serializer\ErrorNormalizer; +use ApiPlatform\Tests\Mock\Exception\ErrorCodeSerializable; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/JsonApi/Serializer/ItemNormalizerTest.php b/tests/JsonApi/Serializer/ItemNormalizerTest.php index ce7dab5fbc4..6df819cc6c6 100644 --- a/tests/JsonApi/Serializer/ItemNormalizerTest.php +++ b/tests/JsonApi/Serializer/ItemNormalizerTest.php @@ -21,7 +21,6 @@ use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\JsonApi\Serializer\ItemNormalizer; @@ -31,6 +30,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CircularReference; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Collections\ArrayCollection; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/JsonLd/Action/ContextActionTest.php b/tests/JsonLd/Action/ContextActionTest.php index 44cb8e9571d..d0bf3073217 100644 --- a/tests/JsonLd/Action/ContextActionTest.php +++ b/tests/JsonLd/Action/ContextActionTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonLd\Action\ContextAction; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; diff --git a/tests/JsonLd/ContextBuilderTest.php b/tests/JsonLd/ContextBuilderTest.php index 8e70cbe9d38..9df102a1d60 100644 --- a/tests/JsonLd/ContextBuilderTest.php +++ b/tests/JsonLd/ContextBuilderTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; @@ -26,6 +25,7 @@ use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/JsonLd/Serializer/ItemNormalizerTest.php b/tests/JsonLd/Serializer/ItemNormalizerTest.php index 4ffbfcbfc2a..26ac57588ec 100644 --- a/tests/JsonLd/Serializer/ItemNormalizerTest.php +++ b/tests/JsonLd/Serializer/ItemNormalizerTest.php @@ -17,7 +17,6 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; @@ -25,6 +24,7 @@ use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/JsonLd/Serializer/ObjectNormalizerTest.php b/tests/JsonLd/Serializer/ObjectNormalizerTest.php index 23a0c3c4cd6..61fbde5b9ad 100644 --- a/tests/JsonLd/Serializer/ObjectNormalizerTest.php +++ b/tests/JsonLd/Serializer/ObjectNormalizerTest.php @@ -14,10 +14,10 @@ namespace ApiPlatform\Tests\JsonLd\Serializer; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonLd\AnonymousContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\ObjectNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/JsonSchema/TypeFactoryTest.php b/tests/JsonSchema/TypeFactoryTest.php index 27c05b11800..fd36710d4fe 100644 --- a/tests/JsonSchema/TypeFactoryTest.php +++ b/tests/JsonSchema/TypeFactoryTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\JsonSchema; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\JsonSchema\TypeFactory; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php index 0b8a17181df..09891a231cc 100644 --- a/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/AttributePropertyMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\AttributePropertyMetadataFactory; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPhp8ApiPropertyAttribute; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php index 37b97955388..f5e4573ce16 100644 --- a/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\CachedPropertyMetadataFactory; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheException; use Psr\Cache\CacheItemInterface; diff --git a/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php b/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php index 07c44bd30f0..bbe2d7b7eb7 100644 --- a/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php +++ b/tests/Metadata/Property/Factory/CachedPropertyNameCollectionFactoryTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\Property\Factory\CachedPropertyNameCollectionFactory; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Cache\CacheException; use Psr\Cache\CacheItemInterface; diff --git a/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php index 18a3f00d8e7..d13dd450c78 100644 --- a/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/DefaultPropertyMetadataFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\DefaultPropertyMetadataFactory; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyPropertyWithDefaultValue; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class DefaultPropertyMetadataFactoryTest extends TestCase diff --git a/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php b/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php index 8754df086d2..f2ada8d8e04 100644 --- a/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php +++ b/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php @@ -15,13 +15,13 @@ use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php index 9e7b159fdf0..d72715836d8 100644 --- a/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/SerializerPropertyMetadataFactoryTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\SerializerPropertyMetadataFactory; @@ -22,6 +21,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Annotation\Ignore; diff --git a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php index 56728eaa45f..1a5ab585e94 100644 --- a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -34,6 +33,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ExtraPropertiesResource; use ApiPlatform\Tests\Fixtures\TestBundle\State\AttributeResourceProcessor; use ApiPlatform\Tests\Fixtures\TestBundle\State\AttributeResourceProvider; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php index b10e48b239c..51aebcd77dc 100644 --- a/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/FormatsResourceMetadataCollectionFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; @@ -21,6 +20,7 @@ use ApiPlatform\Metadata\Resource\Factory\FormatsResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class FormatsResourceMetadataCollectionFactoryTest extends TestCase diff --git a/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php index 948037d6cb5..92667f60bb6 100644 --- a/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/InputOutputResourceMetadataCollectionFactoryTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\InputOutputResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\DummyEntity; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class InputOutputResourceMetadataCollectionFactoryTest extends TestCase diff --git a/tests/Metadata/Resource/Factory/LinkFactoryTest.php b/tests/Metadata/Resource/Factory/LinkFactoryTest.php index 697cd997155..562035efa5e 100644 --- a/tests/Metadata/Resource/Factory/LinkFactoryTest.php +++ b/tests/Metadata/Resource/Factory/LinkFactoryTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; @@ -26,6 +25,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; diff --git a/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php index b324a6e4f78..030e62f06b9 100644 --- a/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\Query; @@ -29,6 +28,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Collections\Collection; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php index 38ebc8e52d9..0961e74aa0d 100644 --- a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\PhpDocResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\ClassWithNoDocBlock; use ApiPlatform\Tests\Fixtures\DummyEntity; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; class PhpDocResourceMetadataCollectionFactoryTest extends TestCase diff --git a/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php index ce944ae6f4b..9481cd620c8 100644 --- a/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -31,6 +30,7 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Metadata/Resource/ResourceMetadataCollectionTest.php b/tests/Metadata/Resource/ResourceMetadataCollectionTest.php index 640006fba84..52b97deb092 100644 --- a/tests/Metadata/Resource/ResourceMetadataCollectionTest.php +++ b/tests/Metadata/Resource/ResourceMetadataCollectionTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Metadata\Resource; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; final class ResourceMetadataCollectionTest extends TestCase diff --git a/tests/OpenApi/Factory/OpenApiFactoryTest.php b/tests/OpenApi/Factory/OpenApiFactoryTest.php index 263df051cb1..1468c7ec395 100644 --- a/tests/OpenApi/Factory/OpenApiFactoryTest.php +++ b/tests/OpenApi/Factory/OpenApiFactoryTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\OpenApi\Factory; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; @@ -46,6 +45,7 @@ use ApiPlatform\Tests\Fixtures\DummyFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Container\ContainerInterface; diff --git a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php index 7e3996b70c1..1050884d9c5 100644 --- a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php +++ b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php @@ -14,11 +14,11 @@ namespace ApiPlatform\Tests\OpenApi\Serializer; use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; diff --git a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php index 71855b63764..93c666f78af 100644 --- a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php +++ b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php @@ -24,7 +24,6 @@ use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory as LegacyOpenApiFactory; use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; use ApiPlatform\Metadata\ApiProperty; @@ -50,6 +49,7 @@ use ApiPlatform\PathResolver\OperationPathResolver; use ApiPlatform\State\Pagination\PaginationOptions; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Container\ContainerInterface; diff --git a/tests/PathResolver/CustomOperationPathResolverTest.php b/tests/PathResolver/CustomOperationPathResolverTest.php deleted file mode 100644 index f486a00c93d..00000000000 --- a/tests/PathResolver/CustomOperationPathResolverTest.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * 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\Tests\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Tests\ProphecyTrait; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolverInterface; -use PHPUnit\Framework\TestCase; - -/** - * @author Baptiste Meyer - */ -class CustomOperationPathResolverTest extends TestCase -{ - use ProphecyTrait; - - public function testResolveOperationPath() - { - $operationPathResolver = new CustomOperationPathResolver($this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $this->assertEquals('/foos.{_format}', $operationPathResolver->resolveOperationPath('Foo', ['path' => '/foos.{_format}'], OperationType::COLLECTION, 'get')); - } - - public function testResolveOperationPathWithDeferred() - { - $operationPathResolverProphecy = $this->prophesize(OperationPathResolverInterface::class); - $operationPathResolverProphecy->resolveOperationPath('Foo', [], OperationType::ITEM, 'get')->willReturn('/foos/{id}.{_format}')->shouldBeCalled(); - - $operationPathResolver = new CustomOperationPathResolver($operationPathResolverProphecy->reveal()); - - $this->assertEquals('/foos/{id}.{_format}', $operationPathResolver->resolveOperationPath('Foo', [], OperationType::ITEM, 'get')); - } - - /** - * @group legacy - * @expectedDeprecation Method ApiPlatform\PathResolver\CustomOperationPathResolver::resolveOperationPath() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1. - */ - public function testLegacyResolveOperationPath() - { - $operationPathResolver = new CustomOperationPathResolver($this->prophesize(OperationPathResolverInterface::class)->reveal()); - - $this->assertEquals('/foos.{_format}', $operationPathResolver->resolveOperationPath('Foo', ['path' => '/foos.{_format}'], true)); - } -} diff --git a/tests/PathResolver/OperationPathResolverTest.php b/tests/PathResolver/OperationPathResolverTest.php deleted file mode 100644 index c70b5e9abcb..00000000000 --- a/tests/PathResolver/OperationPathResolverTest.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\Tests\PathResolver; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\PathResolver\OperationPathResolver; -use PHPUnit\Framework\TestCase; - -class OperationPathResolverTest extends TestCase -{ - public function testResolveItemOperationPath() - { - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - $this->assertEquals('/foos/{id}.{_format}', $operationPathResolver->resolveOperationPath('Foo', [], OperationType::ITEM, 'get')); - } - - public function testResolveItemOperationPathIdentifiedBy() - { - $operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator()); - $this->assertSame('/short_names/{isbn}.{_format}', $operationPathResolver->resolveOperationPath('ShortName', ['identifiers' => ['isbn']], OperationType::ITEM, 'get')); - } -} diff --git a/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php b/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php index 248207daed7..44d21b3153b 100644 --- a/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php +++ b/tests/Problem/Serializer/ConstraintViolationNormalizerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Problem\Serializer; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Problem\Serializer\ConstraintViolationListNormalizer; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; diff --git a/tests/ProphecyTrait.php b/tests/ProphecyTrait.php new file mode 100644 index 00000000000..6bc57c772a3 --- /dev/null +++ b/tests/ProphecyTrait.php @@ -0,0 +1,135 @@ + + * + * 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\Tests; + +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\TestCase; +use Prophecy\Exception\Doubler\DoubleException; +use Prophecy\Exception\Doubler\InterfaceNotFoundException; +use Prophecy\Exception\Prediction\PredictionException; +use Prophecy\Prophecy\MethodProphecy; +use Prophecy\Prophecy\ObjectProphecy; +use Prophecy\Prophet; + +/** + * Copied and adapted from phpspec/prophecy-phpunit. + * To replace by the official package when we'll drop support for PHP 7.1. + * + * @see https://github.com/phpspec/prophecy-phpunit + * + * @copyright Christophe Coevoet + * @author Christophe Coevoet + * @mixin TestCase + */ +trait ProphecyTrait +{ + /** + * @var Prophet|null + * + * @internal + */ + private $prophet; + + /** + * @var bool + * + * @internal + */ + private $prophecyAssertionsCounted = false; + + /** + * @psalm-param class-string|null $classOrInterface + * + * @param mixed|null $classOrInterface + * + * @throws DoubleException + * @throws InterfaceNotFoundException + */ + protected function prophesize($classOrInterface = null): ObjectProphecy + { + if ( + \is_string($classOrInterface) && + \is_callable([$this, 'recordDoubledType']) // Support for PHPUnit 7 + ) { + \assert($this instanceof TestCase); + $this->recordDoubledType($classOrInterface); + } + + return $this->getProphet()->prophesize($classOrInterface); + } + + /** + * @postCondition + * @after + */ + protected function verifyProphecyDoubles(): void + { + if (null === $this->prophet) { + return; + } + + try { + $this->prophet->checkPredictions(); + } catch (PredictionException $e) { + throw new AssertionFailedError($e->getMessage()); + } finally { + $this->countProphecyAssertions(); + } + } + + /** + * @after + */ + protected function tearDownProphecy(): void + { + if (null !== $this->prophet && !$this->prophecyAssertionsCounted) { + // Some Prophecy assertions may have been done in tests themselves even when a failure happened before checking mock objects. + $this->countProphecyAssertions(); + } + + $this->prophet = null; + } + + /** + * @internal + */ + private function countProphecyAssertions(): void + { + \assert($this instanceof TestCase); + $this->prophecyAssertionsCounted = true; + + foreach ($this->prophet->getProphecies() as $objectProphecy) { + /** @var MethodProphecy[] $methodProphecies */ + foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) { + foreach ($methodProphecies as $methodProphecy) { + \assert($methodProphecy instanceof MethodProphecy); + + $this->addToAssertionCount(\count($methodProphecy->getCheckedPredictions())); + } + } + } + } + + /** + * @internal + */ + private function getProphet(): Prophet + { + if (null === $this->prophet) { + $this->prophet = new Prophet(); + } + + return $this->prophet; + } +} diff --git a/tests/Serializer/AbstractItemNormalizerTest.php b/tests/Serializer/AbstractItemNormalizerTest.php index 683cb29adb9..7557ac07b3d 100644 --- a/tests/Serializer/AbstractItemNormalizerTest.php +++ b/tests/Serializer/AbstractItemNormalizerTest.php @@ -13,41 +13,25 @@ namespace ApiPlatform\Tests\Serializer; -use ApiPlatform\Api\IriConverterInterface as NewIriConverterInterface; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyForAdditionalFields; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyForAdditionalFieldsInput; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SecuredDummy; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Collections\ArrayCollection; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Exception\UnexpectedValueException; @@ -60,45 +44,12 @@ /** * @author Amrouche Hamza * @author Kévin Dunglas - * @group legacy */ class AbstractItemNormalizerTest extends TestCase { use ExpectDeprecationTrait; use ProphecyTrait; - /** - * @group legacy - */ - public function testLegacySupportNormalizationAndSupportDenormalization() - { - $std = new \stdClass(); - $dummy = new Dummy(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true)->shouldBeCalled(); - $resourceClassResolverProphecy->isResourceClass(\stdClass::class)->willReturn(false)->shouldBeCalled(); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - ]); - - $this->assertTrue($normalizer->supportsNormalization($dummy)); - $this->assertFalse($normalizer->supportsNormalization($std)); - $this->assertTrue($normalizer->supportsDenormalization($dummy, Dummy::class)); - $this->assertFalse($normalizer->supportsDenormalization($std, \stdClass::class)); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - public function testSupportNormalizationAndSupportDenormalization() { $std = new \stdClass(); @@ -121,9 +72,6 @@ public function testSupportNormalizationAndSupportDenormalization() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -162,8 +110,8 @@ public function testNormalize() $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(true)->withWritable(false)->withReadableLink(false)); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); - $iriConverterProphecy->getIriFromItem($relatedDummy)->willReturn('/dummies/2'); + $iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($relatedDummy, Argument::cetera())->willReturn('/dummies/2'); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->getValue($dummy, 'name')->willReturn('foo'); @@ -190,9 +138,6 @@ public function testNormalize() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -228,7 +173,7 @@ public function testNormalizeWithSecuredProperty() $propertyMetadataFactoryProphecy->create(SecuredDummy::class, 'adminOnlyProperty', [])->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(true)->withSecurity('is_granted(\'ROLE_ADMIN\')')); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/secured_dummies/1'); + $iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/secured_dummies/1'); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->getValue($dummy, 'title')->willReturn('myPublicTitle'); @@ -257,9 +202,6 @@ public function testNormalizeWithSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -318,9 +260,6 @@ public function testDenormalizeWithSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -375,9 +314,6 @@ public function testDenormalizeCreateWithDeniedPostDenormalizeSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -440,9 +376,6 @@ public function testDenormalizeUpdateWithSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -506,9 +439,6 @@ public function testDenormalizeUpdateWithDeniedSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -568,9 +498,6 @@ public function testDenormalizeUpdateWithDeniedPostDenormalizeSecuredProperty() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, $resourceAccessChecker->reveal(), @@ -608,7 +535,7 @@ public function testNormalizeReadableLinks() $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(true)->withWritable(false)->withReadableLink(true)); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/dummies/1'); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->getValue($dummy, 'relatedDummy')->willReturn($relatedDummy); @@ -640,9 +567,6 @@ public function testNormalizeReadableLinks() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -682,8 +606,8 @@ public function testDenormalize() $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(false)->withWritable(true)->withReadableLink(false)->withWritableLink(false)); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getItemFromIri('/dummies/1', Argument::type('array'))->willReturn($relatedDummy1); - $iriConverterProphecy->getItemFromIri('/dummies/2', Argument::type('array'))->willReturn($relatedDummy2); + $iriConverterProphecy->getResourceFromIri('/dummies/1', Argument::type('array'))->willReturn($relatedDummy1); + $iriConverterProphecy->getResourceFromIri('/dummies/2', Argument::type('array'))->willReturn($relatedDummy2); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); @@ -704,9 +628,6 @@ public function testDenormalize() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -724,57 +645,57 @@ public function testDenormalize() public function testCanDenormalizeInputClassWithDifferentFieldsThanResourceClass() { - $data = [ - 'dummyName' => 'Dummy Name', - ]; - - $context = [ - 'resource_class' => DummyForAdditionalFields::class, - 'input' => ['class' => DummyForAdditionalFieldsInput::class], - 'output' => ['class' => DummyForAdditionalFields::class], - ]; - $augmentedContext = $context + ['api_denormalize' => true]; - - $preHydratedDummy = new DummyForAdditionalFieldsInput('Name Dummy'); - $cleanedContext = array_diff_key($augmentedContext, [ - 'input' => null, - 'resource_class' => null, - ]); - $cleanedContextWithObjectToPopulate = array_merge($cleanedContext, [ - AbstractObjectNormalizer::OBJECT_TO_POPULATE => $preHydratedDummy, - AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => true, - ]); - - $dummyInputDto = new DummyForAdditionalFieldsInput('Dummy Name'); - $dummy = new DummyForAdditionalFields('Dummy Name', 'name-dummy'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, DummyForAdditionalFields::class)->willReturn(DummyForAdditionalFields::class); - - $inputDataTransformerProphecy = $this->prophesize(DataTransformerInitializerInterface::class); - $inputDataTransformerProphecy->willImplement(DataTransformerInitializerInterface::class); - $inputDataTransformerProphecy->initialize(DummyForAdditionalFieldsInput::class, $cleanedContext)->willReturn($preHydratedDummy); - $inputDataTransformerProphecy->supportsTransformation($data, DummyForAdditionalFields::class, $augmentedContext)->willReturn(true); - $inputDataTransformerProphecy->transform($dummyInputDto, DummyForAdditionalFields::class, $augmentedContext)->willReturn($dummy); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - $serializerProphecy->denormalize($data, DummyForAdditionalFieldsInput::class, 'json', $cleanedContextWithObjectToPopulate)->willReturn($dummyInputDto); - - $normalizer = new class($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), null, null, null, null, false, [], [$inputDataTransformerProphecy->reveal()], null, null) extends AbstractItemNormalizer { - }; - $normalizer->setSerializer($serializerProphecy->reveal()); - - $actual = $normalizer->denormalize($data, DummyForAdditionalFields::class, 'json', $context); - - $this->assertInstanceOf(DummyForAdditionalFields::class, $actual); - $this->assertEquals('Dummy Name', $actual->getName()); + // $data = [ + // 'dummyName' => 'Dummy Name', + // ]; + // + // $context = [ + // 'resource_class' => DummyForAdditionalFields::class, + // 'input' => ['class' => DummyForAdditionalFieldsInput::class], + // 'output' => ['class' => DummyForAdditionalFields::class], + // ]; + // $augmentedContext = $context + ['api_denormalize' => true]; + // + // $preHydratedDummy = new DummyForAdditionalFieldsInput('Name Dummy'); + // $cleanedContext = array_diff_key($augmentedContext, [ + // 'input' => null, + // 'resource_class' => null, + // ]); + // $cleanedContextWithObjectToPopulate = array_merge($cleanedContext, [ + // AbstractObjectNormalizer::OBJECT_TO_POPULATE => $preHydratedDummy, + // AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => true, + // ]); + // + // $dummyInputDto = new DummyForAdditionalFieldsInput('Dummy Name'); + // $dummy = new DummyForAdditionalFields('Dummy Name', 'name-dummy'); + // + // $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + // + // $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + // + // $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); + // + // $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + // $resourceClassResolverProphecy->getResourceClass(null, DummyForAdditionalFields::class)->willReturn(DummyForAdditionalFields::class); + // + // $inputDataTransformerProphecy = $this->prophesize(DataTransformerInitializerInterface::class); + // $inputDataTransformerProphecy->willImplement(DataTransformerInitializerInterface::class); + // $inputDataTransformerProphecy->initialize(DummyForAdditionalFieldsInput::class, $cleanedContext)->willReturn($preHydratedDummy); + // $inputDataTransformerProphecy->supportsTransformation($data, DummyForAdditionalFields::class, $augmentedContext)->willReturn(true); + // $inputDataTransformerProphecy->transform($dummyInputDto, DummyForAdditionalFields::class, $augmentedContext)->willReturn($dummy); + // + // $serializerProphecy = $this->prophesize(SerializerInterface::class); + // $serializerProphecy->willImplement(DenormalizerInterface::class); + // $serializerProphecy->denormalize($data, DummyForAdditionalFieldsInput::class, 'json', $cleanedContextWithObjectToPopulate)->willReturn($dummyInputDto); + // + // $normalizer = new class($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), null, null, null, [], null, null) extends AbstractItemNormalizer { + // }; + // $normalizer->setSerializer($serializerProphecy->reveal()); + // + // $actual = $normalizer->denormalize($data, DummyForAdditionalFields::class, 'json', $context); + // + // $this->assertInstanceOf(DummyForAdditionalFields::class, $actual); + // $this->assertEquals('Dummy Name', $actual->getName()); } public function testDenormalizeWritableLinks() @@ -822,9 +743,6 @@ public function testDenormalizeWritableLinks() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -878,9 +796,6 @@ public function testBadRelationType() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -930,9 +845,6 @@ public function testInnerDocumentNotAllowed() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -976,9 +888,6 @@ public function testBadType() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1019,9 +928,6 @@ public function testTypeChecksCanBeDisabled() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1066,9 +972,6 @@ public function testJsonAllowIntAsFloat() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1137,9 +1040,6 @@ public function testDenormalizeBadKeyType() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1180,9 +1080,6 @@ public function testNullable() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1196,356 +1093,6 @@ public function testNullable() $propertyAccessorProphecy->setValue($actual, 'name', null)->shouldHaveBeenCalled(); } - /** - * @group legacy - */ - public function testChildInheritedProperty(): void - { - $dummy = new DummyTableInheritance(); - $dummy->setName('foo'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(DummyTableInheritance::class, [])->willReturn( - new PropertyNameCollection(['name', 'nickname']) - )->shouldBeCalled(); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(DummyTableInheritance::class, 'name', [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), '', true) - )->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(DummyTableInheritance::class, 'nickname', [])->willReturn( - new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING, true), '', true, true, false, false, false, false, null, DummyTableInheritanceChild::class) - )->shouldBeCalled(); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1')->shouldBeCalled(); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - $propertyAccessorProphecy->getValue($dummy, 'name')->willReturn('foo')->shouldBeCalled(); - $propertyAccessorProphecy->getValue($dummy, 'nickname')->willThrow(new NoSuchPropertyException())->shouldBeCalled(); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($dummy, DummyTableInheritance::class)->willReturn(DummyTableInheritance::class)->shouldBeCalled(); - $resourceClassResolverProphecy->isResourceClass(DummyTableInheritance::class)->willReturn(true)->shouldBeCalled(); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(NormalizerInterface::class); - $serializerProphecy->normalize('foo', null, Argument::type('array'))->willReturn('foo')->shouldBeCalled(); - $serializerProphecy->normalize(null, null, Argument::type('array'))->willReturn(null)->shouldBeCalled(); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - null, - false, - [], - [], - null, - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $this->assertEquals([ - 'name' => 'foo', - 'nickname' => null, - ], $normalizer->normalize($dummy, null, ['resource_class' => DummyTableInheritance::class, 'resources' => []])); - } - - /** - * TODO: to remove in 3.0. - * - * @group legacy - */ - public function testDenormalizeRelationWithPlainId() - { - $data = [ - 'relatedDummy' => 1, - ]; - - $relatedDummy = new RelatedDummy(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['relatedDummy'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), '', false, true, false, false)); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->willReturn($relatedDummy); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - $itemDataProviderProphecy->reveal(), - true, - [], - [], - null, - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $actual = $normalizer->denormalize($data, Dummy::class, 'jsonld'); - - $this->assertInstanceOf(Dummy::class, $actual); - - $propertyAccessorProphecy->setValue($actual, 'relatedDummy', $relatedDummy)->shouldHaveBeenCalled(); - } - - /** - * TODO: to remove in 3.0. - * - * @group legacy - */ - public function testDenormalizeRelationWithPlainIdNotFound() - { - $this->expectException(ItemNotFoundException::class); - $this->expectExceptionMessage(sprintf('Item not found for resource "%s" with id "1".', RelatedDummy::class)); - - $data = [ - 'relatedDummy' => 1, - ]; - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['relatedDummy'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn( - new PropertyMetadata( - new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), - '', - false, - true, - false, - false - ) - ); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->willReturn(null); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - $itemDataProviderProphecy->reveal(), - true, - [], - [], - null, - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $normalizer->denormalize($data, Dummy::class, 'jsonld'); - } - - /** - * TODO: to remove in 3.0. - */ - public function testDoNotDenormalizeRelationWithPlainIdWhenPlainIdentifiersAreNotAllowed() - { - $this->expectException(UnexpectedValueException::class); - $this->expectExceptionMessage('Expected IRI or nested document for attribute "relatedDummy", "integer" given.'); - - $data = [ - 'relatedDummy' => 1, - ]; - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['relatedDummy'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn( - new PropertyMetadata( - new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class), - '', - false, - true, - false, - false - ) - ); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - $itemDataProviderProphecy->getItem(RelatedDummy::class, 1, null, Argument::type('array'))->shouldNotBeCalled(); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - $itemDataProviderProphecy->reveal(), - false, - [], - [], - null, - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $normalizer->denormalize($data, Dummy::class, 'jsonld'); - } - - /** - * Test case: - * 1. Request `PUT {InputDto} /recover_password` - * 2. The `AbstractItemNormalizer` denormalizes the json representation of `{InputDto}` in a `RecoverPasswordInput` - * 3. The `DataTransformer` transforms this `InputDto` in a `Dummy` - * 4. Messenger is used, we send the `Dummy` - * 5. The handler receives a `{Dummy}` json representation and tries to denormalize it - * 6. Because it has an `input`, the `AbstractItemNormalizer` tries to denormalize it as a `InputDto` which is wrong, it's a `{Dummy}`. - * - * @group legacy - */ - public function testNormalizationWithDataTransformer() - { - $this->expectDeprecation('Since api-platform/core 2.7: The DataTransformer pattern is deprecated, use a Provider or a Processor and either use your input or return a new output there.'); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->willReturn(new PropertyNameCollection(['name'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(false)->withWritable(true)); - - $iriConverterProphecy = $this->prophesize(NewIriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - $resourceClassResolverProphecy->isResourceClass(InputDto::class)->willReturn(false); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - - $jsonInput = ['foo' => 'f', 'bar' => 8]; - $inputDto = new InputDto(); - $inputDto->foo = 'f'; - $inputDto->bar = 8; - $transformed = new Dummy(); - $context = [ - 'operation' => new Get(), - 'operation_type' => 'collection', - 'collection_operation_name' => 'post', - 'resource_class' => Dummy::class, - 'input' => [ - 'class' => InputDto::class, - 'name' => 'InputDto', - ], - 'output' => ['class' => 'null'], - 'api_denormalize' => true, // this is added by the normalizer - ]; - $cleanedContext = array_diff_key($context, [ - 'input' => null, - 'resource_class' => null, - ]); - - $secondJsonInput = ['name' => 'Dummy']; - $secondContext = ['api_denormalize' => true, 'resource_class' => Dummy::class]; - $secondTransformed = new Dummy(); - $secondTransformed->setName('Dummy'); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(DenormalizerInterface::class); - $serializerProphecy->denormalize($jsonInput, InputDto::class, 'jsonld', $cleanedContext)->willReturn($inputDto); - - $itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection( - Dummy::class, - [(new ApiResource())->withOperations(new Operations([(new Get())->withShortName('dummy')->withInput(['class' => InputDto::class])]))] - )); - - $dataTransformerProphecy = $this->prophesize(DataTransformerInterface::class); - $dataTransformerProphecy->supportsTransformation($jsonInput, Dummy::class, $context)->willReturn(true); - $dataTransformerProphecy->supportsTransformation($secondJsonInput, Dummy::class, $secondContext)->willReturn(false); - $dataTransformerProphecy->transform($inputDto, Dummy::class, $context)->willReturn($transformed); - - $secondDataTransformerProphecy = $this->prophesize(DataTransformerInterface::class); - $secondDataTransformerProphecy->supportsTransformation(Argument::any(), Dummy::class, Argument::any())->willReturn(false); - - $normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [ - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - null, - null, - $itemDataProviderProphecy->reveal(), - false, - [], - [$dataTransformerProphecy->reveal(), $secondDataTransformerProphecy->reveal()], - $resourceMetadataFactoryProphecy->reveal(), - null, - ]); - $normalizer->setSerializer($serializerProphecy->reveal()); - - // This is step 1-3, {InputDto} to Dummy - $this->assertEquals($transformed, $normalizer->denormalize($jsonInput, Dummy::class, 'jsonld', $context)); - - // Messenger sends {InputDto} - $actualDummy = $normalizer->denormalize($secondJsonInput, Dummy::class, 'jsonld'); - - $this->assertInstanceOf(Dummy::class, $actualDummy); - - $propertyAccessorProphecy->setValue($actualDummy, 'name', 'Dummy')->shouldHaveBeenCalled(); - } - public function testDenormalizeBasicTypePropertiesFromXml() { $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -1587,7 +1134,7 @@ public function testDenormalizeBasicTypePropertiesFromXml() $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'boolFalse2', false)->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'int1', 4711)->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'int2', -4711)->shouldBeCalled(); - $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'float1', Argument::approximate(123.456, 0.01))->shouldBeCalled(); + $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'float1', Argument::approximate(123.456, 0))->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'float2', Argument::approximate(-1.2344e56, 1))->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'float3', Argument::approximate(45E-6, 1))->shouldBeCalled(); $propertyAccessorProphecy->setValue(Argument::type(ObjectWithBasicProperties::class), 'floatNaN', Argument::that(static function (float $arg) { @@ -1611,9 +1158,6 @@ public function testDenormalizeBasicTypePropertiesFromXml() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, @@ -1685,9 +1229,6 @@ public function testDenormalizeCollectionDecodedFromXmlWithOneChild() $propertyAccessorProphecy->reveal(), null, null, - null, - false, - [], [], null, null, diff --git a/tests/Serializer/ItemNormalizerTest.php b/tests/Serializer/ItemNormalizerTest.php index 4dfcee3e340..7cbf7ae306d 100644 --- a/tests/Serializer/ItemNormalizerTest.php +++ b/tests/Serializer/ItemNormalizerTest.php @@ -13,18 +13,15 @@ namespace ApiPlatform\Tests\Serializer; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Tests\ProphecyTrait; -use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Serializer\ItemNormalizer; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; @@ -35,7 +32,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class ItemNormalizerTest extends TestCase { @@ -93,7 +89,7 @@ public function testNormalize() $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadata); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($dummy, Argument::cetera())->willReturn('/dummies/1'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class); @@ -107,15 +103,7 @@ public function testNormalize() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -142,20 +130,11 @@ public function testDenormalize() $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->willImplement(DenormalizerInterface::class); - $normalizer = new ItemNormalizer( $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -176,7 +155,7 @@ public function testDenormalizeWithIri() $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadata)->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getItemFromIri('/dummies/12', ['resource_class' => Dummy::class, 'api_allow_update' => true, 'fetch_data' => true])->shouldBeCalled(); + $iriConverterProphecy->getResourceFromIri('/dummies/12', ['resource_class' => Dummy::class, 'api_allow_update' => true, 'fetch_data' => true])->shouldBeCalled(); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class); @@ -189,15 +168,7 @@ public function testDenormalizeWithIri() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -226,15 +197,7 @@ public function testDenormalizeWithIdAndUpdateNotAllowed() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); $normalizer->denormalize(['id' => '12', 'name' => 'hello'], Dummy::class, null, $context); @@ -266,15 +229,7 @@ public function testDenormalizeWithIdAndNoResourceClass() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -283,51 +238,4 @@ public function testDenormalizeWithIdAndNoResourceClass() $this->assertSame('42', $object->getId()); $this->assertSame('hello', $object->getName()); } - - /** - * @group legacy - */ - public function testNormalizeWithDataTransformers() - { - $this->expectDeprecation('Since api-platform/core 2.7: The DataTransformer pattern is deprecated, use a Provider or a Processor and either use your input or return a new output there.'); - $dummy = new Dummy(); - $dummy->setName('hello'); - $output = new OutputDto(); - - $propertyNameCollection = new PropertyNameCollection(['baz']); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadata = new ApiProperty(null, null, true); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($output, null)->willThrow(InvalidArgumentException::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(NormalizerInterface::class); - $serializerProphecy->normalize(Argument::type(OutputDto::class), null, Argument::type('array'))->willReturn(['baz' => 'hello'])->shouldBeCalled(); - - $dataTransformer = $this->prophesize(DataTransformerInterface::class); - $dataTransformer->supportsTransformation($dummy, OutputDto::class, Argument::any())->shouldBeCalled()->willReturn(true); - $dataTransformer->transform($dummy, OutputDto::class, Argument::any())->shouldBeCalled()->willReturn($output); - - $normalizer = new ItemNormalizer( - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [$dataTransformer->reveal()], - null - ); - $normalizer->setSerializer($serializerProphecy->reveal()); - - $this->assertEquals(['baz' => 'hello'], $normalizer->normalize($dummy, null, ['resources' => [], 'output' => ['class' => OutputDto::class]])); - } } diff --git a/tests/Serializer/LegacySerializerContextBuilderTest.php b/tests/Serializer/LegacySerializerContextBuilderTest.php deleted file mode 100644 index e516c531a1a..00000000000 --- a/tests/Serializer/LegacySerializerContextBuilderTest.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * 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\Tests\Serializer; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Tests\ProphecyTrait; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Serializer\SerializerContextBuilder; -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Request; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class LegacySerializerContextBuilderTest extends TestCase -{ - use ProphecyTrait; - - /** - * @var SerializerContextBuilder - */ - private $builder; - - protected function setUp(): void - { - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - [], - [], - [ - 'normalization_context' => ['foo' => 'bar', DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'MyDefinition'], - 'denormalization_context' => ['bar' => 'baz'], - ] - ); - - $resourceMetadataWithPatch = new ResourceMetadata( - null, - null, - null, - ['patch' => ['method' => 'PATCH', 'input_formats' => ['json' => ['application/merge-patch+json']]]], - [] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata); - $resourceMetadataFactoryProphecy->create('FooWithPatch')->willReturn($resourceMetadataWithPatch); - - $this->builder = new SerializerContextBuilder($resourceMetadataFactoryProphecy->reveal()); - } - - public function testCreateFromRequest() - { - $request = Request::create('/foos/1'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['foo' => 'bar', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, true)); - - $request = Request::create('/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'pot', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['foo' => 'bar', 'collection_operation_name' => 'pot', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, true)); - - $request = Request::create('/foos/1'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/foos', 'POST'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'collection_operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/foos', 'PUT'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'collection_operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/bars/1/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'subresource_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'operation_type' => 'subresource', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/foowithpatch/1', 'PATCH'); - $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_item_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $expected = ['item_operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'operation_type' => 'item', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - - $request = Request::create('/bars/1/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', '_api_subresource_context' => ['identifiers' => ['id' => ['Foo', 'id']]], 'id' => '1']); - $expected = ['bar' => 'baz', 'subresource_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'operation_type' => 'subresource', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'subresource_identifiers' => ['id' => '1'], 'subresource_resources' => ['Foo' => ['id' => '1']]]; - $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); - } - - public function testThrowExceptionOnInvalidRequest() - { - $this->expectException(RuntimeException::class); - - $this->builder->createFromRequest(new Request(), false); - } - - public function testReuseExistingAttributes() - { - $expected = ['bar' => 'baz', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'item_operation_name' => 'get'])); - } -} diff --git a/tests/Serializer/SerializerContextBuilderTest.php b/tests/Serializer/SerializerContextBuilderTest.php index 4c74636f37e..c7002b7d747 100644 --- a/tests/Serializer/SerializerContextBuilderTest.php +++ b/tests/Serializer/SerializerContextBuilderTest.php @@ -13,51 +13,49 @@ namespace ApiPlatform\Tests\Serializer; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\HttpOperation; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Serializer\SerializerContextBuilder; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; /** * @author Kévin Dunglas - * @group legacy */ class SerializerContextBuilderTest extends TestCase { use ProphecyTrait; - /** - * @var SerializerContextBuilder - */ - private $builder; + private SerializerContextBuilder $builder; + private HttpOperation $operation; + private HttpOperation $patchOperation; protected function setUp(): void { - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - [], - [], - [ - 'normalization_context' => ['foo' => 'bar', DocumentationNormalizer::SWAGGER_DEFINITION_NAME => 'MyDefinition'], - 'denormalization_context' => ['bar' => 'baz'], - ] - ); - - $resourceMetadataWithPatch = new ResourceMetadata( - null, - null, - null, - ['patch' => ['method' => 'PATCH', 'input_formats' => ['json' => ['application/merge-patch+json']]]], - [] - ); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $this->operation = new Get(normalizationContext: ['foo' => 'bar'], denormalizationContext: ['bar' => 'baz'], name: 'get'); + $resourceMetadata = new ResourceMetadataCollection('Foo', [ + new ApiResource(operations: [ + 'get' => $this->operation, + 'post' => $this->operation->withName('post'), + 'put' => $this->operation->withName('put')->withMethod(HttpOperation::METHOD_PUT), + 'get_collection' => $this->operation->withName('get_collection'), + ]), + ]); + + $this->patchOperation = new Patch(inputFormats: ['json' => ['application/merge-patch+json']], name: 'patch'); + $resourceMetadataWithPatch = new ResourceMetadataCollection('Foo', [ + new ApiResource(operations: [ + 'patch' => $this->patchOperation, + ]), + ]); + + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata); $resourceMetadataFactoryProphecy->create('FooWithPatch')->willReturn($resourceMetadataWithPatch); @@ -67,43 +65,43 @@ protected function setUp(): void public function testCreateFromRequest() { $request = Request::create('/foos/1'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['foo' => 'bar', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['foo' => 'bar', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation]; $this->assertEquals($expected, $this->builder->createFromRequest($request, true)); $request = Request::create('/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'pot', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['foo' => 'bar', 'collection_operation_name' => 'pot', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get_collection', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['foo' => 'bar', 'operation_name' => 'get_collection', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('get_collection')]; $this->assertEquals($expected, $this->builder->createFromRequest($request, true)); $request = Request::create('/foos/1'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/foos', 'POST'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'collection_operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['bar' => 'baz', 'operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('post')]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/foos', 'PUT'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'collection_operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'operation_type' => 'collection', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['bar' => 'baz', 'operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('put')->withMethod(HttpOperation::METHOD_PUT)]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/bars/1/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); - $expected = ['bar' => 'baz', 'subresource_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'operation_type' => 'subresource', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']); + $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/foowithpatch/1', 'PATCH'); - $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_item_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']); - $expected = ['item_operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'operation_type' => 'item', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false]; + $request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']); + $expected = ['operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchOperation]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); $request = Request::create('/bars/1/foos'); - $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', '_api_subresource_context' => ['identifiers' => ['id' => ['Foo', 'id']]], 'id' => '1']); - $expected = ['bar' => 'baz', 'subresource_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'operation_type' => 'subresource', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'subresource_identifiers' => ['id' => '1'], 'subresource_resources' => ['Foo' => ['id' => '1']]]; + $request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', '_api_subresource_context' => ['identifiers' => ['id' => ['Foo', 'id']]], 'id' => '1']); + $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'operation' => $this->operation, 'skip_null_values' => true]; $this->assertEquals($expected, $this->builder->createFromRequest($request, false)); } @@ -116,7 +114,7 @@ public function testThrowExceptionOnInvalidRequest() public function testReuseExistingAttributes() { - $expected = ['bar' => 'baz', 'item_operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'operation_type' => 'item', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false]; - $this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'item_operation_name' => 'get'])); + $expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation]; + $this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'operation_name' => 'get'])); } } diff --git a/tests/Serializer/SerializerFilterContextBuilderTest.php b/tests/Serializer/SerializerFilterContextBuilderTest.php index b429d6c6b82..a7e281774ea 100644 --- a/tests/Serializer/SerializerFilterContextBuilderTest.php +++ b/tests/Serializer/SerializerFilterContextBuilderTest.php @@ -14,21 +14,22 @@ namespace ApiPlatform\Tests\Serializer; use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Serializer\Filter\FilterInterface as SerializerFilterInterface; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Serializer\SerializerFilterContextBuilder; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyGroup; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Component\HttpFoundation\Request; /** * @author Baptiste Meyer - * @group legacy */ class SerializerFilterContextBuilderTest extends TestCase { @@ -40,21 +41,15 @@ public function testCreateFromRequestWithCollectionOperation() $attributes = [ 'resource_class' => DummyGroup::class, - 'collection_operation_name' => 'get', + 'operation_name' => 'get', ]; - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['filters' => ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']]] - ); + $resourceMetadata = $this->getMetadataWithFilter(DummyGroup::class, ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $decoratedProphecy->createFromRequest($request, true, $attributes)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyGroup::class)->willReturn($resourceMetadata)->shouldBeCalled(); $dummyGroupGroupFilterProphecy = $this->prophesize(SerializerFilterInterface::class); @@ -79,21 +74,14 @@ public function testCreateFromRequestWithItemOperation() $attributes = [ 'resource_class' => DummyGroup::class, - 'item_operation_name' => 'put', + 'operation_name' => 'get', ]; - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - ['put' => ['filters' => ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']]], - null - ); - + $resourceMetadata = $this->getMetadataWithFilter(DummyGroup::class, ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $decoratedProphecy->createFromRequest($request, true, $attributes)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyGroup::class)->willReturn($resourceMetadata)->shouldBeCalled(); $dummyGroupGroupFilterProphecy = $this->prophesize(SerializerFilterInterface::class); @@ -118,21 +106,15 @@ public function testCreateFromRequestWithoutFilters() $attributes = [ 'resource_class' => DummyGroup::class, - 'collection_operation_name' => 'get', + 'operation_name' => 'get', ]; - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - null, - ['get' => []] - ); + $resourceMetadata = $this->getMetadataWithFilter(DummyGroup::class, null); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $decoratedProphecy->createFromRequest($request, false, $attributes)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyGroup::class)->willReturn($resourceMetadata)->shouldBeCalled(); $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); @@ -145,33 +127,24 @@ public function testCreateFromRequestWithoutAttributes() { $request = new Request([], [], [ '_api_resource_class' => DummyGroup::class, - '_api_collection_operation_name' => 'get', + '_api_operation_name' => 'get', ]); $attributes = [ 'resource_class' => DummyGroup::class, - 'collection_operation_name' => 'get', - 'identifiers' => [ - 'id' => [DummyGroup::class, 'id'], - ], + 'operation_name' => 'get', 'has_composite_identifier' => false, 'receive' => true, 'respond' => true, 'persist' => true, ]; - $resourceMetadata = new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['filters' => ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']]] - ); + $resourceMetadata = $this->getMetadataWithFilter(DummyGroup::class, ['dummy_group.group', 'dummy_group.search', 'dummy_group.nonexistent']); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $decoratedProphecy->createFromRequest($request, true, $attributes)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(DummyGroup::class)->willReturn($resourceMetadata)->shouldBeCalled(); $dummyGroupGroupFilterProphecy = $this->prophesize(SerializerFilterInterface::class); @@ -197,11 +170,20 @@ public function testCreateFromRequestThrowsExceptionWithoutAttributesAndRequestA $request = new Request(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); $decoratedProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderFilter = new SerializerFilterContextBuilder($resourceMetadataFactoryProphecy->reveal(), $filterLocatorProphecy->reveal(), $decoratedProphecy->reveal()); $serializerContextBuilderFilter->createFromRequest($request, true); } + + private function getMetadataWithFilter(string $class, ?array $filters = null): ResourceMetadataCollection + { + return new ResourceMetadataCollection($class, [ + new ApiResource(operations: [ + 'get' => new Get(name: 'get', filters: $filters), + ]), + ]); + } } diff --git a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php index ab58f4ddf11..a298918a51c 100644 --- a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php +++ b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; diff --git a/tests/Symfony/Bundle/ApiPlatformBundleTest.php b/tests/Symfony/Bundle/ApiPlatformBundleTest.php index b8212639307..d6123c7e127 100644 --- a/tests/Symfony/Bundle/ApiPlatformBundleTest.php +++ b/tests/Symfony/Bundle/ApiPlatformBundleTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Symfony\Bundle; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; @@ -26,6 +25,7 @@ use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\PassConfig; diff --git a/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php b/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php index 22eb66ebaf1..aab2eb2e472 100644 --- a/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php +++ b/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Symfony\Bundle\ArgumentResolver; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Post; @@ -24,6 +23,7 @@ use ApiPlatform\Symfony\Bundle\ArgumentResolver\PayloadArgumentResolver; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ResourceImplementation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ResourceInterface; +use ApiPlatform\Tests\ProphecyTrait; use Prophecy\Argument; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php b/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php index 8d6146a7f1d..d1259193e87 100644 --- a/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php +++ b/tests/Symfony/Bundle/Command/DebugResourceCommandTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Symfony\Bundle\Command; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory; use ApiPlatform\Symfony\Bundle\Command\DebugResourceCommand; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Console\Application; diff --git a/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php b/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php index 361ee1b85e2..3c9e1680b7c 100644 --- a/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php +++ b/tests/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php @@ -25,12 +25,12 @@ use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Symfony\Bundle\DataCollector\RequestDataCollector; use ApiPlatform\Tests\Fixtures\DummyEntity; +use ApiPlatform\Tests\ProphecyTrait; use PackageVersions\Versions; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 234751ac9f0..b556217ce99 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -21,7 +21,6 @@ use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; use ApiPlatform\Core\DataTransformer\DataTransformerInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; @@ -48,6 +47,7 @@ use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\TestBundle; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Doctrine\Common\Annotations\Annotation; use Doctrine\ORM\OptimisticLockException; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php index 0827f6feef0..8b2fe8fbf9f 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Doctrine\Orm\Filter\DateFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Serializer\Filter\GroupFilter; @@ -25,6 +24,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Filter\DoesNotImplementInterfaceFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\NoConstructorFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Filter\NoPropertiesArgumentFilter; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Annotations\Reader; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php index 2c8e25fe0e9..037f1f449a8 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php index bb90f141431..91dee4d93d9 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\BaseNode; use Symfony\Component\DependencyInjection\Alias; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php index 857f3c06dab..20f12bb6dc5 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass; +use ApiPlatform\Tests\ProphecyTrait; use Elasticsearch\ClientBuilder; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php index 12268852108..5b6ae6d21d7 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/FilterPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php index c5beea4e75f..90de196c0ea 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php index c35837cbb2a..0bc4d0d9b80 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlQueryResolverPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php index 49dcecbd7ea..bdd99a8c72c 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php index c09e1c41eaf..f5eddcd8974 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPassTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php index 38597b36ed7..4990ad14e92 100644 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/TestClientPassTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Bundle\DependencyInjection\Compiler; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; use ApiPlatform\Symfony\Bundle\Test\Client; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; diff --git a/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php b/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php index 82fe83b4f59..8ab04043adb 100644 --- a/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php +++ b/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\Bundle\EventListener; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Bundle\EventListener\SwaggerUiListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php b/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php index d077c4f9d59..596be0e4524 100644 --- a/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php +++ b/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Documentation\DocumentationInterface; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Model\Info; @@ -24,6 +23,7 @@ use ApiPlatform\OpenApi\Options; use ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction; use ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiContext; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/AddFormatListenerTest.php b/tests/Symfony/EventListener/AddFormatListenerTest.php index a1f9614ab6a..98d325089d1 100644 --- a/tests/Symfony/EventListener/AddFormatListenerTest.php +++ b/tests/Symfony/EventListener/AddFormatListenerTest.php @@ -16,8 +16,8 @@ use ApiPlatform\Core\Api\FormatsProviderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\AddFormatListener; +use ApiPlatform\Tests\ProphecyTrait; use Negotiation\Negotiator; use PHPUnit\Framework\TestCase; use Prophecy\Argument; diff --git a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php index 1aaa4e2ea15..77bc4c24f2c 100644 --- a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\AddLinkHeaderListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; use PHPUnit\Framework\TestCase; diff --git a/tests/Symfony/EventListener/DenyAccessListenerTest.php b/tests/Symfony/EventListener/DenyAccessListenerTest.php index 83fa7cf99ed..5050a51649c 100644 --- a/tests/Symfony/EventListener/DenyAccessListenerTest.php +++ b/tests/Symfony/EventListener/DenyAccessListenerTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\DenyAccessListener; use ApiPlatform\Symfony\Security\ExpressionLanguage; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; use ApiPlatform\Tests\Fixtures\Serializable; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/DeserializeListenerTest.php b/tests/Symfony/EventListener/DeserializeListenerTest.php index 72639475b90..89fff6ef9d3 100644 --- a/tests/Symfony/EventListener/DeserializeListenerTest.php +++ b/tests/Symfony/EventListener/DeserializeListenerTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Core\Api\FormatsProviderInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\DeserializeListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/ExceptionListenerTest.php b/tests/Symfony/EventListener/ExceptionListenerTest.php index fc493db27db..0df0d81f307 100644 --- a/tests/Symfony/EventListener/ExceptionListenerTest.php +++ b/tests/Symfony/EventListener/ExceptionListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\ExceptionListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php index 3eb0634c68e..0843ea0e342 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php index fff92f5477c..751e6761fbd 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformFilteringParametersListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformFilteringParametersListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php index 566c22d314c..c8d74aea832 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformPaginationParametersListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php index c938650f2fe..5c88b6d16d0 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformSortingParametersListenerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\JsonApi\TransformSortingParametersListener; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; diff --git a/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php b/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php index f7cba02b1ba..fe56e285333 100644 --- a/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php +++ b/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php @@ -16,10 +16,10 @@ use ApiPlatform\Core\Filter\QueryParameterValidator; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Symfony\EventListener\QueryParameterValidateListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/ReadListenerTest.php b/tests/Symfony/EventListener/ReadListenerTest.php index 993b616dc04..ba9b23a0739 100644 --- a/tests/Symfony/EventListener/ReadListenerTest.php +++ b/tests/Symfony/EventListener/ReadListenerTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Symfony\EventListener; use ApiPlatform\Api\UriVariablesConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; @@ -26,6 +25,7 @@ use ApiPlatform\State\ProviderInterface; use ApiPlatform\Symfony\EventListener\ReadListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/RespondListenerTest.php b/tests/Symfony/EventListener/RespondListenerTest.php index 42b438c5e92..b60cee1fb06 100644 --- a/tests/Symfony/EventListener/RespondListenerTest.php +++ b/tests/Symfony/EventListener/RespondListenerTest.php @@ -15,9 +15,9 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\EventListener\RespondListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/Symfony/EventListener/SerializeListenerTest.php b/tests/Symfony/EventListener/SerializeListenerTest.php index f97f90498f1..ece915bed83 100644 --- a/tests/Symfony/EventListener/SerializeListenerTest.php +++ b/tests/Symfony/EventListener/SerializeListenerTest.php @@ -15,11 +15,11 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Serializer\ResourceList; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\SerializeListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/EventListener/WriteListenerTest.php b/tests/Symfony/EventListener/WriteListenerTest.php index c7fc05654d9..da8f5f2363d 100644 --- a/tests/Symfony/EventListener/WriteListenerTest.php +++ b/tests/Symfony/EventListener/WriteListenerTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Core\Api\ResourceClassResolverInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -31,6 +30,7 @@ use ApiPlatform\Symfony\EventListener\WriteListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\OperationResource; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/Messenger/ProcessorTest.php b/tests/Symfony/Messenger/ProcessorTest.php index d73221f38ec..7822ef2eb0b 100644 --- a/tests/Symfony/Messenger/ProcessorTest.php +++ b/tests/Symfony/Messenger/ProcessorTest.php @@ -13,13 +13,13 @@ namespace ApiPlatform\Tests\Symfony\Messenger; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; use ApiPlatform\Symfony\Messenger\ContextStamp; use ApiPlatform\Symfony\Messenger\Processor; use ApiPlatform\Symfony\Messenger\RemoveStamp; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Messenger\Envelope; diff --git a/tests/Symfony/Routing/ApiLoaderTest.php b/tests/Symfony/Routing/ApiLoaderTest.php index 0cf4ff6177c..9bbb901173e 100644 --- a/tests/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Symfony/Routing/ApiLoaderTest.php @@ -18,7 +18,6 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; @@ -37,6 +36,7 @@ use ApiPlatform\Tests\Fixtures\DummyEntity; use ApiPlatform\Tests\Fixtures\RelatedDummyEntity; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\DependencyInjection\ContainerInterface; diff --git a/tests/Symfony/Routing/IriConverterTest.php b/tests/Symfony/Routing/IriConverterTest.php index d5a0ad25362..79049d83a30 100644 --- a/tests/Symfony/Routing/IriConverterTest.php +++ b/tests/Symfony/Routing/IriConverterTest.php @@ -17,7 +17,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; @@ -30,6 +29,7 @@ use ApiPlatform\State\ProviderInterface; use ApiPlatform\Symfony\Routing\IriConverter; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Routing\RouterInterface; diff --git a/tests/Symfony/Routing/RouterTest.php b/tests/Symfony/Routing/RouterTest.php index 1581d262539..b5ca68ae3b9 100644 --- a/tests/Symfony/Routing/RouterTest.php +++ b/tests/Symfony/Routing/RouterTest.php @@ -14,8 +14,8 @@ namespace ApiPlatform\Tests\Symfony\Routing; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Routing\Router; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Routing\Exception\ExceptionInterface as RoutingExceptionInterface; diff --git a/tests/Symfony/Security/ResourceAccessCheckerTest.php b/tests/Symfony/Security/ResourceAccessCheckerTest.php index 4ad3e77a64b..3c84d9af89f 100644 --- a/tests/Symfony/Security/ResourceAccessCheckerTest.php +++ b/tests/Symfony/Security/ResourceAccessCheckerTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Symfony\Security; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Security\ExpressionLanguage; use ApiPlatform\Symfony\Security\ResourceAccessChecker; use ApiPlatform\Tests\Fixtures\Serializable; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php index 1f84cd554d4..b676c1c1e10 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaChoiceRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php index ad3b94451de..896a0e11bd6 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCollectionRestrictionTest.php @@ -13,12 +13,12 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaCollectionRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLengthRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Collection; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php index 16d29412e77..5ca4edb02f5 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaCountRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaCountRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Count; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php index a68f6f43301..a9ea787ee13 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaFormatTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaFormat; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Email; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php index 077c1b46233..7a3ddca2b60 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanOrEqualRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaGreaterThanOrEqualRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php index f2f55fd4a73..9bf4bc22cf0 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaGreaterThanRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php index 57d3bb16d06..acca8dfe383 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanOrEqualRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLessThanOrEqualRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php index ca9c984c781..3607ae329a1 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLessThanRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php index 058d090a6d6..3168c1bf9ac 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaOneOfRestrictionTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaLengthRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaOneOfRestriction; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php index c432bbe79ad..70e3bc0c285 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRangeRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRangeRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Validator\Constraint; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php index 1ccb9f209c0..e7fa1ecfc96 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaRegexRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRegexRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Positive; diff --git a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php index 4fa6393e82c..58f94bea1f3 100644 --- a/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php +++ b/tests/Symfony/Validator/Metadata/Property/Restriction/PropertySchemaUniqueRestrictionTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property\Restriction; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaUniqueRestriction; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Positive; diff --git a/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php b/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php index 5f261dbff53..89ca7ae97e7 100644 --- a/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php +++ b/tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Symfony\Validator\Metadata\Property; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction; @@ -43,6 +42,7 @@ use ApiPlatform\Tests\Fixtures\DummyValidatedEntity; use ApiPlatform\Tests\Fixtures\DummyValidatedHostnameEntity; use ApiPlatform\Tests\Fixtures\DummyValidatedUlidEntity; +use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Type; diff --git a/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php b/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php index 719c473a02c..a5bab52138b 100644 --- a/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php +++ b/tests/Symfony/Validator/Metadata/ValidationExceptionListenerTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Symfony\Validator\EventListener; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Symfony\Validator\EventListener\ValidationExceptionListener; use ApiPlatform\Symfony\Validator\Exception\ConstraintViolationListAwareExceptionInterface; use ApiPlatform\Symfony\Validator\Exception\ValidationException; +use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Validator\Exception\ValidationException as BaseValidationException; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Symfony/Validator/Metadata/ValidatorTest.php b/tests/Symfony/Validator/Metadata/ValidatorTest.php index de1651acf04..9e72faf6cc1 100644 --- a/tests/Symfony/Validator/Metadata/ValidatorTest.php +++ b/tests/Symfony/Validator/Metadata/ValidatorTest.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Tests\Symfony\Validator; -use ApiPlatform\Tests\ProphecyTrait; use ApiPlatform\Symfony\Validator\Exception\ValidationException; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; use ApiPlatform\Symfony\Validator\Validator; use ApiPlatform\Tests\Fixtures\DummyEntity; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Component\Validator\ConstraintViolationListInterface; From 0483444c7f7a763835f2ab4dd5faa7d6fe706db0 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 12 May 2022 16:36:30 +0200 Subject: [PATCH 08/56] chore stuff --- .github/workflows/ci.yml | 407 +-------------------------------------- behat.yml.dist | 128 ++++++------ composer.json | 9 +- phpunit.xml.dist | 5 - 4 files changed, 71 insertions(+), 478 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a0199050ce..1e9700c08cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,11 +98,6 @@ jobs: strategy: matrix: php: - - '7.1' - - '7.2' - - '7.3' - - '7.4' - - '8.0' - '8.1' include: - php: '8.1' @@ -131,16 +126,9 @@ jobs: - name: Enable code coverage if: matrix.coverage run: echo "COVERAGE=1" >> $GITHUB_ENV - - name: Remove Doctrine MongoDB ODM - if: (startsWith(matrix.php, '7.1')) - run: | - composer remove --dev --no-interaction --no-progress --no-update --ansi \ - doctrine/mongodb-odm \ - doctrine/mongodb-odm-bundle - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony components - if: (!startsWith(matrix.php, '7.1')) run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - name: Install PHPUnit run: vendor/bin/simple-phpunit --version @@ -154,9 +142,6 @@ jobs: else vendor/bin/simple-phpunit --log-junit build/logs/phpunit/junit.xml fi - - name: Run PHPUnit 8.1+ tests - if: (startsWith(matrix.php, '8.1')) - run: ./vendor/bin/simple-phpunit --stop-on-failure tests/Metadata/Resource/Factory/ - name: Upload test artifacts if: always() uses: actions/upload-artifact@v1 @@ -189,11 +174,6 @@ jobs: strategy: matrix: php: - - '7.1' - - '7.2' - - '7.3' - - '7.4' - - '8.0' - '8.1' include: - php: '8.1' @@ -222,40 +202,15 @@ jobs: - name: Enable code coverage if: matrix.coverage run: echo "COVERAGE=1" >> $GITHUB_ENV - - name: Remove Doctrine MongoDB ODM - if: startsWith(matrix.php, '7.1') - run: | - composer remove --dev --no-interaction --no-progress --no-update --ansi \ - doctrine/mongodb-odm \ - doctrine/mongodb-odm-bundle - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony components - if: (!startsWith(matrix.php, '7.1')) run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - name: Install PHPUnit run: vendor/bin/simple-phpunit --version - name: Clear test app cache - if: (!startsWith(matrix.php, '8.')) run: tests/Fixtures/app/console cache:clear --ansi - - name: Clear test app cache (php 8.0) - if: (startsWith(matrix.php, '8.')) - run: rm -Rf tests/Fixtures/app/var/cache/* - - name: Run Behat tests (PHP < 8) - if: (!startsWith(matrix.php, '8.')) - run: | - mkdir -p build/logs/behat - if [ "$COVERAGE" = '1' ]; then - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default-coverage --no-interaction --tags='~@php8' - else - if [ "${{ matrix.php }}" = '7.1' ]; then - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@symfony/uid&&~@php8' - else - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@php8' - fi - fi - name: Run Behat tests (PHP 8) - if: (startsWith(matrix.php, '8.')) run: | mkdir -p build/logs/behat if [ "$COVERAGE" = '1' ]; then @@ -320,87 +275,6 @@ jobs: path: build/out/openapi continue-on-error: true - phpunit-lowest: - name: PHPUnit (PHP ${{ matrix.php }} lowest) - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '7.4' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring - coverage: none - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Require Symfony components - run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi --no-update - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi --prefer-lowest - - name: Clear test app cache - run: tests/Fixtures/app/console cache:clear --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Run PHPUnit tests - run: vendor/bin/simple-phpunit - - behat-lowest: - name: Behat (PHP ${{ matrix.php }} lowest) - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '7.4' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite - coverage: none - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Require Symfony components - run: composer require symfony/intl symfony/uid --dev --no-interaction --no-progress --ansi --no-update - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi --prefer-lowest - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: tests/Fixtures/app/console cache:clear --ansi - - name: Run Behat tests - # @TODO remove the tag "@symfony/uid" in 3.0 - run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction --tags='~@symfony/uid&&~php8' - postgresql: name: Behat (PHP ${{ matrix.php }}) (PostgreSQL) runs-on: ubuntu-latest @@ -408,7 +282,7 @@ jobs: strategy: matrix: php: - - '7.4' + - '8.1' fail-fast: false env: APP_ENV: postgres @@ -459,7 +333,7 @@ jobs: strategy: matrix: php: - - '7.4' + - '8.1' fail-fast: false services: mysql: @@ -510,7 +384,7 @@ jobs: strategy: matrix: php: - - '8' + - '8.1' fail-fast: false env: APP_ENV: mongodb @@ -596,8 +470,6 @@ jobs: strategy: matrix: php: - - '7.4' - - '8.0' - '8.1' fail-fast: false env: @@ -650,7 +522,7 @@ jobs: strategy: matrix: php: - - '7.4' + - '8.1' fail-fast: false env: SYMFONY_DEPRECATIONS_HELPER: max[total]=0 @@ -779,148 +651,6 @@ jobs: - name: Run Behat tests run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction - behat-rector-upgrade: - name: Behat (PHP ${{ matrix.php }}) (upgrade script) - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '8.1' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi - - name: Require Symfony components - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: rm -Rf tests/Fixtures/app/var/cache/* - - name: Convert metadata to API Platform 3 - run: | - tests/Fixtures/app/console api:upgrade-resource -f - - name: Apply behat features patch (IRIs update) - run: | - git apply .github/patch/v3_features.patch - - name: clear test app cache - run: rm -rf tests/Fixtures/app/var/cache/* - - name: Run Behat tests - run: | - mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction - - name: Upload test artifacts - if: always() - uses: actions/upload-artifact@v1 - with: - name: behat-logs-php${{ matrix.php }} - path: build/logs/behat - continue-on-error: true - - name: Export OpenAPI documents - run: | - mkdir -p build/out/openapi - tests/Fixtures/app/console api:openapi:export --spec-version=2 -o build/out/openapi/swagger_v2.json - tests/Fixtures/app/console api:openapi:export --spec-version=2 --yaml -o build/out/openapi/swagger_v2.yaml - tests/Fixtures/app/console api:openapi:export --spec-version=3 -o build/out/openapi/openapi_v3.json - tests/Fixtures/app/console api:openapi:export --spec-version=3 --yaml -o build/out/openapi/openapi_v3.yaml - - name: Setup node - uses: actions/setup-node@v2 - with: - node-version: '14' - - name: Validate OpenAPI documents - run: | - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/swagger_v2.json - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/swagger_v2.yaml - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/openapi_v3.json - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/openapi_v3.yaml - - name: Upload OpenAPI artifacts - if: always() - uses: actions/upload-artifact@v1 - with: - name: openapi-docs-php${{ matrix.php }} - path: build/out/openapi - continue-on-error: true - - behat-rector-upgrade-mongodb: - name: Behat (PHP ${{ matrix.php }}) (upgrade script / MongoDB) - runs-on: ubuntu-latest - env: - APP_ENV: mongodb - MONGODB_URL: mongodb://localhost:27017 - timeout-minutes: 20 - strategy: - matrix: - php: - - '8.1' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Check - run: | - sudo systemctl start mongod.service - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, mongodb - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi - - name: Require Symfony components - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: rm -Rf tests/Fixtures/app/var/cache/* - - name: Convert metadata to API Platform 3 - run: | - tests/Fixtures/app/console api:upgrade-resource -f - - name: Apply behat features patch (IRIs update) - run: | - git apply .github/patch/v3_features.patch - - name: Clear test app cache - run: rm -Rf tests/Fixtures/app/var/cache/* - - name: Run Behat tests - run: | - mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=mongodb --no-interaction - - name: Upload test artifacts - if: always() - uses: actions/upload-artifact@v1 - with: - name: behat-logs-php${{ matrix.php }} - path: build/logs/behat - continue-on-error: true - windows-phpunit: name: Windows PHPUnit (PHP ${{ matrix.php }}) (SQLite) runs-on: windows-latest @@ -928,8 +658,6 @@ jobs: strategy: matrix: php: - - '7.4' - - '8.0' - '8.1' fail-fast: false env: @@ -955,10 +683,6 @@ jobs: path: ${{ steps.composercache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- - - name: Set Composer platform config - if: (startsWith(matrix.php, '8.')) - run: | - composer config platform.php 7.4.99 - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony components @@ -977,8 +701,6 @@ jobs: strategy: matrix: php: - - '7.4' - - '8.0' - '8.1' fail-fast: false env: @@ -1004,10 +726,6 @@ jobs: path: ${{ steps.composercache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- - - name: Set Composer platform config - if: (startsWith(matrix.php, '8.')) - run: | - composer config platform.php 7.4.99 - name: Update project dependencies run: composer update --no-interaction --no-progress --ansi - name: Require Symfony components @@ -1017,119 +735,4 @@ jobs: - name: Clear test app cache run: tests/Fixtures/app/console cache:clear --ansi - name: Run Behat tests - run: | - if ( "${{ matrix.php }}" -eq '7.4' ) { - vendor/bin/behat --out=std --format=progress --profile=default --no-interaction --tags='~@php8' - } else { - vendor/bin/behat --out=std --format=progress --profile=default --no-interaction - } - - phpunit_legacy_metadata: - name: PHPUnit (PHP ${{ matrix.php }}) 2.7 BC layer - env: - METADATA_BACKWARD_COMPATIBILITY_LAYER: 1 - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '7.4' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite - coverage: pcov - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi - - name: Require Symfony components - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: tests/Fixtures/app/console cache:clear --ansi - - name: Run PHPUnit tests - run: | - mkdir -p build/logs/phpunit - vendor/bin/simple-phpunit --log-junit build/logs/phpunit/junit.xml - - behat_legacy_metadata: - name: Behat (PHP ${{ matrix.php }}) 2.7 BC layer - env: - METADATA_BACKWARD_COMPATIBILITY_LAYER: 1 - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - matrix: - php: - - '7.4' - fail-fast: false - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: pecl, composer - extensions: intl, bcmath, curl, openssl, mbstring, pdo_sqlite - coverage: pcov - ini-values: memory_limit=-1 - - name: Get composer cache directory - id: composercache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composercache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Update project dependencies - run: composer update --no-interaction --no-progress --ansi - - name: Require Symfony components - run: composer require symfony/uid --dev --no-interaction --no-progress --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: tests/Fixtures/app/console cache:clear --ansi - - name: Run Behat tests - run: | - mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@php8' --tags='~@v3' - - name: Run Behat tests (PHP 8) - if: (startsWith(matrix.php, '8.')) - run: | - mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction - - name: Export OpenAPI documents - run: | - mkdir -p build/out/openapi - tests/Fixtures/app/console api:openapi:export --spec-version=2 -o build/out/openapi/swagger_v2.json - tests/Fixtures/app/console api:openapi:export --spec-version=2 --yaml -o build/out/openapi/swagger_v2.yaml - tests/Fixtures/app/console api:openapi:export --spec-version=3 -o build/out/openapi/openapi_v3.json - tests/Fixtures/app/console api:openapi:export --spec-version=3 --yaml -o build/out/openapi/openapi_v3.yaml - - name: Setup node - uses: actions/setup-node@v2 - with: - node-version: '14' - - name: Validate OpenAPI documents - run: | - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/swagger_v2.json - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/swagger_v2.yaml - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/openapi_v3.json - npx git+https://github.com/soyuka/swagger-cli#master validate build/out/openapi/openapi_v3.yaml + run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction diff --git a/behat.yml.dist b/behat.yml.dist index 2ecdb71e7c6..7675928087b 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -2,17 +2,17 @@ default: suites: default: contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -38,17 +38,17 @@ postgres: default: false postgres: &postgres-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -59,17 +59,17 @@ mongodb: default: false mongodb: &mongodb-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -82,9 +82,9 @@ elasticsearch: paths: - '%paths.base%/features/elasticsearch' contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\ElasticsearchContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\ElasticsearchContext' + - 'ApiPlatform\Tests\Behat\JsonContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -94,18 +94,18 @@ default-coverage: suites: default: &default-coverage-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\CoverageContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' @@ -115,18 +115,18 @@ mongodb-coverage: mongodb: &mongodb-coverage-suite <<: *mongodb-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' - - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\HydraContext' - - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' - - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' - - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' - - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - - 'ApiPlatform\Core\Tests\Behat\MercureContext' - - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\HydraContext' + - 'ApiPlatform\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Tests\Behat\MercureContext' + - 'ApiPlatform\Tests\Behat\CoverageContext' + - 'ApiPlatform\Tests\Behat\XmlContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' @@ -136,9 +136,9 @@ elasticsearch-coverage: elasticsearch: &elasticsearch-coverage-suite <<: *elasticsearch-suite contexts: - - 'ApiPlatform\Core\Tests\Behat\CommandContext' - - 'ApiPlatform\Core\Tests\Behat\ElasticsearchContext' - - 'ApiPlatform\Core\Tests\Behat\JsonContext' - - 'ApiPlatform\Core\Tests\Behat\CoverageContext' + - 'ApiPlatform\Tests\Behat\CommandContext' + - 'ApiPlatform\Tests\Behat\ElasticsearchContext' + - 'ApiPlatform\Tests\Behat\JsonContext' + - 'ApiPlatform\Tests\Behat\CoverageContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' diff --git a/composer.json b/composer.json index 5826a3a7400..f17c1ee757f 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,6 @@ "require-dev": { "behat/behat": "^3.1", "behat/mink": "^1.9@dev", - "doctrine/annotations": "^1.7", "doctrine/cache": "^1.11 || ^2.1", "doctrine/common": "^2.11 || ^3.0", "doctrine/data-fixtures": "^1.2.2", @@ -115,14 +114,10 @@ "autoload": { "psr-4": { "ApiPlatform\\": "src/" - }, - "files": [ - "src/deprecation.php" - ] + } }, "autoload-dev": { "psr-4": { - "ApiPlatform\\Core\\Tests\\": "tests/Core/", "ApiPlatform\\Tests\\": "tests/", "App\\": "tests/Fixtures/app/var/tmp/src/" } @@ -139,7 +134,7 @@ }, "extra": { "branch-alias": { - "dev-main": "2.7.x-dev" + "dev-main": "3.0.x-dev" }, "symfony": { "require": "^3.4 || ^4.4 || ^5.1 || ^6.0" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b687076cfda..b73ea695c19 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,8 +16,6 @@ tests - tests/Metadata/Resource/Factory - tests/Metadata/Resource/Factory @@ -29,9 +27,6 @@ features tests vendor - src/Core/Bridge/NelmioApiDoc - src/Core/Bridge/FosUser - src/Core/Bridge/Symfony/Maker/Resources/skeleton .php-cs-fixer.dist.php src/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php From 5fcab2bb3138d063f1981fe4e2321d97ac039acc Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 13 May 2022 10:07:36 +0200 Subject: [PATCH 09/56] doctrine odm to attributes --- .../TestBundle/Document/AbsoluteUrlDummy.php | 12 ++--- .../Document/AbsoluteUrlRelationDummy.php | 12 ++--- .../TestBundle/Document/AbstractDummy.php | 14 +++--- .../Fixtures/TestBundle/Document/Address.php | 12 ++--- tests/Fixtures/TestBundle/Document/Answer.php | 19 ++----- .../Document/ArrayFilterValidator.php | 8 ++- tests/Fixtures/TestBundle/Document/Book.php | 14 ++---- .../TestBundle/Document/CircularReference.php | 14 ++---- .../Fixtures/TestBundle/Document/Comment.php | 22 ++------ .../Fixtures/TestBundle/Document/Company.php | 10 ++-- .../TestBundle/Document/CompositeItem.php | 15 ++---- .../TestBundle/Document/CompositeLabel.php | 11 ++-- .../Document/CompositePrimitiveItem.php | 21 ++------ .../TestBundle/Document/CompositeRelation.php | 19 ++----- .../TestBundle/Document/ConcreteDummy.php | 5 +- .../Document/ContainNonResource.php | 7 +-- .../Fixtures/TestBundle/Document/Content.php | 26 +++------- .../TestBundle/Document/ConvertedBoolean.php | 11 ++-- .../TestBundle/Document/ConvertedDate.php | 11 ++-- .../TestBundle/Document/ConvertedInteger.php | 11 ++-- .../TestBundle/Document/ConvertedOwner.php | 11 ++-- .../TestBundle/Document/ConvertedRelated.php | 11 ++-- .../TestBundle/Document/ConvertedString.php | 11 ++-- .../TestBundle/Document/CustomActionDummy.php | 11 ++-- .../Document/CustomGeneratedIdentifier.php | 7 +-- .../Document/CustomIdentifierDummy.php | 9 ++-- .../CustomMultipleIdentifierDummy.php | 12 ++--- .../Document/CustomNormalizedDummy.php | 11 ++-- .../CustomWritableIdentifierDummy.php | 9 ++-- .../Fixtures/TestBundle/Document/Customer.php | 16 ++---- .../Document/DeprecatedResource.php | 10 ++-- .../Document/DisableItemOperation.php | 11 ++-- tests/Fixtures/TestBundle/Document/Dummy.php | 50 +++++++------------ .../Document/DummyAggregateOffer.php | 15 ++---- .../TestBundle/Document/DummyBoolean.php | 13 ++--- .../Fixtures/TestBundle/Document/DummyCar.php | 35 ++++--------- .../TestBundle/Document/DummyCarColor.php | 15 ++---- .../TestBundle/Document/DummyCustomFormat.php | 10 ++-- .../Document/DummyCustomMutation.php | 19 ++----- .../TestBundle/Document/DummyCustomQuery.php | 5 +- .../TestBundle/Document/DummyDate.php | 17 +++---- ...ummyDifferentGraphQlSerializationGroup.php | 11 ++-- .../TestBundle/Document/DummyDtoCustom.php | 12 ++--- .../Document/DummyDtoInputOutput.php | 10 ++-- .../TestBundle/Document/DummyDtoNoInput.php | 11 ++-- .../TestBundle/Document/DummyDtoNoOutput.php | 11 ++-- .../DummyDtoOutputFallbackToSameClass.php | 11 ++-- .../Document/DummyDtoOutputSameClass.php | 11 ++-- .../Document/DummyEntityWithConstructor.php | 19 ++----- .../TestBundle/Document/DummyFriend.php | 8 ++- .../TestBundle/Document/DummyGroup.php | 18 +++---- .../Document/DummyImmutableDate.php | 9 ++-- .../TestBundle/Document/DummyMercure.php | 19 ++----- .../TestBundle/Document/DummyOffer.php | 11 ++-- .../TestBundle/Document/DummyPassenger.php | 12 ++--- .../TestBundle/Document/DummyProduct.php | 20 +++----- .../TestBundle/Document/DummyProperty.php | 24 +++------ .../Document/DummyTableInheritance.php | 25 +++------- .../Document/DummyTableInheritanceChild.php | 7 +-- .../DummyTableInheritanceDifferentChild.php | 7 +-- ...mmyTableInheritanceNotApiResourceChild.php | 7 +-- .../Document/DummyTableInheritanceRelated.php | 10 ++-- .../TestBundle/Document/DummyTravel.php | 20 ++------ .../TestBundle/Document/DummyValidation.php | 15 ++---- ...mmyWithEmbedManyOmittingTargetDocument.php | 10 ++-- .../TestBundle/Document/EmbeddableDummy.php | 27 +++------- .../TestBundle/Document/EmbeddedDummy.php | 17 +++---- .../Fixtures/TestBundle/Document/Employee.php | 13 ++--- tests/Fixtures/TestBundle/Document/Field.php | 23 ++------- .../TestBundle/Document/FileConfigDummy.php | 15 ++---- .../TestBundle/Document/FilterValidator.php | 8 ++- tests/Fixtures/TestBundle/Document/Foo.php | 11 ++-- .../Fixtures/TestBundle/Document/FooDummy.php | 11 ++-- .../TestBundle/Document/FourthLevel.php | 13 ++--- .../Fixtures/TestBundle/Document/Greeting.php | 20 ++------ .../TestBundle/Document/InitializeInput.php | 16 ++---- .../TestBundle/Document/IriOnlyDummy.php | 9 ++-- .../Document/JsonldContextDummy.php | 6 +-- .../Document/LegacySecuredDummy.php | 15 ++---- .../TestBundle/Document/MaxDepthDummy.php | 14 ++---- .../Document/MaxDepthEagerDummy.php | 14 ++---- .../TestBundle/Document/NetworkPathDummy.php | 12 ++--- .../Document/NetworkPathRelationDummy.php | 12 ++--- .../TestBundle/Document/NoCollectionDummy.php | 6 +-- tests/Fixtures/TestBundle/Document/Order.php | 16 ++---- .../Document/OverriddenOperationDummy.php | 18 +++---- .../TestBundle/Document/ParentDummy.php | 6 +-- .../TestBundle/Document/PatchDummy.php | 10 ++-- .../Document/PatchDummyRelation.php | 10 ++-- .../Fixtures/TestBundle/Document/Payment.php | 12 ++--- tests/Fixtures/TestBundle/Document/Person.php | 17 ++----- .../TestBundle/Document/PersonToPet.php | 14 ++---- tests/Fixtures/TestBundle/Document/Pet.php | 13 ++--- .../TestBundle/Document/ProcessorEntity.php | 11 ++-- .../Fixtures/TestBundle/Document/Product.php | 18 ++----- .../Fixtures/TestBundle/Document/Program.php | 22 ++------ .../TestBundle/Document/ProviderEntity.php | 11 ++-- .../Fixtures/TestBundle/Document/Question.php | 16 ++---- .../Document/ReadableOnlyProperty.php | 10 ++-- .../TestBundle/Document/RelatedDummy.php | 30 ++++------- .../Document/RelatedNormalizedDummy.php | 11 ++-- .../TestBundle/Document/RelatedOwnedDummy.php | 11 ++-- .../Document/RelatedOwningDummy.php | 11 ++-- .../Document/RelatedSecuredDummy.php | 7 +-- .../Document/RelatedToDummyFriend.php | 21 +++----- .../TestBundle/Document/RelationEmbedder.php | 22 +++----- .../Document/ResourceWithBoolean.php | 11 ++-- .../TestBundle/Document/ResourceWithFloat.php | 11 ++-- .../Document/ResourceWithInteger.php | 11 ++-- .../Document/ResourceWithString.php | 11 ++-- .../TestBundle/Document/SecuredDummy.php | 39 +++++---------- .../Document/SingleFileConfigDummy.php | 10 ++-- .../TestBundle/Document/SlugChildDummy.php | 14 ++---- .../TestBundle/Document/SlugParentDummy.php | 12 ++--- tests/Fixtures/TestBundle/Document/SoMany.php | 12 ++--- tests/Fixtures/TestBundle/Document/Taxon.php | 13 ++--- .../TestBundle/Document/ThirdLevel.php | 21 +++----- .../TestBundle/Document/UrlEncodedId.php | 6 +-- tests/Fixtures/TestBundle/Document/User.php | 9 ++-- .../Document/UuidIdentifierDummy.php | 9 ++-- .../TestBundle/Document/VoDummyCar.php | 15 ++---- .../TestBundle/Document/VoDummyDriver.php | 14 ++---- .../Document/VoDummyIdAwareTrait.php | 3 +- .../TestBundle/Document/VoDummyInspection.php | 16 ++---- .../Document/VoDummyInsuranceCompany.php | 9 +--- .../TestBundle/Document/VoDummyVehicle.php | 17 ++----- .../TestBundle/Document/VoidPayment.php | 13 ++--- .../TestBundle/Document/WithJsonDummy.php | 11 ++-- .../TestBundle/Document/WritableId.php | 10 ++-- 129 files changed, 517 insertions(+), 1259 deletions(-) diff --git a/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php b/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php index b2abc40bb2f..5e9f22fdecf 100644 --- a/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php @@ -19,20 +19,14 @@ use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] #[ApiResource(uriTemplate: '/absolute_url_relation_dummies/{id}/absolute_url_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\AbsoluteUrlRelationDummy::class, identifiers: ['id'], toProperty: 'absoluteUrlRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::ABS_URL, operations: [new GetCollection()])] +#[ODM\Document] class AbsoluteUrlDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\ReferenceOne(targetDocument=AbsoluteUrlRelationDummy::class, inversedBy="absoluteUrlDummies", storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: AbsoluteUrlRelationDummy::class, inversedBy: 'absoluteUrlDummies', storeAs: 'id')] public $absoluteUrlRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php b/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php index 094858ae290..8c1684f8eee 100644 --- a/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbsoluteUrlRelationDummy.php @@ -18,19 +18,13 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)] +#[ODM\Document] class AbsoluteUrlRelationDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\ReferenceMany(targetDocument=AbsoluteUrlDummy::class, mappedBy="absoluteUrlRelationDummy") - */ + #[ODM\ReferenceMany(targetDocument: AbsoluteUrlDummy::class, mappedBy: 'absoluteUrlRelationDummy')] public $absoluteUrlDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/AbstractDummy.php b/tests/Fixtures/TestBundle/Document/AbstractDummy.php index fe958a27a1d..69c55c89dd8 100644 --- a/tests/Fixtures/TestBundle/Document/AbstractDummy.php +++ b/tests/Fixtures/TestBundle/Document/AbstractDummy.php @@ -27,27 +27,25 @@ * Abstract Dummy. * * @author Jérémy Derussé - * @ODM\Document - * @ODM\InheritanceType ("SINGLE_COLLECTION") - * @ODM\DiscriminatorField (value="discr") - * @ODM\DiscriminatorMap ({"concrete"=ConcreteDummy::class}) */ #[ApiResource(operations: [new Get(), new Put(), new Delete(), new GetCollection(), new Post()], filters: ['my_dummy.mongodb.search', 'my_dummy.mongodb.order', 'my_dummy.mongodb.date'])] +#[ODM\Document] +#[ODM\InheritanceType('SINGLE_COLLECTION')] +#[ODM\DiscriminatorField(value: 'discr')] +#[ODM\DiscriminatorMap(['concrete' => ConcreteDummy::class])] abstract class AbstractDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string The dummy name - * - * @ODM\Field */ #[ApiProperty(types: ['http://schema.org/name'])] #[Assert\NotBlank] + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Address.php b/tests/Fixtures/TestBundle/Document/Address.php index fc51a941aab..7d2bf5c19a2 100644 --- a/tests/Fixtures/TestBundle/Document/Address.php +++ b/tests/Fixtures/TestBundle/Document/Address.php @@ -17,21 +17,15 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource(normalizationContext: ['groups' => ['order_read']])] +#[ODM\Document] class Address { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups(['order_read'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="string") - */ #[Groups(['order_read'])] + #[ODM\Field(type: 'string')] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Answer.php b/tests/Fixtures/TestBundle/Document/Answer.php index ed3628b8762..3865bc862f4 100644 --- a/tests/Fixtures/TestBundle/Document/Answer.php +++ b/tests/Fixtures/TestBundle/Document/Answer.php @@ -27,33 +27,24 @@ /** * Answer. - * - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(normalizationContext: ['groups' => ['foobar']])])] #[ApiResource(uriTemplate: '/answers/{id}/related_questions/{relatedQuestions}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], toProperty: 'answer'), 'relatedQuestions' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/questions/{id}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])] +#[ODM\Document] class Answer { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Serializer\Groups(['foobar'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(nullable=false) - */ #[Serializer\Groups(['foobar'])] + #[ODM\Field(nullable: false)] private $content; - /** - * @ODM\ReferenceOne(targetDocument=Question::class, mappedBy="answer") - */ #[Serializer\Groups(['foobar'])] + #[ODM\ReferenceOne(targetDocument: Question::class, mappedBy: 'answer')] private $question; - /** - * @ODM\ReferenceMany(targetDocument=Question::class, mappedBy="answer") - */ #[Serializer\Groups(['foobar'])] + #[ODM\ReferenceMany(targetDocument: Question::class, mappedBy: 'answer')] private $relatedQuestions; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php b/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php index e62e876b234..cc6eb675783 100644 --- a/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php +++ b/tests/Fixtures/TestBundle/Document/ArrayFilterValidator.php @@ -23,24 +23,22 @@ * * @author Julien Deniau * @author Alan Poulain - * @ODM\Document */ #[ApiResource(filters: [ArrayRequiredFilter::class])] +#[ODM\Document] class ArrayFilterValidator { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string A name - * - * @ODM\Field */ #[ApiProperty(types: ['http://schema.org/name'])] + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Book.php b/tests/Fixtures/TestBundle/Document/Book.php index bdb4a82304e..e95179ce536 100644 --- a/tests/Fixtures/TestBundle/Document/Book.php +++ b/tests/Fixtures/TestBundle/Document/Book.php @@ -21,22 +21,16 @@ * Book. * * @author Antoine Bluchet - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Get(uriTemplate: '/books/by_isbn/{isbn}.{_format}', requirements: ['isbn' => '.+'], uriVariables: 'isbn')])] +#[ODM\Document] class Book { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(type="string", nullable=true) - */ + #[ODM\Field(type: 'string', nullable: true)] public $name; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $isbn; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/CircularReference.php b/tests/Fixtures/TestBundle/Document/CircularReference.php index c52b4586bc3..8aed20583fc 100644 --- a/tests/Fixtures/TestBundle/Document/CircularReference.php +++ b/tests/Fixtures/TestBundle/Document/CircularReference.php @@ -22,24 +22,18 @@ * Circular Reference. * * @author Kévin Dunglas - * @ODM\Document */ #[ApiResource(normalizationContext: ['groups' => ['circular']])] +#[ODM\Document] class CircularReference { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - /** - * @ODM\ReferenceOne(targetDocument=CircularReference::class, inversedBy="children") - */ #[Groups(['circular'])] + #[ODM\ReferenceOne(targetDocument: self::class, inversedBy: 'children')] public $parent; - /** - * @ODM\ReferenceMany(targetDocument=CircularReference::class, mappedBy="parent") - */ #[Groups(['circular'])] + #[ODM\ReferenceMany(targetDocument: self::class, mappedBy: 'parent')] public $children; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/Comment.php b/tests/Fixtures/TestBundle/Document/Comment.php index 340f4eed62d..af77b18ad73 100644 --- a/tests/Fixtures/TestBundle/Document/Comment.php +++ b/tests/Fixtures/TestBundle/Document/Comment.php @@ -17,29 +17,17 @@ /** * @author Vincent Chalamon - * - * @ODM\Document */ +#[ODM\Document] class Comment { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $comment; - - /** - * @ODM\Field(type="date") - */ + #[ODM\Field(type: 'date')] public $date; - - /** - * @ODM\ReferenceOne(targetDocument=User::class, storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: User::class, storeAs: 'id')] public $author; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Company.php b/tests/Fixtures/TestBundle/Document/Company.php index f38341eaf07..e2eda4cbefb 100644 --- a/tests/Fixtures/TestBundle/Document/Company.php +++ b/tests/Fixtures/TestBundle/Document/Company.php @@ -19,29 +19,25 @@ use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] #[Get] #[Post] #[ApiResource(uriTemplate: '/employees/{employeeId}/rooms/{roomId}/company/{companyId}', uriVariables: ['employeeId' => ['from_class' => Employee::class, 'from_property' => 'company']])] #[Get] #[ApiResource(uriTemplate: '/employees/{employeeId}/company', uriVariables: ['employeeId' => ['from_class' => Employee::class, 'from_property' => 'company']])] +#[ODM\Document] class Company { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] public $name; /** @var Employee[] */ diff --git a/tests/Fixtures/TestBundle/Document/CompositeItem.php b/tests/Fixtures/TestBundle/Document/CompositeItem.php index 6488716a36f..bc6e90fbe0e 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeItem.php +++ b/tests/Fixtures/TestBundle/Document/CompositeItem.php @@ -19,25 +19,18 @@ /** * Composite Item. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class CompositeItem implements \Stringable { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(type="string", nullable=true) - */ #[Groups(['default'])] + #[ODM\Field(type: 'string', nullable: true)] private $field1; - /** - * @ODM\ReferenceMany(targetDocument=CompositeRelation::class, mappedBy="compositeItem") - */ #[Groups(['default'])] + #[ODM\ReferenceMany(targetDocument: CompositeRelation::class, mappedBy: 'compositeItem')] private $compositeValues; /** diff --git a/tests/Fixtures/TestBundle/Document/CompositeLabel.php b/tests/Fixtures/TestBundle/Document/CompositeLabel.php index 8ca472ef76c..dccf6d23f4a 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeLabel.php +++ b/tests/Fixtures/TestBundle/Document/CompositeLabel.php @@ -19,20 +19,15 @@ /** * Composite Label. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class CompositeLabel implements \Stringable { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(type="string", nullable=true) - */ #[Groups(['default'])] + #[ODM\Field(type: 'string', nullable: true)] private $value; /** diff --git a/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php b/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php index c1c04a10194..e447ed1aebe 100644 --- a/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php +++ b/tests/Fixtures/TestBundle/Document/CompositePrimitiveItem.php @@ -18,30 +18,19 @@ /** * Composite Primitive Item. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class CompositePrimitiveItem { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private $description; public function __construct( - /** - * @ODM\Field(type="string") - */ - private readonly string $name, - /** - * @ODM\Field(type="int") - */ - private readonly int $year + #[ODM\Field(type: 'string')] private readonly string $name, + #[ODM\Field(type: 'int')] private readonly int $year ) { } diff --git a/tests/Fixtures/TestBundle/Document/CompositeRelation.php b/tests/Fixtures/TestBundle/Document/CompositeRelation.php index fd6fc8b3cde..a4c82989161 100644 --- a/tests/Fixtures/TestBundle/Document/CompositeRelation.php +++ b/tests/Fixtures/TestBundle/Document/CompositeRelation.php @@ -19,30 +19,21 @@ /** * Composite Relation. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class CompositeRelation { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(type="string", nullable=true) - */ #[Groups(['default'])] + #[ODM\Field(type: 'string', nullable: true)] private $value; - /** - * @ODM\ReferenceOne(targetDocument=CompositeItem::class, inversedBy="compositeValues") - */ #[Groups(['default'])] + #[ODM\ReferenceOne(targetDocument: CompositeItem::class, inversedBy: 'compositeValues')] private $compositeItem; - /** - * @ODM\ReferenceOne(targetDocument=CompositeLabel::class) - */ #[Groups(['default'])] + #[ODM\ReferenceOne(targetDocument: CompositeLabel::class)] private $compositeLabel; /** diff --git a/tests/Fixtures/TestBundle/Document/ConcreteDummy.php b/tests/Fixtures/TestBundle/Document/ConcreteDummy.php index c24bf00a2b8..41794c1cb00 100644 --- a/tests/Fixtures/TestBundle/Document/ConcreteDummy.php +++ b/tests/Fixtures/TestBundle/Document/ConcreteDummy.php @@ -21,17 +21,16 @@ * Concrete Dummy. * * @author Jérémy Derusse - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class ConcreteDummy extends AbstractDummy { /** * @var string a concrete thing - * - * @ODM\Field */ #[Assert\NotBlank] + #[ODM\Field] private $instance; public function setInstance($instance) diff --git a/tests/Fixtures/TestBundle/Document/ContainNonResource.php b/tests/Fixtures/TestBundle/Document/ContainNonResource.php index 52147b7f4a4..b24ef937dd4 100644 --- a/tests/Fixtures/TestBundle/Document/ContainNonResource.php +++ b/tests/Fixtures/TestBundle/Document/ContainNonResource.php @@ -21,17 +21,14 @@ /** * Resource linked to a standard object. * - * @ODM\Document - * * @author Kévin Dunglas */ #[ApiResource(filters: ['my_dummy.property'], normalizationContext: ['groups' => ['contain_non_resource']])] +#[ODM\Document] class ContainNonResource { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups('contain_non_resource')] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; /** * @var ContainNonResource diff --git a/tests/Fixtures/TestBundle/Document/Content.php b/tests/Fixtures/TestBundle/Document/Content.php index 5783f66e55c..f02394c102e 100644 --- a/tests/Fixtures/TestBundle/Document/Content.php +++ b/tests/Fixtures/TestBundle/Document/Content.php @@ -20,34 +20,20 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource(normalizationContext: ['groups' => ['get_content']])] +#[ODM\Document] class Content implements \JsonSerializable { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private ?string $contentType = null; /** * @var Collection - * - * @ODM\ReferenceMany( - * targetDocument=Field::class, - * mappedBy="content", - * strategy="set", - * cascade={"persist"}, - * ) - */ - private $fields; - /** - * @ODM\Field(type="string") */ + #[ODM\ReferenceMany(targetDocument: Field::class, mappedBy: 'content', strategy: 'set', cascade: ['persist'])] + private \Doctrine\Common\Collections\Collection & iterable $fields; + #[ODM\Field(type: 'string')] private readonly string $status; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php index 8d0a6babd95..009438126f7 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedBoolean.php @@ -18,22 +18,17 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiFilter(BooleanFilter::class)] #[ApiResource] +#[ODM\Document] class ConvertedBoolean { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var bool - * - * @ODM\Field(type="bool") */ + #[ODM\Field(type: 'bool')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedDate.php b/tests/Fixtures/TestBundle/Document/ConvertedDate.php index 8800e575059..e97203f21f9 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedDate.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedDate.php @@ -18,22 +18,17 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiFilter(DateFilter::class)] #[ApiResource] +#[ODM\Document] class ConvertedDate { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var \DateTime - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php index 406e3798ec1..e8e7675b5b6 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedInteger.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedInteger.php @@ -20,24 +20,19 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiFilter(NumericFilter::class, properties: ['nameConverted'])] #[ApiFilter(RangeFilter::class, properties: ['nameConverted'])] #[ApiFilter(OrderFilter::class, properties: ['nameConverted'])] #[ApiResource] +#[ODM\Document] class ConvertedInteger { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var int - * - * @ODM\Field(type="int") */ + #[ODM\Field(type: 'int')] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php index 791c30a1714..7a225498ac5 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedOwner.php @@ -18,22 +18,17 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiFilter(SearchFilter::class, properties: ['nameConverted.nameConverted' => 'partial'])] #[ApiResource] +#[ODM\Document] class ConvertedOwner { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var ConvertedRelated - * - * @ODM\ReferenceOne(targetDocument=ConvertedRelated::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceOne(targetDocument: ConvertedRelated::class, storeAs: 'id', nullable: true)] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedRelated.php b/tests/Fixtures/TestBundle/Document/ConvertedRelated.php index 4aa446cd698..e7b36afeb8c 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedRelated.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedRelated.php @@ -16,21 +16,16 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class ConvertedRelated { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ConvertedString.php b/tests/Fixtures/TestBundle/Document/ConvertedString.php index 526c7faccd8..e9c38df3ee4 100644 --- a/tests/Fixtures/TestBundle/Document/ConvertedString.php +++ b/tests/Fixtures/TestBundle/Document/ConvertedString.php @@ -18,22 +18,17 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiFilter(ExistsFilter::class, properties: ['nameConverted'])] #[ApiResource] +#[ODM\Document] class ConvertedString { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null - * - * @ODM\Field(type="string", nullable=true) */ + #[ODM\Field(type: 'string', nullable: true)] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/CustomActionDummy.php b/tests/Fixtures/TestBundle/Document/CustomActionDummy.php index 27554a98ef6..30323168e25 100644 --- a/tests/Fixtures/TestBundle/Document/CustomActionDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomActionDummy.php @@ -20,20 +20,15 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ODM\Document - * * @author Kévin Dunglas */ #[ApiResource(operations: [new Get(), new Get(uriTemplate: 'custom_action_collection_dummies/{id}'), new Get(routeName: 'custom_normalization'), new Get(routeName: 'short_custom_normalization'), new GetCollection(), new GetCollection(uriTemplate: 'custom_action_collection_dummies'), new Post(routeName: 'custom_denormalization'), new GetCollection(routeName: 'short_custom_denormalization')])] +#[ODM\Document] class CustomActionDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field - */ + #[ODM\Field] private string $foo = ''; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php b/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php index e5c19e2c381..22e134d951d 100644 --- a/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php +++ b/tests/Fixtures/TestBundle/Document/CustomGeneratedIdentifier.php @@ -18,15 +18,12 @@ /** * Custom identifier. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class CustomGeneratedIdentifier { - /** - * @ODM\Id(strategy="CUSTOM", type="string", options={"class"="ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\DocumentUuidGenerator"}) - */ + #[ODM\Id(strategy: 'CUSTOM', type: 'string', options: ['class' => \ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\DocumentUuidGenerator::class])] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Generator\Uuid $id = null; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php index 5a8fa46c684..7c419226bd6 100644 --- a/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomIdentifierDummy.php @@ -18,23 +18,20 @@ /** * Custom Identifier Dummy. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class CustomIdentifierDummy { /** * @var int The custom identifier - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $customId = null; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] private ?string $name = null; public function getCustomId(): int diff --git a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php index 146a9be0a25..f2aa4f849ab 100644 --- a/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomMultipleIdentifierDummy.php @@ -20,32 +20,28 @@ /** * Custom Identifier Dummy. - * - * @ODM\Document */ #[ApiResource(uriVariables: ['firstId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['firstId']), 'secondId' => new Link(compositeIdentifier: false, fromClass: self::class, identifiers: ['secondId'])])] +#[ODM\Document] class CustomMultipleIdentifierDummy { /** * @var int The custom identifier - * - * @ODM\Id(strategy="NONE", type="int") */ + #[ODM\Id(strategy: 'NONE', type: 'int')] private ?int $firstId = null; /** * @var int The custom identifier - * - * @ODM\Field(type="int") */ #[ApiProperty(identifier: true)] + #[ODM\Field(type: 'int')] private ?int $secondId = null; /** * @var string The dummy name - * - * @ODM\Field(type="string") */ + #[ODM\Field(type: 'string')] private ?string $name = null; public function getFirstId(): int diff --git a/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php b/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php index f6f054cb400..8e3cff9d05d 100644 --- a/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomNormalizedDummy.php @@ -23,36 +23,33 @@ * Custom Normalized Dummy. * * @author Mikaël Labrut - * @ODM\Document */ #[ApiResource(normalizationContext: ['groups' => ['output']], denormalizationContext: ['groups' => ['input']])] +#[ODM\Document] class CustomNormalizedDummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ #[Groups(['input', 'output'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field */ #[ApiProperty(types: ['http://schema.org/name'])] #[Assert\NotBlank] #[Groups(['input', 'output'])] + #[ODM\Field] private ?string $name = null; /** * @var string|null The dummy name alias - * - * @ODM\Field(nullable=true) */ #[ApiProperty(types: ['http://schema.org/alternateName'])] #[Groups(['input', 'output'])] + #[ODM\Field(nullable: true)] private ?string $alias = null; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php index 9f02150ba9b..167e91516e6 100644 --- a/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/CustomWritableIdentifierDummy.php @@ -18,23 +18,20 @@ /** * Custom Writable Identifier Dummy. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class CustomWritableIdentifierDummy { /** * @var string The special identifier - * - * @ODM\Id(strategy="NONE", type="string") */ + #[ODM\Id(strategy: 'NONE', type: 'string')] private ?string $slug = null; /** * @var string The dummy name - * - * @ODM\Field(name="name", type="string") */ + #[ODM\Field(name: 'name', type: 'string')] private ?string $name = null; /** diff --git a/tests/Fixtures/TestBundle/Document/Customer.php b/tests/Fixtures/TestBundle/Document/Customer.php index 5689df5fa4a..3c442fd6bb7 100644 --- a/tests/Fixtures/TestBundle/Document/Customer.php +++ b/tests/Fixtures/TestBundle/Document/Customer.php @@ -18,26 +18,18 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource(normalizationContext: ['groups' => ['order_read']])] +#[ODM\Document] class Customer { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups(['order_read'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="string") - */ #[Groups(['order_read'])] + #[ODM\Field(type: 'string')] public $name; - /** - * @ODM\ReferenceMany(targetDocument=Address::class) - */ #[Groups(['order_read'])] + #[ODM\ReferenceMany(targetDocument: Address::class)] public $addresses; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DeprecatedResource.php b/tests/Fixtures/TestBundle/Document/DeprecatedResource.php index c91d8cbc20f..3a792c1a956 100644 --- a/tests/Fixtures/TestBundle/Document/DeprecatedResource.php +++ b/tests/Fixtures/TestBundle/Document/DeprecatedResource.php @@ -18,23 +18,19 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ODM\Document - * * @author Kévin Dunglas */ #[ApiResource(deprecationReason: 'This resource is deprecated')] +#[ODM\Document] class DeprecatedResource { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; /** * @var string - * - * @ODM\Field */ #[ApiProperty(deprecationReason: 'This field is deprecated')] + #[ODM\Field] public $deprecatedField; } diff --git a/tests/Fixtures/TestBundle/Document/DisableItemOperation.php b/tests/Fixtures/TestBundle/Document/DisableItemOperation.php index f5b8401e504..973ca42ca50 100644 --- a/tests/Fixtures/TestBundle/Document/DisableItemOperation.php +++ b/tests/Fixtures/TestBundle/Document/DisableItemOperation.php @@ -19,21 +19,16 @@ use ApiPlatform\Metadata\GetCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(operations: [new Get(controller: NotFoundAction::class, read: false, output: false), new GetCollection()])] +#[ODM\Document] class DisableItemOperation { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] public $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Dummy.php b/tests/Fixtures/TestBundle/Document/Dummy.php index ff73ba89e9f..411af813faf 100644 --- a/tests/Fixtures/TestBundle/Document/Dummy.php +++ b/tests/Fixtures/TestBundle/Document/Dummy.php @@ -18,7 +18,6 @@ use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; @@ -27,33 +26,30 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * @ODM\Document */ #[ApiResource(extraProperties: ['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]], filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'])] #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])] +#[ODM\Document] class Dummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] private $id; /** * @var string|null The dummy name - * - * @ODM\Field(type="string") */ #[ApiProperty(types: ['http://schema.org/name'])] #[Assert\NotBlank] + #[ODM\Field(type: 'string')] private $name; /** * @var string|null The dummy name alias - * - * @ODM\Field(nullable=true) */ #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ODM\Field(nullable: true)] private $alias; /** * @var array|null foo @@ -61,82 +57,70 @@ class Dummy private ?array $foo = null; /** * @var string|null A short description of the item - * - * @ODM\Field(type="string", nullable=true) */ #[ApiProperty(types: ['http://schema.org/description'])] + #[ODM\Field(type: 'string', nullable: true)] public $description; /** * @var string|null A dummy - * - * @ODM\Field(nullable=true) */ + #[ODM\Field(nullable: true)] public $dummy; /** * @var bool|null A dummy boolean - * - * @ODM\Field(type="bool", nullable=true) */ + #[ODM\Field(type: 'bool', nullable: true)] public $dummyBoolean; /** * @var \DateTime|null A dummy date - * - * @ODM\Field(type="date", nullable=true) */ #[ApiProperty(types: ['http://schema.org/DateTime'])] + #[ODM\Field(type: 'date', nullable: true)] public $dummyDate; /** * @var float|null A dummy float - * - * @ODM\Field(type="float", nullable=true) */ + #[ODM\Field(type: 'float', nullable: true)] public $dummyFloat; /** * @var float|null A dummy price - * - * @ODM\Field(type="float", nullable=true) */ + #[ODM\Field(type: 'float', nullable: true)] public $dummyPrice; /** * @var RelatedDummy|null A related dummy - * - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummy; /** * @var \Collection Several dummies - * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceMany(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummies; /** * @var array serialize data - * - * @ODM\Field(type="hash", nullable=true) */ + #[ODM\Field(type: 'hash', nullable: true)] public $jsonData; /** * @var array - * - * @ODM\Field(type="collection", nullable=true) */ + #[ODM\Field(type: 'collection', nullable: true)] public $arrayData; /** * @var string|null - * - * @ODM\Field(nullable=true) */ + #[ODM\Field(nullable: true)] public $nameConverted; /** * @var RelatedOwnedDummy|null - * - * @ODM\ReferenceOne(targetDocument=RelatedOwnedDummy::class, cascade={"persist"}, mappedBy="owningDummy", nullable=true) */ + #[ODM\ReferenceOne(targetDocument: RelatedOwnedDummy::class, cascade: ['persist'], mappedBy: 'owningDummy', nullable: true)] public $relatedOwnedDummy; /** * @var RelatedOwningDummy|null - * - * @ODM\ReferenceOne(targetDocument=RelatedOwningDummy::class, cascade={"persist"}, inversedBy="ownedDummy", nullable=true, storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: RelatedOwningDummy::class, cascade: ['persist'], inversedBy: 'ownedDummy', nullable: true, storeAs: 'id')] public $relatedOwningDummy; public static function staticMethod(): void diff --git a/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php index 763a058a5e3..c7a0f0ceaf7 100644 --- a/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php @@ -25,34 +25,29 @@ * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * @ODM\Document */ #[ApiResource] #[ApiResource(uriTemplate: '/dummy_products/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class DummyAggregateOffer { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\ReferenceMany(targetDocument=DummyOffer::class, mappedBy="aggregate", cascade={"persist"}) - */ + #[ODM\ReferenceMany(targetDocument: DummyOffer::class, mappedBy: 'aggregate', cascade: ['persist'])] private \Doctrine\Common\Collections\ArrayCollection $offers; /** * @var DummyProduct The dummy product - * - * @ODM\ReferenceOne(targetDocument=DummyProduct::class, inversedBy="offers", storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: DummyProduct::class, inversedBy: 'offers', storeAs: 'id')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct $product = null; /** * @var int The dummy aggregate offer value - * - * @ODM\Field(type="int") */ + #[ODM\Field(type: 'int')] private $value; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DummyBoolean.php b/tests/Fixtures/TestBundle/Document/DummyBoolean.php index c5127b8d0d0..3662d42a5b9 100644 --- a/tests/Fixtures/TestBundle/Document/DummyBoolean.php +++ b/tests/Fixtures/TestBundle/Document/DummyBoolean.php @@ -16,22 +16,15 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class DummyBoolean { - /** - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] private ?int $id = null; public function __construct( - /** - * @ODM\Field(type="bool", nullable=true) - */ - private readonly bool $isDummyBoolean + #[ODM\Field(type: 'bool', nullable: true)] private readonly bool $isDummyBoolean ) { } diff --git a/tests/Fixtures/TestBundle/Document/DummyCar.php b/tests/Fixtures/TestBundle/Document/DummyCar.php index 0ba862c56de..254b6b9211a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCar.php +++ b/tests/Fixtures/TestBundle/Document/DummyCar.php @@ -29,73 +29,58 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation as Serializer; -/** - * @ODM\Document - */ #[ApiFilter(DateFilter::class, strategy: DateFilter::EXCLUDE_NULL)] #[ApiFilter(BooleanFilter::class)] #[ApiFilter(PropertyFilter::class, arguments: ['parameterName' => 'foobar'])] #[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups'])] #[ApiFilter(GroupFilter::class, arguments: ['parameterName' => 'foobargroups_override'], id: 'override')] #[ApiResource(operations: [new Get(openapiContext: ['tags' => []]), new Put(), new Delete(), new Post(), new GetCollection()], sunset: '2050-01-01', normalizationContext: ['groups' => ['colors']])] +#[ODM\Document] class DummyCar { /** * @var int The entity Id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var mixed Something else - * - * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") */ #[ApiFilter(SearchFilter::class, properties: ['colors.prop' => 'ipartial', 'colors' => 'exact'])] #[Serializer\Groups(['colors'])] + #[ODM\ReferenceMany(targetDocument: DummyCarColor::class, mappedBy: 'car')] private $colors; /** * @var mixed Something else - * - * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") */ #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[Serializer\Groups(['colors'])] + #[ODM\ReferenceMany(targetDocument: DummyCarColor::class, mappedBy: 'car')] private mixed $secondColors = null; /** * @var mixed Something else - * - * @ODM\ReferenceMany(targetDocument=DummyCarColor::class, mappedBy="car") */ #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[Serializer\Groups(['colors'])] + #[ODM\ReferenceMany(targetDocument: DummyCarColor::class, mappedBy: 'car')] private mixed $thirdColors = null; /** * @var mixed Something else - * - * @ODM\ReferenceMany(targetDocument=UuidIdentifierDummy::class) */ #[ApiFilter(SearchFilter::class, strategy: 'exact')] #[Serializer\Groups(['colors'])] + #[ODM\ReferenceMany(targetDocument: UuidIdentifierDummy::class)] private mixed $uuid = null; - /** - * @ODM\Field(type="string") - */ #[ApiFilter(SearchFilter::class, strategy: 'partial')] + #[ODM\Field(type: 'string')] private ?string $name = null; - /** - * @ODM\Field(type="bool") - */ + #[ODM\Field(type: 'bool')] private ?bool $canSell = null; - /** - * @ODM\Field(type="date") - */ + #[ODM\Field(type: 'date')] private ?\DateTime $availableAt = null; - /** - * @ODM\Field - */ #[Serializer\Groups(['colors'])] #[Serializer\SerializedName('carBrand')] + #[ODM\Field] private string $brand = 'DummyBrand'; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DummyCarColor.php b/tests/Fixtures/TestBundle/Document/DummyCarColor.php index df8d7c6a31e..1f7b5aa94f0 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Document/DummyCarColor.php @@ -20,29 +20,22 @@ use Symfony\Component\Serializer\Annotation as Serializer; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class DummyCarColor { /** * @var int The entity Id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\ReferenceOne(targetDocument=DummyCar::class, inversedBy="colors", storeAs="id") - */ #[Assert\NotBlank] + #[ODM\ReferenceOne(targetDocument: DummyCar::class, inversedBy: 'colors', storeAs: 'id')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyCar $car = null; - /** - * @ODM\Field(nullable=false) - */ #[ApiFilter(SearchFilter::class)] #[Assert\NotBlank] #[Serializer\Groups(['colors'])] + #[ODM\Field(nullable: false)] private string $prop = ''; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php b/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php index 81363bdb361..78c29971aac 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomFormat.php @@ -17,24 +17,20 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ODM\Document - */ #[ApiResource(formats: ['xml', 'jsonld', 'csv' => ['text/csv'], 'pdf' => 'application/pdf'])] +#[ODM\Document] class DummyCustomFormat { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; /** * @var string - * - * @ODM\Field */ #[Assert\NotBlank] + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php index d7b915c0725..f1f4e6ec018 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php @@ -22,30 +22,21 @@ /** * Dummy with a custom GraphQL mutation resolver. * - * @ODM\Document - * * @author Raoul Clais */ #[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist_document', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']]), new Mutation(name: 'testOutput', resolver: 'app.graphql.mutation_resolver.dummy_custom', output: OutputDto::class)])] +#[ODM\Document] class DummyCustomMutation { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="int") - */ + #[ODM\Field(type: 'int')] private ?int $operandA = null; - /** - * @ODM\Field(type="int", nullable=true) - */ #[Groups(['sum'])] + #[ODM\Field(type: 'int', nullable: true)] private ?int $operandB = null; - /** - * @ODM\Field(type="int", nullable=true) - */ #[Groups(['result'])] + #[ODM\Field(type: 'int', nullable: true)] private ?int $result = null; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php index 3a02cef3aab..566b397485a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php @@ -23,16 +23,15 @@ * Dummy with custom GraphQL query resolvers. * * @author Lukas Lücke - * @ODM\Document */ #[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item_document', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new Query(name: 'testItemOutput', resolver: 'app.graphql.query_resolver.dummy_custom_item', output: OutputDto::class), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])] +#[ODM\Document] class DummyCustomQuery { /** * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; /** * @var string diff --git a/tests/Fixtures/TestBundle/Document/DummyDate.php b/tests/Fixtures/TestBundle/Document/DummyDate.php index b61c056ffb1..48b3d85e650 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyDate.php @@ -24,7 +24,6 @@ * Dummy Date. * * @author Alan Poulain - * @ODM\Document */ #[ApiFilter(DateFilter::class, properties: [ 'dateIncludeNullAfter' => DateFilter::INCLUDE_NULL_AFTER, @@ -33,37 +32,33 @@ ])] #[ApiFilter(SearchFilter::class, properties: ['dummyDate'])] #[ApiResource(filters: ['my_dummy_date.mongodb.date'])] +#[ODM\Document] class DummyDate { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var \DateTime|null The dummy date - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $dummyDate; /** * @var \DateTime|null - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $dateIncludeNullAfter; /** * @var \DateTime|null - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $dateIncludeNullBefore; /** * @var \DateTime|null - * - * @ODM\Field(type="date") */ + #[ODM\Field(type: 'date')] public $dateIncludeNullBeforeAndAfter; /** diff --git a/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php b/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php index ddb69430dfb..9f154aa58f0 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php +++ b/tests/Fixtures/TestBundle/Document/DummyDifferentGraphQlSerializationGroup.php @@ -23,31 +23,28 @@ * Dummy with different serialization groups for item_query and collection_query. * * @author Mahmood Bazdar - * @ODM\Document */ #[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['item_query']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['collection_query']])])] +#[ODM\Document] class DummyDifferentGraphQlSerializationGroup { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ #[Groups(['item_query', 'collection_query'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field(type="string") */ #[Groups(['item_query', 'collection_query'])] + #[ODM\Field(type: 'string')] private ?string $name = null; /** * @var string|null The dummy title - * - * @ODM\Field(nullable=true) */ #[Groups(['item_query'])] + #[ODM\Field(nullable: true)] private ?string $title = null; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php index 93d1cfce581..4e4f703222b 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoCustom.php @@ -25,29 +25,25 @@ /** * DummyDtoCustom. - * - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), new Put(), new Delete(), new Post(input: CustomInputDto::class), new GetCollection(), new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output')])] +#[ODM\Document] class DummyDtoCustom { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php b/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php index d7a9831f9f4..f37ee5ecdf3 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoInputOutput.php @@ -24,9 +24,9 @@ * Dummy InputOutput. * * @author Kévin Dunglas - * @ODM\Document */ #[ApiResource(input: InputDto::class, output: OutputDto::class)] +#[ODM\Document] class DummyDtoInputOutput { public function __construct() @@ -35,22 +35,22 @@ public function __construct() } /** * @var int The id - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] public $id; /** * @var string - * @ODM\Field */ + #[ODM\Field] public $str; /** * @var int - * @ODM\Field(type="float") */ + #[ODM\Field(type: 'float')] public $num; /** * @var Collection - * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceMany(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummies; } diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php index 1e7f37bc8bf..40324afc0d8 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoNoInput.php @@ -27,28 +27,25 @@ * DummyDtoNoInput. * * @author Vincent Chalamon - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Delete(), new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200), new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class), new GetCollection()], input: false, output: OutputDto::class)] +#[ODM\Document] class DummyDtoNoInput { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; /** * @var float - * - * @ODM\Field(type="float") */ + #[ODM\Field(type: 'float')] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php b/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php index f528ef166c0..84b53e78cad 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php @@ -21,28 +21,25 @@ * DummyDtoNoOutput. * * @author Vincent Chalamon - * @ODM\Document */ #[ApiResource(input: InputDto::class, output: false)] +#[ODM\Document] class DummyDtoNoOutput { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php index 5257f79deee..d5b7828b25e 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php @@ -21,28 +21,25 @@ * Dummy InputOutput. * * @author Daniel West - * @ODM\Document */ #[ApiResource(output: OutputDtoDummy::class)] +#[ODM\Document] class DummyDtoOutputFallbackToSameClass { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php index 79a5da53514..4ffceb19d42 100644 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php +++ b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php @@ -20,28 +20,25 @@ * Dummy InputOutput. * * @author Daniel West - * @ODM\Document */ #[ApiResource(output: DummyDtoOutputSameClass::class)] +#[ODM\Document] class DummyDtoOutputSameClass { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] private ?int $id = null; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $lorem; /** * @var string - * - * @ODM\Field */ + #[ODM\Field] public $ipsum; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php b/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php index 133a9fb99e7..09594088341 100644 --- a/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php +++ b/tests/Fixtures/TestBundle/Document/DummyEntityWithConstructor.php @@ -28,35 +28,26 @@ * https://github.com/api-platform/core/issues/1747. * * @author Maxime Veber - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Put(denormalizationContext: ['groups' => ['put']]), new Post(), new GetCollection()])] +#[ODM\Document] class DummyEntityWithConstructor { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(nullable=true) - */ #[Groups(['put'])] + #[ODM\Field(nullable: true)] private ?string $baz = null; /** * @param DummyObjectWithoutConstructor[] $items */ public function __construct( - /** - * @ODM\Field - */ - private readonly string $foo, - /** - * @ODM\Field - */ - private readonly string $bar, + #[ODM\Field] private readonly string $foo, + #[ODM\Field] private readonly string $bar, private readonly array $items ) { } diff --git a/tests/Fixtures/TestBundle/Document/DummyFriend.php b/tests/Fixtures/TestBundle/Document/DummyFriend.php index f1dfc27ebcb..8590c3fd803 100644 --- a/tests/Fixtures/TestBundle/Document/DummyFriend.php +++ b/tests/Fixtures/TestBundle/Document/DummyFriend.php @@ -25,25 +25,23 @@ * * @author Kévin Dunglas * @author Alan Poulain - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class DummyFriend { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field(type="string") */ #[Assert\NotBlank] #[ApiProperty(types: ['http://schema.org/name'])] #[Groups(['fakemanytomany', 'friends'])] + #[ODM\Field(type: 'string')] private ?string $name = null; /** diff --git a/tests/Fixtures/TestBundle/Document/DummyGroup.php b/tests/Fixtures/TestBundle/Document/DummyGroup.php index e1c29c1f6c0..f5519375c42 100644 --- a/tests/Fixtures/TestBundle/Document/DummyGroup.php +++ b/tests/Fixtures/TestBundle/Document/DummyGroup.php @@ -25,43 +25,37 @@ * * @author Baptiste Meyer * @author Alan Poulain - * @ODM\Document */ #[ApiResource(graphQlOperations: [new Query(name: 'item_query', normalizationContext: ['groups' => ['dummy_foo']]), new QueryCollection(name: 'collection_query', normalizationContext: ['groups' => ['dummy_foo']]), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_bar']], denormalizationContext: ['groups' => ['dummy_bar', 'dummy_baz']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_group.group', 'dummy_group.override_group', 'dummy_group.whitelist_group', 'dummy_group.override_whitelist_group'])] +#[ODM\Document] class DummyGroup { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups(['dummy', 'dummy_read', 'dummy_id'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null - * - * @ODM\Field(nullable=true) */ #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_foo'])] + #[ODM\Field(nullable: true)] public $foo; /** * @var string|null - * - * @ODM\Field(nullable=true) */ #[Groups(['dummy', 'dummy_read', 'dummy_write', 'dummy_bar'])] + #[ODM\Field(nullable: true)] public $bar; /** * @var string|null - * - * @ODM\Field(nullable=true) */ #[Groups(['dummy', 'dummy_read', 'dummy_baz'])] + #[ODM\Field(nullable: true)] public $baz; /** * @var string|null - * - * @ODM\Field(nullable=true) */ #[Groups(['dummy', 'dummy_write', 'dummy_qux'])] + #[ODM\Field(nullable: true)] public $qux; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php b/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php index 9f469df2334..6219a76f4d8 100644 --- a/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php +++ b/tests/Fixtures/TestBundle/Document/DummyImmutableDate.php @@ -19,23 +19,20 @@ /** * Dummy Date Immutable. - * - * @ODM\Document */ #[ApiResource(filters: ['my_dummy_immutable_date.mongodb.date'])] +#[ODM\Document] class DummyImmutableDate { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var \DateTimeImmutable The dummy date - * - * @ODM\Field(type="date_immutable") */ + #[ODM\Field(type: 'date_immutable')] public $dummyDate; /** diff --git a/tests/Fixtures/TestBundle/Document/DummyMercure.php b/tests/Fixtures/TestBundle/Document/DummyMercure.php index 83b2af26f79..34cdbdfc55a 100644 --- a/tests/Fixtures/TestBundle/Document/DummyMercure.php +++ b/tests/Fixtures/TestBundle/Document/DummyMercure.php @@ -17,27 +17,18 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** - * @ODM\Document - * * @author Kévin Dunglas */ #[ApiResource(mercure: true)] +#[ODM\Document] class DummyMercure { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $name; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $description; - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) - */ + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummy; } diff --git a/tests/Fixtures/TestBundle/Document/DummyOffer.php b/tests/Fixtures/TestBundle/Document/DummyOffer.php index 95e5cb4064a..fb5632a4994 100644 --- a/tests/Fixtures/TestBundle/Document/DummyOffer.php +++ b/tests/Fixtures/TestBundle/Document/DummyOffer.php @@ -24,31 +24,28 @@ * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * @ODM\Document */ #[ApiResource] #[ApiResource(uriTemplate: '/dummy_aggregate_offers/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/dummy_products/{id}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class DummyOffer { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var int The dummy aggregate offer value - * - * @ODM\Field(type="int") */ + #[ODM\Field(type: 'int')] private ?int $value = null; /** * @var DummyAggregateOffer The dummy aggregate offer value - * - * @ODM\ReferenceOne(targetDocument=DummyAggregateOffer::class, inversedBy="offers", storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: DummyAggregateOffer::class, inversedBy: 'offers', storeAs: 'id')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer $aggregate = null; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyPassenger.php b/tests/Fixtures/TestBundle/Document/DummyPassenger.php index 28dc7353327..3cb272ad681 100644 --- a/tests/Fixtures/TestBundle/Document/DummyPassenger.php +++ b/tests/Fixtures/TestBundle/Document/DummyPassenger.php @@ -16,19 +16,13 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class DummyPassenger { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $nickname; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyProduct.php b/tests/Fixtures/TestBundle/Document/DummyProduct.php index 8741706e6b1..bf7b238135c 100644 --- a/tests/Fixtures/TestBundle/Document/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Document/DummyProduct.php @@ -26,35 +26,27 @@ * https://github.com/api-platform/core/issues/1107. * * @author Antoine Bluchet - * @ODM\Document */ #[ApiResource] #[ApiResource(uriTemplate: '/dummy_products/{id}/related_products.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class DummyProduct { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\ReferenceMany(targetDocument=DummyAggregateOffer::class, mappedBy="product", cascade={"persist"}) - */ + #[ODM\ReferenceMany(targetDocument: DummyAggregateOffer::class, mappedBy: 'product', cascade: ['persist'])] private \Doctrine\Common\Collections\Collection $offers; /** * @var string The tour name - * - * @ODM\Field */ + #[ODM\Field] private $name; - /** - * @ODM\ReferenceMany(targetDocument=DummyProduct::class, mappedBy="parent") - */ + #[ODM\ReferenceMany(targetDocument: self::class, mappedBy: 'parent')] private \Doctrine\Common\Collections\Collection $relatedProducts; - /** - * @ODM\ReferenceOne(targetDocument=DummyProduct::class, inversedBy="relatedProducts") - */ + #[ODM\ReferenceOne(targetDocument: self::class, inversedBy: 'relatedProducts')] private $parent; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DummyProperty.php b/tests/Fixtures/TestBundle/Document/DummyProperty.php index 659da6e9c6d..5d8732cda83 100644 --- a/tests/Fixtures/TestBundle/Document/DummyProperty.php +++ b/tests/Fixtures/TestBundle/Document/DummyProperty.php @@ -24,57 +24,49 @@ * DummyProperty. * * @author Baptiste Meyer - * @ODM\Document */ #[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query'), new Mutation(name: 'update'), new Mutation(name: 'delete'), new Mutation(name: 'create', normalizationContext: ['groups' => ['dummy_graphql_read']])], normalizationContext: ['groups' => ['dummy_read']], denormalizationContext: ['groups' => ['dummy_write']], filters: ['dummy_property.property', 'dummy_property.whitelist_property', 'dummy_property.whitelisted_properties'])] +#[ODM\Document] class DummyProperty { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups(['dummy_read', 'dummy_graphql_read'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null - * - * @ODM\Field(nullable=true) */ #[Groups(['dummy_read', 'dummy_write'])] + #[ODM\Field(nullable: true)] public $foo; /** * @var string|null - * - * @ODM\Field(nullable=true) */ #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] + #[ODM\Field(nullable: true)] public $bar; /** * @var string|null - * - * @ODM\Field(nullable=true) */ #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] + #[ODM\Field(nullable: true)] public $baz; /** * @var DummyGroup|null - * - * @ODM\ReferenceOne(targetDocument=DummyGroup::class, cascade={"persist"}, nullable=true) */ #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] + #[ODM\ReferenceOne(targetDocument: DummyGroup::class, cascade: ['persist'], nullable: true)] public $group; /** * @var DummyGroup[]|null - * - * @ODM\ReferenceMany(targetDocument=DummyGroup::class, cascade={"persist"}) */ #[Groups(['dummy_read', 'dummy_graphql_read', 'dummy_write'])] + #[ODM\ReferenceMany(targetDocument: DummyGroup::class, cascade: ['persist'])] public $groups; /** * @var string|null - * - * @ODM\Field(nullable=true) */ #[Groups(['dummy_read', 'dummy_write'])] + #[ODM\Field(nullable: true)] public $nameConverted; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php index bf62359f031..2b32967280c 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritance.php @@ -17,37 +17,26 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - * @ODM\InheritanceType ("SINGLE_COLLECTION") - * @ODM\DiscriminatorField (value="discr") - * @ODM\DiscriminatorMap ({ - * "dummyTableInheritance"=DummyTableInheritance::class, - * "dummyTableInheritanceChild"=DummyTableInheritanceChild::class, - * "dummyTableInheritanceDifferentChild"=DummyTableInheritanceDifferentChild::class, - * "dummyTableInheritanceNotApiResourceChild"=DummyTableInheritanceNotApiResourceChild::class - * }) - */ #[ApiResource] +#[ODM\Document] +#[ODM\InheritanceType('SINGLE_COLLECTION')] +#[ODM\DiscriminatorField(value: 'discr')] +#[ODM\DiscriminatorMap(['dummyTableInheritance' => DummyTableInheritance::class, 'dummyTableInheritanceChild' => DummyTableInheritanceChild::class, 'dummyTableInheritanceDifferentChild' => DummyTableInheritanceDifferentChild::class, 'dummyTableInheritanceNotApiResourceChild' => DummyTableInheritanceNotApiResourceChild::class])] class DummyTableInheritance { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ #[Groups(['default'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field */ #[Groups(['default'])] + #[ODM\Field] private ?string $name = null; - /** - * @ODM\ReferenceOne(targetDocument=DummyTableInheritanceRelated::class, inversedBy="children") - */ + #[ODM\ReferenceOne(targetDocument: DummyTableInheritanceRelated::class, inversedBy: 'children')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyTableInheritanceRelated $parent = null; public function getName(): ?string diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php index f68d56d7303..874b2393a38 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceChild.php @@ -17,18 +17,15 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class DummyTableInheritanceChild extends DummyTableInheritance { /** * @var string The dummy nickname - * - * @ODM\Field */ #[Groups(['default'])] + #[ODM\Field] private $nickname; public function getNickname() diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php index d2d18663eed..58df7162ab6 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceDifferentChild.php @@ -17,18 +17,15 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class DummyTableInheritanceDifferentChild extends DummyTableInheritance { /** * @var string The dummy email - * - * @ODM\Field */ #[Groups(['default'])] + #[ODM\Field] private $email; public function getEmail() diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php index e63abb37422..b4616c4ad59 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceNotApiResourceChild.php @@ -15,16 +15,13 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ +#[ODM\Document] class DummyTableInheritanceNotApiResourceChild extends DummyTableInheritance { /** * @var bool The dummy swagg - * - * @ODM\Field(type="bool") */ + #[ODM\Field(type: 'bool')] private bool $swaggerThanParent; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php index db7a6562e98..7741ee0e676 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php +++ b/tests/Fixtures/TestBundle/Document/DummyTableInheritanceRelated.php @@ -19,25 +19,21 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource(normalizationContext: ['groups' => ['default']], denormalizationContext: ['groups' => ['default']])] +#[ODM\Document] class DummyTableInheritanceRelated { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ #[Groups(['default'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var Collection Related children - * - * @ODM\ReferenceMany(targetDocument=DummyTableInheritance::class, mappedBy="parent") */ #[Groups(['default'])] + #[ODM\ReferenceMany(targetDocument: DummyTableInheritance::class, mappedBy: 'parent')] private \Doctrine\Common\Collections\Collection $children; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/DummyTravel.php b/tests/Fixtures/TestBundle/Document/DummyTravel.php index ca6011029c2..40affaca63d 100644 --- a/tests/Fixtures/TestBundle/Document/DummyTravel.php +++ b/tests/Fixtures/TestBundle/Document/DummyTravel.php @@ -16,27 +16,17 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(filters: ['dummy_travel.property'])] +#[ODM\Document] class DummyTravel { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\ReferenceOne(targetDocument=DummyCar::class) - */ + #[ODM\ReferenceOne(targetDocument: DummyCar::class)] public $car; - /** - * @ODM\Field(type="bool") - */ + #[ODM\Field(type: 'bool')] public $confirmed; - /** - * @ODM\ReferenceOne(targetDocument=DummyPassenger::class) - */ + #[ODM\ReferenceOne(targetDocument: DummyPassenger::class)] public $passenger; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/DummyValidation.php b/tests/Fixtures/TestBundle/Document/DummyValidation.php index ef67d1593c5..08848c1e793 100644 --- a/tests/Fixtures/TestBundle/Document/DummyValidation.php +++ b/tests/Fixtures/TestBundle/Document/DummyValidation.php @@ -23,36 +23,31 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ODM\Document - */ #[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new Post(uriTemplate: 'dummy_validation.{_format}'), new GetCollection(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]), new GetCollection(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator'])])] +#[ODM\Document] class DummyValidation { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field(nullable=true) */ #[Assert\NotNull(groups: ['a'])] + #[ODM\Field(nullable: true)] private ?string $name = null; /** * @var string|null The dummy title - * - * @ODM\Field(nullable=true) */ #[Assert\NotNull(groups: ['b'])] + #[ODM\Field(nullable: true)] private ?string $title = null; /** * @var string|null The dummy code - * @ODM\Field */ + #[ODM\Field] private ?string $code = null; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php b/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php index d0445a6e86a..26ea3405325 100644 --- a/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php +++ b/tests/Fixtures/TestBundle/Document/DummyWithEmbedManyOmittingTargetDocument.php @@ -18,23 +18,19 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class DummyWithEmbedManyOmittingTargetDocument { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var EmbeddableDummy[]|Collection - * - * @ODM\EmbedMany */ + #[ODM\EmbedMany] private readonly array|\Doctrine\Common\Collections\Collection $embeddedDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php b/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php index 8b519e37ed8..8fba54a7a92 100644 --- a/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php +++ b/tests/Fixtures/TestBundle/Document/EmbeddableDummy.php @@ -22,52 +22,39 @@ * * @author Jordan Samouh * @author Alexandre Delplace - * - * @ODM\EmbeddedDocument */ +#[ODM\EmbeddedDocument] class EmbeddableDummy { /** * @var string|null The dummy name - * - * @ODM\Field(type="string") */ #[Groups(['embed'])] + #[ODM\Field(type: 'string')] private ?string $dummyName = null; - /** * @var bool|null A dummy boolean - * - * @ODM\Field(type="bool") */ + #[ODM\Field(type: 'bool')] public $dummyBoolean; - /** * @var \DateTime|null A dummy date - * - * @ODM\Field(type="date") */ #[Assert\DateTime] + #[ODM\Field(type: 'date')] public $dummyDate; - /** * @var float|null A dummy float - * - * @ODM\Field(type="float") */ + #[ODM\Field(type: 'float')] public $dummyFloat; - /** * @var float|null A dummy price - * - * @ODM\Field(type="float") */ + #[ODM\Field(type: 'float')] public $dummyPrice; - - /** - * @ODM\Field(type="string") - */ #[Groups(['barcelona', 'chicago'])] + #[ODM\Field(type: 'string')] protected $symfony; public static function staticMethod(): void diff --git a/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php b/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php index 7b76c81c608..69ed9ee5c41 100644 --- a/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php +++ b/tests/Fixtures/TestBundle/Document/EmbeddedDummy.php @@ -28,43 +28,38 @@ * * @author Jordan Samouh * @author Alexandre Delplace - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(uriTemplate: '/embedded_dummies_groups/{id}', normalizationContext: ['groups' => ['embed']]), new Post(), new GetCollection()], filters: ['my_dummy.mongodb.search', 'my_dummy.mongodb.order', 'my_dummy.mongodb.date', 'my_dummy.mongodb.boolean'])] +#[ODM\Document] class EmbeddedDummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field(type="string") */ #[Groups(['embed'])] + #[ODM\Field(type: 'string')] private ?string $name = null; /** * @var \DateTime|null A dummy date - * - * @ODM\Field(type="date") */ #[Assert\DateTime] + #[ODM\Field(type: 'date')] public $dummyDate; /** * @var EmbeddableDummy - * - * @ODM\EmbedOne(targetDocument=EmbeddableDummy::class) */ #[Groups(['embed'])] + #[ODM\EmbedOne(targetDocument: EmbeddableDummy::class)] public $embeddedDummy; /** * @var RelatedDummy|null A related dummy - * - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, storeAs: 'id')] public $relatedDummy; public static function staticMethod(): void diff --git a/tests/Fixtures/TestBundle/Document/Employee.php b/tests/Fixtures/TestBundle/Document/Employee.php index 3ca2d5a499c..ed6ff6f4412 100644 --- a/tests/Fixtures/TestBundle/Document/Employee.php +++ b/tests/Fixtures/TestBundle/Document/Employee.php @@ -19,36 +19,31 @@ use ApiPlatform\Metadata\Post; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] #[Post] #[ApiResource(uriTemplate: '/companies/{companyId}/employees/{id}', uriVariables: ['companyId' => ['from_class' => Company::class, 'to_property' => 'company'], 'id' => ['from_class' => Employee::class]])] #[Get] #[ApiResource(uriTemplate: '/companies/{companyId}/employees', uriVariables: ['companyId' => ['from_class' => Company::class, 'to_property' => 'company']])] #[GetCollection] +#[ODM\Document] class Employee { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] public $name; /** * @var ?Company - * - * @ODM\ReferenceOne(targetDocument=Company::class, storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: Company::class, storeAs: 'id')] public $company; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Field.php b/tests/Fixtures/TestBundle/Document/Field.php index cb7961df786..d7333885294 100644 --- a/tests/Fixtures/TestBundle/Document/Field.php +++ b/tests/Fixtures/TestBundle/Document/Field.php @@ -15,29 +15,16 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ +#[ODM\Document] class Field implements \JsonSerializable { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - - /** - * @ODM\ReferenceOne(targetDocument=Content::class, inversedBy="fields") - */ + #[ODM\ReferenceOne(targetDocument: Content::class, inversedBy: 'fields')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Content $content = null; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private ?string $name = null; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private ?string $value = null; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/FileConfigDummy.php b/tests/Fixtures/TestBundle/Document/FileConfigDummy.php index 2307c657e92..88d6ddfa37b 100644 --- a/tests/Fixtures/TestBundle/Document/FileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Document/FileConfigDummy.php @@ -17,32 +17,25 @@ /** * File Config Dummy. - * - * @ODM\Document */ +#[ODM\Document] class FileConfigDummy { final public const HYDRA_TITLE = 'File config Dummy'; - /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] private $name; - /** * @var string - * - * @ODM\Field */ + #[ODM\Field] private $foo; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/FilterValidator.php b/tests/Fixtures/TestBundle/Document/FilterValidator.php index 15aedd105ec..602f13a27fd 100644 --- a/tests/Fixtures/TestBundle/Document/FilterValidator.php +++ b/tests/Fixtures/TestBundle/Document/FilterValidator.php @@ -30,24 +30,22 @@ * * @author Julien Deniau * @author Alan Poulain - * @ODM\Document */ #[ApiResource(filters: [ArrayItemsFilter::class, BoundsFilter::class, EnumFilter::class, LengthFilter::class, MultipleOfFilter::class, PatternFilter::class, RequiredFilter::class, RequiredAllowEmptyFilter::class])] +#[ODM\Document] class FilterValidator { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string A name - * - * @ODM\Field */ #[ApiProperty(types: ['http://schema.org/name'])] + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Foo.php b/tests/Fixtures/TestBundle/Document/Foo.php index 801bf16f4fa..36108d02506 100644 --- a/tests/Fixtures/TestBundle/Document/Foo.php +++ b/tests/Fixtures/TestBundle/Document/Foo.php @@ -28,28 +28,25 @@ * Foo. * * @author Vincent Chalamon - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new GetCollection(uriTemplate: 'custom_collection_desc_foos', order: ['name' => 'DESC']), new GetCollection(uriTemplate: 'custom_collection_asc_foos', order: ['name' => 'ASC'])], graphQlOperations: [new Query(name: 'item_query'), new QueryCollection(name: 'collection_query', paginationEnabled: false), new Mutation(name: 'create'), new Mutation(name: 'delete')], order: ['bar', 'name' => 'DESC'])] +#[ODM\Document] class Foo { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string The foo name - * - * @ODM\Field */ + #[ODM\Field] private $name; /** * @var string The foo bar - * - * @ODM\Field */ + #[ODM\Field] private $bar; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/FooDummy.php b/tests/Fixtures/TestBundle/Document/FooDummy.php index e0fd4cf8002..edcc63e56bb 100644 --- a/tests/Fixtures/TestBundle/Document/FooDummy.php +++ b/tests/Fixtures/TestBundle/Document/FooDummy.php @@ -21,28 +21,25 @@ * FooDummy. * * @author Vincent Chalamon - * @ODM\Document */ #[ApiResource(graphQlOperations: [new QueryCollection(name: 'collection_query', paginationType: 'page')], order: ['dummy.name'])] +#[ODM\Document] class FooDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string The foo name - * - * @ODM\Field */ + #[ODM\Field] private $name; /** * @var Dummy The foo dummy - * - * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: Dummy::class, cascade: ['persist'], storeAs: 'id')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy $dummy = null; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/FourthLevel.php b/tests/Fixtures/TestBundle/Document/FourthLevel.php index 1f21f6032cb..ac52e1956c1 100644 --- a/tests/Fixtures/TestBundle/Document/FourthLevel.php +++ b/tests/Fixtures/TestBundle/Document/FourthLevel.php @@ -23,7 +23,6 @@ * Fourth Level. * * @author Alan Poulain - * @ODM\Document */ #[ApiResource] #[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] @@ -32,22 +31,18 @@ #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/third_levels/{id}/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel::class, identifiers: ['id'], fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])] +#[ODM\Document] class FourthLevel { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="int") - */ #[Groups(['barcelona', 'chicago'])] + #[ODM\Field(type: 'int')] private ?int $level = 4; - /** - * @ODM\ReferenceMany(targetDocument=ThirdLevel::class, cascade={"persist"}, mappedBy="badFourthLevel", storeAs="id") - */ + #[ODM\ReferenceMany(targetDocument: ThirdLevel::class, cascade: ['persist'], mappedBy: 'badFourthLevel', storeAs: 'id')] public $badThirdLevel; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/Greeting.php b/tests/Fixtures/TestBundle/Document/Greeting.php index 0882ed1965e..5e17a4bf7e7 100644 --- a/tests/Fixtures/TestBundle/Document/Greeting.php +++ b/tests/Fixtures/TestBundle/Document/Greeting.php @@ -18,28 +18,18 @@ use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] #[ApiResource(uriTemplate: '/people/{id}/sent_greetings.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Person::class, identifiers: ['id'], toProperty: 'sender')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class Greeting { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field - */ + #[ODM\Field] public $message = ''; - /** - * @ODM\ReferenceOne(targetDocument=Person::class, inversedBy="sentGreetings", storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: Person::class, inversedBy: 'sentGreetings', storeAs: 'id')] public $sender; - /** - * @ODM\ReferenceOne(targetDocument=Person::class) - */ + #[ODM\ReferenceOne(targetDocument: Person::class)] public $recipient; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/InitializeInput.php b/tests/Fixtures/TestBundle/Document/InitializeInput.php index dc661322ba9..903067842fa 100644 --- a/tests/Fixtures/TestBundle/Document/InitializeInput.php +++ b/tests/Fixtures/TestBundle/Document/InitializeInput.php @@ -17,22 +17,14 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(input: InitializeInputDto::class)] +#[ODM\Document] class InitializeInput { - /** - * @ODM\Id(strategy="NONE", type="int") - */ + #[ODM\Id(strategy: 'NONE', type: 'int')] public $id; - /** - * @ODM\Field - */ + #[ODM\Field] public $manager; - /** - * @ODM\Field - */ + #[ODM\Field] public $name; } diff --git a/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php b/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php index 393f680037a..a36a4e394a1 100644 --- a/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php +++ b/tests/Fixtures/TestBundle/Document/IriOnlyDummy.php @@ -20,20 +20,17 @@ * Dummy with iri_only. * * @author Pierre Thibaudeau - * @ODM\Document */ #[ApiResource(normalizationContext: ['iri_only' => true, 'jsonld_embed_context' => true])] +#[ODM\Document] class IriOnlyDummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private ?string $foo = null; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php b/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php index 25004f56e97..ac2b6828a45 100644 --- a/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php +++ b/tests/Fixtures/TestBundle/Document/JsonldContextDummy.php @@ -19,18 +19,16 @@ /** * Jsonld Context Dummy. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class JsonldContextDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ #[ApiProperty(identifier: true)] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** diff --git a/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php b/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php index ba685fbb617..45a3ae6f2f1 100644 --- a/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/LegacySecuredDummy.php @@ -27,34 +27,29 @@ * Secured resource with legacy access_control attribute. * * @author Vincent Chalamon - * @ODM\Document */ #[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Mutation(name: 'delete'), new Mutation(name: 'update', security: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] +#[ODM\Document] class LegacySecuredDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The title - * - * @ODM\Field */ #[Assert\NotBlank] + #[ODM\Field] private ?string $title = null; /** * @var string The description - * - * @ODM\Field */ + #[ODM\Field] private string $description = ''; /** * @var string|null The owner - * - * @ODM\Field */ #[Assert\NotBlank] + #[ODM\Field] private ?string $owner = null; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php index 70883456ac1..9b6d6251df2 100644 --- a/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Document/MaxDepthDummy.php @@ -21,28 +21,22 @@ /** * * * - * @ODM\Document * * @author Brian Fox */ #[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] +#[ODM\Document] class MaxDepthDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups(['default'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(name="name", type="string") - */ #[Groups(['default'])] + #[ODM\Field(name: 'name', type: 'string')] public $name; - /** - * @ODM\ReferenceOne(targetDocument=MaxDepthDummy::class, cascade={"persist"}) - */ #[Groups(['default'])] #[MaxDepth(1)] + #[ODM\ReferenceOne(targetDocument: self::class, cascade: ['persist'])] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php index 4fb93daeef0..9f71f094a70 100644 --- a/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Document/MaxDepthEagerDummy.php @@ -21,28 +21,22 @@ /** * * * - * @ODM\Document * * @author Brian Fox */ #[ApiResource(normalizationContext: ['groups' => ['default'], 'enable_max_depth' => true], denormalizationContext: ['groups' => ['default'], 'enable_max_depth' => true])] +#[ODM\Document] class MaxDepthEagerDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups(['default'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(name="name", type="string") - */ #[Groups(['default'])] + #[ODM\Field(name: 'name', type: 'string')] public $name; - /** - * @ODM\ReferenceOne(targetDocument=MaxDepthEagerDummy::class, cascade={"persist"}) - */ #[Groups(['default'])] #[MaxDepth(1)] + #[ODM\ReferenceOne(targetDocument: self::class, cascade: ['persist'])] public $child; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php b/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php index 4ba3625421b..4ad7520872a 100644 --- a/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php +++ b/tests/Fixtures/TestBundle/Document/NetworkPathDummy.php @@ -19,20 +19,14 @@ use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] #[ApiResource(uriTemplate: '/network_path_relation_dummies/{id}/network_path_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\NetworkPathRelationDummy::class, identifiers: ['id'], toProperty: 'networkPathRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::NET_PATH, operations: [new GetCollection()])] +#[ODM\Document] class NetworkPathDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\ReferenceOne(targetDocument=NetworkPathRelationDummy::class, inversedBy="networkPathDummies", storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: NetworkPathRelationDummy::class, inversedBy: 'networkPathDummies', storeAs: 'id')] public $networkPathRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php b/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php index 28bdee658bf..7335610f5d8 100644 --- a/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php +++ b/tests/Fixtures/TestBundle/Document/NetworkPathRelationDummy.php @@ -18,19 +18,13 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)] +#[ODM\Document] class NetworkPathRelationDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\ReferenceMany(targetDocument=NetworkPathDummy::class, mappedBy="networkPathRelationDummy") - */ + #[ODM\ReferenceMany(targetDocument: NetworkPathDummy::class, mappedBy: 'networkPathRelationDummy')] public $networkPathDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php b/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php index 1aa02e9ae12..6344b9c3132 100644 --- a/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php +++ b/tests/Fixtures/TestBundle/Document/NoCollectionDummy.php @@ -22,17 +22,15 @@ /** * No Collection Dummy. - * - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete()])] +#[ODM\Document] class NoCollectionDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Order.php b/tests/Fixtures/TestBundle/Document/Order.php index 55f7a6f3326..a2b20778504 100644 --- a/tests/Fixtures/TestBundle/Document/Order.php +++ b/tests/Fixtures/TestBundle/Document/Order.php @@ -18,27 +18,19 @@ use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -/** - * @ODM\Document - */ #[ApiResource(normalizationContext: ['groups' => ['order_read']], forceEager: false)] +#[ODM\Document] class Order { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups(['order_read'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\ReferenceOne(targetDocument=Customer::class) - */ #[Groups(['order_read'])] + #[ODM\ReferenceOne(targetDocument: Customer::class)] public $customer; - /** - * @ODM\ReferenceOne(targetDocument=Customer::class) - */ #[Assert\NotNull] #[Groups(['order_read'])] + #[ODM\ReferenceOne(targetDocument: Customer::class)] public $recipient; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php b/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php index 83a6be3eb57..399919077d4 100644 --- a/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php +++ b/tests/Fixtures/TestBundle/Document/OverriddenOperationDummy.php @@ -28,50 +28,44 @@ * Overridden Operation Dummy. * * @author Amrouche Hamza - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Get(normalizationContext: ['groups' => ['overridden_operation_dummy_get']], denormalizationContext: ['groups' => ['overridden_operation_dummy_get']]), new Put(normalizationContext: ['groups' => ['overridden_operation_dummy_put']], denormalizationContext: ['groups' => ['overridden_operation_dummy_put']]), new Delete(), new GetCollection(), new Post(), new GetCollection(uriTemplate: '/override/swagger')], normalizationContext: ['groups' => ['overridden_operation_dummy_read']], denormalizationContext: ['groups' => ['overridden_operation_dummy_write']])] +#[ODM\Document] class OverriddenOperationDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string The dummy name - * - * @ODM\Field */ #[Assert\NotBlank] #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get'])] #[ApiProperty(types: ['http://schema.org/name'])] + #[ODM\Field] private $name; /** * @var string The dummy name alias - * - * @ODM\Field(nullable=true) */ #[ApiProperty(types: ['http://schema.org/alternateName'])] #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_put', 'overridden_operation_dummy_get'])] + #[ODM\Field(nullable: true)] private $alias; /** * @var string A short description of the item - * - * @ODM\Field(nullable=true) */ #[ApiProperty(types: ['http://schema.org/description'])] #[Groups(['overridden_operation_dummy_read', 'overridden_operation_dummy_write', 'overridden_operation_dummy_get', 'overridden_operation_dummy_put'])] + #[ODM\Field(nullable: true)] public $description; - /** - * @ODM\Field(nullable=true) - */ #[Groups(['overridden_operation_dummy_write'])] + #[ODM\Field(nullable: true)] public $notGettable; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ParentDummy.php b/tests/Fixtures/TestBundle/Document/ParentDummy.php index a6f86f296fd..09f6569cf11 100644 --- a/tests/Fixtures/TestBundle/Document/ParentDummy.php +++ b/tests/Fixtures/TestBundle/Document/ParentDummy.php @@ -21,17 +21,15 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * - * @ODM\MappedSuperclass */ +#[ODM\MappedSuperclass] class ParentDummy { /** * @var int The age - * - * @ODM\Field(type="int", nullable=true) */ #[Groups(['friends'])] + #[ODM\Field(type: 'int', nullable: true)] private $age; public function getAge() diff --git a/tests/Fixtures/TestBundle/Document/PatchDummy.php b/tests/Fixtures/TestBundle/Document/PatchDummy.php index ea90fac19cc..b86e852b60f 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummy.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummy.php @@ -22,17 +22,13 @@ /** * @author Kévin Dunglas - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()])] +#[ODM\Document] class PatchDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $name; } diff --git a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php index 148369a30d9..ae5a9b477b1 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php @@ -23,19 +23,15 @@ /** * @author Kévin Dunglas - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] +#[ODM\Document] class PatchDummyRelation { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class) - */ #[Groups(['chicago'])] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class)] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Document/Payment.php b/tests/Fixtures/TestBundle/Document/Payment.php index 01274b2536a..c5e24d41006 100644 --- a/tests/Fixtures/TestBundle/Document/Payment.php +++ b/tests/Fixtures/TestBundle/Document/Payment.php @@ -20,19 +20,13 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Controller\Payment\VoidPaymentAction; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(operations: [new Get(), new Post(uriTemplate: '/payments/{id}/void', controller: VoidPaymentAction::class, deserialize: false), new Post(), new GetCollection()])] +#[ODM\Document] class Payment { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\ReferenceOne(targetDocument=VoidPayment::class, mappedBy="payment") - */ + #[ODM\ReferenceOne(targetDocument: VoidPayment::class, mappedBy: 'payment')] private $voidPayment; public function __construct(private readonly ?string $amount) diff --git a/tests/Fixtures/TestBundle/Document/Person.php b/tests/Fixtures/TestBundle/Document/Person.php index 707b50d18a0..b3de016d6e4 100644 --- a/tests/Fixtures/TestBundle/Document/Person.php +++ b/tests/Fixtures/TestBundle/Document/Person.php @@ -22,30 +22,23 @@ * Person. * * @author Antoine Bluchet - * @ODM\Document */ #[ApiResource(normalizationContext: ['groups' => ['people.pets']])] +#[ODM\Document] class Person { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(type="string") - */ #[Groups(['people.pets'])] + #[ODM\Field(type: 'string')] public $name; /** - * @ODM\ReferenceMany(targetDocument=PersonToPet::class, mappedBy="person") - * * @var ArrayCollection */ #[Groups(['people.pets'])] + #[ODM\ReferenceMany(targetDocument: PersonToPet::class, mappedBy: 'person')] public $pets; - /** - * @ODM\ReferenceMany(targetDocument=Greeting::class, mappedBy="sender") - */ + #[ODM\ReferenceMany(targetDocument: Greeting::class, mappedBy: 'sender')] public $sentGreetings; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/PersonToPet.php b/tests/Fixtures/TestBundle/Document/PersonToPet.php index 47733105272..819221e7d82 100644 --- a/tests/Fixtures/TestBundle/Document/PersonToPet.php +++ b/tests/Fixtures/TestBundle/Document/PersonToPet.php @@ -20,28 +20,22 @@ * PersonToPet. * * @author Antoine Bluchet - * @ODM\Document */ +#[ODM\Document] class PersonToPet { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\ReferenceOne(targetDocument=Pet::class) - * * @var Pet */ #[Groups(['people.pets'])] + #[ODM\ReferenceOne(targetDocument: Pet::class)] public $pet; - /** - * @ODM\ReferenceOne(targetDocument=Person::class) - * * @var Person */ + #[ODM\ReferenceOne(targetDocument: Person::class)] public $person; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/Pet.php b/tests/Fixtures/TestBundle/Document/Pet.php index 5a23178a475..9e73c844cd4 100644 --- a/tests/Fixtures/TestBundle/Document/Pet.php +++ b/tests/Fixtures/TestBundle/Document/Pet.php @@ -22,25 +22,20 @@ * Pet. * * @author Antoine Bluchet - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class Pet { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(type="string") - */ #[Groups(['people.pets'])] + #[ODM\Field(type: 'string')] public $name; /** - * @ODM\ReferenceMany(targetDocument=PersonToPet::class, mappedBy="pet") - * * @var ArrayCollection */ + #[ODM\ReferenceMany(targetDocument: PersonToPet::class, mappedBy: 'pet')] public $people; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/ProcessorEntity.php b/tests/Fixtures/TestBundle/Document/ProcessorEntity.php index ed2d461cd2e..bfb3046b31e 100644 --- a/tests/Fixtures/TestBundle/Document/ProcessorEntity.php +++ b/tests/Fixtures/TestBundle/Document/ProcessorEntity.php @@ -21,23 +21,18 @@ /** * ProcessorEntity. - * - * @ODM\Document */ #[ApiResource] #[Get] #[Post] +#[ODM\Document] class ProcessorEntity { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field - */ #[Assert\NotBlank] + #[ODM\Field] private ?string $foo = null; /** diff --git a/tests/Fixtures/TestBundle/Document/Product.php b/tests/Fixtures/TestBundle/Document/Product.php index bc7cc51651f..60c9bd18a19 100644 --- a/tests/Fixtures/TestBundle/Document/Product.php +++ b/tests/Fixtures/TestBundle/Document/Product.php @@ -17,24 +17,14 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ +#[ODM\Document] class Product implements ProductInterface { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private ?string $code = null; - - /** - * @ODM\ReferenceOne(targetDocument=Taxon::class) - */ + #[ODM\ReferenceOne(targetDocument: Taxon::class)] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Document\Taxon $mainTaxon = null; /** diff --git a/tests/Fixtures/TestBundle/Document/Program.php b/tests/Fixtures/TestBundle/Document/Program.php index 6d69b40b763..3a681aedda5 100644 --- a/tests/Fixtures/TestBundle/Document/Program.php +++ b/tests/Fixtures/TestBundle/Document/Program.php @@ -17,29 +17,17 @@ /** * @author Vincent Chalamon - * - * @ODM\Document */ +#[ODM\Document] class Program { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] public $name; - - /** - * @ODM\Field(type="date") - */ + #[ODM\Field(type: 'date')] public $date; - - /** - * @ODM\ReferenceOne(targetDocument=User::class, storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: User::class, storeAs: 'id')] public $author; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ProviderEntity.php b/tests/Fixtures/TestBundle/Document/ProviderEntity.php index 35c28c9b6ea..cca5a15a781 100644 --- a/tests/Fixtures/TestBundle/Document/ProviderEntity.php +++ b/tests/Fixtures/TestBundle/Document/ProviderEntity.php @@ -22,24 +22,19 @@ /** * ProviderEntity. - * - * @ODM\Document */ #[ApiResource] #[Get] #[GetCollection] #[Post] +#[ODM\Document] class ProviderEntity { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field - */ #[Assert\NotBlank] + #[ODM\Field] private ?string $foo = null; /** diff --git a/tests/Fixtures/TestBundle/Document/Question.php b/tests/Fixtures/TestBundle/Document/Question.php index 93e3db514f8..91bb15c207f 100644 --- a/tests/Fixtures/TestBundle/Document/Question.php +++ b/tests/Fixtures/TestBundle/Document/Question.php @@ -19,25 +19,17 @@ use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] #[ApiResource(uriTemplate: '/answers/{id}/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Answer::class, identifiers: ['id'], toProperty: 'answer')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/questions/{id}/answer/related_questions.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], fromProperty: 'answer'), 'answer' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Answer::class, identifiers: [], expandedValue: 'answer', toProperty: 'answer')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class Question { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; - /** - * @ODM\Field(nullable=true) - */ + #[ODM\Field(nullable: true)] private $content; - /** - * @ODM\ReferenceOne(targetDocument=Answer::class, inversedBy="question", storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: Answer::class, inversedBy: 'question', storeAs: 'id')] private $answer; /** diff --git a/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php b/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php index 6541deb09a9..d42e588e879 100644 --- a/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php +++ b/tests/Fixtures/TestBundle/Document/ReadableOnlyProperty.php @@ -17,25 +17,21 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class ReadableOnlyProperty { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string The foo name - * - * @ODM\Field */ #[ApiProperty(writable: false)] + #[ODM\Field] private readonly string $name; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/RelatedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedDummy.php index 7d24fbfbdfb..f23f6ac1fb9 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedDummy.php @@ -31,7 +31,6 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * @ODM\Document */ #[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.mongodb.friends'])] #[ApiResource(uriTemplate: '/dummies/{id}/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] @@ -41,57 +40,46 @@ #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.mongodb.friends'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])] +#[ODM\Document] class RelatedDummy extends ParentDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ #[Groups(['chicago', 'friends'])] #[ApiProperty(writable: false)] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; /** * @var string A name - * - * @ODM\Field(type="string", nullable=true) */ #[Groups(['friends'])] + #[ODM\Field(type: 'string', nullable: true)] public $name; - /** - * @ODM\Field(type="string") - */ #[Groups(['barcelona', 'chicago', 'friends'])] + #[ODM\Field(type: 'string')] protected $symfony = 'symfony'; /** * @var \DateTime A dummy date - * - * @ODM\Field(type="date", nullable=true) */ #[Assert\DateTime] #[Groups(['friends'])] + #[ODM\Field(type: 'date', nullable: true)] public $dummyDate; - /** - * @ODM\ReferenceOne(targetDocument=ThirdLevel::class, cascade={"persist"}, nullable=true, storeAs="id") - */ #[Groups(['barcelona', 'chicago', 'friends'])] + #[ODM\ReferenceOne(targetDocument: ThirdLevel::class, cascade: ['persist'], nullable: true, storeAs: 'id')] public $thirdLevel; - /** - * @ODM\ReferenceMany(targetDocument=RelatedToDummyFriend::class, cascade={"persist"}, mappedBy="relatedDummy", storeAs="id") - */ #[Groups(['fakemanytomany', 'friends'])] + #[ODM\ReferenceMany(targetDocument: RelatedToDummyFriend::class, cascade: ['persist'], mappedBy: 'relatedDummy', storeAs: 'id')] public $relatedToDummyFriend; /** * @var bool A dummy bool - * - * @ODM\Field(type="bool") */ #[Groups(['friends'])] + #[ODM\Field(type: 'bool')] public $dummyBoolean; /** * @var EmbeddableDummy - * - * @ODM\EmbedOne(targetDocument=EmbeddableDummy::class) */ #[Groups(['friends'])] + #[ODM\EmbedOne(targetDocument: EmbeddableDummy::class)] public $embeddedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php index 95043bdb915..a9ff3629cd9 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedNormalizedDummy.php @@ -25,34 +25,31 @@ * Related to Normalized Dummy. * * @author Amrouche Hamza - * @ODM\Document */ #[ApiResource(normalizationContext: ['groups' => ['related_output', 'output']], denormalizationContext: ['groups' => ['related_input', 'input']])] +#[ODM\Document] class RelatedNormalizedDummy { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ #[Groups(['related_output', 'related_input'])] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The dummy name - * - * @ODM\Field */ #[Assert\NotBlank] #[ApiProperty(types: ['http://schema.org/name'])] #[Groups(['related_output', 'related_input'])] + #[ODM\Field] private ?string $name = null; /** * @var iterable Several Normalized dummies - * - * @ODM\ReferenceMany(targetDocument=CustomNormalizedDummy::class) */ #[Groups(['related_output', 'related_input'])] + #[ODM\ReferenceMany(targetDocument: CustomNormalizedDummy::class)] public $customNormalizedDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php b/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php index cb12d783f6a..2621e028f5a 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedOwnedDummy.php @@ -22,25 +22,22 @@ * * @author Sergey V. Ryabov * @author Alan Poulain - * @ODM\Document */ #[ApiResource(types: ['https://schema.org/Product'])] +#[ODM\Document] class RelatedOwnedDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; /** * @var string|null A name - * - * @ODM\Field(type="string") */ + #[ODM\Field(type: 'string')] public $name; /** * @var \Dummy|null - * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, inversedBy="relatedOwnedDummy", storeAs="id") */ + #[ODM\ReferenceOne(targetDocument: Dummy::class, cascade: ['persist'], inversedBy: 'relatedOwnedDummy', storeAs: 'id')] public $owningDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php b/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php index f59f6643609..785d0110d4d 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedOwningDummy.php @@ -22,25 +22,22 @@ * * @author Sergey V. Ryabov * @author Alan Poulain - * @ODM\Document */ #[ApiResource(types: ['https://schema.org/Product'])] +#[ODM\Document] class RelatedOwningDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; /** * @var string A name - * - * @ODM\Field(type="string") */ + #[ODM\Field(type: 'string')] public $name; /** * @var \Dummy - * @ODM\ReferenceOne(targetDocument=Dummy::class, cascade={"persist"}, mappedBy="relatedOwningDummy") */ + #[ODM\ReferenceOne(targetDocument: Dummy::class, cascade: ['persist'], mappedBy: 'relatedOwningDummy')] public $ownedDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php b/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php index 4bcdd1ed222..97df42e8beb 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/RelatedSecuredDummy.php @@ -20,17 +20,14 @@ use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_ADMIN\')'), new GetCollection(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\')'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')')], security: 'is_granted(\'ROLE_ADMIN\')')] +#[ODM\Document] class RelatedSecuredDummy { /** * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php b/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php index 8ca0284f410..7db18122581 100644 --- a/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php +++ b/tests/Fixtures/TestBundle/Document/RelatedToDummyFriend.php @@ -23,8 +23,6 @@ /** * Related To Dummy Friend represent an association table for a manytomany relation. - * - * @ODM\Document */ #[ApiResource(normalizationContext: ['groups' => ['fakemanytomany']], filters: ['related_to_dummy_friend.mongodb.name'])] #[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] @@ -32,38 +30,31 @@ #[ApiResource(uriTemplate: '/related_dummies/{id}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/related_to_dummy_friends.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], toProperty: 'relatedDummy')], status: 200, filters: ['related_to_dummy_friend.mongodb.name'], normalizationContext: ['groups' => ['fakemanytomany']], operations: [new GetCollection()])] +#[ODM\Document] class RelatedToDummyFriend { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; /** * @var string The dummy name - * - * @ODM\Field(type="string") */ #[Assert\NotBlank] #[ApiProperty(types: ['http://schema.org/name'])] #[Groups(['fakemanytomany', 'friends'])] + #[ODM\Field(type: 'string')] private $name; /** * @var string|null The dummy description - * - * @ODM\Field(type="string") */ #[Groups(['fakemanytomany', 'friends'])] + #[ODM\Field(type: 'string')] private ?string $description = null; - /** - * @ODM\ReferenceOne(targetDocument=DummyFriend::class, storeAs="id") - */ #[Groups(['fakemanytomany', 'friends'])] #[Assert\NotNull] + #[ODM\ReferenceOne(targetDocument: DummyFriend::class, storeAs: 'id')] private $dummyFriend; - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, inversedBy="relatedToDummyFriend", storeAs="id") - */ #[Assert\NotNull] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, inversedBy: 'relatedToDummyFriend', storeAs: 'id')] private $relatedDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/RelationEmbedder.php b/tests/Fixtures/TestBundle/Document/RelationEmbedder.php index 8220e596f4d..b96cfe2b355 100644 --- a/tests/Fixtures/TestBundle/Document/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Document/RelationEmbedder.php @@ -26,34 +26,24 @@ * Relation Embedder. * * @author Kévin Dunglas - * @ODM\Document */ #[ApiResource(operations: [new Get(), new Put(), new Delete(), new Get(routeName: 'relation_embedded.custom_get'), new Get(uriTemplate: '/api/custom-call/{id}'), new Put(uriTemplate: '/api/custom-call/{id}'), new Post(), new GetCollection()], normalizationContext: ['groups' => ['barcelona']], denormalizationContext: ['groups' => ['chicago']], hydraContext: ['@type' => 'hydra:Operation', 'hydra:title' => 'A custom operation', 'returns' => 'xmls:string'])] +#[ODM\Document] class RelationEmbedder { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - /** - * @ODM\Field - */ #[Groups(['chicago'])] + #[ODM\Field] public $paris = 'Paris'; - /** - * @ODM\Field - */ #[Groups(['barcelona', 'chicago'])] + #[ODM\Field] public $krondstadt = 'Krondstadt'; - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, cascade={"persist"}) - */ #[Groups(['chicago', 'barcelona'])] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, cascade: ['persist'])] public $anotherRelated; - /** - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class) - */ #[Groups(['barcelona', 'chicago'])] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class)] protected $related; public function getRelated() diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php b/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php index d30e0561579..ebe50eb2a11 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithBoolean.php @@ -16,21 +16,16 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class ResourceWithBoolean { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="bool") - */ + #[ODM\Field(type: 'bool')] private bool $myBooleanField = false; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php b/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php index 4ce1c0e0428..5e0b73f84c1 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithFloat.php @@ -16,21 +16,16 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class ResourceWithFloat { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="float") - */ + #[ODM\Field(type: 'float')] private float $myFloatField = 0.0; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php b/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php index cd8c0ce3dd6..16258b8c99e 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithInteger.php @@ -16,21 +16,16 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class ResourceWithInteger { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="int") - */ + #[ODM\Field(type: 'int')] private int $myIntegerField = 0; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/ResourceWithString.php b/tests/Fixtures/TestBundle/Document/ResourceWithString.php index 902c6afd786..f1afac729f8 100644 --- a/tests/Fixtures/TestBundle/Document/ResourceWithString.php +++ b/tests/Fixtures/TestBundle/Document/ResourceWithString.php @@ -16,21 +16,16 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class ResourceWithString { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private string $myStringField = ''; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/SecuredDummy.php b/tests/Fixtures/TestBundle/Document/SecuredDummy.php index ba6d67d6506..7e8dbe547b9 100644 --- a/tests/Fixtures/TestBundle/Document/SecuredDummy.php +++ b/tests/Fixtures/TestBundle/Document/SecuredDummy.php @@ -32,105 +32,92 @@ * * @author Kévin Dunglas * @author Alan Poulain - * @ODM\Document */ #[ApiResource(operations: [new Get(security: 'is_granted(\'ROLE_USER\') and object.getOwner() == user'), new Put(securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new GetCollection(security: 'is_granted(\'ROLE_USER\') or is_granted(\'ROLE_ADMIN\')'), new GetCollection(uriTemplate: 'custom_data_provider_generator', security: 'is_granted(\'ROLE_USER\')'), new Post(security: 'is_granted(\'ROLE_ADMIN\')')], graphQlOperations: [new Query(name: 'item_query', security: 'is_granted(\'ROLE_ADMIN\') or (is_granted(\'ROLE_USER\') and object.getOwner() == user)'), new QueryCollection(name: 'collection_query', security: 'is_granted(\'ROLE_ADMIN\')'), new Mutation(name: 'delete'), new Mutation(name: 'update', securityPostDenormalize: 'is_granted(\'ROLE_USER\') and previous_object.getOwner() == user'), new Mutation(name: 'create', security: 'is_granted(\'ROLE_ADMIN\')', securityMessage: 'Only admins can create a secured dummy.')], security: 'is_granted(\'ROLE_USER\')')] +#[ODM\Document] class SecuredDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The title - * - * @ODM\Field */ #[Assert\NotBlank] + #[ODM\Field] private ?string $title = null; /** * @var string The description - * - * @ODM\Field */ + #[ODM\Field] private string $description = ''; /** * @var string The dummy secret property, only readable/writable by specific users - * - * @ODM\Field */ #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ODM\Field] private ?string $adminOnlyProperty = ''; /** * @var string Secret property, only readable/writable by owners - * - * @ODM\Field */ #[ApiProperty(security: 'object == null or object.getOwner() == user', securityPostDenormalize: 'object.getOwner() == user')] + #[ODM\Field] private ?string $ownerOnlyProperty = ''; /** * @var string|null The owner - * - * @ODM\Field */ #[Assert\NotBlank] + #[ODM\Field] private ?string $owner = null; /** * @var Collection Several dummies - * - * @ODM\ReferenceMany(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ODM\ReferenceMany(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] public $relatedDummies; /** * @var RelatedDummy - * - * @ODM\ReferenceOne(targetDocument=RelatedDummy::class, storeAs="id", nullable=true) */ #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] + #[ODM\ReferenceOne(targetDocument: RelatedDummy::class, storeAs: 'id', nullable: true)] protected $relatedDummy; /** * A collection of dummies that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies - * - * @ODM\ReferenceMany(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) */ #[ApiProperty(security: "is_granted('ROLE_USER')")] + #[ODM\ReferenceMany(targetDocument: RelatedSecuredDummy::class, storeAs: 'id', nullable: true)] public $relatedSecuredDummies; /** * A dummy that only users can access. The security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy - * - * @ODM\ReferenceOne(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) */ #[ApiProperty(security: "is_granted('ROLE_USER')")] + #[ODM\ReferenceOne(targetDocument: RelatedSecuredDummy::class, storeAs: 'id', nullable: true)] protected $relatedSecuredDummy; /** * Collection of dummies that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * * @var Collection Several dummies - * - * @ODM\ReferenceMany(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceMany(targetDocument: RelatedSecuredDummy::class, storeAs: 'id', nullable: true)] public $publicRelatedSecuredDummies; /** * A dummy that anyone can access. There is no ApiProperty security, and the security on RelatedSecuredDummy shouldn't be run. * * @var RelatedSecuredDummy - * - * @ODM\ReferenceOne(targetDocument=RelatedSecuredDummy::class, storeAs="id", nullable=true) */ + #[ODM\ReferenceOne(targetDocument: RelatedSecuredDummy::class, storeAs: 'id', nullable: true)] protected $publicRelatedSecuredDummy; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php b/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php index 914446960cd..6e4de942ade 100644 --- a/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php +++ b/tests/Fixtures/TestBundle/Document/SingleFileConfigDummy.php @@ -17,23 +17,19 @@ /** * File Config Dummy. - * - * @ODM\Document */ +#[ODM\Document] class SingleFileConfigDummy { /** * @var int The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] private $name; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/SlugChildDummy.php b/tests/Fixtures/TestBundle/Document/SlugChildDummy.php index c5b4dfd058b..543a4ac8963 100644 --- a/tests/Fixtures/TestBundle/Document/SlugChildDummy.php +++ b/tests/Fixtures/TestBundle/Document/SlugChildDummy.php @@ -19,33 +19,27 @@ use ApiPlatform\Metadata\Link; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] #[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugParentDummy::class, identifiers: ['slug'], toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] #[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy/child_dummies.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], fromProperty: 'parentDummy'), 'parentDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugParentDummy::class, identifiers: [], expandedValue: 'parent_dummy', toProperty: 'parentDummy')], status: 200, operations: [new GetCollection()])] +#[ODM\Document] class SlugChildDummy { /** * @var int The identifier - * - * @ODM\Id(strategy="INCREMENT", type="int") */ #[ApiProperty(identifier: false)] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string The slug used as API identifier - * - * @ODM\Field */ #[ApiProperty(identifier: true)] + #[ODM\Field] private ?string $slug = null; - /** - * @ODM\ReferenceOne(targetDocument=SlugParentDummy::class, inversedBy="childDummies", storeAs="id") - */ + #[ODM\ReferenceOne(targetDocument: SlugParentDummy::class, inversedBy: 'childDummies', storeAs: 'id')] private $parentDummy; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/SlugParentDummy.php b/tests/Fixtures/TestBundle/Document/SlugParentDummy.php index b6e093a2ecc..12318bf5ab3 100644 --- a/tests/Fixtures/TestBundle/Document/SlugParentDummy.php +++ b/tests/Fixtures/TestBundle/Document/SlugParentDummy.php @@ -23,35 +23,31 @@ /** * Custom Identifier Dummy With Subresource. - * - * @ODM\Document */ #[ApiResource(uriVariables: 'slug')] #[ApiResource(uriTemplate: '/slug_parent_dummies/{slug}/child_dummies/{childDummies}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: self::class, identifiers: ['slug'], toProperty: 'parentDummy'), 'childDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/slug_child_dummies/{slug}/parent_dummy.{_format}', uriVariables: ['slug' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\SlugChildDummy::class, identifiers: ['slug'], fromProperty: 'parentDummy')], status: 200, operations: [new Get()])] +#[ODM\Document] class SlugParentDummy { /** * @var int|null The database identifier - * - * @ODM\Id(strategy="INCREMENT", type="int") */ #[ApiProperty(identifier: false)] + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; /** * @var string|null The slug used a API identifier - * - * @ODM\Field */ #[ApiProperty(identifier: true)] + #[ODM\Field] private ?string $slug = null; /** - * @ODM\ReferenceMany(targetDocument=SlugChildDummy::class, mappedBy="parentDummy") - * * @var \Collection */ + #[ODM\ReferenceMany(targetDocument: SlugChildDummy::class, mappedBy: 'parentDummy')] private \Collection $childDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Document/SoMany.php b/tests/Fixtures/TestBundle/Document/SoMany.php index fa56e94f4d1..3fcc1fb03ef 100644 --- a/tests/Fixtures/TestBundle/Document/SoMany.php +++ b/tests/Fixtures/TestBundle/Document/SoMany.php @@ -19,20 +19,14 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiFilter(RangeFilter::class, properties: ['id'])] #[ApiFilter(OrderFilter::class, properties: ['id' => 'DESC'])] #[ApiResource(paginationPartial: true, paginationViaCursor: [['field' => 'id', 'direction' => 'DESC']])] +#[ODM\Document] class SoMany { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; - /** - * @ODM\Field(nullable=true) - */ + #[ODM\Field(nullable: true)] public $content; } diff --git a/tests/Fixtures/TestBundle/Document/Taxon.php b/tests/Fixtures/TestBundle/Document/Taxon.php index c3e491cd3ff..30e948be12f 100644 --- a/tests/Fixtures/TestBundle/Document/Taxon.php +++ b/tests/Fixtures/TestBundle/Document/Taxon.php @@ -16,19 +16,12 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Model\TaxonInterface; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ +#[ODM\Document] class Taxon implements TaxonInterface { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - - /** - * @ODM\Field(type="string") - */ + #[ODM\Field(type: 'string')] private ?string $code = null; /** diff --git a/tests/Fixtures/TestBundle/Document/ThirdLevel.php b/tests/Fixtures/TestBundle/Document/ThirdLevel.php index bd118b0b8cd..2b0c83aa2d8 100644 --- a/tests/Fixtures/TestBundle/Document/ThirdLevel.php +++ b/tests/Fixtures/TestBundle/Document/ThirdLevel.php @@ -24,7 +24,6 @@ * * @author Kévin Dunglas * @author Alexandre Delplace - * @ODM\Document */ #[ApiResource] #[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] @@ -32,31 +31,23 @@ #[ApiResource(uriTemplate: '/related_dummies/{id}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] #[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level.{_format}', uriVariables: ['id' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: \ApiPlatform\Tests\Fixtures\TestBundle\Document\RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel')], status: 200, operations: [new Get()])] +#[ODM\Document] class ThirdLevel { /** * @var int|null The id - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; - /** - * @ODM\Field(type="int") - */ #[Groups(['barcelona', 'chicago'])] + #[ODM\Field(type: 'int')] private int $level = 3; - /** - * @ODM\Field(type="bool") - */ + #[ODM\Field(type: 'bool')] private bool $test = true; - /** - * @ODM\ReferenceOne(targetDocument=FourthLevel::class, cascade={"persist"}, storeAs="id") - */ #[Groups(['barcelona', 'chicago', 'friends'])] + #[ODM\ReferenceOne(targetDocument: FourthLevel::class, cascade: ['persist'], storeAs: 'id')] public $fourthLevel; - /** - * @ODM\ReferenceOne(targetDocument=FourthLevel::class, cascade={"persist"}) - */ + #[ODM\ReferenceOne(targetDocument: FourthLevel::class, cascade: ['persist'])] public $badFourthLevel; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/UrlEncodedId.php b/tests/Fixtures/TestBundle/Document/UrlEncodedId.php index c1f9227db5a..f6b430443a7 100644 --- a/tests/Fixtures/TestBundle/Document/UrlEncodedId.php +++ b/tests/Fixtures/TestBundle/Document/UrlEncodedId.php @@ -23,14 +23,12 @@ * @author Daniel West * * Resource with an ID that will be URL encoded - * @ODM\Document */ #[ApiResource(operations: [new Get(requirements: ['id' => '.+']), new Post(), new GetCollection()])] +#[ODM\Document] class UrlEncodedId { - /** - * @ODM\Id(strategy="none") - */ + #[ODM\Id(strategy: 'none')] private string $id = '%encode:id'; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/User.php b/tests/Fixtures/TestBundle/Document/User.php index c1781d0f0e0..d7c3290cf14 100644 --- a/tests/Fixtures/TestBundle/Document/User.php +++ b/tests/Fixtures/TestBundle/Document/User.php @@ -30,19 +30,17 @@ /** * A User. * - * @ODM\Document (collection="user_test") - * * @author Théo FIDRY * @author Kévin Dunglas */ #[ApiResource(operations: [new Get(), new Put(), new Delete(), new Put(input: RecoverPasswordInput::class, output: RecoverPasswordOutput::class, uriTemplate: 'users/recover/{id}'), new Post(), new GetCollection(), new Post(uriTemplate: '/users/password_reset_request', messenger: 'input', input: PasswordResetRequest::class, output: PasswordResetRequestResult::class, normalizationContext: ['groups' => ['user_password_reset_request']], denormalizationContext: ['groups' => ['user_password_reset_request']])], normalizationContext: ['groups' => ['user', 'user-read']], denormalizationContext: ['groups' => ['user', 'user-write']])] +#[ODM\Document(collection: 'user_test')] class User extends AbstractSecurityUser { /** * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] protected $id; /** * @var string|null @@ -51,10 +49,9 @@ class User extends AbstractSecurityUser protected $email; /** * @var string|null - * - * @ODM\Field(type="string", nullable=true) */ #[Groups(['user'])] + #[ODM\Field(type: 'string', nullable: true)] protected $fullname; /** * @var string|null diff --git a/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php b/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php index c68feacc570..e681eb6bba2 100644 --- a/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Document/UuidIdentifierDummy.php @@ -18,23 +18,20 @@ /** * Custom identifier dummy. - * - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class UuidIdentifierDummy { /** * @var string The custom identifier - * - * @ODM\Id(strategy="UUID") */ + #[ODM\Id(strategy: 'UUID')] private ?string $uuid = null; /** * @var string The dummy name - * - * @ODM\Field */ + #[ODM\Field] private ?string $name = null; public function getUuid(): string diff --git a/tests/Fixtures/TestBundle/Document/VoDummyCar.php b/tests/Fixtures/TestBundle/Document/VoDummyCar.php index a42225eba33..f8473c5925d 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyCar.php @@ -19,27 +19,18 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource(normalizationContext: ['groups' => ['car_read']], denormalizationContext: ['groups' => ['car_write']])] +#[ODM\Document] class VoDummyCar extends VoDummyVehicle { /** * @var VoDummyInspection[]|Collection - * - * @ODM\ReferenceMany(targetDocument=VoDummyInspection::class, mappedBy="car", cascade={"persist"}) */ #[Groups(['car_read', 'car_write'])] + #[ODM\ReferenceMany(targetDocument: VoDummyInspection::class, mappedBy: 'car', cascade: ['persist'])] private readonly array|\Doctrine\Common\Collections\Collection $inspections; - public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, /** - * @ODM\Field(type="int") - */ - #[Groups(['car_read', 'car_write'])] private readonly int $mileage, /** - * @ODM\Field - */ - #[Groups(['car_read', 'car_write'])] private readonly string $bodyType = 'coupe') + public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, #[Groups(['car_read', 'car_write'])] #[ODM\Field(type: 'int')] private readonly int $mileage, #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $bodyType = 'coupe') { parent::__construct($make, $insuranceCompany, $drivers); $this->inspections = new ArrayCollection(); diff --git a/tests/Fixtures/TestBundle/Document/VoDummyDriver.php b/tests/Fixtures/TestBundle/Document/VoDummyDriver.php index 441382771b2..5e059fe276c 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyDriver.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyDriver.php @@ -17,23 +17,15 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class VoDummyDriver { use VoDummyIdAwareTrait; public function __construct( - /** - * @ODM\Field - */ - #[Groups(['car_read', 'car_write'])] private readonly string $firstName, - /** - * @ODM\Field - */ - #[Groups(['car_read', 'car_write'])] private readonly string $lastName + #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $firstName, + #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $lastName ) { } diff --git a/tests/Fixtures/TestBundle/Document/VoDummyIdAwareTrait.php b/tests/Fixtures/TestBundle/Document/VoDummyIdAwareTrait.php index 2dc3cd328b0..e396227747e 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyIdAwareTrait.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyIdAwareTrait.php @@ -19,9 +19,8 @@ trait VoDummyIdAwareTrait { /** * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] protected $id; public function getId() diff --git a/tests/Fixtures/TestBundle/Document/VoDummyInspection.php b/tests/Fixtures/TestBundle/Document/VoDummyInspection.php index 49572bf6c22..c6313e282f5 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyInspection.php @@ -18,26 +18,16 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource(graphQlOperations: [], normalizationContext: ['groups' => ['inspection_read']], denormalizationContext: ['groups' => ['inspection_write']])] +#[ODM\Document] class VoDummyInspection { use VoDummyIdAwareTrait; - /** - * @ODM\Field(type="date") - */ #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] + #[ODM\Field(type: 'date')] private \DateTime $performed; - public function __construct(/** - * @ODM\Field(type="bool") - */ - #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private readonly bool $accepted, /** - * @ODM\ReferenceOne(targetDocument=VoDummyCar::class, inversedBy="inspections") - */ - #[Groups(['inspection_read', 'inspection_write'])] private readonly VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') + public function __construct(#[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] #[ODM\Field(type: 'bool')] private readonly bool $accepted, #[Groups(['inspection_read', 'inspection_write'])] #[ODM\ReferenceOne(targetDocument: VoDummyCar::class, inversedBy: 'inspections')] private readonly VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') { $this->performed = $performed ?: new DateTime(); } diff --git a/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php b/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php index 22474225ef2..3f2d3f5a7bd 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyInsuranceCompany.php @@ -17,19 +17,14 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class VoDummyInsuranceCompany { use VoDummyIdAwareTrait; public function __construct( - /** - * @ODM\Field - */ - #[Groups(['car_read', 'car_write'])] private readonly string $name + #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $name ) { } diff --git a/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php b/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php index 33c8fd1bc69..6c7abaf4c6f 100644 --- a/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php +++ b/tests/Fixtures/TestBundle/Document/VoDummyVehicle.php @@ -18,29 +18,20 @@ use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @ODM\MappedSuperclass - */ +#[ODM\MappedSuperclass] abstract class VoDummyVehicle { use VoDummyIdAwareTrait; /** * @var VoDummyDriver[]|Collection - * - * @ODM\ReferenceMany(targetDocument=VoDummyDriver::class, cascade={"persist"}) */ #[Groups(['car_read', 'car_write'])] + #[ODM\ReferenceMany(targetDocument: VoDummyDriver::class, cascade: ['persist'])] private readonly array|\Doctrine\Common\Collections\Collection $drivers; public function __construct( - /** - * @ODM\Field - */ - #[Groups(['car_read', 'car_write'])] private readonly string $make, - /** - * @ODM\ReferenceOne(targetDocument=VoDummyInsuranceCompany::class, cascade={"persist"}) - */ - #[Groups(['car_read', 'car_write'])] private readonly VoDummyInsuranceCompany $insuranceCompany, + #[Groups(['car_read', 'car_write'])] #[ODM\Field] private readonly string $make, + #[Groups(['car_read', 'car_write'])] #[ODM\ReferenceOne(targetDocument: VoDummyInsuranceCompany::class, cascade: ['persist'])] private readonly VoDummyInsuranceCompany $insuranceCompany, array $drivers ) { $this->drivers = new ArrayCollection($drivers); diff --git a/tests/Fixtures/TestBundle/Document/VoidPayment.php b/tests/Fixtures/TestBundle/Document/VoidPayment.php index 6598bcccf67..4e86efd8c39 100644 --- a/tests/Fixtures/TestBundle/Document/VoidPayment.php +++ b/tests/Fixtures/TestBundle/Document/VoidPayment.php @@ -16,22 +16,15 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class VoidPayment { - /** - * @ODM\Id(strategy="INCREMENT", type="int") - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private ?int $id = null; public function __construct( - /** - * @ODM\ReferenceOne(targetDocument=Payment::class, inversedBy="voidPayment") - */ - private readonly Payment $payment + #[ODM\ReferenceOne(targetDocument: Payment::class, inversedBy: 'voidPayment')] private readonly Payment $payment ) { } diff --git a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php index 492e5cb569c..98c33558e89 100644 --- a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php +++ b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php @@ -16,21 +16,16 @@ use ApiPlatform\Metadata\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * @ODM\Document - */ #[ApiResource] +#[ODM\Document] class WithJsonDummy { - /** - * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) - */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] private ?int $id = null; /** * @var array|null - * - * @ODM\Field(type="hash", nullable=true) */ + #[ODM\Field(type: 'hash', nullable: true)] public $json; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/WritableId.php b/tests/Fixtures/TestBundle/Document/WritableId.php index 12e5ab24dfa..096b7c1e43f 100644 --- a/tests/Fixtures/TestBundle/Document/WritableId.php +++ b/tests/Fixtures/TestBundle/Document/WritableId.php @@ -19,18 +19,14 @@ /** * @author Kévin Dunglas - * @ODM\Document */ #[ApiResource] +#[ODM\Document] class WritableId { - /** - * @ODM\Id(strategy="UUID", type="string") - */ #[Assert\Uuid] + #[ODM\Id(strategy: 'UUID', type: 'string')] public $id; - /** - * @ODM\Field - */ + #[ODM\Field] public $name; } From 59d811e4f64dac713a24125a4dc2cbcd9f6fe512 Mon Sep 17 00:00:00 2001 From: Vincent Date: Fri, 13 May 2022 11:58:17 +0200 Subject: [PATCH 10/56] Metadata (#36) * test: fix Metadata tests * test: remove legacy environments from Behat tests * chore: remove deprecations from DeprecationMetadataTrait and rename it to SanitizeMetadataTrait * chore: remove annotation support on Metadata * fix: PHP CS * fix: typo * chore: remove SanitizeMetadataTrait * chore: set PHP dependency to 8.1 in composer.json * fix: PHP typo --- composer.json | 2 +- .../Property/DeprecationMetadataTrait.php | 48 ---- .../AttributePropertyMetadataFactory.php | 12 +- .../ExtractorPropertyMetadataFactory.php | 15 - .../Factory/LegacyPropertyMetadataFactory.php | 88 ------ .../Resource/DeprecationMetadataTrait.php | 84 ------ ...butesResourceMetadataCollectionFactory.php | 10 +- ...actorResourceMetadataCollectionFactory.php | 11 +- ...ltersResourceMetadataCollectionFactory.php | 20 +- ...adataResourceMetadataCollectionFactory.php | 265 ----------------- ...adataResourceMetadataCollectionFactory.php | 190 ------------- src/Symfony/Bundle/ApiPlatformBundle.php | 4 - .../Compiler/AnnotationFilterPass.php | 102 ------- .../Resources/config/metadata/resource.xml | 1 - src/Util/AnnotationFilterExtractorTrait.php | 157 ---------- .../FileConfigurations/properties.xml | 13 + .../FileConfigurations/properties.yml | 11 + .../FileConfigurations/propertiesinvalid.yml | 4 +- .../FileConfigurations/propertyinvalid.xml | 18 +- .../FileConfigurations/propertyinvalid.yml | 5 +- .../Fixtures/FileConfigurations/resources.xml | 82 ------ .../Fixtures/FileConfigurations/resources.yml | 48 ---- .../Fixtures/TestBundle/Document/Content.php | 2 +- .../Fixtures/TestBundle/Entity/DummyPhp8.php | 16 +- .../TestBundle/Entity/FilterValidator.php | 4 +- .../resources.yaml | 0 .../config/api_resources_legacy/resources.yml | 30 -- .../api_resources_legacy_odm/resources.yml | 16 -- .../api_resources_legacy_orm/resources.yml | 17 -- .../properties.xml | 0 .../resources.xml | 0 .../resources.yaml | 0 .../properties.xml | 0 .../resources.xml | 0 .../resources.yaml | 0 .../Util/AnnotationFilterExtractor.php | 31 -- tests/Fixtures/app/AppKernel.php | 34 +-- .../app/config/{config_v3.yml => config.yml} | 1 - ..._metadata_backward_compatibility_layer.yml | 6 - .../PropertyMetadataCompatibilityTest.php | 3 - .../ResourceMetadataCompatibilityTest.php | 3 - .../CachedPropertyMetadataFactoryTest.php | 2 +- ...actorPropertyNameCollectionFactoryTest.php | 46 ++- .../Property/PropertyNameCollectionTest.php | 2 +- .../Resource/Factory/LinkFactoryTest.php | 2 +- ...eResourceMetadataCollectionFactoryTest.php | 2 +- .../Symfony/Bundle/ApiPlatformBundleTest.php | 3 - .../Compiler/AnnotationFilterPassTest.php | 269 ------------------ 48 files changed, 85 insertions(+), 1594 deletions(-) delete mode 100644 src/Metadata/Property/DeprecationMetadataTrait.php delete mode 100644 src/Metadata/Property/Factory/LegacyPropertyMetadataFactory.php delete mode 100644 src/Metadata/Resource/DeprecationMetadataTrait.php delete mode 100644 src/Metadata/Resource/Factory/LegacyResourceMetadataResourceMetadataCollectionFactory.php delete mode 100644 src/Metadata/Resource/Factory/LegacySubresourceMetadataResourceMetadataCollectionFactory.php delete mode 100644 src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php delete mode 100644 src/Util/AnnotationFilterExtractorTrait.php create mode 100644 tests/Fixtures/FileConfigurations/properties.xml create mode 100644 tests/Fixtures/FileConfigurations/properties.yml delete mode 100644 tests/Fixtures/FileConfigurations/resources.xml delete mode 100644 tests/Fixtures/FileConfigurations/resources.yml rename tests/Fixtures/TestBundle/Resources/config/{api_resources_v3 => api_resources}/resources.yaml (100%) delete mode 100644 tests/Fixtures/TestBundle/Resources/config/api_resources_legacy/resources.yml delete mode 100644 tests/Fixtures/TestBundle/Resources/config/api_resources_legacy_odm/resources.yml delete mode 100644 tests/Fixtures/TestBundle/Resources/config/api_resources_legacy_orm/resources.yml rename tests/Fixtures/TestBundle/Resources/config/{api_resources_v3_odm => api_resources_odm}/properties.xml (100%) rename tests/Fixtures/TestBundle/Resources/config/{api_resources_v3_odm => api_resources_odm}/resources.xml (100%) rename tests/Fixtures/TestBundle/Resources/config/{api_resources_v3_odm => api_resources_odm}/resources.yaml (100%) rename tests/Fixtures/TestBundle/Resources/config/{api_resources_v3_orm => api_resources_orm}/properties.xml (100%) rename tests/Fixtures/TestBundle/Resources/config/{api_resources_v3_orm => api_resources_orm}/resources.xml (100%) rename tests/Fixtures/TestBundle/Resources/config/{api_resources_v3_orm => api_resources_orm}/resources.yaml (100%) delete mode 100644 tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php rename tests/Fixtures/app/config/{config_v3.yml => config.yml} (99%) delete mode 100644 tests/Fixtures/app/config/config_metadata_backward_compatibility_layer.yml delete mode 100644 tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php diff --git a/composer.json b/composer.json index f17c1ee757f..d262f4f25b7 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ } ], "require": { - "php": ">=7.1", + "php": ">=8.1", "doctrine/inflector": "^1.0 || ^2.0", "fig/link-util": "^1.0", "psr/cache": "^1.0 || ^2.0 || ^3.0", diff --git a/src/Metadata/Property/DeprecationMetadataTrait.php b/src/Metadata/Property/DeprecationMetadataTrait.php deleted file mode 100644 index a270f4ad86e..00000000000 --- a/src/Metadata/Property/DeprecationMetadataTrait.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * 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\Metadata\Property; - -use ApiPlatform\Core\Annotation\ApiProperty; -use ApiPlatform\Metadata\ApiProperty as ApiPropertyMetadata; -use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; - -/** - * @internal - */ -trait DeprecationMetadataTrait -{ - private $camelCaseToSnakeCaseNameConverter; - - private function withDeprecatedAttributes(ApiPropertyMetadata $propertyMetadata, array $attributes): ApiPropertyMetadata - { - $extraProperties = []; - if (!$this->camelCaseToSnakeCaseNameConverter) { - $this->camelCaseToSnakeCaseNameConverter = new CamelCaseToSnakeCaseNameConverter(); - } - - foreach ($attributes as $key => $value) { - $propertyName = $this->camelCaseToSnakeCaseNameConverter->denormalize($key); - - if (method_exists($propertyMetadata, $methodName = 'with'.ucfirst($propertyName))) { - trigger_deprecation('api-platform', '2.7', sprintf('Using "%s" inside attributes on the "%s" annotation is deprecated, use "%s" on the attribute "%s" instead', $key, ApiProperty::class, $propertyName, ApiPropertyMetadata::class)); - $propertyMetadata = $propertyMetadata->{$methodName}($value); - continue; - } - - $extraProperties[$key] = $value; - } - - return $propertyMetadata->withExtraProperties($propertyMetadata->getExtraProperties() + $extraProperties); - } -} diff --git a/src/Metadata/Property/Factory/AttributePropertyMetadataFactory.php b/src/Metadata/Property/Factory/AttributePropertyMetadataFactory.php index ed9c4f7d550..231e3938392 100644 --- a/src/Metadata/Property/Factory/AttributePropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/AttributePropertyMetadataFactory.php @@ -100,17 +100,7 @@ private function createMetadata(ApiProperty $attribute, ApiProperty $propertyMet } foreach (get_class_methods(ApiProperty::class) as $method) { - if ( - // TODO: remove these checks for deprecated methods in 3.0 - 'getAttribute' !== $method && - 'isChildInherited' !== $method && - 'getSubresource' !== $method && - 'getAttributes' !== $method && - // end of deprecated methods - - preg_match('/^(?:get|is)(.*)/', $method, $matches) && - null !== $val = $attribute->{$method}() - ) { + if (preg_match('/^(?:get|is)(.*)/', $method, $matches) && null !== $val = $attribute->{$method}()) { $propertyMetadata = $propertyMetadata->{"with{$matches[1]}"}($val); } } diff --git a/src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php b/src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php index 6b019947b95..e9feb7cb77e 100644 --- a/src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php @@ -16,7 +16,6 @@ use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Extractor\PropertyExtractorInterface; -use ApiPlatform\Metadata\Property\DeprecationMetadataTrait; use Symfony\Component\PropertyInfo\Type; /** @@ -27,7 +26,6 @@ */ final class ExtractorPropertyMetadataFactory implements PropertyMetadataFactoryInterface { - use DeprecationMetadataTrait; private $extractor; private $decorated; @@ -65,11 +63,6 @@ public function create(string $resourceClass, string $property, array $options = $apiProperty = new ApiProperty(); foreach ($propertyMetadata as $key => $value) { - if ('subresource' === $key) { - trigger_deprecation('api-platform', '2.7', 'Using "subresource" is deprecated, declare another resource instead.'); - continue; - } - if ('builtinTypes' === $key && null !== $value) { $value = array_map(function (string $builtinType): Type { return new Type($builtinType); @@ -83,10 +76,6 @@ public function create(string $resourceClass, string $property, array $options = } } - if (isset($propertyMetadata['attributes'])) { - $apiProperty = $this->withDeprecatedAttributes($apiProperty, $propertyMetadata['attributes']); - } - return $apiProperty; } @@ -127,10 +116,6 @@ private function update(ApiProperty $propertyMetadata, array $metadata): ApiProp $propertyMetadata = $propertyMetadata->{'with'.ucfirst($metadataKey)}($metadata[$metadataKey]); } - if (isset($metadata['attributes'])) { - $propertyMetadata = $this->withDeprecatedAttributes($propertyMetadata, $metadata['attributes']); - } - return $propertyMetadata; } } diff --git a/src/Metadata/Property/Factory/LegacyPropertyMetadataFactory.php b/src/Metadata/Property/Factory/LegacyPropertyMetadataFactory.php deleted file mode 100644 index cd61f123f49..00000000000 --- a/src/Metadata/Property/Factory/LegacyPropertyMetadataFactory.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * 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\Metadata\Property\Factory; - -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Exception\PropertyNotFoundException; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\Property\DeprecationMetadataTrait; - -final class LegacyPropertyMetadataFactory implements PropertyMetadataFactoryInterface -{ - use DeprecationMetadataTrait; - - private $legacyPropertyMetadataFactory; - private $decorated; - - public function __construct(LegacyPropertyMetadataFactoryInterface $legacyPropertyMetadataFactory, PropertyMetadataFactoryInterface $decorated = null) - { - $this->legacyPropertyMetadataFactory = $legacyPropertyMetadataFactory; - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function create(string $resourceClass, string $property, array $options = []): ApiProperty - { - if (null === $this->decorated) { - $propertyMetadata = new ApiProperty(); - } else { - try { - $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); - } catch (PropertyNotFoundException $propertyNotFoundException) { - $propertyMetadata = new ApiProperty(); - } - } - - try { - $legacyPropertyMetadata = $this->legacyPropertyMetadataFactory->create($resourceClass, $property, ['deprecate' => false] + $options); - } catch (PropertyNotFoundException|ResourceClassNotFoundException $propertyNotFoundException) { - return $propertyMetadata; - } - - foreach (get_class_methods($legacyPropertyMetadata) as $method) { - if (0 !== strpos($method, 'get') && 0 !== strpos($method, 'is')) { - continue; - } - - if ('getIri' === $method) { - if (!$legacyPropertyMetadata->getIri()) { - continue; - } - - $propertyMetadata = $propertyMetadata->withIris([$legacyPropertyMetadata->getIri()]); - continue; - } - - if ('getType' === $method) { - if (!$legacyPropertyMetadata->getType()) { - continue; - } - - $propertyMetadata = $propertyMetadata->withBuiltinTypes([$legacyPropertyMetadata->getType()]); - continue; - } - - $wither = str_replace(['get', 'is'], 'with', $method); - - if (method_exists($propertyMetadata, $wither) && null !== $legacyPropertyMetadata->{$method}() && null === $propertyMetadata->{$method}()) { - $propertyMetadata = $propertyMetadata->{$wither}($legacyPropertyMetadata->{$method}()); - } - } - - return $this->withDeprecatedAttributes($propertyMetadata, $legacyPropertyMetadata->getAttributes() ?? []); - } -} diff --git a/src/Metadata/Resource/DeprecationMetadataTrait.php b/src/Metadata/Resource/DeprecationMetadataTrait.php deleted file mode 100644 index c229cc049a4..00000000000 --- a/src/Metadata/Resource/DeprecationMetadataTrait.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * 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\Metadata\Resource; - -use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; - -/** - * @internal - */ -trait DeprecationMetadataTrait -{ - private $camelCaseToSnakeCaseNameConverter; - - public function getKeyValue(string $key, $value) - { - if (!$this->camelCaseToSnakeCaseNameConverter) { - $this->camelCaseToSnakeCaseNameConverter = new CamelCaseToSnakeCaseNameConverter(); - } - - if ('attributes' === $key) { - trigger_deprecation('api-platform/core', '2.7', 'The "attributes" option is deprecated and will be renamed to "extra_properties".'); - $key = 'extra_properties'; - } elseif ('iri' === $key) { - trigger_deprecation('api-platform/core', '2.7', 'The "iri" is deprecated and will be renamed to "types".'); - $key = 'types'; - $value = [$value]; - } elseif ('validation_groups' === $key) { - trigger_deprecation('api-platform/core', '2.7', 'The "validation_groups" is deprecated and will be renamed to "validation_context" having an array with a "groups" key.'); - $key = 'validation_context'; - $value = ['groups' => $value]; - } elseif ('access_control' === $key) { - $key = 'security'; - trigger_deprecation('api-platform/core', '2.7', 'The "access_control" option is deprecated and will be renamed to "security".'); - } elseif ('access_control_message' === $key) { - $key = 'security_message'; - trigger_deprecation('api-platform/core', '2.7', 'The "access_control_message" option is deprecated and will be renamed to "security_message".'); - } elseif ('path' === $key) { - $key = 'uri_template'; - trigger_deprecation('api-platform/core', '2.7', 'The "path" option is deprecated and will be renamed to "uri_template".'); - // Transform default value to an empty array if null - } elseif (\in_array($key, ['denormalization_context', 'normalization_context', 'hydra_context', 'openapi_context', 'order', 'pagination_via_cursor', 'exception_to_status'], true)) { - if (null === $value) { - $value = []; - } elseif (!\is_array($value)) { - $value = [$value]; - } - } elseif ('route_prefix' === $key) { - $value = \is_string($value) ? $value : ''; - } elseif ('swagger_context' === $key) { - trigger_deprecation('api-platform/core', '2.7', 'The "swagger_context" option is deprecated and will be removed, use "openapi_context".'); - $key = 'openapi_context'; - $value = $value ?? []; - } elseif ('query_parameter_validation_enabled' === $key) { - $value = !$value ? false : $value; - // GraphQl related keys - } elseif (\in_array($key, ['collection_query', 'item_query', 'mutation'], true)) { - trigger_deprecation('api-platform/core', '2.7', 'To specify a GraphQl resolver use "resolver" instead of "mutation", "item_query" or "collection_query".'); - $key = 'resolver'; - } elseif ('filters' === $key) { - $value = null === $value ? [] : $value; - } elseif ('graphql' === $key) { - trigger_deprecation('api-platform/core', '2.7', 'The "graphql" option is deprecated and will be renamed to "graphQlOperations".'); - $key = 'graphQlOperations'; - } elseif ('identifiers' === $key) { - $key = 'uriVariables'; - } elseif ('doctrine_mongodb' === $key) { - $key = 'extra_properties'; - $value = ['doctrine_mongodb' => $value]; - } - - return [$this->camelCaseToSnakeCaseNameConverter->denormalize($key), $value]; - } -} diff --git a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php index 1f2bd8433a5..58fdffab7f4 100644 --- a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php @@ -32,10 +32,10 @@ use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Put; -use ApiPlatform\Metadata\Resource\DeprecationMetadataTrait; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; +use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; /** * Creates a resource metadata from {@see ApiResource} annotations. @@ -45,12 +45,11 @@ */ final class AttributesResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface { - use DeprecationMetadataTrait; - private $defaults; private $decorated; private $logger; private $graphQlEnabled; + private $camelCaseToSnakeCaseNameConverter; public function __construct(ResourceMetadataCollectionFactoryInterface $decorated = null, LoggerInterface $logger = null, array $defaults = [], bool $graphQlEnabled = false) { @@ -58,6 +57,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $decorate $this->decorated = $decorated; $this->logger = $logger ?? new NullLogger(); $this->graphQlEnabled = $graphQlEnabled; + $this->camelCaseToSnakeCaseNameConverter = new CamelCaseToSnakeCaseNameConverter(); } /** @@ -236,10 +236,8 @@ private function getOperationWithDefaults(ApiResource $resource, Operation $oper */ private function addGlobalDefaults($operation) { - $extraProperties = $operation->getExtraProperties(); foreach ($this->defaults as $key => $value) { - [$newKey, $value] = $this->getKeyValue($key, $value); - $upperKey = ucfirst($newKey); + $upperKey = ucfirst($this->camelCaseToSnakeCaseNameConverter->denormalize($key)); $getter = 'get'.$upperKey; if (!method_exists($operation, $getter)) { diff --git a/src/Metadata/Resource/Factory/ExtractorResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/ExtractorResourceMetadataCollectionFactory.php index 6ba2c98ce24..a4fd02bccad 100644 --- a/src/Metadata/Resource/Factory/ExtractorResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/ExtractorResourceMetadataCollectionFactory.php @@ -24,8 +24,8 @@ use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Put; -use ApiPlatform\Metadata\Resource\DeprecationMetadataTrait; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; /** * Creates a resource metadata from {@see Resource} extractors (XML, YAML). @@ -35,16 +35,17 @@ */ final class ExtractorResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface { - use DeprecationMetadataTrait; private $extractor; private $decorated; private $defaults; + private $camelCaseToSnakeCaseNameConverter; public function __construct(ResourceExtractorInterface $extractor, ResourceMetadataCollectionFactoryInterface $decorated = null, array $defaults = []) { $this->extractor = $extractor; $this->decorated = $decorated; $this->defaults = $defaults; + $this->camelCaseToSnakeCaseNameConverter = new CamelCaseToSnakeCaseNameConverter(); } /** @@ -130,7 +131,7 @@ private function buildOperations(?array $data, ApiResource $resource): array continue; } - [$camelCaseKey, $value] = $this->getKeyValue($key, $value); + $camelCaseKey = $this->camelCaseToSnakeCaseNameConverter->denormalize($key); $methodName = 'with'.ucfirst($camelCaseKey); if (method_exists($operation, $methodName)) { @@ -164,7 +165,7 @@ private function buildGraphQlOperations(?array $data, ApiResource $resource): ar continue; } - [$camelCaseKey, $value] = $this->getKeyValue($key, $value); + $camelCaseKey = $this->camelCaseToSnakeCaseNameConverter->denormalize($key); $methodName = 'with'.ucfirst($camelCaseKey); if (method_exists($operation, $methodName)) { @@ -184,7 +185,7 @@ private function buildGraphQlOperations(?array $data, ApiResource $resource): ar private function getOperationWithDefaults(ApiResource $resource, HttpOperation $operation): HttpOperation { foreach (($this->defaults['attributes'] ?? []) as $key => $value) { - [$key, $value] = $this->getKeyValue($key, $value); + $key = $this->camelCaseToSnakeCaseNameConverter->denormalize($key); if (null === $operation->{'get'.ucfirst($key)}()) { $operation = $operation->{'with'.ucfirst($key)}($value); } diff --git a/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php index 55c17ffb23d..9fd6af348eb 100644 --- a/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php @@ -15,8 +15,6 @@ use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; -use ApiPlatform\Util\AnnotationFilterExtractorTrait; -use Doctrine\Common\Annotations\Reader; /** * Creates a resource metadata from {@see Resource} annotations. @@ -26,17 +24,11 @@ */ final class FiltersResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface { - use AnnotationFilterExtractorTrait; - private $decorated; - private $reader; - public function __construct(ResourceMetadataCollectionFactoryInterface $decorated = null, ?Reader $reader = null) + public function __construct(ResourceMetadataCollectionFactoryInterface $decorated = null) { $this->decorated = $decorated; - if ($reader) { - $this->reader = $reader; - } } /** @@ -56,21 +48,15 @@ public function create(string $resourceClass): ResourceMetadataCollection throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); } - $filters = array_keys($this->readFilterAnnotations($reflectionClass, $this->reader)); - - if (\count($filters)) { - trigger_deprecation('api-platform/core', '2.7', 'Use php attributes instead of doctrine annotations to declare filters.'); - } - foreach ($resourceMetadataCollection as $i => $resource) { foreach ($operations = $resource->getOperations() as $operationName => $operation) { - $operations->add($operationName, $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? [], $filters)))); + $operations->add($operationName, $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? [])))); } $resourceMetadataCollection[$i] = $resource->withOperations($operations); foreach ($graphQlOperations = $resource->getGraphQlOperations() ?? [] as $operationName => $operation) { - $graphQlOperations[$operationName] = $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? [], $filters))); + $graphQlOperations[$operationName] = $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? []))); } $resourceMetadataCollection[$i] = $resource->withGraphQlOperations($graphQlOperations); diff --git a/src/Metadata/Resource/Factory/LegacyResourceMetadataResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/LegacyResourceMetadataResourceMetadataCollectionFactory.php deleted file mode 100644 index f35d8fd179a..00000000000 --- a/src/Metadata/Resource/Factory/LegacyResourceMetadataResourceMetadataCollectionFactory.php +++ /dev/null @@ -1,265 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Bridge\Symfony\Routing\RouteNameGenerator; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\CollectionOperationInterface; -use ApiPlatform\Metadata\Delete; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\GraphQl\Mutation; -use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation; -use ApiPlatform\Metadata\GraphQl\Query; -use ApiPlatform\Metadata\GraphQl\QueryCollection; -use ApiPlatform\Metadata\GraphQl\Subscription; -use ApiPlatform\Metadata\HttpOperation; -use ApiPlatform\Metadata\Link; -use ApiPlatform\Metadata\Operations; -use ApiPlatform\Metadata\Post; -use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Metadata\Resource\DeprecationMetadataTrait; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; - -final class LegacyResourceMetadataResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface -{ - use DeprecationMetadataTrait; - private $decorated; - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $defaults; - - public function __construct(ResourceMetadataCollectionFactoryInterface $decorated = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory = null, PropertyMetadataFactoryInterface $propertyMetadataFactory = null, array $defaults = []) - { - $this->decorated = $decorated; - $this->resourceMetadataFactory = $resourceMetadataFactory; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->defaults = $defaults + ['attributes' => []]; - } - - public function create(string $resourceClass): ResourceMetadataCollection - { - $resourceMetadataCollection = new ResourceMetadataCollection($resourceClass); - if ($this->decorated) { - $resourceMetadataCollection = $this->decorated->create($resourceClass); - } - - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - } catch (ResourceClassNotFoundException $resourceNotFoundException) { - return $resourceMetadataCollection; - } - - $attributes = $resourceMetadata->getAttributes() ?? []; - - foreach ($this->defaults['attributes'] as $key => $value) { - if (!$value) { - continue; - } - - if (!isset($attributes[$key])) { - $attributes[$key] = $value; - } - } - - $resource = (new ApiResource()) - ->withShortName($resourceMetadata->getShortName()) - ->withClass($resourceClass) - ->withExtraProperties(['is_legacy_resource_metadata' => true]); - - if ($description = $resourceMetadata->getDescription()) { - $resource = $resource->withDescription($description); - } - - if ($resourceMetadata->getIri()) { - $resource = $resource->withTypes([$resourceMetadata->getIri()]); - } - - foreach ($attributes as $key => $value) { - $resource = $this->setAttributeValue($resource, $key, $value); - } - - $resource = $this->identifiersToUriVariables($resourceMetadata, $resource); - - $operations = []; - foreach ($this->createOperations($resourceMetadata->getItemOperations(), OperationType::ITEM, $resource) as $operationName => $operation) { - $operationName = RouteNameGenerator::generate($operationName, $resourceMetadata->getShortName(), OperationType::ITEM); - $operations[$operationName] = $operation->withShortName($resourceMetadata->getShortName())->withName($operationName); - } - - foreach ($this->createOperations($resourceMetadata->getCollectionOperations(), OperationType::COLLECTION, $resource) as $operationName => $operation) { - $operationName = RouteNameGenerator::generate($operationName, $resourceMetadata->getShortName(), OperationType::COLLECTION); - $operations[$operationName] = $operation->withShortName($resourceMetadata->getShortName())->withName($operationName); - } - - if (!$resourceMetadata->getGraphql()) { - // GraphQl can be null or an empty array, an empty array doesn't disable graphql type creation - $resourceMetadataCollection[] = $resource->withGraphQlOperations($resourceMetadata->getGraphql())->withOperations(new Operations($operations)); - - return $resourceMetadataCollection; - } - - $graphQlOperations = []; - foreach ($resourceMetadata->getGraphql() as $operationName => $operation) { - if (false !== strpos($operationName, 'query') || isset($operation['item_query']) || isset($operation['collection_query'])) { - $graphQlOperation = isset($operation['collection_query']) || false !== strpos($operationName, 'collection') ? new QueryCollection() : new Query(); - /** @var GraphQlOperation $graphQlOperation */ - $graphQlOperation = $graphQlOperation->withName($operationName); - } else { - /** @var GraphQlOperation $graphQlOperation */ - $graphQlOperation = (new Mutation()) - ->withDescription(ucfirst("{$operationName}s a {$resourceMetadata->getShortName()}.")) - ->withName($operationName); - } - - $graphQlOperation = $graphQlOperation - ->withArgs($operation['args'] ?? null) - ->withResolver($operation['item_query'] ?? $operation['collection_query'] ?? $operation['mutation'] ?? null) - ->withClass($resourceClass); - - foreach ($operation as $key => $value) { - $graphQlOperation = $this->setAttributeValue($graphQlOperation, $key, $value); - } - - $graphQlOperation = $graphQlOperation->withResource($resource); - - if ('update' === $operationName && $graphQlOperation instanceof Mutation && $graphQlOperation->getMercure()) { - $graphQlOperations['update_subscription'] = (new Subscription()) - ->withDescription("Subscribes to the $operationName event of a {$graphQlOperation->getShortName()}.") - ->withName('update_subscription') - ->withOperation($graphQlOperation); - } - - $graphQlOperations[$operationName] = $graphQlOperation; - } - - $resourceMetadataCollection[] = $resource->withOperations(new Operations($operations))->withGraphQlOperations($graphQlOperations); - - return $resourceMetadataCollection; - } - - private function createOperations(array $operations, string $type, ApiResource $resource): iterable - { - $priority = 0; - foreach ($operations as $operationName => $operation) { - $newOperation = OperationType::COLLECTION === $type ? new GetCollection() : new HttpOperation(); - - $newOperation = $newOperation->withMethod($operation['method']) - ->withClass($resource->getClass()) - ->withPriority($priority++); - - if (HttpOperation::METHOD_DELETE === $operation['method']) { - $newOperation = (new Delete())->withOperation($newOperation); - } elseif (HttpOperation::METHOD_POST === $operation['method'] && !isset($operation['path'])) { - $newOperation = (new Post())->withOperation($newOperation)->withUriVariables([])->withRead(false); - } - - foreach ($operation as $key => $value) { - $newOperation = $this->setAttributeValue($newOperation, $key, $value); - } - - $newOperation = $newOperation->withResource($resource); - - if ($newOperation instanceof CollectionOperationInterface && $newOperation instanceof HttpOperation) { - $newOperation = $newOperation->withUriVariables([]); - } - - $newOperation = $newOperation->withExtraProperties($newOperation->getExtraProperties() + ['is_legacy_resource_metadata' => true]); - // Avoiding operation name collision by adding _collection, this is rewritten by the UriTemplateResourceMetadataCollectionFactory - yield sprintf('%s%s', $newOperation->getRouteName() ?? $operationName, OperationType::COLLECTION === $type ? '_collection' : '') => $newOperation; - } - } - - /** - * @param HttpOperation|GraphQlOperation|ApiResource $operation - * @param mixed $value - * - * @return HttpOperation|GraphQlOperation|ApiResource - */ - private function setAttributeValue($operation, string $key, $value) - { - if ('identifiers' === $key) { - if (!$operation instanceof ApiResource && $operation instanceof CollectionOperationInterface) { - return $operation; - } - - trigger_deprecation('api-platform/core', '2.7', 'The "identifiers" option is deprecated and will be renamed to "uriVariables".'); - if (\is_string($value)) { - $value = [$value => [$operation->getClass(), $value]]; - } - - $uriVariables = []; - foreach ($value ?? [] as $parameterName => $identifiedBy) { - $uriVariables[$parameterName] = (new Link())->withFromClass($identifiedBy[0])->withIdentifiers([$identifiedBy[1]])->withParameterName($parameterName); - } - - return $operation->withUriVariables($uriVariables); - } - - [$camelCaseKey, $value] = $this->getKeyValue($key, $value); - $methodName = 'with'.ucfirst($camelCaseKey); - - if (null === $value) { - return $operation; - } - - if (method_exists($operation, $methodName)) { - return $operation->{$methodName}($value); - } - - return $operation->withExtraProperties($operation->getExtraProperties() + [$key => $value]); - } - - /** - * @param ApiResource|HttpOperation $resource - * - * @return ApiResource|HttpOperation - */ - private function identifiersToUriVariables(ResourceMetadata $resourceMetadata, $resource) - { - $identifiers = []; - - foreach ($this->propertyNameCollectionFactory->create($resource->getClass()) as $property) { - $propertyMetadata = $this->propertyMetadataFactory->create($resource->getClass(), $property); - if ($propertyMetadata->isIdentifier()) { - $identifiers[] = $property; - } - } - - $compositeIdentifier = $resourceMetadata->getAttribute('composite_identifier', null); - $numIdentifiers = \count($identifiers); - if (null === $compositeIdentifier) { - $compositeIdentifier = $numIdentifiers > 1 ? true : false; - } - - if ($compositeIdentifier || 1 === $numIdentifiers) { - $parameterName = 1 === $numIdentifiers ? $identifiers[0] : 'id'; - - return $resource->withUriVariables([$parameterName => (new Link())->withFromClass($resource->getClass())->withIdentifiers($identifiers)->withParameterName($parameterName)->withCompositeIdentifier($compositeIdentifier)]); - } - - $uriVariables = []; - foreach ($identifiers as $identifier) { - $uriVariables[$identifier] = (new Link())->withFromClass($resource->getClass())->withIdentifiers([$identifier])->withParameterName($identifier)->withCompositeIdentifier($compositeIdentifier); - } - - return $resource->withUriVariables($uriVariables); - } -} diff --git a/src/Metadata/Resource/Factory/LegacySubresourceMetadataResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/LegacySubresourceMetadataResourceMetadataCollectionFactory.php deleted file mode 100644 index e90ddd94fda..00000000000 --- a/src/Metadata/Resource/Factory/LegacySubresourceMetadataResourceMetadataCollectionFactory.php +++ /dev/null @@ -1,190 +0,0 @@ - - * - * 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\Metadata\Resource\Factory; - -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation; -use ApiPlatform\Metadata\HttpOperation; -use ApiPlatform\Metadata\Link; -use ApiPlatform\Metadata\Operations; -use ApiPlatform\Metadata\Resource\DeprecationMetadataTrait; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; - -/** - * We have to compute a local cache having all the resource => subresource matching. - * - * @deprecated - */ -final class LegacySubresourceMetadataResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface -{ - use DeprecationMetadataTrait; - private $decorated; - private $resourceNameCollectionFactory; - private $subresourceOperationFactory; - private $localCache = []; - - public function __construct(SubresourceOperationFactoryInterface $subresourceOperationFactory, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $decorated = null) - { - $this->subresourceOperationFactory = $subresourceOperationFactory; - $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->decorated = $decorated; - } - - public function create(string $resourceClass): ResourceMetadataCollection - { - $resourceMetadataCollection = new ResourceMetadataCollection($resourceClass); - if ($this->decorated) { - $resourceMetadataCollection = $this->decorated->create($resourceClass); - } - - if (0 === \count($this->localCache)) { - $this->computeSubresourceCache(); - } - - if (!isset($this->localCache[$resourceClass])) { - return $resourceMetadataCollection; - } - - $defaults = $resourceMetadataCollection[0] ?? new ApiResource(); - foreach ($this->localCache[$resourceClass] as $resource) { - $operations = iterator_to_array($resource->getOperations()); - $operation = current($operations); - $operationName = key($operations); - - foreach (get_class_methods($defaults) as $methodName) { - if (0 !== strpos($methodName, 'get')) { - continue; - } - - if (!method_exists($operation, $methodName)) { - continue; - } - - $operationValue = $operation->{$methodName}(); - if (null !== $operationValue) { - continue; - } - - if (($value = $defaults->{$methodName}()) !== null) { - $operation = $operation->{'with'.substr($methodName, 3)}($value); - } - } - - $resourceMetadataCollection[] = $resource->withOperations(new Operations([$operationName => $operation->withName($operationName)])); - } - - return $resourceMetadataCollection; - } - - private function computeSubresourceCache() - { - foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - if (!isset($this->localCache[$resourceClass])) { - $this->localCache[$resourceClass] = []; - } - - foreach ($this->subresourceOperationFactory->create($resourceClass) as $subresourceMetadata) { - if (!isset($this->localCache[$subresourceMetadata['resource_class']])) { - $this->localCache[$subresourceMetadata['resource_class']] = []; - } - - $identifiers = []; - // Removing the third tuple element - $previousParameterName = null; - foreach ($subresourceMetadata['identifiers'] as $parameterName => [$class, $property, $isPresent]) { - if (!$isPresent) { - continue; - } - - $identifiers[$parameterName] = (new Link())->withFromClass($class)->withIdentifiers([$property])->withParameterName($parameterName)->withCompositeIdentifier(false); - if ($previousParameterName) { - $identifiers[$previousParameterName] = $identifiers[$previousParameterName]->withFromProperty($parameterName); - } - - $previousParameterName = $parameterName; - } - - $extraProperties = ['is_legacy_subresource' => true]; - if ($subresourceMetadata['property']) { - $extraProperties['legacy_subresource_property'] = $subresourceMetadata['property']; - } - - if ($subresourceMetadata['identifiers']) { - $extraProperties['legacy_subresource_identifiers'] = $subresourceMetadata['identifiers']; - unset($subresourceMetadata['identifiers']); - } - - $resource = (new ApiResource())->withExtraProperties($extraProperties)->withUriVariables($identifiers)->withStateless(false); - /* @var HttpOperation $operation */ - $operation = ($subresourceMetadata['collection'] ? new GetCollection() : new Get()); - $operation = $operation->withUriVariables($identifiers); - $operation = $operation->withExtraProperties($extraProperties + ['legacy_subresource_operation_name' => $subresourceMetadata['route_name']]); - - if ($subresourceMetadata['path'] && $operation instanceof HttpOperation) { - $resource = $resource->withUriTemplate($subresourceMetadata['path']); - $operation = $operation->withUriTemplate($subresourceMetadata['path']); - } - - if ($subresourceMetadata['shortNames'][0]) { - $resource = $resource->withShortName($subresourceMetadata['shortNames'][0]); - $operation = $operation->withShortName($subresourceMetadata['shortNames'][0]); - } - - if ($subresourceMetadata['resource_class']) { - $resource = $resource->withClass($subresourceMetadata['resource_class']); - $operation = $operation->withClass($subresourceMetadata['resource_class']); - } - - foreach ($subresourceMetadata as $key => $value) { - if ('route_name' === $key) { - continue; - } - $resource = $this->setAttributeValue($resource, $key, $value); - $operation = $this->setAttributeValue($operation, $key, $value); - } - - $resource = $resource->withOperations(new Operations([ - $subresourceMetadata['route_name'] => $operation, - ])); - - if ($subresourceMetadata['controller']) { // manage null values from subresources - $resource = $resource->withController($subresourceMetadata['controller']); - } - - $this->localCache[$resource->getClass()][] = $resource; - } - } - } - - /** - * @param HttpOperation|GraphQlOperation|ApiResource $operation - * @param mixed $value - * - * @return HttpOperation|GraphQlOperation|ApiResource - */ - private function setAttributeValue($operation, string $key, $value) - { - [$camelCaseKey, $value] = $this->getKeyValue($key, $value); - $methodName = 'with'.ucfirst($camelCaseKey); - - if (method_exists($operation, $methodName) && null !== $value) { - return $operation->{$methodName}($value); - } - - return $operation; - } -} diff --git a/src/Symfony/Bundle/ApiPlatformBundle.php b/src/Symfony/Bundle/ApiPlatformBundle.php index 6c7462f6c13..7de347e70a7 100644 --- a/src/Symfony/Bundle/ApiPlatformBundle.php +++ b/src/Symfony/Bundle/ApiPlatformBundle.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Symfony\Bundle; -use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; @@ -24,7 +23,6 @@ use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; @@ -43,8 +41,6 @@ public function build(ContainerBuilder $container) parent::build($container); $container->addCompilerPass(new DataProviderPass()); - // Run the compiler pass before the {@see ResolveInstanceofConditionalsPass} to allow autoconfiguration of generated filter definitions. - $container->addCompilerPass(new AnnotationFilterPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 101); $container->addCompilerPass(new FilterPass()); $container->addCompilerPass(new ElasticsearchClientPass()); $container->addCompilerPass(new GraphQlTypePass()); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php deleted file mode 100644 index 8f072fb4f21..00000000000 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php +++ /dev/null @@ -1,102 +0,0 @@ - - * - * 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\Symfony\Bundle\DependencyInjection\Compiler; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Util\AnnotationFilterExtractorTrait; -use ApiPlatform\Util\ReflectionClassRecursiveIterator; -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * Registers filter services from {@see ApiFilter} annotations. - * - * @internal - * - * @author Antoine Bluchet - */ -final class AnnotationFilterPass implements CompilerPassInterface -{ - use AnnotationFilterExtractorTrait; - - private const TAG_FILTER_NAME = 'api_platform.filter'; - - /** - * @var Reader|null - */ - private $reader; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container): void - { - $resourceClassDirectories = $container->getParameter('api_platform.resource_class_directories'); - - foreach (ReflectionClassRecursiveIterator::getReflectionClassesFromDirectories($resourceClassDirectories) as $className => $reflectionClass) { - $this->createFilterDefinitions($reflectionClass, $container); - } - } - - /** - * @throws InvalidArgumentException - */ - private function createFilterDefinitions(\ReflectionClass $resourceReflectionClass, ContainerBuilder $container): void - { - if (null === $this->reader) { - $this->reader = $container->has('annotation_reader') ? $container->get('annotation_reader') : null; - } - - foreach ($this->readFilterAnnotations($resourceReflectionClass, $this->reader) as $id => [$arguments, $filterClass]) { - if ($container->has($id)) { - continue; - } - - if (null === $filterReflectionClass = $container->getReflectionClass($filterClass, false)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $filterClass, $id)); - } - - if ($container->has($filterClass) && ($parentDefinition = $container->findDefinition($filterClass))->isAbstract()) { - $definition = new ChildDefinition($parentDefinition->getClass()); - } else { - $definition = new Definition($filterReflectionClass->getName()); - $definition->setAutoconfigured(true); - } - - $definition->addTag(self::TAG_FILTER_NAME); - $definition->setAutowired(true); - - $parameterNames = []; - if (null !== $constructorReflectionMethod = $filterReflectionClass->getConstructor()) { - foreach ($constructorReflectionMethod->getParameters() as $reflectionParameter) { - $parameterNames[$reflectionParameter->name] = true; - } - } - - foreach ($arguments as $key => $value) { - if (!isset($parameterNames[$key])) { - throw new InvalidArgumentException(sprintf('Class "%s" does not have argument "$%s".', $filterClass, $key)); - } - - $definition->setArgument("$$key", $value); - } - - $container->setDefinition($id, $definition); - } - } -} diff --git a/src/Symfony/Bundle/Resources/config/metadata/resource.xml b/src/Symfony/Bundle/Resources/config/metadata/resource.xml index dcefe35db1d..7b36b96de96 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/resource.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/resource.xml @@ -51,7 +51,6 @@ - diff --git a/src/Util/AnnotationFilterExtractorTrait.php b/src/Util/AnnotationFilterExtractorTrait.php deleted file mode 100644 index 2ff621d2570..00000000000 --- a/src/Util/AnnotationFilterExtractorTrait.php +++ /dev/null @@ -1,157 +0,0 @@ - - * - * 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\Util; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Metadata\ApiFilter as ApiFilterMetadata; -use Doctrine\Common\Annotations\Reader; - -/** - * Generates a service id for a generic filter. - * - * @internal - * - * @author Antoine Bluchet - */ -trait AnnotationFilterExtractorTrait -{ - /** - * Filters annotations to get back only ApiFilter annotations. - * - * @param \ReflectionClass|\ReflectionProperty $reflector - * - * @return \Iterator only ApiFilter annotations - */ - private function getFilterAnnotations(\Reflector $reflector, ?Reader $reader = null): \Iterator - { - if (\PHP_VERSION_ID >= 80000) { - $attributes = $reflector->getAttributes(ApiFilter::class) ?: $reflector->getAttributes(ApiFilterMetadata::class); - - foreach ($attributes as $attribute) { - yield $attribute->newInstance(); - } - } - - if (null === $reader) { - return; - } - - $miscAnnotations = $reflector instanceof \ReflectionClass ? $reader->getClassAnnotations($reflector) : $reader->getPropertyAnnotations($reflector); - foreach ($miscAnnotations as $miscAnnotation) { - if (ApiFilter::class === \get_class($miscAnnotation)) { - yield $miscAnnotation; - } - } - } - - /** - * Given a filter annotation and reflection elements, find out the properties where the filter is applied. - * - * @param ApiFilter|ApiFilterMetadata $filterAnnotation - */ - private function getFilterProperties($filterAnnotation, \ReflectionClass $reflectionClass, \ReflectionProperty $reflectionProperty = null): array - { - $properties = []; - - if ($filterAnnotation->properties) { - foreach ($filterAnnotation->properties as $property => $strategy) { - if (\is_int($property)) { - $properties[$strategy] = null; - } else { - $properties[$property] = $strategy; - } - } - - return $properties; - } - - if (null !== $reflectionProperty) { - $properties[$reflectionProperty->getName()] = $filterAnnotation->strategy ?: null; - - return $properties; - } - - if ($filterAnnotation->strategy) { - foreach ($reflectionClass->getProperties() as $reflectionProperty) { - $properties[$reflectionProperty->getName()] = $filterAnnotation->strategy; - } - } - - return $properties; - } - - /** - * Reads filter annotations from a ReflectionClass. - * - * @return array Key is the filter id. It has two values, properties and the ApiFilter instance - */ - private function readFilterAnnotations(\ReflectionClass $reflectionClass, Reader $reader = null): array - { - $filters = []; - - foreach ($this->getFilterAnnotations($reflectionClass, $reader) as $filterAnnotation) { - $filterClass = $filterAnnotation->filterClass; - $id = $this->generateFilterId($reflectionClass, $filterClass, $filterAnnotation->id); - - if (!isset($filters[$id])) { - $filters[$id] = [$filterAnnotation->arguments, $filterClass]; - } - - if ($properties = $this->getFilterProperties($filterAnnotation, $reflectionClass)) { - $filters[$id][0]['properties'] = $properties; - } - } - - foreach ($reflectionClass->getProperties() as $reflectionProperty) { - foreach ($this->getFilterAnnotations($reflectionProperty, $reader) as $filterAnnotation) { - $filterClass = $filterAnnotation->filterClass; - $id = $this->generateFilterId($reflectionClass, $filterClass, $filterAnnotation->id); - - if (!isset($filters[$id])) { - $filters[$id] = [$filterAnnotation->arguments, $filterClass]; - } - - if ($properties = $this->getFilterProperties($filterAnnotation, $reflectionClass, $reflectionProperty)) { - if (isset($filters[$id][0]['properties'])) { - $filters[$id][0]['properties'] = array_merge($filters[$id][0]['properties'], $properties); - } else { - $filters[$id][0]['properties'] = $properties; - } - } - } - } - - $parent = $reflectionClass->getParentClass(); - - if (false !== $parent) { - return array_merge($filters, $this->readFilterAnnotations($parent, $reader)); - } - - return $filters; - } - - /** - * Generates a unique, per-class and per-filter identifier prefixed by `annotated_`. - * - * @param \ReflectionClass $reflectionClass the reflection class of a Resource - * @param string $filterClass the filter class - * @param string|null $filterId the filter id - */ - private function generateFilterId(\ReflectionClass $reflectionClass, string $filterClass, string $filterId = null): string - { - $suffix = null !== $filterId ? '_'.$filterId : $filterId; - - return 'annotated_'.Inflector::tableize(str_replace('\\', '', $reflectionClass->getName().(new \ReflectionClass($filterClass))->getName().$suffix)); - } -} diff --git a/tests/Fixtures/FileConfigurations/properties.xml b/tests/Fixtures/FileConfigurations/properties.xml new file mode 100644 index 00000000000..24c791e2771 --- /dev/null +++ b/tests/Fixtures/FileConfigurations/properties.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/tests/Fixtures/FileConfigurations/properties.yml b/tests/Fixtures/FileConfigurations/properties.yml new file mode 100644 index 00000000000..ec9bedd7bb9 --- /dev/null +++ b/tests/Fixtures/FileConfigurations/properties.yml @@ -0,0 +1,11 @@ +properties: + 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy': + 'foo': + description: 'The dummy foo' + readable: true + writable: true + readableLink: false + writableLink: false + required: true + 'name': + description: 'The dummy name' diff --git a/tests/Fixtures/FileConfigurations/propertiesinvalid.yml b/tests/Fixtures/FileConfigurations/propertiesinvalid.yml index a931583a418..0cb6a93534a 100644 --- a/tests/Fixtures/FileConfigurations/propertiesinvalid.yml +++ b/tests/Fixtures/FileConfigurations/propertiesinvalid.yml @@ -1,3 +1 @@ -resources: - 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy': - properties: 'invalid' +properties: 'invalid' diff --git a/tests/Fixtures/FileConfigurations/propertyinvalid.xml b/tests/Fixtures/FileConfigurations/propertyinvalid.xml index f029c4c6c65..f268ad38e28 100644 --- a/tests/Fixtures/FileConfigurations/propertyinvalid.xml +++ b/tests/Fixtures/FileConfigurations/propertyinvalid.xml @@ -1,12 +1,10 @@ - - - - Foo - - - + + + Foo + + diff --git a/tests/Fixtures/FileConfigurations/propertyinvalid.yml b/tests/Fixtures/FileConfigurations/propertyinvalid.yml index 4f40b6aa52b..c3869735ada 100644 --- a/tests/Fixtures/FileConfigurations/propertyinvalid.yml +++ b/tests/Fixtures/FileConfigurations/propertyinvalid.yml @@ -1,4 +1,3 @@ -resources: +properties: 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy': - properties: - 'foo': 'invalid' + 'foo': 'invalid' diff --git a/tests/Fixtures/FileConfigurations/resources.xml b/tests/Fixtures/FileConfigurations/resources.xml deleted file mode 100644 index b2638921afe..00000000000 --- a/tests/Fixtures/FileConfigurations/resources.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - GET - - - POST - - - - - POST - the/collection/path - - - - - the/subresource/path - - - - - - - graphql - - - - - - - default - - - - - default - - - - hydra:Operation - File config Dummy - - true - - - - - Foo - - - - Bar - - Baz - - Baz - - - - - diff --git a/tests/Fixtures/FileConfigurations/resources.yml b/tests/Fixtures/FileConfigurations/resources.yml deleted file mode 100644 index a49b3b9f65d..00000000000 --- a/tests/Fixtures/FileConfigurations/resources.yml +++ /dev/null @@ -1,48 +0,0 @@ -resources: - 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy': ~ - 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy': - shortName: 'thedummyshortname' - description: 'Dummy resource' - itemOperations: - my_op_name: - method: 'GET' - my_other_op_name: - method: 'POST' - collectionOperations: - my_collection_op: - method: 'POST' - path: 'the/collection/path' - subresourceOperations: - my_collection_subresource: - path: 'the/subresource/path' - graphql: - query: - normalization_context: - groups: ['graphql'] - attributes: - normalization_context: - groups: ['default'] - denormalization_context: - groups: ['default'] - hydra_context: - '@type': 'hydra:Operation' - '@hydra:title': !php/const ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy::HYDRA_TITLE - stateless: true - iri: 'someirischema' - properties: - 'foo': - subresource: {collection: true, resourceClass: 'Foo', maxDepth: 1} - description: 'The dummy foo' - readable: true - writable: true - readableLink: false - writableLink: false - required: true - attributes: - 'foo': ['Foo'] - 'bar': - '0': ['Bar'] - 'baz': 'Baz' - 'baz': 'Baz' - 'name': - description: 'The dummy name' diff --git a/tests/Fixtures/TestBundle/Document/Content.php b/tests/Fixtures/TestBundle/Document/Content.php index f02394c102e..71edd0ed39f 100644 --- a/tests/Fixtures/TestBundle/Document/Content.php +++ b/tests/Fixtures/TestBundle/Document/Content.php @@ -32,7 +32,7 @@ class Content implements \JsonSerializable * @var Collection */ #[ODM\ReferenceMany(targetDocument: Field::class, mappedBy: 'content', strategy: 'set', cascade: ['persist'])] - private \Doctrine\Common\Collections\Collection & iterable $fields; + private \Doctrine\Common\Collections\Collection $fields; #[ODM\Field(type: 'string')] private readonly string $status; diff --git a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php index 811bc29f14f..26fa301ca7c 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyPhp8.php +++ b/tests/Fixtures/TestBundle/Entity/DummyPhp8.php @@ -9,21 +9,16 @@ * file that was distributed with this source code. */ -declare (strict_types=1); +declare(strict_types=1); namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Post; -use ApiPlatform\Metadata\Delete; -use ApiPlatform\Metadata\Patch; -use ApiPlatform\Metadata\Put; -use ApiPlatform\Metadata\Get; -use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Metadata\ApiResource; use Doctrine\ORM\Mapping as ORM; + #[ApiResource(description: 'Hey PHP 8')] #[ORM\Entity] class DummyPhp8 @@ -35,8 +30,9 @@ class DummyPhp8 #[ApiFilter(SearchFilter::class)] #[ORM\Column] public $filtered; + #[ApiProperty(description: 'a foo')] - public function getFoo() : int + public function getFoo(): int { return 0; } diff --git a/tests/Fixtures/TestBundle/Entity/FilterValidator.php b/tests/Fixtures/TestBundle/Entity/FilterValidator.php index df13aaf2028..6ef0be0c435 100644 --- a/tests/Fixtures/TestBundle/Entity/FilterValidator.php +++ b/tests/Fixtures/TestBundle/Entity/FilterValidator.php @@ -41,8 +41,8 @@ class FilterValidator #[ORM\Id] #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - - #[ApiProperty(types: ["http://schema.org/name"]) + + #[ApiProperty(types: ['http://schema.org/name'])] #[ORM\Column] private string $name; diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_v3/resources.yaml b/tests/Fixtures/TestBundle/Resources/config/api_resources/resources.yaml similarity index 100% rename from tests/Fixtures/TestBundle/Resources/config/api_resources_v3/resources.yaml rename to tests/Fixtures/TestBundle/Resources/config/api_resources/resources.yaml diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy/resources.yml b/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy/resources.yml deleted file mode 100644 index c97fb7e67e0..00000000000 --- a/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy/resources.yml +++ /dev/null @@ -1,30 +0,0 @@ -resources: - ApiPlatform\Tests\Fixtures\TestBundle\Model\DummyAddress: - collectionOperations: - get: - openapi_context: - x-visibility: hide - - ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceInterface: - itemOperations: - get: - method: 'GET' - - collectionOperations: - get: - method: 'GET' - - properties: - foo: - identifier: true - - ApiPlatform\Tests\Fixtures\TestBundle\Model\ResourceBarInterface: - itemOperations: - get: - method: 'GET' - collectionOperations: - get: - method: 'GET' - - ApiPlatform\Tests\Fixtures\TestBundle\Entity\FlexConfig: ~ - diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy_odm/resources.yml b/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy_odm/resources.yml deleted file mode 100644 index 915c989fa1e..00000000000 --- a/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy_odm/resources.yml +++ /dev/null @@ -1,16 +0,0 @@ -resources: - ApiPlatform\Tests\Fixtures\TestBundle\Document\FileConfigDummy: - shortName: fileconfigdummy - description: Dummy resource - itemOperations: - custom_operation: - method: GET - controller: app.config_dummy_resource.action - properties: - foo: - description: The dummy foo - - ApiPlatform\Tests\Fixtures\TestBundle\Document\SingleFileConfigDummy: - shortName: single_file_config - description: File configured resource - diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy_orm/resources.yml b/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy_orm/resources.yml deleted file mode 100644 index 3dd39528528..00000000000 --- a/tests/Fixtures/TestBundle/Resources/config/api_resources_legacy_orm/resources.yml +++ /dev/null @@ -1,17 +0,0 @@ -resources: - ApiPlatform\Tests\Fixtures\TestBundle\Entity\FlexConfig: ~ - - ApiPlatform\Tests\Fixtures\TestBundle\Entity\FileConfigDummy: - shortName: fileconfigdummy - description: Dummy resource - itemOperations: - custom_operation: - method: GET - controller: app.config_dummy_resource.action - properties: - foo: - description: The dummy foo - - ApiPlatform\Tests\Fixtures\TestBundle\Entity\SingleFileConfigDummy: - shortName: single_file_config - description: File configured resource diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_v3_odm/properties.xml b/tests/Fixtures/TestBundle/Resources/config/api_resources_odm/properties.xml similarity index 100% rename from tests/Fixtures/TestBundle/Resources/config/api_resources_v3_odm/properties.xml rename to tests/Fixtures/TestBundle/Resources/config/api_resources_odm/properties.xml diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_v3_odm/resources.xml b/tests/Fixtures/TestBundle/Resources/config/api_resources_odm/resources.xml similarity index 100% rename from tests/Fixtures/TestBundle/Resources/config/api_resources_v3_odm/resources.xml rename to tests/Fixtures/TestBundle/Resources/config/api_resources_odm/resources.xml diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_v3_odm/resources.yaml b/tests/Fixtures/TestBundle/Resources/config/api_resources_odm/resources.yaml similarity index 100% rename from tests/Fixtures/TestBundle/Resources/config/api_resources_v3_odm/resources.yaml rename to tests/Fixtures/TestBundle/Resources/config/api_resources_odm/resources.yaml diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_v3_orm/properties.xml b/tests/Fixtures/TestBundle/Resources/config/api_resources_orm/properties.xml similarity index 100% rename from tests/Fixtures/TestBundle/Resources/config/api_resources_v3_orm/properties.xml rename to tests/Fixtures/TestBundle/Resources/config/api_resources_orm/properties.xml diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_v3_orm/resources.xml b/tests/Fixtures/TestBundle/Resources/config/api_resources_orm/resources.xml similarity index 100% rename from tests/Fixtures/TestBundle/Resources/config/api_resources_v3_orm/resources.xml rename to tests/Fixtures/TestBundle/Resources/config/api_resources_orm/resources.xml diff --git a/tests/Fixtures/TestBundle/Resources/config/api_resources_v3_orm/resources.yaml b/tests/Fixtures/TestBundle/Resources/config/api_resources_orm/resources.yaml similarity index 100% rename from tests/Fixtures/TestBundle/Resources/config/api_resources_v3_orm/resources.yaml rename to tests/Fixtures/TestBundle/Resources/config/api_resources_orm/resources.yaml diff --git a/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php b/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php deleted file mode 100644 index 20f4f42628c..00000000000 --- a/tests/Fixtures/TestBundle/Util/AnnotationFilterExtractor.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\Util; - -use ApiPlatform\Util\AnnotationFilterExtractorTrait; -use Doctrine\Common\Annotations\Reader; - -class AnnotationFilterExtractor -{ - use AnnotationFilterExtractorTrait; - - public function __construct(private readonly ?Reader $reader = null) - { - } - - public function getFilters(\ReflectionClass $reflectionClass) - { - return $this->readFilterAnnotations($reflectionClass, $this->reader); - } -} diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index 31eb496bd97..15f820c1009 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -244,44 +244,18 @@ class_exists(NativePasswordHasher::class) ? 'password_hashers' : 'encoders' => [ $metadataBackwardCompatibilityLayer = (bool) ($_SERVER['METADATA_BACKWARD_COMPATIBILITY_LAYER'] ?? false); $c->prependExtensionConfig('api_platform', ['metadata_backward_compatibility_layer' => $metadataBackwardCompatibilityLayer]); - if ($metadataBackwardCompatibilityLayer) { - $loader->load(__DIR__.'/config/config_metadata_backward_compatibility_layer.yml'); - $c->prependExtensionConfig('api_platform', [ - 'mapping' => [ - 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources_legacy'], - ], - ]); - - if ('mongodb' === $this->environment) { - $c->prependExtensionConfig('api_platform', [ - 'mapping' => [ - 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources_legacy_odm'], - ], - ]); - - return; - } - - $c->prependExtensionConfig('api_platform', [ - 'mapping' => [ - 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources_legacy_orm'], - ], - ]); - - return; - } - $loader->load(__DIR__.'/config/config_v3.yml'); + $loader->load(__DIR__.'/config/config.yml'); $c->prependExtensionConfig('api_platform', [ 'mapping' => [ - 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources_v3'], + 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources'], ], ]); if ('mongodb' === $this->environment) { $c->prependExtensionConfig('api_platform', [ 'mapping' => [ - 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources_v3_odm'], + 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources_odm'], ], ]); @@ -290,7 +264,7 @@ class_exists(NativePasswordHasher::class) ? 'password_hashers' : 'encoders' => [ $c->prependExtensionConfig('api_platform', [ 'mapping' => [ - 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources_v3_orm'], + 'paths' => ['%kernel.project_dir%/../TestBundle/Resources/config/api_resources_orm'], ], ]); } diff --git a/tests/Fixtures/app/config/config_v3.yml b/tests/Fixtures/app/config/config.yml similarity index 99% rename from tests/Fixtures/app/config/config_v3.yml rename to tests/Fixtures/app/config/config.yml index 48b5660d438..e242437e78a 100644 --- a/tests/Fixtures/app/config/config_v3.yml +++ b/tests/Fixtures/app/config/config.yml @@ -3,4 +3,3 @@ services: class: 'ApiPlatform\Tests\Fixtures\TestBundle\Metadata\ProviderResourceMetadatatCollectionFactory' decorates: api_platform.metadata.resource.metadata_collection_factory arguments: ['@ApiPlatform\Tests\Fixtures\TestBundle\Metadata\ProviderResourceMetadatatCollectionFactory.inner'] - diff --git a/tests/Fixtures/app/config/config_metadata_backward_compatibility_layer.yml b/tests/Fixtures/app/config/config_metadata_backward_compatibility_layer.yml deleted file mode 100644 index f7fa2058245..00000000000 --- a/tests/Fixtures/app/config/config_metadata_backward_compatibility_layer.yml +++ /dev/null @@ -1,6 +0,0 @@ -services: - app.graphql.type_converter: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\GraphQl\Type\TypeConverterLegacy' - decorates: 'api_platform.graphql.type_converter' - arguments: ['@app.graphql.type_converter.inner'] - public: false diff --git a/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php b/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php index 84677a9912d..d6a020f3984 100644 --- a/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php +++ b/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php @@ -17,7 +17,6 @@ use ApiPlatform\Metadata\Extractor\XmlPropertyExtractor; use ApiPlatform\Metadata\Extractor\YamlPropertyExtractor; use ApiPlatform\Metadata\Property\Factory\ExtractorPropertyMetadataFactory; -use ApiPlatform\Metadata\Resource\DeprecationMetadataTrait; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Comment; use ApiPlatform\Tests\Metadata\Extractor\Adapter\PropertyAdapterInterface; use ApiPlatform\Tests\Metadata\Extractor\Adapter\XmlPropertyAdapter; @@ -34,8 +33,6 @@ */ final class PropertyMetadataCompatibilityTest extends TestCase { - use DeprecationMetadataTrait; - private const RESOURCE_CLASS = Comment::class; private const PROPERTY = 'comment'; private const FIXTURES = [ diff --git a/tests/Metadata/Extractor/ResourceMetadataCompatibilityTest.php b/tests/Metadata/Extractor/ResourceMetadataCompatibilityTest.php index f8fe305f995..c87e688363d 100644 --- a/tests/Metadata/Extractor/ResourceMetadataCompatibilityTest.php +++ b/tests/Metadata/Extractor/ResourceMetadataCompatibilityTest.php @@ -28,7 +28,6 @@ use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Put; -use ApiPlatform\Metadata\Resource\DeprecationMetadataTrait; use ApiPlatform\Metadata\Resource\Factory\ExtractorResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Comment; @@ -46,8 +45,6 @@ */ final class ResourceMetadataCompatibilityTest extends TestCase { - use DeprecationMetadataTrait; - private const RESOURCE_CLASS = Comment::class; private const SHORT_NAME = 'Comment'; private const FIXTURES = [ diff --git a/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php b/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php index f5e4573ce16..9b2f32f8571 100644 --- a/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php +++ b/tests/Metadata/Property/Factory/CachedPropertyMetadataFactoryTest.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\Metadata\Property\Factory; +namespace ApiPlatform\Tests\Metadata\Property\Factory; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\CachedPropertyMetadataFactory; diff --git a/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php b/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php index f2ada8d8e04..483104d0a46 100644 --- a/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php +++ b/tests/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactoryTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\Metadata\Property\Factory; -use ApiPlatform\Core\Metadata\Extractor\XmlExtractor; -use ApiPlatform\Core\Metadata\Extractor\YamlExtractor; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; +use ApiPlatform\Metadata\Extractor\XmlPropertyExtractor; +use ApiPlatform\Metadata\Extractor\YamlPropertyExtractor; use ApiPlatform\Metadata\Property\Factory\ExtractorPropertyNameCollectionFactory; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; @@ -33,17 +33,17 @@ class ExtractorPropertyNameCollectionFactoryTest extends TestCase public function testCreateXml() { - $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resources.xml'; + $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/properties.xml'; $this->assertEquals( - (new ExtractorPropertyNameCollectionFactory(new XmlExtractor([$configPath])))->create(FileConfigDummy::class), + (new ExtractorPropertyNameCollectionFactory(new XmlPropertyExtractor([$configPath])))->create(FileConfigDummy::class), new PropertyNameCollection(['foo', 'name']) ); } public function testCreateWithParentPropertyNameCollectionFactoryXml() { - $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resources.xml'; + $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/properties.xml'; $decorated = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $decorated @@ -52,7 +52,7 @@ public function testCreateWithParentPropertyNameCollectionFactoryXml() ->shouldBeCalled(); $this->assertEquals( - (new ExtractorPropertyNameCollectionFactory(new XmlExtractor([$configPath]), $decorated->reveal()))->create(FileConfigDummy::class), + (new ExtractorPropertyNameCollectionFactory(new XmlPropertyExtractor([$configPath]), $decorated->reveal()))->create(FileConfigDummy::class), new PropertyNameCollection(['id', 'foo', 'name']) ); } @@ -64,32 +64,32 @@ public function testCreateWithNonexistentResourceXml() $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resourcenotfound.xml'; - (new ExtractorPropertyNameCollectionFactory(new XmlExtractor([$configPath])))->create('ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThisDoesNotExist'); + (new ExtractorPropertyNameCollectionFactory(new XmlPropertyExtractor([$configPath])))->create('ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThisDoesNotExist'); } public function testCreateWithInvalidXml() { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('#.+Element \'\\{https://api-platform.com/schema/metadata\\}foo\': This element is not expected\\..+#'); + $this->expectExceptionMessageMatches('#.+Element \'\\{https://api-platform.com/schema/metadata/properties-3.0\\}foo\': This element is not expected\\..+#'); $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/propertyinvalid.xml'; - (new ExtractorPropertyNameCollectionFactory(new XmlExtractor([$configPath])))->create(FileConfigDummy::class); + (new ExtractorPropertyNameCollectionFactory(new XmlPropertyExtractor([$configPath])))->create(FileConfigDummy::class); } public function testCreateYaml() { - $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resources.yml'; + $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/properties.yml'; $this->assertEquals( - (new ExtractorPropertyNameCollectionFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class), + (new ExtractorPropertyNameCollectionFactory(new YamlPropertyExtractor([$configPath])))->create(FileConfigDummy::class), new PropertyNameCollection(['foo', 'name']) ); } public function testCreateWithParentPropertyMetadataFactoryYaml() { - $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resources.yml'; + $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/properties.yml'; $decorated = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $decorated @@ -98,7 +98,7 @@ public function testCreateWithParentPropertyMetadataFactoryYaml() ->shouldBeCalled(); $this->assertEquals( - (new ExtractorPropertyNameCollectionFactory(new YamlExtractor([$configPath]), $decorated->reveal()))->create(FileConfigDummy::class), + (new ExtractorPropertyNameCollectionFactory(new YamlPropertyExtractor([$configPath]), $decorated->reveal()))->create(FileConfigDummy::class), new PropertyNameCollection(['id', 'foo', 'name']) ); } @@ -110,37 +110,27 @@ public function testCreateWithNonexistentResourceYaml() $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resourcenotfound.yml'; - (new ExtractorPropertyNameCollectionFactory(new YamlExtractor([$configPath])))->create('ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThisDoesNotExist'); + (new ExtractorPropertyNameCollectionFactory(new YamlPropertyExtractor([$configPath])))->create('ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThisDoesNotExist'); } public function testCreateWithMalformedResourcesSettingYaml() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"resources" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/resourcesinvalid\\.yml"\\./'); - - $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resourcesinvalid.yml'; - - (new ExtractorPropertyNameCollectionFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class); - } - - public function testCreateWithMalformedPropertiesSettingYaml() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessageMatches('/"properties" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/propertiesinvalid\\.yml"\\./'); $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/propertiesinvalid.yml'; - (new ExtractorPropertyNameCollectionFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class); + (new ExtractorPropertyNameCollectionFactory(new YamlPropertyExtractor([$configPath])))->create(FileConfigDummy::class); } public function testCreateWithMalformedPropertySettingYaml() { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/"foo" setting is expected to be null or an array, string given in ".+\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/Fixtures\\/FileConfigurations\\/propertyinvalid\\.yml"\\./'); + $this->expectExceptionMessage('"foo" setting is expected to be null or an array, string given.'); $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/propertyinvalid.yml'; - (new ExtractorPropertyNameCollectionFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class); + (new ExtractorPropertyNameCollectionFactory(new YamlPropertyExtractor([$configPath])))->create(FileConfigDummy::class); } public function testCreateWithMalformedYaml() @@ -149,6 +139,6 @@ public function testCreateWithMalformedYaml() $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/parse_exception.yml'; - (new ExtractorPropertyNameCollectionFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class); + (new ExtractorPropertyNameCollectionFactory(new YamlPropertyExtractor([$configPath])))->create(FileConfigDummy::class); } } diff --git a/tests/Metadata/Property/PropertyNameCollectionTest.php b/tests/Metadata/Property/PropertyNameCollectionTest.php index 462207a70a1..1c4f8bfd53c 100644 --- a/tests/Metadata/Property/PropertyNameCollectionTest.php +++ b/tests/Metadata/Property/PropertyNameCollectionTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\Metadata\Property; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Metadata/Resource/Factory/LinkFactoryTest.php b/tests/Metadata/Resource/Factory/LinkFactoryTest.php index 562035efa5e..68d294f8214 100644 --- a/tests/Metadata/Resource/Factory/LinkFactoryTest.php +++ b/tests/Metadata/Resource/Factory/LinkFactoryTest.php @@ -14,10 +14,10 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Symfony\PropertyInfo\Metadata\Property\PropertyInfoPropertyNameCollectionFactory; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; +use ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; diff --git a/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php index 9481cd620c8..4ea6e6b4f2f 100644 --- a/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactoryTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Metadata\Resource\Factory; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -28,6 +27,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\UriTemplateResourceMetadataCollectionFactory; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Operation\PathSegmentNameGeneratorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AttributeResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; diff --git a/tests/Symfony/Bundle/ApiPlatformBundleTest.php b/tests/Symfony/Bundle/ApiPlatformBundleTest.php index d6123c7e127..14fcf41188f 100644 --- a/tests/Symfony/Bundle/ApiPlatformBundleTest.php +++ b/tests/Symfony/Bundle/ApiPlatformBundleTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Symfony\Bundle; use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; -use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; @@ -28,7 +27,6 @@ use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\ContainerBuilder; /** @@ -42,7 +40,6 @@ public function testBuild() { $containerProphecy = $this->prophesize(ContainerBuilder::class); $containerProphecy->addCompilerPass(Argument::type(DataProviderPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); - $containerProphecy->addCompilerPass(Argument::type(AnnotationFilterPass::class), PassConfig::TYPE_BEFORE_OPTIMIZATION, 101)->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(FilterPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(ElasticsearchClientPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(GraphQlTypePass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php deleted file mode 100644 index 8b2fe8fbf9f..00000000000 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php +++ /dev/null @@ -1,269 +0,0 @@ - - * - * 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\Tests\Symfony\Bundle\DependencyInjection\Compiler; - -use ApiPlatform\Api\FilterInterface; -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; -use ApiPlatform\Doctrine\Orm\Filter\DateFilter; -use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Serializer\Filter\GroupFilter; -use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\Fixtures\TestBundle\Filter\DoesNotImplementInterfaceFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Filter\NoConstructorFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Filter\NoPropertiesArgumentFilter; -use ApiPlatform\Tests\ProphecyTrait; -use Doctrine\Common\Annotations\Reader; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException as DependencyInjectionInvalidArgumentException; - -/** - * @author Antoine Bluchet - */ -class AnnotationFilterPassTest extends TestCase -{ - use ProphecyTrait; - - public function testConstruct(): void - { - $annotationFilterPass = new AnnotationFilterPass(); - - $this->assertInstanceOf(CompilerPassInterface::class, $annotationFilterPass); - } - - public function testProcess(): void - { - $readerProphecy = $this->prophesize(Reader::class); - $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); - $readerProphecy->getClassAnnotations(Argument::allOf( - Argument::type(\ReflectionClass::class), - Argument::which('getName', Dummy::class) - ))->willReturn([ - new ApiFilter(['value' => SearchFilter::class, 'strategy' => 'exact', 'properties' => ['description', 'relatedDummy.name', 'name']]), - new ApiFilter(['value' => GroupFilter::class, 'arguments' => ['parameterName' => 'foobar']]), - ]); - $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); - $readerProphecy->getPropertyAnnotations(Argument::allOf( - Argument::type(\ReflectionProperty::class), - Argument::that(function (\ReflectionProperty $reflectionProperty): bool { - return Dummy::class === $reflectionProperty->getDeclaringClass()->getName(); - }), - Argument::which('getName', 'dummyDate') - ))->willReturn([ - new ApiFilter(['value' => DateFilter::class]), - ]); - - $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); - $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ - __DIR__.'/../../../../Fixtures/TestBundle/Entity/', - ]); - $containerBuilderProphecy->has('annotation_reader')->willReturn(true); - $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(false); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_serializer_filter_group_filter')->willReturn(false); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_doctrine_orm_filter_date_filter')->willReturn(false); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(false); - $containerBuilderProphecy->has(SearchFilter::class)->willReturn(false); - $containerBuilderProphecy->has(GroupFilter::class)->willReturn(false); - $containerBuilderProphecy->has(DateFilter::class)->willReturn(true); - $containerBuilderProphecy->findDefinition(DateFilter::class)->willReturn((new Definition(DateFilter::class))->setAbstract(true)); - $containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(new \ReflectionClass(SearchFilter::class)); - $containerBuilderProphecy->getReflectionClass(GroupFilter::class, false)->willReturn(new \ReflectionClass(GroupFilter::class)); - $containerBuilderProphecy->getReflectionClass(DateFilter::class, false)->willReturn(new \ReflectionClass(DateFilter::class)); - $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter', Argument::allOf( - Argument::type(Definition::class), - Argument::that(function (Definition $definition): bool { - return SearchFilter::class === $definition->getClass() && ['$properties' => ['description' => null, 'relatedDummy.name' => null, 'name' => null]] === $definition->getArguments(); - }) - ))->shouldBeCalled(); - $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_serializer_filter_group_filter', Argument::allOf( - Argument::type(Definition::class), - Argument::that(function (Definition $definition): bool { - return GroupFilter::class === $definition->getClass() && ['$parameterName' => 'foobar'] === $definition->getArguments(); - }) - ))->shouldBeCalled(); - $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_doctrine_orm_filter_date_filter', Argument::allOf( - Argument::type(ChildDefinition::class), - Argument::that(function (ChildDefinition $definition): bool { - return DateFilter::class === $definition->getParent() && ['$properties' => ['dummyDate' => null]] === $definition->getArguments(); - }) - ))->shouldBeCalled(); - if (\PHP_VERSION_ID >= 80000) { - $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter', Argument::allOf( - Argument::type(Definition::class), - Argument::that(function (Definition $definition): bool { - return SearchFilter::class === $definition->getClass() && ['$properties' => ['filtered' => null]] === $definition->getArguments(); - }) - ))->shouldBeCalled(); - } - - $annotationFilterPass = new AnnotationFilterPass(); - $annotationFilterPass->process($containerBuilderProphecy->reveal()); - } - - public function testProcessFilterWhichDoesNotImplementRequiredInterface(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage(sprintf('The filter class "%s" does not implement "%s".', DoesNotImplementInterfaceFilter::class, FilterInterface::class)); - - $readerProphecy = $this->prophesize(Reader::class); - $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); - $readerProphecy->getClassAnnotations(Argument::allOf( - Argument::type(\ReflectionClass::class), - Argument::which('getName', Dummy::class) - ))->willReturn([ - new ApiFilter(['value' => DoesNotImplementInterfaceFilter::class]), - ]); - $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); - - $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); - $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ - __DIR__.'/../../../../Fixtures/TestBundle/Entity/', - ]); - $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); - - $annotationFilterPass = new AnnotationFilterPass(); - $annotationFilterPass->process($containerBuilderProphecy->reveal()); - } - - public function testProcessFilterWhichHasAlreadyBeenRegistered(): void - { - $readerProphecy = $this->prophesize(Reader::class); - $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); - $readerProphecy->getClassAnnotations(Argument::allOf( - Argument::type(\ReflectionClass::class), - Argument::which('getName', Dummy::class) - ))->willReturn([ - new ApiFilter(['value' => SearchFilter::class]), - ]); - $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); - - $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); - $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ - __DIR__.'/../../../../Fixtures/TestBundle/Entity/', - ]); - $containerBuilderProphecy->has('annotation_reader')->willReturn(true); - $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(true); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(true); - $containerBuilderProphecy->setDefinition(Argument::cetera())->shouldNotBeCalled(); - - $annotationFilterPass = new AnnotationFilterPass(); - $annotationFilterPass->process($containerBuilderProphecy->reveal()); - } - - public function testProcessInvalidFilterClass(): void - { - $this->expectException(DependencyInjectionInvalidArgumentException::class); - $this->expectExceptionMessage(sprintf('Class "%s" used for service "annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter" cannot be found.', SearchFilter::class)); - - $readerProphecy = $this->prophesize(Reader::class); - $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); - $readerProphecy->getClassAnnotations(Argument::allOf( - Argument::type(\ReflectionClass::class), - Argument::which('getName', Dummy::class) - ))->willReturn([ - new ApiFilter(['value' => SearchFilter::class]), - ]); - $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); - - $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); - $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ - __DIR__.'/../../../../Fixtures/TestBundle/Entity/', - ]); - $containerBuilderProphecy->has('annotation_reader')->willReturn(true); - $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(false); - $containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(null); - - $annotationFilterPass = new AnnotationFilterPass(); - $annotationFilterPass->process($containerBuilderProphecy->reveal()); - } - - public function testProcessFilterWithoutConstructor(): void - { - $readerProphecy = $this->prophesize(Reader::class); - $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); - $readerProphecy->getClassAnnotations(Argument::allOf( - Argument::type(\ReflectionClass::class), - Argument::which('getName', Dummy::class) - ))->willReturn([ - new ApiFilter(['value' => NoConstructorFilter::class]), - ]); - $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); - - $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); - $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ - __DIR__.'/../../../../Fixtures/TestBundle/Entity/', - ]); - $containerBuilderProphecy->has('annotation_reader')->willReturn(true); - $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_filter_no_constructor_filter')->willReturn(false); - $containerBuilderProphecy->getReflectionClass(NoConstructorFilter::class, false)->willReturn(new \ReflectionClass(NoConstructorFilter::class)); - $containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(new \ReflectionClass(SearchFilter::class)); - $containerBuilderProphecy->has(NoConstructorFilter::class)->willReturn(true); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(true); - $containerBuilderProphecy->findDefinition(NoConstructorFilter::class)->willReturn((new Definition(NoConstructorFilter::class))->setAbstract(false)); - $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_filter_no_constructor_filter', Argument::allOf( - Argument::type(Definition::class), - Argument::that(function (Definition $definition): bool { - return NoConstructorFilter::class === $definition->getClass() && [] === $definition->getArguments(); - }) - ))->shouldBeCalled(); - - $annotationFilterPass = new AnnotationFilterPass(); - $annotationFilterPass->process($containerBuilderProphecy->reveal()); - } - - public function testProcessFilterWithoutPropertiesArgument(): void - { - $readerProphecy = $this->prophesize(Reader::class); - $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); - $readerProphecy->getClassAnnotations(Argument::allOf( - Argument::type(\ReflectionClass::class), - Argument::which('getName', Dummy::class) - ))->willReturn([ - new ApiFilter(['value' => NoPropertiesArgumentFilter::class]), - ]); - $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); - - $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); - $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ - __DIR__.'/../../../../Fixtures/TestBundle/Entity/', - ]); - $containerBuilderProphecy->has('annotation_reader')->willReturn(true); - $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_filter_no_properties_argument_filter')->willReturn(false); - $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(true); - $containerBuilderProphecy->getReflectionClass(NoPropertiesArgumentFilter::class, false)->willReturn(new \ReflectionClass(NoPropertiesArgumentFilter::class)); - $containerBuilderProphecy->has(NoPropertiesArgumentFilter::class)->willReturn(true); - $containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(new \ReflectionClass(SearchFilter::class)); - $containerBuilderProphecy->findDefinition(NoPropertiesArgumentFilter::class)->willReturn((new Definition(NoPropertiesArgumentFilter::class))->setAbstract(false)); - $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_filter_no_properties_argument_filter', Argument::allOf( - Argument::type(Definition::class), - Argument::that(function (Definition $definition): bool { - return NoPropertiesArgumentFilter::class === $definition->getClass() && [] === $definition->getArguments(); - }) - ))->shouldBeCalled(); - - $annotationFilterPass = new AnnotationFilterPass(); - $annotationFilterPass->process($containerBuilderProphecy->reveal()); - } -} From 352509bbc43268fdbeaef104192a715e8139f585 Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 13 May 2022 14:17:36 +0200 Subject: [PATCH 11/56] refactor(json-schema): schema factory --- src/Util/ResourceClassInfoTrait.php | 15 ++------------- tests/JsonSchema/SchemaFactoryTest.php | 10 +++++----- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/Util/ResourceClassInfoTrait.php b/src/Util/ResourceClassInfoTrait.php index fa5bec30697..abc08f7a147 100644 --- a/src/Util/ResourceClassInfoTrait.php +++ b/src/Util/ResourceClassInfoTrait.php @@ -14,8 +14,6 @@ namespace ApiPlatform\Util; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; /** @@ -33,7 +31,7 @@ trait ResourceClassInfoTrait private $resourceClassResolver; /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface|null + * @var ResourceMetadataCollectionFactoryInterface|null */ private $resourceMetadataFactory; @@ -66,19 +64,10 @@ private function isResourceClass(string $class): bool return $this->resourceClassResolver->isResourceClass($class); } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { + if ($this->resourceMetadataFactory) { return \count($this->resourceMetadataFactory->create($class)) > 0 ? true : false; } - // TODO: 3.0 remove - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - try { - $this->resourceMetadataFactory->create($class); - } catch (ResourceClassNotFoundException $e) { - return false; - } - } - // assume that it's a resource class return true; } diff --git a/tests/JsonSchema/SchemaFactoryTest.php b/tests/JsonSchema/SchemaFactoryTest.php index 86b76332d9e..9293edda45f 100644 --- a/tests/JsonSchema/SchemaFactoryTest.php +++ b/tests/JsonSchema/SchemaFactoryTest.php @@ -109,11 +109,11 @@ public function testBuildSchemaForOperationWithOverriddenSerializerGroups(): voi AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false, ])->withShortName($shortName)->withValidationContext(['groups' => ['validation_groups_dummy_put']]); $resourceMetadataFactoryProphecy->create(OverriddenOperationDummy::class) - ->willReturn( - new ResourceMetadataCollection(OverriddenOperationDummy::class, [ - (new ApiResource())->withOperations(new Operations(['put' => $operation])), - ]) - ); + ->willReturn( + new ResourceMetadataCollection(OverriddenOperationDummy::class, [ + (new ApiResource())->withOperations(new Operations(['put' => $operation])), + ]) + ); $serializerGroup = 'overridden_operation_dummy_put'; $validationGroups = 'validation_groups_dummy_put'; From e5ee7735793f8a33775d366c6c6850af1828384c Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 13 May 2022 15:50:32 +0200 Subject: [PATCH 12/56] refactor(json-schema): schema factory --- .../Command/JsonSchemaGenerateCommand.php | 36 +++---------------- src/JsonSchema/TypeFactory.php | 2 +- .../Bundle/Test/ApiTestAssertionsTrait.php | 20 ++--------- tests/Fixtures/TestBundle/Entity/Dummy.php | 11 +++--- tests/Hydra/JsonSchema/SchemaFactoryTest.php | 7 ++-- .../Command/JsonSchemaGenerateCommandTest.php | 18 +++------- 6 files changed, 19 insertions(+), 75 deletions(-) diff --git a/src/JsonSchema/Command/JsonSchemaGenerateCommand.php b/src/JsonSchema/Command/JsonSchemaGenerateCommand.php index 4cdd7e9a941..46a0f297d3e 100644 --- a/src/JsonSchema/Command/JsonSchemaGenerateCommand.php +++ b/src/JsonSchema/Command/JsonSchemaGenerateCommand.php @@ -13,8 +13,6 @@ namespace ApiPlatform\JsonSchema\Command; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface as LegacySchemaFactoryInterface; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\HttpOperation; @@ -57,8 +55,7 @@ protected function configure() $this ->setDescription('Generates the JSON Schema for a resource operation.') ->addArgument('resource', InputArgument::REQUIRED, 'The Fully Qualified Class Name (FQCN) of the resource') - ->addOption('itemOperation', null, InputOption::VALUE_REQUIRED, 'The item operation') - ->addOption('collectionOperation', null, InputOption::VALUE_REQUIRED, 'The collection operation') + ->addOption('operation', null, InputOption::VALUE_REQUIRED, 'The operation name') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The response format', (string) $this->formats[0]) ->addOption('type', null, InputOption::VALUE_REQUIRED, sprintf('The type of schema to generate (%s or %s)', Schema::TYPE_INPUT, Schema::TYPE_OUTPUT), Schema::TYPE_INPUT); } @@ -72,10 +69,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** @var string $resource */ $resource = $input->getArgument('resource'); - /** @var ?string $itemOperation */ - $itemOperation = $input->getOption('itemOperation'); - /** @var ?string $collectionOperation */ - $collectionOperation = $input->getOption('collectionOperation'); + $operation = $input->getOption('operation'); /** @var string $format */ $format = $input->getOption('format'); /** @var string $type */ @@ -91,30 +85,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int throw new InvalidOptionException(sprintf('The response format "%s" is not supported. Supported formats are : %s.', $format, implode(', ', $this->formats))); } - /** @var ?string $operationType */ - $operationType = null; - /** @var ?string $operationName */ - $operationName = null; + $schema = $this->schemaFactory->buildSchema($resource, $format, $type, $operation ? (new class() extends HttpOperation {})->withName($operation) : null); - if ($itemOperation && $collectionOperation) { - $io->error('You can only use one of "--itemOperation" and "--collectionOperation" options at the same time.'); - - return 1; - } - - if (null !== $itemOperation || null !== $collectionOperation) { - $operationType = $itemOperation ? OperationType::ITEM : OperationType::COLLECTION; - $operationName = $itemOperation ?? $collectionOperation; - } - - if ($this->schemaFactory instanceof LegacySchemaFactoryInterface) { - $schema = $this->schemaFactory->buildSchema($resource, $format, $type, $operationType, $operationName); - } else { - $schema = $this->schemaFactory->buildSchema($resource, $format, $type, $operationName ? (new class() extends HttpOperation {})->withName($operationName) : null); - } - - if (null !== $operationType && null !== $operationName && !$schema->isDefined()) { - $io->error(sprintf('There is no %s defined for the operation "%s" of the resource "%s".', $type, $operationName, $resource)); + if (!$schema->isDefined()) { + $io->error(sprintf('There is no %s defined for the operation "%s" of the resource "%s".', $type, $operation, $resource)); return 1; } diff --git a/src/JsonSchema/TypeFactory.php b/src/JsonSchema/TypeFactory.php index 45754f5eca1..6c0c3aaba79 100644 --- a/src/JsonSchema/TypeFactory.php +++ b/src/JsonSchema/TypeFactory.php @@ -154,7 +154,7 @@ private function getClassType(?string $className, string $format, ?bool $readabl throw new \LogicException('The schema factory must be injected by calling the "setSchemaFactory" method.'); } - $subSchema = $this->schemaFactory instanceof LegacySchemaFactoryInterface ? $this->schemaFactory->buildSchema($className, $format, Schema::TYPE_OUTPUT, null, null, $subSchema, $serializerContext, false) : $this->schemaFactory->buildSchema($className, $format, Schema::TYPE_OUTPUT, null, $subSchema, $serializerContext, false); + $subSchema = $this->schemaFactory->buildSchema($className, $format, Schema::TYPE_OUTPUT, null, $subSchema, $serializerContext, false); return ['$ref' => $subSchema['$ref']]; } diff --git a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php b/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php index dc7150c2067..60080f41703 100644 --- a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php +++ b/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Symfony\Bundle\Test; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\JsonSchema\SchemaFactoryInterface as LegacySchemaFactoryInterface; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Get; @@ -115,28 +113,14 @@ public static function assertMatchesJsonSchema($jsonSchema, ?int $checkMode = nu public static function assertMatchesResourceCollectionJsonSchema(string $resourceClass, ?string $operationName = null, string $format = 'jsonld'): void { - $schemaFactory = self::getSchemaFactory(); - - if ($schemaFactory instanceof LegacySchemaFactoryInterface) { - $schema = $schemaFactory->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, OperationType::COLLECTION, $operationName, null); - } else { - $operation = $operationName ? (new GetCollection())->withName($operationName) : new GetCollection(); - $schema = $schemaFactory->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, $operation, null); - } + $schema = self::getSchemaFactory()->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, new GetCollection(name: $operationName), null); static::assertMatchesJsonSchema($schema->getArrayCopy()); } public static function assertMatchesResourceItemJsonSchema(string $resourceClass, ?string $operationName = null, string $format = 'jsonld'): void { - $schemaFactory = self::getSchemaFactory(); - - if ($schemaFactory instanceof LegacySchemaFactoryInterface) { - $schema = $schemaFactory->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, OperationType::ITEM, $operationName, null); - } else { - $operation = $operationName ? (new Get())->withName($operationName) : new Get(); - $schema = $schemaFactory->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, $operation, null); - } + $schema = self::getSchemaFactory()->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, new Get(name: $operationName), null); static::assertMatchesJsonSchema($schema->getArrayCopy()); } diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index e0ec439d089..32439d08b7e 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -98,17 +98,14 @@ class Dummy #[ORM\Column(type: 'decimal', precision: 10, scale: 2, nullable: true)] public $dummyPrice; - /** - * @var RelatedDummy|null A related dummy - */ #[ApiProperty(push: true)] - #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] - public $relatedDummy; + #[ORM\ManyToOne(targetEntity: RelatedDummy::class)] + public ?RelatedDummy $relatedDummy; /** - * @var \Collection Several dummies + * @var \Collection Several dummies */ - #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] + #[ORM\ManyToMany(targetEntity: RelatedDummy::class)] public $relatedDummies; /** diff --git a/tests/Hydra/JsonSchema/SchemaFactoryTest.php b/tests/Hydra/JsonSchema/SchemaFactoryTest.php index d4cb02c82bd..45c1a96faa5 100644 --- a/tests/Hydra/JsonSchema/SchemaFactoryTest.php +++ b/tests/Hydra/JsonSchema/SchemaFactoryTest.php @@ -21,7 +21,6 @@ use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; @@ -43,9 +42,9 @@ protected function setUp(): void $resourceMetadataFactoryCollection = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryCollection->create(Dummy::class)->willReturn( new ResourceMetadataCollection(Dummy::class, [ - (new ApiResource())->withOperations(new Operations([ - 'get' => (new Get())->withName('get'), - ])), + new ApiResource(operations: [ + 'get' => new Get(name: 'get'), + ]), ]) ); diff --git a/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php b/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php index 638d1930a09..4e0350b0b3e 100644 --- a/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php +++ b/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php @@ -21,8 +21,6 @@ /** * @author Jacques Lefebvre - * - * @group legacy */ class JsonSchemaGenerateCommandTest extends KernelTestCase { @@ -32,7 +30,6 @@ class JsonSchemaGenerateCommandTest extends KernelTestCase private $tester; private $entityClass; - private $legacy; protected function setUp(): void { @@ -44,40 +41,33 @@ protected function setUp(): void $this->entityClass = 'mongodb' === $kernel->getEnvironment() ? DocumentDummy::class : Dummy::class; $this->tester = new ApplicationTester($application); - $this->legacy = $kernel->getContainer()->getParameter('api_platform.metadata_backward_compatibility_layer'); } public function testExecuteWithoutOption() { $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass]); + dump($this->tester->getDisplay()); $this->assertJson($this->tester->getDisplay()); } public function testExecuteWithItemOperationGet() { - $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--itemOperation' => 'api_dummies_get_item', '--type' => 'output']); + $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => 'api_dummies_get_item', '--type' => 'output']); $this->assertJson($this->tester->getDisplay()); } public function testExecuteWithCollectionOperationGet() { - $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--collectionOperation' => 'api_dummies_get_collection', '--type' => 'output']); + $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => 'api_dummies_get_collection', '--type' => 'output']); $this->assertJson($this->tester->getDisplay()); } - public function testExecuteWithTooManyOptions() - { - $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--collectionOperation' => '_api_/dummies.{_format}_get', '--itemOperation' => '_api_/dummies/{id}.{_format}_get', '--type' => 'output']); - - $this->assertStringStartsWith('[ERROR] You can only use one of "--itemOperation" and "--collectionOperation" options at the same time.', trim(preg_replace('/\s+/', ' ', $this->tester->getDisplay()))); - } - public function testExecuteWithJsonldFormatOption() { - $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--collectionOperation' => $this->legacy ? 'post' : 'api_dummies_post_collection', '--format' => 'jsonld']); + $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => 'api_dummies_post_collection', '--format' => 'jsonld']); $result = $this->tester->getDisplay(); $this->assertStringContainsString('@id', $result); From 4ea0564ede1ea611c8d916a901c8cbf6f271bd7e Mon Sep 17 00:00:00 2001 From: Vincent Date: Mon, 16 May 2022 10:59:07 +0200 Subject: [PATCH 13/56] test: fix Hydra/Serializer tests (#41) --- .../CollectionFiltersNormalizer.php | 28 +- src/Hydra/Serializer/CollectionNormalizer.php | 20 +- .../Serializer/DocumentationNormalizer.php | 274 ++++-------------- src/Hydra/Serializer/EntrypointNormalizer.php | 33 +-- .../PartialCollectionViewNormalizer.php | 13 +- src/Symfony/Bundle/Resources/config/hydra.xml | 2 - .../CollectionFiltersNormalizerTest.php | 94 +++--- .../Serializer/CollectionNormalizerTest.php | 32 +- .../DocumentationNormalizerTest.php | 136 ++------- .../Serializer/EntrypointNormalizerTest.php | 27 +- .../PartialCollectionViewNormalizerTest.php | 25 +- 11 files changed, 185 insertions(+), 499 deletions(-) diff --git a/src/Hydra/Serializer/CollectionFiltersNormalizer.php b/src/Hydra/Serializer/CollectionFiltersNormalizer.php index 43c3453e8e5..6f125ccc342 100644 --- a/src/Hydra/Serializer/CollectionFiltersNormalizer.php +++ b/src/Hydra/Serializer/CollectionFiltersNormalizer.php @@ -16,9 +16,6 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\FilterLocatorTrait; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\ResourceClassResolverInterface as LegacyResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use Psr\Container\ContainerInterface; use Symfony\Component\Serializer\Exception\UnexpectedValueException; @@ -39,19 +36,15 @@ final class CollectionFiltersNormalizer implements NormalizerInterface, Normaliz private $resourceClassResolver; /** - * @param ContainerInterface|FilterCollection $filterLocator The new filter locator or the deprecated filter collection - * @param mixed $resourceMetadataFactory - * @param ResourceClassResolverInterface|LegacyResourceClassResolverInterface $resourceClassResolver + * @param ContainerInterface $filterLocator The new filter locator or the deprecated filter collection + * @param mixed $resourceMetadataFactory */ - public function __construct(NormalizerInterface $collectionNormalizer, $resourceMetadataFactory, $resourceClassResolver, $filterLocator) + public function __construct(NormalizerInterface $collectionNormalizer, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ContainerInterface $filterLocator) { $this->setFilterLocator($filterLocator); $this->collectionNormalizer = $collectionNormalizer; $this->resourceMetadataFactory = $resourceMetadataFactory; $this->resourceClassResolver = $resourceClassResolver; - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -85,19 +78,8 @@ public function normalize($object, $format = null, array $context = []) return $data; } $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class']); - $resourceFilters = null; - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $operationName = $context['collection_operation_name'] ?? null; - if (null === $operationName) { - $resourceFilters = $resourceMetadata->getAttribute('filters', []); - } else { - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); - } - } elseif ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation($context['operation_name'] ?? null); - $resourceFilters = $operation->getFilters(); - } + $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation($context['operation_name'] ?? null); + $resourceFilters = $operation->getFilters(); if (!$resourceFilters) { return $data; } diff --git a/src/Hydra/Serializer/CollectionNormalizer.php b/src/Hydra/Serializer/CollectionNormalizer.php index 36b335cb821..fa13ab4d532 100644 --- a/src/Hydra/Serializer/CollectionNormalizer.php +++ b/src/Hydra/Serializer/CollectionNormalizer.php @@ -16,8 +16,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Api\OperationType; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\JsonLdContextTrait; use ApiPlatform\Serializer\ContextTrait; @@ -50,14 +48,10 @@ final class CollectionNormalizer implements NormalizerInterface, NormalizerAware self::IRI_ONLY => false, ]; - public function __construct(ContextBuilderInterface $contextBuilder, ResourceClassResolverInterface $resourceClassResolver, $iriConverter, array $defaultContext = []) + public function __construct(ContextBuilderInterface $contextBuilder, ResourceClassResolverInterface $resourceClassResolver, IriConverterInterface $iriConverter, array $defaultContext = []) { $this->contextBuilder = $contextBuilder; $this->resourceClassResolver = $resourceClassResolver; - - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } $this->iriConverter = $iriConverter; $this->defaultContext = array_merge($this->defaultContext, $defaultContext); } @@ -84,14 +78,7 @@ public function normalize($object, $format = null, array $context = []): array $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class']); $context = $this->initContext($resourceClass, $context); $data = $this->addJsonLdContext($this->contextBuilder, $resourceClass, $context); - - if ($this->iriConverter instanceof LegacyIriConverterInterface) { - // TODO: remove in 3.0 - $data['@id'] = isset($context['operation_type']) && OperationType::SUBRESOURCE === $context['operation_type'] ? $this->iriConverter->getSubresourceIriFromResourceClass($resourceClass, $context) : $this->iriConverter->getIriFromResourceClass($resourceClass); - } else { - $data['@id'] = $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); - } - + $data['@id'] = $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); $data['@type'] = 'hydra:Collection'; $data['hydra:member'] = []; $iriOnly = $context[self::IRI_ONLY] ?? $this->defaultContext[self::IRI_ONLY]; @@ -99,7 +86,7 @@ public function normalize($object, $format = null, array $context = []): array foreach ($object as $obj) { if ($iriOnly) { - $data['hydra:member'][] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($obj) : $this->iriConverter->getIriFromResource($obj); + $data['hydra:member'][] = $this->iriConverter->getIriFromResource($obj); } else { $data['hydra:member'][] = $this->normalizer->normalize($obj, $format, $context); } @@ -108,6 +95,7 @@ public function normalize($object, $format = null, array $context = []): array if ($object instanceof PaginatorInterface) { $data['hydra:totalItems'] = $object->getTotalItems(); } + if (\is_array($object) || ($object instanceof \Countable && !$object instanceof PartialPaginatorInterface)) { $data['hydra:totalItems'] = \count($object); } diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index 3b3c154b5c3..483bc5567cd 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -15,15 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Documentation\Documentation; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\ApiProperty; @@ -33,6 +24,7 @@ use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use Symfony\Component\PropertyInfo\Type; @@ -50,44 +42,20 @@ final class DocumentationNormalizer implements NormalizerInterface, CacheableSup { public const FORMAT = 'jsonld'; - /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface - */ private $resourceMetadataFactory; private $propertyNameCollectionFactory; - - /** - * @var PropertyMetadataFactoryInterface|LegacyPropertyMetadataFactoryInterface - */ private $propertyMetadataFactory; private $resourceClassResolver; - private $operationMethodResolver; private $urlGenerator; - private $subresourceOperationFactory; private $nameConverter; - public function __construct($resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver = null, UrlGeneratorInterface $urlGenerator, SubresourceOperationFactoryInterface $subresourceOperationFactory = null, NameConverterInterface $nameConverter = null) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, UrlGeneratorInterface $urlGenerator, NameConverterInterface $nameConverter = null) { - if ($operationMethodResolver) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', OperationMethodResolverInterface::class, __METHOD__), \E_USER_DEPRECATED); - } - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - if ($subresourceOperationFactory) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Using "%s" is deprecated and will be removed.', SubresourceOperationFactoryInterface::class)); - } - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; $this->resourceClassResolver = $resourceClassResolver; - $this->operationMethodResolver = $operationMethodResolver; $this->urlGenerator = $urlGenerator; - $this->subresourceOperationFactory = $subresourceOperationFactory; $this->nameConverter = $nameConverter; } @@ -103,20 +71,10 @@ public function normalize($object, $format = null, array $context = []) foreach ($object->getResourceNameCollection() as $resourceClass) { $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadataCollection instanceof ResourceMetadata) { - $shortName = $resourceMetadataCollection->getShortName(); - $prefixedShortName = $resourceMetadataCollection->getIri() ?? "#$shortName"; - - $this->populateEntrypointProperties($resourceClass, $resourceMetadataCollection, $shortName, $prefixedShortName, $entrypointProperties); - $classes[] = $this->getClass($resourceClass, $resourceMetadataCollection, $shortName, $prefixedShortName, $context); - continue; - } - $resourceMetadata = $resourceMetadataCollection[0]; $shortName = $resourceMetadata->getShortName(); $prefixedShortName = $resourceMetadata->getTypes()[0] ?? "#$shortName"; - $this->populateEntrypointProperties($resourceClass, $resourceMetadata, $shortName, $prefixedShortName, $entrypointProperties, $resourceMetadataCollection); + $this->populateEntrypointProperties($resourceMetadata, $shortName, $prefixedShortName, $entrypointProperties, $resourceMetadataCollection); $classes[] = $this->getClass($resourceClass, $resourceMetadata, $shortName, $prefixedShortName, $context, $resourceMetadataCollection); } @@ -125,12 +83,10 @@ public function normalize($object, $format = null, array $context = []) /** * Populates entrypoint properties. - * - * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function populateEntrypointProperties(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array &$entrypointProperties, ?ResourceMetadataCollection $resourceMetadataCollection = null) + private function populateEntrypointProperties(ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array &$entrypointProperties, ?ResourceMetadataCollection $resourceMetadataCollection = null) { - $hydraCollectionOperations = $this->getHydraOperations($resourceClass, $resourceMetadata, $prefixedShortName, true, $resourceMetadataCollection); + $hydraCollectionOperations = $this->getHydraOperations(true, $resourceMetadataCollection); if (empty($hydraCollectionOperations)) { return; } @@ -158,7 +114,7 @@ private function populateEntrypointProperties(string $resourceClass, $resourceMe 'hydra:writeable' => false, ]; - if ($resourceMetadata instanceof ResourceMetadata ? $resourceMetadata->getCollectionOperationAttribute('GET', 'deprecation_reason', null, true) : $resourceMetadata->getDeprecationReason()) { + if ($resourceMetadata->getDeprecationReason()) { $entrypointProperty['owl:deprecated'] = true; } @@ -167,18 +123,11 @@ private function populateEntrypointProperties(string $resourceClass, $resourceMe /** * Gets a Hydra class. - * - * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getClass(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array $context, ?ResourceMetadataCollection $resourceMetadataCollection = null): array + private function getClass(string $resourceClass, ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array $context, ?ResourceMetadataCollection $resourceMetadataCollection = null): array { - if ($resourceMetadata instanceof ApiResource) { - $description = $resourceMetadata->getDescription(); - $isDeprecated = $resourceMetadata->getDeprecationReason(); - } else { - $description = $resourceMetadata->getDescription(); - $isDeprecated = $resourceMetadata->getAttribute('deprecation_reason'); - } + $description = $resourceMetadata->getDescription(); + $isDeprecated = $resourceMetadata->getDeprecationReason(); $class = [ '@id' => $prefixedShortName, @@ -186,7 +135,7 @@ private function getClass(string $resourceClass, $resourceMetadata, string $shor 'rdfs:label' => $shortName, 'hydra:title' => $shortName, 'hydra:supportedProperty' => $this->getHydraProperties($resourceClass, $resourceMetadata, $shortName, $prefixedShortName, $context), - 'hydra:supportedOperation' => $this->getHydraOperations($resourceClass, $resourceMetadata, $prefixedShortName, false, $resourceMetadataCollection), + 'hydra:supportedOperation' => $this->getHydraOperations(false, $resourceMetadataCollection), ]; if (null !== $description) { @@ -200,35 +149,6 @@ private function getClass(string $resourceClass, $resourceMetadata, string $shor return $class; } - /** - * Gets the context for the property name factory. - */ - private function getPropertyNameCollectionFactoryContext(ResourceMetadata $resourceMetadata): array - { - $attributes = $resourceMetadata->getAttributes(); - $context = []; - - if (isset($attributes['normalization_context'][AbstractNormalizer::GROUPS])) { - $context['serializer_groups'] = (array) $attributes['normalization_context'][AbstractNormalizer::GROUPS]; - } - - if (!isset($attributes['denormalization_context'][AbstractNormalizer::GROUPS])) { - return $context; - } - - if (isset($context['serializer_groups'])) { - foreach ((array) $attributes['denormalization_context'][AbstractNormalizer::GROUPS] as $groupName) { - $context['serializer_groups'][] = $groupName; - } - - return $context; - } - - $context['serializer_groups'] = (array) $attributes['denormalization_context'][AbstractNormalizer::GROUPS]; - - return $context; - } - /** * Creates context for property metatata factories. */ @@ -265,54 +185,36 @@ private function getPropertyMetadataFactoryContext(ApiResource $resourceMetadata /** * Gets Hydra properties. - * - * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getHydraProperties(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array $context): array + private function getHydraProperties(string $resourceClass, ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array $context): array { $classes = []; - if ($resourceMetadata instanceof ResourceMetadata) { - foreach ($resourceMetadata->getCollectionOperations() as $operationName => $operation) { - $inputMetadata = $resourceMetadata->getTypedOperationAttribute(OperationType::COLLECTION, $operationName, 'input', ['class' => $resourceClass], true); - if (null !== $inputClass = $inputMetadata['class'] ?? null) { - $classes[$inputClass] = true; - } - - $outputMetadata = $resourceMetadata->getTypedOperationAttribute(OperationType::COLLECTION, $operationName, 'output', ['class' => $resourceClass], true); - if (null !== $outputClass = $outputMetadata['class'] ?? null) { - $classes[$outputClass] = true; - } + foreach ($resourceMetadata->getOperations() as $operation) { + /** @var Operation $operation */ + if (!$operation instanceof CollectionOperationInterface) { + continue; } - } else { - $classes[$resourceClass] = true; - foreach ($resourceMetadata->getOperations() as $operation) { - /** @var Operation $operation */ - if (!$operation instanceof CollectionOperationInterface) { - continue; - } - $inputMetadata = $operation->getInput(); - if (null !== $inputClass = $inputMetadata['class'] ?? null) { - $classes[$inputClass] = true; - } + $inputMetadata = $operation->getInput(); + if (null !== $inputClass = $inputMetadata['class'] ?? null) { + $classes[$inputClass] = true; + } - $outputMetadata = $operation->getOutput(); - if (null !== $outputClass = $outputMetadata['class'] ?? null) { - $classes[$outputClass] = true; - } + $outputMetadata = $operation->getOutput(); + if (null !== $outputClass = $outputMetadata['class'] ?? null) { + $classes[$outputClass] = true; } } + if (!$classes) { + $classes[$resourceClass] = true; + } + /** @var string[] $classes */ $classes = array_keys($classes); $properties = []; - if ($resourceMetadata instanceof ResourceMetadata) { - $propertyNameContext = $this->getPropertyNameCollectionFactoryContext($resourceMetadata); - $propertyContext = []; - } else { - [$propertyNameContext, $propertyContext] = $this->getPropertyMetadataFactoryContext($resourceMetadata); - } + [$propertyNameContext, $propertyContext] = $this->getPropertyMetadataFactoryContext($resourceMetadata); foreach ($classes as $class) { foreach ($this->propertyNameCollectionFactory->create($class, $propertyNameContext) as $propertyName) { @@ -335,38 +237,17 @@ private function getHydraProperties(string $resourceClass, $resourceMetadata, st /** * Gets Hydra operations. - * - * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getHydraOperations(string $resourceClass, $resourceMetadata, string $prefixedShortName, bool $collection, ?ResourceMetadataCollection $resourceMetadataCollection = null): array + private function getHydraOperations(bool $collection, ?ResourceMetadataCollection $resourceMetadataCollection = null): array { - if ($resourceMetadata instanceof ResourceMetadata) { - if (null === $operations = $collection ? $resourceMetadata->getCollectionOperations() : $resourceMetadata->getItemOperations()) { - return []; - } - - $hydraOperations = []; - foreach ($operations as $operationName => $operation) { - $hydraOperations[] = $this->getHydraOperation($resourceClass, $resourceMetadata, $operationName, $operation, $prefixedShortName, $collection ? OperationType::COLLECTION : OperationType::ITEM); - } - } else { - $hydraOperations = []; - foreach ($resourceMetadataCollection as $resourceMetadata) { - foreach ($resourceMetadata->getOperations() as $operationName => $operation) { - if (($operation instanceof Post || $operation instanceof CollectionOperationInterface) !== $collection) { - continue; - } - - $hydraOperations[] = $this->getHydraOperation($resourceClass, $resourceMetadata, $operationName, $operation, $operation->getTypes()[0] ?? "#{$operation->getShortName()}", null); + $hydraOperations = []; + foreach ($resourceMetadataCollection as $resourceMetadata) { + foreach ($resourceMetadata->getOperations() as $operation) { + if (($operation instanceof Post || $operation instanceof CollectionOperationInterface) !== $collection) { + continue; } - } - } - if (null !== $this->subresourceOperationFactory && !$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) { - $subresourceMetadata = $this->resourceMetadataFactory->create($operation['resource_class']); - $propertyMetadata = $this->propertyMetadataFactory->create(end($operation['identifiers'])[0], $operation['property']); - $hydraOperations[] = $this->getHydraOperation($resourceClass, $subresourceMetadata, $operation['route_name'], $operation, "#{$subresourceMetadata->getShortName()}", OperationType::SUBRESOURCE, $propertyMetadata->getSubresource()); + $hydraOperations[] = $this->getHydraOperation($operation, $operation->getTypes()[0] ?? "#{$operation->getShortName()}"); } } @@ -375,58 +256,27 @@ private function getHydraOperations(string $resourceClass, $resourceMetadata, st /** * Gets and populates if applicable a Hydra operation. - * - * @param ResourceMetadata|ApiResource $resourceMetadata - * @param SubresourceMetadata $subresourceMetadata - * @param array|HttpOperation $operation */ - private function getHydraOperation(string $resourceClass, $resourceMetadata, string $operationName, $operation, string $prefixedShortName, ?string $operationType = null, SubresourceMetadata $subresourceMetadata = null): array + private function getHydraOperation(HttpOperation $operation, string $prefixedShortName): array { - if ($operation instanceof HttpOperation) { - $method = $operation->getMethod() ?: HttpOperation::METHOD_GET; - } elseif ($this->operationMethodResolver) { - if (OperationType::COLLECTION === $operationType) { - $method = $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); - } elseif (OperationType::ITEM === $operationType) { - $method = $this->operationMethodResolver->getItemOperationMethod($resourceClass, $operationName); - } else { - $method = 'GET'; - } - } else { - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); - } - + $method = $operation->getMethod() ?: HttpOperation::METHOD_GET; $hydraOperation = $operation instanceof HttpOperation ? ($operation->getHydraContext() ?? []) : ($operation['hydra_context'] ?? []); - if ($operation instanceof HttpOperation ? $operation->getDeprecationReason() : $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', null, true)) { + if ($operation->getDeprecationReason()) { $hydraOperation['owl:deprecated'] = true; } - if ($operation instanceof HttpOperation) { - $shortName = $operation->getShortName(); - $inputMetadata = $operation->getInput() ?? []; - $outputMetadata = $operation->getOutput() ?? []; - $operationType = $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM; - } else { - $shortName = $resourceMetadata->getShortName(); - $inputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input', ['class' => false]); - $outputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output', ['class' => false]); - } - + $shortName = $operation->getShortName(); + $inputMetadata = $operation->getInput() ?? []; + $outputMetadata = $operation->getOutput() ?? []; $inputClass = \array_key_exists('class', $inputMetadata) ? $inputMetadata['class'] : false; $outputClass = \array_key_exists('class', $outputMetadata) ? $outputMetadata['class'] : false; - if ('GET' === $method && OperationType::COLLECTION === $operationType) { + if ('GET' === $method && $operation instanceof CollectionOperationInterface) { $hydraOperation += [ '@type' => ['hydra:Operation', 'schema:FindAction'], 'hydra:title' => "Retrieves the collection of $shortName resources.", 'returns' => 'hydra:Collection', ]; - } elseif ('GET' === $method && OperationType::SUBRESOURCE === $operationType) { - $hydraOperation += [ - '@type' => ['hydra:Operation', 'schema:FindAction'], - 'hydra:title' => $subresourceMetadata && $subresourceMetadata->isCollection() ? "Retrieves the collection of $shortName resources." : "Retrieves a $shortName resource.", - 'returns' => null === $outputClass ? 'owl:Nothing' : "#$shortName", - ]; } elseif ('GET' === $method) { $hydraOperation += [ '@type' => ['hydra:Operation', 'schema:FindAction'], @@ -475,20 +325,17 @@ private function getHydraOperation(string $resourceClass, $resourceMetadata, str /** * Gets the range of the property. - * - * @param ApiProperty|PropertyMetadata $propertyMetadata */ - private function getRange($propertyMetadata): ?string + private function getRange(ApiProperty $propertyMetadata): ?string { - $jsonldContext = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttributes()['jsonld_context'] ?? [] : $propertyMetadata->getJsonldContext(); + $jsonldContext = $propertyMetadata->getJsonldContext(); if (isset($jsonldContext['@type'])) { return $jsonldContext['@type']; } - // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; - if (null === $type) { + $type = $propertyMetadata->getBuiltinTypes()[0] ?? []; + if ([] === $type) { return null; } @@ -516,17 +363,13 @@ private function getRange($propertyMetadata): ?string if ($this->resourceClassResolver->isResourceClass($className)) { $resourceMetadata = $this->resourceMetadataFactory->create($className); - if ($resourceMetadata instanceof ResourceMetadataCollection) { - $operation = $resourceMetadata->getOperation(); - - if (!$operation instanceof HttpOperation) { - return "#{$operation->getShortName()}"; - } + $operation = $resourceMetadata->getOperation(); - return $operation->getTypes()[0] ?? "#{$operation->getShortName()}"; + if (!$operation instanceof HttpOperation) { + return "#{$operation->getShortName()}"; } - return $resourceMetadata->getIri() ?? "#{$resourceMetadata->getShortName()}"; + return $operation->getTypes()[0] ?? "#{$operation->getShortName()}"; } } @@ -617,17 +460,11 @@ private function getClasses(array $entrypointProperties, array $classes): array /** * Gets a property definition. - * - * @param ApiProperty|PropertyMetadata $propertyMetadata */ - private function getProperty($propertyMetadata, string $propertyName, string $prefixedShortName, string $shortName): array + private function getProperty(ApiProperty $propertyMetadata, string $propertyName, string $prefixedShortName, string $shortName): array { - if ($propertyMetadata instanceof PropertyMetadata) { - $iri = $propertyMetadata->getIri(); - } else { - if ($iri = $propertyMetadata->getIris()) { - $iri = 1 === \count($iri) ? $iri[0] : $iri; - } + if ($iri = $propertyMetadata->getIris()) { + $iri = 1 === \count($iri) ? $iri[0] : $iri; } if (!isset($iri)) { @@ -641,10 +478,9 @@ private function getProperty($propertyMetadata, string $propertyName, string $pr 'domain' => $prefixedShortName, ]; - // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; - if (null !== $type && !$type->isCollection() && (null !== $className = $type->getClassName()) && $this->resourceClassResolver->isResourceClass($className)) { + if ([] !== $type && !$type->isCollection() && (null !== $className = $type->getClassName()) && $this->resourceClassResolver->isResourceClass($className)) { $propertyData['owl:maxCardinality'] = 1; } @@ -665,7 +501,7 @@ private function getProperty($propertyMetadata, string $propertyName, string $pr $property['hydra:description'] = $description; } - if ($deprecationReason = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('deprecation_reason') : $propertyMetadata->getDeprecationReason()) { + if ($propertyMetadata->getDeprecationReason()) { $property['owl:deprecated'] = true; } diff --git a/src/Hydra/Serializer/EntrypointNormalizer.php b/src/Hydra/Serializer/EntrypointNormalizer.php index 12b738b21d5..e4b22807462 100644 --- a/src/Hydra/Serializer/EntrypointNormalizer.php +++ b/src/Hydra/Serializer/EntrypointNormalizer.php @@ -16,14 +16,10 @@ use ApiPlatform\Api\Entrypoint; use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -40,17 +36,9 @@ final class EntrypointNormalizer implements NormalizerInterface, CacheableSuppor private $iriConverter; private $urlGenerator; - public function __construct($resourceMetadataFactory, $iriConverter, UrlGeneratorInterface $urlGenerator) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, IriConverterInterface $iriConverter, UrlGeneratorInterface $urlGenerator) { - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - $this->iriConverter = $iriConverter; - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->urlGenerator = $urlGenerator; } @@ -67,35 +55,22 @@ public function normalize($object, $format = null, array $context = []): array ]; foreach ($object->getResourceNameCollection() as $resourceClass) { - /** @var ResourceMetadata|ResourceMetadataCollection */ $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if ($resourceMetadata instanceof ResourceMetadata) { - if (empty($resourceMetadata->getCollectionOperations())) { - continue; - } - try { - $entrypoint[lcfirst($resourceMetadata->getShortName())] = $this->iriConverter->getIriFromResourceClass($resourceClass); - } catch (InvalidArgumentException $ex) { - // Ignore resources without GET operations - } - continue; - } - foreach ($resourceMetadata as $resource) { if ($resource->getExtraProperties()['is_alternate_resource_metadata'] ?? false) { continue; } - foreach ($resource->getOperations() as $operationName => $operation) { + foreach ($resource->getOperations() as $operation) { $key = lcfirst($resource->getShortName()); if (!$operation instanceof CollectionOperationInterface || isset($entrypoint[$key])) { continue; } try { - $entrypoint[$key] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromResourceClass($resourceClass) : $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_PATH, $operation); - } catch (InvalidArgumentException|OperationNotFoundException $ex) { + $entrypoint[$key] = $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_PATH, $operation); + } catch (InvalidArgumentException|OperationNotFoundException) { // Ignore resources without GET operations } } diff --git a/src/Hydra/Serializer/PartialCollectionViewNormalizer.php b/src/Hydra/Serializer/PartialCollectionViewNormalizer.php index f5c902e843b..c14c6b177f4 100644 --- a/src/Hydra/Serializer/PartialCollectionViewNormalizer.php +++ b/src/Hydra/Serializer/PartialCollectionViewNormalizer.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Hydra\Serializer; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; @@ -39,17 +38,12 @@ final class PartialCollectionViewNormalizer implements NormalizerInterface, Norm private $resourceMetadataFactory; private $propertyAccessor; - public function __construct(NormalizerInterface $collectionNormalizer, string $pageParameterName = 'page', string $enabledParameterName = 'pagination', $resourceMetadataFactory = null, PropertyAccessorInterface $propertyAccessor = null) + public function __construct(NormalizerInterface $collectionNormalizer, string $pageParameterName = 'page', string $enabledParameterName = 'pagination', ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, PropertyAccessorInterface $propertyAccessor = null) { $this->collectionNormalizer = $collectionNormalizer; $this->pageParameterName = $pageParameterName; $this->enabledParameterName = $enabledParameterName; $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor(); } @@ -91,10 +85,7 @@ public function normalize($object, $format = null, array $context = []) $isPaginatedWithCursor = false; $cursorPaginationAttribute = null; - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && isset($context['resource_class']) && $paginated) { - $metadata = $this->resourceMetadataFactory->create($context['resource_class']); - $isPaginatedWithCursor = null !== $cursorPaginationAttribute = $metadata->getCollectionOperationAttribute($context['collection_operation_name'] ?? $context['subresource_operation_name'], 'pagination_via_cursor', null, true); - } elseif ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && isset($context['resource_class']) && $paginated) { + if ($this->resourceMetadataFactory && isset($context['resource_class']) && $paginated) { $operation = $this->resourceMetadataFactory->create($context['resource_class'])->getOperation($context['operation_name'] ?? null); $isPaginatedWithCursor = [] !== $cursorPaginationAttribute = ($operation->getPaginationViaCursor() ?? []); } diff --git a/src/Symfony/Bundle/Resources/config/hydra.xml b/src/Symfony/Bundle/Resources/config/hydra.xml index 6710e7b7eb4..c94ad71262e 100644 --- a/src/Symfony/Bundle/Resources/config/hydra.xml +++ b/src/Symfony/Bundle/Resources/config/hydra.xml @@ -10,9 +10,7 @@ - null - null diff --git a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php index af309bea518..626da772d3f 100644 --- a/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php @@ -14,14 +14,15 @@ namespace ApiPlatform\Tests\Hydra\Serializer; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Doctrine\Orm\Filter\FilterInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Hydra\Serializer\CollectionFiltersNormalizer; use ApiPlatform\Hydra\Serializer\CollectionNormalizer; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\Foo; use ApiPlatform\Tests\Fixtures\NotAResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -34,7 +35,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class CollectionFiltersNormalizerTest extends TestCase { @@ -49,7 +49,7 @@ public function testSupportsNormalization() $normalizer = new CollectionFiltersNormalizer( $decoratedProphecy->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), + $this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $this->prophesize(ContainerInterface::class)->reveal() ); @@ -81,7 +81,7 @@ public function testNormalizeNonResourceCollection() $normalizedNotAResourceB, ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($data, null)->willThrow(InvalidArgumentException::class); @@ -132,7 +132,7 @@ public function testNormalizeSubLevelResourceCollection() $normalizedFooThree, ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); @@ -141,8 +141,7 @@ public function testNormalizeSubLevelResourceCollection() $normalizer = new CollectionFiltersNormalizer($decoratedProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), $filterLocatorProphecy->reveal()); $actual = $normalizer->normalize($data, CollectionNormalizer::FORMAT, [ - 'collection_operation_name' => 'get', - 'operation_type' => OperationType::COLLECTION, + 'operation_name' => 'get', 'resource_class' => Foo::class, 'api_sub_level' => true, ]); @@ -176,7 +175,7 @@ public function testNormalizeSubLevelNonResourceCollection() $normalizedNotAResourceB, ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($data, null)->willThrow(InvalidArgumentException::class); @@ -201,12 +200,18 @@ public function testDoNothingIfNoFilter() $decoratedProphecy = $this->prophesize(NormalizerInterface::class); $decoratedProphecy->normalize($dummy, CollectionNormalizer::FORMAT, [ - 'collection_operation_name' => 'get', + 'operation_name' => 'get', 'resource_class' => Dummy::class, ])->willReturn(['name' => 'foo']); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('foo', '', null, [], ['get' => []])); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(Dummy::class)) + ->withShortName('Dummy') + ->withOperations(new Operations([ + 'get' => (new GetCollection())->withShortName('Dummy'), + ])), + ])); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class)->willReturn(Dummy::class); @@ -219,7 +224,7 @@ public function testDoNothingIfNoFilter() ); $this->assertEquals(['name' => 'foo'], $normalizer->normalize($dummy, CollectionNormalizer::FORMAT, [ - 'collection_operation_name' => 'get', + 'operation_name' => 'get', 'resource_class' => Dummy::class, ])); } @@ -231,10 +236,17 @@ public function testDoNothingIfNoRequestUri() $decoratedProphecy = $this->prophesize(NormalizerInterface::class); $decoratedProphecy->normalize($dummy, CollectionNormalizer::FORMAT, [ 'resource_class' => Dummy::class, + 'operation_name' => 'get', ])->willReturn(['name' => 'foo']); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('foo', '', null, [], [], ['filters' => ['foo']])); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(Dummy::class)) + ->withShortName('Dummy') + ->withOperations(new Operations([ + 'get' => (new GetCollection())->withShortName('Dummy')->withFilters(['foo']), + ])), + ])); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class)->willReturn(Dummy::class); @@ -248,6 +260,7 @@ public function testDoNothingIfNoRequestUri() $this->assertEquals(['name' => 'foo'], $normalizer->normalize($dummy, CollectionNormalizer::FORMAT, [ 'resource_class' => Dummy::class, + 'operation_name' => 'get', ])); } @@ -260,49 +273,23 @@ public function testNormalize() $filterLocatorProphecy->has('foo')->willReturn(true)->shouldBeCalled(); $filterLocatorProphecy->get('foo')->willReturn($filterProphecy->reveal())->shouldBeCalled(); - $this->normalize($filterLocatorProphecy->reveal()); - } - - /** - * @group legacy - * @expectedDeprecation The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Provide an implementation of Psr\Container\ContainerInterface instead. - */ - public function testNormalizeWithDeprecatedFilterCollection() - { - $filterProphecy = $this->prophesize(FilterInterface::class); - $filterProphecy->getDescription(Dummy::class)->willReturn(['a' => ['property' => 'name', 'required' => true]])->shouldBeCalled(); - - $this->normalize(new FilterCollection(['foo' => $filterProphecy->reveal()])); - } - - /** - * @group legacy - */ - public function testConstructWithInvalidFilterLocator() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "$filterLocator" argument is expected to be an implementation of the "Psr\\Container\\ContainerInterface" interface.'); - - new CollectionFiltersNormalizer( - $this->prophesize(NormalizerInterface::class)->reveal(), - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - new \ArrayObject() - ); - } - - private function normalize($filterLocator) - { $dummy = new Dummy(); $decoratedProphecy = $this->prophesize(NormalizerInterface::class); $decoratedProphecy->normalize($dummy, CollectionNormalizer::FORMAT, [ 'request_uri' => '/foo?bar=baz', 'resource_class' => Dummy::class, + 'operation_name' => 'get', ])->willReturn(['name' => 'foo']); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('foo', '', null, [], [], ['filters' => ['foo']])); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(Dummy::class)) + ->withShortName('Dummy') + ->withOperations(new Operations([ + 'get' => (new GetCollection())->withShortName('Dummy')->withFilters(['foo']), + ])), + ])); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class)->willReturn(Dummy::class); @@ -311,7 +298,7 @@ private function normalize($filterLocator) $decoratedProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - $filterLocator + $filterLocatorProphecy->reveal() ); $this->assertEquals([ @@ -332,6 +319,7 @@ private function normalize($filterLocator) ], $normalizer->normalize($dummy, CollectionNormalizer::FORMAT, [ 'request_uri' => '/foo?bar=baz', 'resource_class' => Dummy::class, + 'operation_name' => 'get', ])); } } diff --git a/tests/Hydra/Serializer/CollectionNormalizerTest.php b/tests/Hydra/Serializer/CollectionNormalizerTest.php index 3b025f1b3d6..63cf4d47d90 100644 --- a/tests/Hydra/Serializer/CollectionNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionNormalizerTest.php @@ -13,9 +13,9 @@ namespace ApiPlatform\Tests\Hydra\Serializer; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Api\OperationType; +use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Hydra\Serializer\CollectionNormalizer; use ApiPlatform\JsonLd\ContextBuilderInterface; @@ -45,7 +45,7 @@ public function testSupportsNormalize() $iriConvert = $this->prophesize(IriConverterInterface::class); $contextBuilder = $this->prophesize(ContextBuilderInterface::class); $contextBuilder->getResourceContextUri('Foo')->willReturn('/contexts/Foo'); - $iriConvert->getIriFromResourceClass('Foo')->willReturn('/foos'); + $iriConvert->getIriFromResource('Foo', UrlGeneratorInterface::ABS_PATH, Argument::any(), Argument::any())->willReturn('/foos'); $normalizer = new CollectionNormalizer($contextBuilder->reveal(), $resourceClassResolverProphecy->reveal(), $iriConvert->reveal()); @@ -87,7 +87,7 @@ public function testNormalizeResourceCollection() $resourceClassResolverProphecy->getResourceClass($data, Foo::class)->willReturn(Foo::class); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResourceClass(Foo::class)->willReturn('/foos'); + $iriConverterProphecy->getIriFromResource(Foo::class, UrlGeneratorInterface::ABS_PATH, Argument::any(), Argument::any())->willReturn('/foos'); $delegateNormalizerProphecy = $this->prophesize(NormalizerInterface::class); $delegateNormalizerProphecy->normalize($fooOne, CollectionNormalizer::FORMAT, Argument::allOf( @@ -103,8 +103,7 @@ public function testNormalizeResourceCollection() $normalizer->setNormalizer($delegateNormalizerProphecy->reveal()); $actual = $normalizer->normalize($data, CollectionNormalizer::FORMAT, [ - 'collection_operation_name' => 'get', - 'operation_type' => OperationType::COLLECTION, + 'operation_name' => 'get', 'resource_class' => Foo::class, ]); @@ -204,8 +203,7 @@ public function testNormalizeSubLevelResourceCollection() $normalizer->setNormalizer($delegateNormalizerProphecy->reveal()); $actual = $normalizer->normalize($data, CollectionNormalizer::FORMAT, [ - 'collection_operation_name' => 'get', - 'operation_type' => OperationType::COLLECTION, + 'operation_name' => 'get', 'resource_class' => Foo::class, 'api_sub_level' => true, ]); @@ -316,7 +314,7 @@ private function normalizePaginator($partial = false) $resourceClassResolverProphecy->getResourceClass($paginatorProphecy, 'Foo')->willReturn('Foo'); $iriConvert = $this->prophesize(IriConverterInterface::class); - $iriConvert->getIriFromResourceClass('Foo')->willReturn('/foo/1'); + $iriConvert->getIriFromResource('Foo', UrlGeneratorInterface::ABS_PATH, Argument::any(), Argument::any())->willReturn('/foo/1'); $contextBuilder = $this->prophesize(ContextBuilderInterface::class); $contextBuilder->getResourceContextUri('Foo')->willReturn('/contexts/Foo'); @@ -355,9 +353,9 @@ public function testNormalizeIriOnlyResourceCollection(): void $resourceClassResolverProphecy->getResourceClass($data, Foo::class)->willReturn(Foo::class); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResourceClass(Foo::class)->willReturn('/foos'); - $iriConverterProphecy->getIriFromItem($fooOne)->willReturn('/foos/1'); - $iriConverterProphecy->getIriFromItem($fooThree)->willReturn('/foos/3'); + $iriConverterProphecy->getIriFromResource(Foo::class, UrlGeneratorInterface::ABS_PATH, Argument::any(), Argument::any())->willReturn('/foos'); + $iriConverterProphecy->getIriFromResource($fooOne)->willReturn('/foos/1'); + $iriConverterProphecy->getIriFromResource($fooThree)->willReturn('/foos/3'); $delegateNormalizerProphecy = $this->prophesize(NormalizerInterface::class); @@ -365,7 +363,7 @@ public function testNormalizeIriOnlyResourceCollection(): void $normalizer->setNormalizer($delegateNormalizerProphecy->reveal()); $actual = $normalizer->normalize($data, CollectionNormalizer::FORMAT, [ - 'collection_operation_name' => 'get', + 'operation_name' => 'get', 'iri_only' => true, 'resource_class' => Foo::class, ]); @@ -407,9 +405,9 @@ public function testNormalizeIriOnlyEmbedContextResourceCollection(): void $resourceClassResolverProphecy->getResourceClass($data, Foo::class)->willReturn(Foo::class); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResourceClass(Foo::class)->willReturn('/foos'); - $iriConverterProphecy->getIriFromItem($fooOne)->willReturn('/foos/1'); - $iriConverterProphecy->getIriFromItem($fooThree)->willReturn('/foos/3'); + $iriConverterProphecy->getIriFromResource(Foo::class, UrlGeneratorInterface::ABS_PATH, Argument::any(), Argument::any())->willReturn('/foos'); + $iriConverterProphecy->getIriFromResource($fooOne)->willReturn('/foos/1'); + $iriConverterProphecy->getIriFromResource($fooThree)->willReturn('/foos/3'); $delegateNormalizerProphecy = $this->prophesize(NormalizerInterface::class); @@ -417,7 +415,7 @@ public function testNormalizeIriOnlyEmbedContextResourceCollection(): void $normalizer->setNormalizer($delegateNormalizerProphecy->reveal()); $actual = $normalizer->normalize($data, CollectionNormalizer::FORMAT, [ - 'collection_operation_name' => 'get', + 'operation_name' => 'get', 'iri_only' => true, 'jsonld_embed_context' => true, 'resource_class' => Foo::class, diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index 784c7a946bf..9ee79fc1ba8 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -15,13 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Hydra\Serializer\DocumentationNormalizer; use ApiPlatform\Metadata\ApiProperty; @@ -45,22 +38,11 @@ /** * @author Amrouche Hamza - * @group legacy */ class DocumentationNormalizerTest extends TestCase { use ProphecyTrait; - public function testNormalizeLegacyResourceMetadata(): void - { - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummy')); - - $this->doTestNormalize(null, $resourceMetadataFactoryProphecy->reveal()); - } - public function testNormalize(): void { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); @@ -77,25 +59,10 @@ public function testNormalize(): void (new ApiResource())->withShortName('relatedDummy')->withOperations(new Operations(['get' => (new Get())->withShortName('relatedDummy')])), ])); - $this->doTestNormalize(null, $resourceMetadataFactoryProphecy->reveal()); - } - - public function testLegacyNormalize(): void - { - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod('dummy', 'get')->shouldBeCalled()->willReturn('GET'); - $operationMethodResolverProphecy->getItemOperationMethod('dummy', 'put')->shouldBeCalled()->willReturn('PUT'); - $operationMethodResolverProphecy->getCollectionOperationMethod('dummy', 'get')->shouldBeCalled()->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod('dummy', 'post')->shouldBeCalled()->willReturn('POST'); - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummy')); - - $this->doTestNormalize($operationMethodResolverProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); + $this->doTestNormalize($resourceMetadataFactoryProphecy->reveal()); } - private function doTestNormalize(OperationMethodResolverInterface $operationMethodResolver = null, $resourceMetadataFactory = null): void + private function doTestNormalize($resourceMetadataFactory = null): void { $title = 'Test Api'; $desc = 'test ApiGerard'; @@ -105,54 +72,20 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create('dummy', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['name', 'description', 'nameConverted', 'relatedDummy', 'iri'])); - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( - (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( - (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withAttributes(['jsonld_context' => ['@type' => '@id']]) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( - (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy')))->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new PropertyMetadata())->withIri('https://schema.org/Dummy')); - } else { - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@type' => '@id']) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy'))])->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withIris(['https://schema.org/Dummy'])); - } + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@type' => '@id']) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy'))])->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); + $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withIris(['https://schema.org/Dummy'])); $subresourceOperationFactoryProphecy = null; - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $subresourceMetadata = new SubresourceMetadata('relatedDummy', false); - $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy')->shouldBeCalled()->willReturn((new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy')))->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withSubresource($subresourceMetadata)); - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn([ - 'api_dummies_subresource_get_related_dummy' => [ - 'property' => 'relatedDummy', - 'collection' => false, - 'resource_class' => 'relatedDummy', - 'shortNames' => ['relatedDummy'], - 'identifiers' => [ - 'id' => ['dummy', 'id', true], - ], - 'route_name' => 'api_dummies_subresource_get_related_dummy', - 'path' => '/dummies/{id}/related_dummy.{_format}', - ], - ]); - } - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(true); @@ -167,9 +100,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - $operationMethodResolver, $urlGenerator->reveal(), - $subresourceOperationFactoryProphecy ? $subresourceOperationFactoryProphecy->reveal() : null, new CustomConverter() ); @@ -427,15 +358,6 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth 'hydra:entrypoint' => '/', ]; - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $expected['hydra:supportedClass'][1]['hydra:supportedProperty'][0]['hydra:property']['hydra:supportedOperation'][] = [ - '@type' => ['hydra:Operation', 'schema:FindAction'], - 'hydra:method' => 'GET', - 'hydra:title' => 'Retrieves a relatedDummy resource.', - 'rdfs:label' => 'Retrieves a relatedDummy resource.', - 'returns' => '#relatedDummy', - ]; - } $this->assertEquals($expected, $documentationNormalizer->normalize($documentation)); $this->assertTrue($documentationNormalizer->supportsNormalization($documentation, 'jsonld')); $this->assertFalse($documentationNormalizer->supportsNormalization($documentation, 'hal')); @@ -453,23 +375,18 @@ public function testNormalizeInputOutputClass() $propertyNameCollectionFactoryProphecy->create('inputClass', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['a', 'b'])); $propertyNameCollectionFactoryProphecy->create('outputClass', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['c', 'd'])); - $dummyMetadata = new ResourceMetadata( - 'dummy', - 'dummy', - '#dummy', - [ - 'get' => ['method' => 'GET'], - 'put' => ['method' => 'PUT', 'input' => ['class' => null]], - ], - [ - 'get' => ['method' => 'GET'], - 'post' => ['method' => 'POST', 'output' => ['class' => null]], - ], - [ - 'input' => ['class' => 'inputClass'], - 'output' => ['class' => 'outputClass'], - ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $dummyMetadata = new ResourceMetadataCollection('dummy', [ + (new ApiResource()) + ->withShortName('dummy') + ->withDescription('dummy') + ->withOperations(new Operations([ + 'get_collection' => (new GetCollection())->withShortName('dummy')->withInput(['class' => 'inputClass'])->withOutput(['class' => 'outputClass']), + 'post' => (new Post())->withShortName('dummy')->withInput(['class' => 'inputClass'])->withOutput(['class' => null]), + 'get' => (new Get())->withShortName('dummy')->withInput(['class' => 'inputClass'])->withOutput(['class' => 'outputClass']), + 'put' => (new Put())->withShortName('dummy')->withInput(['class' => null])->withOutput(['class' => 'outputClass']), + ])), + ]); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -491,7 +408,6 @@ public function testNormalizeInputOutputClass() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - null, $urlGenerator->reveal() ); diff --git a/tests/Hydra/Serializer/EntrypointNormalizerTest.php b/tests/Hydra/Serializer/EntrypointNormalizerTest.php index 69ef89c04ec..5f9ff6ed083 100644 --- a/tests/Hydra/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hydra/Serializer/EntrypointNormalizerTest.php @@ -14,10 +14,8 @@ namespace ApiPlatform\Tests\Hydra\Serializer; use ApiPlatform\Api\Entrypoint; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Hydra\Serializer\EntrypointNormalizer; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; @@ -29,6 +27,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\FooDummy; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; +use Prophecy\Argument; /** * @author Kévin Dunglas @@ -60,13 +59,21 @@ public function testNormalizeWithResourceMetadata() $collection = new ResourceNameCollection([FooDummy::class, Dummy::class]); $entrypoint = new Entrypoint($collection); - $factoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, ['get']))->shouldBeCalled(); - $factoryProphecy->create(FooDummy::class)->willReturn(new ResourceMetadata('FooDummy', null, null, null, ['get']))->shouldBeCalled(); + $factoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $factoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource())->withShortName('Dummy')->withUriTemplate('/api/dummies')->withOperations(new Operations([ + 'get' => new GetCollection(), + ])), + ]))->shouldBeCalled(); + $factoryProphecy->create(FooDummy::class)->willReturn(new ResourceMetadataCollection(FooDummy::class, [ + (new ApiResource())->withShortName('FooDummy')->withUriTemplate('/api/foo_dummies')->withOperations(new Operations([ + 'get' => new GetCollection(), + ])), + ]))->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResourceClass(Dummy::class)->willReturn('/api/dummies')->shouldBeCalled(); - $iriConverterProphecy->getIriFromResourceClass(FooDummy::class)->willReturn('/api/foo_dummies')->shouldBeCalled(); + $iriConverterProphecy->getIriFromResource(Dummy::class, UrlGeneratorInterface::ABS_PATH, Argument::any())->willReturn('/api/dummies')->shouldBeCalled(); + $iriConverterProphecy->getIriFromResource(FooDummy::class, UrlGeneratorInterface::ABS_PATH, Argument::any())->willReturn('/api/foo_dummies')->shouldBeCalled(); $urlGeneratorProphecy = $this->prophesize(UrlGeneratorInterface::class); $urlGeneratorProphecy->generate('api_entrypoint')->willReturn('/api')->shouldBeCalled(); @@ -103,8 +110,8 @@ public function testNormalizeWithResourceCollection() )->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResourceClass(Dummy::class)->willReturn('/api/dummies')->shouldBeCalled(); - $iriConverterProphecy->getIriFromResourceClass(FooDummy::class)->willReturn('/api/foo_dummies')->shouldBeCalled(); + $iriConverterProphecy->getIriFromResource(Dummy::class, UrlGeneratorInterface::ABS_PATH, Argument::any())->willReturn('/api/dummies')->shouldBeCalled(); + $iriConverterProphecy->getIriFromResource(FooDummy::class, UrlGeneratorInterface::ABS_PATH, Argument::any())->willReturn('/api/foo_dummies')->shouldBeCalled(); $urlGeneratorProphecy = $this->prophesize(UrlGeneratorInterface::class); $urlGeneratorProphecy->generate('api_entrypoint')->willReturn('/api')->shouldBeCalled(); diff --git a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php index 0501963ca1c..774aea9b632 100644 --- a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php +++ b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php @@ -13,9 +13,12 @@ namespace ApiPlatform\Tests\Hydra\Serializer; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Hydra\Serializer\PartialCollectionViewNormalizer; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SoMany; @@ -38,7 +41,7 @@ public function testNormalizeDoesNotChangeSubLevel() { $decoratedNormalizerProphecy = $this->prophesize(NormalizerInterface::class); $decoratedNormalizerProphecy->normalize(Argument::any(), null, ['jsonld_sub_level' => true])->willReturn(['foo' => 'bar'])->shouldBeCalled(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $normalizer = new PartialCollectionViewNormalizer($decoratedNormalizerProphecy->reveal(), 'page', 'pagination', $resourceMetadataFactory->reveal()); $this->assertEquals(['foo' => 'bar'], $normalizer->normalize(new \stdClass(), null, ['jsonld_sub_level' => true])); @@ -48,7 +51,7 @@ public function testNormalizeDoesNotChangeWhenNoFilterNorPagination() { $decoratedNormalizerProphecy = $this->prophesize(NormalizerInterface::class); $decoratedNormalizerProphecy->normalize(Argument::any(), null, Argument::type('array'))->willReturn(['foo' => 'bar'])->shouldBeCalled(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $normalizer = new PartialCollectionViewNormalizer($decoratedNormalizerProphecy->reveal(), 'page', 'pagination', $resourceMetadataFactory->reveal()); $this->assertEquals(['foo' => 'bar'], $normalizer->normalize(new \stdClass(), null, ['request_uri' => '/?page=1&pagination=1'])); @@ -141,15 +144,19 @@ private function normalizePaginator(bool $partial = false, bool $cursor = false) $paginatorProphecy->current()->willReturn($firstSoMany, $lastSoMany)->shouldBeCalledTimes(2); $paginatorProphecy->next()->shouldBeCalledTimes(2); - $soManyMetadata = new ResourceMetadata(null, null, null, null, ['get' => ['pagination_via_cursor' => [['field' => 'id', 'direction' => 'desc']]]]); + $soManyMetadata = new ResourceMetadataCollection(SoMany::class, [ + (new ApiResource())->withShortName('SoMany')->withOperations(new Operations([ + 'get' => (new GetCollection())->withPaginationViaCursor([['field' => 'id', 'direction' => 'desc']]), + ])), + ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create(SoMany::class)->willReturn($soManyMetadata)->shouldBeCalledOnce(); } $normalizer = new PartialCollectionViewNormalizer($decoratedNormalizerProphecy->reveal(), '_page', 'pagination', $resourceMetadataFactoryProphecy ? $resourceMetadataFactoryProphecy->reveal() : null); - return $normalizer->normalize($paginatorProphecy->reveal(), null, ['resource_class' => SoMany::class, 'collection_operation_name' => 'get']); + return $normalizer->normalize($paginatorProphecy->reveal(), null, ['resource_class' => SoMany::class, 'operation_name' => 'get']); } public function testSupportsNormalization() @@ -158,7 +165,7 @@ public function testSupportsNormalization() $decoratedNormalizerProphecy->willImplement(CacheableSupportsMethodInterface::class); $decoratedNormalizerProphecy->supportsNormalization(Argument::any(), null)->willReturn(true)->shouldBeCalled(); $decoratedNormalizerProphecy->hasCacheableSupportsMethod()->willReturn(true)->shouldBeCalled(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $normalizer = new PartialCollectionViewNormalizer($decoratedNormalizerProphecy->reveal(), 'page', 'pagination', $resourceMetadataFactory->reveal()); $this->assertTrue($normalizer->supportsNormalization(new \stdClass())); @@ -172,7 +179,7 @@ public function testSetNormalizer() $decoratedNormalizerProphecy = $this->prophesize(NormalizerInterface::class); $decoratedNormalizerProphecy->willImplement(NormalizerAwareInterface::class); $decoratedNormalizerProphecy->setNormalizer(Argument::type(NormalizerInterface::class))->shouldBeCalled(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $normalizer = new PartialCollectionViewNormalizer($decoratedNormalizerProphecy->reveal(), 'page', 'pagination', $resourceMetadataFactory->reveal()); $normalizer->setNormalizer($injectedNormalizer); From 817da50294c36217ad52dbfc8880add1164fd772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Deuchnord?= Date: Mon, 16 May 2022 11:00:01 +0200 Subject: [PATCH 14/56] tests: fix OpenApiFactory (#39) --- tests/OpenApi/Factory/OpenApiFactoryTest.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/OpenApi/Factory/OpenApiFactoryTest.php b/tests/OpenApi/Factory/OpenApiFactoryTest.php index 1468c7ec395..899aad6b1bd 100644 --- a/tests/OpenApi/Factory/OpenApiFactoryTest.php +++ b/tests/OpenApi/Factory/OpenApiFactoryTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\OpenApi\Factory; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; @@ -39,8 +38,6 @@ use ApiPlatform\OpenApi\Model\ExternalDocumentation; use ApiPlatform\OpenApi\OpenApi; use ApiPlatform\OpenApi\Options; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; use ApiPlatform\State\Pagination\PaginationOptions; use ApiPlatform\Tests\Fixtures\DummyFilter; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; @@ -180,8 +177,6 @@ public function testInvoke(): void (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('This is an enum.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withOpenapiContext(['type' => 'string', 'enum' => ['one', 'two'], 'example' => 'one']) ); - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); $filters = [ 'f1' => new DummyFilter(['name' => [ @@ -238,7 +233,6 @@ public function testInvoke(): void $propertyMetadataFactory, $schemaFactory, $typeFactory, - $operationPathResolver, $filterLocatorProphecy->reveal(), [], new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ @@ -259,6 +253,7 @@ public function testInvoke(): void 'type' => 'object', 'description' => 'This is a dummy', 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'], + 'deprecated' => false, 'properties' => [ 'id' => new \ArrayObject([ 'type' => 'integer', From 628ffb9e6f6c18318029edb656df2bda63a30093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Deuchnord?= Date: Mon, 16 May 2022 11:00:12 +0200 Subject: [PATCH 15/56] test: OpenApi (#40) --- .../Serializer/CollectionNormalizer.php | 14 ++--- .../Serializer/CollectionNormalizerTest.php | 59 +++++++++++++++---- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/JsonApi/Serializer/CollectionNormalizer.php b/src/JsonApi/Serializer/CollectionNormalizer.php index 34a727befd2..f11535b0fe1 100644 --- a/src/JsonApi/Serializer/CollectionNormalizer.php +++ b/src/JsonApi/Serializer/CollectionNormalizer.php @@ -14,7 +14,7 @@ namespace ApiPlatform\JsonApi\Serializer; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Serializer\AbstractCollectionNormalizer; use ApiPlatform\Util\IriHelper; @@ -31,7 +31,7 @@ final class CollectionNormalizer extends AbstractCollectionNormalizer { public const FORMAT = 'jsonapi'; - public function __construct(ResourceClassResolverInterface $resourceClassResolver, string $pageParameterName, $resourceMetadataFactory) + public function __construct(ResourceClassResolverInterface $resourceClassResolver, string $pageParameterName, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { parent::__construct($resourceClassResolver, $pageParameterName, $resourceMetadataFactory); } @@ -44,14 +44,10 @@ protected function getPaginationData($object, array $context = []): array [$paginator, $paginated, $currentPage, $itemsPerPage, $lastPage, $pageTotalItems, $totalItems] = $this->getPaginationConfig($object, $context); $parsed = IriHelper::parseIri($context['uri'] ?? '/', $this->pageParameterName); - /** @var ResourceMetadata|ResourceMetadataCollection */ + /** @var ResourceMetadataCollection */ $metadata = $this->resourceMetadataFactory->create($context['resource_class'] ?? ''); - if ($metadata instanceof ResourceMetadataCollection) { - $operation = $metadata->getOperation($context['operation_name'] ?? null); - $urlGenerationStrategy = $operation->getUrlGenerationStrategy(); - } else { - $urlGenerationStrategy = $metadata->getAttribute('url_generation_strategy'); - } + $operation = $metadata->getOperation($context['operation_name'] ?? null); + $urlGenerationStrategy = $operation->getUrlGenerationStrategy(); $data = [ 'links' => [ diff --git a/tests/JsonApi/Serializer/CollectionNormalizerTest.php b/tests/JsonApi/Serializer/CollectionNormalizerTest.php index 37348e9fd54..b1c7a836807 100644 --- a/tests/JsonApi/Serializer/CollectionNormalizerTest.php +++ b/tests/JsonApi/Serializer/CollectionNormalizerTest.php @@ -14,9 +14,12 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\JsonApi\Serializer\CollectionNormalizer; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\ProphecyTrait; @@ -35,7 +38,7 @@ class CollectionNormalizerTest extends TestCase public function testSupportsNormalize() { $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $normalizer = new CollectionNormalizer($resourceClassResolverProphecy->reveal(), 'page', $resourceMetadataFactoryProphecy->reveal()); @@ -63,12 +66,17 @@ public function testNormalizePaginator() $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($paginator, 'Foo')->willReturn('Foo'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource()) + ->withShortName('Foo') + ->withOperations(new Operations(['get' => (new GetCollection())])) + ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos?page=3', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos?page=3', 'api_sub_level' => true, 'resource_class' => 'Foo', @@ -113,6 +121,7 @@ public function testNormalizePaginator() $this->assertEquals($expected, $normalizer->normalize($paginator, CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos?page=3', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos?page=3', 'resource_class' => 'Foo', ])); @@ -134,12 +143,17 @@ public function testNormalizePartialPaginator() $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($paginator, 'Foo')->willReturn('Foo'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource()) + ->withShortName('Foo') + ->withOperations(new Operations(['get' => (new GetCollection())])) + ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos?page=3', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos?page=3', 'api_sub_level' => true, 'resource_class' => 'Foo', @@ -181,6 +195,7 @@ public function testNormalizePartialPaginator() $this->assertEquals($expected, $normalizer->normalize($paginator, CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos?page=3', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos?page=3', 'resource_class' => 'Foo', ])); @@ -192,11 +207,16 @@ public function testNormalizeArray() $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($data, 'Foo')->willReturn('Foo'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource()) + ->withShortName('Foo') + ->withOperations(new Operations(['get' => (new GetCollection())])) + ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos', 'api_sub_level' => true, 'resource_class' => 'Foo', @@ -231,6 +251,7 @@ public function testNormalizeArray() $this->assertEquals($expected, $normalizer->normalize($data, CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos', 'resource_class' => 'Foo', ])); @@ -243,12 +264,17 @@ public function testNormalizeIncludedData() $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($data, 'Foo')->willReturn('Foo'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource()) + ->withShortName('Foo') + ->withOperations(new Operations(['get' => (new GetCollection())])) + ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos', 'api_sub_level' => true, 'resource_class' => 'Foo', @@ -303,6 +329,7 @@ public function testNormalizeIncludedData() $this->assertEquals($expected, $normalizer->normalize($data, CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos', 'resource_class' => 'Foo', ])); @@ -318,12 +345,17 @@ public function testNormalizeWithoutDataKey() $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($data, 'Foo')->willReturn('Foo'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource()) + ->withShortName('Foo') + ->withOperations(new Operations(['get' => (new GetCollection())])) + ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos', 'api_sub_level' => true, 'resource_class' => 'Foo', @@ -334,6 +366,7 @@ public function testNormalizeWithoutDataKey() $normalizer->normalize($data, CollectionNormalizer::FORMAT, [ 'request_uri' => '/foos', + 'operation_name' => 'get', 'uri' => 'http://example.com/foos', 'resource_class' => 'Foo', ]); From d2055716e601bb09603c2ca7b2a67e61d7a03515 Mon Sep 17 00:00:00 2001 From: Vincent Date: Mon, 16 May 2022 11:00:35 +0200 Subject: [PATCH 16/56] test: fix Hal/Serializer tests (#38) * test: fix Hal/Serializer tests * Update src/Hal/Serializer/EntrypointNormalizer.php Co-authored-by: Antoine Bluchet * Apply suggestions from code review c * fix: review Co-authored-by: Antoine Bluchet --- src/Hal/Serializer/CollectionNormalizer.php | 11 +---- src/Hal/Serializer/EntrypointNormalizer.php | 37 ++--------------- src/Hal/Serializer/ObjectNormalizer.php | 9 +---- .../AbstractCollectionNormalizer.php | 6 +-- src/Serializer/AbstractItemNormalizer.php | 10 +---- .../Serializer/CollectionNormalizerTest.php | 23 +++++++---- .../Serializer/EntrypointNormalizerTest.php | 24 +++++++---- tests/Hal/Serializer/ItemNormalizerTest.php | 40 +++++-------------- 8 files changed, 54 insertions(+), 106 deletions(-) diff --git a/src/Hal/Serializer/CollectionNormalizer.php b/src/Hal/Serializer/CollectionNormalizer.php index b1688595dc6..f2081c0d746 100644 --- a/src/Hal/Serializer/CollectionNormalizer.php +++ b/src/Hal/Serializer/CollectionNormalizer.php @@ -14,8 +14,6 @@ namespace ApiPlatform\Hal\Serializer; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Serializer\AbstractCollectionNormalizer; use ApiPlatform\Util\IriHelper; use Symfony\Component\Serializer\Exception\UnexpectedValueException; @@ -43,14 +41,9 @@ protected function getPaginationData($object, array $context = []): array [$paginator, $paginated, $currentPage, $itemsPerPage, $lastPage, $pageTotalItems, $totalItems] = $this->getPaginationConfig($object, $context); $parsed = IriHelper::parseIri($context['uri'] ?? '/', $this->pageParameterName); - /** @var ResourceMetadata|ResourceMetadataCollection */ $metadata = $this->resourceMetadataFactory->create($context['resource_class'] ?? ''); - if ($metadata instanceof ResourceMetadataCollection) { - $operation = $metadata->getOperation($context['operation_name'] ?? null); - $urlGenerationStrategy = $operation->getUrlGenerationStrategy(); - } else { - $urlGenerationStrategy = $metadata->getAttribute('url_generation_strategy'); - } + $operation = $metadata->getOperation($context['operation_name'] ?? null); + $urlGenerationStrategy = $operation->getUrlGenerationStrategy(); $data = [ '_links' => [ diff --git a/src/Hal/Serializer/EntrypointNormalizer.php b/src/Hal/Serializer/EntrypointNormalizer.php index 391516df21a..5c2f48ae24a 100644 --- a/src/Hal/Serializer/EntrypointNormalizer.php +++ b/src/Hal/Serializer/EntrypointNormalizer.php @@ -16,14 +16,10 @@ use ApiPlatform\Api\Entrypoint; use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -36,27 +32,15 @@ final class EntrypointNormalizer implements NormalizerInterface, CacheableSuppor { public const FORMAT = 'jsonhal'; - /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface - */ private $resourceMetadataFactory; - /** @var LegacyIriConverterInterface|IriConverterInterface */ private $iriConverter; private $urlGenerator; - public function __construct($resourceMetadataFactory, $iriConverter, UrlGeneratorInterface $urlGenerator) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, IriConverterInterface $iriConverter, UrlGeneratorInterface $urlGenerator) { $this->resourceMetadataFactory = $resourceMetadataFactory; $this->iriConverter = $iriConverter; $this->urlGenerator = $urlGenerator; - - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -67,32 +51,19 @@ public function normalize($object, $format = null, array $context = []): array $entrypoint = ['_links' => ['self' => ['href' => $this->urlGenerator->generate('api_entrypoint')]]]; foreach ($object->getResourceNameCollection() as $resourceClass) { - /** @var ResourceMetadata|ResourceMetadataCollection */ $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if ($resourceMetadata instanceof ResourceMetadata) { - if (!$resourceMetadata->getCollectionOperations()) { - continue; - } - - try { - $entrypoint['_links'][lcfirst($resourceMetadata->getShortName())]['href'] = $this->iriConverter->getIriFromResourceClass($resourceClass); - } catch (InvalidArgumentException $ex) { - // Ignore resources without GET operations - } - } - foreach ($resourceMetadata as $resource) { - foreach ($resource->getOperations() as $operationName => $operation) { + foreach ($resource->getOperations() as $operation) { /** @var Operation $operation */ if (!$operation instanceof CollectionOperationInterface) { continue; } try { - $href = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromResourceClass($resourceClass) : $this->iriConverter->getIriFromResource($operation->getClass(), UrlGeneratorInterface::ABS_PATH, $operation); + $href = $this->iriConverter->getIriFromResource($operation->getClass(), UrlGeneratorInterface::ABS_PATH, $operation); $entrypoint['_links'][lcfirst($operation->getShortName())]['href'] = $href; - } catch (InvalidArgumentException $ex) { + } catch (InvalidArgumentException) { // Ignore resources without GET operations } } diff --git a/src/Hal/Serializer/ObjectNormalizer.php b/src/Hal/Serializer/ObjectNormalizer.php index a05c3561169..296aed73b62 100644 --- a/src/Hal/Serializer/ObjectNormalizer.php +++ b/src/Hal/Serializer/ObjectNormalizer.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Hal\Serializer; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; @@ -31,14 +30,10 @@ final class ObjectNormalizer implements NormalizerInterface, DenormalizerInterfa private $decorated; private $iriConverter; - public function __construct(NormalizerInterface $decorated, $iriConverter) + public function __construct(NormalizerInterface $decorated, IriConverterInterface $iriConverter) { $this->decorated = $decorated; $this->iriConverter = $iriConverter; - - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } } /** @@ -81,7 +76,7 @@ public function normalize($object, $format = null, array $context = []) $metadata = [ '_links' => [ 'self' => [ - 'href' => $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($originalResource) : $this->iriConverter->getIriFromResource($originalResource), + 'href' => $this->iriConverter->getIriFromResource($originalResource), ], ], ]; diff --git a/src/Serializer/AbstractCollectionNormalizer.php b/src/Serializer/AbstractCollectionNormalizer.php index d4aa8f41042..1fd727d7b0c 100644 --- a/src/Serializer/AbstractCollectionNormalizer.php +++ b/src/Serializer/AbstractCollectionNormalizer.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Serializer; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; @@ -43,12 +42,9 @@ abstract class AbstractCollectionNormalizer implements NormalizerInterface, Norm protected $resourceClassResolver; protected $pageParameterName; - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface - */ protected $resourceMetadataFactory; - public function __construct(ResourceClassResolverInterface $resourceClassResolver, string $pageParameterName, $resourceMetadataFactory = null) + public function __construct(ResourceClassResolverInterface $resourceClassResolver, string $pageParameterName, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null) { $this->resourceClassResolver = $resourceClassResolver; $this->pageParameterName = $pageParameterName; diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index e28f997e269..6cac7a383a1 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -59,22 +59,14 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer * @var PropertyNameCollectionFactoryInterface */ protected $propertyNameCollectionFactory; - /** - * @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface - */ protected $propertyMetadataFactory; - /** - * @var LegacyIriConverterInterface|IriConverterInterface - */ protected $iriConverter; protected $resourceClassResolver; protected $resourceAccessChecker; protected $propertyAccessor; - protected $allowPlainIdentifiers; - protected $dataTransformers = []; protected $localCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { if (!isset($defaultContext['circular_reference_handler'])) { $defaultContext['circular_reference_handler'] = function ($object) { diff --git a/tests/Hal/Serializer/CollectionNormalizerTest.php b/tests/Hal/Serializer/CollectionNormalizerTest.php index b1bc4d57954..a5bf0749496 100644 --- a/tests/Hal/Serializer/CollectionNormalizerTest.php +++ b/tests/Hal/Serializer/CollectionNormalizerTest.php @@ -14,9 +14,12 @@ namespace ApiPlatform\Tests\Hal\Serializer; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Hal\Serializer\CollectionNormalizer; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; use ApiPlatform\Tests\ProphecyTrait; @@ -34,7 +37,7 @@ class CollectionNormalizerTest extends TestCase public function testSupportsNormalize() { $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $normalizer = new CollectionNormalizer($resourceClassResolverProphecy->reveal(), 'page', $resourceMetadataFactoryProphecy->reveal()); $this->assertTrue($normalizer->supportsNormalization([], CollectionNormalizer::FORMAT)); @@ -48,7 +51,7 @@ public function testNormalizeApiSubLevel() { $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass()->shouldNotBeCalled(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('bar', null, ['api_sub_level' => true])->willReturn(22); @@ -142,13 +145,18 @@ private function normalizePaginator($partial = false) $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($paginatorProphecy, 'Foo')->willReturn('Foo'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource())->withShortName('Foo')->withOperations(new Operations([ + 'bar' => (new GetCollection())->withShortName('Foo'), + ])), + ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ - 'api_sub_level' => true, 'resource_class' => 'Foo', + 'operation_name' => 'bar', + 'api_sub_level' => true, ])->willReturn(['_links' => ['self' => '/me'], 'name' => 'Kévin']); $normalizer = new CollectionNormalizer($resourceClassResolverProphecy->reveal(), 'page', $resourceMetadataFactoryProphecy->reveal()); @@ -156,6 +164,7 @@ private function normalizePaginator($partial = false) return $normalizer->normalize($paginatorProphecy->reveal(), CollectionNormalizer::FORMAT, [ 'resource_class' => 'Foo', + 'operation_name' => 'bar', ]); } } diff --git a/tests/Hal/Serializer/EntrypointNormalizerTest.php b/tests/Hal/Serializer/EntrypointNormalizerTest.php index 788ec6fea2a..c4a3bb23ead 100644 --- a/tests/Hal/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hal/Serializer/EntrypointNormalizerTest.php @@ -14,11 +14,14 @@ namespace ApiPlatform\Tests\Hal\Serializer; use ApiPlatform\Api\Entrypoint; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Hal\Serializer\EntrypointNormalizer; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; @@ -37,7 +40,7 @@ public function testSupportNormalization() $collection = new ResourceNameCollection(); $entrypoint = new Entrypoint($collection); - $factoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $factoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $urlGeneratorProphecy = $this->prophesize(UrlGeneratorInterface::class); @@ -53,11 +56,18 @@ public function testNormalize() { $collection = new ResourceNameCollection([Dummy::class]); $entrypoint = new Entrypoint($collection); - $factoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, ['get']))->shouldBeCalled(); + $factoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $operation = (new GetCollection())->withShortName('Dummy')->withClass(Dummy::class); + $factoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection('Dummy', [ + (new ApiResource('Dummy')) + ->withShortName('Dummy') + ->withOperations(new Operations([ + 'get' => $operation, + ])), + ]))->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResourceClass(Dummy::class)->willReturn('/api/dummies')->shouldBeCalled(); + $iriConverterProphecy->getIriFromResource(Dummy::class, UrlGeneratorInterface::ABS_PATH, $operation)->willReturn('/api/dummies')->shouldBeCalled(); $urlGeneratorProphecy = $this->prophesize(UrlGeneratorInterface::class); $urlGeneratorProphecy->generate('api_entrypoint')->willReturn('/api')->shouldBeCalled(); diff --git a/tests/Hal/Serializer/ItemNormalizerTest.php b/tests/Hal/Serializer/ItemNormalizerTest.php index 00e1740a226..c5e98d48f83 100644 --- a/tests/Hal/Serializer/ItemNormalizerTest.php +++ b/tests/Hal/Serializer/ItemNormalizerTest.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Tests\Hal\Serializer; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Hal\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; @@ -24,7 +24,6 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MaxDepthDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\ProphecyTrait; -use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; @@ -126,8 +125,8 @@ public function testNormalize() ); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); - $iriConverterProphecy->getIriFromItem($relatedDummy)->willReturn('/related-dummies/2'); + $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($relatedDummy)->willReturn('/related-dummies/2'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class); @@ -150,13 +149,7 @@ public function testNormalize() $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), null, - $nameConverter->reveal(), - null, - null, - false, - [], - [], - null + $nameConverter->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -194,8 +187,8 @@ public function testNormalizeWithoutCache() ); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); - $iriConverterProphecy->getIriFromItem($relatedDummy)->willReturn('/related-dummies/2'); + $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($relatedDummy)->willReturn('/related-dummies/2'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class); @@ -218,13 +211,7 @@ public function testNormalizeWithoutCache() $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), null, - $nameConverter->reveal(), - null, - null, - false, - [], - [], - null + $nameConverter->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -280,9 +267,9 @@ public function testMaxDepth() ); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($level1)->willReturn('/max_depth_dummies/1'); - $iriConverterProphecy->getIriFromItem($level2)->willReturn('/max_depth_dummies/2'); - $iriConverterProphecy->getIriFromItem($level3)->willReturn('/max_depth_dummies/3'); + $iriConverterProphecy->getIriFromResource($level1)->willReturn('/max_depth_dummies/1'); + $iriConverterProphecy->getIriFromResource($level2)->willReturn('/max_depth_dummies/2'); + $iriConverterProphecy->getIriFromResource($level3)->willReturn('/max_depth_dummies/3'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($level1, null)->willReturn(MaxDepthDummy::class); @@ -299,12 +286,7 @@ public function testMaxDepth() $resourceClassResolverProphecy->reveal(), null, null, - $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())), - null, - false, - [], - [], - null + new ClassMetadataFactory(new AnnotationLoader()) ); $serializer = new Serializer([$normalizer]); $normalizer->setSerializer($serializer); From 2467d472cf481a48357d20a3d66b69496f079885 Mon Sep 17 00:00:00 2001 From: soyuka Date: Mon, 16 May 2022 11:37:03 +0200 Subject: [PATCH 17/56] refactor: api loader --- src/Symfony/Routing/ApiLoader.php | 39 +++++-------------------- tests/Symfony/Routing/ApiLoaderTest.php | 21 ++++--------- 2 files changed, 13 insertions(+), 47 deletions(-) diff --git a/src/Symfony/Routing/ApiLoader.php b/src/Symfony/Routing/ApiLoader.php index ed6fb74d821..343761cb419 100644 --- a/src/Symfony/Routing/ApiLoader.php +++ b/src/Symfony/Routing/ApiLoader.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Symfony\Routing; +use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -33,10 +34,6 @@ */ final class ApiLoader extends Loader { - /** - * @deprecated since version 2.1, to be removed in 3.0. Use {@see RouteNameGenerator::ROUTE_NAME_PREFIX} instead. - */ - public const ROUTE_NAME_PREFIX = 'api_'; public const DEFAULT_ACTION_PATTERN = 'api_platform.action.'; private $fileLoader; @@ -50,7 +47,6 @@ final class ApiLoader extends Loader private $graphQlPlaygroundEnabled; private $entrypointEnabled; private $docsEnabled; - private $identifiersExtractor; public function __construct(KernelInterface $kernel, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ContainerInterface $container, array $formats, array $resourceClassDirectories = [], bool $graphqlEnabled = false, bool $entrypointEnabled = true, bool $docsEnabled = true, bool $graphiQlEnabled = false, bool $graphQlPlaygroundEnabled = false) { @@ -87,31 +83,6 @@ public function load($data, $type = null): RouteCollection continue; } - // $legacyDefaults = []; - - // if ($operation->getExtraProperties()['is_legacy_subresource'] ?? false) { - // $legacyDefaults['_api_subresource_operation_name'] = $operationName; - // $legacyDefaults['_api_subresource_context'] = [ - // 'property' => $operation->getExtraProperties()['legacy_subresource_property'], - // 'identifiers' => $operation->getExtraProperties()['legacy_subresource_identifiers'], - // 'collection' => $operation instanceof CollectionOperationInterface, - // 'operationId' => $operation->getExtraProperties()['legacy_subresource_operation_name'] ?? null, - // ]; - // $legacyDefaults['_api_identifiers'] = $operation->getExtraProperties()['legacy_subresource_identifiers']; - // } elseif ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) { - // $legacyDefaults[sprintf('_api_%s_operation_name', $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM)] = $operationName; - // $legacyDefaults['_api_identifiers'] = []; - // // Legacy identifiers - // $hasCompositeIdentifier = false; - // foreach ($operation->getUriVariables() ?? [] as $parameterName => $identifiedBy) { - // $hasCompositeIdentifier = $identifiedBy->getCompositeIdentifier(); - // foreach ($identifiedBy->getIdentifiers() ?? [] as $identifier) { - // $legacyDefaults['_api_identifiers'][] = $identifier; - // } - // } - // $legacyDefaults['_api_has_composite_identifier'] = $hasCompositeIdentifier; - // } - $path = ($operation->getRoutePrefix() ?? '').$operation->getUriTemplate(); foreach ($operation->getUriVariables() ?? [] as $parameterName => $link) { if (!$expandedValue = $link->getExpandedValue()) { @@ -120,11 +91,17 @@ public function load($data, $type = null): RouteCollection $path = str_replace(sprintf('{%s}', $parameterName), $expandedValue, $path); } + + if ($controller = $operation->getController()) { + if (!$this->container->has($controller)) { + throw new RuntimeException(sprintf('There is no builtin action for the "%s" operation. You need to define the controller yourself.', $operationName)); + } + } $route = new Route( $path, [ - '_controller' => $operation->getController() ?? 'api_platform.action.placeholder', + '_controller' => $controller ?? 'api_platform.action.placeholder', '_format' => null, '_stateless' => $operation->getStateless(), '_api_resource_class' => $resourceClass, diff --git a/tests/Symfony/Routing/ApiLoaderTest.php b/tests/Symfony/Routing/ApiLoaderTest.php index 9bbb901173e..8558a0a7b95 100644 --- a/tests/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Symfony/Routing/ApiLoaderTest.php @@ -14,10 +14,9 @@ namespace ApiPlatform\Tests\Symfony\Routing; use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; @@ -30,8 +29,6 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; use ApiPlatform\Symfony\Routing\ApiLoader; use ApiPlatform\Tests\Fixtures\DummyEntity; use ApiPlatform\Tests\Fixtures\RelatedDummyEntity; @@ -46,9 +43,6 @@ /** * @author Antoine Bluchet * @author Amrouche Hamza - * - * TODO: in 3.0 just remove the IdentifiersExtractor - * @group legacy */ class ApiLoaderTest extends TestCase { @@ -255,6 +249,7 @@ private function getApiLoaderWithResourceMetadataCollection(ResourceMetadataColl $kernelProphecy = $this->prophesize(KernelInterface::class); $kernelProphecy->locateResource(Argument::any())->willReturn($routingConfig); $possibleArguments = [ + 'some.service.name', 'api_platform.action.get_collection', 'api_platform.action.post_collection', 'api_platform.action.get_item', @@ -284,15 +279,9 @@ private function getApiLoaderWithResourceMetadataCollection(ResourceMetadataColl $propertyMetadataFactoryProphecy->create(RelatedDummyEntity::class, 'id')->willReturn(new ApiProperty()); $propertyMetadataFactoryProphecy->create(DummyEntity::class, 'id')->willReturn(new ApiProperty()); - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - $identifiersExtractor = $identifiersExtractorProphecy->reveal(); - - return new ApiLoader($kernelProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactory, $operationPathResolver, $containerProphecy->reveal(), ['jsonld' => ['application/ld+json']], [], null, false, true, true, false, false, $identifiersExtractor); + return new ApiLoader($kernelProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactory, $containerProphecy->reveal(), ['jsonld' => ['application/ld+json']], [], false, true, true, false, false); } private function getRoute(string $path, string $controller, ?bool $stateless, string $resourceClass, array $identifiers, string $operationName, array $extraDefaults = [], array $methods = [], array $requirements = [], array $options = [], string $host = '', array $schemes = [], string $condition = ''): Route From 89c5145d7ca18c85ece10a1f607a74c60170ea5c Mon Sep 17 00:00:00 2001 From: soyuka Date: Mon, 16 May 2022 16:25:32 +0200 Subject: [PATCH 18/56] crap php 7 --- src/Symfony/Routing/ApiLoader.php | 3 +-- tests/JsonApi/Serializer/CollectionNormalizerTest.php | 10 +++++----- tests/Symfony/Routing/ApiLoaderTest.php | 7 +++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Routing/ApiLoader.php b/src/Symfony/Routing/ApiLoader.php index 343761cb419..9e9eb0e6fa3 100644 --- a/src/Symfony/Routing/ApiLoader.php +++ b/src/Symfony/Routing/ApiLoader.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Symfony\Routing; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; @@ -91,7 +90,7 @@ public function load($data, $type = null): RouteCollection $path = str_replace(sprintf('{%s}', $parameterName), $expandedValue, $path); } - + if ($controller = $operation->getController()) { if (!$this->container->has($controller)) { throw new RuntimeException(sprintf('There is no builtin action for the "%s" operation. You need to define the controller yourself.', $operationName)); diff --git a/tests/JsonApi/Serializer/CollectionNormalizerTest.php b/tests/JsonApi/Serializer/CollectionNormalizerTest.php index b1c7a836807..c4d3c26c1d8 100644 --- a/tests/JsonApi/Serializer/CollectionNormalizerTest.php +++ b/tests/JsonApi/Serializer/CollectionNormalizerTest.php @@ -70,7 +70,7 @@ public function testNormalizePaginator() $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ (new ApiResource()) ->withShortName('Foo') - ->withOperations(new Operations(['get' => (new GetCollection())])) + ->withOperations(new Operations(['get' => (new GetCollection())])), ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); @@ -147,7 +147,7 @@ public function testNormalizePartialPaginator() $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ (new ApiResource()) ->withShortName('Foo') - ->withOperations(new Operations(['get' => (new GetCollection())])) + ->withOperations(new Operations(['get' => (new GetCollection())])), ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); @@ -211,7 +211,7 @@ public function testNormalizeArray() $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ (new ApiResource()) ->withShortName('Foo') - ->withOperations(new Operations(['get' => (new GetCollection())])) + ->withOperations(new Operations(['get' => (new GetCollection())])), ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); $itemNormalizer->normalize('foo', CollectionNormalizer::FORMAT, [ @@ -268,7 +268,7 @@ public function testNormalizeIncludedData() $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ (new ApiResource()) ->withShortName('Foo') - ->withOperations(new Operations(['get' => (new GetCollection())])) + ->withOperations(new Operations(['get' => (new GetCollection())])), ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); @@ -349,7 +349,7 @@ public function testNormalizeWithoutDataKey() $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ (new ApiResource()) ->withShortName('Foo') - ->withOperations(new Operations(['get' => (new GetCollection())])) + ->withOperations(new Operations(['get' => (new GetCollection())])), ])); $itemNormalizer = $this->prophesize(NormalizerInterface::class); diff --git a/tests/Symfony/Routing/ApiLoaderTest.php b/tests/Symfony/Routing/ApiLoaderTest.php index 8558a0a7b95..9d723ff579e 100644 --- a/tests/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Symfony/Routing/ApiLoaderTest.php @@ -13,10 +13,6 @@ namespace ApiPlatform\Tests\Symfony\Routing; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; @@ -24,6 +20,9 @@ use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Link; use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Metadata\Put; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; From 732e2de50aceddd3780acb47088800a7974d403f Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Mon, 30 May 2022 17:05:22 +0200 Subject: [PATCH 19/56] chore(doctrine): remove deprecated code (#42) --- phpstan.neon.dist | 5 +- src/Api/FilterLocatorTrait.php | 1 - .../Common/Filter/ExistsFilterTrait.php | 2 +- .../Common/Filter/NumericFilterTrait.php | 2 +- .../Common/Filter/OrderFilterTrait.php | 2 +- .../Common/Filter/SearchFilterTrait.php | 22 +- src/Doctrine/Common/PropertyHelperTrait.php | 37 +- .../Common/State/LinksHandlerTrait.php | 4 +- .../Common/State/PersistProcessor.php | 2 +- src/Doctrine/Common/State/RemoveProcessor.php | 2 +- ...ggregationCollectionExtensionInterface.php | 3 +- .../AggregationItemExtensionInterface.php | 3 +- ...tionResultCollectionExtensionInterface.php | 5 +- ...ggregationResultItemExtensionInterface.php | 5 +- .../Odm/Extension/FilterExtension.php | 38 +- src/Doctrine/Odm/Extension/OrderExtension.php | 67 +- .../Odm/Extension/PaginationExtension.php | 41 +- src/Doctrine/Odm/Filter/AbstractFilter.php | 19 +- src/Doctrine/Odm/Filter/BooleanFilter.php | 3 +- src/Doctrine/Odm/Filter/DateFilter.php | 5 +- src/Doctrine/Odm/Filter/ExistsFilter.php | 15 +- src/Doctrine/Odm/Filter/FilterInterface.php | 3 +- src/Doctrine/Odm/Filter/NumericFilter.php | 3 +- src/Doctrine/Odm/Filter/OrderFilter.php | 9 +- src/Doctrine/Odm/Filter/RangeFilter.php | 5 +- src/Doctrine/Odm/Filter/SearchFilter.php | 20 +- ...trineMongoDbOdmPropertyMetadataFactory.php | 4 +- ...DbOdmResourceCollectionMetadataFactory.php | 10 +- src/Doctrine/Odm/Paginator.php | 43 +- src/Doctrine/Odm/PropertyHelperTrait.php | 2 +- .../Odm/PropertyInfo/DoctrineExtractor.php | 37 +- src/Doctrine/Odm/State/CollectionProvider.php | 21 +- src/Doctrine/Odm/State/ItemProvider.php | 12 +- src/Doctrine/Orm/AbstractPaginator.php | 8 +- ...AwareQueryCollectionExtensionInterface.php | 30 - ...ueryResultCollectionExtensionInterface.php | 34 - ...AwareQueryResultItemExtensionInterface.php | 34 - .../Orm/Extension/EagerLoadingExtension.php | 77 +- .../Extension/FilterEagerLoadingExtension.php | 77 +- .../Orm/Extension/FilterExtension.php | 53 +- src/Doctrine/Orm/Extension/OrderExtension.php | 71 +- .../Orm/Extension/PaginationExtension.php | 349 +----- .../QueryCollectionExtensionInterface.php | 3 +- .../Extension/QueryItemExtensionInterface.php | 3 +- ...ueryResultCollectionExtensionInterface.php | 5 +- .../QueryResultItemExtensionInterface.php | 5 +- .../Orm/Filter/AbstractContextAwareFilter.php | 36 - src/Doctrine/Orm/Filter/AbstractFilter.php | 84 +- src/Doctrine/Orm/Filter/BooleanFilter.php | 10 +- .../Filter/ContextAwareFilterInterface.php | 30 - src/Doctrine/Orm/Filter/DateFilter.php | 17 +- src/Doctrine/Orm/Filter/ExistsFilter.php | 57 +- src/Doctrine/Orm/Filter/FilterInterface.php | 3 +- src/Doctrine/Orm/Filter/NumericFilter.php | 10 +- src/Doctrine/Orm/Filter/OrderFilter.php | 33 +- src/Doctrine/Orm/Filter/RangeFilter.php | 17 +- src/Doctrine/Orm/Filter/SearchFilter.php | 117 +- .../DoctrineOrmPropertyMetadataFactory.php | 4 +- ...neOrmResourceCollectionMetadataFactory.php | 10 +- src/Doctrine/Orm/Paginator.php | 5 +- src/Doctrine/Orm/PropertyHelperTrait.php | 28 +- src/Doctrine/Orm/State/CollectionProvider.php | 12 +- src/Doctrine/Orm/State/ItemProvider.php | 12 +- src/Doctrine/Orm/Util/EagerLoadingTrait.php | 108 -- src/Doctrine/Orm/Util/QueryBuilderHelper.php | 2 +- src/Doctrine/Orm/Util/QueryChecker.php | 14 +- src/Doctrine/Orm/Util/QueryJoinParser.php | 91 -- src/Doctrine/Orm/Util/QueryNameGenerator.php | 4 +- .../Extension/AbstractFilterExtension.php | 15 +- ...BodySearchCollectionExtensionInterface.php | 4 +- src/Elasticsearch/Extension/SortExtension.php | 18 +- src/Elasticsearch/Filter/AbstractFilter.php | 6 +- .../Filter/AbstractSearchFilter.php | 13 +- src/Elasticsearch/Filter/FilterInterface.php | 3 +- src/Elasticsearch/Filter/OrderFilter.php | 5 +- .../Metadata/Document/DocumentMetadata.php | 4 +- .../AttributeDocumentMetadataFactory.php | 21 +- .../Factory/CachedDocumentMetadataFactory.php | 6 +- .../Factory/CatDocumentMetadataFactory.php | 24 +- .../ConfiguredDocumentMetadataFactory.php | 4 +- ...viderResourceMetadataCollectionFactory.php | 7 +- src/Elasticsearch/Paginator.php | 14 +- .../Serializer/DocumentNormalizer.php | 6 +- .../Serializer/ItemNormalizer.php | 2 +- .../InnerFieldsNameConverter.php | 2 +- .../State/CollectionProvider.php | 17 +- src/Elasticsearch/State/ItemProvider.php | 6 +- src/Elasticsearch/Util/FieldDatatypeTrait.php | 24 +- src/GraphQl/Resolver/Stage/SerializeStage.php | 8 +- src/GraphQl/Type/FieldsBuilder.php | 10 +- src/GraphQl/Type/TypeBuilder.php | 4 +- src/GraphQl/Type/TypeBuilderInterface.php | 2 +- src/State/Pagination/Pagination.php | 149 +-- .../ApiPlatformExtension.php | 4 +- .../Resources/config/doctrine_mongodb_odm.xml | 5 +- .../Bundle/Resources/config/doctrine_orm.xml | 12 - .../Bundle/Resources/config/elasticsearch.xml | 2 - src/Test/DoctrineMongoDbOdmFilterTestCase.php | 29 +- src/Test/DoctrineMongoDbOdmTestCase.php | 6 +- src/Test/DoctrineOrmFilterTestCase.php | 58 +- src/Util/RequestParser.php | 11 - .../Common/Filter/BooleanFilterTestTrait.php | 4 +- .../Common/Filter/OrderFilterTestTrait.php | 2 +- .../Common/Filter/SearchFilterTestTrait.php | 2 +- .../Odm/Extension/FilterExtensionTest.php | 32 +- .../Odm/Extension/OrderExtensionTest.php | 46 +- .../Odm/Extension/PaginationExtensionTest.php | 195 +--- .../Doctrine/Odm/Filter/BooleanFilterTest.php | 5 +- tests/Doctrine/Odm/Filter/DateFilterTest.php | 4 +- .../Doctrine/Odm/Filter/ExistsFilterTest.php | 38 +- .../Doctrine/Odm/Filter/NumericFilterTest.php | 6 +- tests/Doctrine/Odm/Filter/OrderFilterTest.php | 6 +- tests/Doctrine/Odm/Filter/RangeFilterTest.php | 6 +- .../Doctrine/Odm/Filter/SearchFilterTest.php | 13 +- ...eMongoDbOdmPropertyMetadataFactoryTest.php | 8 +- ...mResourceCollectionMetadataFactoryTest.php | 4 +- tests/Doctrine/Odm/PaginatorTest.php | 32 +- .../Odm/State/CollectionProviderTest.php | 36 +- tests/Doctrine/Odm/State/ItemProviderTest.php | 72 +- .../Extension/EagerLoadingExtensionTest.php | 238 ++-- .../FilterEagerLoadingExtensionTest.php | 157 +-- .../Orm/Extension/FilterExtensionTest.php | 65 +- .../Orm/Extension/OrderExtensionTest.php | 46 +- .../Orm/Extension/PaginationExtensionTest.php | 1031 ++--------------- .../Doctrine/Orm/Filter/BooleanFilterTest.php | 2 +- .../Doctrine/Orm/Filter/CommonFilterTest.php | 41 - tests/Doctrine/Orm/Filter/DateFilterTest.php | 54 +- .../Doctrine/Orm/Filter/ExistsFilterTest.php | 68 +- .../Doctrine/Orm/Filter/NumericFilterTest.php | 4 +- tests/Doctrine/Orm/Filter/OrderFilterTest.php | 15 +- tests/Doctrine/Orm/Filter/RangeFilterTest.php | 4 +- .../Doctrine/Orm/Filter/SearchFilterTest.php | 133 +-- ...DoctrineOrmPropertyMetadataFactoryTest.php | 12 +- ...mResourceCollectionMetadataFactoryTest.php | 4 +- tests/Doctrine/Orm/PaginatorTest.php | 20 +- .../Orm/State/CollectionProviderTest.php | 46 +- tests/Doctrine/Orm/State/ItemProviderTest.php | 85 +- .../Orm/Util/QueryBuilderHelperTest.php | 4 +- tests/Doctrine/Orm/Util/QueryCheckerTest.php | 131 +-- .../Doctrine/Orm/Util/QueryJoinParserTest.php | 138 --- .../Orm/Util/QueryNameGeneratorTest.php | 4 +- .../ConstantScoreFilterExtensionTest.php | 36 +- .../Extension/SortExtensionTest.php | 47 +- .../Extension/SortFilterExtensionTest.php | 36 +- .../Elasticsearch/Filter/MatchFilterTest.php | 29 +- .../Elasticsearch/Filter/OrderFilterTest.php | 16 +- tests/Elasticsearch/Filter/TermFilterTest.php | 29 +- .../Document/DocumentMetadataTest.php | 2 +- .../AttributeDocumentMetadataFactoryTest.php | 29 +- .../CachedDocumentMetadataFactoryTest.php | 12 +- .../CatDocumentMetadataFactoryTest.php | 43 +- .../ConfiguredDocumentMetadataFactoryTest.php | 8 +- tests/Elasticsearch/PaginatorTest.php | 33 +- .../Serializer/DocumentNormalizerTest.php | 22 +- .../InnerFieldsNameConverterTest.php | 6 +- .../State/CollectionProviderTest.php | 16 +- .../Elasticsearch/State/ItemProviderTest.php | 11 +- .../Util/FieldDatatypeTraitTest.php | 10 +- .../DummyCustomMutationDtoDataTransformer.php | 64 - .../DummyCustomQueryDtoDataTransformer.php | 64 - .../Doctrine/Orm/Filter/DummyFilter.php | 38 - .../TestBundle/Filter/ArrayItemsFilter.php | 3 +- .../TestBundle/Filter/ArrayRequiredFilter.php | 3 +- .../TestBundle/Filter/BoundsFilter.php | 3 +- .../Filter/ComplexSubQueryFilter.php | 8 +- .../Fixtures/TestBundle/Filter/EnumFilter.php | 3 +- .../TestBundle/Filter/LengthFilter.php | 3 +- .../TestBundle/Filter/MultipleOfFilter.php | 3 +- .../TestBundle/Filter/PatternFilter.php | 3 +- .../Filter/RequiredAllowEmptyFilter.php | 3 +- .../TestBundle/Filter/RequiredFilter.php | 3 +- tests/Fixtures/app/config/config_common.yml | 2 +- tests/Fixtures/app/config/config_mongodb.yml | 2 +- tests/Util/RequestParserTest.php | 15 +- 174 files changed, 1262 insertions(+), 4562 deletions(-) delete mode 100644 src/Doctrine/Orm/Extension/ContextAwareQueryCollectionExtensionInterface.php delete mode 100644 src/Doctrine/Orm/Extension/ContextAwareQueryResultCollectionExtensionInterface.php delete mode 100644 src/Doctrine/Orm/Extension/ContextAwareQueryResultItemExtensionInterface.php delete mode 100644 src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php delete mode 100644 src/Doctrine/Orm/Filter/ContextAwareFilterInterface.php delete mode 100644 src/Doctrine/Orm/Util/EagerLoadingTrait.php delete mode 100644 src/Doctrine/Orm/Util/QueryJoinParser.php delete mode 100644 tests/Doctrine/Orm/Filter/CommonFilterTest.php delete mode 100644 tests/Doctrine/Orm/Util/QueryJoinParserTest.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/DummyCustomMutationDtoDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/DataTransformer/DummyCustomQueryDtoDataTransformer.php delete mode 100644 tests/Fixtures/TestBundle/Doctrine/Orm/Filter/DummyFilter.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index d4127b20f78..12d2b5e1783 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -44,7 +44,6 @@ parameters: - src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php - src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php - src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php - - src/Core/Bridge/Doctrine/Orm/Filter/AbstractContextAwareFilter.php - src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php - src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php - src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php @@ -340,7 +339,7 @@ parameters: - '#Method ApiPlatform\\Doctrine\\Orm\\Filter\\(Abstract|Exists|Order)Filter::filterProperty\(\) invoked with 7 parameters, 5-6 required\.#' - '#Method ApiPlatform\\Doctrine\\Orm\\Filter\\(AbstractFilter|FilterInterface)::apply\(\) invoked with 5 parameters, 3-4 required\.#' - '#Method ApiPlatform\\PathResolver\\OperationPathResolverInterface::resolveOperationPath\(\) invoked with 4 parameters, 3 required\.#' - - + - message: '#If condition is always false.#' path: src/Core @@ -366,7 +365,7 @@ parameters: message: '#Call to an undefined method Symfony\\Component\\PropertyInfo\\Type::getCollectionKeyType\(\)#' path: src # Skipped tests, we do this on purpose - - + - message: "#^Unreachable statement - code above always terminates.$#" path: tests - diff --git a/src/Api/FilterLocatorTrait.php b/src/Api/FilterLocatorTrait.php index f7281f92003..005494fa9a2 100644 --- a/src/Api/FilterLocatorTrait.php +++ b/src/Api/FilterLocatorTrait.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Api; -use ApiPlatform\Core\Api\FilterCollection; use ApiPlatform\Exception\InvalidArgumentException; use Psr\Container\ContainerInterface; diff --git a/src/Doctrine/Common/Filter/ExistsFilterTrait.php b/src/Doctrine/Common/Filter/ExistsFilterTrait.php index 41cfe4a36a0..c7551e584bc 100644 --- a/src/Doctrine/Common/Filter/ExistsFilterTrait.php +++ b/src/Doctrine/Common/Filter/ExistsFilterTrait.php @@ -30,7 +30,7 @@ trait ExistsFilterTrait /** * @var string Keyword used to retrieve the value */ - private $existsParameterName; + private string $existsParameterName; /** * {@inheritdoc} diff --git a/src/Doctrine/Common/Filter/NumericFilterTrait.php b/src/Doctrine/Common/Filter/NumericFilterTrait.php index 5d4850d6644..d2787ac8c1d 100644 --- a/src/Doctrine/Common/Filter/NumericFilterTrait.php +++ b/src/Doctrine/Common/Filter/NumericFilterTrait.php @@ -52,7 +52,7 @@ public function getDescription(string $resourceClass): array 'property' => $propertyName, 'type' => $this->getType((string) $this->getDoctrineFieldType($property, $resourceClass)), 'required' => false, - 'is_collection' => '[]' === substr((string) $filterParameterName, -2), + 'is_collection' => str_ends_with((string) $filterParameterName, '[]'), ]; } } diff --git a/src/Doctrine/Common/Filter/OrderFilterTrait.php b/src/Doctrine/Common/Filter/OrderFilterTrait.php index 8d7ad9d302f..ae59cbf5ec9 100644 --- a/src/Doctrine/Common/Filter/OrderFilterTrait.php +++ b/src/Doctrine/Common/Filter/OrderFilterTrait.php @@ -29,7 +29,7 @@ trait OrderFilterTrait /** * @var string Keyword used to retrieve the value */ - protected $orderParameterName; + protected string $orderParameterName; /** * {@inheritdoc} diff --git a/src/Doctrine/Common/Filter/SearchFilterTrait.php b/src/Doctrine/Common/Filter/SearchFilterTrait.php index 1aa89b8ab8b..0b9d472e543 100644 --- a/src/Doctrine/Common/Filter/SearchFilterTrait.php +++ b/src/Doctrine/Common/Filter/SearchFilterTrait.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Doctrine\Common\Filter; +use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use ApiPlatform\Doctrine\Common\PropertyHelperTrait; use ApiPlatform\Exception\InvalidArgumentException; use Psr\Log\LoggerInterface; @@ -30,12 +30,9 @@ trait SearchFilterTrait { use PropertyHelperTrait; - /** - * @var LegacyIriConverterInterface|IriConverterInterface - */ - protected $iriConverter; - protected $propertyAccessor; - protected $identifiersExtractor; + protected IriConverterInterface $iriConverter; + protected PropertyAccessorInterface $propertyAccessor; + protected ?IdentifiersExtractorInterface $identifiersExtractor; /** * {@inheritdoc} @@ -79,7 +76,7 @@ public function getDescription(string $resourceClass): array 'type' => $typeOfField, 'required' => false, 'strategy' => $strategy, - 'is_collection' => '[]' === substr((string) $filterParameterName, -2), + 'is_collection' => str_ends_with((string) $filterParameterName, '[]'), ]; } } elseif ($metadata->hasAssociation($field)) { @@ -94,7 +91,7 @@ public function getDescription(string $resourceClass): array 'type' => 'string', 'required' => false, 'strategy' => self::STRATEGY_EXACT, - 'is_collection' => '[]' === substr((string) $filterParameterName, -2), + 'is_collection' => str_ends_with((string) $filterParameterName, '[]'), ]; } } @@ -112,10 +109,7 @@ abstract protected function getProperties(): ?array; abstract protected function getLogger(): LoggerInterface; - /** - * @return IriConverterInterface|LegacyIriConverterInterface - */ - abstract protected function getIriConverter(); + abstract protected function getIriConverter(): IriConverterInterface; abstract protected function getPropertyAccessor(): PropertyAccessorInterface; @@ -128,7 +122,7 @@ protected function getIdFromValue(string $value) { try { $iriConverter = $this->getIriConverter(); - $item = $iriConverter instanceof LegacyIriConverterInterface ? $iriConverter->getItemFromIri($value, ['fetch_data' => false]) : $iriConverter->getResourceFromIri($value, ['fetch_data' => false]); // @phpstan-ignore-line bc-compatibility inside a trait + $item = $iriConverter->getResourceFromIri($value, ['fetch_data' => false]); return $this->getPropertyAccessor()->getValue($item, 'id'); } catch (InvalidArgumentException $e) { diff --git a/src/Doctrine/Common/PropertyHelperTrait.php b/src/Doctrine/Common/PropertyHelperTrait.php index 21ec57b8be2..73daab890c5 100644 --- a/src/Doctrine/Common/PropertyHelperTrait.php +++ b/src/Doctrine/Common/PropertyHelperTrait.php @@ -47,26 +47,14 @@ protected function isPropertyMapped(string $property, string $resourceClass, boo /** * Determines whether the given property is nested. */ - protected function isPropertyNested(string $property/* , string $resourceClass */): bool + protected function isPropertyNested(string $property, string $resourceClass): bool { - if (\func_num_args() > 1) { - $resourceClass = (string) func_get_arg(1); - } else { - if (__CLASS__ !== static::class) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a second `$resourceClass` argument in version API Platform 3.0. Not defining it is deprecated since API Platform 2.1.', __FUNCTION__), \E_USER_DEPRECATED); - } - } - $resourceClass = null; - } - $pos = strpos($property, '.'); if (false === $pos) { return false; } - return null !== $resourceClass && $this->getClassMetadata($resourceClass)->hasAssociation(substr($property, 0, $pos)); + return $this->getClassMetadata($resourceClass)->hasAssociation(substr($property, 0, $pos)); } /** @@ -74,7 +62,7 @@ protected function isPropertyNested(string $property/* , string $resourceClass * */ protected function isPropertyEmbedded(string $property, string $resourceClass): bool { - return false !== strpos($property, '.') && $this->getClassMetadata($resourceClass)->hasField($property); + return str_contains($property, '.') && $this->getClassMetadata($resourceClass)->hasField($property); } /** @@ -84,27 +72,10 @@ protected function isPropertyEmbedded(string $property, string $resourceClass): * - associations: array of associations according to nesting order * - field: string holding the actual field (leaf node) */ - protected function splitPropertyParts(string $property/* , string $resourceClass */): array + protected function splitPropertyParts(string $property, string $resourceClass): array { - $resourceClass = null; $parts = explode('.', $property); - if (\func_num_args() > 1) { - $resourceClass = func_get_arg(1); - } elseif (__CLASS__ !== static::class) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a second `$resourceClass` argument in version API Platform 3.0. Not defining it is deprecated since API Platform 2.1.', __FUNCTION__), \E_USER_DEPRECATED); - } - } - - if (null === $resourceClass) { - return [ - 'associations' => \array_slice($parts, 0, -1), - 'field' => end($parts), - ]; - } - $metadata = $this->getClassMetadata($resourceClass); $slice = 0; diff --git a/src/Doctrine/Common/State/LinksHandlerTrait.php b/src/Doctrine/Common/State/LinksHandlerTrait.php index 8c86d9bd7fc..2033ac76241 100644 --- a/src/Doctrine/Common/State/LinksHandlerTrait.php +++ b/src/Doctrine/Common/State/LinksHandlerTrait.php @@ -42,7 +42,7 @@ private function getLinks(string $resourceClass, Operation $operation, array $co } } - // Using graphql, it's possible that we won't find a graphql operation of the same type (eg it is disabled). + // Using GraphQL, it's possible that we won't find a GraphQL Operation of the same type (e.g. it is disabled). try { $resourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($linkClass); $linkedOperation = $resourceMetadataCollection->getOperation($operation->getName()); @@ -51,7 +51,7 @@ private function getLinks(string $resourceClass, Operation $operation, array $co throw $e; } - // Instead we'll look for the first Query available + // Instead, we'll look for the first Query available. foreach ($resourceMetadataCollection as $resourceMetadata) { foreach ($resourceMetadata->getGraphQlOperations() as $operation) { if ($operation instanceof Query) { diff --git a/src/Doctrine/Common/State/PersistProcessor.php b/src/Doctrine/Common/State/PersistProcessor.php index f43a5bcf0b0..1f28f2c905f 100644 --- a/src/Doctrine/Common/State/PersistProcessor.php +++ b/src/Doctrine/Common/State/PersistProcessor.php @@ -25,7 +25,7 @@ final class PersistProcessor implements ProcessorInterface { use ClassInfoTrait; - private $managerRegistry; + private ManagerRegistry $managerRegistry; public function __construct(ManagerRegistry $managerRegistry) { diff --git a/src/Doctrine/Common/State/RemoveProcessor.php b/src/Doctrine/Common/State/RemoveProcessor.php index f149b13e8cf..528305b9043 100644 --- a/src/Doctrine/Common/State/RemoveProcessor.php +++ b/src/Doctrine/Common/State/RemoveProcessor.php @@ -23,7 +23,7 @@ final class RemoveProcessor implements ProcessorInterface { use ClassInfoTrait; - private $managerRegistry; + private ManagerRegistry $managerRegistry; public function __construct(ManagerRegistry $managerRegistry) { diff --git a/src/Doctrine/Odm/Extension/AggregationCollectionExtensionInterface.php b/src/Doctrine/Odm/Extension/AggregationCollectionExtensionInterface.php index 5a000ecc329..04e9636b4db 100644 --- a/src/Doctrine/Odm/Extension/AggregationCollectionExtensionInterface.php +++ b/src/Doctrine/Odm/Extension/AggregationCollectionExtensionInterface.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Odm\Extension; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; /** @@ -24,5 +25,5 @@ */ interface AggregationCollectionExtensionInterface { - public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []); + public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []); } diff --git a/src/Doctrine/Odm/Extension/AggregationItemExtensionInterface.php b/src/Doctrine/Odm/Extension/AggregationItemExtensionInterface.php index 5314a685793..8985984faec 100644 --- a/src/Doctrine/Odm/Extension/AggregationItemExtensionInterface.php +++ b/src/Doctrine/Odm/Extension/AggregationItemExtensionInterface.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Odm\Extension; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; /** @@ -24,5 +25,5 @@ */ interface AggregationItemExtensionInterface { - public function applyToItem(Builder $aggregationBuilder, string $resourceClass, array $identifiers, string $operationName = null, array &$context = []); + public function applyToItem(Builder $aggregationBuilder, string $resourceClass, array $identifiers, Operation $operation = null, array &$context = []); } diff --git a/src/Doctrine/Odm/Extension/AggregationResultCollectionExtensionInterface.php b/src/Doctrine/Odm/Extension/AggregationResultCollectionExtensionInterface.php index 6dfb069f453..02fd0b11e01 100644 --- a/src/Doctrine/Odm/Extension/AggregationResultCollectionExtensionInterface.php +++ b/src/Doctrine/Odm/Extension/AggregationResultCollectionExtensionInterface.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Odm\Extension; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; /** @@ -25,7 +26,7 @@ */ interface AggregationResultCollectionExtensionInterface extends AggregationCollectionExtensionInterface { - public function supportsResult(string $resourceClass, string $operationName = null, array $context = []): bool; + public function supportsResult(string $resourceClass, Operation $operation = null, array $context = []): bool; - public function getResult(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array $context = []); + public function getResult(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array $context = []); } diff --git a/src/Doctrine/Odm/Extension/AggregationResultItemExtensionInterface.php b/src/Doctrine/Odm/Extension/AggregationResultItemExtensionInterface.php index 9d483804e8c..6e1cb18f415 100644 --- a/src/Doctrine/Odm/Extension/AggregationResultItemExtensionInterface.php +++ b/src/Doctrine/Odm/Extension/AggregationResultItemExtensionInterface.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Odm\Extension; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; /** @@ -25,7 +26,7 @@ */ interface AggregationResultItemExtensionInterface extends AggregationItemExtensionInterface { - public function supportsResult(string $resourceClass, string $operationName = null, array $context = []): bool; + public function supportsResult(string $resourceClass, Operation $operation = null, array $context = []): bool; - public function getResult(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array $context = []); + public function getResult(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array $context = []); } diff --git a/src/Doctrine/Odm/Extension/FilterExtension.php b/src/Doctrine/Odm/Extension/FilterExtension.php index b5df5addbc1..71777a6d8bc 100644 --- a/src/Doctrine/Odm/Extension/FilterExtension.php +++ b/src/Doctrine/Odm/Extension/FilterExtension.php @@ -13,12 +13,8 @@ namespace ApiPlatform\Doctrine\Odm\Extension; -use ApiPlatform\Api\FilterLocatorTrait; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Doctrine\Odm\Filter\FilterInterface; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Psr\Container\ContainerInterface; @@ -32,47 +28,29 @@ */ final class FilterExtension implements AggregationCollectionExtensionInterface { - use FilterLocatorTrait; + private ContainerInterface $filterLocator; - private $resourceMetadataFactory; - - /** - * @param ContainerInterface|FilterCollection $filterLocator The new filter locator or the deprecated filter collection - * @param mixed $resourceMetadataFactory - */ - public function __construct($resourceMetadataFactory, $filterLocator) + public function __construct(ContainerInterface $filterLocator) { - $this->setFilterLocator($filterLocator); - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; + $this->filterLocator = $filterLocator; } /** * {@inheritdoc} */ - public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $resourceMetadata->getOperation($operationName); - $resourceFilters = $operation->getFilters(); - } catch (OperationNotFoundException $e) { - $resourceFilters = $resourceMetadata->getOperation(null, true)->getFilters(); - } + $resourceFilters = $operation?->getFilters(); if (empty($resourceFilters)) { return; } foreach ($resourceFilters as $filterId) { - $filter = $this->getFilter($filterId); + $filter = $this->filterLocator->has($filterId) ? $this->filterLocator->get($filterId) : null; if ($filter instanceof FilterInterface) { $context['filters'] = $context['filters'] ?? []; - $filter->apply($aggregationBuilder, $resourceClass, $operationName, $context); + $filter->apply($aggregationBuilder, $resourceClass, $operation, $context); } } } diff --git a/src/Doctrine/Odm/Extension/OrderExtension.php b/src/Doctrine/Odm/Extension/OrderExtension.php index f2858a26876..69c510fb4bf 100644 --- a/src/Doctrine/Odm/Extension/OrderExtension.php +++ b/src/Doctrine/Odm/Extension/OrderExtension.php @@ -13,11 +13,9 @@ namespace ApiPlatform\Doctrine\Odm\Extension; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Doctrine\Common\PropertyHelperTrait; use ApiPlatform\Doctrine\Odm\PropertyHelperTrait as MongoDbOdmPropertyHelperTrait; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort; use Doctrine\Persistence\ManagerRegistry; @@ -38,17 +36,11 @@ final class OrderExtension implements AggregationCollectionExtensionInterface use MongoDbOdmPropertyHelperTrait; use PropertyHelperTrait; - private $order; - private $resourceMetadataFactory; - private $managerRegistry; + private ?string $order; + private ?ManagerRegistry $managerRegistry; - public function __construct(string $order = null, $resourceMetadataFactory = null, ManagerRegistry $managerRegistry = null) + public function __construct(string $order = null, ManagerRegistry $managerRegistry = null) { - if ($resourceMetadataFactory && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->order = $order; $this->managerRegistry = $managerRegistry; } @@ -56,7 +48,7 @@ public function __construct(string $order = null, $resourceMetadataFactory = nul /** * {@inheritdoc} */ - public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { // Do not apply order if already defined on $aggregationBuilder if ($this->hasSortStage($aggregationBuilder)) { @@ -65,40 +57,29 @@ public function applyToCollection(Builder $aggregationBuilder, string $resourceC $classMetaData = $this->getClassMetadata($resourceClass); $identifiers = $classMetaData->getIdentifier(); - if (null !== $this->resourceMetadataFactory) { - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - if (isset($context['operation'])) { - $defaultOrder = $context['operation']->getOrder() ?? []; - } else { - $metadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $defaultOrder = $metadata->getOperation($operationName)->getOrder(); - } catch (OperationNotFoundException $e) { - $defaultOrder = $metadata->getOperation(null, true)->getOrder(); - } - } - } else { - $defaultOrder = $this->resourceMetadataFactory->create($resourceClass)->getAttribute('order'); - } + if (isset($context['operation'])) { + $defaultOrder = $context['operation']->getOrder() ?? []; + } else { + $defaultOrder = $operation?->getOrder(); + } - if ($defaultOrder) { - foreach ($defaultOrder as $field => $order) { - if (\is_int($field)) { - // Default direction - $field = $order; - $order = 'ASC'; - } - - if ($this->isPropertyNested($field, $resourceClass)) { - [$field] = $this->addLookupsForNestedProperty($field, $aggregationBuilder, $resourceClass); - } - $aggregationBuilder->sort( - $context['mongodb_odm_sort_fields'] = ($context['mongodb_odm_sort_fields'] ?? []) + [$field => $order] - ); + if ($defaultOrder) { + foreach ($defaultOrder as $field => $order) { + if (\is_int($field)) { + // Default direction + $field = $order; + $order = 'ASC'; } - return; + if ($this->isPropertyNested($field, $resourceClass)) { + [$field] = $this->addLookupsForNestedProperty($field, $aggregationBuilder, $resourceClass); + } + $aggregationBuilder->sort( + $context['mongodb_odm_sort_fields'] = ($context['mongodb_odm_sort_fields'] ?? []) + [$field => $order] + ); } + + return; } if (null !== $this->order) { diff --git a/src/Doctrine/Odm/Extension/PaginationExtension.php b/src/Doctrine/Odm/Extension/PaginationExtension.php index 8734a9381a8..186c25bd79c 100644 --- a/src/Doctrine/Odm/Extension/PaginationExtension.php +++ b/src/Doctrine/Odm/Extension/PaginationExtension.php @@ -13,11 +13,9 @@ namespace ApiPlatform\Doctrine\Odm\Extension; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Doctrine\Odm\Paginator; -use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Operation; use ApiPlatform\State\Pagination\Pagination; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\DocumentManager; @@ -35,19 +33,12 @@ */ final class PaginationExtension implements AggregationResultCollectionExtensionInterface { - private $managerRegistry; - private $resourceMetadataFactory; - private $pagination; + private ManagerRegistry $managerRegistry; + private Pagination $pagination; - public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataFactory, Pagination $pagination) + public function __construct(ManagerRegistry $managerRegistry, Pagination $pagination) { $this->managerRegistry = $managerRegistry; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->pagination = $pagination; } @@ -56,19 +47,19 @@ public function __construct(ManagerRegistry $managerRegistry, $resourceMetadataF * * @throws RuntimeException */ - public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { - if (!$this->pagination->isEnabled($resourceClass, $operationName, $context)) { + if (!$this->pagination->isEnabled($operation, $context)) { return; } - if (($context['graphql_operation_name'] ?? false) && !$this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context)) { + if (($context['graphql_operation_name'] ?? false) && !$this->pagination->isGraphQlEnabled($operation, $context)) { return; } $context = $this->addCountToContext(clone $aggregationBuilder, $context); - [, $offset, $limit] = $this->pagination->getPagination($resourceClass, $operationName, $context); + [, $offset, $limit] = $this->pagination->getPagination($operation, $context); $manager = $this->managerRegistry->getManagerForClass($resourceClass); if (!$manager instanceof DocumentManager) { @@ -101,13 +92,13 @@ public function applyToCollection(Builder $aggregationBuilder, string $resourceC /** * {@inheritdoc} */ - public function supportsResult(string $resourceClass, string $operationName = null, array $context = []): bool + public function supportsResult(string $resourceClass, Operation $operation = null, array $context = []): bool { if ($context['graphql_operation_name'] ?? false) { - return $this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context); + return $this->pagination->isGraphQlEnabled($operation, $context); } - return $this->pagination->isEnabled($resourceClass, $operationName, $context); + return $this->pagination->isEnabled($operation, $context); } /** @@ -115,20 +106,14 @@ public function supportsResult(string $resourceClass, string $operationName = nu * * @throws RuntimeException */ - public function getResult(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array $context = []) + public function getResult(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array $context = []): iterable { $manager = $this->managerRegistry->getManagerForClass($resourceClass); if (!$manager instanceof DocumentManager) { throw new RuntimeException(sprintf('The manager for "%s" must be an instance of "%s".', $resourceClass, DocumentManager::class)); } - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName); - $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; - } catch (OperationNotFoundException $e) { - $attribute = $resourceMetadata->getOperation(null, true)->getExtraProperties()['doctrine_mongodb'] ?? []; - } + $attribute = $operation?->getExtraProperties()['doctrine_mongodb'] ?? []; $executeOptions = $attribute['execute_options'] ?? []; return new Paginator($aggregationBuilder->execute($executeOptions), $manager->getUnitOfWork(), $resourceClass, $aggregationBuilder->getPipeline()); diff --git a/src/Doctrine/Odm/Filter/AbstractFilter.php b/src/Doctrine/Odm/Filter/AbstractFilter.php index 567d9a8a1fb..2b2e782e99a 100644 --- a/src/Doctrine/Odm/Filter/AbstractFilter.php +++ b/src/Doctrine/Odm/Filter/AbstractFilter.php @@ -15,6 +15,7 @@ use ApiPlatform\Doctrine\Common\PropertyHelperTrait; use ApiPlatform\Doctrine\Odm\PropertyHelperTrait as MongoDbOdmPropertyHelperTrait; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\Persistence\ManagerRegistry; use Psr\Log\LoggerInterface; @@ -35,10 +36,10 @@ abstract class AbstractFilter implements FilterInterface use MongoDbOdmPropertyHelperTrait; use PropertyHelperTrait; - protected $managerRegistry; - protected $logger; - protected $properties; - protected $nameConverter; + protected ManagerRegistry $managerRegistry; + protected LoggerInterface $logger; + protected ?array $properties; + protected ?NameConverterInterface $nameConverter; public function __construct(ManagerRegistry $managerRegistry, LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null) { @@ -51,10 +52,10 @@ public function __construct(ManagerRegistry $managerRegistry, LoggerInterface $l /** * {@inheritdoc} */ - public function apply(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + public function apply(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []) { foreach ($context['filters'] as $property => $value) { - $this->filterProperty($this->denormalizePropertyName($property), $value, $aggregationBuilder, $resourceClass, $operationName, $context); + $this->filterProperty($this->denormalizePropertyName($property), $value, $aggregationBuilder, $resourceClass, $operation, $context); } } @@ -63,7 +64,7 @@ public function apply(Builder $aggregationBuilder, string $resourceClass, string * * @param mixed $value */ - abstract protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []); + abstract protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []); protected function getManagerRegistry(): ManagerRegistry { @@ -93,7 +94,7 @@ protected function isPropertyEnabled(string $property, string $resourceClass): b return \array_key_exists($property, $this->properties); } - protected function denormalizePropertyName($property) + protected function denormalizePropertyName($property): string { if (!$this->nameConverter instanceof NameConverterInterface) { return $property; @@ -102,7 +103,7 @@ protected function denormalizePropertyName($property) return implode('.', array_map([$this->nameConverter, 'denormalize'], explode('.', (string) $property))); } - protected function normalizePropertyName($property) + protected function normalizePropertyName($property): string { if (!$this->nameConverter instanceof NameConverterInterface) { return $property; diff --git a/src/Doctrine/Odm/Filter/BooleanFilter.php b/src/Doctrine/Odm/Filter/BooleanFilter.php index 111760aa251..9d7534d7b12 100644 --- a/src/Doctrine/Odm/Filter/BooleanFilter.php +++ b/src/Doctrine/Odm/Filter/BooleanFilter.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Odm\Filter; use ApiPlatform\Doctrine\Common\Filter\BooleanFilterTrait; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; @@ -44,7 +45,7 @@ final class BooleanFilter extends AbstractFilter /** * {@inheritdoc} */ - protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { if ( !$this->isPropertyEnabled($property, $resourceClass) || diff --git a/src/Doctrine/Odm/Filter/DateFilter.php b/src/Doctrine/Odm/Filter/DateFilter.php index 9b64b4b4a56..899915dec8c 100644 --- a/src/Doctrine/Odm/Filter/DateFilter.php +++ b/src/Doctrine/Odm/Filter/DateFilter.php @@ -16,6 +16,7 @@ use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface; use ApiPlatform\Doctrine\Common\Filter\DateFilterTrait; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; @@ -28,7 +29,7 @@ * @author Théo FIDRY * @author Alan Poulain */ -class DateFilter extends AbstractFilter implements DateFilterInterface +final class DateFilter extends AbstractFilter implements DateFilterInterface { use DateFilterTrait; @@ -40,7 +41,7 @@ class DateFilter extends AbstractFilter implements DateFilterInterface /** * {@inheritdoc} */ - protected function filterProperty(string $property, $values, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + protected function filterProperty(string $property, $values, Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { // Expect $values to be an array having the period as keys and the date value as values if ( diff --git a/src/Doctrine/Odm/Filter/ExistsFilter.php b/src/Doctrine/Odm/Filter/ExistsFilter.php index 829d60315d5..833091541ed 100644 --- a/src/Doctrine/Odm/Filter/ExistsFilter.php +++ b/src/Doctrine/Odm/Filter/ExistsFilter.php @@ -15,6 +15,7 @@ use ApiPlatform\Doctrine\Common\Filter\ExistsFilterInterface; use ApiPlatform\Doctrine\Common\Filter\ExistsFilterTrait; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\Persistence\ManagerRegistry; @@ -50,27 +51,19 @@ public function __construct(ManagerRegistry $managerRegistry, LoggerInterface $l /** * {@inheritdoc} */ - public function apply(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + public function apply(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { - if (!\is_array($context['filters'][$this->existsParameterName] ?? null)) { - $context['exists_deprecated_syntax'] = true; - parent::apply($aggregationBuilder, $resourceClass, $operationName, $context); - - return; - } - foreach ($context['filters'][$this->existsParameterName] as $property => $value) { - $this->filterProperty($this->denormalizePropertyName($property), $value, $aggregationBuilder, $resourceClass, $operationName, $context); + $this->filterProperty($this->denormalizePropertyName($property), $value, $aggregationBuilder, $resourceClass, $operation, $context); } } /** * {@inheritdoc} */ - protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { if ( - (($context['exists_deprecated_syntax'] ?? false) && !isset($value[self::QUERY_PARAMETER_KEY])) || !$this->isPropertyEnabled($property, $resourceClass) || !$this->isPropertyMapped($property, $resourceClass, true) || !$this->isNullableField($property, $resourceClass) diff --git a/src/Doctrine/Odm/Filter/FilterInterface.php b/src/Doctrine/Odm/Filter/FilterInterface.php index 12d6cfd08d7..dd60954f642 100644 --- a/src/Doctrine/Odm/Filter/FilterInterface.php +++ b/src/Doctrine/Odm/Filter/FilterInterface.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Odm\Filter; use ApiPlatform\Api\FilterInterface as BaseFilterInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; /** @@ -28,5 +29,5 @@ interface FilterInterface extends BaseFilterInterface /** * Applies the filter. */ - public function apply(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []); + public function apply(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []); } diff --git a/src/Doctrine/Odm/Filter/NumericFilter.php b/src/Doctrine/Odm/Filter/NumericFilter.php index e6766af8a98..e00310d04d0 100644 --- a/src/Doctrine/Odm/Filter/NumericFilter.php +++ b/src/Doctrine/Odm/Filter/NumericFilter.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Odm\Filter; use ApiPlatform\Doctrine\Common\Filter\NumericFilterTrait; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; @@ -47,7 +48,7 @@ final class NumericFilter extends AbstractFilter /** * {@inheritdoc} */ - protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { if ( !$this->isPropertyEnabled($property, $resourceClass) || diff --git a/src/Doctrine/Odm/Filter/OrderFilter.php b/src/Doctrine/Odm/Filter/OrderFilter.php index 60c6df2f7cd..888f099a44a 100644 --- a/src/Doctrine/Odm/Filter/OrderFilter.php +++ b/src/Doctrine/Odm/Filter/OrderFilter.php @@ -15,6 +15,7 @@ use ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface; use ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\Persistence\ManagerRegistry; use Psr\Log\LoggerInterface; @@ -63,27 +64,27 @@ public function __construct(ManagerRegistry $managerRegistry, string $orderParam /** * {@inheritdoc} */ - public function apply(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + public function apply(Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { if (isset($context['filters']) && !isset($context['filters'][$this->orderParameterName])) { return; } if (!isset($context['filters'][$this->orderParameterName]) || !\is_array($context['filters'][$this->orderParameterName])) { - parent::apply($aggregationBuilder, $resourceClass, $operationName, $context); + parent::apply($aggregationBuilder, $resourceClass, $operation, $context); return; } foreach ($context['filters'][$this->orderParameterName] as $property => $value) { - $this->filterProperty($this->denormalizePropertyName($property), $value, $aggregationBuilder, $resourceClass, $operationName, $context); + $this->filterProperty($this->denormalizePropertyName($property), $value, $aggregationBuilder, $resourceClass, $operation, $context); } } /** * {@inheritdoc} */ - protected function filterProperty(string $property, $direction, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + protected function filterProperty(string $property, $direction, Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { if (!$this->isPropertyEnabled($property, $resourceClass) || !$this->isPropertyMapped($property, $resourceClass)) { return; diff --git a/src/Doctrine/Odm/Filter/RangeFilter.php b/src/Doctrine/Odm/Filter/RangeFilter.php index b6c1c7d9d48..f6cb01f4a4b 100644 --- a/src/Doctrine/Odm/Filter/RangeFilter.php +++ b/src/Doctrine/Odm/Filter/RangeFilter.php @@ -15,6 +15,7 @@ use ApiPlatform\Doctrine\Common\Filter\RangeFilterInterface; use ApiPlatform\Doctrine\Common\Filter\RangeFilterTrait; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; /** @@ -32,7 +33,7 @@ final class RangeFilter extends AbstractFilter implements RangeFilterInterface /** * {@inheritdoc} */ - protected function filterProperty(string $property, $values, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + protected function filterProperty(string $property, $values, Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { if ( !\is_array($values) || @@ -67,7 +68,7 @@ protected function filterProperty(string $property, $values, Builder $aggregatio /** * Adds the match stage according to the operator. */ - protected function addMatch(Builder $aggregationBuilder, string $field, string $matchField, string $operator, string $value) + protected function addMatch(Builder $aggregationBuilder, string $field, string $matchField, string $operator, string $value): void { switch ($operator) { case self::PARAMETER_BETWEEN: diff --git a/src/Doctrine/Odm/Filter/SearchFilter.php b/src/Doctrine/Odm/Filter/SearchFilter.php index b3d350968fe..447a6baf2a7 100644 --- a/src/Doctrine/Odm/Filter/SearchFilter.php +++ b/src/Doctrine/Odm/Filter/SearchFilter.php @@ -13,11 +13,12 @@ namespace ApiPlatform\Doctrine\Odm\Filter; +use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; use ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface; use ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Operation; use Doctrine\ODM\MongoDB\Aggregation\Builder; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MongoDBClassMetadata; use Doctrine\ODM\MongoDB\Types\Type as MongoDbType; @@ -43,7 +44,7 @@ final class SearchFilter extends AbstractFilter implements SearchFilterInterface public const DOCTRINE_INTEGER_TYPE = [MongoDbType::INTEGER, MongoDbType::INT]; - public function __construct(ManagerRegistry $managerRegistry, IriConverterInterface $iriConverter, IdentifiersExtractorInterface $identifiersExtractor, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null) + public function __construct(ManagerRegistry $managerRegistry, IriConverterInterface $iriConverter, ?IdentifiersExtractorInterface $identifiersExtractor, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null) { parent::__construct($managerRegistry, $logger, $properties, $nameConverter); @@ -52,7 +53,7 @@ public function __construct(ManagerRegistry $managerRegistry, IriConverterInterf $this->identifiersExtractor = $identifiersExtractor; } - protected function getIriConverter() + protected function getIriConverter(): IriConverterInterface { return $this->iriConverter; } @@ -65,7 +66,7 @@ protected function getPropertyAccessor(): PropertyAccessorInterface /** * {@inheritdoc} */ - protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = []) + protected function filterProperty(string $property, $value, Builder $aggregationBuilder, string $resourceClass, Operation $operation = null, array &$context = []): void { if ( null === $value || @@ -91,7 +92,7 @@ protected function filterProperty(string $property, $value, Builder $aggregation $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; // prefixing the strategy with i makes it case insensitive - if (0 === strpos($strategy, 'i')) { + if (str_starts_with($strategy, 'i')) { $strategy = substr($strategy, 1); $caseSensitive = false; } @@ -123,13 +124,10 @@ protected function filterProperty(string $property, $value, Builder $aggregation } $values = array_map([$this, 'getIdFromValue'], $values); - $doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass); - if (null !== $this->identifiersExtractor) { - $associationResourceClass = $metadata->getAssociationTargetClass($field); - $associationFieldIdentifier = $this->identifiersExtractor->getIdentifiersFromResourceClass($associationResourceClass)[0]; - $doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass); - } + $associationResourceClass = $metadata->getAssociationTargetClass($field); + $associationFieldIdentifier = $metadata->getIdentifierFieldNames()[0]; + $doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass); if (!$this->hasValidValues($values, $doctrineTypeField)) { $this->logger->notice('Invalid filter ignored', [ diff --git a/src/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php b/src/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php index 9c90c4e8115..e1f05727d60 100644 --- a/src/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php +++ b/src/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactory.php @@ -28,8 +28,8 @@ */ final class DoctrineMongoDbOdmPropertyMetadataFactory implements PropertyMetadataFactoryInterface { - private $decorated; - private $managerRegistry; + private PropertyMetadataFactoryInterface $decorated; + private ManagerRegistry $managerRegistry; public function __construct(ManagerRegistry $managerRegistry, PropertyMetadataFactoryInterface $decorated) { diff --git a/src/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactory.php b/src/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactory.php index ec2ea373e40..01e3e69644d 100644 --- a/src/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactory.php +++ b/src/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactory.php @@ -27,15 +27,9 @@ final class DoctrineMongoDbOdmResourceCollectionMetadataFactory implements ResourceMetadataCollectionFactoryInterface { - /** - * @var ManagerRegistry - */ - private $managerRegistry; + private ManagerRegistry $managerRegistry; - /** - * @var ResourceMetadataCollectionFactoryInterface - */ - private $decorated; + private ResourceMetadataCollectionFactoryInterface $decorated; public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataCollectionFactoryInterface $decorated) { diff --git a/src/Doctrine/Odm/Paginator.php b/src/Doctrine/Odm/Paginator.php index 69efc1baf86..9cfb51472a8 100644 --- a/src/Doctrine/Odm/Paginator.php +++ b/src/Doctrine/Odm/Paginator.php @@ -31,38 +31,21 @@ final class Paginator implements \IteratorAggregate, PaginatorInterface public const LIMIT_ZERO_MARKER_FIELD = '___'; public const LIMIT_ZERO_MARKER = 'limit0'; - /** - * @var Iterator - */ - private $mongoDbOdmIterator; - /** - * @var array - */ - private $pipeline; - /** - * @var UnitOfWork - */ - private $unitOfWork; - /** - * @var string - */ - private $resourceClass; + private Iterator $mongoDbOdmIterator; - /** @var \ArrayIterator|null */ - private $iterator; + private array $pipeline; - /** - * @var int - */ - private $firstResult; - /** - * @var int - */ - private $maxResults; - /** - * @var int - */ - private $totalItems; + private UnitOfWork $unitOfWork; + + private string $resourceClass; + + private ?\ArrayIterator $iterator; + + private int $firstResult; + + private int $maxResults; + + private int $totalItems; public function __construct(Iterator $mongoDbOdmIterator, UnitOfWork $unitOfWork, string $resourceClass, array $pipeline) { diff --git a/src/Doctrine/Odm/PropertyHelperTrait.php b/src/Doctrine/Odm/PropertyHelperTrait.php index 436293cf694..df849ebbbc1 100644 --- a/src/Doctrine/Odm/PropertyHelperTrait.php +++ b/src/Doctrine/Odm/PropertyHelperTrait.php @@ -31,7 +31,7 @@ trait PropertyHelperTrait /** * Splits the given property into parts. */ - abstract protected function splitPropertyParts(string $property/* , string $resourceClass */): array; + abstract protected function splitPropertyParts(string $property, string $resourceClass): array; /** * Gets class metadata for the given resource. diff --git a/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php b/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php index 511d5adb10d..29ed546d941 100644 --- a/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php +++ b/src/Doctrine/Odm/PropertyInfo/DoctrineExtractor.php @@ -34,7 +34,7 @@ */ final class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface { - private $objectManager; + private ObjectManager $objectManager; public function __construct(ObjectManager $objectManager) { @@ -132,7 +132,7 @@ public function isWritable($class, $property, array $context = []): ?bool { if ( null === ($metadata = $this->getMetadata($class)) - || $metadata instanceof MongoDbClassMetadata && MongoDbClassMetadata::GENERATOR_TYPE_NONE === $metadata->generatorType + || ($metadata instanceof MongoDbClassMetadata && MongoDbClassMetadata::GENERATOR_TYPE_NONE === $metadata->generatorType) || !\in_array($property, $metadata->getIdentifierFieldNames(), true) ) { return null; @@ -155,31 +155,12 @@ private function getMetadata(string $class): ?ClassMetadata */ private function getPhpType(string $doctrineType): ?string { - switch ($doctrineType) { - case MongoDbType::INTEGER: - case MongoDbType::INT: - case MongoDbType::INTID: - case MongoDbType::KEY: - return Type::BUILTIN_TYPE_INT; - case MongoDbType::FLOAT: - return Type::BUILTIN_TYPE_FLOAT; - case MongoDbType::STRING: - case MongoDbType::ID: - case MongoDbType::OBJECTID: - case MongoDbType::TIMESTAMP: - case MongoDbType::BINDATA: - case MongoDbType::BINDATABYTEARRAY: - case MongoDbType::BINDATACUSTOM: - case MongoDbType::BINDATAFUNC: - case MongoDbType::BINDATAMD5: - case MongoDbType::BINDATAUUID: - case MongoDbType::BINDATAUUIDRFC4122: - return Type::BUILTIN_TYPE_STRING; - case MongoDbType::BOOLEAN: - case MongoDbType::BOOL: - return Type::BUILTIN_TYPE_BOOL; - } - - return null; + return match ($doctrineType) { + MongoDbType::INTEGER, MongoDbType::INT, MongoDbType::INTID, MongoDbType::KEY => Type::BUILTIN_TYPE_INT, + MongoDbType::FLOAT => Type::BUILTIN_TYPE_FLOAT, + MongoDbType::STRING, MongoDbType::ID, MongoDbType::OBJECTID, MongoDbType::TIMESTAMP, MongoDbType::BINDATA, MongoDbType::BINDATABYTEARRAY, MongoDbType::BINDATACUSTOM, MongoDbType::BINDATAFUNC, MongoDbType::BINDATAMD5, MongoDbType::BINDATAUUID, MongoDbType::BINDATAUUIDRFC4122 => Type::BUILTIN_TYPE_STRING, + MongoDbType::BOOLEAN, MongoDbType::BOOL => Type::BUILTIN_TYPE_BOOL, + default => null, + }; } } diff --git a/src/Doctrine/Odm/State/CollectionProvider.php b/src/Doctrine/Odm/State/CollectionProvider.php index c4153607a7c..72c56ebc613 100644 --- a/src/Doctrine/Odm/State/CollectionProvider.php +++ b/src/Doctrine/Odm/State/CollectionProvider.php @@ -15,7 +15,6 @@ use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; -use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -32,9 +31,9 @@ final class CollectionProvider implements ProviderInterface { use LinksHandlerTrait; - private $resourceMetadataCollectionFactory; - private $managerRegistry; - private $collectionExtensions; + private ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory; + private ManagerRegistry $managerRegistry; + private iterable $collectionExtensions; /** * @param AggregationCollectionExtensionInterface[] $collectionExtensions @@ -63,20 +62,14 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $this->handleLinks($aggregationBuilder, $uriVariables, $context, $resourceClass, $operation); foreach ($this->collectionExtensions as $extension) { - $extension->applyToCollection($aggregationBuilder, $resourceClass, $operation->getName(), $context); + $extension->applyToCollection($aggregationBuilder, $resourceClass, $operation, $context); - if ($extension instanceof AggregationResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operation->getName(), $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operation->getName(), $context); + if ($extension instanceof AggregationResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operation, $context)) { + return $extension->getResult($aggregationBuilder, $resourceClass, $operation, $context); } } - $resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass); - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operation->getName()); - $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; - } catch (OperationNotFoundException $e) { - $attribute = $resourceMetadata->getOperation(null, true)->getExtraProperties()['doctrine_mongodb'] ?? []; - } + $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; $executeOptions = $attribute['execute_options'] ?? []; return $aggregationBuilder->hydrate($resourceClass)->execute($executeOptions); diff --git a/src/Doctrine/Odm/State/ItemProvider.php b/src/Doctrine/Odm/State/ItemProvider.php index 0549a032c4f..2972610270b 100644 --- a/src/Doctrine/Odm/State/ItemProvider.php +++ b/src/Doctrine/Odm/State/ItemProvider.php @@ -34,9 +34,9 @@ final class ItemProvider implements ProviderInterface { use LinksHandlerTrait; - private $resourceMetadataCollectionFactory; - private $managerRegistry; - private $itemExtensions; + private ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory; + private ManagerRegistry $managerRegistry; + private iterable $itemExtensions; /** * @param AggregationItemExtensionInterface[] $itemExtensions @@ -70,10 +70,10 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $this->handleLinks($aggregationBuilder, $uriVariables, $context, $resourceClass, $operation); foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($aggregationBuilder, $resourceClass, $uriVariables, $operation->getName(), $context); + $extension->applyToItem($aggregationBuilder, $resourceClass, $uriVariables, $operation, $context); - if ($extension instanceof AggregationResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operation->getName(), $context)) { - return $extension->getResult($aggregationBuilder, $resourceClass, $operation->getName(), $context); + if ($extension instanceof AggregationResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operation, $context)) { + return $extension->getResult($aggregationBuilder, $resourceClass, $operation, $context); } } diff --git a/src/Doctrine/Orm/AbstractPaginator.php b/src/Doctrine/Orm/AbstractPaginator.php index f024925012b..36599df1d47 100644 --- a/src/Doctrine/Orm/AbstractPaginator.php +++ b/src/Doctrine/Orm/AbstractPaginator.php @@ -20,10 +20,10 @@ abstract class AbstractPaginator implements \IteratorAggregate, PartialPaginatorInterface { - protected $paginator; - protected $iterator; - protected $firstResult; - protected $maxResults; + protected DoctrinePaginator $paginator; + protected array|\Traversable $iterator; + protected ?int $firstResult; + protected ?int $maxResults; /** * @throws InvalidArgumentException diff --git a/src/Doctrine/Orm/Extension/ContextAwareQueryCollectionExtensionInterface.php b/src/Doctrine/Orm/Extension/ContextAwareQueryCollectionExtensionInterface.php deleted file mode 100644 index abb54bf6899..00000000000 --- a/src/Doctrine/Orm/Extension/ContextAwareQueryCollectionExtensionInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * 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\Doctrine\Orm\Extension; - -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use Doctrine\ORM\QueryBuilder; - -/** - * Context aware extension. - * - * @author Kévin Dunglas - */ -interface ContextAwareQueryCollectionExtensionInterface extends QueryCollectionExtensionInterface -{ - /** - * {@inheritdoc} - */ - public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = []); -} diff --git a/src/Doctrine/Orm/Extension/ContextAwareQueryResultCollectionExtensionInterface.php b/src/Doctrine/Orm/Extension/ContextAwareQueryResultCollectionExtensionInterface.php deleted file mode 100644 index a1dc0fa9900..00000000000 --- a/src/Doctrine/Orm/Extension/ContextAwareQueryResultCollectionExtensionInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\Doctrine\Orm\Extension; - -use Doctrine\ORM\QueryBuilder; - -/** - * Context aware extension. - * - * @author Kévin Dunglas - */ -interface ContextAwareQueryResultCollectionExtensionInterface extends QueryResultCollectionExtensionInterface -{ - /** - * {@inheritdoc} - */ - public function supportsResult(string $resourceClass, string $operationName = null, array $context = []): bool; - - /** - * {@inheritdoc} - */ - public function getResult(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null, array $context = []); -} diff --git a/src/Doctrine/Orm/Extension/ContextAwareQueryResultItemExtensionInterface.php b/src/Doctrine/Orm/Extension/ContextAwareQueryResultItemExtensionInterface.php deleted file mode 100644 index 554563e93e6..00000000000 --- a/src/Doctrine/Orm/Extension/ContextAwareQueryResultItemExtensionInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\Doctrine\Orm\Extension; - -use Doctrine\ORM\QueryBuilder; - -/** - * Context aware extension. - * - * @author Kévin Dunglas - */ -interface ContextAwareQueryResultItemExtensionInterface extends QueryResultItemExtensionInterface -{ - /** - * {@inheritdoc} - */ - public function supportsResult(string $resourceClass, string $operationName = null, array $context = []): bool; - - /** - * {@inheritdoc} - */ - public function getResult(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null, array $context = []); -} diff --git a/src/Doctrine/Orm/Extension/EagerLoadingExtension.php b/src/Doctrine/Orm/Extension/EagerLoadingExtension.php index a3f224bfd3e..61641a8124b 100644 --- a/src/Doctrine/Orm/Extension/EagerLoadingExtension.php +++ b/src/Doctrine/Orm/Extension/EagerLoadingExtension.php @@ -13,19 +13,15 @@ namespace ApiPlatform\Doctrine\Orm\Extension; -use ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Exception\PropertyNotFoundException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Property\PropertyMetadata; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Query\Expr\Join; @@ -43,20 +39,17 @@ * @author Antoine Bluchet * @author Baptiste Meyer */ -final class EagerLoadingExtension implements ContextAwareQueryCollectionExtensionInterface, QueryItemExtensionInterface +final class EagerLoadingExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface { - use EagerLoadingTrait; + private PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory; + private PropertyMetadataFactoryInterface $propertyMetadataFactory; + private ?ClassMetadataFactoryInterface $classMetadataFactory; + private int $maxJoins; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - private $classMetadataFactory; - private $maxJoins; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, int $maxJoins = 30, bool $forceEager = true, bool $fetchPartial = false, ClassMetadataFactoryInterface $classMetadataFactory = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, int $maxJoins = 30, bool $forceEager = true, bool $fetchPartial = false, ClassMetadataFactoryInterface $classMetadataFactory = null) { $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->classMetadataFactory = $classMetadataFactory; $this->maxJoins = $maxJoins; $this->forceEager = $forceEager; @@ -66,9 +59,9 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName /** * {@inheritdoc} */ - public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass = null, string $operationName = null, array $context = []) + public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass = null, Operation $operation = null, array $context = []): void { - $this->apply(true, $queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); + $this->apply($queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); } /** @@ -76,34 +69,21 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator * * The context may contain serialization groups which helps defining joined entities that are readable. */ - public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []) + public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, Operation $operation = null, array $context = []): void { - $this->apply(false, $queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); + $this->apply($queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); } - private function apply(bool $collection, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, ?string $resourceClass, ?string $operationName, array $context) + private function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, ?string $resourceClass, ?Operation $operation, array $context): void { if (null === $resourceClass) { throw new InvalidArgumentException('The "$resourceClass" parameter must not be null'); } $options = []; - if (null !== $operationName) { - // TODO remove in 3.0 - $options[($collection ? 'collection' : 'item').'_operation_name'] = $operationName; - } - $operation = null; - $forceEager = $this->forceEager; - $fetchPartial = $this->fetchPartial; - $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $resourceMetadataCollection->getOperation($operationName); - $forceEager = $operation->getForceEager() ?? $this->forceEager; - $fetchPartial = $operation->getFetchPartial() ?? $this->fetchPartial; - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - } + $forceEager = $operation?->getForceEager() ?? $this->forceEager; + $fetchPartial = $operation?->getFetchPartial() ?? $this->fetchPartial; if (!isset($context['groups']) && !isset($context['attributes'])) { $contextType = isset($context['api_denormalize']) ? 'denormalization_context' : 'normalization_context'; @@ -140,7 +120,7 @@ private function apply(bool $collection, QueryBuilder $queryBuilder, QueryNameGe * * @throws RuntimeException when the max number of joins has been reached */ - private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, bool $forceEager, bool $fetchPartial, string $parentAlias, array $options = [], array $normalizationContext = [], bool $wasLeftJoin = false, int &$joinCount = 0, int $currentDepth = null, string $parentAssociation = null) + private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, bool $forceEager, bool $fetchPartial, string $parentAlias, array $options = [], array $normalizationContext = [], bool $wasLeftJoin = false, int &$joinCount = 0, int $currentDepth = null, string $parentAssociation = null): void { if ($joinCount > $this->maxJoins) { throw new RuntimeException('The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary with the "api_platform.eager_loading.max_joins" configuration key (https://api-platform.com/docs/core/performance/#eager-loading), or limit the maximum serialization depth using the "enable_max_depth" option of the Symfony serializer (https://symfony.com/doc/current/components/serializer.html#handling-serialization-depth).'); @@ -149,7 +129,7 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt $currentDepth = $currentDepth > 0 ? $currentDepth - 1 : $currentDepth; $entityManager = $queryBuilder->getEntityManager(); $classMetadata = $entityManager->getClassMetadata($resourceClass); - $attributesMetadata = $this->classMetadataFactory ? $this->classMetadataFactory->getMetadataFor($resourceClass)->getAttributesMetadata() : null; + $attributesMetadata = $this->classMetadataFactory?->getMetadataFor($resourceClass)->getAttributesMetadata(); foreach ($classMetadata->associationMappings as $association => $mapping) { // Don't join if max depth is enabled and the current depth limit is reached @@ -255,7 +235,7 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt } } - private function addSelect(QueryBuilder $queryBuilder, string $entity, string $associationAlias, array $propertyMetadataOptions) + private function addSelect(QueryBuilder $queryBuilder, string $entity, string $associationAlias, array $propertyMetadataOptions): void { $select = []; $entityManager = $queryBuilder->getEntityManager(); @@ -267,7 +247,6 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a } foreach ($this->propertyNameCollectionFactory->create($entity) as $property) { - /** @var ApiProperty|PropertyMetadata */ $propertyMetadata = $this->propertyMetadataFactory->create($entity, $property, $propertyMetadataOptions); if (true === $propertyMetadata->isIdentifier()) { @@ -300,7 +279,7 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a $queryBuilder->addSelect(sprintf('partial %s.{%s}', $associationAlias, implode(',', $select))); } - private function addSelectOnce(QueryBuilder $queryBuilder, string $alias) + private function addSelectOnce(QueryBuilder $queryBuilder, string $alias): void { $existingSelects = array_reduce($queryBuilder->getDQLPart('select') ?? [], function ($existing, $dqlSelect) { return ($dqlSelect instanceof Select) ? array_merge($existing, $dqlSelect->getParts()) : $existing; @@ -310,24 +289,4 @@ private function addSelectOnce(QueryBuilder $queryBuilder, string $alias) $queryBuilder->addSelect($alias); } } - - /** - * Gets the serializer context. - * - * @param string $contextType normalization_context or denormalization_context - * @param array $options represents the operation name so that groups are the one of the specific operation - */ - private function getNormalizationContext(string $resourceClass, string $contextType, array $options): array - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (isset($options['collection_operation_name'])) { - $context = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], $contextType, null, true); - } elseif (isset($options['item_operation_name'])) { - $context = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], $contextType, null, true); - } else { - $context = $resourceMetadata->getAttribute($contextType); - } - - return $context ?? []; - } } diff --git a/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php b/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php index 453f1146c73..55c81125eb1 100644 --- a/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php +++ b/src/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php @@ -14,15 +14,12 @@ namespace ApiPlatform\Doctrine\Orm\Extension; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Doctrine\Orm\Util\EagerLoadingTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation; -use ApiPlatform\Metadata\HttpOperation; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Operation; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; @@ -30,19 +27,13 @@ * Fixes filters on OneToMany associations * https://github.com/api-platform/core/issues/944. */ -final class FilterEagerLoadingExtension implements ContextAwareQueryCollectionExtensionInterface +final class FilterEagerLoadingExtension implements QueryCollectionExtensionInterface { - use EagerLoadingTrait; + private ?ResourceClassResolverInterface $resourceClassResolver; + private bool $forceEager; - private $resourceClassResolver; - - public function __construct($resourceMetadataFactory, bool $forceEager = true, ResourceClassResolverInterface $resourceClassResolver = null) + public function __construct(bool $forceEager = true, ResourceClassResolverInterface $resourceClassResolver = null) { - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->forceEager = $forceEager; $this->resourceClassResolver = $resourceClassResolver; } @@ -50,7 +41,7 @@ public function __construct($resourceMetadataFactory, bool $forceEager = true, R /** * {@inheritdoc} */ - public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass = null, string $operationName = null, array $context = []) + public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass = null, Operation $operation = null, array $context = []): void { if (null === $resourceClass) { throw new InvalidArgumentException('The "$resourceClass" parameter must not be null'); @@ -58,27 +49,11 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator $em = $queryBuilder->getEntityManager(); $classMetadata = $em->getClassMetadata($resourceClass); - /** @var HttpOperation|GraphQlOperation|null */ - $operation = null; - $forceEager = $this->forceEager; - - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - try { - $operation = $resourceMetadataCollection->getOperation($operationName); - $forceEager = $operation->getForceEager() ?? $this->forceEager; - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - } - if (!$forceEager && !$this->hasFetchEagerAssociation($em, $classMetadata)) { - return; - } - } else { - // TODO: remove in 3.0 - if (!$this->shouldOperationForceEager($resourceClass, ['collection_operation_name' => $operationName]) && !$this->hasFetchEagerAssociation($em, $classMetadata)) { - return; - } + $forceEager = $operation?->getForceEager() ?? $this->forceEager; + + if (!$forceEager && !$this->hasFetchEagerAssociation($em, $classMetadata)) { + return; } // If no where part, nothing to do @@ -136,6 +111,34 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator $queryBuilder->add('where', $queryBuilderClone->getDQLPart('where')); } + /** + * Checks if the class has an associationMapping with FETCH=EAGER. + * + * @param array $checked array cache of tested metadata classes + */ + private function hasFetchEagerAssociation(EntityManagerInterface $em, ClassMetadataInfo $classMetadata, array &$checked = []): bool + { + $checked[] = $classMetadata->name; + + foreach ($classMetadata->getAssociationMappings() as $mapping) { + if (ClassMetadataInfo::FETCH_EAGER === $mapping['fetch']) { + return true; + } + + $related = $em->getClassMetadata($mapping['targetEntity']); + + if (\in_array($related->name, $checked, true)) { + continue; + } + + if (true === $this->hasFetchEagerAssociation($em, $related, $checked)) { + return true; + } + } + + return false; + } + /** * Returns a clone of the given query builder where everything gets re-aliased. * diff --git a/src/Doctrine/Orm/Extension/FilterExtension.php b/src/Doctrine/Orm/Extension/FilterExtension.php index ceb898ad47f..f1ccbde02c2 100644 --- a/src/Doctrine/Orm/Extension/FilterExtension.php +++ b/src/Doctrine/Orm/Extension/FilterExtension.php @@ -13,17 +13,11 @@ namespace ApiPlatform\Doctrine\Orm\Extension; -use ApiPlatform\Api\FilterLocatorTrait; -use ApiPlatform\Core\Api\FilterCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Doctrine\Orm\Filter\FilterInterface; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; use Psr\Container\ContainerInterface; @@ -33,52 +27,25 @@ * @author Kévin Dunglas * @author Samuel ROZE */ -final class FilterExtension implements ContextAwareQueryCollectionExtensionInterface +final class FilterExtension implements QueryCollectionExtensionInterface { - use FilterLocatorTrait; + private ContainerInterface $filterLocator; - private $resourceMetadataFactory; - - /** - * @param ContainerInterface|FilterCollection $filterLocator The new filter locator or the deprecated filter collection - * @param mixed $resourceMetadataFactory - */ - public function __construct($resourceMetadataFactory, $filterLocator) + public function __construct(ContainerInterface $filterLocator) { - $this->setFilterLocator($filterLocator); - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; + $this->filterLocator = $filterLocator; } /** * {@inheritdoc} */ - public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass = null, string $operationName = null, array $context = []) + public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass = null, Operation $operation = null, array $context = []): void { if (null === $resourceClass) { throw new InvalidArgumentException('The "$resourceClass" parameter must not be null'); } - /** @var ResourceMetadata|ResourceMetadataCollection */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadata instanceof ResourceMetadata) { - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); - } else { - try { - $operation = $context['operation'] ?? $resourceMetadata->getOperation($operationName); - $resourceFilters = $operation->getFilters(); - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - if (isset($context['graphql_operation_name'])) { - $resourceFilters = $resourceMetadata->getOperation(null, true)->getFilters(); - } - } - } + $resourceFilters = $operation?->getFilters(); if (empty($resourceFilters)) { return; @@ -87,7 +54,7 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator $orderFilters = []; foreach ($resourceFilters as $filterId) { - $filter = $this->getFilter($filterId); + $filter = $this->filterLocator->has($filterId) ? $this->filterLocator->get($filterId) : null; if ($filter instanceof FilterInterface) { // Apply the OrderFilter after every other filter to avoid an edge case where OrderFilter would do a LEFT JOIN instead of an INNER JOIN if ($filter instanceof OrderFilter) { @@ -96,13 +63,13 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator } $context['filters'] = $context['filters'] ?? []; - $filter->apply($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); + $filter->apply($queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); } } foreach ($orderFilters as $orderFilter) { $context['filters'] = $context['filters'] ?? []; - $orderFilter->apply($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); + $orderFilter->apply($queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); } } } diff --git a/src/Doctrine/Orm/Extension/OrderExtension.php b/src/Doctrine/Orm/Extension/OrderExtension.php index b8a29f4e0d5..34297b1f006 100644 --- a/src/Doctrine/Orm/Extension/OrderExtension.php +++ b/src/Doctrine/Orm/Extension/OrderExtension.php @@ -13,12 +13,10 @@ namespace ApiPlatform\Doctrine\Orm\Extension; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; /** @@ -28,29 +26,19 @@ * @author Samuel ROZE * @author Vincent Chalamon */ -final class OrderExtension implements ContextAwareQueryCollectionExtensionInterface +final class OrderExtension implements QueryCollectionExtensionInterface { - private $order; - private $resourceMetadataFactory; + private ?string $order; - /** - * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory - */ - public function __construct(string $order = null, $resourceMetadataFactory = null) + public function __construct(string $order = null) { - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if ($this->resourceMetadataFactory && $this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->order = $order; } /** * {@inheritdoc} */ - public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass = null, string $operationName = null, array $context = []) + public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass = null, Operation $operation = null, array $context = []): void { if (null === $resourceClass) { throw new InvalidArgumentException('The "$resourceClass" parameter must not be null'); @@ -66,41 +54,28 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator $classMetaData = $queryBuilder->getEntityManager()->getClassMetadata($resourceClass); $identifiers = $classMetaData->getIdentifier(); - if (null !== $this->resourceMetadataFactory) { - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - try { - $defaultOrder = $resourceMetadataCollection->getOperation($operationName)->getOrder() ?? []; - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - $defaultOrder = []; + $defaultOrder = $operation?->getOrder() ?? []; + + if ([] !== $defaultOrder) { + foreach ($defaultOrder as $field => $order) { + if (\is_int($field)) { + // Default direction + $field = $order; + $order = 'ASC'; } - } else { - // TODO: remove in 3.0 - $defaultOrder = $this->resourceMetadataFactory->create($resourceClass)->getCollectionOperationAttribute($operationName, 'order', [], true); - } - if (null !== $defaultOrder && [] !== $defaultOrder) { - foreach ($defaultOrder as $field => $order) { - if (\is_int($field)) { - // Default direction - $field = $order; - $order = 'ASC'; - } - - $pos = strpos($field, '.'); - if (false === $pos || isset($classMetaData->embeddedClasses[substr($field, 0, $pos)])) { - // Configure default filter with property - $field = "{$rootAlias}.{$field}"; - } else { - $alias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $rootAlias, substr($field, 0, $pos)); - $field = sprintf('%s.%s', $alias, substr($field, $pos + 1)); - } - $queryBuilder->addOrderBy($field, $order); + $pos = strpos($field, '.'); + if (false === $pos || isset($classMetaData->embeddedClasses[substr($field, 0, $pos)])) { + // Configure default filter with property + $field = "{$rootAlias}.{$field}"; + } else { + $alias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $rootAlias, substr($field, 0, $pos)); + $field = sprintf('%s.%s', $alias, substr($field, $pos + 1)); } - - return; + $queryBuilder->addOrderBy($field, $order); } + + return; } if (null !== $this->order) { diff --git a/src/Doctrine/Orm/Extension/PaginationExtension.php b/src/Doctrine/Orm/Extension/PaginationExtension.php index 10259f41b27..8873772c2c4 100644 --- a/src/Doctrine/Orm/Extension/PaginationExtension.php +++ b/src/Doctrine/Orm/Extension/PaginationExtension.php @@ -13,24 +13,17 @@ namespace ApiPlatform\Doctrine\Orm\Extension; -use ApiPlatform\Core\DataProvider\Pagination as LegacyPagination; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Doctrine\Orm\AbstractPaginator; use ApiPlatform\Doctrine\Orm\Paginator; use ApiPlatform\Doctrine\Orm\Util\QueryChecker; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Operation; use ApiPlatform\State\Pagination\Pagination; use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\Tools\Pagination\CountWalker; use Doctrine\ORM\Tools\Pagination\Paginator as DoctrineOrmPaginator; use Doctrine\Persistence\ManagerRegistry; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; // Help opcache.preload discover always-needed symbols class_exists(AbstractPaginator::class); @@ -41,91 +34,23 @@ class_exists(AbstractPaginator::class); * @author Kévin Dunglas * @author Samuel ROZE */ -final class PaginationExtension implements ContextAwareQueryResultCollectionExtensionInterface +final class PaginationExtension implements QueryResultCollectionExtensionInterface { - private $managerRegistry; - private $requestStack; - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface - */ - private $resourceMetadataFactory; - private $enabled; - private $clientEnabled; - private $clientItemsPerPage; - private $itemsPerPage; - private $pageParameterName; - private $enabledParameterName; - private $itemsPerPageParameterName; - private $maximumItemPerPage; - private $partial; - private $clientPartial; - private $partialParameterName; - /** - * @var Pagination|null - */ - private $pagination; + private ManagerRegistry $managerRegistry; + private ?Pagination $pagination; - /** - * @param ResourceMetadataFactoryInterface|RequestStack $resourceMetadataFactory - * @param Pagination|ResourceMetadataFactoryInterface $pagination - */ - public function __construct(ManagerRegistry $managerRegistry, /* ResourceMetadataCollectionFactoryInterface */ $resourceMetadataFactory, /* Pagination */ $pagination) + public function __construct(ManagerRegistry $managerRegistry, Pagination $pagination) { - if ($resourceMetadataFactory instanceof RequestStack && $pagination instanceof ResourceMetadataFactoryInterface) { - @trigger_error(sprintf('Passing an instance of "%s" as second argument of "%s" is deprecated since API Platform 2.4 and will not be possible anymore in API Platform 3. Pass an instance of "%s" instead.', RequestStack::class, self::class, ResourceMetadataFactoryInterface::class), \E_USER_DEPRECATED); - @trigger_error(sprintf('Passing an instance of "%s" as third argument of "%s" is deprecated since API Platform 2.4 and will not be possible anymore in API Platform 3. Pass an instance of "%s" instead.', ResourceMetadataFactoryInterface::class, self::class, Pagination::class), \E_USER_DEPRECATED); - - $this->requestStack = $resourceMetadataFactory; - $resourceMetadataFactory = $pagination; - $pagination = null; - - $args = \array_slice(\func_get_args(), 3); - $legacyPaginationArgs = [ - ['arg_name' => 'enabled', 'type' => 'bool', 'default' => true], - ['arg_name' => 'clientEnabled', 'type' => 'bool', 'default' => false], - ['arg_name' => 'clientItemsPerPage', 'type' => 'bool', 'default' => false], - ['arg_name' => 'itemsPerPage', 'type' => 'int', 'default' => 30], - ['arg_name' => 'pageParameterName', 'type' => 'string', 'default' => 'page'], - ['arg_name' => 'enabledParameterName', 'type' => 'string', 'default' => 'pagination'], - ['arg_name' => 'itemsPerPageParameterName', 'type' => 'string', 'default' => 'itemsPerPage'], - ['arg_name' => 'maximumItemPerPage', 'type' => 'int', 'default' => null], - ['arg_name' => 'partial', 'type' => 'bool', 'default' => false], - ['arg_name' => 'clientPartial', 'type' => 'bool', 'default' => false], - ['arg_name' => 'partialParameterName', 'type' => 'string', 'default' => 'partial'], - ]; - - foreach ($legacyPaginationArgs as $pos => $arg) { - if (\array_key_exists($pos, $args)) { - @trigger_error(sprintf('Passing "$%s" arguments is deprecated since API Platform 2.4 and will not be possible anymore in API Platform 3. Pass an instance of "%s" as third argument instead.', implode('", "$', array_column($legacyPaginationArgs, 'arg_name')), Paginator::class), \E_USER_DEPRECATED); - - if (!((null === $arg['default'] && null === $args[$pos]) || \call_user_func("is_{$arg['type']}", $args[$pos]))) { - throw new InvalidArgumentException(sprintf('The "$%s" argument is expected to be a %s%s.', $arg['arg_name'], $arg['type'], null === $arg['default'] ? ' or null' : '')); - } - - $value = $args[$pos]; - } else { - $value = $arg['default']; - } - - $this->{$arg['arg_name']} = $value; - } - } elseif (!$resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - throw new InvalidArgumentException(sprintf('The "$resourceMetadataFactory" argument is expected to be an implementation of the "%s" interface.', ResourceMetadataFactoryInterface::class)); - } elseif (!$pagination instanceof Pagination && !$pagination instanceof LegacyPagination) { // @phpstan-ignore-line - throw new InvalidArgumentException(sprintf('The "$pagination" argument is expected to be an instance of the "%s" class, "%s" given.', Pagination::class, \get_class($pagination))); - } - $this->managerRegistry = $managerRegistry; - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->pagination = $pagination; } /** * {@inheritdoc} */ - public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = []) + public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { - if (null === $pagination = $this->getPagination($queryBuilder, $resourceClass, $operationName, $context)) { + if (null === $pagination = $this->getPagination($queryBuilder, $operation, $context)) { return; } @@ -139,27 +64,19 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator /** * {@inheritdoc} */ - public function supportsResult(string $resourceClass, string $operationName = null, array $context = []): bool + public function supportsResult(string $resourceClass, Operation $operation = null, array $context = []): bool { if ($context['graphql_operation_name'] ?? false) { - return $this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context); + return $this->pagination->isGraphQlEnabled($operation, $context); } - if (null === $this->requestStack) { - return $this->pagination->isEnabled($resourceClass, $operationName, $context); - } - - if (null === $request = $this->requestStack->getCurrentRequest()) { - return false; - } - - return $this->isPaginationEnabled($request, $this->resourceMetadataFactory->create($resourceClass), $operationName); + return $this->pagination->isEnabled($operation, $context); } /** * {@inheritdoc} */ - public function getResult(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null, array $context = []): iterable + public function getResult(QueryBuilder $queryBuilder, string $resourceClass = null, Operation $operation = null, array $context = []): iterable { $query = $queryBuilder->getQuery(); @@ -168,18 +85,10 @@ public function getResult(QueryBuilder $queryBuilder, string $resourceClass = nu $query->setHint(CountWalker::HINT_DISTINCT, false); } - $doctrineOrmPaginator = new DoctrineOrmPaginator($query, $this->shouldDoctrinePaginatorFetchJoinCollection($queryBuilder, $resourceClass, $operationName, $context)); - $doctrineOrmPaginator->setUseOutputWalkers($this->shouldDoctrinePaginatorUseOutputWalkers($queryBuilder, $resourceClass, $operationName, $context)); - - if (null === $this->requestStack) { - $isPartialEnabled = $this->pagination->isPartialEnabled($resourceClass, $operationName, $context); - } else { - $isPartialEnabled = $this->isPartialPaginationEnabled( - $this->requestStack->getCurrentRequest(), - null === $resourceClass ? null : $this->resourceMetadataFactory->create($resourceClass), - $operationName - ); - } + $doctrineOrmPaginator = new DoctrineOrmPaginator($query, $this->shouldDoctrinePaginatorFetchJoinCollection($queryBuilder, $operation, $context)); + $doctrineOrmPaginator->setUseOutputWalkers($this->shouldDoctrinePaginatorUseOutputWalkers($queryBuilder, $operation, $context)); + + $isPartialEnabled = $this->pagination->isPartialEnabled($operation, $context); if ($isPartialEnabled) { return new class($doctrineOrmPaginator) extends AbstractPaginator { @@ -192,158 +101,17 @@ public function getResult(QueryBuilder $queryBuilder, string $resourceClass = nu /** * @throws InvalidArgumentException */ - private function getPagination(QueryBuilder $queryBuilder, string $resourceClass, ?string $operationName, array $context): ?array + private function getPagination(QueryBuilder $queryBuilder, ?Operation $operation, array $context): ?array { - $request = null; - if (null !== $this->requestStack && null === $request = $this->requestStack->getCurrentRequest()) { - return null; - } - - if (null === $request) { - $enabled = isset($context['graphql_operation_name']) ? $this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context) : $this->pagination->isEnabled($resourceClass, $operationName, $context); - - if (!$enabled) { - return null; - } - - $context = $this->addCountToContext($queryBuilder, $context); + $enabled = isset($context['graphql_operation_name']) ? $this->pagination->isGraphQlEnabled($operation, $context) : $this->pagination->isEnabled($operation, $context); - return \array_slice($this->pagination->getPagination($resourceClass, $operationName, $context), 1); - } - - /** - * @var ResourceMetadata|ResourceMetadataCollection - */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (!$this->isPaginationEnabled($request, $resourceMetadata, $operationName)) { + if (!$enabled) { return null; } - $itemsPerPage = $this->itemsPerPage; - $maxItemsPerPage = $this->maximumItemPerPage; - - // TODO: remove in 3.0 - if ($resourceMetadata instanceof ResourceMetadata) { - $itemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', $this->itemsPerPage, true); - if ($request->attributes->getBoolean('_graphql', false)) { - $collectionArgs = $request->attributes->get('_graphql_collections_args', []); - $itemsPerPage = $collectionArgs[$resourceClass]['first'] ?? $itemsPerPage; - } - - if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) { - $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'maximum_items_per_page', null, true); - - if (null !== $maxItemsPerPage) { - @trigger_error('The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3.', \E_USER_DEPRECATED); - } - - $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage ?? $this->maximumItemPerPage, true); - $itemsPerPage = (int) $this->getPaginationParameter($request, $this->itemsPerPageParameterName, $itemsPerPage); - $itemsPerPage = (null !== $maxItemsPerPage && $itemsPerPage >= $maxItemsPerPage ? $maxItemsPerPage : $itemsPerPage); - } - } elseif ($resourceMetadata instanceof ResourceMetadataCollection) { - try { - $operation = $resourceMetadata->getOperation($operationName); - $itemsPerPage = $operation->getPaginationItemsPerPage(); - if ($operation->getPaginationClientItemsPerPage()) { - $maxItemsPerPage = $operation->getPaginationMaximumItemsPerPage() ?? $this->maximumItemPerPage; - $itemsPerPage = (int) $this->getPaginationParameter($request, $this->itemsPerPageParameterName, $itemsPerPage); - $itemsPerPage = (null !== $maxItemsPerPage && $itemsPerPage >= $maxItemsPerPage ? $maxItemsPerPage : $itemsPerPage); - } - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - } - - if ($request->attributes->getBoolean('_graphql', false)) { - $collectionArgs = $request->attributes->get('_graphql_collections_args', []); - $itemsPerPage = $collectionArgs[$resourceClass]['first'] ?? $itemsPerPage; - } - } - - if (0 > $itemsPerPage) { - throw new InvalidArgumentException('Item per page parameter should not be less than 0'); - } - - $page = (int) $this->getPaginationParameter($request, $this->pageParameterName, 1); - - if (1 > $page) { - throw new InvalidArgumentException('Page should not be less than 1'); - } - - if (0 === $itemsPerPage && 1 < $page) { - throw new InvalidArgumentException('Page should not be greater than 1 if itemsPerPage is equal to 0'); - } - - $firstResult = ($page - 1) * $itemsPerPage; - if ($request->attributes->getBoolean('_graphql', false)) { - $collectionArgs = $request->attributes->get('_graphql_collections_args', []); - if (isset($collectionArgs[$resourceClass]['after'])) { - $after = base64_decode($collectionArgs[$resourceClass]['after'], true); - $firstResult = (int) $after; - $firstResult = false === $after ? $firstResult : ++$firstResult; - } - } - - return [$firstResult, $itemsPerPage]; - } - - /** - * @param ResourceMetadata|ResourceMetadataCollection $resourceMetadata - */ - private function isPartialPaginationEnabled(Request $request = null, $resourceMetadata = null, string $operationName = null): bool - { - $enabled = $this->partial; - $clientEnabled = $this->clientPartial; - - if ($resourceMetadata instanceof ResourceMetadata) { - $enabled = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_partial', $enabled, true); - - if ($request) { - $clientEnabled = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_partial', $clientEnabled, true); - } - } elseif ($resourceMetadata instanceof ResourceMetadataCollection) { - $operation = $resourceMetadata->getOperation($operationName); - $enabled = $operation->getPaginationPartial() ?? $enabled; - $clientEnabled = $operation->getPaginationClientPartial() ?? $clientEnabled; - } - - if ($clientEnabled && $request) { - $enabled = filter_var($this->getPaginationParameter($request, $this->partialParameterName, $enabled), \FILTER_VALIDATE_BOOLEAN); - } + $context = $this->addCountToContext($queryBuilder, $context); - return $enabled; - } - - /** - * @param ResourceMetadata|ResourceMetadataCollection $resourceMetadata - */ - private function isPaginationEnabled(Request $request, $resourceMetadata, string $operationName = null): bool - { - $clientEnabled = false; - $enabled = false; - if ($resourceMetadata instanceof ResourceMetadata) { - $enabled = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_enabled', $this->enabled, true); - $clientEnabled = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_enabled', $this->clientEnabled, true); - } elseif ($resourceMetadata instanceof ResourceMetadataCollection) { - $operation = $resourceMetadata->getOperation($operationName); - $enabled = $operation->getPaginationEnabled(); - $clientEnabled = $operation->getPaginationClientEnabled(); - } - - if ($clientEnabled) { - $enabled = filter_var($this->getPaginationParameter($request, $this->enabledParameterName, $enabled), \FILTER_VALIDATE_BOOLEAN); - } - - return $enabled; - } - - private function getPaginationParameter(Request $request, string $parameterName, $default = null) - { - if (null !== $paginationAttribute = $request->attributes->get('_api_pagination')) { - return \array_key_exists($parameterName, $paginationAttribute) ? $paginationAttribute[$parameterName] : $default; - } - - return $request->query->all()[$parameterName] ?? $default; + return \array_slice($this->pagination->getPagination($operation, $context), 1); } private function addCountToContext(QueryBuilder $queryBuilder, array $context): array @@ -362,37 +130,16 @@ private function addCountToContext(QueryBuilder $queryBuilder, array $context): /** * Determines the value of the $fetchJoinCollection argument passed to the Doctrine ORM Paginator. */ - private function shouldDoctrinePaginatorFetchJoinCollection(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null, array $context = []): bool + private function shouldDoctrinePaginatorFetchJoinCollection(QueryBuilder $queryBuilder, Operation $operation = null, array $context = []): bool { - if (null !== $resourceClass) { - /** - * @var ResourceMetadata|ResourceMetadataCollection - */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadata instanceof ResourceMetadata) { - $fetchJoinCollection = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_fetch_join_collection', null, true); - } elseif ($resourceMetadata instanceof ResourceMetadataCollection) { - try { - $operation = $resourceMetadata->getOperation($operationName); - $fetchJoinCollection = $operation->getPaginationFetchJoinCollection(); - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - $fetchJoinCollection = null; - } - } - - if ((isset($context['collection_operation_name']) || isset($context['operation_name'])) && isset($fetchJoinCollection)) { - return $fetchJoinCollection; - } - - if ($resourceMetadata instanceof ResourceMetadata) { - $fetchJoinCollection = $resourceMetadata->getGraphqlAttribute($operationName, 'pagination_fetch_join_collection', null, true); - } - - if (isset($context['graphql_operation_name']) && isset($fetchJoinCollection)) { - return $fetchJoinCollection; - } + $fetchJoinCollection = $operation?->getPaginationFetchJoinCollection(); + + if ((isset($context['collection_operation_name']) || isset($context['operation_name'])) && isset($fetchJoinCollection)) { + return $fetchJoinCollection; + } + + if (isset($context['graphql_operation_name']) && isset($fetchJoinCollection)) { + return $fetchJoinCollection; } /* @@ -416,36 +163,16 @@ private function shouldDoctrinePaginatorFetchJoinCollection(QueryBuilder $queryB /** * Determines whether the Doctrine ORM Paginator should use output walkers. */ - private function shouldDoctrinePaginatorUseOutputWalkers(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null, array $context = []): bool + private function shouldDoctrinePaginatorUseOutputWalkers(QueryBuilder $queryBuilder, Operation $operation = null, array $context = []): bool { - if (null !== $resourceClass) { - /** - * @var ResourceMetadata|ResourceMetadataCollection - */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadata instanceof ResourceMetadata) { - $useOutputWalkers = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_use_output_walkers', null, true); - } elseif ($resourceMetadata instanceof ResourceMetadataCollection) { - try { - $operation = $resourceMetadata->getOperation($operationName); - $useOutputWalkers = $operation->getPaginationUseOutputWalkers(); - } catch (OperationNotFoundException $e) { - // In some cases the operation may not exist - } - } - - if ((isset($context['collection_operation_name']) || isset($context['operation_name'])) && isset($useOutputWalkers)) { - return $useOutputWalkers; - } - - if ($resourceMetadata instanceof ResourceMetadata) { - $useOutputWalkers = $resourceMetadata->getGraphqlAttribute($operationName, 'pagination_use_output_walkers', null, true); - } - - if (isset($context['graphql_operation_name']) && isset($useOutputWalkers)) { - return $useOutputWalkers; - } + $useOutputWalkers = $operation?->getPaginationUseOutputWalkers(); + + if ((isset($context['collection_operation_name']) || isset($context['operation_name'])) && isset($useOutputWalkers)) { + return $useOutputWalkers; + } + + if (isset($context['graphql_operation_name']) && isset($useOutputWalkers)) { + return $useOutputWalkers; } /* diff --git a/src/Doctrine/Orm/Extension/QueryCollectionExtensionInterface.php b/src/Doctrine/Orm/Extension/QueryCollectionExtensionInterface.php index 4d7c58447c1..cb386135ea3 100644 --- a/src/Doctrine/Orm/Extension/QueryCollectionExtensionInterface.php +++ b/src/Doctrine/Orm/Extension/QueryCollectionExtensionInterface.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Orm\Extension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; /** @@ -24,5 +25,5 @@ */ interface QueryCollectionExtensionInterface { - public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null); + public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void; } diff --git a/src/Doctrine/Orm/Extension/QueryItemExtensionInterface.php b/src/Doctrine/Orm/Extension/QueryItemExtensionInterface.php index 3765a9944ee..f337ebc4762 100644 --- a/src/Doctrine/Orm/Extension/QueryItemExtensionInterface.php +++ b/src/Doctrine/Orm/Extension/QueryItemExtensionInterface.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Orm\Extension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; /** @@ -24,5 +25,5 @@ */ interface QueryItemExtensionInterface { - public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []); + public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, Operation $operation = null, array $context = []): void; } diff --git a/src/Doctrine/Orm/Extension/QueryResultCollectionExtensionInterface.php b/src/Doctrine/Orm/Extension/QueryResultCollectionExtensionInterface.php index 331bca4b122..c5a971f5945 100644 --- a/src/Doctrine/Orm/Extension/QueryResultCollectionExtensionInterface.php +++ b/src/Doctrine/Orm/Extension/QueryResultCollectionExtensionInterface.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Orm\Extension; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; /** @@ -24,10 +25,10 @@ */ interface QueryResultCollectionExtensionInterface extends QueryCollectionExtensionInterface { - public function supportsResult(string $resourceClass, string $operationName = null): bool; + public function supportsResult(string $resourceClass, Operation $operation = null, array $context = []): bool; /** * @return iterable */ - public function getResult(QueryBuilder $queryBuilder); + public function getResult(QueryBuilder $queryBuilder, string $resourceClass = null, Operation $operation = null, array $context = []); } diff --git a/src/Doctrine/Orm/Extension/QueryResultItemExtensionInterface.php b/src/Doctrine/Orm/Extension/QueryResultItemExtensionInterface.php index dad0ece3012..783776345e1 100644 --- a/src/Doctrine/Orm/Extension/QueryResultItemExtensionInterface.php +++ b/src/Doctrine/Orm/Extension/QueryResultItemExtensionInterface.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Doctrine\Orm\Extension; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; /** @@ -23,10 +24,10 @@ */ interface QueryResultItemExtensionInterface extends QueryItemExtensionInterface { - public function supportsResult(string $resourceClass, string $operationName = null): bool; + public function supportsResult(string $resourceClass, Operation $operation = null, array $context = []): bool; /** * @return object|null */ - public function getResult(QueryBuilder $queryBuilder); + public function getResult(QueryBuilder $queryBuilder, string $resourceClass = null, Operation $operation = null, array $context = []); } diff --git a/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php b/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php deleted file mode 100644 index 4385d8f5a95..00000000000 --- a/src/Doctrine/Orm/Filter/AbstractContextAwareFilter.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use Doctrine\ORM\QueryBuilder; - -abstract class AbstractContextAwareFilter extends AbstractFilter implements ContextAwareFilterInterface -{ - /** - * {@inheritdoc} - */ - public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = []) - { - if (!isset($context['filters']) || !\is_array($context['filters'])) { - parent::apply($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); - - return; - } - - foreach ($context['filters'] as $property => $value) { - $this->filterProperty($this->denormalizePropertyName($property), $value, $queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); - } - } -} diff --git a/src/Doctrine/Orm/Filter/AbstractFilter.php b/src/Doctrine/Orm/Filter/AbstractFilter.php index 68d8cc61c30..d34e0770951 100644 --- a/src/Doctrine/Orm/Filter/AbstractFilter.php +++ b/src/Doctrine/Orm/Filter/AbstractFilter.php @@ -16,42 +16,26 @@ use ApiPlatform\Doctrine\Common\PropertyHelperTrait; use ApiPlatform\Doctrine\Orm\PropertyHelperTrait as OrmPropertyHelperTrait; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Util\RequestParser; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -/** - * {@inheritdoc} - * - * Abstract class with helpers for easing the implementation of a filter. - * - * @author Kévin Dunglas - * @author Théo FIDRY - */ abstract class AbstractFilter implements FilterInterface { use OrmPropertyHelperTrait; use PropertyHelperTrait; - protected $managerRegistry; - protected $requestStack; - protected $logger; - protected $properties; - protected $nameConverter; + protected ManagerRegistry $managerRegistry; + protected LoggerInterface $logger; + protected ?array $properties; + protected ?NameConverterInterface $nameConverter; - public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $requestStack = null, LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null) + public function __construct(ManagerRegistry $managerRegistry, LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null) { - if (null !== $requestStack) { - @trigger_error(sprintf('Passing an instance of "%s" is deprecated since 2.2. Use "filters" context key instead.', RequestStack::class), \E_USER_DEPRECATED); - } - $this->managerRegistry = $managerRegistry; - $this->requestStack = $requestStack; $this->logger = $logger ?? new NullLogger(); $this->properties = $properties; $this->nameConverter = $nameConverter; @@ -60,16 +44,10 @@ public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $req /** * {@inheritdoc} */ - public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null/* , array $context = [] */) + public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []) { - @trigger_error(sprintf('Using "%s::apply()" is deprecated since 2.2. Use "%s::apply()" with the "filters" context key instead.', __CLASS__, AbstractContextAwareFilter::class), \E_USER_DEPRECATED); - - if (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest()) { - return; - } - - foreach ($this->extractProperties($request, $resourceClass) as $property => $value) { - $this->filterProperty($property, $value, $queryBuilder, $queryNameGenerator, $resourceClass, $operationName); + foreach ($context['filters'] as $property => $value) { + $this->filterProperty($this->denormalizePropertyName($property), $value, $queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); } } @@ -78,7 +56,7 @@ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $q * * @param mixed $value */ - abstract protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null/* , array $context = [] */); + abstract protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []); protected function getManagerRegistry(): ManagerRegistry { @@ -98,20 +76,8 @@ protected function getLogger(): LoggerInterface /** * Determines whether the given property is enabled. */ - protected function isPropertyEnabled(string $property/* , string $resourceClass */): bool + protected function isPropertyEnabled(string $property, string $resourceClass): bool { - if (\func_num_args() > 1) { - $resourceClass = func_get_arg(1); - } else { - if (__CLASS__ !== static::class) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a second `$resourceClass` argument in version API Platform 3.0. Not defining it is deprecated since API Platform 2.1.', __FUNCTION__), \E_USER_DEPRECATED); - } - } - $resourceClass = null; - } - if (null === $this->properties) { // to ensure sanity, nested properties must still be explicitly enabled return !$this->isPropertyNested($property, $resourceClass); @@ -120,31 +86,7 @@ protected function isPropertyEnabled(string $property/* , string $resourceClass return \array_key_exists($property, $this->properties); } - /** - * Extracts properties to filter from the request. - */ - protected function extractProperties(Request $request/* , string $resourceClass */): array - { - @trigger_error(sprintf('The use of "%s::extractProperties()" is deprecated since 2.2. Use the "filters" key of the context instead.', __CLASS__), \E_USER_DEPRECATED); - - $resourceClass = \func_num_args() > 1 ? (string) func_get_arg(1) : null; - $needsFixing = false; - if (null !== $this->properties) { - foreach ($this->properties as $property => $value) { - if (($this->isPropertyNested($property, $resourceClass) || $this->isPropertyEmbedded($property, $resourceClass)) && $request->query->has(str_replace('.', '_', $property))) { - $needsFixing = true; - } - } - } - - if ($needsFixing) { - $request = RequestParser::parseAndDuplicateRequest($request); - } - - return $request->query->all(); - } - - protected function denormalizePropertyName($property) + protected function denormalizePropertyName($property): string { if (!$this->nameConverter instanceof NameConverterInterface) { return $property; @@ -153,7 +95,7 @@ protected function denormalizePropertyName($property) return implode('.', array_map([$this->nameConverter, 'denormalize'], explode('.', (string) $property))); } - protected function normalizePropertyName($property) + protected function normalizePropertyName($property): string { if (!$this->nameConverter instanceof NameConverterInterface) { return $property; diff --git a/src/Doctrine/Orm/Filter/BooleanFilter.php b/src/Doctrine/Orm/Filter/BooleanFilter.php index 4f2bacc3257..b0db432d94a 100644 --- a/src/Doctrine/Orm/Filter/BooleanFilter.php +++ b/src/Doctrine/Orm/Filter/BooleanFilter.php @@ -15,7 +15,9 @@ use ApiPlatform\Doctrine\Common\Filter\BooleanFilterTrait; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; /** @@ -29,10 +31,8 @@ * * @author Amrouche Hamza * @author Teoh Han Hui - * - * @final */ -class BooleanFilter extends AbstractContextAwareFilter +final class BooleanFilter extends AbstractFilter { use BooleanFilterTrait; @@ -43,7 +43,7 @@ class BooleanFilter extends AbstractContextAwareFilter /** * {@inheritdoc} */ - protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) + protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { if ( !$this->isPropertyEnabled($property, $resourceClass) || @@ -62,7 +62,7 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB $field = $property; if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); + [$alias, $field] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass, Join::INNER_JOIN); } $valueParameter = $queryNameGenerator->generateParameterName($field); diff --git a/src/Doctrine/Orm/Filter/ContextAwareFilterInterface.php b/src/Doctrine/Orm/Filter/ContextAwareFilterInterface.php deleted file mode 100644 index 60c0058de9e..00000000000 --- a/src/Doctrine/Orm/Filter/ContextAwareFilterInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * 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\Doctrine\Orm\Filter; - -use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use Doctrine\ORM\QueryBuilder; - -/** - * Context aware filter. - * - * @author Kévin Dunglas - */ -interface ContextAwareFilterInterface extends FilterInterface -{ - /** - * {@inheritdoc} - */ - public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = []); -} diff --git a/src/Doctrine/Orm/Filter/DateFilter.php b/src/Doctrine/Orm/Filter/DateFilter.php index 5d63a1a94e0..07a67dfd885 100644 --- a/src/Doctrine/Orm/Filter/DateFilter.php +++ b/src/Doctrine/Orm/Filter/DateFilter.php @@ -17,8 +17,10 @@ use ApiPlatform\Doctrine\Common\Filter\DateFilterTrait; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Operation; use Doctrine\DBAL\Types\Type as DBALType; use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; /** @@ -26,10 +28,8 @@ * * @author Kévin Dunglas * @author Théo FIDRY - * - * @final */ -class DateFilter extends AbstractContextAwareFilter implements DateFilterInterface +final class DateFilter extends AbstractFilter implements DateFilterInterface { use DateFilterTrait; @@ -47,7 +47,7 @@ class DateFilter extends AbstractContextAwareFilter implements DateFilterInterfa /** * {@inheritdoc} */ - protected function filterProperty(string $property, $values, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) + protected function filterProperty(string $property, $values, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { // Expect $values to be an array having the period as keys and the date value as values if ( @@ -63,7 +63,7 @@ protected function filterProperty(string $property, $values, QueryBuilder $query $field = $property; if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); + [$alias, $field] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass, Join::INNER_JOIN); } $nullManagement = $this->properties[$property] ?? null; @@ -128,11 +128,8 @@ protected function filterProperty(string $property, $values, QueryBuilder $query /** * Adds the where clause according to the chosen null management. - * - * @param string|DBALType $type - * @param mixed $value */ - protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, string $operator, $value, string $nullManagement = null, $type = null) + protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, string $operator, mixed $value, string $nullManagement = null, DBALType|string $type = null) { $type = (string) $type; $value = $this->normalizeValue($value, $operator); @@ -142,7 +139,7 @@ protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterf } try { - $value = false === strpos($type, '_immutable') ? new \DateTime($value) : new \DateTimeImmutable($value); + $value = !str_contains($type, '_immutable') ? new \DateTime($value) : new \DateTimeImmutable($value); } catch (\Exception $e) { // Silently ignore this filter if it can not be transformed to a \DateTime $this->logger->notice('Invalid filter ignored', [ diff --git a/src/Doctrine/Orm/Filter/ExistsFilter.php b/src/Doctrine/Orm/Filter/ExistsFilter.php index 854461d7b6d..faee5500c80 100644 --- a/src/Doctrine/Orm/Filter/ExistsFilter.php +++ b/src/Doctrine/Orm/Filter/ExistsFilter.php @@ -17,13 +17,12 @@ use ApiPlatform\Doctrine\Common\Filter\ExistsFilterTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; /** @@ -37,16 +36,14 @@ * Interpretation: filter products which have a brand * * @author Teoh Han Hui - * - * @final */ -class ExistsFilter extends AbstractContextAwareFilter implements ExistsFilterInterface +final class ExistsFilter extends AbstractFilter implements ExistsFilterInterface { use ExistsFilterTrait; - public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $requestStack = null, LoggerInterface $logger = null, array $properties = null, string $existsParameterName = self::QUERY_PARAMETER_KEY, NameConverterInterface $nameConverter = null) + public function __construct(ManagerRegistry $managerRegistry, LoggerInterface $logger = null, array $properties = null, string $existsParameterName = self::QUERY_PARAMETER_KEY, NameConverterInterface $nameConverter = null) { - parent::__construct($managerRegistry, $requestStack, $logger, $properties, $nameConverter); + parent::__construct($managerRegistry, $logger, $properties, $nameConverter); $this->existsParameterName = $existsParameterName; } @@ -54,39 +51,19 @@ public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $req /** * {@inheritdoc} */ - public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = []) + public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { - if (!\is_array($context['filters'][$this->existsParameterName] ?? null)) { - $context['exists_deprecated_syntax'] = true; - parent::apply($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); - - return; - } - foreach ($context['filters'][$this->existsParameterName] as $property => $value) { - $this->filterProperty($this->denormalizePropertyName($property), $value, $queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); + $this->filterProperty($this->denormalizePropertyName($property), $value, $queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); } } /** * {@inheritdoc} */ - protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null/* , array $context = [] */) + protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { - if (\func_num_args() > 6) { - $context = func_get_arg(6); - } else { - if (__CLASS__ !== static::class) { /** @phpstan-ignore-line The class was not final before */ - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a seventh `$context` argument in version API Platform 3.0. Not defining it is deprecated since API Platform 2.5.', __FUNCTION__), \E_USER_DEPRECATED); - } - } - $context = []; - } - if ( - (($context['exists_deprecated_syntax'] ?? false) && !isset($value[self::QUERY_PARAMETER_KEY])) || !$this->isPropertyEnabled($property, $resourceClass) || !$this->isPropertyMapped($property, $resourceClass, true) || !$this->isNullableField($property, $resourceClass) @@ -104,7 +81,7 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB $associations = []; if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); + [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass, Join::INNER_JOIN); } $metadata = $this->getNestedMetadata($resourceClass, $associations); @@ -192,22 +169,4 @@ private function isAssociationNullable(array $associationMapping): bool return true; } - - /** - * {@inheritdoc} - */ - protected function extractProperties(Request $request/* , string $resourceClass */): array - { - if (!$request->query->has($this->existsParameterName)) { - $resourceClass = \func_num_args() > 1 ? (string) func_get_arg(1) : null; - - return parent::extractProperties($request, $resourceClass); - } - - @trigger_error(sprintf('The use of "%s::extractProperties()" is deprecated since 2.2. Use the "filters" key of the context instead.', __CLASS__), \E_USER_DEPRECATED); - - $properties = $request->query->all()[$this->existsParameterName]; - - return \is_array($properties) ? $properties : []; - } } diff --git a/src/Doctrine/Orm/Filter/FilterInterface.php b/src/Doctrine/Orm/Filter/FilterInterface.php index 66d7c0a5cb6..41b12bc1874 100644 --- a/src/Doctrine/Orm/Filter/FilterInterface.php +++ b/src/Doctrine/Orm/Filter/FilterInterface.php @@ -15,6 +15,7 @@ use ApiPlatform\Api\FilterInterface as BaseFilterInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; /** @@ -27,5 +28,5 @@ interface FilterInterface extends BaseFilterInterface /** * Applies the filter. */ - public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null); + public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []); } diff --git a/src/Doctrine/Orm/Filter/NumericFilter.php b/src/Doctrine/Orm/Filter/NumericFilter.php index f32e16f0771..39062af8669 100644 --- a/src/Doctrine/Orm/Filter/NumericFilter.php +++ b/src/Doctrine/Orm/Filter/NumericFilter.php @@ -15,7 +15,9 @@ use ApiPlatform\Doctrine\Common\Filter\NumericFilterTrait; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; /** @@ -28,10 +30,8 @@ * * @author Amrouche Hamza * @author Teoh Han Hui - * - * @final */ -class NumericFilter extends AbstractContextAwareFilter +final class NumericFilter extends AbstractFilter { use NumericFilterTrait; @@ -51,7 +51,7 @@ class NumericFilter extends AbstractContextAwareFilter /** * {@inheritdoc} */ - protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) + protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { if ( !$this->isPropertyEnabled($property, $resourceClass) || @@ -70,7 +70,7 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB $field = $property; if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); + [$alias, $field] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass, Join::INNER_JOIN); } $valueParameter = $queryNameGenerator->generateParameterName($field); diff --git a/src/Doctrine/Orm/Filter/OrderFilter.php b/src/Doctrine/Orm/Filter/OrderFilter.php index 8241b52e1b3..580390d0f62 100644 --- a/src/Doctrine/Orm/Filter/OrderFilter.php +++ b/src/Doctrine/Orm/Filter/OrderFilter.php @@ -16,12 +16,11 @@ use ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface; use ApiPlatform\Doctrine\Common\Filter\OrderFilterTrait; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Operation; use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; /** @@ -36,16 +35,14 @@ * * @author Kévin Dunglas * @author Théo FIDRY - * - * @final */ -class OrderFilter extends AbstractContextAwareFilter implements OrderFilterInterface +final class OrderFilter extends AbstractFilter implements OrderFilterInterface { use OrderFilterTrait; - private $orderNullsComparison; + private ?string $orderNullsComparison; - public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $requestStack = null, string $orderParameterName = 'order', LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null, ?string $orderNullsComparison = null) + public function __construct(ManagerRegistry $managerRegistry, string $orderParameterName = 'order', LoggerInterface $logger = null, array $properties = null, NameConverterInterface $nameConverter = null, ?string $orderNullsComparison = null) { if (null !== $properties) { $properties = array_map(static function ($propertyOptions) { @@ -60,7 +57,7 @@ public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $req }, $properties); } - parent::__construct($managerRegistry, $requestStack, $logger, $properties, $nameConverter); + parent::__construct($managerRegistry, $logger, $properties, $nameConverter); $this->orderParameterName = $orderParameterName; $this->orderNullsComparison = $orderNullsComparison; @@ -69,27 +66,27 @@ public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $req /** * {@inheritdoc} */ - public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = []) + public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { if (isset($context['filters']) && !isset($context['filters'][$this->orderParameterName])) { return; } if (!isset($context['filters'][$this->orderParameterName]) || !\is_array($context['filters'][$this->orderParameterName])) { - parent::apply($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); + parent::apply($queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); return; } foreach ($context['filters'][$this->orderParameterName] as $property => $value) { - $this->filterProperty($this->denormalizePropertyName($property), $value, $queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context); + $this->filterProperty($this->denormalizePropertyName($property), $value, $queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); } } /** * {@inheritdoc} */ - protected function filterProperty(string $property, $direction, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) + protected function filterProperty(string $property, $direction, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { if (!$this->isPropertyEnabled($property, $resourceClass) || !$this->isPropertyMapped($property, $resourceClass)) { return; @@ -118,16 +115,4 @@ protected function filterProperty(string $property, $direction, QueryBuilder $qu $queryBuilder->addOrderBy(sprintf('%s.%s', $alias, $field), $direction); } - - /** - * {@inheritdoc} - */ - protected function extractProperties(Request $request/* , string $resourceClass */): array - { - @trigger_error(sprintf('The use of "%s::extractProperties()" is deprecated since 2.2. Use the "filters" key of the context instead.', __CLASS__), \E_USER_DEPRECATED); - - $properties = $request->query->all()[$this->orderParameterName] ?? null; - - return \is_array($properties) ? $properties : []; - } } diff --git a/src/Doctrine/Orm/Filter/RangeFilter.php b/src/Doctrine/Orm/Filter/RangeFilter.php index e8738bb00bd..dbd64c0a365 100644 --- a/src/Doctrine/Orm/Filter/RangeFilter.php +++ b/src/Doctrine/Orm/Filter/RangeFilter.php @@ -16,23 +16,23 @@ use ApiPlatform\Doctrine\Common\Filter\RangeFilterInterface; use ApiPlatform\Doctrine\Common\Filter\RangeFilterTrait; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Operation; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; /** * Filters the collection by range. * * @author Lee Siong Chan - * - * @final */ -class RangeFilter extends AbstractContextAwareFilter implements RangeFilterInterface +final class RangeFilter extends AbstractFilter implements RangeFilterInterface { use RangeFilterTrait; /** * {@inheritdoc} */ - protected function filterProperty(string $property, $values, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) + protected function filterProperty(string $property, $values, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { if ( !\is_array($values) || @@ -51,7 +51,7 @@ protected function filterProperty(string $property, $values, QueryBuilder $query $field = $property; if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); + [$alias, $field] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass, Join::INNER_JOIN); } foreach ($values as $operator => $value) { @@ -68,13 +68,8 @@ protected function filterProperty(string $property, $values, QueryBuilder $query /** * Adds the where clause according to the operator. - * - * @param string $alias - * @param string $field - * @param string $operator - * @param string $value */ - protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, $alias, $field, $operator, $value) + protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, string $operator, string $value): void { $valueParameter = $queryNameGenerator->generateParameterName($field); diff --git a/src/Doctrine/Orm/Filter/SearchFilter.php b/src/Doctrine/Orm/Filter/SearchFilter.php index 13c184a1743..a6ffe5b0d59 100644 --- a/src/Doctrine/Orm/Filter/SearchFilter.php +++ b/src/Doctrine/Orm/Filter/SearchFilter.php @@ -13,18 +13,19 @@ namespace ApiPlatform\Doctrine\Orm\Filter; +use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; use ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface; use ApiPlatform\Doctrine\Common\Filter\SearchFilterTrait; use ApiPlatform\Doctrine\Orm\Util\QueryBuilderHelper; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Operation; use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -33,29 +34,23 @@ * Filter the collection by given properties. * * @author Kévin Dunglas - * - * @final */ -class SearchFilter extends AbstractContextAwareFilter implements SearchFilterInterface +final class SearchFilter extends AbstractFilter implements SearchFilterInterface { use SearchFilterTrait; public const DOCTRINE_INTEGER_TYPE = Types::INTEGER; - public function __construct(ManagerRegistry $managerRegistry, ?RequestStack $requestStack, IriConverterInterface $iriConverter, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, IdentifiersExtractorInterface $identifiersExtractor = null, NameConverterInterface $nameConverter = null) + public function __construct(ManagerRegistry $managerRegistry, IriConverterInterface $iriConverter, PropertyAccessorInterface $propertyAccessor = null, LoggerInterface $logger = null, array $properties = null, IdentifiersExtractorInterface $identifiersExtractor = null, NameConverterInterface $nameConverter = null) { - parent::__construct($managerRegistry, $requestStack, $logger, $properties, $nameConverter); - - if (null === $identifiersExtractor) { - @trigger_error('Not injecting ItemIdentifiersExtractor is deprecated since API Platform 2.5 and can lead to unexpected behaviors, it will not be possible anymore in API Platform 3.0.', \E_USER_DEPRECATED); - } + parent::__construct($managerRegistry, $logger, $properties, $nameConverter); $this->iriConverter = $iriConverter; $this->identifiersExtractor = $identifiersExtractor; $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } - protected function getIriConverter() + protected function getIriConverter(): IriConverterInterface { return $this->iriConverter; } @@ -68,7 +63,7 @@ protected function getPropertyAccessor(): PropertyAccessorInterface /** * {@inheritdoc} */ - protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) + protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { if ( null === $value || @@ -88,14 +83,14 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB $associations = []; if ($this->isPropertyNested($property, $resourceClass)) { - [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass); + [$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass, Join::INNER_JOIN); } $caseSensitive = true; $strategy = $this->properties[$property] ?? self::STRATEGY_EXACT; // prefixing the strategy with i makes it case insensitive - if (0 === strpos($strategy, 'i')) { + if (str_starts_with($strategy, 'i')) { $strategy = substr($strategy, 1); $caseSensitive = false; } @@ -126,14 +121,10 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB } $values = array_map([$this, 'getIdFromValue'], $values); - $associationFieldIdentifier = 'id'; - $doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass); - if (null !== $this->identifiersExtractor) { - $associationResourceClass = $metadata->getAssociationTargetClass($field); - $associationFieldIdentifier = $this->identifiersExtractor->getIdentifiersFromResourceClass($associationResourceClass)[0]; - $doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass); - } + $associationResourceClass = $metadata->getAssociationTargetClass($field); + $associationFieldIdentifier = $metadata->getIdentifierFieldNames()[0]; + $doctrineTypeField = $this->getDoctrineFieldType($associationFieldIdentifier, $associationResourceClass); if (!$this->hasValidValues($values, $doctrineTypeField)) { $this->logger->notice('Invalid filter ignored', [ @@ -156,11 +147,9 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB /** * Adds where clause according to the strategy. * - * @param mixed $values - * * @throws InvalidArgumentException If strategy does not exist */ - protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, $values, bool $caseSensitive) + protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, mixed $values, bool $caseSensitive): void { if (!\is_array($values)) { $values = [$values]; @@ -192,34 +181,31 @@ protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuild $keyValueParameter = sprintf('%s_%s', $valueParameter, $key); $parameters[$caseSensitive ? $value : strtolower($value)] = $keyValueParameter; - switch ($strategy) { - case self::STRATEGY_PARTIAL: - $ors[] = $queryBuilder->expr()->like( - $wrapCase($aliasedField), - $wrapCase((string) $queryBuilder->expr()->concat("'%'", $keyValueParameter, "'%'")) - ); - break; - case self::STRATEGY_START: - $ors[] = $queryBuilder->expr()->like( + $ors[] = match ($strategy) { + self::STRATEGY_PARTIAL => $queryBuilder->expr()->like( + $wrapCase($aliasedField), + $wrapCase((string) $queryBuilder->expr()->concat("'%'", $keyValueParameter, "'%'")) + ), + self::STRATEGY_START => $queryBuilder->expr()->like( + $wrapCase($aliasedField), + $wrapCase((string) $queryBuilder->expr()->concat($keyValueParameter, "'%'")) + ), + self::STRATEGY_END => $queryBuilder->expr()->like( + $wrapCase($aliasedField), + $wrapCase((string) $queryBuilder->expr()->concat("'%'", $keyValueParameter)) + ), + self::STRATEGY_WORD_START => $queryBuilder->expr()->orX( + $queryBuilder->expr()->like( $wrapCase($aliasedField), $wrapCase((string) $queryBuilder->expr()->concat($keyValueParameter, "'%'")) - ); - break; - case self::STRATEGY_END: - $ors[] = $queryBuilder->expr()->like( + ), + $queryBuilder->expr()->like( $wrapCase($aliasedField), - $wrapCase((string) $queryBuilder->expr()->concat("'%'", $keyValueParameter)) - ); - break; - case self::STRATEGY_WORD_START: - $ors[] = $queryBuilder->expr()->orX( - $queryBuilder->expr()->like($wrapCase($aliasedField), $wrapCase((string) $queryBuilder->expr()->concat($keyValueParameter, "'%'"))), - $queryBuilder->expr()->like($wrapCase($aliasedField), $wrapCase((string) $queryBuilder->expr()->concat("'% '", $keyValueParameter, "'%'"))) - ); - break; - default: - throw new InvalidArgumentException(sprintf('strategy %s does not exist.', $strategy)); - } + $wrapCase((string) $queryBuilder->expr()->concat("'% '", $keyValueParameter, "'%'")) + ) + ), + default => throw new InvalidArgumentException(sprintf('strategy %s does not exist.', $strategy)), + }; } $queryBuilder->andWhere($queryBuilder->expr()->orX(...$ors)); @@ -249,28 +235,13 @@ protected function createWrapCase(bool $caseSensitive): \Closure */ protected function getType(string $doctrineType): string { - switch ($doctrineType) { - case Types::ARRAY: - return 'array'; - case Types::BIGINT: - case Types::INTEGER: - case Types::SMALLINT: - return 'int'; - case Types::BOOLEAN: - return 'bool'; - case Types::DATE_MUTABLE: - case Types::TIME_MUTABLE: - case Types::DATETIME_MUTABLE: - case Types::DATETIMETZ_MUTABLE: - case Types::DATE_IMMUTABLE: - case Types::TIME_IMMUTABLE: - case Types::DATETIME_IMMUTABLE: - case Types::DATETIMETZ_IMMUTABLE: - return \DateTimeInterface::class; - case Types::FLOAT: - return 'float'; - } - - return 'string'; + return match ($doctrineType) { + Types::ARRAY => 'array', + Types::BIGINT, Types::INTEGER, Types::SMALLINT => 'int', + Types::BOOLEAN => 'bool', + Types::DATE_MUTABLE, Types::TIME_MUTABLE, Types::DATETIME_MUTABLE, Types::DATETIMETZ_MUTABLE, Types::DATE_IMMUTABLE, Types::TIME_IMMUTABLE, Types::DATETIME_IMMUTABLE, Types::DATETIMETZ_IMMUTABLE => \DateTimeInterface::class, + Types::FLOAT => 'float', + default => 'string', + }; } } diff --git a/src/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php b/src/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php index 611640e1424..5b08a8f202d 100644 --- a/src/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php +++ b/src/Doctrine/Orm/Metadata/Property/DoctrineOrmPropertyMetadataFactory.php @@ -25,8 +25,8 @@ */ final class DoctrineOrmPropertyMetadataFactory implements PropertyMetadataFactoryInterface { - private $decorated; - private $managerRegistry; + private PropertyMetadataFactoryInterface $decorated; + private ManagerRegistry $managerRegistry; public function __construct(ManagerRegistry $managerRegistry, PropertyMetadataFactoryInterface $decorated) { diff --git a/src/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactory.php b/src/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactory.php index 7f50d12977b..c594009ac62 100644 --- a/src/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactory.php +++ b/src/Doctrine/Orm/Metadata/Resource/DoctrineOrmResourceCollectionMetadataFactory.php @@ -27,15 +27,9 @@ final class DoctrineOrmResourceCollectionMetadataFactory implements ResourceMetadataCollectionFactoryInterface { - /** - * @var ManagerRegistry - */ - private $managerRegistry; + private ManagerRegistry $managerRegistry; - /** - * @var ResourceMetadataCollectionFactoryInterface - */ - private $decorated; + private ResourceMetadataCollectionFactoryInterface $decorated; public function __construct(ManagerRegistry $managerRegistry, ResourceMetadataCollectionFactoryInterface $decorated) { diff --git a/src/Doctrine/Orm/Paginator.php b/src/Doctrine/Orm/Paginator.php index 92f8265b66e..df61f23ce18 100644 --- a/src/Doctrine/Orm/Paginator.php +++ b/src/Doctrine/Orm/Paginator.php @@ -23,10 +23,7 @@ */ final class Paginator extends AbstractPaginator implements PaginatorInterface, QueryAwareInterface { - /** - * @var int|null - */ - private $totalItems; + private ?int $totalItems; /** * {@inheritdoc} diff --git a/src/Doctrine/Orm/PropertyHelperTrait.php b/src/Doctrine/Orm/PropertyHelperTrait.php index d29f586bcab..7711e88bd0a 100644 --- a/src/Doctrine/Orm/PropertyHelperTrait.php +++ b/src/Doctrine/Orm/PropertyHelperTrait.php @@ -29,7 +29,7 @@ trait PropertyHelperTrait /** * Splits the given property into parts. */ - abstract protected function splitPropertyParts(string $property/* , string $resourceClass */): array; + abstract protected function splitPropertyParts(string $property, string $resourceClass): array; /** * Adds the necessary joins for a nested property. @@ -40,32 +40,8 @@ abstract protected function splitPropertyParts(string $property/* , string $reso * the second element is the $field name * the third element is the $associations array */ - protected function addJoinsForNestedProperty(string $property, string $rootAlias, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator/* , string $resourceClass, string $joinType */): array + protected function addJoinsForNestedProperty(string $property, string $rootAlias, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $joinType): array { - if (\func_num_args() > 4) { - $resourceClass = func_get_arg(4); - } else { - if (__CLASS__ !== static::class) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a fifth `$resourceClass` argument in version API Platform 3.0. Not defining it is deprecated since API Platform 2.1.', __FUNCTION__), \E_USER_DEPRECATED); - } - } - $resourceClass = null; - } - - if (\func_num_args() > 5) { - $joinType = func_get_arg(5); - } else { - if (__CLASS__ !== static::class) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a sixth `$joinType` argument in version API Platform 3.0. Not defining it is deprecated since API Platform 2.3.', __FUNCTION__), \E_USER_DEPRECATED); - } - } - $joinType = null; - } - $propertyParts = $this->splitPropertyParts($property, $resourceClass); $parentAlias = $rootAlias; $alias = null; diff --git a/src/Doctrine/Orm/State/CollectionProvider.php b/src/Doctrine/Orm/State/CollectionProvider.php index a652020df42..3b85f79b905 100644 --- a/src/Doctrine/Orm/State/CollectionProvider.php +++ b/src/Doctrine/Orm/State/CollectionProvider.php @@ -34,9 +34,9 @@ final class CollectionProvider implements ProviderInterface { use LinksHandlerTrait; - private $resourceMetadataCollectionFactory; - private $managerRegistry; - private $collectionExtensions; + private ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory; + private ManagerRegistry $managerRegistry; + private iterable $collectionExtensions; /** * @param QueryCollectionExtensionInterface[] $collectionExtensions @@ -66,10 +66,10 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $this->handleLinks($queryBuilder, $uriVariables, $queryNameGenerator, $context, $resourceClass, $operation); foreach ($this->collectionExtensions as $extension) { - $extension->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operation->getName(), $context); + $extension->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); - if ($extension instanceof QueryResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operation->getName(), $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operation->getName(), $context); + if ($extension instanceof QueryResultCollectionExtensionInterface && $extension->supportsResult($resourceClass, $operation, $context)) { + return $extension->getResult($queryBuilder, $resourceClass, $operation, $context); } } diff --git a/src/Doctrine/Orm/State/ItemProvider.php b/src/Doctrine/Orm/State/ItemProvider.php index b61191b30a3..414da6214b5 100644 --- a/src/Doctrine/Orm/State/ItemProvider.php +++ b/src/Doctrine/Orm/State/ItemProvider.php @@ -34,9 +34,9 @@ final class ItemProvider implements ProviderInterface { use LinksHandlerTrait; - private $resourceMetadataCollectionFactory; - private $managerRegistry; - private $itemExtensions; + private ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory; + private ManagerRegistry $managerRegistry; + private iterable $itemExtensions; /** * @param QueryItemExtensionInterface[] $itemExtensions @@ -71,10 +71,10 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $this->handleLinks($queryBuilder, $uriVariables, $queryNameGenerator, $context, $resourceClass, $operation); foreach ($this->itemExtensions as $extension) { - $extension->applyToItem($queryBuilder, $queryNameGenerator, $resourceClass, $uriVariables, $operation->getName(), $context); + $extension->applyToItem($queryBuilder, $queryNameGenerator, $resourceClass, $uriVariables, $operation, $context); - if ($extension instanceof QueryResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operation->getName(), $context)) { - return $extension->getResult($queryBuilder, $resourceClass, $operation->getName(), $context); + if ($extension instanceof QueryResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operation, $context)) { + return $extension->getResult($queryBuilder, $resourceClass, $operation, $context); } } diff --git a/src/Doctrine/Orm/Util/EagerLoadingTrait.php b/src/Doctrine/Orm/Util/EagerLoadingTrait.php deleted file mode 100644 index 12d125fd3f4..00000000000 --- a/src/Doctrine/Orm/Util/EagerLoadingTrait.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * 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\Doctrine\Orm\Util; - -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadataInfo; - -/** - * @author Antoine Bluchet - * - * TODO: remove in 3.0. - * - * @internal - */ -trait EagerLoadingTrait -{ - private $forceEager; - private $fetchPartial; - - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface - */ - private $resourceMetadataFactory; - - /** - * Checks if an operation has a `force_eager` attribute. - */ - private function shouldOperationForceEager(string $resourceClass, array $options): bool - { - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - throw new RuntimeException('Method should not be called.'); - } - - return $this->getBooleanOperationAttribute($resourceClass, $options, 'force_eager', $this->forceEager); - } - - /** - * Checks if an operation has a `fetch_partial` attribute. - */ - private function shouldOperationFetchPartial(string $resourceClass, array $options): bool - { - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - throw new RuntimeException('Method should not be called.'); - } - - return $this->getBooleanOperationAttribute($resourceClass, $options, 'fetch_partial', $this->fetchPartial); - } - - /** - * Get the boolean attribute of an operation or the resource metadata. - */ - private function getBooleanOperationAttribute(string $resourceClass, array $options, string $attributeName, bool $default): bool - { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if (isset($options['collection_operation_name'])) { - $attribute = $resourceMetadata->getCollectionOperationAttribute($options['collection_operation_name'], $attributeName, null, true); - } elseif (isset($options['item_operation_name'])) { - $attribute = $resourceMetadata->getItemOperationAttribute($options['item_operation_name'], $attributeName, null, true); - } else { - $attribute = $resourceMetadata->getAttribute($attributeName); - } - - return \is_bool($attribute) ? $attribute : $default; - } - - /** - * Checks if the class has an associationMapping with FETCH=EAGER. - * - * @param array $checked array cache of tested metadata classes - */ - private function hasFetchEagerAssociation(EntityManagerInterface $em, ClassMetadataInfo $classMetadata, array &$checked = []): bool - { - $checked[] = $classMetadata->name; - - foreach ($classMetadata->getAssociationMappings() as $mapping) { - if (ClassMetadataInfo::FETCH_EAGER === $mapping['fetch']) { - return true; - } - - $related = $em->getClassMetadata($mapping['targetEntity']); - - if (\in_array($related->name, $checked, true)) { - continue; - } - - if (true === $this->hasFetchEagerAssociation($em, $related, $checked)) { - return true; - } - } - - return false; - } -} diff --git a/src/Doctrine/Orm/Util/QueryBuilderHelper.php b/src/Doctrine/Orm/Util/QueryBuilderHelper.php index b22d5e5d87a..60f6c7371a4 100644 --- a/src/Doctrine/Orm/Util/QueryBuilderHelper.php +++ b/src/Doctrine/Orm/Util/QueryBuilderHelper.php @@ -208,7 +208,7 @@ private static function mapJoinAliases(iterable $joins): array $alias = $join->getAlias(); $relationship = $join->getJoin(); - if (false !== strpos($relationship, '.')) { + if (str_contains($relationship, '.')) { $aliasMap[$alias] = explode('.', $relationship); } else { $aliasMap[$alias] = $relationship; diff --git a/src/Doctrine/Orm/Util/QueryChecker.php b/src/Doctrine/Orm/Util/QueryChecker.php index ce8dd718a5c..04941e1e7cd 100644 --- a/src/Doctrine/Orm/Util/QueryChecker.php +++ b/src/Doctrine/Orm/Util/QueryChecker.php @@ -120,7 +120,7 @@ public static function hasOrderByOnFetchJoinedToManyAssociation(QueryBuilder $qu foreach ($orderByParts as $orderBy) { foreach ($orderBy->getParts() as $part) { - if (false !== strpos($part, '.')) { + if (str_contains($part, '.')) { [$alias] = explode('.', $part); $orderByAliases[] = $alias; @@ -150,18 +150,6 @@ public static function hasOrderByOnFetchJoinedToManyAssociation(QueryBuilder $qu return false; } - /** - * Determines whether the QueryBuilder has ORDER BY on a column from a fetch joined to-many association. - * - * @deprecated - */ - public static function hasOrderByOnToManyJoin(QueryBuilder $queryBuilder, ManagerRegistry $managerRegistry): bool - { - @trigger_error(sprintf('The use of "%s::hasOrderByOnToManyJoin()" is deprecated since 2.4 and will be removed in 3.0. Use "%1$s::hasOrderByOnFetchJoinedToManyAssociation()" instead.', __CLASS__), \E_USER_DEPRECATED); - - return self::hasOrderByOnFetchJoinedToManyAssociation($queryBuilder, $managerRegistry); - } - /** * Determines whether the QueryBuilder already has a left join. */ diff --git a/src/Doctrine/Orm/Util/QueryJoinParser.php b/src/Doctrine/Orm/Util/QueryJoinParser.php deleted file mode 100644 index abe9bf2fd01..00000000000 --- a/src/Doctrine/Orm/Util/QueryJoinParser.php +++ /dev/null @@ -1,91 +0,0 @@ - - * - * 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\Doctrine\Orm\Util; - -use Doctrine\ORM\Query\Expr\Join; -use Doctrine\ORM\Query\Expr\OrderBy; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\Mapping\ClassMetadata; - -/** - * Utility functions for working with Doctrine ORM query. - * - * @author Teoh Han Hui - * @author Vincent Chalamon - * - * @internal - * - * @deprecated - */ -final class QueryJoinParser -{ - private function __construct() - { - } - - /** - * Gets the class metadata from a given join alias. - * - * @deprecated - */ - public static function getClassMetadataFromJoinAlias(string $alias, QueryBuilder $queryBuilder, ManagerRegistry $managerRegistry): ClassMetadata - { - @trigger_error(sprintf('The use of "%s::getClassMetadataFromJoinAlias()" is deprecated since 2.4 and will be removed in 3.0. Use "%s::getEntityClassByAlias()" instead.', __CLASS__, QueryBuilderHelper::class), \E_USER_DEPRECATED); - - $entityClass = QueryBuilderHelper::getEntityClassByAlias($alias, $queryBuilder, $managerRegistry); - - return $managerRegistry - ->getManagerForClass($entityClass) - ->getClassMetadata($entityClass); - } - - /** - * Gets the relationship from a Join expression. - * - * @deprecated - */ - public static function getJoinRelationship(Join $join): string - { - @trigger_error(sprintf('The use of "%s::getJoinRelationship()" is deprecated since 2.3 and will be removed in 3.0. Use "%s::getJoin()" directly instead.', __CLASS__, Join::class), \E_USER_DEPRECATED); - - return $join->getJoin(); - } - - /** - * Gets the alias from a Join expression. - * - * @deprecated - */ - public static function getJoinAlias(Join $join): string - { - @trigger_error(sprintf('The use of "%s::getJoinAlias()" is deprecated since 2.3 and will be removed in 3.0. Use "%s::getAlias()" directly instead.', __CLASS__, Join::class), \E_USER_DEPRECATED); - - return $join->getAlias(); - } - - /** - * Gets the parts from an OrderBy expression. - * - * @return string[] - * - * @deprecated - */ - public static function getOrderByParts(OrderBy $orderBy): array - { - @trigger_error(sprintf('The use of "%s::getOrderByParts()" is deprecated since 2.3 and will be removed in 3.0. Use "%s::getParts()" directly instead.', __CLASS__, OrderBy::class), \E_USER_DEPRECATED); - - return $orderBy->getParts(); - } -} diff --git a/src/Doctrine/Orm/Util/QueryNameGenerator.php b/src/Doctrine/Orm/Util/QueryNameGenerator.php index 9bf85b1581d..810a1e050c4 100644 --- a/src/Doctrine/Orm/Util/QueryNameGenerator.php +++ b/src/Doctrine/Orm/Util/QueryNameGenerator.php @@ -22,8 +22,8 @@ */ final class QueryNameGenerator implements QueryNameGeneratorInterface { - private $incrementedAssociation = 1; - private $incrementedName = 1; + private int $incrementedAssociation = 1; + private int $incrementedName = 1; /** * {@inheritdoc} diff --git a/src/Elasticsearch/Extension/AbstractFilterExtension.php b/src/Elasticsearch/Extension/AbstractFilterExtension.php index da139632bc8..05157429d34 100644 --- a/src/Elasticsearch/Extension/AbstractFilterExtension.php +++ b/src/Elasticsearch/Extension/AbstractFilterExtension.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Elasticsearch\Extension; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Metadata\Operation; use Psr\Container\ContainerInterface; /** @@ -25,22 +25,19 @@ */ abstract class AbstractFilterExtension implements RequestBodySearchCollectionExtensionInterface { - private $resourceMetadataFactory; - private $filterLocator; + private ContainerInterface $filterLocator; - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ContainerInterface $filterLocator) + public function __construct(ContainerInterface $filterLocator) { - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->filterLocator = $filterLocator; } /** * {@inheritdoc} */ - public function applyToCollection(array $requestBody, string $resourceClass, ?string $operationName = null, array $context = []): array + public function applyToCollection(array $requestBody, string $resourceClass, ?Operation $operation = null, array $context = []): array { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); + $resourceFilters = $operation?->getFilters(); if (!$resourceFilters) { return $requestBody; @@ -51,7 +48,7 @@ public function applyToCollection(array $requestBody, string $resourceClass, ?st foreach ($resourceFilters as $filterId) { if ($this->filterLocator->has($filterId) && is_a($filter = $this->filterLocator->get($filterId), $this->getFilterInterface())) { - $clauseBody = $filter->apply($clauseBody, $resourceClass, $operationName, $context); + $clauseBody = $filter->apply($clauseBody, $resourceClass, $operation, $context); } } diff --git a/src/Elasticsearch/Extension/RequestBodySearchCollectionExtensionInterface.php b/src/Elasticsearch/Extension/RequestBodySearchCollectionExtensionInterface.php index f5b50d10d65..3e9ece3fc49 100644 --- a/src/Elasticsearch/Extension/RequestBodySearchCollectionExtensionInterface.php +++ b/src/Elasticsearch/Extension/RequestBodySearchCollectionExtensionInterface.php @@ -13,6 +13,8 @@ namespace ApiPlatform\Elasticsearch\Extension; +use ApiPlatform\Metadata\Operation; + /** * Interface of Elasticsearch request body search extensions for collection queries. * @@ -24,5 +26,5 @@ */ interface RequestBodySearchCollectionExtensionInterface { - public function applyToCollection(array $requestBody, string $resourceClass, ?string $operationName = null, array $context = []): array; + public function applyToCollection(array $requestBody, string $resourceClass, ?Operation $operation = null, array $context = []): array; } diff --git a/src/Elasticsearch/Extension/SortExtension.php b/src/Elasticsearch/Extension/SortExtension.php index 627663e8018..b480cb92768 100644 --- a/src/Elasticsearch/Extension/SortExtension.php +++ b/src/Elasticsearch/Extension/SortExtension.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Elasticsearch\Extension; +use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Elasticsearch\Util\FieldDatatypeTrait; +use ApiPlatform\Metadata\Operation; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; /** @@ -32,14 +32,12 @@ final class SortExtension implements RequestBodySearchCollectionExtensionInterfa { use FieldDatatypeTrait; - private $defaultDirection; - private $identifierExtractor; - private $resourceMetadataFactory; - private $nameConverter; + private ?string $defaultDirection; + private IdentifiersExtractorInterface $identifierExtractor; + private ?NameConverterInterface $nameConverter; - public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, IdentifierExtractorInterface $identifierExtractor, $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, ?string $defaultDirection = null) + public function __construct(IdentifiersExtractorInterface $identifierExtractor, $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, ?string $defaultDirection = null) { - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->identifierExtractor = $identifierExtractor; $this->propertyMetadataFactory = $propertyMetadataFactory; $this->resourceClassResolver = $resourceClassResolver; @@ -50,12 +48,12 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa /** * {@inheritdoc} */ - public function applyToCollection(array $requestBody, string $resourceClass, ?string $operationName = null, array $context = []): array + public function applyToCollection(array $requestBody, string $resourceClass, ?Operation $operation = null, array $context = []): array { $orders = []; if ( - null !== ($defaultOrder = $this->resourceMetadataFactory->create($resourceClass)->getAttribute('order')) + null !== ($defaultOrder = $operation?->getOrder()) && \is_array($defaultOrder) ) { foreach ($defaultOrder as $property => $direction) { diff --git a/src/Elasticsearch/Filter/AbstractFilter.php b/src/Elasticsearch/Filter/AbstractFilter.php index eb5b9b471c3..70a14f91440 100644 --- a/src/Elasticsearch/Filter/AbstractFilter.php +++ b/src/Elasticsearch/Filter/AbstractFilter.php @@ -33,9 +33,9 @@ abstract class AbstractFilter implements FilterInterface { use FieldDatatypeTrait { getNestedFieldPath as protected; } - protected $properties; - protected $propertyNameCollectionFactory; - protected $nameConverter; + protected ?array $properties; + protected PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory; + protected ?NameConverterInterface $nameConverter; public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, ?array $properties = null) { diff --git a/src/Elasticsearch/Filter/AbstractSearchFilter.php b/src/Elasticsearch/Filter/AbstractSearchFilter.php index 56d3d33dd9b..b1153e9ef1f 100644 --- a/src/Elasticsearch/Filter/AbstractSearchFilter.php +++ b/src/Elasticsearch/Filter/AbstractSearchFilter.php @@ -13,10 +13,11 @@ namespace ApiPlatform\Elasticsearch\Filter; +use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; @@ -34,14 +35,14 @@ */ abstract class AbstractSearchFilter extends AbstractFilter implements ConstantScoreFilterInterface { - protected $identifierExtractor; - protected $iriConverter; - protected $propertyAccessor; + protected IdentifiersExtractorInterface $identifierExtractor; + protected IriConverterInterface $iriConverter; + protected PropertyAccessorInterface $propertyAccessor; /** * {@inheritdoc} */ - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, IdentifierExtractorInterface $identifierExtractor, IriConverterInterface $iriConverter, PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter = null, ?array $properties = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, IdentifiersExtractorInterface $identifierExtractor, IriConverterInterface $iriConverter, PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter = null, ?array $properties = null) { parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceClassResolver, $nameConverter, $properties); @@ -53,7 +54,7 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName /** * {@inheritdoc} */ - public function apply(array $clauseBody, string $resourceClass, ?string $operationName = null, array $context = []): array + public function apply(array $clauseBody, string $resourceClass, ?Operation $operation = null, array $context = []): array { $searches = []; diff --git a/src/Elasticsearch/Filter/FilterInterface.php b/src/Elasticsearch/Filter/FilterInterface.php index 80d7857af88..424397f1a52 100644 --- a/src/Elasticsearch/Filter/FilterInterface.php +++ b/src/Elasticsearch/Filter/FilterInterface.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Elasticsearch\Filter; use ApiPlatform\Api\FilterInterface as BaseFilterInterface; +use ApiPlatform\Metadata\Operation; /** * Elasticsearch filter interface. @@ -24,5 +25,5 @@ */ interface FilterInterface extends BaseFilterInterface { - public function apply(array $clauseBody, string $resourceClass, ?string $operationName = null, array $context = []): array; + public function apply(array $clauseBody, string $resourceClass, ?Operation $operation = null, array $context = []): array; } diff --git a/src/Elasticsearch/Filter/OrderFilter.php b/src/Elasticsearch/Filter/OrderFilter.php index d07951f0e29..a7f1445c826 100644 --- a/src/Elasticsearch/Filter/OrderFilter.php +++ b/src/Elasticsearch/Filter/OrderFilter.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Elasticsearch\Filter; use ApiPlatform\Api\ResourceClassResolverInterface; +use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -29,7 +30,7 @@ */ final class OrderFilter extends AbstractFilter implements SortFilterInterface { - private $orderParameterName; + private string $orderParameterName; /** * {@inheritdoc} @@ -44,7 +45,7 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName /** * {@inheritdoc} */ - public function apply(array $clauseBody, string $resourceClass, ?string $operationName = null, array $context = []): array + public function apply(array $clauseBody, string $resourceClass, ?Operation $operation = null, array $context = []): array { if (!\is_array($properties = $context['filters'][$this->orderParameterName] ?? [])) { return $clauseBody; diff --git a/src/Elasticsearch/Metadata/Document/DocumentMetadata.php b/src/Elasticsearch/Metadata/Document/DocumentMetadata.php index c6197da4ffb..8933d8cb260 100644 --- a/src/Elasticsearch/Metadata/Document/DocumentMetadata.php +++ b/src/Elasticsearch/Metadata/Document/DocumentMetadata.php @@ -26,8 +26,8 @@ final class DocumentMetadata { public const DEFAULT_TYPE = '_doc'; - private $index; - private $type; + private ?string $index; + private string $type; public function __construct(?string $index = null, string $type = self::DEFAULT_TYPE) { diff --git a/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php index 3b4f9647af5..1bda4f5a540 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php @@ -13,12 +13,9 @@ namespace ApiPlatform\Elasticsearch\Metadata\Document\Factory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; /** * Creates document's metadata using the attribute configuration. @@ -29,16 +26,10 @@ */ final class AttributeDocumentMetadataFactory implements DocumentMetadataFactoryInterface { - /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface - */ - private $resourceMetadataFactory; - private $decorated; + private ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory; + private ?DocumentMetadataFactoryInterface $decorated; - /** - * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory - */ - public function __construct($resourceMetadataFactory, ?DocumentMetadataFactoryInterface $decorated = null) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ?DocumentMetadataFactoryInterface $decorated = null) { $this->resourceMetadataFactory = $resourceMetadataFactory; $this->decorated = $decorated; @@ -61,10 +52,9 @@ public function create(string $resourceClass): DocumentMetadata $resourceMetadata = null; if (!$documentMetadata || null === $documentMetadata->getIndex()) { - /** @var ResourceMetadata|ResourceMetadataCollection */ $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $index = $resourceMetadata instanceof ResourceMetadata ? $resourceMetadata->getAttribute('elasticsearch_index') : ($resourceMetadata->getOperation()->getExtraProperties()['elasticsearch_index'] ?? null); + $index = $resourceMetadata->getOperation()->getExtraProperties()['elasticsearch_index'] ?? null; if (null !== $index) { $documentMetadata = $documentMetadata ? $documentMetadata->withIndex($index) : new DocumentMetadata($index); @@ -72,9 +62,8 @@ public function create(string $resourceClass): DocumentMetadata } if (!$documentMetadata || DocumentMetadata::DEFAULT_TYPE === $documentMetadata->getType()) { - /** @var ResourceMetadata|ResourceMetadataCollection */ $resourceMetadata = $resourceMetadata ?? $this->resourceMetadataFactory->create($resourceClass); - $type = $resourceMetadata instanceof ResourceMetadata ? $resourceMetadata->getAttribute('elasticsearch_type') : ($resourceMetadata->getOperation()->getExtraProperties()['elasticsearch_type'] ?? null); + $type = $resourceMetadata->getOperation()->getExtraProperties()['elasticsearch_type'] ?? null; if (null !== $type) { $documentMetadata = $documentMetadata ? $documentMetadata->withType($type) : new DocumentMetadata(null, $type); diff --git a/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php index 08316964138..4ec1d580cf1 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php @@ -29,9 +29,9 @@ final class CachedDocumentMetadataFactory implements DocumentMetadataFactoryInte { private const CACHE_KEY_PREFIX = 'index_metadata'; - private $cacheItemPool; - private $decorated; - private $localCache = []; + private CacheItemPoolInterface $cacheItemPool; + private DocumentMetadataFactoryInterface $decorated; + private array $localCache = []; public function __construct(CacheItemPoolInterface $cacheItemPool, DocumentMetadataFactoryInterface $decorated) { diff --git a/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php index 2a7a8f60f3a..51224775edb 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php @@ -13,12 +13,9 @@ namespace ApiPlatform\Elasticsearch\Metadata\Document\Factory; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Elasticsearch\Exception\IndexNotFoundException; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Util\Inflector; use Elasticsearch\Client; use Elasticsearch\Common\Exceptions\Missing404Exception; @@ -34,17 +31,11 @@ */ final class CatDocumentMetadataFactory implements DocumentMetadataFactoryInterface { - private $client; - /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface - */ - private $resourceMetadataFactory; - private $decorated; + private Client $client; + private ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory; + private ?DocumentMetadataFactoryInterface $decorated; - /** - * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory - */ - public function __construct(Client $client, $resourceMetadataFactory, ?DocumentMetadataFactoryInterface $decorated = null) + public function __construct(Client $client, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ?DocumentMetadataFactoryInterface $decorated = null) { $this->client = $client; $this->resourceMetadataFactory = $resourceMetadataFactory; @@ -69,13 +60,8 @@ public function create(string $resourceClass): DocumentMetadata return $documentMetadata; } - /** @var ResourceMetadata|ResourceMetadataCollection */ $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if ($resourceMetadata instanceof ResourceMetadata) { - $resourceShortName = $resourceMetadata->getShortName(); - } else { - $resourceShortName = $resourceMetadata->getOperation()->getShortName(); - } + $resourceShortName = $resourceMetadata->getOperation()->getShortName(); if (null === $resourceShortName) { return $this->handleNotFound($documentMetadata, $resourceClass); diff --git a/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php b/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php index fb1d1da7098..eb56bd0709e 100644 --- a/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php +++ b/src/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php @@ -25,8 +25,8 @@ */ final class ConfiguredDocumentMetadataFactory implements DocumentMetadataFactoryInterface { - private $mapping; - private $decorated; + private array $mapping; + private ?DocumentMetadataFactoryInterface $decorated; public function __construct(array $mapping, ?DocumentMetadataFactoryInterface $decorated = null) { diff --git a/src/Elasticsearch/Metadata/Resource/Factory/ElasticsearchProviderResourceMetadataCollectionFactory.php b/src/Elasticsearch/Metadata/Resource/Factory/ElasticsearchProviderResourceMetadataCollectionFactory.php index f61ab4179e7..2f69b874378 100644 --- a/src/Elasticsearch/Metadata/Resource/Factory/ElasticsearchProviderResourceMetadataCollectionFactory.php +++ b/src/Elasticsearch/Metadata/Resource/Factory/ElasticsearchProviderResourceMetadataCollectionFactory.php @@ -24,12 +24,9 @@ final class ElasticsearchProviderResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface { - /** - * @var ResourceMetadataCollectionFactoryInterface - */ - private $decorated; + private ResourceMetadataCollectionFactoryInterface $decorated; - private $client; + private Client $client; public function __construct(Client $client, ResourceMetadataCollectionFactoryInterface $decorated) { diff --git a/src/Elasticsearch/Paginator.php b/src/Elasticsearch/Paginator.php index f04504f7e8f..182a0c70c61 100644 --- a/src/Elasticsearch/Paginator.php +++ b/src/Elasticsearch/Paginator.php @@ -27,13 +27,13 @@ */ final class Paginator implements \IteratorAggregate, PaginatorInterface { - private $denormalizer; - private $documents; - private $resourceClass; - private $limit; - private $offset; - private $cachedDenormalizedDocuments = []; - private $denormalizationContext = []; + private DenormalizerInterface $denormalizer; + private array $documents; + private string $resourceClass; + private int $limit; + private int $offset; + private array $cachedDenormalizedDocuments = []; + private array $denormalizationContext = []; public function __construct(DenormalizerInterface $denormalizer, array $documents, string $resourceClass, int $limit, int $offset, array $denormalizationContext = []) { diff --git a/src/Elasticsearch/Serializer/DocumentNormalizer.php b/src/Elasticsearch/Serializer/DocumentNormalizer.php index 7400c5e27f3..f0309ef0b06 100644 --- a/src/Elasticsearch/Serializer/DocumentNormalizer.php +++ b/src/Elasticsearch/Serializer/DocumentNormalizer.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Elasticsearch\Serializer; -use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; +use ApiPlatform\Api\IdentifiersExtractorInterface; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; use Symfony\Component\Serializer\Exception\LogicException; @@ -33,9 +33,9 @@ final class DocumentNormalizer extends ObjectNormalizer { public const FORMAT = 'elasticsearch'; - private $identifierExtractor; + private IdentifiersExtractorInterface $identifierExtractor; - public function __construct(IdentifierExtractorInterface $identifierExtractor, ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = []) + public function __construct(IdentifiersExtractorInterface $identifierExtractor, ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = []) { parent::__construct($classMetadataFactory, $nameConverter, $propertyAccessor, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext); diff --git a/src/Elasticsearch/Serializer/ItemNormalizer.php b/src/Elasticsearch/Serializer/ItemNormalizer.php index 86cf5f3090d..3b2d6eb13c1 100644 --- a/src/Elasticsearch/Serializer/ItemNormalizer.php +++ b/src/Elasticsearch/Serializer/ItemNormalizer.php @@ -30,7 +30,7 @@ final class ItemNormalizer implements NormalizerInterface, DenormalizerInterface { public const FORMAT = 'elasticsearch'; - private $decorated; + private NormalizerInterface $decorated; public function __construct(NormalizerInterface $decorated) { diff --git a/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php b/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php index a408a1181ad..d98b9dcabf8 100644 --- a/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php +++ b/src/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php @@ -26,7 +26,7 @@ */ final class InnerFieldsNameConverter implements AdvancedNameConverterInterface { - private $decorated; + private NameConverterInterface $decorated; public function __construct(?NameConverterInterface $decorated = null) { diff --git a/src/Elasticsearch/State/CollectionProvider.php b/src/Elasticsearch/State/CollectionProvider.php index 96fcbc4876d..f85106c97ff 100644 --- a/src/Elasticsearch/State/CollectionProvider.php +++ b/src/Elasticsearch/State/CollectionProvider.php @@ -33,11 +33,11 @@ */ final class CollectionProvider implements ProviderInterface { - private $client; - private $documentMetadataFactory; - private $denormalizer; - private $pagination; - private $collectionExtensions; + private Client $client; + private DocumentMetadataFactoryInterface $documentMetadataFactory; + private DenormalizerInterface $denormalizer; + private Pagination $pagination; + private iterable $collectionExtensions; /** * @param RequestBodySearchCollectionExtensionInterface[] $collectionExtensions @@ -59,20 +59,19 @@ public function __construct(Client $client, DocumentMetadataFactoryInterface $do public function provide(Operation $operation, array $uriVariables = [], array $context = []) { $resourceClass = $operation->getClass(); - $operationName = $operation->getName(); $documentMetadata = $this->documentMetadataFactory->create($resourceClass); $body = []; foreach ($this->collectionExtensions as $collectionExtension) { - $body = $collectionExtension->applyToCollection($body, $resourceClass, $operationName, $context); + $body = $collectionExtension->applyToCollection($body, $resourceClass, $operation, $context); } if (!isset($body['query']) && !isset($body['aggs'])) { $body['query'] = ['match_all' => new \stdClass()]; } - $limit = $body['size'] = $body['size'] ?? $this->pagination->getLimit($resourceClass, $operationName, $context); - $offset = $body['from'] = $body['from'] ?? $this->pagination->getOffset($resourceClass, $operationName, $context); + $limit = $body['size'] = $body['size'] ?? $this->pagination->getLimit($operation, $context); + $offset = $body['from'] = $body['from'] ?? $this->pagination->getOffset($operation, $context); $params = [ 'index' => $documentMetadata->getIndex(), diff --git a/src/Elasticsearch/State/ItemProvider.php b/src/Elasticsearch/State/ItemProvider.php index d0af8c93207..f36ac6fcc54 100644 --- a/src/Elasticsearch/State/ItemProvider.php +++ b/src/Elasticsearch/State/ItemProvider.php @@ -33,9 +33,9 @@ */ final class ItemProvider implements ProviderInterface { - private $client; - private $documentMetadataFactory; - private $denormalizer; + private Client $client; + private DocumentMetadataFactoryInterface $documentMetadataFactory; + private DenormalizerInterface $denormalizer; public function __construct(Client $client, DocumentMetadataFactoryInterface $documentMetadataFactory, DenormalizerInterface $denormalizer) { diff --git a/src/Elasticsearch/Util/FieldDatatypeTrait.php b/src/Elasticsearch/Util/FieldDatatypeTrait.php index e5fec39bb45..df518f2b0d1 100644 --- a/src/Elasticsearch/Util/FieldDatatypeTrait.php +++ b/src/Elasticsearch/Util/FieldDatatypeTrait.php @@ -14,10 +14,7 @@ namespace ApiPlatform\Elasticsearch\Util; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Exception\PropertyNotFoundException; -use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use Symfony\Component\PropertyInfo\Type; @@ -32,15 +29,9 @@ */ trait FieldDatatypeTrait { - /** - * @var PropertyMetadataFactoryInterface|LegacyPropertyMetadataFactoryInterface - */ - private $propertyMetadataFactory; + private PropertyMetadataFactoryInterface $propertyMetadataFactory; - /** - * @var ResourceClassResolverInterface - */ - private $resourceClassResolver; + private ResourceClassResolverInterface $resourceClassResolver; /** * Is the decomposed given property of the given resource class potentially mapped as a nested field in Elasticsearch? @@ -63,20 +54,13 @@ private function getNestedFieldPath(string $resourceClass, string $property): ?s } try { - /** @var ApiProperty|PropertyMetadata $propertyMetadata */ $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $currentProperty); } catch (PropertyNotFoundException $e) { return null; } - // TODO: 3.0 this is the default + allow multiple types - if ($propertyMetadata instanceof ApiProperty) { // @phpstan-ignore-line - $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; - } - - if ($propertyMetadata instanceof PropertyMetadata) { - $type = $propertyMetadata->getType(); - } + // TODO: 3.0 allow multiple types + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; if (null === $type) { return null; diff --git a/src/GraphQl/Resolver/Stage/SerializeStage.php b/src/GraphQl/Resolver/Stage/SerializeStage.php index 7032950a1f2..cbe326b1205 100644 --- a/src/GraphQl/Resolver/Stage/SerializeStage.php +++ b/src/GraphQl/Resolver/Stage/SerializeStage.php @@ -56,8 +56,8 @@ public function __invoke($itemOrCollection, string $resourceClass, Operation $op if (!($operation->canSerialize() ?? true)) { if ($isCollection) { - if ($this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context)) { - return 'cursor' === $this->pagination->getGraphQlPaginationType($resourceClass, $operationName) ? + if ($this->pagination->isGraphQlEnabled($operation, $context)) { + return 'cursor' === $this->pagination->getGraphQlPaginationType($operation) ? $this->getDefaultCursorBasedPaginatedData() : $this->getDefaultPageBasedPaginatedData(); } @@ -88,13 +88,13 @@ public function __invoke($itemOrCollection, string $resourceClass, Operation $op } if ($isCollection && is_iterable($itemOrCollection)) { - if (!$this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context)) { + if (!$this->pagination->isGraphQlEnabled($operation, $context)) { $data = []; foreach ($itemOrCollection as $index => $object) { $data[$index] = $this->normalizer->normalize($object, ItemNormalizer::FORMAT, $normalizationContext); } } else { - $data = 'cursor' === $this->pagination->getGraphQlPaginationType($resourceClass, $operationName) ? + $data = 'cursor' === $this->pagination->getGraphQlPaginationType($operation) ? $this->serializeCursorBasedPaginatedCollection($itemOrCollection, $normalizationContext, $context) : $this->serializePageBasedPaginatedCollection($itemOrCollection, $normalizationContext); } diff --git a/src/GraphQl/Type/FieldsBuilder.php b/src/GraphQl/Type/FieldsBuilder.php index ac3de4ecd55..db68a307a96 100644 --- a/src/GraphQl/Type/FieldsBuilder.php +++ b/src/GraphQl/Type/FieldsBuilder.php @@ -314,8 +314,8 @@ private function getResourceFieldConfiguration(?string $property, ?string $field } if (!$input && !$rootOperation instanceof Mutation && !$rootOperation instanceof Subscription && !$isStandardGraphqlType && $isCollectionType) { - if ($this->pagination->isGraphQlEnabled($resourceClass, $rootOperation->getName())) { - $args = $this->getGraphQlPaginationArgs($resourceClass, $rootOperation->getName()); + if ($this->pagination->isGraphQlEnabled($rootOperation)) { + $args = $this->getGraphQlPaginationArgs($rootOperation); } // Find the collection operation to get filters, there might be a smarter way to do this @@ -355,9 +355,9 @@ private function getResourceFieldConfiguration(?string $property, ?string $field return null; } - private function getGraphQlPaginationArgs(string $resourceClass, string $queryName): array + private function getGraphQlPaginationArgs(Operation $queryOperation): array { - $paginationType = $this->pagination->getGraphQlPaginationType($resourceClass, $queryName); + $paginationType = $this->pagination->getGraphQlPaginationType($queryOperation); if ('cursor' === $paginationType) { return [ @@ -522,7 +522,7 @@ private function convertType(Type $type, bool $input, Operation $rootOperation, } if ($this->typeBuilder->isCollection($type)) { - return $this->pagination->isGraphQlEnabled($resourceClass, $rootOperation->getName()) && !$input ? $this->typeBuilder->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $rootOperation->getName()) : GraphQLType::listOf($graphqlType); + return $this->pagination->isGraphQlEnabled($rootOperation) && !$input ? $this->typeBuilder->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $rootOperation) : GraphQLType::listOf($graphqlType); } return $forceNullable || !$graphqlType instanceof NullableType || $type->isNullable() || ($rootOperation instanceof Mutation && 'update' === $rootOperation->getName()) diff --git a/src/GraphQl/Type/TypeBuilder.php b/src/GraphQl/Type/TypeBuilder.php index 2d9330f8e86..650023b02fd 100644 --- a/src/GraphQl/Type/TypeBuilder.php +++ b/src/GraphQl/Type/TypeBuilder.php @@ -221,10 +221,10 @@ public function getNodeInterface(): InterfaceType /** * {@inheritdoc} */ - public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, string $operationName): GraphQLType + public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, Operation $operation): GraphQLType { $shortName = $resourceType->name; - $paginationType = $this->pagination->getGraphQlPaginationType($resourceClass, $operationName); + $paginationType = $this->pagination->getGraphQlPaginationType($operation); $connectionTypeKey = sprintf('%s%sConnection', $shortName, ucfirst($paginationType)); if ($this->typesContainer->has($connectionTypeKey)) { diff --git a/src/GraphQl/Type/TypeBuilderInterface.php b/src/GraphQl/Type/TypeBuilderInterface.php index ebe59a0fd4b..50bb0077893 100644 --- a/src/GraphQl/Type/TypeBuilderInterface.php +++ b/src/GraphQl/Type/TypeBuilderInterface.php @@ -43,7 +43,7 @@ public function getNodeInterface(): InterfaceType; /** * Gets the type of a paginated collection of the given resource type. */ - public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, string $operationName): GraphQLType; + public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, Operation $operation): GraphQLType; /** * Returns true if a type is a collection. diff --git a/src/State/Pagination/Pagination.php b/src/State/Pagination/Pagination.php index b1c3f6b5984..5df332d0420 100644 --- a/src/State/Pagination/Pagination.php +++ b/src/State/Pagination/Pagination.php @@ -13,13 +13,8 @@ namespace ApiPlatform\State\Pagination; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\ResourceClassNotFoundException; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Metadata\Operation; /** * Pagination configuration. @@ -28,21 +23,11 @@ */ final class Pagination { - private $options; - private $graphQlOptions; + private array $options; + private array $graphQlOptions; - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface|null - */ - private $resourceMetadataFactory; - - public function __construct($resourceMetadataFactory, array $options = [], array $graphQlOptions = []) + public function __construct(array $options = [], array $graphQlOptions = []) { - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; $this->options = array_merge([ 'enabled' => true, 'client_enabled' => false, @@ -85,11 +70,11 @@ public function getPage(array $context = []): int /** * Gets the current offset. */ - public function getOffset(string $resourceClass = null, string $operationName = null, array $context = []): int + public function getOffset(Operation $operation = null, array $context = []): int { $graphql = (bool) ($context['graphql_operation_name'] ?? false); - $limit = $this->getLimit($resourceClass, $operationName, $context); + $limit = $this->getLimit($operation, $context); if ($graphql && null !== ($after = $this->getParameterFromContext($context, 'after'))) { return false === ($after = base64_decode($after, true)) ? 0 : (int) $after + 1; @@ -117,33 +102,12 @@ public function getOffset(string $resourceClass = null, string $operationName = * * @throws InvalidArgumentException */ - public function getLimit(string $resourceClass = null, string $operationName = null, array $context = []): int + public function getLimit(Operation $operation = null, array $context = []): int { $graphql = (bool) ($context['graphql_operation_name'] ?? false); - $limit = $this->options['items_per_page']; - $clientLimit = $this->options['client_items_per_page']; - - $resourceMetadata = null; - if (null !== $resourceClass) { - /** - * @var ResourceMetadata|ResourceMetadataCollection - */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadata instanceof ResourceMetadata) { - $limit = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', $limit, true); - $clientLimit = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $clientLimit, true); - } else { - try { - $operation = $resourceMetadata->getOperation($operationName); - $limit = $operation->getPaginationItemsPerPage() ?? $limit; - $clientLimit = $operation->getPaginationClientItemsPerPage() ?? $clientLimit; - } catch (OperationNotFoundException $e) { - // GraphQl operation may not exist - } - } - } + $limit = $operation?->getPaginationItemsPerPage() ?? $this->options['items_per_page']; + $clientLimit = $operation?->getPaginationClientItemsPerPage() ?? $this->options['client_items_per_page']; if ($graphql && null !== ($first = $this->getParameterFromContext($context, 'first'))) { $limit = $first; @@ -160,22 +124,7 @@ public function getLimit(string $resourceClass = null, string $operationName = n if ($clientLimit) { $limit = (int) $this->getParameterFromContext($context, $this->options['items_per_page_parameter_name'], $limit); - $maxItemsPerPage = null; - - if ($resourceMetadata instanceof ResourceMetadata) { - $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'maximum_items_per_page', null, true); - if (null !== $maxItemsPerPage) { - @trigger_error('The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3.', \E_USER_DEPRECATED); - } - $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage ?? $this->options['maximum_items_per_page'], true); - } elseif ($resourceMetadata instanceof ResourceMetadataCollection) { - try { - $operation = $resourceMetadata->getOperation($operationName); - $maxItemsPerPage = $operation->getPaginationMaximumItemsPerPage() ?? $this->options['maximum_items_per_page']; - } catch (OperationNotFoundException $e) { - $maxItemsPerPage = $this->options['maximum_items_per_page']; - } - } + $maxItemsPerPage = $operation?->getPaginationMaximumItemsPerPage() ?? $this->options['maximum_items_per_page']; if (null !== $maxItemsPerPage && $limit > $maxItemsPerPage) { $limit = $maxItemsPerPage; @@ -199,40 +148,40 @@ public function getLimit(string $resourceClass = null, string $operationName = n * * @throws InvalidArgumentException */ - public function getPagination(string $resourceClass = null, string $operationName = null, array $context = []): array + public function getPagination(Operation $operation = null, array $context = []): array { $page = $this->getPage($context); - $limit = $this->getLimit($resourceClass, $operationName, $context); + $limit = $this->getLimit($operation, $context); if (0 === $limit && 1 < $page) { throw new InvalidArgumentException('Page should not be greater than 1 if limit is equal to 0'); } - return [$page, $this->getOffset($resourceClass, $operationName, $context), $limit]; + return [$page, $this->getOffset($operation, $context), $limit]; } /** * Is the pagination enabled? */ - public function isEnabled(string $resourceClass = null, string $operationName = null, array $context = []): bool + public function isEnabled(Operation $operation = null, array $context = []): bool { - return $this->getEnabled($context, $resourceClass, $operationName); + return $this->getEnabled($context, $operation); } /** * Is the pagination enabled for GraphQL? */ - public function isGraphQlEnabled(?string $resourceClass = null, ?string $operationName = null, array $context = []): bool + public function isGraphQlEnabled(?Operation $operation = null, array $context = []): bool { - return $this->getGraphQlEnabled($resourceClass, $operationName); + return $this->getGraphQlEnabled($operation); } /** * Is the partial pagination enabled? */ - public function isPartialEnabled(string $resourceClass = null, string $operationName = null, array $context = []): bool + public function isPartialEnabled(Operation $operation = null, array $context = []): bool { - return $this->getEnabled($context, $resourceClass, $operationName, true); + return $this->getEnabled($context, $operation, true); } public function getOptions(): array @@ -240,49 +189,21 @@ public function getOptions(): array return $this->options; } - public function getGraphQlPaginationType(string $resourceClass, string $operationName): string + public function getGraphQlPaginationType(Operation $operation): string { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadata instanceof ResourceMetadataCollection) { - $operation = $resourceMetadata->getOperation($operationName); - - return $operation->getPaginationType() ?? 'cursor'; - } - } catch (ResourceClassNotFoundException $e) { - return 'cursor'; - } catch (OperationNotFoundException $e) { - return 'cursor'; - } - - return (string) $resourceMetadata->getGraphqlAttribute($operationName, 'pagination_type', 'cursor', true); + return $operation->getPaginationType() ?? 'cursor'; } /** * Is the classic or partial pagination enabled? */ - private function getEnabled(array $context, string $resourceClass = null, string $operationName = null, bool $partial = false): bool + private function getEnabled(array $context, Operation $operation = null, bool $partial = false): bool { $enabled = $this->options[$partial ? 'partial' : 'enabled']; $clientEnabled = $this->options[$partial ? 'client_partial' : 'client_enabled']; - if (null !== $resourceClass) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadata instanceof ResourceMetadataCollection) { - try { - $operation = $resourceMetadata->getOperation($operationName); - $enabled = ($partial ? $operation->getPaginationPartial() : $operation->getPaginationEnabled()) ?? $enabled; - $clientEnabled = ($partial ? $operation->getPaginationClientPartial() : $operation->getPaginationClientEnabled()) ?? $clientEnabled; - } catch (OperationNotFoundException $e) { - // GraphQl operation may not exist - } - } else { - $enabled = $resourceMetadata->getCollectionOperationAttribute($operationName, $partial ? 'pagination_partial' : 'pagination_enabled', $enabled, true); - $clientEnabled = $resourceMetadata->getCollectionOperationAttribute($operationName, $partial ? 'pagination_client_partial' : 'pagination_client_enabled', $clientEnabled, true); - } - } + $enabled = ($partial ? $operation?->getPaginationPartial() : $operation?->getPaginationEnabled()) ?? $enabled; + $clientEnabled = ($partial ? $operation?->getPaginationClientPartial() : $operation?->getPaginationClientEnabled()) ?? $clientEnabled; if ($clientEnabled) { return filter_var($this->getParameterFromContext($context, $this->options[$partial ? 'partial_parameter_name' : 'enabled_parameter_name'], $enabled), \FILTER_VALIDATE_BOOLEAN); @@ -291,29 +212,11 @@ private function getEnabled(array $context, string $resourceClass = null, string return (bool) $enabled; } - private function getGraphQlEnabled(?string $resourceClass, ?string $operationName): bool + private function getGraphQlEnabled(?Operation $operation): bool { $enabled = $this->graphQlOptions['enabled']; - if (null !== $resourceClass) { - try { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadata instanceof ResourceMetadataCollection) { - $operation = $resourceMetadata->getOperation($operationName); - - return $operation->getPaginationEnabled() ?? $enabled; - } - } catch (ResourceClassNotFoundException $e) { - return $enabled; - } catch (OperationNotFoundException $e) { - return $enabled; - } - - return (bool) $resourceMetadata->getGraphqlAttribute($operationName, 'pagination_enabled', $enabled, true); - } - - return $enabled; + return $operation?->getPaginationEnabled() ?? $enabled; } /** diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 920d809bfe6..8b062f8fc0a 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -22,7 +22,7 @@ use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface as DoctrineQueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; -use ApiPlatform\Doctrine\Orm\Filter\AbstractContextAwareFilter as DoctrineOrmAbstractContextAwareFilter; +use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter as DoctrineOrmAbstractFilter; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\GraphQl\Error\ErrorHandlerInterface; use ApiPlatform\GraphQl\Resolver\MutationResolverInterface; @@ -507,7 +507,7 @@ private function registerDoctrineOrmConfiguration(ContainerBuilder $container, a ->addTag('api_platform.doctrine.orm.query_extension.item'); $container->registerForAutoconfiguration(DoctrineQueryCollectionExtensionInterface::class) ->addTag('api_platform.doctrine.orm.query_extension.collection'); - $container->registerForAutoconfiguration(DoctrineOrmAbstractContextAwareFilter::class) + $container->registerForAutoconfiguration(DoctrineOrmAbstractFilter::class) ->setBindings(['$requestStack' => null]); $loader->load('doctrine_orm.xml'); diff --git a/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml b/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml index 6ce17d97ba9..26cd5f3192c 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml @@ -83,7 +83,6 @@ - @@ -93,7 +92,6 @@ - @@ -102,7 +100,6 @@ %api_platform.collection.order% - @@ -120,7 +117,7 @@ - + diff --git a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml index ed332e74fa1..fc3bd048d13 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml @@ -25,7 +25,6 @@ - null %api_platform.collection.order_parameter_name% @@ -35,7 +34,6 @@ - null @@ -43,7 +41,6 @@ - null @@ -51,7 +48,6 @@ - null @@ -59,7 +55,6 @@ - null @@ -67,7 +62,6 @@ - null %api_platform.collection.exists_parameter_name% @@ -79,7 +73,6 @@ - %api_platform.eager_loading.max_joins% %api_platform.eager_loading.force_eager% null @@ -94,7 +87,6 @@ - @@ -104,7 +96,6 @@ - %api_platform.eager_loading.force_eager% @@ -114,7 +105,6 @@ - @@ -123,7 +113,6 @@ %api_platform.collection.order% - @@ -158,7 +147,6 @@ - null diff --git a/src/Symfony/Bundle/Resources/config/elasticsearch.xml b/src/Symfony/Bundle/Resources/config/elasticsearch.xml index c74b5231aed..3a3da700bb3 100644 --- a/src/Symfony/Bundle/Resources/config/elasticsearch.xml +++ b/src/Symfony/Bundle/Resources/config/elasticsearch.xml @@ -87,7 +87,6 @@ - @@ -100,7 +99,6 @@ - diff --git a/src/Test/DoctrineMongoDbOdmFilterTestCase.php b/src/Test/DoctrineMongoDbOdmFilterTestCase.php index 705d82d3cb5..e89881bfd4c 100644 --- a/src/Test/DoctrineMongoDbOdmFilterTestCase.php +++ b/src/Test/DoctrineMongoDbOdmFilterTestCase.php @@ -26,30 +26,15 @@ */ abstract class DoctrineMongoDbOdmFilterTestCase extends KernelTestCase { - /** - * @var DocumentManager - */ - protected $manager; + protected DocumentManager $manager; - /** - * @var ManagerRegistry - */ - protected $managerRegistry; + protected ManagerRegistry $managerRegistry; - /** - * @var DocumentRepository - */ - protected $repository; + protected DocumentRepository $repository; - /** - * @var string - */ - protected $resourceClass; + protected string $resourceClass; - /** - * @var string - */ - protected $filterClass; + protected string $filterClass; protected function setUp(): void { @@ -63,12 +48,12 @@ protected function setUp(): void /** * @dataProvider provideApplyTestData */ - public function testApply(?array $properties, array $filterParameters, array $expectedPipeline, callable $factory = null, string $resourceClass = null) + public function testApply(?array $properties, array $filterParameters, array $expectedPipeline, callable $factory = null, string $resourceClass = null): void { $this->doTestApply($properties, $filterParameters, $expectedPipeline, $factory, $resourceClass); } - protected function doTestApply(?array $properties, array $filterParameters, array $expectedPipeline, callable $filterFactory = null, string $resourceClass = null) + protected function doTestApply(?array $properties, array $filterParameters, array $expectedPipeline, callable $filterFactory = null, string $resourceClass = null): void { if (null === $filterFactory) { $filterFactory = function (ManagerRegistry $managerRegistry, array $properties = null): FilterInterface { diff --git a/src/Test/DoctrineMongoDbOdmTestCase.php b/src/Test/DoctrineMongoDbOdmTestCase.php index 455afd00545..467a9d053db 100644 --- a/src/Test/DoctrineMongoDbOdmTestCase.php +++ b/src/Test/DoctrineMongoDbOdmTestCase.php @@ -13,11 +13,11 @@ namespace ApiPlatform\Test; -use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Cache\ArrayCache; use Doctrine\ODM\MongoDB\Configuration; use Doctrine\ODM\MongoDB\DocumentManager; -use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver; +use Doctrine\ODM\MongoDB\Mapping\Driver\AttributeDriver; +use Doctrine\ODM\MongoDB\Mapping\Driver\AttributeReader; use PHPUnit\Framework\TestCase; use Symfony\Component\Cache\Adapter\ArrayAdapter; use function sys_get_temp_dir; @@ -41,7 +41,7 @@ public static function createTestDocumentManager($paths = []) $config->setHydratorDir(sys_get_temp_dir()); $config->setProxyNamespace('SymfonyTests\Doctrine'); $config->setHydratorNamespace('SymfonyTests\Doctrine'); - $config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), $paths)); + $config->setMetadataDriverImpl(new AttributeDriver($paths, new AttributeReader())); if (method_exists($config, 'setMetadataCache')) { $config->setMetadataCache(new ArrayAdapter()); } else { diff --git a/src/Test/DoctrineOrmFilterTestCase.php b/src/Test/DoctrineOrmFilterTestCase.php index 242b094ca21..94f9aaf1d2e 100644 --- a/src/Test/DoctrineOrmFilterTestCase.php +++ b/src/Test/DoctrineOrmFilterTestCase.php @@ -19,8 +19,6 @@ use Doctrine\ORM\EntityRepository; use Doctrine\Persistence\ManagerRegistry; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; /** * @internal @@ -29,30 +27,15 @@ */ abstract class DoctrineOrmFilterTestCase extends KernelTestCase { - /** - * @var ManagerRegistry - */ - protected $managerRegistry; + protected ManagerRegistry $managerRegistry; - /** - * @var EntityRepository - */ - protected $repository; + protected EntityRepository $repository; - /** - * @var string - */ - protected $resourceClass = Dummy::class; + protected string $resourceClass = Dummy::class; - /** - * @var string - */ - protected $alias = 'o'; + protected string $alias = 'o'; - /** - * @var string - */ - protected $filterClass; + protected string $filterClass; protected function setUp(): void { @@ -65,36 +48,21 @@ protected function setUp(): void /** * @dataProvider provideApplyTestData */ - public function testApply(?array $properties, array $filterParameters, string $expectedDql, array $expectedParameters = null, callable $factory = null, string $resourceClass = null) + public function testApply(?array $properties, array $filterParameters, string $expectedDql, array $expectedParameters = null, callable $factory = null, string $resourceClass = null): void { - $this->doTestApply(false, $properties, $filterParameters, $expectedDql, $expectedParameters, $factory, $resourceClass); + $this->doTestApply($properties, $filterParameters, $expectedDql, $expectedParameters, $factory, $resourceClass); } - /** - * @group legacy - * @dataProvider provideApplyTestData - */ - public function testApplyRequest(?array $properties, array $filterParameters, string $expectedDql, array $expectedParameters = null, callable $factory = null, string $resourceClass = null) - { - $this->doTestApply(true, $properties, $filterParameters, $expectedDql, $expectedParameters, $factory, $resourceClass); - } - - protected function doTestApply(bool $request, ?array $properties, array $filterParameters, string $expectedDql, array $expectedParameters = null, callable $filterFactory = null, string $resourceClass = null) + protected function doTestApply(?array $properties, array $filterParameters, string $expectedDql, array $expectedParameters = null, callable $filterFactory = null, string $resourceClass = null): void { if (null === $filterFactory) { - $filterFactory = function (ManagerRegistry $managerRegistry, array $properties = null, RequestStack $requestStack = null): FilterInterface { + $filterFactory = function (ManagerRegistry $managerRegistry, array $properties = null): FilterInterface { $filterClass = $this->filterClass; - return new $filterClass($managerRegistry, $requestStack, null, $properties); + return new $filterClass($managerRegistry, null, $properties); }; } - $requestStack = null; - if ($request) { - $requestStack = new RequestStack(); - $requestStack->push(Request::create('/api/dummies', 'GET', $filterParameters)); - } - $repository = $this->repository; if ($resourceClass) { /** @var EntityRepository $repository */ @@ -102,8 +70,8 @@ protected function doTestApply(bool $request, ?array $properties, array $filterP } $resourceClass = $resourceClass ?: $this->resourceClass; $queryBuilder = $repository->createQueryBuilder($this->alias); - $filterCallable = $filterFactory($this->managerRegistry, $properties, $requestStack); - $filterCallable->apply($queryBuilder, new QueryNameGenerator(), $resourceClass, null, $request ? [] : ['filters' => $filterParameters]); + $filterCallable = $filterFactory($this->managerRegistry, $properties); + $filterCallable->apply($queryBuilder, new QueryNameGenerator(), $resourceClass, null, ['filters' => $filterParameters]); $this->assertEquals($expectedDql, $queryBuilder->getQuery()->getDQL()); @@ -121,7 +89,7 @@ protected function doTestApply(bool $request, ?array $properties, array $filterP protected function buildFilter(?array $properties = null) { - return new $this->filterClass($this->managerRegistry, null, null, $properties); + return new $this->filterClass($this->managerRegistry, null, $properties); } abstract public function provideApplyTestData(): array; diff --git a/src/Util/RequestParser.php b/src/Util/RequestParser.php index 5d76abca243..32c3366c09c 100644 --- a/src/Util/RequestParser.php +++ b/src/Util/RequestParser.php @@ -29,17 +29,6 @@ private function __construct() { } - /** - * Gets a fixed request. - */ - public static function parseAndDuplicateRequest(Request $request): Request - { - $query = self::parseRequestParams(self::getQueryString($request) ?? ''); - $body = self::parseRequestParams($request->getContent()); - - return $request->duplicate($query, $body); - } - /** * Parses request parameters from the specified source. * diff --git a/tests/Doctrine/Common/Filter/BooleanFilterTestTrait.php b/tests/Doctrine/Common/Filter/BooleanFilterTestTrait.php index 3f24d39324b..bef80144d9f 100644 --- a/tests/Doctrine/Common/Filter/BooleanFilterTestTrait.php +++ b/tests/Doctrine/Common/Filter/BooleanFilterTestTrait.php @@ -18,7 +18,7 @@ */ trait BooleanFilterTestTrait { - public function testGetDescription() + public function testGetDescription(): void { $filter = $this->buildFilter([ 'id' => null, @@ -36,7 +36,7 @@ public function testGetDescription() ], $filter->getDescription($this->resourceClass)); } - public function testGetDescriptionDefaultFields() + public function testGetDescriptionDefaultFields(): void { $filter = $this->buildFilter(); diff --git a/tests/Doctrine/Common/Filter/OrderFilterTestTrait.php b/tests/Doctrine/Common/Filter/OrderFilterTestTrait.php index 78db64bbfd8..54d303e9467 100644 --- a/tests/Doctrine/Common/Filter/OrderFilterTestTrait.php +++ b/tests/Doctrine/Common/Filter/OrderFilterTestTrait.php @@ -19,7 +19,7 @@ */ trait OrderFilterTestTrait { - public function testGetDescription() + public function testGetDescription(): void { $filter = $this->buildFilter(['id' => null, 'name' => null, 'foo' => null]); diff --git a/tests/Doctrine/Common/Filter/SearchFilterTestTrait.php b/tests/Doctrine/Common/Filter/SearchFilterTestTrait.php index 38b77a6a251..d828f53c1d2 100644 --- a/tests/Doctrine/Common/Filter/SearchFilterTestTrait.php +++ b/tests/Doctrine/Common/Filter/SearchFilterTestTrait.php @@ -19,7 +19,7 @@ */ trait SearchFilterTestTrait { - public function testGetDescription() + public function testGetDescription(): void { $filter = $this->buildSearchFilter($this->managerRegistry, [ 'id' => null, diff --git a/tests/Doctrine/Odm/Extension/FilterExtensionTest.php b/tests/Doctrine/Odm/Extension/FilterExtensionTest.php index 06a4bb6e431..0f6a3a3be67 100644 --- a/tests/Doctrine/Odm/Extension/FilterExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/FilterExtensionTest.php @@ -16,15 +16,12 @@ use ApiPlatform\Api\FilterInterface as ApiFilterInterface; use ApiPlatform\Doctrine\Odm\Extension\FilterExtension; use ApiPlatform\Doctrine\Odm\Filter\FilterInterface; -use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Operations; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; use PHPUnit\Framework\TestCase; +use Prophecy\Argument; use Psr\Container\ContainerInterface; /** @@ -36,18 +33,16 @@ class FilterExtensionTest extends TestCase { use ProphecyTrait; - public function testApplyToCollectionWithValidFilters() + public function testApplyToCollectionWithValidFilters(): void { $aggregationBuilderProphecy = $this->prophesize(Builder::class); - $dummyMetadata = new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withFilters(['dummyFilter', 'dummyBadFilter'])]))]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); - $aggregationBuilder = $aggregationBuilderProphecy->reveal(); + $operation = (new GetCollection())->withFilters(['dummyFilter', 'dummyBadFilter']); + $mongoDbOdmFilterProphecy = $this->prophesize(FilterInterface::class); - $mongoDbOdmFilterProphecy->apply($aggregationBuilder, Dummy::class, 'get', ['filters' => []])->shouldBeCalled(); + $mongoDbOdmFilterProphecy->apply($aggregationBuilder, Dummy::class, $operation, ['filters' => []])->shouldBeCalled(); $ordinaryFilterProphecy = $this->prophesize(ApiFilterInterface::class); @@ -57,17 +52,18 @@ public function testApplyToCollectionWithValidFilters() $filterLocatorProphecy->get('dummyFilter')->willReturn($mongoDbOdmFilterProphecy->reveal())->shouldBeCalled(); $filterLocatorProphecy->get('dummyBadFilter')->willReturn($ordinaryFilterProphecy->reveal())->shouldBeCalled(); - $orderExtensionTest = new FilterExtension($resourceMetadataFactoryProphecy->reveal(), $filterLocatorProphecy->reveal()); - $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, 'get'); + $filterExtensionTest = new FilterExtension($filterLocatorProphecy->reveal()); + $filterExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, $operation); } - public function testApplyToCollectionWithoutFilters() + public function testApplyToCollectionWithoutFilters(): void { - $dummyMetadata = new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withFilters(['dummyFilter', 'dummyBadFilter'])]))]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); + $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); + + $filterLocatorProphecy->has(Argument::cetera())->willReturn(false); + $filterLocatorProphecy->get(Argument::cetera())->shouldNotBeCalled(); - $orderExtensionTest = new FilterExtension($resourceMetadataFactoryProphecy->reveal(), $this->prophesize(ContainerInterface::class)->reveal()); - $orderExtensionTest->applyToCollection($this->prophesize(Builder::class)->reveal(), Dummy::class, 'get'); + $filterExtensionTest = new FilterExtension($filterLocatorProphecy->reveal()); + $filterExtensionTest->applyToCollection($this->prophesize(Builder::class)->reveal(), Dummy::class, (new GetCollection())->withFilters(['dummyFilter', 'dummyBadFilter'])); } } diff --git a/tests/Doctrine/Odm/Extension/OrderExtensionTest.php b/tests/Doctrine/Odm/Extension/OrderExtensionTest.php index 9354f2ea689..80041cad7e4 100644 --- a/tests/Doctrine/Odm/Extension/OrderExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/OrderExtensionTest.php @@ -14,11 +14,7 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Extension; use ApiPlatform\Doctrine\Odm\Extension\OrderExtension; -use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Operations; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Dummy; use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; @@ -39,7 +35,7 @@ class OrderExtensionTest extends TestCase { use ProphecyTrait; - public function testApplyToCollectionWithValidOrder() + public function testApplyToCollectionWithValidOrder(): void { $aggregationBuilderProphecy = $this->prophesize(Builder::class); @@ -56,11 +52,11 @@ public function testApplyToCollectionWithValidOrder() $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($objectManagerProphecy->reveal()); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - $orderExtensionTest = new OrderExtension('asc', null, $managerRegistryProphecy->reveal()); + $orderExtensionTest = new OrderExtension('asc', $managerRegistryProphecy->reveal()); $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class); } - public function testApplyToCollectionWithWrongOrder() + public function testApplyToCollectionWithWrongOrder(): void { $aggregationBuilderProphecy = $this->prophesize(Builder::class); @@ -77,13 +73,12 @@ public function testApplyToCollectionWithWrongOrder() $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($objectManagerProphecy->reveal()); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - $orderExtensionTest = new OrderExtension(null, null, $managerRegistryProphecy->reveal()); + $orderExtensionTest = new OrderExtension(null, $managerRegistryProphecy->reveal()); $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class); } - public function testApplyToCollectionWithOrderOverridden() + public function testApplyToCollectionWithOrderOverridden(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $aggregationBuilderProphecy = $this->prophesize(Builder::class); $aggregationBuilderProphecy->getStage(0)->willThrow(new OutOfRangeException('message')); @@ -92,9 +87,6 @@ public function testApplyToCollectionWithOrderOverridden() $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']); - $dummyMetadata = new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withOrder(['foo' => 'DESC'])]))]); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $objectManagerProphecy = $this->prophesize(DocumentManager::class); $objectManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); @@ -102,13 +94,12 @@ public function testApplyToCollectionWithOrderOverridden() $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($objectManagerProphecy->reveal()); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - $orderExtensionTest = new OrderExtension('asc', $resourceMetadataFactoryProphecy->reveal(), $managerRegistryProphecy->reveal()); - $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, 'get'); + $orderExtensionTest = new OrderExtension('asc', $managerRegistryProphecy->reveal()); + $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, (new GetCollection())->withOrder(['foo' => 'DESC'])); } - public function testApplyToCollectionWithOrderOverriddenWithNoDirection() + public function testApplyToCollectionWithOrderOverriddenWithNoDirection(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $aggregationBuilderProphecy = $this->prophesize(Builder::class); $aggregationBuilderProphecy->getStage(0)->willThrow(new OutOfRangeException('message')); @@ -118,9 +109,6 @@ public function testApplyToCollectionWithOrderOverriddenWithNoDirection() $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->getIdentifier()->shouldBeCalled()->willReturn(['name']); - $dummyMetadata = new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withOrder(['foo', 'bar' => 'DESC'])]))]); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $objectManagerProphecy = $this->prophesize(DocumentManager::class); $objectManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); @@ -128,13 +116,12 @@ public function testApplyToCollectionWithOrderOverriddenWithNoDirection() $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($objectManagerProphecy->reveal()); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - $orderExtensionTest = new OrderExtension('asc', $resourceMetadataFactoryProphecy->reveal(), $managerRegistryProphecy->reveal()); - $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, 'get'); + $orderExtensionTest = new OrderExtension('asc', $managerRegistryProphecy->reveal()); + $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, (new GetCollection())->withOrder(['foo', 'bar' => 'DESC'])); } - public function testApplyToCollectionWithOrderOverriddenWithAssociation() + public function testApplyToCollectionWithOrderOverriddenWithAssociation(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $aggregationBuilderProphecy = $this->prophesize(Builder::class); $lookupProphecy = $this->prophesize(Lookup::class); @@ -154,9 +141,6 @@ public function testApplyToCollectionWithOrderOverriddenWithAssociation() $classMetadataProphecy->hasReference('author')->shouldBeCalled()->willReturn(true); $classMetadataProphecy->getFieldMapping('author')->shouldBeCalled()->willReturn(['isOwningSide' => true, 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_ID]); - $dummyMetadata = new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withOrder(['author.name'])]))]); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $objectManagerProphecy = $this->prophesize(DocumentManager::class); $objectManagerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); @@ -164,11 +148,11 @@ public function testApplyToCollectionWithOrderOverriddenWithAssociation() $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldBeCalled()->willReturn($objectManagerProphecy->reveal()); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - $orderExtensionTest = new OrderExtension('asc', $resourceMetadataFactoryProphecy->reveal(), $managerRegistryProphecy->reveal()); - $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, 'get'); + $orderExtensionTest = new OrderExtension('asc', $managerRegistryProphecy->reveal()); + $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class, (new GetCollection())->withOrder(['author.name'])); } - public function testApplyToCollectionWithExistingSortStage() + public function testApplyToCollectionWithExistingSortStage(): void { $aggregationBuilderProphecy = $this->prophesize(Builder::class); @@ -178,7 +162,7 @@ public function testApplyToCollectionWithExistingSortStage() $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); $managerRegistryProphecy->getManagerForClass(Dummy::class)->shouldNotBeCalled(); - $orderExtensionTest = new OrderExtension('asc', null, $managerRegistryProphecy->reveal()); + $orderExtensionTest = new OrderExtension('asc', $managerRegistryProphecy->reveal()); $orderExtensionTest->applyToCollection($aggregationBuilder, Dummy::class); } } diff --git a/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php b/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php index 237254611db..ae62027e2e3 100644 --- a/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php +++ b/tests/Doctrine/Odm/Extension/PaginationExtensionTest.php @@ -16,11 +16,7 @@ use ApiPlatform\Doctrine\Odm\Extension\PaginationExtension; use ApiPlatform\Doctrine\Odm\Paginator; use ApiPlatform\Exception\InvalidArgumentException; -use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Operations; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\Pagination\PartialPaginatorInterface; @@ -48,7 +44,6 @@ class PaginationExtensionTest extends TestCase use ProphecyTrait; private $managerRegistryProphecy; - private $resourceMetadataFactoryProphecy; /** * {@inheritdoc} @@ -58,16 +53,11 @@ protected function setUp(): void parent::setUp(); $this->managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); } - public function testApplyToCollection() + public function testApplyToCollection(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationItemsPerPage(40)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'page_parameter_name' => '_page', ]); @@ -77,19 +67,14 @@ public function testApplyToCollection() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationItemsPerPage(40), $context); } - public function testApplyToCollectionWithItemPerPageZero() + public function testApplyToCollectionWithItemPerPageZero(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationItemsPerPage(0)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'items_per_page' => 0, 'page_parameter_name' => '_page', ]); @@ -100,22 +85,17 @@ public function testApplyToCollectionWithItemPerPageZero() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationItemsPerPage(0), $context); } - public function testApplyToCollectionWithItemPerPageZeroAndPage2() + public function testApplyToCollectionWithItemPerPageZeroAndPage2(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Page should not be greater than 1 if limit is equal to 0'); - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationItemsPerPage(0)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'items_per_page' => 0, 'page_parameter_name' => '_page', ]); @@ -127,22 +107,17 @@ public function testApplyToCollectionWithItemPerPageZeroAndPage2() $extension = new PaginationExtension( $this->prophesize(ManagerRegistry::class)->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationItemsPerPage(0), $context); } - public function testApplyToCollectionWithItemPerPageLessThan0() + public function testApplyToCollectionWithItemPerPageLessThan0(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Limit should not be less than 0'); - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationItemsPerPage(-20)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'items_per_page' => -20, 'page_parameter_name' => '_page', ]); @@ -154,19 +129,14 @@ public function testApplyToCollectionWithItemPerPageLessThan0() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationItemsPerPage(-20), $context); } - public function testApplyToCollectionWithItemPerPageTooHigh() + public function testApplyToCollectionWithItemPerPageTooHigh(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationClientItemsPerPage(true)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'page_parameter_name' => '_page', 'maximum_items_per_page' => 300, ]); @@ -177,19 +147,14 @@ public function testApplyToCollectionWithItemPerPageTooHigh() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationClientItemsPerPage(true), $context); } - public function testApplyToCollectionWithGraphql() + public function testApplyToCollectionWithGraphql(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationClientItemsPerPage(true)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory); + $pagination = new Pagination(); $aggregationBuilderProphecy = $this->mockAggregationBuilder(10, 5); @@ -197,19 +162,14 @@ public function testApplyToCollectionWithGraphql() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationClientItemsPerPage(true), $context); } - public function testApplyToCollectionWithGraphqlAndCountContext() + public function testApplyToCollectionWithGraphqlAndCountContext(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationClientItemsPerPage(true)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory); + $pagination = new Pagination(); $aggregationBuilderProphecy = $this->mockAggregationBuilder(4, 5); $iteratorProphecy = $this->prophesize(Iterator::class); @@ -226,19 +186,14 @@ public function testApplyToCollectionWithGraphqlAndCountContext() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationClientItemsPerPage(true), $context); } - public function testApplyToCollectionNoFilters() + public function testApplyToCollectionNoFilters(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory); + $pagination = new Pagination(); $aggregationBuilderProphecy = $this->mockAggregationBuilder(0, 30); @@ -246,19 +201,14 @@ public function testApplyToCollectionNoFilters() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true), $context); } - public function testApplyToCollectionPaginationDisabled() + public function testApplyToCollectionPaginationDisabled(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => new GetCollection()]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'enabled' => false, ]); @@ -269,19 +219,14 @@ public function testApplyToCollectionPaginationDisabled() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', new GetCollection(), $context); } - public function testApplyToCollectionGraphQlPaginationDisabled() + public function testApplyToCollectionGraphQlPaginationDisabled(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => new GetCollection()]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [], [ + $pagination = new Pagination([], [ 'enabled' => false, ]); @@ -292,19 +237,14 @@ public function testApplyToCollectionGraphQlPaginationDisabled() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', new GetCollection(), $context); } - public function testApplyToCollectionWithMaximumItemsPerPage() + public function testApplyToCollectionWithMaximumItemsPerPage(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationMaximumItemsPerPage(80)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'client_enabled' => true, 'client_items_per_page' => true, 'pagination_maximum_items_per_page' => 50, @@ -316,88 +256,65 @@ public function testApplyToCollectionWithMaximumItemsPerPage() $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', 'get', $context); + $extension->applyToCollection($aggregationBuilderProphecy->reveal(), 'Foo', (new GetCollection())->withPaginationEnabled(true)->withPaginationClientEnabled(true)->withPaginationMaximumItemsPerPage(80), $context); } - public function testSupportsResult() + public function testSupportsResult(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withPaginationEnabled(true)]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory); + $pagination = new Pagination(); $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $this->assertTrue($extension->supportsResult('Foo', 'get')); + $this->assertTrue($extension->supportsResult('Foo', (new GetCollection())->withPaginationEnabled(true))); } - public function testSupportsResultClientNotAllowedToPaginate() + public function testSupportsResultClientNotAllowedToPaginate(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => new GetCollection()]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'enabled' => false, 'client_enabled' => false, ]); $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $this->assertFalse($extension->supportsResult('Foo', 'get', ['filters' => ['pagination' => true]])); + $this->assertFalse($extension->supportsResult('Foo', new GetCollection(), ['filters' => ['pagination' => true]])); } - public function testSupportsResultPaginationDisabled() + public function testSupportsResultPaginationDisabled(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => new GetCollection()]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [ + $pagination = new Pagination([ 'enabled' => false, ]); $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $this->assertFalse($extension->supportsResult('Foo', 'get', ['filters' => ['enabled' => false]])); + $this->assertFalse($extension->supportsResult('Foo', new GetCollection(), ['filters' => ['enabled' => false]])); } - public function testSupportsResultGraphQlPaginationDisabled() + public function testSupportsResultGraphQlPaginationDisabled(): void { - $dummyMetadata = new ResourceMetadataCollection('Foo', [(new ApiResource())->withOperations(new Operations(['get' => new GetCollection()]))]); - $this->resourceMetadataFactoryProphecy->create('Foo')->willReturn($dummyMetadata); - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory, [], [ + $pagination = new Pagination([], [ 'enabled' => false, ]); $extension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $this->assertFalse($extension->supportsResult('Foo', 'get', ['filters' => ['enabled' => false], 'graphql_operation_name' => 'query'])); + $this->assertFalse($extension->supportsResult('Foo', new GetCollection(), ['filters' => ['enabled' => false], 'graphql_operation_name' => 'query'])); } - public function testGetResult() + public function testGetResult(): void { - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory); + $pagination = new Pagination(); $fixturesPath = \dirname((string) (new \ReflectionClass(Dummy::class))->getFileName()); $config = DoctrineMongoDbOdmSetup::createAnnotationMetadataConfiguration([$fixturesPath], true); @@ -405,9 +322,6 @@ public function testGetResult() $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($documentManager); - $dummyMetadata = new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['get' => new GetCollection()]))]); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $iteratorProphecy = $this->prophesize(Iterator::class); $iteratorProphecy->toArray()->willReturn([ [ @@ -437,21 +351,18 @@ public function testGetResult() $paginationExtension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $result = $paginationExtension->getResult($aggregationBuilderProphecy->reveal(), Dummy::class, 'get'); + $result = $paginationExtension->getResult($aggregationBuilderProphecy->reveal(), Dummy::class, new GetCollection()); $this->assertInstanceOf(PartialPaginatorInterface::class, $result); $this->assertInstanceOf(PaginatorInterface::class, $result); } - public function testGetResultWithExecuteOptions() + public function testGetResultWithExecuteOptions(): void { - $resourceMetadataFactory = $this->resourceMetadataFactoryProphecy->reveal(); - - $pagination = new Pagination($resourceMetadataFactory); + $pagination = new Pagination(); $fixturesPath = \dirname((string) (new \ReflectionClass(Dummy::class))->getFileName()); $config = DoctrineMongoDbOdmSetup::createAnnotationMetadataConfiguration([$fixturesPath], true); @@ -459,9 +370,6 @@ public function testGetResultWithExecuteOptions() $this->managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($documentManager); - $dummyMetadata = new ResourceMetadataCollection(Dummy::class, [(new ApiResource())->withOperations(new Operations(['get' => (new GetCollection())->withExtraProperties(['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]])]))]); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($dummyMetadata); - $iteratorProphecy = $this->prophesize(Iterator::class); $iteratorProphecy->toArray()->willReturn([ [ @@ -491,11 +399,10 @@ public function testGetResultWithExecuteOptions() $paginationExtension = new PaginationExtension( $this->managerRegistryProphecy->reveal(), - $resourceMetadataFactory, $pagination ); - $result = $paginationExtension->getResult($aggregationBuilderProphecy->reveal(), Dummy::class, 'get'); + $result = $paginationExtension->getResult($aggregationBuilderProphecy->reveal(), Dummy::class, (new GetCollection())->withExtraProperties(['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]])); $this->assertInstanceOf(PartialPaginatorInterface::class, $result); $this->assertInstanceOf(PaginatorInterface::class, $result); diff --git a/tests/Doctrine/Odm/Filter/BooleanFilterTest.php b/tests/Doctrine/Odm/Filter/BooleanFilterTest.php index 901743320a0..e59f4b47329 100644 --- a/tests/Doctrine/Odm/Filter/BooleanFilterTest.php +++ b/tests/Doctrine/Odm/Filter/BooleanFilterTest.php @@ -20,7 +20,6 @@ /** * @group mongodb - * @group legacy * * @author Alan Poulain */ @@ -28,8 +27,8 @@ class BooleanFilterTest extends DoctrineMongoDbOdmFilterTestCase { use BooleanFilterTestTrait; - protected $filterClass = BooleanFilter::class; - protected $resourceClass = Dummy::class; + protected string $filterClass = BooleanFilter::class; + protected string $resourceClass = Dummy::class; public function provideApplyTestData(): array { diff --git a/tests/Doctrine/Odm/Filter/DateFilterTest.php b/tests/Doctrine/Odm/Filter/DateFilterTest.php index 4cfa6d4116a..33c7854e229 100644 --- a/tests/Doctrine/Odm/Filter/DateFilterTest.php +++ b/tests/Doctrine/Odm/Filter/DateFilterTest.php @@ -28,8 +28,8 @@ class DateFilterTest extends DoctrineMongoDbOdmFilterTestCase { use DateFilterTestTrait; - protected $filterClass = DateFilter::class; - protected $resourceClass = Dummy::class; + protected string $filterClass = DateFilter::class; + protected string $resourceClass = Dummy::class; public function provideApplyTestData(): array { diff --git a/tests/Doctrine/Odm/Filter/ExistsFilterTest.php b/tests/Doctrine/Odm/Filter/ExistsFilterTest.php index c5a5b9ad513..37cb8a093af 100644 --- a/tests/Doctrine/Odm/Filter/ExistsFilterTest.php +++ b/tests/Doctrine/Odm/Filter/ExistsFilterTest.php @@ -28,10 +28,10 @@ class ExistsFilterTest extends DoctrineMongoDbOdmFilterTestCase { use ExistsFilterTestTrait; - protected $filterClass = ExistsFilter::class; - protected $resourceClass = Dummy::class; + protected string $filterClass = ExistsFilter::class; + protected string $resourceClass = Dummy::class; - public function testGetDescriptionDefaultFields() + public function testGetDescriptionDefaultFields(): void { $filter = $this->buildFilter(); @@ -430,38 +430,6 @@ public function provideApplyTestData(): array ); } - /** - * @group legacy - * @expectedDeprecation The ExistsFilter syntax "description[exists]=true/false" is deprecated since 2.5. Use the syntax "exists[description]=true/false" instead. - */ - public function testLegacyExistsAfterSyntax() - { - $args = [ - [ - 'description' => null, - ], - [ - 'description' => [ - 'exists' => 'true', - ], - ], - [ - [ - '$match' => [ - 'description' => [ - '$ne' => null, - ], - ], - ], - ], - function (ManagerRegistry $managerRegistry, array $properties = null): ExistsFilter { - return new ExistsFilter($managerRegistry, null, $properties, 'exists'); - }, - ]; - - $this->testApply(...$args); - } - protected function buildFilter(?array $properties = null) { return new $this->filterClass($this->managerRegistry, null, $properties, 'exists'); diff --git a/tests/Doctrine/Odm/Filter/NumericFilterTest.php b/tests/Doctrine/Odm/Filter/NumericFilterTest.php index 16887430492..fd5101ef317 100644 --- a/tests/Doctrine/Odm/Filter/NumericFilterTest.php +++ b/tests/Doctrine/Odm/Filter/NumericFilterTest.php @@ -27,10 +27,10 @@ class NumericFilterTest extends DoctrineMongoDbOdmFilterTestCase { use NumericFilterTestTrait; - protected $filterClass = NumericFilter::class; - protected $resourceClass = Dummy::class; + protected string $filterClass = NumericFilter::class; + protected string $resourceClass = Dummy::class; - public function testGetDescriptionDefaultFields() + public function testGetDescriptionDefaultFields(): void { $filter = $this->buildFilter(); diff --git a/tests/Doctrine/Odm/Filter/OrderFilterTest.php b/tests/Doctrine/Odm/Filter/OrderFilterTest.php index f2aeb429e29..41267927ce1 100644 --- a/tests/Doctrine/Odm/Filter/OrderFilterTest.php +++ b/tests/Doctrine/Odm/Filter/OrderFilterTest.php @@ -30,10 +30,10 @@ class OrderFilterTest extends DoctrineMongoDbOdmFilterTestCase { use OrderFilterTestTrait; - protected $filterClass = OrderFilter::class; - protected $resourceClass = Dummy::class; + protected string $filterClass = OrderFilter::class; + protected string $resourceClass = Dummy::class; - public function testGetDescriptionDefaultFields() + public function testGetDescriptionDefaultFields(): void { $filter = $this->buildFilter(); diff --git a/tests/Doctrine/Odm/Filter/RangeFilterTest.php b/tests/Doctrine/Odm/Filter/RangeFilterTest.php index 012afc82b83..bd3678d917d 100644 --- a/tests/Doctrine/Odm/Filter/RangeFilterTest.php +++ b/tests/Doctrine/Odm/Filter/RangeFilterTest.php @@ -27,10 +27,10 @@ class RangeFilterTest extends DoctrineMongoDbOdmFilterTestCase { use RangeFilterTestTrait; - protected $filterClass = RangeFilter::class; - protected $resourceClass = Dummy::class; + protected string $filterClass = RangeFilter::class; + protected string $resourceClass = Dummy::class; - public function testGetDescriptionDefaultFields() + public function testGetDescriptionDefaultFields(): void { $filter = $this->buildFilter(); diff --git a/tests/Doctrine/Odm/Filter/SearchFilterTest.php b/tests/Doctrine/Odm/Filter/SearchFilterTest.php index 67fa41815c4..6f25c16c82c 100644 --- a/tests/Doctrine/Odm/Filter/SearchFilterTest.php +++ b/tests/Doctrine/Odm/Filter/SearchFilterTest.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Tests\Doctrine\Odm\Filter; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; use ApiPlatform\Doctrine\Odm\Filter\SearchFilter; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Test\DoctrineMongoDbOdmFilterTestCase; @@ -31,15 +30,14 @@ * @author Alan Poulain * * @group mongodb - * @group legacy */ class SearchFilterTest extends DoctrineMongoDbOdmFilterTestCase { use ProphecyTrait; use SearchFilterTestTrait; - protected $filterClass = SearchFilter::class; - protected $resourceClass = Dummy::class; + protected string $filterClass = SearchFilter::class; + protected string $resourceClass = Dummy::class; public function testGetDescriptionDefaultFields() { @@ -740,7 +738,7 @@ public function provideApplyTestData(): array ); } - protected function buildSearchFilter(ManagerRegistry $managerRegistry, ?array $properties = null) + protected function buildSearchFilter(ManagerRegistry $managerRegistry, ?array $properties = null): SearchFilter { $relatedDummyProphecy = $this->prophesize(RelatedDummy::class); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); @@ -758,9 +756,6 @@ protected function buildSearchFilter(ManagerRegistry $managerRegistry, ?array $p $iriConverter = $iriConverterProphecy->reveal(); $propertyAccessor = static::$kernel->getContainer()->get('test.property_accessor'); - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - return new SearchFilter($managerRegistry, $iriConverter, $identifierExtractorProphecy->reveal(), $propertyAccessor, null, $properties, new CustomConverter()); + return new SearchFilter($managerRegistry, $iriConverter, null, $propertyAccessor, null, $properties, new CustomConverter()); } } diff --git a/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php b/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php index 075f169d731..00a1835a301 100644 --- a/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php +++ b/tests/Doctrine/Odm/Metadata/Property/DoctrineMongoDbOdmPropertyMetadataFactoryTest.php @@ -32,7 +32,7 @@ class DoctrineMongoDbOdmPropertyMetadataFactoryTest extends TestCase { use ProphecyTrait; - public function testCreateNoManager() + public function testCreateNoManager(): void { $propertyMetadata = new ApiProperty(); $propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -46,7 +46,7 @@ public function testCreateNoManager() $this->assertEquals($doctrineMongoDbOdmPropertyMetadataFactory->create(Dummy::class, 'id'), $propertyMetadata); } - public function testCreateIsIdentifier() + public function testCreateIsIdentifier(): void { $propertyMetadata = new ApiProperty(); $propertyMetadata = $propertyMetadata->withIdentifier(true); @@ -67,7 +67,7 @@ public function testCreateIsIdentifier() $this->assertEquals($doctrineMongoDbOdmPropertyMetadataFactory->create(Dummy::class, 'id'), $propertyMetadata); } - public function testCreateIsWritable() + public function testCreateIsWritable(): void { $propertyMetadata = new ApiProperty(); $propertyMetadata = $propertyMetadata->withWritable(false); @@ -92,7 +92,7 @@ public function testCreateIsWritable() $this->assertEquals($doctrinePropertyMetadata->isWritable(), false); } - public function testCreateClassMetadata() + public function testCreateClassMetadata(): void { $propertyMetadata = new ApiProperty(); diff --git a/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php b/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php index 2dc7ac2a522..0d40a37e73f 100644 --- a/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php +++ b/tests/Doctrine/Odm/Metadata/Resource/DoctrineMongoDbOdmResourceCollectionMetadataFactoryTest.php @@ -55,7 +55,7 @@ private function getResourceMetadataCollectionFactory(Operation $operation) return $resourceMetadataCollectionFactory->reveal(); } - public function testWithoutManager() + public function testWithoutManager(): void { if (!class_exists(DocumentManager::class)) { $this->markTestSkipped('ODM not installed'); @@ -75,7 +75,7 @@ public function testWithoutManager() /** * @dataProvider operationProvider */ - public function testWithProvider(Operation $operation, string $expectedProvider = null, string $expectedProcessor = null) + public function testWithProvider(Operation $operation, string $expectedProvider = null, string $expectedProcessor = null): void { if (!class_exists(DocumentManager::class)) { $this->markTestSkipped('ODM not installed'); diff --git a/tests/Doctrine/Odm/PaginatorTest.php b/tests/Doctrine/Odm/PaginatorTest.php index a6f447a47c3..c0e0eca925b 100644 --- a/tests/Doctrine/Odm/PaginatorTest.php +++ b/tests/Doctrine/Odm/PaginatorTest.php @@ -31,14 +31,8 @@ class PaginatorTest extends TestCase /** * @dataProvider initializeProvider - * - * @param mixed $firstResult - * @param mixed $maxResults - * @param mixed $totalItems - * @param mixed $currentPage - * @param mixed $lastPage */ - public function testInitialize($firstResult, $maxResults, $totalItems, $currentPage, $lastPage) + public function testInitialize(int $firstResult, int $maxResults, int $totalItems, int $currentPage, int $lastPage): void { $paginator = $this->getPaginator($firstResult, $maxResults, $totalItems); @@ -47,7 +41,7 @@ public function testInitialize($firstResult, $maxResults, $totalItems, $currentP $this->assertEquals($maxResults, $paginator->getItemsPerPage()); } - public function testInitializeWithFacetStageNotApplied() + public function testInitializeWithFacetStageNotApplied(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('$facet stage was not applied to the aggregation pipeline.'); @@ -55,7 +49,7 @@ public function testInitializeWithFacetStageNotApplied() $this->getPaginatorWithMissingStage(); } - public function testInitializeWithResultsFacetNotApplied() + public function testInitializeWithResultsFacetNotApplied(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('"results" facet was not applied to the aggregation pipeline.'); @@ -63,7 +57,7 @@ public function testInitializeWithResultsFacetNotApplied() $this->getPaginatorWithMissingStage(true); } - public function testInitializeWithCountFacetNotApplied() + public function testInitializeWithCountFacetNotApplied(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('"count" facet was not applied to the aggregation pipeline.'); @@ -71,7 +65,7 @@ public function testInitializeWithCountFacetNotApplied() $this->getPaginatorWithMissingStage(true, true); } - public function testInitializeWithSkipStageNotApplied() + public function testInitializeWithSkipStageNotApplied(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('$skip stage was not applied to the facet stage of the aggregation pipeline.'); @@ -79,7 +73,7 @@ public function testInitializeWithSkipStageNotApplied() $this->getPaginatorWithMissingStage(true, true, true); } - public function testInitializeWithLimitStageNotApplied() + public function testInitializeWithLimitStageNotApplied(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('$limit stage was not applied to the facet stage of the aggregation pipeline.'); @@ -87,7 +81,7 @@ public function testInitializeWithLimitStageNotApplied() $this->getPaginatorWithMissingStage(true, true, true, true); } - public function testInitializeWithLimitZeroStageApplied() + public function testInitializeWithLimitZeroStageApplied(): void { $paginator = $this->getPaginator(0, 5, 0, true); @@ -96,7 +90,7 @@ public function testInitializeWithLimitZeroStageApplied() $this->assertEquals(0, $paginator->getItemsPerPage()); } - public function testInitializeWithNoCount() + public function testInitializeWithNoCount(): void { $paginator = $this->getPaginatorWithNoCount(); @@ -105,14 +99,14 @@ public function testInitializeWithNoCount() $this->assertEquals(15, $paginator->getItemsPerPage()); } - public function testGetIterator() + public function testGetIterator(): void { $paginator = $this->getPaginator(); $this->assertSame($paginator->getIterator(), $paginator->getIterator(), 'Iterator should be cached'); } - private function getPaginator($firstResult = 1, $maxResults = 15, $totalItems = 42, $limitZero = false) + private function getPaginator($firstResult = 1, $maxResults = 15, $totalItems = 42, $limitZero = false): Paginator { $iterator = $this->prophesize(Iterator::class); $pipeline = [ @@ -146,7 +140,7 @@ private function getPaginator($firstResult = 1, $maxResults = 15, $totalItems = return new Paginator($iterator->reveal(), $documentManager->getUnitOfWork(), Dummy::class, $pipeline); } - private function getPaginatorWithMissingStage($facet = false, $results = false, $count = false, $maxResults = false) + private function getPaginatorWithMissingStage($facet = false, $results = false, $count = false, $maxResults = false): Paginator { $pipeline = []; @@ -177,7 +171,7 @@ private function getPaginatorWithMissingStage($facet = false, $results = false, return new Paginator($iterator->reveal(), $documentManager->getUnitOfWork(), Dummy::class, $pipeline); } - private function getPaginatorWithNoCount($firstResult = 1, $maxResults = 15) + private function getPaginatorWithNoCount($firstResult = 1, $maxResults = 15): Paginator { $iterator = $this->prophesize(Iterator::class); $pipeline = [ @@ -207,7 +201,7 @@ private function getPaginatorWithNoCount($firstResult = 1, $maxResults = 15) return new Paginator($iterator->reveal(), $documentManager->getUnitOfWork(), Dummy::class, $pipeline); } - public function initializeProvider() + public function initializeProvider(): array { return [ 'First of three pages of 15 items each' => [0, 15, 42, 1, 3], diff --git a/tests/Doctrine/Odm/State/CollectionProviderTest.php b/tests/Doctrine/Odm/State/CollectionProviderTest.php index bd976a3102f..8498e64509f 100644 --- a/tests/Doctrine/Odm/State/CollectionProviderTest.php +++ b/tests/Doctrine/Odm/State/CollectionProviderTest.php @@ -17,11 +17,8 @@ use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\State\CollectionProvider; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ProviderEntity; use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; @@ -53,7 +50,7 @@ protected function setUp(): void $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); } - public function testGetCollection() + public function testGetCollection(): void { $iterator = $this->prophesize(Iterator::class)->reveal(); @@ -69,17 +66,17 @@ public function testGetCollection() $managerProphecy->getRepository(ProviderEntity::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); $this->managerRegistryProphecy->getManagerForClass(ProviderEntity::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); + $operation = (new GetCollection())->withName('foo')->withClass(ProviderEntity::class); - $this->resourceMetadataFactoryProphecy->create(ProviderEntity::class)->willReturn(new ResourceMetadataCollection(ProviderEntity::class, [(new ApiResource())->withOperations(new Operations(['foo' => $operation]))])); $extensionProphecy = $this->prophesize(AggregationCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, ProviderEntity::class, 'foo', [])->shouldBeCalled(); + $extensionProphecy->applyToCollection($aggregationBuilder, ProviderEntity::class, $operation, [])->shouldBeCalled(); $dataProvider = new CollectionProvider($this->resourceMetadataFactoryProphecy->reveal(), $this->managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); $this->assertEquals($iterator, $dataProvider->provide($operation, [])); } - public function testGetCollectionWithExecuteOptions() + public function testGetCollectionWithExecuteOptions(): void { $iterator = $this->prophesize(Iterator::class)->reveal(); @@ -97,19 +94,15 @@ public function testGetCollectionWithExecuteOptions() $this->managerRegistryProphecy->getManagerForClass(ProviderEntity::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); $operation = (new GetCollection())->withExtraProperties(['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]])->withName('foo')->withClass(ProviderEntity::class); - $this->resourceMetadataFactoryProphecy->create(ProviderEntity::class) - ->willReturn(new ResourceMetadataCollection(ProviderEntity::class, [ - (new ApiResource())->withOperations(new Operations(['foo' => $operation])), - ])); $extensionProphecy = $this->prophesize(AggregationCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, ProviderEntity::class, 'foo', [])->shouldBeCalled(); + $extensionProphecy->applyToCollection($aggregationBuilder, ProviderEntity::class, $operation, [])->shouldBeCalled(); $dataProvider = new CollectionProvider($this->resourceMetadataFactoryProphecy->reveal(), $this->managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); $this->assertEquals($iterator, $dataProvider->provide($operation, [])); } - public function testAggregationResultExtension() + public function testAggregationResultExtension(): void { $aggregationBuilderProphecy = $this->prophesize(Builder::class); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); @@ -121,18 +114,19 @@ public function testAggregationResultExtension() $managerProphecy->getRepository(ProviderEntity::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); $this->managerRegistryProphecy->getManagerForClass(ProviderEntity::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); + $operation = (new GetCollection())->withName('foo')->withClass(ProviderEntity::class); $extensionProphecy = $this->prophesize(AggregationResultCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, ProviderEntity::class, 'foo', [])->shouldBeCalled(); - $extensionProphecy->supportsResult(ProviderEntity::class, 'foo', [])->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($aggregationBuilder, ProviderEntity::class, 'foo', [])->willReturn([])->shouldBeCalled(); + $extensionProphecy->applyToCollection($aggregationBuilder, ProviderEntity::class, $operation, [])->shouldBeCalled(); + $extensionProphecy->supportsResult(ProviderEntity::class, $operation, [])->willReturn(true)->shouldBeCalled(); + $extensionProphecy->getResult($aggregationBuilder, ProviderEntity::class, $operation, [])->willReturn([])->shouldBeCalled(); $dataProvider = new CollectionProvider($this->resourceMetadataFactoryProphecy->reveal(), $this->managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->provide($operation, [])); } - public function testCannotCreateAggregationBuilder() + public function testCannotCreateAggregationBuilder(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessage('The repository for "ApiPlatform\Tests\Fixtures\TestBundle\Document\ProviderEntity" must be an instance of "Doctrine\ODM\MongoDB\Repository\DocumentRepository".'); @@ -149,7 +143,7 @@ public function testCannotCreateAggregationBuilder() $this->assertEquals([], $dataProvider->provide($operation, [])); } - public function testOperationNotFound() + public function testOperationNotFound(): void { $iterator = $this->prophesize(Iterator::class)->reveal(); @@ -166,12 +160,12 @@ public function testOperationNotFound() $this->managerRegistryProphecy->getManagerForClass(ProviderEntity::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - $this->resourceMetadataFactoryProphecy->create(ProviderEntity::class)->willReturn(new ResourceMetadataCollection(ProviderEntity::class, [(new ApiResource())->withOperations(new Operations(['foo' => new GetCollection()]))])); + $operation = new GetCollection(name: 'bar', class: ProviderEntity::class); $extensionProphecy = $this->prophesize(AggregationCollectionExtensionInterface::class); - $extensionProphecy->applyToCollection($aggregationBuilder, ProviderEntity::class, 'bar', [])->shouldBeCalled(); + $extensionProphecy->applyToCollection($aggregationBuilder, ProviderEntity::class, $operation, [])->shouldBeCalled(); $dataProvider = new CollectionProvider($this->resourceMetadataFactoryProphecy->reveal(), $this->managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]); - $this->assertEquals($iterator, $dataProvider->provide((new GetCollection())->withName('bar')->withClass(ProviderEntity::class), [])); + $this->assertEquals($iterator, $dataProvider->provide($operation, [])); } } diff --git a/tests/Doctrine/Odm/State/ItemProviderTest.php b/tests/Doctrine/Odm/State/ItemProviderTest.php index 3c1f43f237e..132573dc6f7 100644 --- a/tests/Doctrine/Odm/State/ItemProviderTest.php +++ b/tests/Doctrine/Odm/State/ItemProviderTest.php @@ -13,17 +13,13 @@ namespace ApiPlatform\Tests\Doctrine\Odm\State; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; use ApiPlatform\Doctrine\Odm\State\ItemProvider; use ApiPlatform\Exception\RuntimeException; -use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Link; -use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ProviderEntity; use ApiPlatform\Tests\ProphecyTrait; use Doctrine\ODM\MongoDB\Aggregation\Builder; @@ -44,11 +40,9 @@ class ItemProviderTest extends TestCase { use ProphecyTrait; - public function testGetItemSingleIdentifier() + public function testGetItemSingleIdentifier(): void { - $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - - $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $context = ['foo' => 'bar', 'fetch_data' => true]; $matchProphecy = $this->prophesize(AggregationMatch::class); $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); @@ -66,24 +60,22 @@ public function testGetItemSingleIdentifier() $managerRegistry = $this->getManagerRegistry(ProviderEntity::class, $aggregationBuilder); - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, ProviderEntity::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $operation = (new Get()) ->withUriVariables([(new Link())->withFromClass(ProviderEntity::class)->withIdentifiers(['id'])]) ->withClass(ProviderEntity::class) ->withName('foo'); - $resourceMetadataCollection = new ResourceMetadataCollection(ProviderEntity::class, [(new ApiResource())->withOperations(new Operations(['foo' => $operation]))]); - $resourceMetadataFactory->create(ProviderEntity::class)->willReturn($resourceMetadataCollection); - $dataProvider = new ItemProvider($resourceMetadataFactory->reveal(), $managerRegistry, [$extensionProphecy->reveal()]); + $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); + $extensionProphecy->applyToItem($aggregationBuilder, ProviderEntity::class, ['id' => 1], $operation, $context)->shouldBeCalled(); + + $dataProvider = new ItemProvider($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(), $managerRegistry, [$extensionProphecy->reveal()]); $this->assertEquals($result, $dataProvider->provide($operation, ['id' => 1], $context)); } - public function testGetItemWithExecuteOptions() + public function testGetItemWithExecuteOptions(): void { - $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; + $context = ['foo' => 'bar', 'fetch_data' => true]; $matchProphecy = $this->prophesize(AggregationMatch::class); $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); @@ -101,27 +93,22 @@ public function testGetItemWithExecuteOptions() $managerRegistry = $this->getManagerRegistry(ProviderEntity::class, $aggregationBuilder); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $operation = (new Get()) ->withUriVariables([(new Link())->withFromClass(ProviderEntity::class)->withIdentifiers(['id'])]) ->withClass(ProviderEntity::class) ->withName('foo') ->withExtraProperties(['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]]); - $resourceMetadataCollection = new ResourceMetadataCollection(ProviderEntity::class, [(new ApiResource())->withOperations(new Operations(['foo' => $operation]))]); - $resourceMetadataFactory->create(ProviderEntity::class)->willReturn($resourceMetadataCollection); $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, ProviderEntity::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); + $extensionProphecy->applyToItem($aggregationBuilder, ProviderEntity::class, ['id' => 1], $operation, $context)->shouldBeCalled(); - $dataProvider = new ItemProvider($resourceMetadataFactory->reveal(), $managerRegistry, [$extensionProphecy->reveal()]); + $dataProvider = new ItemProvider($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(), $managerRegistry, [$extensionProphecy->reveal()]); $this->assertEquals($result, $dataProvider->provide($operation, ['id' => 1], $context)); } - public function testGetItemDoubleIdentifier() + public function testGetItemDoubleIdentifier(): void { - $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $matchProphecy = $this->prophesize(AggregationMatch::class); $matchProphecy->field('ida')->willReturn($matchProphecy)->shouldBeCalled(); $matchProphecy->field('idb')->willReturn($matchProphecy)->shouldBeCalled(); @@ -140,23 +127,21 @@ public function testGetItemDoubleIdentifier() $managerRegistry = $this->getManagerRegistry(ProviderEntity::class, $aggregationBuilder); - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, ProviderEntity::class, ['ida' => 1, 'idb' => 2], 'foo', $context)->shouldBeCalled(); - $operation = (new Get()) ->withUriVariables([(new Link())->withFromClass(ProviderEntity::class)->withIdentifiers(['ida', 'idb'])]) ->withClass(ProviderEntity::class) ->withName('foo'); - $resourceMetadataCollection = new ResourceMetadataCollection(ProviderEntity::class, [(new ApiResource())->withOperations(new Operations(['foo' => $operation]))]); - $resourceMetadataFactory->create(ProviderEntity::class)->willReturn($resourceMetadataCollection); - $dataProvider = new ItemProvider($resourceMetadataFactory->reveal(), $managerRegistry, [$extensionProphecy->reveal()]); + $context = []; + $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); + $extensionProphecy->applyToItem($aggregationBuilder, ProviderEntity::class, ['ida' => 1, 'idb' => 2], $operation, $context)->shouldBeCalled(); + + $dataProvider = new ItemProvider($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(), $managerRegistry, [$extensionProphecy->reveal()]); $this->assertEquals($result, $dataProvider->provide($operation, ['ida' => 1, 'idb' => 2], $context)); } - public function testAggregationResultExtension() + public function testAggregationResultExtension(): void { $matchProphecy = $this->prophesize(AggregationMatch::class); $matchProphecy->field('id')->willReturn($matchProphecy)->shouldBeCalled(); @@ -168,26 +153,23 @@ public function testAggregationResultExtension() $managerRegistry = $this->getManagerRegistry(ProviderEntity::class, $aggregationBuilder); - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; - $extensionProphecy = $this->prophesize(AggregationResultItemExtensionInterface::class); - $extensionProphecy->applyToItem($aggregationBuilder, ProviderEntity::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $extensionProphecy->supportsResult(ProviderEntity::class, 'foo', $context)->willReturn(true)->shouldBeCalled(); - $extensionProphecy->getResult($aggregationBuilder, ProviderEntity::class, 'foo', $context)->willReturn([])->shouldBeCalled(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $operation = (new Get()) ->withUriVariables([(new Link())->withFromClass(ProviderEntity::class)->withIdentifiers(['id'])]) ->withClass(ProviderEntity::class) ->withName('foo'); - $resourceMetadataCollection = new ResourceMetadataCollection(ProviderEntity::class, [(new ApiResource())->withOperations(new Operations(['foo' => $operation]))]); - $resourceMetadataFactory->create(ProviderEntity::class)->willReturn($resourceMetadataCollection); - $dataProvider = new ItemProvider($resourceMetadataFactory->reveal(), $managerRegistry, [$extensionProphecy->reveal()]); + $context = []; + $extensionProphecy = $this->prophesize(AggregationResultItemExtensionInterface::class); + $extensionProphecy->applyToItem($aggregationBuilder, ProviderEntity::class, ['id' => 1], $operation, $context)->shouldBeCalled(); + $extensionProphecy->supportsResult(ProviderEntity::class, $operation, $context)->willReturn(true)->shouldBeCalled(); + $extensionProphecy->getResult($aggregationBuilder, ProviderEntity::class, $operation, $context)->willReturn([])->shouldBeCalled(); + + $dataProvider = new ItemProvider($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(), $managerRegistry, [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->provide($operation, ['id' => 1], $context)); } - public function testCannotCreateAggregationBuilder() + public function testCannotCreateAggregationBuilder(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessage('The repository for "ApiPlatform\Tests\Fixtures\TestBundle\Document\ProviderEntity" must be an instance of "Doctrine\ODM\MongoDB\Repository\DocumentRepository".'); @@ -202,9 +184,7 @@ public function testCannotCreateAggregationBuilder() $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(); - - (new ItemProvider($resourceMetadataFactory, $managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]))->provide((new Get())->withClass(ProviderEntity::class), [], [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]); + (new ItemProvider($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(), $managerRegistryProphecy->reveal(), [$extensionProphecy->reveal()]))->provide((new Get())->withClass(ProviderEntity::class), [], []); } /** diff --git a/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php index 6a3ee4d8049..266f260c7dd 100644 --- a/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/EagerLoadingExtensionTest.php @@ -19,13 +19,11 @@ use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\AbstractDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ConcreteDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -40,7 +38,6 @@ use Doctrine\ORM\QueryBuilder; use PHPUnit\Framework\TestCase; use Prophecy\Argument; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Serializer\Mapping\AttributeMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadataInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; @@ -54,12 +51,10 @@ class EagerLoadingExtensionTest extends TestCase { use ProphecyTrait; - public function testApplyToCollection() + public function testApplyToCollection(): void { $context = ['groups' => ['foo']]; $callContext = ['serializer_groups' => ['foo']]; - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -128,18 +123,15 @@ public function testApplyToCollection() $queryBuilderProphecy->getDQLPart('join')->willReturn([]); $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, null, $context); } - public function testApplyToItem() + public function testApplyToItem(): void { $context = ['groups' => ['foo']]; $callContext = ['serializer_groups' => ['foo']]; - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $relatedNameCollection = new PropertyNameCollection(['id', 'name', 'embeddedDummy', 'notindatabase', 'notreadable', 'relation']); @@ -236,20 +228,17 @@ public function testApplyToItem() $queryBuilderProphecy->getDQLPart('select')->willReturn([]); $queryBuilder = $queryBuilderProphecy->reveal(); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); $orderExtensionTest->applyToItem($queryBuilder, new QueryNameGenerator(), Dummy::class, [], null, $context); } - public function testCreateItemWithOperationName() + public function testCreateItemWithOperation(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'foo', ['item_operation_name' => 'item_operation', 'serializer_groups' => ['foo']])->shouldBeCalled()->willReturn(new ApiProperty()); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'foo', ['serializer_groups' => ['foo']])->shouldBeCalled()->willReturn(new ApiProperty()); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = [ @@ -261,19 +250,16 @@ public function testCreateItemWithOperationName() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); - $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], 'item_operation', ['groups' => ['foo']]); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], new Get(name: 'item_operation'), ['groups' => ['foo']]); } - public function testCreateCollectionWithOperationName() + public function testCreateCollectionWithOperation(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class)); - $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'foo', ['collection_operation_name' => 'collection_operation', 'serializer_groups' => ['foo']])->shouldBeCalled()->willReturn(new ApiProperty()); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'foo', ['serializer_groups' => ['foo']])->shouldBeCalled()->willReturn(new ApiProperty()); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = [ @@ -285,62 +271,55 @@ public function testCreateCollectionWithOperationName() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); - $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, 'collection_operation', ['groups' => ['foo']]); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, new GetCollection(name: 'collection_operation'), ['groups' => ['foo']]); } - public function testDenormalizeItemWithCorrectResourceClass() + public function testDenormalizeItemWithCorrectResourceClass(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - // Dummy is the correct class for the denormalization context serialization groups, and we're fetching RelatedDummy - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($this->getMetadataWithNormalizationContext(RelatedDummy::class, ['groups' => ['foo']]))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldNotBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = []; + // Dummy is the correct class for the denormalization context serialization groups, and we're fetching RelatedDummy $emProphecy = $this->prophesize(EntityManager::class); + $emProphecy->getClassMetadata(Dummy::class)->shouldNotBeCalled(); $emProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); - $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], 'get', ['resource_class' => Dummy::class]); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], new Get(name: 'get', normalizationContext: ['groups' => ['foo']]), ['resource_class' => Dummy::class]); } - public function testDenormalizeItemWithExistingGroups() + public function testDenormalizeItemWithExistingGroups(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - // groups exist from the context, we don't need to compute them again - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn($this->getMetadataWithNormalizationContext(RelatedDummy::class, ['groups' => ['foo']]))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldNotBeCalled(); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = []; + // groups exist from the context, we don't need to compute them again $emProphecy = $this->prophesize(EntityManager::class); + $emProphecy->getClassMetadata(Dummy::class)->shouldNotBeCalled(); $emProphecy->getClassMetadata(RelatedDummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); - $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], 'item_operation', [AbstractNormalizer::GROUPS => 'some_groups']); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), RelatedDummy::class, ['id' => 1], new Get(name: 'item_operation', normalizationContext: ['groups' => ['foo']]), [AbstractNormalizer::GROUPS => 'some_groups']); } - public function testMaxJoinsReached() + public function testMaxJoinsReached(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessage('The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary with the "api_platform.eager_loading.max_joins" configuration key (https://api-platform.com/docs/core/performance/#eager-loading), or limit the maximum serialization depth using the "enable_max_depth" option of the Symfony serializer (https://symfony.com/doc/current/components/serializer.html#handling-serialization-depth).'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class))->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $relatedNameCollection = new PropertyNameCollection(['dummy']); @@ -382,15 +361,12 @@ public function testMaxJoinsReached() $queryBuilderProphecy->addSelect(Argument::type('string'))->shouldBeCalled(); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, null, ['groups' => ['foo']]); } - public function testMaxDepth() + public function testMaxDepth(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, ['enable_max_depth' => 'true', 'groups' => ['foo']])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $relatedNameCollection = new PropertyNameCollection(['dummy']); @@ -448,15 +424,12 @@ public function testMaxDepth() $queryBuilderProphecy->addSelect(Argument::type('string'))->shouldBeCalled(); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true, $classMetadataFactoryProphecy->reveal()); - $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true, $classMetadataFactoryProphecy->reveal()); + $eagerExtensionTest->applyToCollection($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, new GetCollection(normalizationContext: ['enable_max_depth' => 'true', 'groups' => ['foo']])); } - public function testForceEager() + public function testForceEager(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, [AbstractNormalizer::GROUPS => 'foobar'])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); @@ -491,15 +464,12 @@ public function testForceEager() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); - $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, true, true); + $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], new Get(normalizationContext: [AbstractNormalizer::GROUPS => 'foobar'])); } - public function testExtraLazy() + public function testExtraLazy(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($this->getMetadataWithNormalizationContext(Dummy::class, [AbstractNormalizer::GROUPS => 'foobar'])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); // $propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); @@ -525,19 +495,16 @@ public function testExtraLazy() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); - $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, true, true); + $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], new Get(normalizationContext: [AbstractNormalizer::GROUPS => 'foobar'])); } - public function testResourceClassNotFoundException() + public function testResourceClassNotFoundException(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foo']])->willThrow(new ResourceClassNotFoundException()); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willThrow(new ResourceClassNotFoundException()); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = [ @@ -549,19 +516,16 @@ public function testResourceClassNotFoundException() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); - $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, true, true); + $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], new Get(normalizationContext: [AbstractNormalizer::GROUPS => 'foo'])); } - public function testPropertyNotFoundException() + public function testPropertyNotFoundException(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foo']])->willThrow(new PropertyNotFoundException()); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willThrow(new PropertyNotFoundException()); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = [ @@ -573,22 +537,19 @@ public function testPropertyNotFoundException() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); - $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, true, true); + $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], new Get(normalizationContext: [AbstractNormalizer::GROUPS => 'foo'])); } - public function testResourceClassNotFoundExceptionPropertyNameCollection() + public function testResourceClassNotFoundExceptionPropertyNameCollection(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(UnknownDummy::class)->willThrow(new ResourceClassNotFoundException()); $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relation', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata); $classMetadataProphecy = $this->prophesize(ClassMetadata::class); $classMetadataProphecy->associationMappings = [ @@ -603,15 +564,12 @@ public function testResourceClassNotFoundExceptionPropertyNameCollection() $queryBuilderProphecy->innerJoin('o.relation', 'relation_a1')->shouldBeCalledTimes(1); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, true, true); - $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, []); + $orderExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, true, true); + $orderExtensionTest->applyToItem($queryBuilderProphecy->reveal(), new QueryNameGenerator(), Dummy::class, [], new Get(normalizationContext: [AbstractNormalizer::GROUPS => 'foo'])); } - public function testAttributes() + public function testAttributes(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $relatedNameCollection = new PropertyNameCollection(['id', 'name']); @@ -621,16 +579,16 @@ public function testAttributes() $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $idPropertyMetadata = new ApiProperty(); $idPropertyMetadata = $idPropertyMetadata->withIdentifier(true); $namePropertyMetadata = new ApiProperty(); $namePropertyMetadata = $namePropertyMetadata->withReadable(true); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'id', ['serializer_groups' => ['foo']])->willReturn($idPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', ['serializer_groups' => ['foo']])->willReturn($namePropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'id', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($idPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($namePropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -663,24 +621,19 @@ public function testAttributes() $queryBuilderProphecy->addSelect('partial relatedDummy_a2.{id,name}')->shouldBeCalledTimes(1); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $request = Request::create('/api/dummies', 'GET', []); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, new GetCollection(normalizationContext: [AbstractNormalizer::GROUPS => 'foo'])); } - public function testNotInAttributes() + public function testNotInAttributes(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -698,18 +651,13 @@ public function testNotInAttributes() $queryBuilderProphecy->getRootAliases()->willReturn(['o']); $queryBuilderProphecy->getEntityManager()->willReturn($emProphecy); - $request = Request::create('/api/dummies', 'GET', []); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, new GetCollection(normalizationContext: [AbstractNormalizer::GROUPS => 'foo', AbstractNormalizer::ATTRIBUTES => ['relatedDummy']])); } - public function testOnlyOneRelationNotInAttributes() + public function testOnlyOneRelationNotInAttributes(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $relatedNameCollection = new PropertyNameCollection(['id', 'name']); @@ -719,16 +667,16 @@ public function testOnlyOneRelationNotInAttributes() $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $idPropertyMetadata = new ApiProperty(); $idPropertyMetadata = $idPropertyMetadata->withIdentifier(true); $namePropertyMetadata = new ApiProperty(); $namePropertyMetadata = $namePropertyMetadata->withReadable(true); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'id', ['serializer_groups' => ['foo']])->willReturn($idPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', ['serializer_groups' => ['foo']])->willReturn($namePropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'id', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($idPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(RelatedDummy::class, 'name', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($namePropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -759,26 +707,21 @@ public function testOnlyOneRelationNotInAttributes() $queryBuilderProphecy->addSelect('partial relatedDummy_a1.{id,name}')->shouldBeCalledTimes(1); $queryBuilderProphecy->getDQLPart('join')->willReturn([]); - $request = Request::create('/api/dummies', 'GET', []); - $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false, true); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false, true); + $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, new GetCollection(normalizationContext: [AbstractNormalizer::GROUPS => 'foo', AbstractNormalizer::ATTRIBUTES => ['relatedDummy' => ['id', 'name']]])); } - public function testApplyToCollectionNoPartial() + public function testApplyToCollectionNoPartial(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $relationPropertyMetadata = new ApiProperty(); $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy2', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy2', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -805,15 +748,12 @@ public function testApplyToCollectionNoPartial() $queryBuilderProphecy->getDQLPart('select')->willReturn([]); $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30); + $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, new GetCollection(normalizationContext: [AbstractNormalizer::GROUPS => 'foo'])); } - public function testApplyToCollectionWithANonReadableButFetchEagerProperty() + public function testApplyToCollectionWithANonReadableButFetchEagerProperty(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -825,8 +765,8 @@ public function testApplyToCollectionWithANonReadableButFetchEagerProperty() $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(false); $relationPropertyMetadata = $relationPropertyMetadata->withReadable(false); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy2', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy2', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -853,8 +793,8 @@ public function testApplyToCollectionWithANonReadableButFetchEagerProperty() $queryBuilderProphecy->getDQLPart('select')->willReturn([]); $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30); + $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, new GetCollection(normalizationContext: [AbstractNormalizer::GROUPS => 'foo'])); } /** @@ -863,9 +803,7 @@ public function testApplyToCollectionWithANonReadableButFetchEagerProperty() public function testApplyToCollectionWithExistingJoin(string $joinType): void { $context = ['groups' => ['foo']]; - $callContext = ['serializer_groups' => ['foo']]; - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $callContext = ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo']; $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); @@ -899,8 +837,8 @@ public function testApplyToCollectionWithExistingJoin(string $joinType): void $queryBuilderProphecy->addSelect('existing_join_alias')->shouldBeCalledTimes(1); $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30, false); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, null, $context); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30, false); + $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, new GetCollection(normalizationContext: [AbstractNormalizer::GROUPS => 'foo']), $context); } public function provideExistingJoinCases(): iterable @@ -909,11 +847,8 @@ public function provideExistingJoinCases(): iterable yield [Join::INNER_JOIN]; } - public function testApplyToCollectionWithAReadableButNotFetchEagerProperty() + public function testApplyToCollectionWithAReadableButNotFetchEagerProperty(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn((new ResourceMetadata())->withAttributes(['normalization_context' => ['groups' => ['foo']]])); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -922,8 +857,8 @@ public function testApplyToCollectionWithAReadableButNotFetchEagerProperty() $relationPropertyMetadata = $relationPropertyMetadata->withReadableLink(true); $relationPropertyMetadata = $relationPropertyMetadata->withReadable(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy2', ['serializer_groups' => ['foo']])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy2', ['serializer_groups' => ['foo'], 'normalization_groups' => 'foo'])->willReturn($relationPropertyMetadata)->shouldBeCalled(); $queryBuilderProphecy = $this->prophesize(QueryBuilder::class); @@ -946,16 +881,7 @@ public function testApplyToCollectionWithAReadableButNotFetchEagerProperty() $queryBuilderProphecy->addSelect('relatedDummy2_a2')->shouldNotBeCalled(); $queryBuilder = $queryBuilderProphecy->reveal(); - $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), 30); - $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class); - } - - private function getMetadataWithNormalizationContext(string $class, array $context = []): ResourceMetadataCollection - { - return new ResourceMetadataCollection($class, [ - new ApiResource(operations: [ - 'get' => new Get(name: 'get', normalizationContext: $context), - ]), - ]); + $eagerExtensionTest = new EagerLoadingExtension($propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), 30); + $eagerExtensionTest->applyToCollection($queryBuilder, new QueryNameGenerator(), Dummy::class, new GetCollection(normalizationContext: [AbstractNormalizer::GROUPS => 'foo'])); } } diff --git a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php index 3381dc26c72..4d86afba29b 100644 --- a/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php +++ b/tests/Doctrine/Orm/Extension/FilterEagerLoadingExtensionTest.php @@ -14,10 +14,9 @@ namespace ApiPlatform\Tests\Doctrine\Orm\Extension; use ApiPlatform\Api\ResourceClassResolver; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CompositeItem; @@ -34,21 +33,13 @@ /** * @author Antoine Bluchet - * @group legacy */ class FilterEagerLoadingExtensionTest extends TestCase { use ProphecyTrait; - public function testIsNoForceEagerCollectionAttributes() + public function testIsNoForceEagerCollectionAttributes(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class, null, null, null, [ - 'get' => [ - 'force_eager' => false, - ], - ], null)); - $em = $this->prophesize(EntityManager::class); $em->getClassMetadata(DummyCar::class)->shouldBeCalled()->willReturn(new ClassMetadataInfo(DummyCar::class)); @@ -58,76 +49,45 @@ public function testIsNoForceEagerCollectionAttributes() $queryNameGenerator = $this->prophesize(QueryNameGeneratorInterface::class); - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), true); - $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class, 'get'); + $filterEagerLoadingExtension = new FilterEagerLoadingExtension(true); + $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class, new Get(name: 'get', forceEager: false)); } - public function testIsNoForceEagerResource() + public function testIsForceEagerConfig(): void { $em = $this->prophesize(EntityManager::class); $em->getClassMetadata(DummyCar::class)->shouldBeCalled()->willReturn(new ClassMetadataInfo(DummyCar::class)); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class, null, null, null, [ - 'get' => [], - ], ['force_eager' => false])); - $qb = $this->prophesize(QueryBuilder::class); $qb->getDQLPart('where')->shouldNotBeCalled(); $qb->getEntityManager()->willReturn($em); $queryNameGenerator = $this->prophesize(QueryNameGeneratorInterface::class); - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), true); - $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class); + $filterEagerLoadingExtension = new FilterEagerLoadingExtension(false); + $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class, new Get(name: 'get')); } - public function testIsForceEagerConfig() + public function testHasNoWherePart(): void { $em = $this->prophesize(EntityManager::class); $em->getClassMetadata(DummyCar::class)->shouldBeCalled()->willReturn(new ClassMetadataInfo(DummyCar::class)); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class, null, null, null, [ - 'get' => [], - ])); - - $qb = $this->prophesize(QueryBuilder::class); - $qb->getDQLPart('where')->shouldNotBeCalled(); - $qb->getEntityManager()->willReturn($em); - - $queryNameGenerator = $this->prophesize(QueryNameGeneratorInterface::class); - - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), false); - $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class, 'get'); - } - - public function testHasNoWherePart() - { - $em = $this->prophesize(EntityManager::class); - $em->getClassMetadata(DummyCar::class)->shouldBeCalled()->willReturn(new ClassMetadataInfo(DummyCar::class)); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class)); - $qb = $this->prophesize(QueryBuilder::class); $qb->getDQLPart('where')->shouldBeCalled()->willReturn(null); $qb->getEntityManager()->willReturn($em); $queryNameGenerator = $this->prophesize(QueryNameGeneratorInterface::class); - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), true); - $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class, 'get'); + $filterEagerLoadingExtension = new FilterEagerLoadingExtension(true); + $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class, new Get(name: 'get')); } - public function testHasNoJoinPart() + public function testHasNoJoinPart(): void { $em = $this->prophesize(EntityManager::class); $em->getClassMetadata(DummyCar::class)->shouldBeCalled()->willReturn(new ClassMetadataInfo(DummyCar::class)); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class)); - $qb = $this->prophesize(QueryBuilder::class); $qb->getDQLPart('where')->shouldBeCalled()->willReturn(new Expr\Andx()); $qb->getDQLPart('join')->shouldBeCalled()->willReturn(null); @@ -136,15 +96,12 @@ public function testHasNoJoinPart() $queryNameGenerator = $this->prophesize(QueryNameGeneratorInterface::class); - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), true); - $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class, 'get'); + $filterEagerLoadingExtension = new FilterEagerLoadingExtension(true); + $filterEagerLoadingExtension->applyToCollection($qb->reveal(), $queryNameGenerator->reveal(), DummyCar::class, new Get(name: 'get')); } - public function testApplyCollection() + public function testApplyCollection(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class)); - $em = $this->prophesize(EntityManager::class); $em->getExpressionBuilder()->shouldBeCalled()->willReturn(new Expr()); $em->getClassMetadata(DummyCar::class)->shouldBeCalled()->willReturn(new ClassMetadataInfo(DummyCar::class)); @@ -161,17 +118,14 @@ public function testApplyCollection() $queryNameGenerator->generateJoinAlias('colors')->shouldBeCalled()->willReturn('colors_2'); $queryNameGenerator->generateJoinAlias('o')->shouldBeCalled()->willReturn('o_2'); - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), true); - $filterEagerLoadingExtension->applyToCollection($qb, $queryNameGenerator->reveal(), DummyCar::class, 'get'); + $filterEagerLoadingExtension = new FilterEagerLoadingExtension(true); + $filterEagerLoadingExtension->applyToCollection($qb, $queryNameGenerator->reveal(), DummyCar::class, new Get(name: 'get')); $this->assertEquals('SELECT o FROM ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar o LEFT JOIN o.colors colors WHERE o IN(SELECT o_2 FROM ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar o_2 LEFT JOIN o_2.colors colors_2 WHERE o_2.colors = :foo)', $qb->getDQL()); } - public function testApplyCollectionWithManualJoin() + public function testApplyCollectionWithManualJoin(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class)); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyTravel::class])); @@ -196,8 +150,8 @@ public function testApplyCollectionWithManualJoin() $queryNameGenerator->generateJoinAlias('o')->shouldBeCalled()->willReturn('o_2'); $queryNameGenerator->generateJoinAlias('t_a3')->shouldBeCalled()->willReturn('t_a3_a20'); - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), true, new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal())); - $filterEagerLoadingExtension->applyToCollection($qb, $queryNameGenerator->reveal(), DummyCar::class, 'get'); + $filterEagerLoadingExtension = new FilterEagerLoadingExtension(true, new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal())); + $filterEagerLoadingExtension->applyToCollection($qb, $queryNameGenerator->reveal(), DummyCar::class, new Get(name: 'get')); $expected = <<<'SQL' SELECT o @@ -215,11 +169,8 @@ public function testApplyCollectionWithManualJoin() $this->assertEquals($this->toDQLString($expected), $qb->getDQL()); } - public function testApplyCollectionCorrectlyReplacesJoinCondition() + public function testApplyCollectionCorrectlyReplacesJoinCondition(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class)); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyTravel::class])); @@ -241,8 +192,8 @@ public function testApplyCollectionCorrectlyReplacesJoinCondition() $queryNameGenerator->generateJoinAlias('colors')->shouldBeCalled()->willReturn('colors_2'); $queryNameGenerator->generateJoinAlias('o')->shouldBeCalled()->willReturn('o_2'); - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), true, new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal())); - $filterEagerLoadingExtension->applyToCollection($qb, $queryNameGenerator->reveal(), DummyCar::class, 'get'); + $filterEagerLoadingExtension = new FilterEagerLoadingExtension(true, new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal())); + $filterEagerLoadingExtension->applyToCollection($qb, $queryNameGenerator->reveal(), DummyCar::class, new Get(name: 'get')); $expected = <<<'SQL' SELECT o @@ -261,11 +212,8 @@ public function testApplyCollectionCorrectlyReplacesJoinCondition() /** * https://github.com/api-platform/core/issues/1021. */ - public function testHiddenOrderBy() + public function testHiddenOrderBy(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata(DummyCar::class)); - $em = $this->prophesize(EntityManager::class); $em->getExpressionBuilder()->shouldBeCalled()->willReturn(new Expr()); $em->getClassMetadata(DummyCar::class)->shouldBeCalled()->willReturn(new ClassMetadataInfo(DummyCar::class)); @@ -282,8 +230,8 @@ public function testHiddenOrderBy() $queryNameGenerator = $this->prophesize(QueryNameGeneratorInterface::class); $queryNameGenerator->generateJoinAlias('colors')->shouldBeCalled()->willReturn('colors_2'); $queryNameGenerator->generateJoinAlias('o')->shouldBeCalled()->willReturn('o_2'); - $filterEagerLoadingExtension = new FilterEagerLoadingExtension($resourceMetadataFactoryProphecy->reveal(), true); - $filterEagerLoadingExtension->applyToCollection($qb, $queryNameGenerator->reveal(), DummyCar::class, 'get'); + $filterEagerLoadingExtension = new FilterEagerLoadingExtension(true); + $filterEagerLoadingExtension->applyToCollection($qb, $queryNameGenerator->reveal(), DummyCar::class, new Get(name: 'get')); $expected = << - - - - - diff --git a/src/Util/OperationRequestInitiatorTrait.php b/src/Util/OperationRequestInitiatorTrait.php index e2037c5a0bb..ae1f4537e11 100644 --- a/src/Util/OperationRequestInitiatorTrait.php +++ b/src/Util/OperationRequestInitiatorTrait.php @@ -36,13 +36,11 @@ private function initializeOperation(Request $request): ?HttpOperation return $request->attributes->get('_api_operation'); } - // TODO: 3.0 $resourceMetadataCollectionFactory is mandatory if (null === $request->attributes->get('_api_resource_class') || null === $this->resourceMetadataCollectionFactory) { return null; } - // TODO: 3.0 remove collection/item - $operationName = $request->attributes->get('_api_operation_name') ?? $request->attributes->get('_api_collection_operation_name') ?? $request->attributes->get('_api_item_operation_name') ?? $request->attributes->get('_api_subresource_operation_name'); + $operationName = $request->attributes->get('_api_operation_name') ?? null; /** @var HttpOperation $operation */ $operation = $this->resourceMetadataCollectionFactory->create($request->attributes->get('_api_resource_class'))->getOperation($operationName); $request->attributes->set('_api_operation', $operation); diff --git a/tests/Elasticsearch/Extension/SortExtensionTest.php b/tests/Elasticsearch/Extension/SortExtensionTest.php index 7852b269865..fd00b3c2047 100644 --- a/tests/Elasticsearch/Extension/SortExtensionTest.php +++ b/tests/Elasticsearch/Extension/SortExtensionTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Elasticsearch\Extension; -use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface; use ApiPlatform\Elasticsearch\Extension\SortExtension; @@ -35,7 +34,6 @@ public function testConstruct(): void self::assertInstanceOf( RequestBodySearchCollectionExtensionInterface::class, new SortExtension( - $this->prophesize(IdentifiersExtractorInterface::class)->reveal(), $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal(), @@ -50,9 +48,9 @@ public function testApplyToCollection(): void $nameConverterProphecy->normalize('name', Foo::class)->willReturn('name')->shouldBeCalled(); $nameConverterProphecy->normalize('bar', Foo::class)->willReturn('bar')->shouldBeCalled(); - $sortExtension = new SortExtension($this->prophesize(IdentifiersExtractorInterface::class)->reveal(), $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $nameConverterProphecy->reveal(), 'asc'); + $sortExtension = new SortExtension($this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $nameConverterProphecy->reveal(), 'asc'); - self::assertSame(['sort' => [['name' => ['order' => 'asc']], ['bar' => ['order' => 'desc']]]], $sortExtension->applyToCollection([], Foo::class, new GetCollection(order: ['name', 'bar' => 'desc']))); + self::assertSame(['sort' => [['name' => ['order' => 'asc']], ['bar' => ['order' => 'desc']]]], $sortExtension->applyToCollection([], Foo::class, (new GetCollection())->withOrder(['name', 'bar' => 'desc']))); } public function testApplyToCollectionWithNestedProperty(): void @@ -69,27 +67,24 @@ public function testApplyToCollectionWithNestedProperty(): void $nameConverterProphecy->normalize('foo.bar', Foo::class)->willReturn('foo.bar')->shouldBeCalled(); $nameConverterProphecy->normalize('foo', Foo::class)->willReturn('foo')->shouldBeCalled(); - $sortExtension = new SortExtension($this->prophesize(IdentifiersExtractorInterface::class)->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), $nameConverterProphecy->reveal(), 'asc'); + $sortExtension = new SortExtension($propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), $nameConverterProphecy->reveal(), 'asc'); - self::assertSame(['sort' => [['foo.bar' => ['order' => 'desc', 'nested' => ['path' => 'foo']]]]], $sortExtension->applyToCollection([], Foo::class, new GetCollection(order: ['foo.bar' => 'desc']))); + self::assertSame(['sort' => [['foo.bar' => ['order' => 'desc', 'nested' => ['path' => 'foo']]]]], $sortExtension->applyToCollection([], Foo::class, (new GetCollection())->withOrder(['foo.bar' => 'desc']))); } public function testApplyToCollectionWithDefaultDirection(): void { - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $nameConverterProphecy = $this->prophesize(NameConverterInterface::class); $nameConverterProphecy->normalize('id', Foo::class)->willReturn('id')->shouldBeCalled(); - $sortExtension = new SortExtension($identifierExtractorProphecy->reveal(), $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $nameConverterProphecy->reveal(), 'asc'); + $sortExtension = new SortExtension($this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $nameConverterProphecy->reveal(), 'asc'); self::assertSame(['sort' => [['id' => ['order' => 'asc']]]], $sortExtension->applyToCollection([], Foo::class)); } public function testApplyToCollectionWithNoOrdering(): void { - $sortExtension = new SortExtension($this->prophesize(IdentifiersExtractorInterface::class)->reveal(), $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal()); + $sortExtension = new SortExtension($this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal()); self::assertEmpty($sortExtension->applyToCollection([], Foo::class)); } diff --git a/tests/Elasticsearch/Filter/MatchFilterTest.php b/tests/Elasticsearch/Filter/MatchFilterTest.php index c69f6229cc0..6bcdabd15c4 100644 --- a/tests/Elasticsearch/Filter/MatchFilterTest.php +++ b/tests/Elasticsearch/Filter/MatchFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Elasticsearch\Filter; -use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; @@ -43,7 +42,6 @@ public function testConstruct(): void $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - $this->prophesize(IdentifiersExtractorInterface::class)->reveal(), $this->prophesize(IriConverterInterface::class)->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal() @@ -60,9 +58,6 @@ public function testApply(): void $propertyMetadataFactoryProphecy->create(Foo::class, 'id')->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)]))->shouldBeCalled(); $propertyMetadataFactoryProphecy->create(Foo::class, 'name')->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)]))->shouldBeCalled(); - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $foo = new Foo(); $foo->setName('Xavier'); $foo->setBar('Thévenard'); @@ -81,7 +76,6 @@ public function testApply(): void $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - $identifierExtractorProphecy->reveal(), $iriConverterProphecy->reveal(), $propertyAccessorProphecy->reveal(), $nameConverterProphecy->reveal() @@ -105,9 +99,6 @@ public function testApplyWithNestedProperty(): void $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->isResourceClass(Foo::class)->willReturn(true)->shouldBeCalled(); - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $nameConverterProphecy = $this->prophesize(NameConverterInterface::class); $nameConverterProphecy->normalize('foo.bar', Foo::class, null, Argument::type('array'))->willReturn('foo.bar')->shouldBeCalled(); $nameConverterProphecy->normalize('foo', Foo::class, null, Argument::type('array'))->willReturn('foo')->shouldBeCalled(); @@ -116,7 +107,6 @@ public function testApplyWithNestedProperty(): void $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - $identifierExtractorProphecy->reveal(), $this->prophesize(IriConverterInterface::class)->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), $nameConverterProphecy->reveal(), @@ -138,9 +128,6 @@ public function testApplyWithInvalidFilters(): void $propertyMetadataFactoryProphecy->create(Foo::class, 'id')->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)]))->shouldBeCalled(); $propertyMetadataFactoryProphecy->create(Foo::class, 'bar')->willReturn(new ApiProperty())->shouldBeCalled(); - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getResourceFromIri('/invalid_iri_foos/1', ['fetch_data' => false])->willThrow(new InvalidArgumentException())->shouldBeCalled(); @@ -148,7 +135,6 @@ public function testApplyWithInvalidFilters(): void $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - $identifierExtractorProphecy->reveal(), $iriConverterProphecy->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal() @@ -179,7 +165,6 @@ public function testGetDescription(): void $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - $this->prophesize(IdentifiersExtractorInterface::class)->reveal(), $this->prophesize(IriConverterInterface::class)->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal() diff --git a/tests/Elasticsearch/Filter/TermFilterTest.php b/tests/Elasticsearch/Filter/TermFilterTest.php index 219a702d80b..b34bcbf2932 100644 --- a/tests/Elasticsearch/Filter/TermFilterTest.php +++ b/tests/Elasticsearch/Filter/TermFilterTest.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Tests\Elasticsearch\Filter; -use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Elasticsearch\Filter\ConstantScoreFilterInterface; @@ -43,7 +42,6 @@ public function testConstruct(): void $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - $this->prophesize(IdentifiersExtractorInterface::class)->reveal(), $this->prophesize(IriConverterInterface::class)->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal() @@ -60,9 +58,6 @@ public function testApply(): void $propertyMetadataFactoryProphecy->create(Foo::class, 'id')->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)]))->shouldBeCalled(); $propertyMetadataFactoryProphecy->create(Foo::class, 'name')->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)]))->shouldBeCalled(); - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $foo = new Foo(); $foo->setName('Xavier'); $foo->setBar('Thévenard'); @@ -81,7 +76,6 @@ public function testApply(): void $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - $identifierExtractorProphecy->reveal(), $iriConverterProphecy->reveal(), $propertyAccessorProphecy->reveal(), $nameConverterProphecy->reveal() @@ -105,9 +99,6 @@ public function testApplyWithNestedProperty(): void $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->isResourceClass(Foo::class)->willReturn(true)->shouldBeCalled(); - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $nameConverterProphecy = $this->prophesize(NameConverterInterface::class); $nameConverterProphecy->normalize('foo.bar', Foo::class, null, Argument::type('array'))->willReturn('foo.bar')->shouldBeCalled(); $nameConverterProphecy->normalize('foo', Foo::class, null, Argument::type('array'))->willReturn('foo')->shouldBeCalled(); @@ -116,7 +107,6 @@ public function testApplyWithNestedProperty(): void $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - $identifierExtractorProphecy->reveal(), $this->prophesize(IriConverterInterface::class)->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), $nameConverterProphecy->reveal(), @@ -138,9 +128,6 @@ public function testApplyWithInvalidFilters(): void $propertyMetadataFactoryProphecy->create(Foo::class, 'id')->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)]))->shouldBeCalled(); $propertyMetadataFactoryProphecy->create(Foo::class, 'bar')->willReturn(new ApiProperty())->shouldBeCalled(); - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getResourceFromIri('/invalid_iri_foos/1', ['fetch_data' => false])->willThrow(new InvalidArgumentException())->shouldBeCalled(); @@ -148,7 +135,6 @@ public function testApplyWithInvalidFilters(): void $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - $identifierExtractorProphecy->reveal(), $iriConverterProphecy->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal() @@ -179,7 +165,6 @@ public function testGetDescription(): void $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - $this->prophesize(IdentifiersExtractorInterface::class)->reveal(), $this->prophesize(IriConverterInterface::class)->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), $this->prophesize(NameConverterInterface::class)->reveal() diff --git a/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php b/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php index 73b62f4a6c4..91de10f7305 100644 --- a/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php +++ b/tests/Elasticsearch/Serializer/DocumentNormalizerTest.php @@ -13,8 +13,12 @@ namespace ApiPlatform\Tests\Elasticsearch\Serializer; -use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Foo; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -28,7 +32,7 @@ final class DocumentNormalizerTest extends TestCase public function testConstruct(): void { - $itemNormalizer = new DocumentNormalizer($this->prophesize(IdentifiersExtractorInterface::class)->reveal()); + $itemNormalizer = new DocumentNormalizer($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal()); self::assertInstanceOf(DenormalizerInterface::class, $itemNormalizer); self::assertInstanceOf(NormalizerInterface::class, $itemNormalizer); @@ -49,7 +53,7 @@ public function testSupportsDenormalization(): void ], ]; - $itemNormalizer = new DocumentNormalizer($this->prophesize(IdentifiersExtractorInterface::class)->reveal()); + $itemNormalizer = new DocumentNormalizer($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal()); self::assertTrue($itemNormalizer->supportsDenormalization($document, Foo::class, DocumentNormalizer::FORMAT)); self::assertFalse($itemNormalizer->supportsDenormalization($document, Foo::class, 'text/coffee')); @@ -69,10 +73,10 @@ public function testDenormalize(): void ], ]; - $identifierExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifierExtractorProphecy->getIdentifierFromResourceClass(Foo::class)->willReturn('id')->shouldBeCalled(); + $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactory->create(Foo::class)->willReturn(new ResourceMetadataCollection(Foo::class, [(new ApiResource())->withOperations(new Operations([new Get()]))])); - $normalizer = new DocumentNormalizer($identifierExtractorProphecy->reveal()); + $normalizer = new DocumentNormalizer($resourceMetadataFactory->reveal()); $expectedFoo = new Foo(); $expectedFoo->setName('Caroline'); @@ -83,7 +87,7 @@ public function testDenormalize(): void public function testSupportsNormalization(): void { - $itemNormalizer = new DocumentNormalizer($this->prophesize(IdentifiersExtractorInterface::class)->reveal()); + $itemNormalizer = new DocumentNormalizer($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal()); self::assertTrue($itemNormalizer->supportsNormalization(new Foo(), DocumentNormalizer::FORMAT)); } @@ -93,6 +97,6 @@ public function testNormalize(): void $this->expectException(LogicException::class); $this->expectExceptionMessage(sprintf('%s is a write-only format.', DocumentNormalizer::FORMAT)); - (new DocumentNormalizer($this->prophesize(IdentifiersExtractorInterface::class)->reveal()))->normalize(new Foo(), DocumentNormalizer::FORMAT); + (new DocumentNormalizer($this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal()))->normalize(new Foo(), DocumentNormalizer::FORMAT); } } diff --git a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php index 6bfcb44d63c..c5162f2938a 100644 --- a/tests/GraphQl/Resolver/Stage/SerializeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SerializeStageTest.php @@ -201,7 +201,7 @@ private function createSerializeStage(bool $paginationEnabled): SerializeStage { $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataCollectionFactoryProphecy->create(Argument::type('string'))->willReturn(new ResourceMetadataCollection('')); - $pagination = new Pagination($resourceMetadataCollectionFactoryProphecy->reveal(), [], ['enabled' => $paginationEnabled]); + $pagination = new Pagination([], ['enabled' => $paginationEnabled]); return new SerializeStage( $this->normalizerProphecy->reveal(), diff --git a/tests/GraphQl/Serializer/ItemNormalizerTest.php b/tests/GraphQl/Serializer/ItemNormalizerTest.php index 7911bbbc9fd..c457c5d6a49 100644 --- a/tests/GraphQl/Serializer/ItemNormalizerTest.php +++ b/tests/GraphQl/Serializer/ItemNormalizerTest.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Core\Tests\GraphQl\Serializer; +use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; @@ -104,15 +104,7 @@ public function testNormalize() $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $identifiersExtractorProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - false, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -159,13 +151,7 @@ public function testNormalizeNoResolverData(): void $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $identifiersExtractorProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -206,13 +192,7 @@ public function testDenormalize() $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $identifiersExtractorProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - null, - null, - [], - null + $resourceClassResolverProphecy->reveal() ); $normalizer->setSerializer($serializerProphecy->reveal()); diff --git a/tests/GraphQl/Type/FieldsBuilderTest.php b/tests/GraphQl/Type/FieldsBuilderTest.php index 86cc2d45d25..fe863e0d2e5 100644 --- a/tests/GraphQl/Type/FieldsBuilderTest.php +++ b/tests/GraphQl/Type/FieldsBuilderTest.php @@ -116,7 +116,7 @@ protected function setUp(): void private function buildFieldsBuilder(?AdvancedNameConverterInterface $advancedNameConverter = null): FieldsBuilder { - return new FieldsBuilder($this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->resourceClassResolverProphecy->reveal(), $this->typesContainerProphecy->reveal(), $this->typeBuilderProphecy->reveal(), $this->typeConverterProphecy->reveal(), $this->itemResolverFactoryProphecy->reveal(), $this->collectionResolverFactoryProphecy->reveal(), $this->itemMutationResolverFactoryProphecy->reveal(), $this->itemSubscriptionResolverFactoryProphecy->reveal(), $this->filterLocatorProphecy->reveal(), new Pagination($this->resourceMetadataCollectionFactoryProphecy->reveal()), $advancedNameConverter ?? new CustomConverter(), '__'); + return new FieldsBuilder($this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->resourceClassResolverProphecy->reveal(), $this->typesContainerProphecy->reveal(), $this->typeBuilderProphecy->reveal(), $this->typeConverterProphecy->reveal(), $this->itemResolverFactoryProphecy->reveal(), $this->collectionResolverFactoryProphecy->reveal(), $this->itemMutationResolverFactoryProphecy->reveal(), $this->itemSubscriptionResolverFactoryProphecy->reveal(), $this->filterLocatorProphecy->reveal(), new Pagination(), $advancedNameConverter ?? new CustomConverter(), '__'); } public function testGetNodeQueryFields(): void @@ -236,7 +236,7 @@ public function testGetCollectionQueryFields(string $resourceClass, Operation $o }), $resourceClass, $resourceClass, null, 0)->willReturn($graphqlType); $this->typeConverterProphecy->resolveType(Argument::type('string'))->willReturn(GraphQLType::string()); $this->typeBuilderProphecy->isCollection(Argument::type(Type::class))->willReturn(true); - $this->typeBuilderProphecy->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $operation->getName())->willReturn($graphqlType); + $this->typeBuilderProphecy->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $operation)->willReturn($graphqlType); $this->resourceMetadataCollectionFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadataCollection($resourceClass, [(new ApiResource())->withGraphQlOperations([$operation->getName() => $operation])])); $this->collectionResolverFactoryProphecy->__invoke($resourceClass, $resourceClass, $operation)->willReturn($resolver); $this->filterLocatorProphecy->has('my_filter')->willReturn(true); diff --git a/tests/GraphQl/Type/TypeBuilderTest.php b/tests/GraphQl/Type/TypeBuilderTest.php index f2436be513c..64adb22d7ca 100644 --- a/tests/GraphQl/Type/TypeBuilderTest.php +++ b/tests/GraphQl/Type/TypeBuilderTest.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace ApiPlatform\Core\Tests\GraphQl\Type; +namespace ApiPlatform\Tests\GraphQl\Type; use ApiPlatform\GraphQl\Serializer\ItemNormalizer; use ApiPlatform\GraphQl\Type\FieldsBuilderInterface; @@ -23,7 +23,6 @@ use ApiPlatform\Metadata\GraphQl\Query; use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\Metadata\GraphQl\Subscription; -use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -57,9 +56,6 @@ class TypeBuilderTest extends TestCase /** @var ObjectProphecy */ private $fieldsBuilderLocatorProphecy; - /** @var ObjectProphecy */ - private $resourceMetadataCollectionFactoryProphecy; - /** @var TypeBuilder */ private $typeBuilder; @@ -72,12 +68,11 @@ protected function setUp(): void $this->defaultFieldResolver = function () { }; $this->fieldsBuilderLocatorProphecy = $this->prophesize(ContainerInterface::class); - $this->resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $this->typeBuilder = new TypeBuilder( $this->typesContainerProphecy->reveal(), $this->defaultFieldResolver, $this->fieldsBuilderLocatorProphecy->reveal(), - new Pagination($this->resourceMetadataCollectionFactoryProphecy->reveal()) + new Pagination() ); } @@ -483,18 +478,15 @@ public function testGetNodeInterface(): void public function testCursorBasedGetResourcePaginatedCollectionType(): void { + /** @var Operation */ + $operation = (new Query())->withPaginationType('cursor'); $this->typesContainerProphecy->has('StringCursorConnection')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('StringCursorConnection', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->set('StringEdge', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->set('StringPageInfo', Argument::type(ObjectType::class))->shouldBeCalled(); - $this->resourceMetadataCollectionFactoryProphecy->create('StringResourceClass')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('StringResourceClass', [ - (new ApiResource())->withGraphQlOperations([ - 'operationName' => (new Query())->withPaginationType('cursor'), - ]), - ])); /** @var ObjectType $resourcePaginatedCollectionType */ - $resourcePaginatedCollectionType = $this->typeBuilder->getResourcePaginatedCollectionType(GraphQLType::string(), 'StringResourceClass', 'operationName'); + $resourcePaginatedCollectionType = $this->typeBuilder->getResourcePaginatedCollectionType(GraphQLType::string(), 'StringResourceClass', $operation); $this->assertSame('StringCursorConnection', $resourcePaginatedCollectionType->name); $this->assertSame('Cursor connection for String.', $resourcePaginatedCollectionType->description); @@ -542,18 +534,14 @@ public function testCursorBasedGetResourcePaginatedCollectionType(): void public function testPageBasedGetResourcePaginatedCollectionType(): void { + /** @var Operation $operation */ + $operation = (new Query())->withPaginationType('page'); $this->typesContainerProphecy->has('StringPageConnection')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('StringPageConnection', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->set('StringPaginationInfo', Argument::type(ObjectType::class))->shouldBeCalled(); - $this->resourceMetadataCollectionFactoryProphecy->create('StringResourceClass')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('StringResourceClass', [ - (new ApiResource())->withGraphQlOperations([ - 'operationName' => (new Query())->withPaginationType('page'), - ]), - ])); - /** @var ObjectType $resourcePaginatedCollectionType */ - $resourcePaginatedCollectionType = $this->typeBuilder->getResourcePaginatedCollectionType(GraphQLType::string(), 'StringResourceClass', 'operationName'); + $resourcePaginatedCollectionType = $this->typeBuilder->getResourcePaginatedCollectionType(GraphQLType::string(), 'StringResourceClass', $operation); $this->assertSame('StringPageConnection', $resourcePaginatedCollectionType->name); $this->assertSame('Page connection for String.', $resourcePaginatedCollectionType->description); diff --git a/tests/HttpCache/EventListener/AddHeadersListenerTest.php b/tests/HttpCache/EventListener/AddHeadersListenerTest.php index e2807f27d8d..457e296bfe1 100644 --- a/tests/HttpCache/EventListener/AddHeadersListenerTest.php +++ b/tests/HttpCache/EventListener/AddHeadersListenerTest.php @@ -13,9 +13,11 @@ namespace ApiPlatform\Tests\HttpCache\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\HttpCache\EventListener\AddHeadersListener; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -26,7 +28,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class AddHeadersListenerTest extends TestCase { @@ -103,13 +104,13 @@ public function testAddHeaders() $response = new Response('some content', 200, ['Vary' => ['Accept', 'Cookie']]); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $factory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $factory->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [new ApiResource(operations: ['get' => new Get(name: 'get')])]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30); $listener->onKernelResponse($event); @@ -129,13 +130,13 @@ public function testDoNotSetHeaderWhenAlreadySet() $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); + $factory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $factory->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [new ApiResource(operations: ['get' => new Get(name: 'get')])]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30); $listener->onKernelResponse($event); @@ -150,14 +151,14 @@ public function testSetHeadersFromResourceMetadata() $response = new Response('some content', 200, ['Vary' => ['Accept', 'Cookie']]); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $metadata = new ResourceMetadata(null, null, null, null, null, ['cache_headers' => ['max_age' => 123, 'shared_max_age' => 456, 'stale_while_revalidate' => 928, 'stale_if_error' => 70, 'vary' => ['Vary-1', 'Vary-2']]]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); + $operation = new Get(name: 'get', cacheHeaders: ['max_age' => 123, 'shared_max_age' => 456, 'stale_while_revalidate' => 928, 'stale_if_error' => 70, 'vary' => ['Vary-1', 'Vary-2']]); + $factory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $factory->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [new ApiResource(operations: ['get' => $operation])]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30); $listener->onKernelResponse($event); @@ -171,20 +172,19 @@ public function testSetHeadersFromResourceMetadataMarkedAsPrivate() $response = new Response('some content', 200); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $metadata = new ResourceMetadata(null, null, null, null, null, [ - 'cache_headers' => [ - 'max_age' => 123, - 'public' => false, - 'shared_max_age' => 456, - ], + $operation = new Get(name: 'get', cacheHeaders: [ + 'max_age' => 123, + 'public' => false, + 'shared_max_age' => 456, ]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); + + $factory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $factory->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [new ApiResource(operations: ['get' => $operation])]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); $listener->onKernelResponse($event); @@ -200,20 +200,19 @@ public function testSetHeadersFromResourceMetadataMarkedAsPublic() $response = new Response('some content', 200); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $metadata = new ResourceMetadata(null, null, null, null, null, [ - 'cache_headers' => [ - 'max_age' => 123, - 'public' => true, - 'shared_max_age' => 456, - ], + $operation = new Get(name: 'get', cacheHeaders: [ + 'max_age' => 123, + 'public' => true, + 'shared_max_age' => 456, ]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); + + $factory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $factory->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [new ApiResource(operations: ['get' => $operation])]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); $listener->onKernelResponse($event); @@ -226,19 +225,18 @@ public function testSetHeadersFromResourceMetadataWithNoPrivacy() $response = new Response('some content', 200); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $metadata = new ResourceMetadata(null, null, null, null, null, [ - 'cache_headers' => [ - 'max_age' => 123, - 'shared_max_age' => 456, - ], + $operation = new Get(name: 'get', cacheHeaders: [ + 'max_age' => 123, + 'shared_max_age' => 456, ]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); + + $factory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $factory->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [new ApiResource(operations: ['get' => $operation])]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); $listener->onKernelResponse($event); @@ -251,19 +249,18 @@ public function testSetHeadersFromResourceMetadataWithNoPrivacyDefaultsPrivate() $response = new Response('some content', 200); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); - $metadata = new ResourceMetadata(null, null, null, null, null, [ - 'cache_headers' => [ - 'max_age' => 123, - 'shared_max_age' => 456, - ], + $operation = new Get(name: 'get', cacheHeaders: [ + 'max_age' => 123, + 'shared_max_age' => 456, ]); - $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); + + $factory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $factory->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [new ApiResource(operations: ['get' => $operation])]))->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], false, $factory->reveal()); $listener->onKernelResponse($event); diff --git a/tests/HttpCache/EventListener/AddTagsListenerTest.php b/tests/HttpCache/EventListener/AddTagsListenerTest.php index 93bfd0dd341..371f9ad4a64 100644 --- a/tests/HttpCache/EventListener/AddTagsListenerTest.php +++ b/tests/HttpCache/EventListener/AddTagsListenerTest.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use ApiPlatform\HttpCache\EventListener\AddTagsListener; use ApiPlatform\HttpCache\PurgerInterface; use ApiPlatform\Metadata\ApiResource; @@ -34,7 +33,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class AddTagsListenerTest extends TestCase { @@ -135,7 +133,7 @@ public function testAddTags() $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); @@ -192,31 +190,9 @@ public function testAddCollectionIriWhenCollectionIsEmpty() $this->assertSame('/dummies', $response->headers->get('Cache-Tags')); } - public function testAddSubResourceCollectionIri() - { - $iriConverterProphecy = $this->prophesize(LegacyIriConverterInterface::class); - $iriConverterProphecy->getIriFromResourceClass(Dummy::class, UrlGeneratorInterface::ABS_PATH)->willReturn('/dummies')->shouldBeCalled(); - - $response = new Response(); - $response->setPublic(); - $response->setEtag('foo'); - - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_subresource_operation_name' => 'api_dummies_relatedDummies_get_subresource', '_api_subresource_context' => ['collection' => true]]), - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - $response - ); - - $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event); - - $this->assertSame('/foo,/bar,/dummies', $response->headers->get('Cache-Tags')); - } - public function testAddTagsWithXKey() { - $operation = (new GetCollection()); + $operation = (new GetCollection(name: 'get')); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getIriFromResource(Dummy::class, UrlGeneratorInterface::ABS_PATH, $operation, Argument::type('array'))->willReturn('/dummies')->shouldBeCalled(); @@ -230,7 +206,7 @@ public function testAddTagsWithXKey() $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_resources' => ['/foo' => '/foo', '/bar' => '/bar'], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_resources' => ['/foo' => '/foo', '/bar' => '/bar'], '_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), HttpKernelInterface::MASTER_REQUEST, $response ); @@ -246,7 +222,7 @@ public function testAddTagsWithXKey() public function testAddTagsWithoutHeader() { - $operation = (new GetCollection()); + $operation = (new GetCollection(name: 'get')); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getIriFromResource(Dummy::class, UrlGeneratorInterface::ABS_PATH, $operation, Argument::type('array'))->willReturn('/dummies')->shouldBeCalled(); @@ -260,7 +236,7 @@ public function testAddTagsWithoutHeader() $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_resources' => ['/foo' => '/foo', '/bar' => '/bar'], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_resources' => ['/foo' => '/foo', '/bar' => '/bar'], '_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), HttpKernelInterface::MASTER_REQUEST, $response ); From 3cfa5375a921ef195d8207f1cc7c797777cfaf49 Mon Sep 17 00:00:00 2001 From: Vincent Chalamon Date: Wed, 18 May 2022 09:17:49 +0200 Subject: [PATCH 21/56] test: fix Util tests --- src/Util/AttributesExtractor.php | 16 ---- .../Command/JsonSchemaGenerateCommandTest.php | 1 - .../AnnotationFilterExtractorTraitTest.php | 85 ------------------- tests/Util/RequestAttributesExtractorTest.php | 67 ++++++--------- 4 files changed, 27 insertions(+), 142 deletions(-) delete mode 100644 tests/Util/AnnotationFilterExtractorTraitTest.php diff --git a/src/Util/AttributesExtractor.php b/src/Util/AttributesExtractor.php index 6225c7fc170..89470fad7b2 100644 --- a/src/Util/AttributesExtractor.php +++ b/src/Util/AttributesExtractor.php @@ -33,22 +33,6 @@ private function __construct() public static function extractAttributes(array $attributes): array { $result = ['resource_class' => $attributes['_api_resource_class'] ?? null, 'has_composite_identifier' => $attributes['_api_has_composite_identifier'] ?? false]; - if ($subresourceContext = $attributes['_api_subresource_context'] ?? null) { - $result['subresource_context'] = $subresourceContext; - } - - // // Normalizing identifiers tuples - // // TODO: 3.0 remove - // $identifiers = []; - // foreach (($attributes['_api_identifiers'] ?? ['id']) as $parameterName => $identifiedBy) { - // if (\is_string($identifiedBy)) { - // $identifiers[$identifiedBy] = [$result['resource_class'], $identifiedBy]; - // } else { - // $identifiers[$parameterName] = $identifiedBy; - // } - // } - // - // $result['identifiers'] = $identifiers; if (null === $result['resource_class']) { return []; diff --git a/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php b/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php index 4e0350b0b3e..dbef8b3f7b4 100644 --- a/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php +++ b/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php @@ -47,7 +47,6 @@ public function testExecuteWithoutOption() { $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass]); - dump($this->tester->getDisplay()); $this->assertJson($this->tester->getDisplay()); } diff --git a/tests/Util/AnnotationFilterExtractorTraitTest.php b/tests/Util/AnnotationFilterExtractorTraitTest.php deleted file mode 100644 index f0b7f07c2cf..00000000000 --- a/tests/Util/AnnotationFilterExtractorTraitTest.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * 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\Tests\Util; - -use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; -use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter; -use ApiPlatform\Doctrine\Orm\Filter\DateFilter; -use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; -use ApiPlatform\Serializer\Filter\GroupFilter; -use ApiPlatform\Serializer\Filter\PropertyFilter; -use ApiPlatform\Tests\Fixtures\DummyEntityFilterAnnotated; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; -use ApiPlatform\Tests\Fixtures\TestBundle\Util\AnnotationFilterExtractor; -use Doctrine\Common\Annotations\AnnotationReader; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; - -class AnnotationFilterExtractorTraitTest extends KernelTestCase -{ - private $extractor; - - protected function setUp(): void - { - self::bootKernel(); - $this->extractor = new AnnotationFilterExtractor(new AnnotationReader()); - } - - public function testReadAnnotations() - { - $reflectionClass = new \ReflectionClass(DummyCar::class); - $this->assertEquals($this->extractor->getFilters($reflectionClass), [ - 'annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_car_api_platform_doctrine_orm_filter_date_filter' => [ - ['properties' => ['id' => 'exclude_null', 'colors' => 'exclude_null', 'name' => 'exclude_null', 'canSell' => 'exclude_null', 'availableAt' => 'exclude_null', 'brand' => 'exclude_null', 'secondColors' => 'exclude_null', 'thirdColors' => 'exclude_null', 'uuid' => 'exclude_null', 'info' => 'exclude_null']], - DateFilter::class, - ], - 'annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_car_api_platform_doctrine_orm_filter_boolean_filter' => [ - [], - BooleanFilter::class, - ], - 'annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_car_api_platform_core_bridge_doctrine_orm_filter_search_filter' => [ - ['properties' => ['name' => 'partial', 'colors.prop' => 'ipartial', 'colors' => 'exact', 'secondColors' => 'exact', 'thirdColors' => 'exact', 'uuid' => 'exact']], - SearchFilter::class, - ], - 'annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_car_api_platform_serializer_filter_property_filter' => [ - ['parameterName' => 'foobar'], - PropertyFilter::class, - ], - 'annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_car_api_platform_serializer_filter_group_filter' => [ - ['parameterName' => 'foobargroups'], - GroupFilter::class, - ], - 'annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_car_api_platform_serializer_filter_group_filter_override' => [ - ['parameterName' => 'foobargroups_override'], - GroupFilter::class, - ], - ]); - } - - public function testReadOrderAnnotations() - { - $reflectionClass = new \ReflectionClass(DummyEntityFilterAnnotated::class); - - $this->assertEquals($this->extractor->getFilters($reflectionClass), [ - 'annotated_api_platform_tests_fixtures_dummy_entity_filter_annotated_api_platform_doctrine_orm_filter_order_filter' => [ - [ - 'orderParameterName' => 'positionOrder', - 'properties' => [ - 'position' => null, 'priority' => null, 'number' => 'ASC', - ], - ], - OrderFilter::class, - ], - ]); - } -} diff --git a/tests/Util/RequestAttributesExtractorTest.php b/tests/Util/RequestAttributesExtractorTest.php index f37ab0d963b..474fe3ae201 100644 --- a/tests/Util/RequestAttributesExtractorTest.php +++ b/tests/Util/RequestAttributesExtractorTest.php @@ -24,154 +24,143 @@ class RequestAttributesExtractorTest extends TestCase { public function testExtractCollectionAttributes() { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'post']); $this->assertEquals([ 'resource_class' => 'Foo', - 'collection_operation_name' => 'post', + 'operation_name' => 'post', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); } public function testExtractItemAttributes() { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); } public function testExtractReceive() { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_receive' => '0']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_receive' => '0']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => false, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_receive' => '1']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_receive' => '1']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); } public function testExtractRespond() { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_respond' => '0']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_respond' => '0']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => false, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_respond' => '1']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_respond' => '1']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); } public function testExtractPersist() { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_persist' => '0']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_persist' => '0']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => false, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_persist' => '1']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_persist' => '1']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); } public function testResourceClassNotSet() { - $this->assertEmpty(RequestAttributesExtractor::extractAttributes(new Request([], [], ['_api_item_operation_name' => 'get']))); + $this->assertEmpty(RequestAttributesExtractor::extractAttributes(new Request([], [], ['_api_operation_name' => 'get']))); } public function testOperationNotSet() @@ -182,31 +171,29 @@ public function testOperationNotSet() public function testExtractPreviousDataAttributes() { $object = new \stdClass(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', 'previous_data' => $object]); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', 'previous_data' => $object]); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, 'previous_data' => $object, - 'identifiers' => ['id' => ['Foo', 'id']], 'has_composite_identifier' => false, ], RequestAttributesExtractor::extractAttributes($request)); } public function testExtractIdentifiers() { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_identifiers' => ['test'], '_api_has_composite_identifier' => true]); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_identifiers' => ['test'], '_api_has_composite_identifier' => true]); $this->assertEquals([ 'resource_class' => 'Foo', - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, - 'identifiers' => ['test' => ['Foo', 'test']], 'has_composite_identifier' => true, ], RequestAttributesExtractor::extractAttributes($request)); } From 65149ba12f4dbcf5fd724d855ee7364ccdf157d9 Mon Sep 17 00:00:00 2001 From: Vincent Chalamon Date: Wed, 18 May 2022 10:13:07 +0200 Subject: [PATCH 22/56] test: fix OpenApi tests --- .../Serializer/ApiGatewayNormalizerTest.php | 30 +-- .../Serializer/OpenApiNormalizerTest.php | 212 ++++-------------- 2 files changed, 57 insertions(+), 185 deletions(-) diff --git a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php index 1050884d9c5..a37c9213e10 100644 --- a/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php +++ b/tests/OpenApi/Serializer/ApiGatewayNormalizerTest.php @@ -13,10 +13,10 @@ namespace ApiPlatform\Tests\OpenApi\Serializer; -use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer; +use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -29,14 +29,14 @@ final class ApiGatewayNormalizerTest extends TestCase public function testSupportsNormalization(): void { - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->willImplement(CacheableSupportsMethodInterface::class); - $documentationNormalizerProphecy->supportsNormalization(DocumentationNormalizer::FORMAT, Documentation::class)->willReturn(true); - $documentationNormalizerProphecy->hasCacheableSupportsMethod()->willReturn(true); + $normalizerProphecy = $this->prophesize(NormalizerInterface::class); + $normalizerProphecy->willImplement(CacheableSupportsMethodInterface::class); + $normalizerProphecy->supportsNormalization(OpenApiNormalizer::FORMAT, Documentation::class)->willReturn(true); + $normalizerProphecy->hasCacheableSupportsMethod()->willReturn(true); - $normalizer = new ApiGatewayNormalizer($documentationNormalizerProphecy->reveal()); + $normalizer = new ApiGatewayNormalizer($normalizerProphecy->reveal()); - $this->assertTrue($normalizer->supportsNormalization(DocumentationNormalizer::FORMAT, Documentation::class)); + $this->assertTrue($normalizer->supportsNormalization(OpenApiNormalizer::FORMAT, Documentation::class)); $this->assertTrue($normalizer->hasCacheableSupportsMethod()); } @@ -355,15 +355,15 @@ public function testNormalize(): void 'basePath' => '/', ]; - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize($documentation, DocumentationNormalizer::FORMAT, [ + $normalizerProphecy = $this->prophesize(NormalizerInterface::class); + $normalizerProphecy->normalize($documentation, OpenApiNormalizer::FORMAT, [ 'spec_version' => 2, ApiGatewayNormalizer::API_GATEWAY => true, ])->willReturn($swaggerDocument); - $normalizer = new ApiGatewayNormalizer($documentationNormalizerProphecy->reveal()); + $normalizer = new ApiGatewayNormalizer($normalizerProphecy->reveal()); - $this->assertEquals($modifiedSwaggerDocument, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, [ + $this->assertEquals($modifiedSwaggerDocument, $normalizer->normalize($documentation, OpenApiNormalizer::FORMAT, [ 'spec_version' => 2, ApiGatewayNormalizer::API_GATEWAY => true, ])); @@ -534,14 +534,14 @@ public function testNormalizeNotInApiGatewayContext(): void ]), ]; - $documentationNormalizerProphecy = $this->prophesize(NormalizerInterface::class); - $documentationNormalizerProphecy->normalize($documentation, DocumentationNormalizer::FORMAT, [ + $normalizerProphecy = $this->prophesize(NormalizerInterface::class); + $normalizerProphecy->normalize($documentation, OpenApiNormalizer::FORMAT, [ 'spec_version' => 2, ])->willReturn($swaggerDocument); - $normalizer = new ApiGatewayNormalizer($documentationNormalizerProphecy->reveal()); + $normalizer = new ApiGatewayNormalizer($normalizerProphecy->reveal()); - $this->assertEquals($swaggerDocument, $normalizer->normalize($documentation, DocumentationNormalizer::FORMAT, [ + $this->assertEquals($swaggerDocument, $normalizer->normalize($documentation, OpenApiNormalizer::FORMAT, [ 'spec_version' => 2, ])); } diff --git a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php index 93c666f78af..48050c3370d 100644 --- a/tests/OpenApi/Serializer/OpenApiNormalizerTest.php +++ b/tests/OpenApi/Serializer/OpenApiNormalizerTest.php @@ -13,17 +13,6 @@ namespace ApiPlatform\Tests\OpenApi\Serializer; -use ApiPlatform\Core\Api\IdentifiersExtractorInterface; -use ApiPlatform\Core\JsonSchema\SchemaFactory as LegacySchemaFactory; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\OpenApi\Factory\OpenApiFactory as LegacyOpenApiFactory; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator; use ApiPlatform\JsonSchema\SchemaFactory; use ApiPlatform\JsonSchema\TypeFactory; use ApiPlatform\Metadata\ApiProperty; @@ -35,6 +24,8 @@ use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; use ApiPlatform\Metadata\Put; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; @@ -45,8 +36,6 @@ use ApiPlatform\OpenApi\OpenApi; use ApiPlatform\OpenApi\Options; use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer; -use ApiPlatform\PathResolver\CustomOperationPathResolver; -use ApiPlatform\PathResolver\OperationPathResolver; use ApiPlatform\State\Pagination\PaginationOptions; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; @@ -59,9 +48,6 @@ use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; -/** - * @group legacy - */ class OpenApiNormalizerTest extends TestCase { use ProphecyTrait; @@ -71,151 +57,6 @@ class OpenApiNormalizerTest extends TestCase 'output_formats' => ['jsonld' => ['application/ld+json']], ]; - /** - * @groupe legacy - */ - public function testLegacyFactoryNormalize() - { - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Dummy::class, 'Zorro'])); - $defaultContext = ['base_url' => '/app_dev.php/']; - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate', 'paths'])); - $propertyNameCollectionFactoryProphecy->create('Zorro', Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id'])); - - $dummyMetadata = new ResourceMetadata( - 'Dummy', - 'This is a dummy.', - 'http://schema.example.com/Dummy', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'put' => ['method' => 'PUT'] + self::OPERATION_FORMATS, - 'delete' => ['method' => 'DELETE'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - 'post' => ['method' => 'POST', 'openapi_context' => ['security' => [], 'servers' => ['url' => '/test']]] + self::OPERATION_FORMATS, - ], - [] - ); - - $zorroMetadata = new ResourceMetadata( - 'Zorro', - 'This is zorro.', - 'http://schema.example.com/Zorro', - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - ], - [ - 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS, - ], - [] - ); - - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create(Argument::any(), Argument::any(), Argument::any())->willReturn([]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create('Zorro')->shouldBeCalled()->willReturn($zorroMetadata); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true, null, null, null, null, null, null, null)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is a name.', true, true, true, true, false, false, null, null, [], null, null, null, null, ['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$'])); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'This is an initializable but not writable property.', true, false, true, true, false, false, null, null, [], null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class), 'This is a \DateTimeInterface object.', true, true, true, true, false, false, null, null, [])); - // Check reserved word "paths": when normalize->recursiveClean in OpenApi Component Schema. - $propertyMetadataFactoryProphecy->create(Dummy::class, 'paths', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_ARRAY), 'This is a array.', true, true, true, true, false, false, null, null, [])); - - $propertyMetadataFactoryProphecy->create('Zorro', 'id', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_INT), 'This is an id.', true, false, null, null, null, true)); - - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); - $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); - $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); - $propertyMetadataFactory = $propertyMetadataFactoryProphecy->reveal(); - - $typeFactory = new TypeFactory(); - $schemaFactory = new LegacySchemaFactory($typeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new CamelCaseToSnakeCaseNameConverter()); - $typeFactory->setSchemaFactory($schemaFactory); - - $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); - $identifiersExtractorProphecy->getIdentifiersFromResourceClass(Argument::type('string'))->willReturn(['id']); - - $factory = new LegacyOpenApiFactory( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactory, - $propertyNameCollectionFactory, - $propertyMetadataFactory, - $schemaFactory, - $typeFactory, - $operationPathResolver, - $filterLocatorProphecy->reveal(), - $subresourceOperationFactoryProphecy->reveal(), - $identifiersExtractorProphecy->reveal(), - [], - new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ - 'header' => [ - 'type' => 'header', - 'name' => 'Authorization', - ], - 'query' => [ - 'type' => 'query', - 'name' => 'key', - ], - ]), - new PaginationOptions(true, 'page', true, 'itemsPerPage', true, 'pagination') - ); - - $openApi = $factory(['base_url' => '/app_dev.php/']); - - $pathItem = $openApi->getPaths()->getPath('/dummies/{id}'); - $operation = $pathItem->getGet(); - - $openApi->getPaths()->addPath('/dummies/{id}', $pathItem->withGet( - $operation->withParameters(array_merge( - $operation->getParameters(), - [new Model\Parameter('fields', 'query', 'Fields to remove of the output')] - )) - )); - - $openApi = $openApi->withInfo((new Model\Info('New Title', 'v2', 'Description of my custom API'))->withExtensionProperty('info-key', 'Info value')); - $openApi = $openApi->withExtensionProperty('key', 'Custom x-key value'); - $openApi = $openApi->withExtensionProperty('x-value', 'Custom x-value value'); - - $encoders = [new JsonEncoder()]; - $normalizers = [new ObjectNormalizer()]; - - $serializer = new Serializer($normalizers, $encoders); - $normalizers[0]->setSerializer($serializer); - - $normalizer = new OpenApiNormalizer($normalizers[0]); - - $openApiAsArray = $normalizer->normalize($openApi); - - // Just testing normalization specifics - $this->assertEquals($openApiAsArray['x-key'], 'Custom x-key value'); - $this->assertEquals($openApiAsArray['x-value'], 'Custom x-value value'); - $this->assertEquals($openApiAsArray['info']['x-info-key'], 'Info value'); - $this->assertArrayNotHasKey('extensionProperties', $openApiAsArray); - // this key is null, should not be in the output - $this->assertArrayNotHasKey('termsOfService', $openApiAsArray['info']); - $this->assertArrayNotHasKey('summary', $openApiAsArray['info']); - $this->assertArrayNotHasKey('paths', $openApiAsArray['paths']); - $this->assertArrayHasKey('/dummies/{id}', $openApiAsArray['paths']); - $this->assertArrayNotHasKey('servers', $openApiAsArray['paths']['/dummies/{id}']['get']); - $this->assertArrayNotHasKey('security', $openApiAsArray['paths']['/dummies/{id}']['get']); - - // Security can be disabled per-operation using an empty array - $this->assertEquals([], $openApiAsArray['paths']['/dummies']['post']['security']); - $this->assertEquals(['url' => '/test'], $openApiAsArray['paths']['/dummies']['post']['servers']); - - // Make sure things are sorted - $this->assertEquals(array_keys($openApiAsArray['paths']), ['/dummies', '/dummies/{id}', '/zorros', '/zorros/{id}']); - // Test name converter doesn't rename this property - $this->assertArrayHasKey('requestBody', $openApiAsArray['paths']['/dummies']['post']); - } - public function testNormalizeWithSchemas() { $openApi = new OpenApi(new Model\Info('My API', '1.0.0', 'An amazing API'), [new Model\Server('https://example.com')], new Model\Paths(), new Model\Components(new \ArrayObject(['z' => [], 'b' => []]))); @@ -254,7 +95,6 @@ public function testNormalize() { $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->shouldBeCalled()->willReturn(new ResourceNameCollection([Dummy::class, 'Zorro'])); - $defaultContext = ['base_url' => '/app_dev.php/']; $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id', 'name', 'description', 'dummyDate'])); $propertyNameCollectionFactoryProphecy->create('Zorro', Argument::any())->shouldBeCalled()->willReturn(new PropertyNameCollection(['id'])); @@ -299,24 +139,57 @@ public function testNormalize() $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::any())->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)])->withDescription('This is an id.')->withReadable(true)->withWritable(false)->withIdentifier(true) + (new ApiProperty()) + ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)]) + ->withDescription('This is an id.') + ->withReadable(true) + ->withWritable(false) + ->withIdentifier(true) ); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withSchema(['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$']) + (new ApiProperty()) + ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)]) + ->withDescription('This is a name.') + ->withReadable(true) + ->withWritable(true) + ->withReadableLink(true) + ->withWritableLink(true) + ->withRequired(false) + ->withIdentifier(false) + ->withSchema(['minLength' => 3, 'maxLength' => 20, 'pattern' => '^dummyPattern$']) ); $propertyMetadataFactoryProphecy->create(Dummy::class, 'description', Argument::any())->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('This is an initializable but not writable property.')->withReadable(true)->withWritable(false)->withReadableLink(true)->withWritableLink(true)->withInitializable(true) + (new ApiProperty()) + ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)]) + ->withDescription('This is an initializable but not writable property.') + ->withReadable(true) + ->withWritable(false) + ->withReadableLink(true) + ->withWritableLink(true) + ->withRequired(false) + ->withIdentifier(false) ); $propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyDate', Argument::any())->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class)])->withDescription('This is a \DateTimeInterface object.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + (new ApiProperty()) + ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, true, \DateTime::class)]) + ->withDescription('This is a \DateTimeInterface object.') + ->withReadable(true) + ->withWritable(true) + ->withReadableLink(true) + ->withWritableLink(true) + ->withRequired(false) + ->withIdentifier(false) ); $propertyMetadataFactoryProphecy->create('Zorro', 'id', Argument::any())->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)])->withDescription('This is an id.')->withReadable(true)->withWritable(false)->withIdentifier(true) + (new ApiProperty()) + ->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_INT)]) + ->withDescription('This is an id.') + ->withReadable(true) + ->withWritable(false) + ->withIdentifier(true) ); - $operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator())); $filterLocatorProphecy = $this->prophesize(ContainerInterface::class); $resourceMetadataFactory = $resourceCollectionMetadataFactoryProphecy->reveal(); $propertyNameCollectionFactory = $propertyNameCollectionFactoryProphecy->reveal(); @@ -333,7 +206,6 @@ public function testNormalize() $propertyMetadataFactory, $schemaFactory, $typeFactory, - $operationPathResolver, $filterLocatorProphecy->reveal(), [], new Options('Test API', 'This is a test API.', '1.2.3', true, 'oauth2', 'authorizationCode', '/oauth/v2/token', '/oauth/v2/auth', '/oauth/v2/refresh', ['scope param'], [ From 098d98219a6675949fef631f817f598fc22c7887 Mon Sep 17 00:00:00 2001 From: Vincent Chalamon Date: Wed, 18 May 2022 10:22:20 +0200 Subject: [PATCH 23/56] test: fix Metadata tests --- src/Metadata/ApiProperty.php | 1 - .../Metadata/Extractor/PropertyMetadataCompatibilityTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Metadata/ApiProperty.php b/src/Metadata/ApiProperty.php index bf97c45b7fd..64fe8c9f55a 100644 --- a/src/Metadata/ApiProperty.php +++ b/src/Metadata/ApiProperty.php @@ -169,7 +169,6 @@ public function __construct( $this->jsonSchemaContext = $jsonSchemaContext; $this->push = $push; $this->security = $security; - $this->openapiContext = $openapiContext; $this->securityPostDenormalize = $securityPostDenormalize; $this->types = $types; $this->builtinTypes = $builtinTypes; diff --git a/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php b/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php index d6a020f3984..b3ac23e40b3 100644 --- a/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php +++ b/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php @@ -60,7 +60,7 @@ final class PropertyMetadataCompatibilityTest extends TestCase 'foo' => 'bar', ], 'jsonSchemaContext' => [ - 'foo' => 'bar', + 'lorem' => 'ipsum', ], 'push' => true, 'security' => 'is_granted(\'IS_AUTHENTICATED_ANONYMOUSLY\')', @@ -71,7 +71,7 @@ final class PropertyMetadataCompatibilityTest extends TestCase 'extraProperties' => [ 'custom_property' => 'Lorem ipsum dolor sit amet', ], - 'iris' => ['https://schema.org/totalPrice'], + 'iri' => false, ]; /** From 927c96452e132c852d15a4ac55d2dd4c3f5407ad Mon Sep 17 00:00:00 2001 From: Vincent Chalamon Date: Wed, 18 May 2022 11:07:37 +0200 Subject: [PATCH 24/56] test: fix JsonLd tests --- src/GraphQl/Serializer/ItemNormalizer.php | 3 +- src/JsonApi/Serializer/ItemNormalizer.php | 8 +- src/JsonLd/Action/ContextAction.php | 31 +++---- src/JsonLd/ContextBuilder.php | 84 ++----------------- src/JsonLd/Serializer/ItemNormalizer.php | 2 +- src/JsonLd/Serializer/ObjectNormalizer.php | 9 +- src/Serializer/AbstractItemNormalizer.php | 45 ++++------ tests/JsonLd/Action/ContextActionTest.php | 61 ++++++++++---- tests/JsonLd/ContextBuilderTest.php | 72 +++++++++++----- .../JsonLd/Serializer/ItemNormalizerTest.php | 82 ++++-------------- .../Serializer/ObjectNormalizerTest.php | 7 +- 11 files changed, 158 insertions(+), 246 deletions(-) diff --git a/src/GraphQl/Serializer/ItemNormalizer.php b/src/GraphQl/Serializer/ItemNormalizer.php index 669f25c58c3..5bf8a4b167a 100644 --- a/src/GraphQl/Serializer/ItemNormalizer.php +++ b/src/GraphQl/Serializer/ItemNormalizer.php @@ -16,6 +16,7 @@ use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; +use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -95,7 +96,7 @@ public function normalize($object, $format = null, array $context = []) /** * {@inheritdoc} */ - protected function normalizeCollectionOfRelations($propertyMetadata, $attributeValue, string $resourceClass, ?string $format, array $context): array + protected function normalizeCollectionOfRelations(ApiProperty $propertyMetadata, iterable $attributeValue, string $resourceClass, ?string $format, array $context): array { // to-many are handled directly by the GraphQL resolver return []; diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index c32c49131ee..2ac2d940742 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -183,12 +183,10 @@ protected function setAttributeValue($object, $attribute, $value, $format = null * * @see http://jsonapi.org/format/#document-resource-object-linkage * - * @param ApiProperty|PropertyMetadata $propertyMetadata - * * @throws RuntimeException * @throws NotNormalizableValueException */ - protected function denormalizeRelation(string $attributeName, $propertyMetadata, string $className, $value, ?string $format, array $context) + protected function denormalizeRelation(string $attributeName, ApiProperty $propertyMetadata, string $className, $value, ?string $format, array $context) { if (!\is_array($value) || !isset($value['id'], $value['type'])) { throw new NotNormalizableValueException('Only resource linkage supported currently, see: http://jsonapi.org/format/#document-resource-object-linkage.'); @@ -204,11 +202,9 @@ protected function denormalizeRelation(string $attributeName, $propertyMetadata, /** * {@inheritdoc} * - * @param ApiProperty|PropertyMetadata $propertyMetadata - * * @see http://jsonapi.org/format/#document-resource-object-linkage */ - protected function normalizeRelation($propertyMetadata, $relatedObject, string $resourceClass, ?string $format, array $context) + protected function normalizeRelation(ApiProperty $propertyMetadata, ?object $relatedObject, string $resourceClass, ?string $format, array $context) { if (null !== $relatedObject) { $iri = $this->iriConverter->getIriFromResource($relatedObject); diff --git a/src/JsonLd/Action/ContextAction.php b/src/JsonLd/Action/ContextAction.php index bbb21fa781a..63fa573eaf4 100644 --- a/src/JsonLd/Action/ContextAction.php +++ b/src/JsonLd/Action/ContextAction.php @@ -13,8 +13,6 @@ namespace ApiPlatform\JsonLd\Action; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -36,20 +34,13 @@ final class ContextAction private $contextBuilder; private $resourceNameCollectionFactory; - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface|null - */ - private $resourceMetadataFactory; + private $resourceMetadataCollectionFactory; - public function __construct(ContextBuilderInterface $contextBuilder, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, $resourceMetadataFactory) + public function __construct(ContextBuilderInterface $contextBuilder, ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory) { $this->contextBuilder = $contextBuilder; $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } + $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; } /** @@ -68,18 +59,16 @@ public function __invoke(string $shortName): array } foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - /** @var ResourceMetadata|ResourceMetadataCollection */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); + /** @var ResourceMetadataCollection */ + $resourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($resourceClass); - if ($resourceMetadata instanceof ResourceMetadataCollection) { - try { - $resourceMetadata = $resourceMetadata->getOperation(); - } catch (OperationNotFoundException $e) { - continue; - } + try { + $resourceMetadataCollection = $resourceMetadataCollection->getOperation(); + } catch (OperationNotFoundException) { + continue; } - if ($shortName === $resourceMetadata->getShortName()) { + if ($shortName === $resourceMetadataCollection->getShortName()) { return ['@context' => $this->contextBuilder->getResourceContext($resourceClass)]; } } diff --git a/src/JsonLd/ContextBuilder.php b/src/JsonLd/ContextBuilder.php index a458dda7a3e..a28456253ab 100644 --- a/src/JsonLd/ContextBuilder.php +++ b/src/JsonLd/ContextBuilder.php @@ -14,12 +14,8 @@ namespace ApiPlatform\JsonLd; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\HttpOperation; +use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -29,7 +25,6 @@ /** * {@inheritdoc} - * TODO: 3.0 simplify or remove the class. * * @author Kévin Dunglas */ @@ -40,17 +35,8 @@ final class ContextBuilder implements AnonymousContextBuilderInterface public const FORMAT = 'jsonld'; private $resourceNameCollectionFactory; - /** - * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory - */ private $resourceMetadataFactory; - /** - * @var LegacyPropertyNameCollectionFactoryInterface|PropertyNameCollectionFactoryInterface - */ private $propertyNameCollectionFactory; - /** - * @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface - */ private $propertyMetadataFactory; private $urlGenerator; @@ -59,7 +45,7 @@ final class ContextBuilder implements AnonymousContextBuilderInterface */ private $nameConverter; - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, UrlGeneratorInterface $urlGenerator, NameConverterInterface $nameConverter = null) + public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, UrlGeneratorInterface $urlGenerator, NameConverterInterface $nameConverter = null) { $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; $this->resourceMetadataFactory = $resourceMetadataFactory; @@ -67,10 +53,6 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName $this->propertyMetadataFactory = $propertyMetadataFactory; $this->urlGenerator = $urlGenerator; $this->nameConverter = $nameConverter; - - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -92,12 +74,7 @@ public function getEntrypointContext(int $referenceType = UrlGeneratorInterface: $context = $this->getBaseContext($referenceType); foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - // TODO: remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $shortName = $this->resourceMetadataFactory->create($resourceClass)->getShortName(); - } else { - $shortName = $this->resourceMetadataFactory->create($resourceClass)[0]->getShortName(); - } + $shortName = $this->resourceMetadataFactory->create($resourceClass)[0]->getShortName(); $resourceName = lcfirst($shortName); @@ -115,23 +92,6 @@ public function getEntrypointContext(int $referenceType = UrlGeneratorInterface: */ public function getResourceContext(string $resourceClass, int $referenceType = UrlGeneratorInterface::ABS_PATH): array { - // TODO: Remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (null === $shortName = $resourceMetadata->getShortName()) { - return []; - } - - if ($resourceMetadata->getAttribute('normalization_context')['iri_only'] ?? false) { - $context = $this->getBaseContext($referenceType); - $context['hydra:member']['@type'] = '@id'; - - return $context; - } - - return $this->getResourceContextWithShortname($resourceClass, $referenceType, $shortName); - } - $operation = $this->resourceMetadataFactory->create($resourceClass)->getOperation(); if (null === $shortName = $operation->getShortName()) { return []; @@ -152,16 +112,6 @@ public function getResourceContext(string $resourceClass, int $referenceType = U */ public function getResourceContextUri(string $resourceClass, int $referenceType = null): string { - // TODO: remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (null === $referenceType) { - $referenceType = $resourceMetadata->getAttribute('url_generation_strategy'); - } - - return $this->urlGenerator->generate('api_jsonld_context', ['shortName' => $resourceMetadata->getShortName()], $referenceType); - } - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass)[0]; if (null === $referenceType) { $referenceType = $resourceMetadata->getUrlGenerationStrategy(); @@ -197,27 +147,19 @@ public function getAnonymousResourceContext($object, array $context = [], int $r // here the object can be different from the resource given by the $context['api_resource'] value if (isset($context['api_resource'])) { - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))->getShortName(); - } else { - $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))[0]->getShortName(); - } + $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))[0]->getShortName(); } return $jsonLdContext; } - private function getResourceContextWithShortname(string $resourceClass, int $referenceType, string $shortName, ?HttpOperation $operation = null): array + private function getResourceContextWithShortname(string $resourceClass, int $referenceType, string $shortName, ?Operation $operation = null): array { $context = $this->getBaseContext($referenceType); - if ($this->propertyMetadataFactory instanceof LegacyPropertyMetadataFactoryInterface) { - $propertyContext = []; - } else { - $propertyContext = $operation ? ['normalization_groups' => $operation->getNormalizationContext()['groups'] ?? null, 'denormalization_groups' => $operation->getDenormalizationContext()['groups'] ?? null] : ['normalization_groups' => [], 'denormalization_groups' => []]; - } + $propertyContext = $operation ? ['normalization_groups' => $operation->getNormalizationContext()['groups'] ?? null, 'denormalization_groups' => $operation->getDenormalizationContext()['groups'] ?? null] : ['normalization_groups' => [], 'denormalization_groups' => []]; foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - /** @var PropertyMetadata|ApiProperty */ + /** @var ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName, $propertyContext); if ($propertyMetadata->isIdentifier() && true !== $propertyMetadata->isWritable()) { @@ -225,16 +167,8 @@ private function getResourceContextWithShortname(string $resourceClass, int $ref } $convertedName = $this->nameConverter ? $this->nameConverter->normalize($propertyName, $resourceClass, self::FORMAT) : $propertyName; - if ($propertyMetadata instanceof PropertyMetadata) { - $jsonldContext = ($propertyMetadata->getAttributes() ?? [])['jsonld_context'] ?? []; - $id = $propertyMetadata->getIri(); - } else { - $jsonldContext = $propertyMetadata->getJsonldContext() ?? []; - - if ($id = $propertyMetadata->getIris()) { - $id = 1 === \count($id) ? $id[0] : $id; - } - } + $jsonldContext = $propertyMetadata->getJsonldContext() ?? []; + $id = $propertyMetadata->getTypes()[0] ?? null; if (!$id) { $id = sprintf('%s/%s', $shortName, $convertedName); diff --git a/src/JsonLd/Serializer/ItemNormalizer.php b/src/JsonLd/Serializer/ItemNormalizer.php index 7fd4828fcc4..89c3b41e556 100644 --- a/src/JsonLd/Serializer/ItemNormalizer.php +++ b/src/JsonLd/Serializer/ItemNormalizer.php @@ -48,7 +48,7 @@ final class ItemNormalizer extends AbstractItemNormalizer public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ContextBuilderInterface $contextBuilder, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, null, false, $defaultContext, $dataTransformers, $resourceMetadataFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $defaultContext, $resourceMetadataFactory, $resourceAccessChecker); $this->contextBuilder = $contextBuilder; } diff --git a/src/JsonLd/Serializer/ObjectNormalizer.php b/src/JsonLd/Serializer/ObjectNormalizer.php index 93b064ed261..c3e0df18d28 100644 --- a/src/JsonLd/Serializer/ObjectNormalizer.php +++ b/src/JsonLd/Serializer/ObjectNormalizer.php @@ -14,7 +14,6 @@ namespace ApiPlatform\JsonLd\Serializer; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\JsonLd\AnonymousContextBuilderInterface; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; @@ -34,15 +33,11 @@ final class ObjectNormalizer implements NormalizerInterface, CacheableSupportsMe private $iriConverter; private $anonymousContextBuilder; - public function __construct(NormalizerInterface $decorated, $iriConverter, AnonymousContextBuilderInterface $anonymousContextBuilder) + public function __construct(NormalizerInterface $decorated, IriConverterInterface $iriConverter, AnonymousContextBuilderInterface $anonymousContextBuilder) { $this->decorated = $decorated; $this->iriConverter = $iriConverter; $this->anonymousContextBuilder = $anonymousContextBuilder; - - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } } /** @@ -92,7 +87,7 @@ public function normalize($object, $format = null, array $context = []) if (isset($originalResource)) { try { - $context['output']['iri'] = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($originalResource) : $this->iriConverter->getIriFromResource($originalResource); + $context['output']['iri'] = $this->iriConverter->getIriFromResource($originalResource); } catch (InvalidArgumentException $e) { // The original resource has no identifiers } diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 6cac7a383a1..e083e382033 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -402,9 +402,9 @@ protected function canAccessAttribute($object, string $attribute, array $context } $options = $this->getFactoryOptions($context); - /** @var PropertyMetadata|ApiProperty */ + /** @var ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $options); - $security = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('security') : $propertyMetadata->getSecurity(); + $security = $propertyMetadata->getSecurity(); if ($this->resourceAccessChecker && $security) { return $this->resourceAccessChecker->isGranted($context['resource_class'], $security, [ 'object' => $object, @@ -423,9 +423,9 @@ protected function canAccessAttribute($object, string $attribute, array $context protected function canAccessAttributePostDenormalize($object, $previousObject, string $attribute, array $context = []): bool { $options = $this->getFactoryOptions($context); - /** @var PropertyMetadata|ApiProperty */ + /** @var ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $options); - $security = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('security_post_denormalize') : $propertyMetadata->getSecurityPostDenormalize(); + $security = $propertyMetadata->getSecurityPostDenormalize(); if ($this->resourceAccessChecker && $security) { return $this->resourceAccessChecker->isGranted($context['resource_class'], $security, [ 'object' => $object, @@ -468,12 +468,11 @@ protected function validateType(string $attribute, Type $type, $value, string $f /** * Denormalizes a collection of objects. * - * @param ApiProperty|PropertyMetadata $propertyMetadata - * @param mixed $value + * @param mixed $value * * @throws InvalidArgumentException */ - protected function denormalizeCollection(string $attribute, $propertyMetadata, Type $type, string $className, $value, ?string $format, array $context): array + protected function denormalizeCollection(string $attribute, ApiProperty $propertyMetadata, Type $type, string $className, $value, ?string $format, array $context): array { if (!\is_array($value)) { throw new InvalidArgumentException(sprintf('The type of the "%s" attribute must be "array", "%s" given.', $attribute, \gettype($value))); @@ -497,8 +496,7 @@ protected function denormalizeCollection(string $attribute, $propertyMetadata, T /** * Denormalizes a relation. * - * @param ApiProperty|PropertyMetadata $propertyMetadata - * @param mixed $value + * @param mixed $value * * @throws LogicException * @throws UnexpectedValueException @@ -506,7 +504,7 @@ protected function denormalizeCollection(string $attribute, $propertyMetadata, T * * @return object|null */ - protected function denormalizeRelation(string $attributeName, $propertyMetadata, string $className, $value, ?string $format, array $context) + protected function denormalizeRelation(string $attributeName, ApiProperty $propertyMetadata, string $className, $value, ?string $format, array $context) { if (\is_string($value)) { try { @@ -600,20 +598,13 @@ protected function createRelationSerializationContext(string $resourceClass, arr protected function getAttributeValue($object, $attribute, $format = null, array $context = []) { $context['api_attribute'] = $attribute; - /** @var ApiProperty|PropertyMetadata */ + /** @var ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context)); try { $attributeValue = $this->propertyAccessor->getValue($object, $attribute); } catch (NoSuchPropertyException $e) { - // BC to be removed in 3.0 - if ($propertyMetadata instanceof PropertyMetadata && !$propertyMetadata->hasChildInherited()) { - throw $e; - } - if ($propertyMetadata instanceof ApiProperty) { - throw $e; - } - + throw $e; $attributeValue = null; } @@ -621,7 +612,7 @@ protected function getAttributeValue($object, $attribute, $format = null, array return $attributeValue; } - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : ($propertyMetadata->getBuiltinTypes()[0] ?? null); + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; if ( $type && @@ -692,12 +683,9 @@ protected function getAttributeValue($object, $attribute, $format = null, array /** * Normalizes a collection of relations (to-many). * - * @param ApiProperty|PropertyMetadata $propertyMetadata - * @param iterable $attributeValue - * * @throws UnexpectedValueException */ - protected function normalizeCollectionOfRelations($propertyMetadata, $attributeValue, string $resourceClass, ?string $format, array $context): array + protected function normalizeCollectionOfRelations(ApiProperty $propertyMetadata, iterable $attributeValue, string $resourceClass, ?string $format, array $context): array { $value = []; foreach ($attributeValue as $index => $obj) { @@ -714,15 +702,12 @@ protected function normalizeCollectionOfRelations($propertyMetadata, $attributeV /** * Normalizes a relation. * - * @param ApiProperty|PropertyMetadata $propertyMetadata - * @param object|null $relatedObject - * * @throws LogicException * @throws UnexpectedValueException * * @return string|array|\ArrayObject|null IRI or normalized object data */ - protected function normalizeRelation($propertyMetadata, $relatedObject, string $resourceClass, ?string $format, array $context) + protected function normalizeRelation(ApiProperty $propertyMetadata, ?object $relatedObject, string $resourceClass, ?string $format, array $context) { if (null === $relatedObject || !empty($context['attributes']) || $propertyMetadata->isReadableLink()) { if (!$this->serializer instanceof NormalizerInterface) { @@ -738,13 +723,13 @@ protected function normalizeRelation($propertyMetadata, $relatedObject, string $ return $normalizedRelatedObject; } - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($relatedObject) : $this->iriConverter->getIriFromResource($relatedObject); + $iri = $this->iriConverter->getIriFromResource($relatedObject); if (isset($context['resources'])) { $context['resources'][$iri] = $iri; } - $push = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('push', false) : ($propertyMetadata->getPush() ?? false); + $push = $propertyMetadata->getPush() ?? false; if (isset($context['resources_to_push']) && $push) { $context['resources_to_push'][$iri] = $iri; } diff --git a/tests/JsonLd/Action/ContextActionTest.php b/tests/JsonLd/Action/ContextActionTest.php index d0bf3073217..f2e8df2cf55 100644 --- a/tests/JsonLd/Action/ContextActionTest.php +++ b/tests/JsonLd/Action/ContextActionTest.php @@ -13,11 +13,17 @@ namespace ApiPlatform\Tests\JsonLd\Action; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\JsonLd\Action\ContextAction; use ApiPlatform\JsonLd\ContextBuilderInterface; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -25,7 +31,6 @@ /** * @author Amrouche Hamza - * @group legacy */ class ContextActionTest extends TestCase { @@ -35,9 +40,9 @@ public function testContextActionWithEntrypoint() { $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $contextBuilderProphecy->getEntrypointContext()->willReturn(['/entrypoints']); - $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); + $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataCollectionFactoryProphecy->reveal()); $this->assertEquals(['@context' => ['/entrypoints']], $contextAction('Entrypoint')); } @@ -46,9 +51,9 @@ public function testContextActionWithContexts() { $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $contextBuilderProphecy->getBaseContext()->willReturn(['/contexts']); - $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); + $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataCollectionFactoryProphecy->reveal()); $this->assertEquals(['@context' => ['/contexts']], $contextAction('Error')); } @@ -57,13 +62,26 @@ public function testContextActionWithResourceClass() { $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummy'])); - $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); + $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataCollectionFactoryProphecy->reveal()); $contextBuilderProphecy->getResourceContext('dummy')->willReturn(['/dummies']); - $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn( - new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], []) + $resourceMetadataCollectionFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn( + new ResourceMetadataCollection('dummy', [ + (new ApiResource()) + ->withShortName('dummy') + ->withDescription('dummy') + ->withTypes(['#dummy']) + ->withOperations(new Operations([ + 'get' => (new Get())->withShortName('dummy'), + 'put' => (new Put())->withShortName('dummy'), + 'get_collection' => (new GetCollection())->withShortName('dummy'), + 'post' => (new Post())->withShortName('dummy'), + 'custom' => (new Get())->withUriTemplate('/foo')->withShortName('dummy'), + 'custom2' => (new Post())->withUriTemplate('/foo')->withShortName('dummy'), + ])), + ]) ); $this->assertEquals(['@context' => ['/dummies']], $contextAction('dummy')); } @@ -74,12 +92,25 @@ public function testContextActionWithThrown() $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['gerard'])); - $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); + $contextAction = new ContextAction($contextBuilderProphecy->reveal(), $resourceNameCollectionFactoryProphecy->reveal(), $resourceMetadataCollectionFactoryProphecy->reveal()); - $resourceMetadataFactoryProphecy->create('gerard')->shouldBeCalled()->willReturn( - new ResourceMetadata('gerard', 'gerard', '#dummy', ['get' => ['method' => 'GET'], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST'], 'custom' => ['method' => 'GET', 'path' => '/foo'], 'custom2' => ['method' => 'POST', 'path' => '/foo']], []) + $resourceMetadataCollectionFactoryProphecy->create('gerard')->shouldBeCalled()->willReturn( + new ResourceMetadataCollection('gerard', [ + (new ApiResource()) + ->withShortName('gerard') + ->withDescription('gerard') + ->withTypes(['#dummy']) + ->withOperations(new Operations([ + 'get' => (new Get())->withShortName('gerard'), + 'put' => (new Put())->withShortName('gerard'), + 'get_collection' => (new GetCollection())->withShortName('gerard'), + 'post' => (new Post())->withShortName('gerard'), + 'custom' => (new Get())->withUriTemplate('/foo')->withShortName('gerard'), + 'custom2' => (new Post())->withUriTemplate('/foo')->withShortName('gerard'), + ])), + ]) ); $contextAction('dummy'); } diff --git a/tests/JsonLd/ContextBuilderTest.php b/tests/JsonLd/ContextBuilderTest.php index 9df102a1d60..6458ed12094 100644 --- a/tests/JsonLd/ContextBuilderTest.php +++ b/tests/JsonLd/ContextBuilderTest.php @@ -14,14 +14,17 @@ namespace ApiPlatform\Tests\JsonLd; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -32,7 +35,6 @@ /** * @author Markus Mächler - * @group legacy */ class ContextBuilderTest extends TestCase { @@ -40,7 +42,7 @@ class ContextBuilderTest extends TestCase private $entityClass; private $resourceNameCollectionFactoryProphecy; - private $resourceMetadataFactoryProphecy; + private $resourceMetadataCollectionFactoryProphecy; private $propertyNameCollectionFactoryProphecy; private $propertyMetadataFactoryProphecy; private $urlGeneratorProphecy; @@ -49,7 +51,7 @@ protected function setUp(): void { $this->entityClass = '\Dummy\DummyEntity'; $this->resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $this->resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $this->propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $this->propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $this->urlGeneratorProphecy = $this->prophesize(UrlGeneratorInterface::class); @@ -57,11 +59,15 @@ protected function setUp(): void public function testResourceContext() { - $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata('DummyEntity')); + $this->resourceMetadataCollectionFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadataCollection('DummyEntity', [ + (new ApiResource()) + ->withShortName('DummyEntity') + ->withOperations(new Operations(['get' => (new Get())->withShortName('DummyEntity')])), + ])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $expected = [ '@vocab' => '#', @@ -74,11 +80,15 @@ public function testResourceContext() public function testIriOnlyResourceContext() { - $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata('DummyEntity', null, null, null, null, ['normalization_context' => ['iri_only' => true]])); + $this->resourceMetadataCollectionFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadataCollection('DummyEntity', [ + (new ApiResource()) + ->withShortName('DummyEntity') + ->withOperations(new Operations(['get' => (new Get())->withShortName('DummyEntity')->withNormalizationContext(['iri_only' => true])])), + ])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $expected = [ '@vocab' => '#', @@ -93,11 +103,15 @@ public function testIriOnlyResourceContext() public function testResourceContextWithJsonldContext() { - $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata('DummyEntity')); + $this->resourceMetadataCollectionFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadataCollection('DummyEntity', [ + (new ApiResource()) + ->withShortName('DummyEntity') + ->withOperations(new Operations(['get' => (new Get())->withShortName('DummyEntity')])), + ])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@type' => '@id', '@id' => 'customId', 'foo' => 'bar'])); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $expected = [ '@vocab' => '#', @@ -114,12 +128,16 @@ public function testResourceContextWithJsonldContext() public function testGetEntryPointContext() { - $this->resourceMetadataFactoryProphecy->create('dummyPropertyA')->willReturn(new ResourceMetadata('DummyEntity')); + $this->resourceMetadataCollectionFactoryProphecy->create('dummyPropertyA')->willReturn(new ResourceMetadataCollection('DummyEntity', [ + (new ApiResource()) + ->withShortName('DummyEntity') + ->withOperations(new Operations(['get' => (new Get())->withShortName('DummyEntity')])), + ])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@type' => '@id', '@id' => 'customId', 'foo' => 'bar'])); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $expected = [ '@vocab' => '#', @@ -135,11 +153,15 @@ public function testGetEntryPointContext() public function testResourceContextWithReverse() { - $this->resourceMetadataFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadata('DummyEntity')); + $this->resourceMetadataCollectionFactoryProphecy->create($this->entityClass)->willReturn(new ResourceMetadataCollection('DummyEntity', [ + (new ApiResource()) + ->withShortName('DummyEntity') + ->withOperations(new Operations(['get' => (new Get())->withShortName('DummyEntity')])), + ])); $this->propertyNameCollectionFactoryProphecy->create($this->entityClass)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create($this->entityClass, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@reverse' => 'parent'])); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $expected = [ '@vocab' => '#', @@ -159,7 +181,7 @@ public function testAnonymousResourceContext() $this->propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create(Dummy::class, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $context = $contextBuilder->getAnonymousResourceContext($dummy); $this->assertEquals('Dummy', $context['@type']); @@ -177,7 +199,7 @@ public function testAnonymousResourceContextWithIri() $this->propertyNameCollectionFactoryProphecy->create(OutputDto::class)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create(OutputDto::class, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $expected = [ '@context' => [ @@ -198,9 +220,13 @@ public function testAnonymousResourceContextWithApiResource() $this->propertyNameCollectionFactoryProphecy->create(OutputDto::class)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create(OutputDto::class, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $this->resourceMetadataCollectionFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection('Dummy', [ + (new ApiResource()) + ->withShortName('Dummy') + ->withOperations(new Operations(['get' => (new Get())->withShortName('Dummy')])), + ])); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $expected = [ '@context' => [ @@ -221,9 +247,13 @@ public function testAnonymousResourceContextWithApiResourceHavingContext() $this->propertyNameCollectionFactoryProphecy->create(OutputDto::class)->willReturn(new PropertyNameCollection(['dummyPropertyA'])); $this->propertyMetadataFactoryProphecy->create(OutputDto::class, 'dummyPropertyA', Argument::type('array'))->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('Dummy property A')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $this->resourceMetadataCollectionFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection('Dummy', [ + (new ApiResource()) + ->withShortName('Dummy') + ->withOperations(new Operations(['get' => (new Get())->withShortName('Dummy')])), + ])); - $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); + $contextBuilder = new ContextBuilder($this->resourceNameCollectionFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->urlGeneratorProphecy->reveal()); $expected = [ '@id' => '/dummies', diff --git a/tests/JsonLd/Serializer/ItemNormalizerTest.php b/tests/JsonLd/Serializer/ItemNormalizerTest.php index 26ac57588ec..a2473ac6f07 100644 --- a/tests/JsonLd/Serializer/ItemNormalizerTest.php +++ b/tests/JsonLd/Serializer/ItemNormalizerTest.php @@ -13,16 +13,20 @@ namespace ApiPlatform\Tests\JsonLd\Serializer; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\ItemNormalizer; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Property\PropertyNameCollection; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; @@ -32,83 +36,32 @@ /** * @author Kévin Dunglas - * @group legacy */ class ItemNormalizerTest extends TestCase { use ProphecyTrait; - /** - * @group legacy - */ - public function testDontSupportDenormalization() - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); - $resourceClassResolverProphecy->getResourceClass(['dummy'], 'Dummy')->willReturn(Dummy::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['name' => 'name'])); - - $normalizer = new ItemNormalizer($resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), $contextBuilderProphecy->reveal()); - - $this->assertFalse($normalizer->supportsDenormalization('foo', ItemNormalizer::FORMAT)); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - - /** - * @group legacy - */ - public function testSupportNormalization() - { - $std = new \stdClass(); - $dummy = new Dummy(); - $dummy->setDescription('hello'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $contextBuilderProphecy = $this->prophesize(ContextBuilderInterface::class); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true)->shouldBeCalled(); - $resourceClassResolverProphecy->isResourceClass(\stdClass::class)->willReturn(false)->shouldBeCalled(); - - $normalizer = new ItemNormalizer( - $resourceMetadataFactoryProphecy->reveal(), - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $contextBuilderProphecy->reveal() - ); - - $this->assertTrue($normalizer->supportsNormalization($dummy, 'jsonld')); - $this->assertFalse($normalizer->supportsNormalization($dummy, 'xml')); - $this->assertFalse($normalizer->supportsNormalization($std, 'jsonld')); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - public function testNormalize() { $dummy = new Dummy(); $dummy->setName('hello'); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection('Dummy', [ + (new ApiResource()) + ->withShortName('Dummy') + ->withOperations(new Operations(['get' => (new Get())->withShortName('Dummy')])), + ])); $propertyNameCollection = new PropertyNameCollection(['name']); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn($propertyNameCollection); + $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->willReturn($propertyNameCollection); $propertyMetadata = (new ApiProperty())->withReadable(true); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn($propertyMetadata); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->willReturn($propertyMetadata); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1988'); + $iriConverterProphecy->getIriFromResource($dummy, UrlGeneratorInterface::ABS_PATH, null, Argument::any())->willReturn('/dummies/1988'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class); @@ -122,7 +75,7 @@ public function testNormalize() $contextBuilderProphecy->getResourceContextUri(Dummy::class)->willReturn('/contexts/Dummy'); $normalizer = new ItemNormalizer( - $resourceMetadataFactoryProphecy->reveal(), + $resourceMetadataCollectionFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), @@ -131,7 +84,6 @@ public function testNormalize() null, null, null, - [], [] ); $normalizer->setSerializer($serializerProphecy->reveal()); diff --git a/tests/JsonLd/Serializer/ObjectNormalizerTest.php b/tests/JsonLd/Serializer/ObjectNormalizerTest.php index 61fbde5b9ad..b376fa3f46a 100644 --- a/tests/JsonLd/Serializer/ObjectNormalizerTest.php +++ b/tests/JsonLd/Serializer/ObjectNormalizerTest.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Tests\JsonLd\Serializer; -use ApiPlatform\Core\Api\IriConverterInterface; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\JsonLd\AnonymousContextBuilderInterface; use ApiPlatform\JsonLd\Serializer\ObjectNormalizer; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -25,7 +25,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class ObjectNormalizerTest extends TestCase { @@ -93,7 +92,7 @@ public function testNormalizeWithOutput() $dummy->setName('hello'); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummy/1234'); + $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummy/1234'); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->willImplement(NormalizerInterface::class); @@ -123,7 +122,7 @@ public function testNormalizeWithContext() $dummy->setName('hello'); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummy/1234'); + $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummy/1234'); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->willImplement(NormalizerInterface::class); From add4789134dccb9dae2cb4dadfe12d1fb8be0ee1 Mon Sep 17 00:00:00 2001 From: Vincent Chalamon Date: Wed, 18 May 2022 13:19:05 +0200 Subject: [PATCH 25/56] test: fix JsonApi tests --- .../ConstraintViolationListNormalizer.php | 12 +- .../Serializer/EntrypointNormalizer.php | 37 +-- src/JsonApi/Serializer/ItemNormalizer.php | 7 +- src/JsonApi/Serializer/ObjectNormalizer.php | 37 +-- src/JsonLd/Serializer/ItemNormalizer.php | 2 +- src/Serializer/AbstractItemNormalizer.php | 51 ++-- src/Serializer/InputOutputMetadataTrait.php | 37 +-- src/Serializer/ItemNormalizer.php | 2 +- .../Serializer/EntrypointNormalizerTest.php | 45 ++-- .../JsonApi/Serializer/ItemNormalizerTest.php | 232 +++++------------- 10 files changed, 142 insertions(+), 320 deletions(-) diff --git a/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php b/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php index d93514f146b..33b23986158 100644 --- a/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php +++ b/src/JsonApi/Serializer/ConstraintViolationListNormalizer.php @@ -13,8 +13,6 @@ namespace ApiPlatform\JsonApi\Serializer; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -33,12 +31,9 @@ final class ConstraintViolationListNormalizer implements NormalizerInterface, Ca public const FORMAT = 'jsonapi'; private $nameConverter; - /** - * @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface - */ private $propertyMetadataFactory; - public function __construct($propertyMetadataFactory, NameConverterInterface $nameConverter = null) + public function __construct(PropertyMetadataFactoryInterface $propertyMetadataFactory, NameConverterInterface $nameConverter = null) { $this->propertyMetadataFactory = $propertyMetadataFactory; $this->nameConverter = $nameConverter; @@ -90,7 +85,7 @@ private function getSourcePointerFromViolation(ConstraintViolationInterface $vio } $class = \get_class($violation->getRoot()); - /** @var ApiProperty|PropertyMetadata */ + /** @var ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory ->create( // Im quite sure this requires some thought in case of validations over relationships @@ -102,8 +97,7 @@ private function getSourcePointerFromViolation(ConstraintViolationInterface $vio $fieldName = $this->nameConverter->normalize($fieldName, $class, self::FORMAT); } - // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : ($propertyMetadata->getBuiltinTypes()[0] ?? null); + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; if ($type && null !== $type->getClassName()) { return "data/relationships/$fieldName"; } diff --git a/src/JsonApi/Serializer/EntrypointNormalizer.php b/src/JsonApi/Serializer/EntrypointNormalizer.php index f0e2cd76ae6..69228850e0c 100644 --- a/src/JsonApi/Serializer/EntrypointNormalizer.php +++ b/src/JsonApi/Serializer/EntrypointNormalizer.php @@ -16,9 +16,6 @@ use ApiPlatform\Api\Entrypoint; use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\HttpOperation; @@ -41,19 +38,11 @@ final class EntrypointNormalizer implements NormalizerInterface, CacheableSuppor private $iriConverter; private $urlGenerator; - public function __construct($resourceMetadataFactory, $iriConverter, UrlGeneratorInterface $urlGenerator) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, IriConverterInterface $iriConverter, UrlGeneratorInterface $urlGenerator) { $this->resourceMetadataFactory = $resourceMetadataFactory; $this->iriConverter = $iriConverter; $this->urlGenerator = $urlGenerator; - - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -66,36 +55,20 @@ public function normalize($object, $format = null, array $context = []) $entrypoint = ['links' => ['self' => $this->urlGenerator->generate('api_entrypoint', [], UrlGeneratorInterface::ABS_URL)]]; foreach ($object->getResourceNameCollection() as $resourceClass) { - /** @var ResourceMetadata|ResourceMetadataCollection */ + /** @var ResourceMetadataCollection */ $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if ($resourceMetadata instanceof ResourceMetadata) { - if (!$resourceMetadata->getCollectionOperations()) { - continue; - } - - try { - $entrypoint['links'][lcfirst($resourceMetadata->getShortName())] = $this->iriConverter->getIriFromResourceClass($resourceClass, UrlGeneratorInterface::ABS_URL); - } catch (InvalidArgumentException $ex) { - // Ignore resources without GET operations - } - } - foreach ($resourceMetadata as $resource) { - foreach ($resource->getOperations() as $operationName => $operation) { + foreach ($resource->getOperations() as $operation) { if (!$operation instanceof CollectionOperationInterface || ($operation instanceof HttpOperation && $operation->getUriVariables())) { continue; } try { - if ($this->iriConverter instanceof LegacyIriConverterInterface) { - $iri = $this->iriConverter->getIriFromResourceClass($resourceClass, UrlGeneratorInterface::ABS_URL); - } else { - $iri = $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_URL, $operation); - } + $iri = $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_URL, $operation); $entrypoint['links'][lcfirst($resource->getShortName())] = $iri; - } catch (InvalidArgumentException $ex) { + } catch (InvalidArgumentException) { // Ignore resources without GET operations } } diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index 2ac2d940742..2a47e8f8753 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -17,6 +17,7 @@ use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\AbstractItemNormalizer; use ApiPlatform\Serializer\CacheKeyTrait; use ApiPlatform\Serializer\ContextTrait; @@ -48,9 +49,9 @@ final class ItemNormalizer extends AbstractItemNormalizer private $componentsCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter, $resourceMetadataFactory, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, null, $defaultContext, $resourceMetadataFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, null, $defaultContext, $resourceMetadataCollectionFactory, $resourceAccessChecker); } /** @@ -453,7 +454,7 @@ private function getIncludedNestedResources(string $relationshipName, array $con private function getResourceShortName(string $resourceClass): string { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); + $resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass); return $resourceMetadata->getOperation()->getShortName(); } diff --git a/src/JsonApi/Serializer/ObjectNormalizer.php b/src/JsonApi/Serializer/ObjectNormalizer.php index 6c7e0cf5331..ea930fc11fc 100644 --- a/src/JsonApi/Serializer/ObjectNormalizer.php +++ b/src/JsonApi/Serializer/ObjectNormalizer.php @@ -15,11 +15,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Util\ClassInfoTrait; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -35,30 +31,16 @@ final class ObjectNormalizer implements NormalizerInterface, CacheableSupportsMe public const FORMAT = 'jsonapi'; private $decorated; - /** - * @var IriConverterInterface|LegacyIriConverterInterface - */ private $iriConverter; private $resourceClassResolver; - /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface - */ private $resourceMetadataFactory; - public function __construct(NormalizerInterface $decorated, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, $resourceMetadataFactory) + public function __construct(NormalizerInterface $decorated, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) { $this->decorated = $decorated; $this->iriConverter = $iriConverter; $this->resourceClassResolver = $resourceClassResolver; $this->resourceMetadataFactory = $resourceMetadataFactory; - - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -97,8 +79,8 @@ public function normalize($object, $format = null, array $context = []) if (isset($originalResource)) { $resourceClass = $this->resourceClassResolver->getResourceClass($originalResource); $resourceData = [ - 'id' => $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($originalResource) : $this->iriConverter->getIriFromResource($originalResource), - 'type' => $this->getResourceShortName($resourceClass), + 'id' => $this->iriConverter->getIriFromResource($originalResource), + 'type' => $this->resourceMetadataFactory->create($resourceClass)->getOperation()->getShortName(), ]; } else { $resourceData = [ @@ -113,17 +95,4 @@ public function normalize($object, $format = null, array $context = []) return ['data' => $resourceData]; } - - // TODO: 3.0 remove - private function getResourceShortName(string $resourceClass): string - { - /** @var ResourceMetadata|ResourceMetadataCollection */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - - if ($resourceMetadata instanceof ResourceMetadata) { - return $resourceMetadata->getShortName(); - } - - return $resourceMetadata->getOperation()->getShortName(); - } } diff --git a/src/JsonLd/Serializer/ItemNormalizer.php b/src/JsonLd/Serializer/ItemNormalizer.php index 89c3b41e556..9ef170b36df 100644 --- a/src/JsonLd/Serializer/ItemNormalizer.php +++ b/src/JsonLd/Serializer/ItemNormalizer.php @@ -96,7 +96,7 @@ public function normalize($object, $format = null, array $context = []) return $data; } - $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation(); + $operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); $types = $operation instanceof HttpOperation ? $operation->getTypes() : null; if (null === $types) { $types = [$operation->getShortName()]; diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index e083e382033..dbcf1ddd4a3 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -18,6 +18,8 @@ use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\InvalidValueException; use ApiPlatform\Exception\ItemNotFoundException; +use ApiPlatform\Exception\OperationNotFoundException; +use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; @@ -66,7 +68,7 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer protected $propertyAccessor; protected $localCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { if (!isset($defaultContext['circular_reference_handler'])) { $defaultContext['circular_reference_handler'] = function ($object) { @@ -84,7 +86,7 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName $this->iriConverter = $iriConverter; $this->resourceClassResolver = $resourceClassResolver; $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); - $this->resourceMetadataFactory = $resourceMetadataFactory; + $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; $this->resourceAccessChecker = $resourceAccessChecker; } @@ -554,10 +556,13 @@ protected function getFactoryOptions(array $context): array $options['serializer_groups'] = (array) $context[self::GROUPS]; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $operation = $context['operation'] ?? $this->resourceMetadataFactory->create($context['resource_class'])->getOperation($context['operation_name'] ?? null); - $options['normalization_groups'] = $operation->getNormalizationContext()['groups'] ?? null; - $options['denormalization_groups'] = $operation->getDenormalizationContext()['groups'] ?? null; + if (null !== $this->resourceMetadataCollectionFactory) { + try { + $operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($context['resource_class'])->getOperation($context['operation_name'] ?? null); + $options['normalization_groups'] = $operation->getNormalizationContext()['groups'] ?? null; + $options['denormalization_groups'] = $operation->getDenormalizationContext()['groups'] ?? null; + } catch (OperationNotFoundException|ResourceClassNotFoundException) { + } } if (isset($context['operation_name'])) { @@ -575,18 +580,6 @@ protected function getFactoryOptions(array $context): array return $options; } - /** - * Creates the context to use when serializing a relation. - * - * @deprecated since version 2.1, to be removed in 3.0. - */ - protected function createRelationSerializationContext(string $resourceClass, array $context): array - { - @trigger_error(sprintf('The method %s() is deprecated since 2.1 and will be removed in 3.0.', __METHOD__), \E_USER_DEPRECATED); - - return $context; - } - /** * {@inheritdoc} * @@ -605,7 +598,6 @@ protected function getAttributeValue($object, $attribute, $format = null, array $attributeValue = $this->propertyAccessor->getValue($object, $attribute); } catch (NoSuchPropertyException $e) { throw $e; - $attributeValue = null; } if ($context['api_denormalize'] ?? false) { @@ -628,8 +620,11 @@ protected function getAttributeValue($object, $attribute, $format = null, array $resourceClass = $this->resourceClassResolver->getResourceClass($attributeValue, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $childContext['operation'] = $this->resourceMetadataFactory->create($resourceClass)->getOperation(); + if (null !== $this->resourceMetadataCollectionFactory) { + try { + $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); + } catch (OperationNotFoundException|ResourceClassNotFoundException) { + } } unset($childContext['iri'], $childContext['uri_variables']); @@ -648,8 +643,11 @@ protected function getAttributeValue($object, $attribute, $format = null, array $resourceClass = $this->resourceClassResolver->getResourceClass($attributeValue, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $childContext['operation'] = $this->resourceMetadataFactory->create($resourceClass)->getOperation(); + if (null !== $this->resourceMetadataCollectionFactory) { + try { + $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); + } catch (OperationNotFoundException|ResourceClassNotFoundException) { + } } unset($childContext['iri'], $childContext['uri_variables']); @@ -783,8 +781,11 @@ private function createAttributeValue($attribute, $value, $format = null, array $resourceClass = $this->resourceClassResolver->getResourceClass(null, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $childContext['operation'] = $this->resourceMetadataFactory->create($resourceClass)->getOperation(); + if (null !== $this->resourceMetadataCollectionFactory) { + try { + $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); + } catch (OperationNotFoundException|ResourceClassNotFoundException) { + } } return $this->denormalizeRelation($attribute, $propertyMetadata, $resourceClass, $value, $format, $childContext); diff --git a/src/Serializer/InputOutputMetadataTrait.php b/src/Serializer/InputOutputMetadataTrait.php index 8c7758053cf..1f4b45787cf 100644 --- a/src/Serializer/InputOutputMetadataTrait.php +++ b/src/Serializer/InputOutputMetadataTrait.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Serializer; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -21,14 +20,14 @@ trait InputOutputMetadataTrait { /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface|null + * @var ResourceMetadataCollectionFactoryInterface|null */ - protected $resourceMetadataFactory; + protected $resourceMetadataCollectionFactory; protected function getInputClass(string $class, array $context = []): ?string { - if (!$this->resourceMetadataFactory || !$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - return $this->getInputOutputMetadata($class, 'input', $context); + if (!$this->resourceMetadataCollectionFactory) { + return $context['input']['class'] ?? null; } if (null !== ($context['input']['class'] ?? null)) { @@ -38,8 +37,8 @@ protected function getInputClass(string $class, array $context = []): ?string $operation = $context['operation'] ?? null; if (!$operation) { try { - $operation = $this->resourceMetadataFactory->create($class)->getOperation($context['operation_name'] ?? null); - } catch (OperationNotFoundException $e) { + $operation = $this->resourceMetadataCollectionFactory->create($class)->getOperation($context['operation_name'] ?? null); + } catch (OperationNotFoundException|ResourceClassNotFoundException $e) { return null; } } @@ -49,8 +48,8 @@ protected function getInputClass(string $class, array $context = []): ?string protected function getOutputClass(string $class, array $context = []): ?string { - if (!$this->resourceMetadataFactory || !$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - return $this->getInputOutputMetadata($class, 'output', $context); + if (!$this->resourceMetadataCollectionFactory) { + return $context['output']['class'] ?? null; } if (null !== ($context['output']['class'] ?? null)) { @@ -60,28 +59,12 @@ protected function getOutputClass(string $class, array $context = []): ?string $operation = $context['operation'] ?? null; if (null === $operation) { try { - $operation = $this->resourceMetadataFactory->create($class)->getOperation($context['operation_name'] ?? null); - } catch (OperationNotFoundException $e) { + $operation = $this->resourceMetadataCollectionFactory->create($class)->getOperation($context['operation_name'] ?? null); + } catch (OperationNotFoundException|ResourceClassNotFoundException $e) { return null; } } return $operation ? $operation->getOutput()['class'] ?? null : null; } - - // TODO: remove in 3.0 - private function getInputOutputMetadata(string $class, string $inputOrOutput, array $context) - { - if (null === $this->resourceMetadataFactory || null !== ($context[$inputOrOutput]['class'] ?? null)) { - return $context[$inputOrOutput]['class'] ?? null; - } - - try { - $metadata = $this->resourceMetadataFactory->create($class); - } catch (ResourceClassNotFoundException $e) { - return null; - } - - return $metadata->getAttribute($inputOrOutput)['class'] ?? null; - } } diff --git a/src/Serializer/ItemNormalizer.php b/src/Serializer/ItemNormalizer.php index 80390d98afd..9b20c6ffada 100644 --- a/src/Serializer/ItemNormalizer.php +++ b/src/Serializer/ItemNormalizer.php @@ -77,7 +77,7 @@ private function updateObjectToPopulate(array $data, array &$context): void try { $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri((string) $data['id'], $context + ['fetch_data' => true]); } catch (InvalidArgumentException $e) { - $operation = $this->resourceMetadataFactory->create($context['resource_class'])->getOperation(); + $operation = $this->resourceMetadataCollectionFactory->create($context['resource_class'])->getOperation(); // todo: we could guess uri variables with the operation and the data instead of hardcoding id $iri = $this->iriConverter->getIriFromResource($context['resource_class'], UrlGeneratorInterface::ABS_PATH, $operation, ['uri_variables' => ['id' => $data['id']]]); diff --git a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php index 17e65def0f6..6f3b32f1c57 100644 --- a/tests/JsonApi/Serializer/EntrypointNormalizerTest.php +++ b/tests/JsonApi/Serializer/EntrypointNormalizerTest.php @@ -14,22 +14,27 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; use ApiPlatform\Api\Entrypoint; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\JsonApi\Serializer\EntrypointNormalizer; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Operation; +use ApiPlatform\Metadata\Operations; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; +use Prophecy\Argument; /** * @author Amrouche Hamza - * @group legacy */ class EntrypointNormalizerTest extends TestCase { @@ -40,7 +45,7 @@ public function testSupportNormalization() $collection = new ResourceNameCollection(); $entrypoint = new Entrypoint($collection); - $factoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $factoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $urlGeneratorProphecy = $this->prophesize(UrlGeneratorInterface::class); @@ -56,15 +61,27 @@ public function testNormalize() { $collection = new ResourceNameCollection([Dummy::class, RelatedDummy::class, DummyCar::class]); $entrypoint = new Entrypoint($collection); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', null, null, null, ['get']))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadata('RelatedDummy', null, null, ['get'], null))->shouldBeCalled(); - $resourceMetadataFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadata('DummyCar', null, null, null, ['post']))->shouldBeCalled(); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection('Dummy', [ + (new ApiResource())->withShortName('Dummy')->withOperations(new Operations([ + 'get' => (new GetCollection())->withShortName('Dummy'), + ])), + ]))->shouldBeCalled(); + $resourceMetadataCollectionFactoryProphecy->create(RelatedDummy::class)->willReturn(new ResourceMetadataCollection('RelatedDummy', [ + (new ApiResource())->withShortName('RelatedDummy')->withOperations(new Operations([ + 'get' => (new Get())->withShortName('RelatedDummy'), + ])), + ]))->shouldBeCalled(); + $resourceMetadataCollectionFactoryProphecy->create(DummyCar::class)->willReturn(new ResourceMetadataCollection('DummyCar', [ + (new ApiResource())->withShortName('DummyCar')->withOperations(new Operations([ + 'post' => (new Post())->withShortName('DummyCar'), + ])), + ]))->shouldBeCalled(); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromResourceClass(Dummy::class, UrlGeneratorInterface::ABS_URL)->willReturn('http://localhost/api/dummies')->shouldBeCalled(); - $iriConverterProphecy->getIriFromResourceClass(RelatedDummy::class, UrlGeneratorInterface::ABS_URL)->shouldNotBeCalled(); - $iriConverterProphecy->getIriFromResourceClass(DummyCar::class, UrlGeneratorInterface::ABS_URL)->willThrow(new InvalidArgumentException())->shouldBeCalled(); + $iriConverterProphecy->getIriFromResource(Dummy::class, UrlGeneratorInterface::ABS_URL, Argument::type(Operation::class))->willReturn('http://localhost/api/dummies')->shouldBeCalled(); + $iriConverterProphecy->getIriFromResource(RelatedDummy::class, UrlGeneratorInterface::ABS_URL, Argument::type(Operation::class))->shouldNotBeCalled(); + $iriConverterProphecy->getIriFromResource(DummyCar::class, UrlGeneratorInterface::ABS_URL, Argument::type(Operation::class))->shouldNotBeCalled(); $urlGeneratorProphecy = $this->prophesize(UrlGeneratorInterface::class); $urlGeneratorProphecy->generate('api_entrypoint', [], UrlGeneratorInterface::ABS_URL)->willReturn('http://localhost/api')->shouldBeCalled(); @@ -76,7 +93,7 @@ public function testNormalize() 'dummy' => 'http://localhost/api/dummies', ], ], - (new EntrypointNormalizer($resourceMetadataFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $urlGeneratorProphecy->reveal()))->normalize($entrypoint, EntrypointNormalizer::FORMAT) + (new EntrypointNormalizer($resourceMetadataCollectionFactoryProphecy->reveal(), $iriConverterProphecy->reveal(), $urlGeneratorProphecy->reveal()))->normalize($entrypoint, EntrypointNormalizer::FORMAT) ); } } diff --git a/tests/JsonApi/Serializer/ItemNormalizerTest.php b/tests/JsonApi/Serializer/ItemNormalizerTest.php index 6df819cc6c6..a2b335cf66e 100644 --- a/tests/JsonApi/Serializer/ItemNormalizerTest.php +++ b/tests/JsonApi/Serializer/ItemNormalizerTest.php @@ -13,20 +13,21 @@ namespace ApiPlatform\Tests\JsonApi\Serializer; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; -use ApiPlatform\Core\Api\IriConverterInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\JsonApi\Serializer\ItemNormalizer; use ApiPlatform\JsonApi\Serializer\ReservedAttributeNameConverter; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Property\PropertyNameCollection; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\CircularReference; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; @@ -44,63 +45,11 @@ /** * @author Amrouche Hamza - * @group legacy */ class ItemNormalizerTest extends TestCase { use ProphecyTrait; - /** - * @group legacy - */ - public function testSupportDenormalization() - { - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true)->shouldBeCalled(); - $resourceClassResolverProphecy->isResourceClass(\stdClass::class)->willReturn(false)->shouldBeCalled(); - - $normalizer = new ItemNormalizer( - $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), - $this->prophesize(IriConverterInterface::class)->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal() - ); - - $this->assertTrue($normalizer->supportsDenormalization(null, Dummy::class, ItemNormalizer::FORMAT)); - $this->assertFalse($normalizer->supportsDenormalization(null, \stdClass::class, ItemNormalizer::FORMAT)); - $this->assertTrue($normalizer->hasCacheableSupportsMethod()); - } - - /** - * @group legacy - */ - public function testSupportNormalization() - { - $std = new \stdClass(); - $dummy = new Dummy(); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true)->shouldBeCalled(); - $resourceClassResolverProphecy->isResourceClass(\stdClass::class)->willReturn(false)->shouldBeCalled(); - - $normalizer = new ItemNormalizer( - $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), - $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), - $this->prophesize(IriConverterInterface::class)->reveal(), - $resourceClassResolverProphecy->reveal(), - null, - null, - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal() - ); - - $this->assertTrue($normalizer->supportsNormalization($dummy, ItemNormalizer::FORMAT)); - $this->assertFalse($normalizer->supportsNormalization($dummy, 'xml')); - $this->assertFalse($normalizer->supportsNormalization($std, ItemNormalizer::FORMAT)); - } - public function testNormalize(): void { $dummy = new Dummy(); @@ -108,82 +57,15 @@ public function testNormalize(): void $dummy->setName('hello'); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['id', 'name', '\bad_property'])); + $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->willReturn(new PropertyNameCollection(['id', 'name', '\bad_property'])); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn((new ApiProperty())->withReadable(true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', [])->willReturn((new ApiProperty())->withReadable(true)->withIdentifier(true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, '\bad_property', [])->willReturn((new ApiProperty())->withReadable(true)); - - $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/10'); - - $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); - $resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class); - $resourceClassResolverProphecy->getResourceClass($dummy, Dummy::class)->willReturn(Dummy::class); - $resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true); - - $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - $propertyAccessorProphecy->getValue($dummy, 'id')->willReturn(10); - $propertyAccessorProphecy->getValue($dummy, 'name')->willReturn('hello'); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', 'A dummy', '/dummy', null, null, ['id', 'name'])); - - $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(NormalizerInterface::class); - $serializerProphecy->normalize('hello', ItemNormalizer::FORMAT, Argument::type('array'))->willReturn('hello'); - $serializerProphecy->normalize(10, ItemNormalizer::FORMAT, Argument::type('array'))->willReturn(10); - $serializerProphecy->normalize(null, ItemNormalizer::FORMAT, Argument::type('array'))->willReturn(null); - - $normalizer = new ItemNormalizer( - $propertyNameCollectionFactoryProphecy->reveal(), - $propertyMetadataFactoryProphecy->reveal(), - $iriConverterProphecy->reveal(), - $resourceClassResolverProphecy->reveal(), - $propertyAccessorProphecy->reveal(), - new ReservedAttributeNameConverter(), - $resourceMetadataFactoryProphecy->reveal(), - [], - [] - ); - - $normalizer->setSerializer($serializerProphecy->reveal()); - - $expected = [ - 'data' => [ - 'type' => 'Dummy', - 'id' => '/dummies/10', - 'attributes' => [ - '_id' => 10, - 'name' => 'hello', - ], - ], - ]; - - $this->assertEquals($expected, $normalizer->normalize($dummy, ItemNormalizer::FORMAT)); - } - - /** - * @group legacy - */ - public function testNormalizeChildInheritedProperty(): void - { - $dummy = new Dummy(); - $dummy->setId(10); - $dummy->setName('hello'); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['id', 'name', 'inherited', '\bad_property'])); - - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn(new PropertyMetadata(null, null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', [])->willReturn(new PropertyMetadata(null, null, true, null, null, null, null, true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'inherited', [])->willReturn(new PropertyMetadata(null, null, true, null, null, null, null, null, null, 'foo')); - $propertyMetadataFactoryProphecy->create(Dummy::class, '\bad_property', [])->willReturn(new PropertyMetadata(null, null, true)); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->willReturn((new ApiProperty())->withReadable(true)); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'id', Argument::any())->willReturn((new ApiProperty())->withReadable(true)->withIdentifier(true)); + $propertyMetadataFactoryProphecy->create(Dummy::class, '\bad_property', Argument::any())->willReturn((new ApiProperty())->withReadable(true)); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/10'); + $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummies/10'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class); @@ -193,10 +75,15 @@ public function testNormalizeChildInheritedProperty(): void $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->getValue($dummy, 'id')->willReturn(10); $propertyAccessorProphecy->getValue($dummy, 'name')->willReturn('hello'); - $propertyAccessorProphecy->getValue($dummy, 'inherited')->willThrow(new NoSuchPropertyException()); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy', 'A dummy', '/dummy', null, null, ['id', 'name'])); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection('Dummy', [ + (new ApiResource()) + ->withShortName('Dummy') + ->withDescription('A dummy') + ->withUriTemplate('/dummy') + ->withOperations(new Operations(['get' => (new Get())->withShortName('Dummy')])), + ])); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->willImplement(NormalizerInterface::class); @@ -211,8 +98,7 @@ public function testNormalizeChildInheritedProperty(): void $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), - $resourceMetadataFactoryProphecy->reveal(), - [], + $resourceMetadataCollectionFactoryProphecy->reveal(), [] ); @@ -225,7 +111,6 @@ public function testNormalizeChildInheritedProperty(): void 'attributes' => [ '_id' => 10, 'name' => 'hello', - 'inherited' => null, ], ], ]; @@ -240,14 +125,14 @@ public function testNormalizeCircularReference() $circularReferenceEntity->parent = $circularReferenceEntity; $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($circularReferenceEntity)->willReturn('/circular_references/1'); + $iriConverterProphecy->getIriFromResource($circularReferenceEntity)->willReturn('/circular_references/1'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($circularReferenceEntity, null)->willReturn(CircularReference::class); $resourceClassResolverProphecy->getResourceClass($circularReferenceEntity, CircularReference::class)->willReturn(CircularReference::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(CircularReference::class)->willReturn(new ResourceMetadata('CircularReference')); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy->create(CircularReference::class)->willReturn(new ResourceMetadataCollection('CircularReference')); $normalizer = new ItemNormalizer( $this->prophesize(PropertyNameCollectionFactoryInterface::class)->reveal(), @@ -256,8 +141,7 @@ public function testNormalizeCircularReference() $resourceClassResolverProphecy->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), new ReservedAttributeNameConverter(), - $resourceMetadataFactoryProphecy->reveal(), - [], + $resourceMetadataCollectionFactoryProphecy->reveal(), [] ); @@ -290,13 +174,13 @@ public function testNormalizeNonExistentProperty() $dummy->setId(1); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['bar'])); + $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->willReturn(new PropertyNameCollection(['bar'])); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'bar', [])->willReturn((new ApiProperty())->withReadable(true)); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'bar', Argument::any())->willReturn((new ApiProperty())->withReadable(true)); $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getIriFromItem($dummy)->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($dummy)->willReturn('/dummies/1'); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->getResourceClass($dummy, null)->willReturn(Dummy::class); @@ -306,8 +190,12 @@ public function testNormalizeNonExistentProperty() $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->getValue($dummy, 'bar')->willThrow(new NoSuchPropertyException()); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('Dummy')); + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection('Dummy', [ + (new ApiResource()) + ->withShortName('Dummy') + ->withOperations(new Operations(['get' => (new Get())->withShortName('Dummy')])), + ])); $normalizer = new ItemNormalizer( $propertyNameCollectionFactoryProphecy->reveal(), @@ -316,8 +204,7 @@ public function testNormalizeNonExistentProperty() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), - $resourceMetadataFactoryProphecy->reveal(), - [], + $resourceMetadataCollectionFactoryProphecy->reveal(), [] ); @@ -358,24 +245,24 @@ public function testDenormalize() $relatedDummy2->setId(2); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['name', 'ghost', 'relatedDummy', 'relatedDummies'])); + $propertyNameCollectionFactoryProphecy->create(Dummy::class, Argument::any())->willReturn(new PropertyNameCollection(['name', 'ghost', 'relatedDummy', 'relatedDummies'])); $relatedDummyType = new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class); $relatedDummiesType = new Type(Type::BUILTIN_TYPE_OBJECT, false, ArrayCollection::class, true, new Type(Type::BUILTIN_TYPE_INT), $relatedDummyType); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', [])->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(false)->withWritable(true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'ghost', [])->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(false)->withWritable(true)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', [])->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummyType])->withReadable(false)->withWritable(true)->withReadableLink(false)->withWritableLink(false)); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(false)->withWritable(true)->withReadableLink(false)->withWritableLink(false)); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'name', Argument::any())->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(false)->withWritable(true)); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'ghost', Argument::any())->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('')->withReadable(false)->withWritable(true)); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummy', Argument::any())->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummyType])->withReadable(false)->withWritable(true)->withReadableLink(false)->withWritableLink(false)); + $propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', Argument::any())->willReturn((new ApiProperty())->withBuiltinTypes([$relatedDummiesType])->withReadable(false)->withWritable(true)->withReadableLink(false)->withWritableLink(false)); $getItemFromIriSecondArgCallback = function ($arg) { return \is_array($arg) && isset($arg['fetch_data']) && true === $arg['fetch_data']; }; $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $iriConverterProphecy->getItemFromIri('/related_dummies/1', Argument::that($getItemFromIriSecondArgCallback))->willReturn($relatedDummy1); - $iriConverterProphecy->getItemFromIri('/related_dummies/2', Argument::that($getItemFromIriSecondArgCallback))->willReturn($relatedDummy2); + $iriConverterProphecy->getResourceFromIri('/related_dummies/1', Argument::that($getItemFromIriSecondArgCallback))->willReturn($relatedDummy1); + $iriConverterProphecy->getResourceFromIri('/related_dummies/2', Argument::that($getItemFromIriSecondArgCallback))->willReturn($relatedDummy2); $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); $propertyAccessorProphecy->setValue(Argument::type(Dummy::class), 'name', 'foo')->will(function () {}); @@ -392,8 +279,9 @@ public function testDenormalize() $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->willImplement(NormalizerInterface::class); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); + $resourceMetadataCollectionFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactory->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); + $resourceMetadataCollectionFactory->create(RelatedDummy::class)->willThrow(ResourceClassNotFoundException::class); $normalizer = new ItemNormalizer( $propertyNameCollectionFactoryProphecy->reveal(), @@ -402,8 +290,7 @@ public function testDenormalize() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), - $resourceMetadataFactory->reveal(), - [], + $resourceMetadataCollectionFactory->reveal(), [] ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -423,8 +310,7 @@ public function testDenormalizeUpdateOperationNotAllowed() $this->prophesize(ResourceClassResolverInterface::class)->reveal(), null, null, - $this->prophesize(ResourceMetadataFactoryInterface::class)->reveal(), - [], + $this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(), [] ); @@ -480,8 +366,8 @@ public function testDenormalizeCollectionIsNotArray() $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); + $resourceMetadataCollectionFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactory->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); $normalizer = new ItemNormalizer( $propertyNameCollectionFactoryProphecy->reveal(), @@ -490,8 +376,7 @@ public function testDenormalizeCollectionIsNotArray() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), - $resourceMetadataFactory->reveal(), - [], + $resourceMetadataCollectionFactory->reveal(), [] ); @@ -538,8 +423,8 @@ public function testDenormalizeCollectionWithInvalidKey() $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); + $resourceMetadataCollectionFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactory->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); $normalizer = new ItemNormalizer( $propertyNameCollectionFactoryProphecy->reveal(), @@ -548,8 +433,7 @@ public function testDenormalizeCollectionWithInvalidKey() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), - $resourceMetadataFactory->reveal(), - [], + $resourceMetadataCollectionFactory->reveal(), [] ); @@ -591,8 +475,9 @@ public function testDenormalizeRelationIsNotResourceLinkage() $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); + $resourceMetadataCollectionFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactory->create(Dummy::class)->willThrow(ResourceClassNotFoundException::class); + $resourceMetadataCollectionFactory->create(RelatedDummy::class)->willThrow(ResourceClassNotFoundException::class); $normalizer = new ItemNormalizer( $propertyNameCollectionFactoryProphecy->reveal(), @@ -601,8 +486,7 @@ public function testDenormalizeRelationIsNotResourceLinkage() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), - $resourceMetadataFactory->reveal(), - [], + $resourceMetadataCollectionFactory->reveal(), [] ); From 8bc9450efe7622642412b1613220ee4aaa56c894 Mon Sep 17 00:00:00 2001 From: Vincent Chalamon Date: Wed, 18 May 2022 13:37:36 +0200 Subject: [PATCH 26/56] feat: revamp ExceptionAction --- src/Action/ExceptionAction.php | 43 ++++++++------------- src/Symfony/Bundle/Resources/config/api.xml | 2 +- src/Util/OperationRequestInitiatorTrait.php | 1 - 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/Action/ExceptionAction.php b/src/Action/ExceptionAction.php index ac9d4106fc3..433fbcb0cbf 100644 --- a/src/Action/ExceptionAction.php +++ b/src/Action/ExceptionAction.php @@ -13,7 +13,8 @@ namespace ApiPlatform\Action; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\ErrorFormatGuesser; use ApiPlatform\Util\OperationRequestInitiatorTrait; @@ -37,28 +38,18 @@ final class ExceptionAction private $serializer; private $errorFormats; private $exceptionToStatus; - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface|null - */ - private $resourceMetadataFactory; + private $resourceMetadataCollectionFactory; /** - * @param array $errorFormats A list of enabled error formats - * @param array $exceptionToStatus A list of exceptions mapped to their HTTP status code - * @param mixed|null $resourceMetadataFactory + * @param array $errorFormats A list of enabled error formats + * @param array $exceptionToStatus A list of exceptions mapped to their HTTP status code */ - public function __construct(SerializerInterface $serializer, array $errorFormats, array $exceptionToStatus = [], $resourceMetadataFactory = null) + public function __construct(SerializerInterface $serializer, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, array $errorFormats, array $exceptionToStatus = []) { $this->serializer = $serializer; $this->errorFormats = $errorFormats; $this->exceptionToStatus = $exceptionToStatus; - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (null !== $resourceMetadataFactory && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } else { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } + $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; } /** @@ -98,21 +89,19 @@ private function getOperationExceptionToStatus(Request $request): array { $attributes = RequestAttributesExtractor::extractAttributes($request); - if ([] === $attributes || null === $this->resourceMetadataFactory) { + if ([] === $attributes) { return []; } - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - $operationExceptionToStatus = $resourceMetadata->getOperationAttribute($attributes, 'exception_to_status', [], false); - $resourceExceptionToStatus = $resourceMetadata->getAttribute('exception_to_status', []); - - if (!\is_array($operationExceptionToStatus) || !\is_array($resourceExceptionToStatus)) { - throw new \LogicException('"exception_to_status" attribute should be an array.'); + $resourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($attributes['resource_class']); + /** @var HttpOperation $operation */ + $operation = $resourceMetadataCollection->getOperation($attributes['operation_name'] ?? null); + $exceptionToStatus = $operation->getExceptionToStatus() ?: []; + foreach ($resourceMetadataCollection as $resourceMetadata) { + /** @var ApiResource $resourceMetadata */ + $exceptionToStatus = array_merge($exceptionToStatus, $resourceMetadata->getExceptionToStatus() ?: []); } - return array_merge( - $resourceExceptionToStatus, - $operationExceptionToStatus - ); + return $exceptionToStatus; } } diff --git a/src/Symfony/Bundle/Resources/config/api.xml b/src/Symfony/Bundle/Resources/config/api.xml index def9586dbe3..52f8d28ecdf 100644 --- a/src/Symfony/Bundle/Resources/config/api.xml +++ b/src/Symfony/Bundle/Resources/config/api.xml @@ -112,9 +112,9 @@ + %api_platform.error_formats% %api_platform.exception_to_status% - diff --git a/src/Util/OperationRequestInitiatorTrait.php b/src/Util/OperationRequestInitiatorTrait.php index ae1f4537e11..5360ef38d41 100644 --- a/src/Util/OperationRequestInitiatorTrait.php +++ b/src/Util/OperationRequestInitiatorTrait.php @@ -44,7 +44,6 @@ private function initializeOperation(Request $request): ?HttpOperation /** @var HttpOperation $operation */ $operation = $this->resourceMetadataCollectionFactory->create($request->attributes->get('_api_resource_class'))->getOperation($operationName); $request->attributes->set('_api_operation', $operation); - $request->attributes->set('_api_operation_name', $operationName); return $operation; } From 7df03116220667935168fffba9bf1abdd9af15b9 Mon Sep 17 00:00:00 2001 From: Vincent Chalamon Date: Wed, 18 May 2022 13:42:58 +0200 Subject: [PATCH 27/56] chore: remove src/Core paths from phpstan --- phpstan.neon.dist | 238 ---------------------------------------------- 1 file changed, 238 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 12d2b5e1783..799cd8d7b21 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -16,233 +16,10 @@ parameters: - src/Symfony/Bundle/Test/Constraint/ArraySubset.php - tests/Fixtures/app/AppKernel.php excludePaths: - - src/Core/Bridge/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php - # Class ... extends final class cannot be ignored... - - src/Core/Action/EntrypointAction.php - - src/Core/Action/ExceptionAction.php - - src/Core/Action/NotFoundAction.php - - src/Core/Action/PlaceholderAction.php - - src/Core/Api/Entrypoint.php - - src/Core/Api/FormatMatcher.php - - src/Core/Api/ResourceClassResolver.php - - src/Core/Bridge/Doctrine/EventListener/PurgeHttpCacheListener.php - - src/Core/Bridge/Doctrine/EventListener/WriteListener.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Extension/PaginationExtension.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterExtension.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Extension/OrderExtension.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Extension/FilterEagerLoadingExtension.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Filter/AbstractFilter.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Filter/BooleanFilter.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Filter/ExistsFilter.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Filter/NumericFilter.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Filter/OrderFilter.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Filter/RangeFilter.php - - src/Core/Bridge/Doctrine/MongoDbOdm/Paginator.php - - src/Core/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractor.php - - src/Core/Bridge/Doctrine/Orm/Extension/EagerLoadingExtension.php - - src/Core/Bridge/Doctrine/Orm/Extension/FilterEagerLoadingExtension.php - - src/Core/Bridge/Doctrine/Orm/Extension/FilterExtension.php - - src/Core/Bridge/Doctrine/Orm/Extension/OrderExtension.php - - src/Core/Bridge/Doctrine/Orm/Extension/PaginationExtension.php - - src/Core/Bridge/Doctrine/Orm/Filter/AbstractFilter.php - - src/Core/Bridge/Doctrine/Orm/Filter/BooleanFilter.php - - src/Core/Bridge/Doctrine/Orm/Filter/DateFilter.php - - src/Core/Bridge/Doctrine/Orm/Filter/ExistsFilter.php - - src/Core/Bridge/Doctrine/Orm/Filter/NumericFilter.php - - src/Core/Bridge/Doctrine/Orm/Filter/OrderFilter.php - - src/Core/Bridge/Doctrine/Orm/Filter/RangeFilter.php - - src/Core/Bridge/Doctrine/Orm/Paginator.php - - src/Core/Bridge/Doctrine/Orm/Util/QueryBuilderHelper.php - - src/Core/Bridge/Doctrine/Orm/Util/QueryChecker.php - - src/Core/Bridge/Doctrine/Orm/Util/QueryJoinParser.php - - src/Core/Bridge/Doctrine/Orm/Util/QueryNameGenerator.php - - src/Core/Bridge/Elasticsearch/DataProvider/Extension/AbstractFilterExtension.php - - src/Core/Bridge/Elasticsearch/DataProvider/Extension/ConstantScoreFilterExtension.php - - src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortExtension.php - - src/Core/Bridge/Elasticsearch/DataProvider/Extension/SortFilterExtension.php - - src/Core/Bridge/Elasticsearch/DataProvider/Paginator.php - - src/Core/Bridge/Elasticsearch/Exception/IndexNotFoundException.php - - src/Core/Bridge/Elasticsearch/Exception/NonUniqueIdentifierException.php - - src/Core/Bridge/Elasticsearch/Metadata/Document/DocumentMetadata.php - - src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/AttributeDocumentMetadataFactory.php - - src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CachedDocumentMetadataFactory.php - - src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/CatDocumentMetadataFactory.php - - src/Core/Bridge/Elasticsearch/Metadata/Document/Factory/ConfiguredDocumentMetadataFactory.php - - src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php - - src/Core/Bridge/Elasticsearch/Serializer/ItemNormalizer.php - - src/Core/Bridge/Elasticsearch/Serializer/NameConverter/InnerFieldsNameConverter.php - - src/Core/Bridge/RamseyUuid/Serializer/UuidDenormalizer.php - - src/Core/Bridge/Symfony/Bundle/ApiPlatformBundle.php - - src/Core/Bridge/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolver.php - - src/Core/Bridge/Symfony/Bundle/Command/OpenApiCommand.php - - src/Core/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/AuthenticatorManagerPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DataProviderPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/FilterPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/ElasticsearchClientPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlQueryResolverPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlTypePass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/GraphQlMutationResolverPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/MetadataAwareNameConverterPass.php - - src/Core/Bridge/Symfony/Bundle/DependencyInjection/Compiler/TestClientPass.php - - src/Core/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php - - src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php - - src/Core/Bridge/Symfony/Bundle/SwaggerUi/SwaggerUiContext.php - - src/Core/Bridge/Symfony/Bundle/Test/Client.php - - src/Core/Bridge/Symfony/Bundle/Test/Response.php - - src/Core/Bridge/Symfony/Identifier/Normalizer/UuidNormalizer.php - - src/Core/Bridge/Symfony/Messenger/ContextStamp.php - - src/Core/Bridge/Symfony/Messenger/RemoveStamp.php - - src/Core/Bridge/Symfony/PropertyInfo/Metadata/Property/PropertyInfoPropertyNameCollectionFactory.php - - src/Core/Bridge/Symfony/Routing/ApiLoader.php - - src/Core/Bridge/Symfony/Routing/Router.php - - src/Core/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php - - src/Core/Bridge/Symfony/Validator/Exception/ValidationException.php - - src/Core/Bridge/Symfony/Validator/Validator.php - - src/Core/DataProvider/ArrayPaginator.php - - src/Core/DataProvider/PaginationOptions.php - - src/Core/DataProvider/TraversablePaginator.php - - src/Core/Documentation/Action/DocumentationAction.php - - src/Core/Documentation/Documentation.php - - src/Core/EventListener/AddFormatListener.php - - src/Core/EventListener/DeserializeListener.php - - src/Core/EventListener/EventPriorities.php - - src/Core/EventListener/ExceptionListener.php - - src/Core/EventListener/QueryParameterValidateListener.php - - src/Core/EventListener/RespondListener.php - - src/Core/EventListener/SerializeListener.php - - src/Core/Exception/FilterValidationException.php - - src/Core/Exception/InvalidIdentifierException.php - - src/Core/Filter/Validator/ArrayItems.php - - src/Core/Filter/Validator/Bounds.php - - src/Core/Filter/Validator/Enum.php - - src/Core/Filter/Validator/Length.php - - src/Core/Filter/Validator/MultipleOf.php - - src/Core/Filter/Validator/Pattern.php - - src/Core/Filter/Validator/Required.php - - src/Core/GraphQl/Action/EntrypointAction.php - - src/Core/GraphQl/Action/GraphQlPlaygroundAction.php - - src/Core/GraphQl/Action/GraphiQlAction.php - - src/Core/GraphQl/Error/ErrorHandler.php - - src/Core/GraphQl/Executor.php - - src/Core/GraphQl/Type/Definition/IterableType.php - - src/Core/GraphQl/Type/Definition/UploadType.php - - src/Core/GraphQl/Type/TypeNotFoundException.php - - src/Core/GraphQl/Type/TypesContainer.php - - src/Core/GraphQl/Type/TypesFactory.php - - src/Core/Hal/JsonSchema/SchemaFactory.php - - src/Core/Hal/Serializer/CollectionNormalizer.php - - src/Core/Hal/Serializer/EntrypointNormalizer.php - - src/Core/Hal/Serializer/ItemNormalizer.php - - src/Core/Hal/Serializer/ObjectNormalizer.php - - src/Core/HttpCache/EventListener/AddHeadersListener.php - - src/Core/HttpCache/EventListener/AddTagsListener.php - - src/Core/HttpCache/VarnishPurger.php - - src/Core/HttpCache/VarnishXKeyPurger.php - - src/Core/Hydra/EventListener/AddLinkHeaderListener.php - - src/Core/Hydra/JsonSchema/SchemaFactory.php - - src/Core/Hydra/Serializer/CollectionFiltersNormalizer.php - - src/Core/Hydra/Serializer/CollectionNormalizer.php - - src/Core/Hydra/Serializer/ConstraintViolationListNormalizer.php - - src/Core/Hydra/Serializer/DocumentationNormalizer.php - - src/Core/Hydra/Serializer/EntrypointNormalizer.php - - src/Core/Hydra/Serializer/ErrorNormalizer.php - - src/Core/Hydra/Serializer/PartialCollectionViewNormalizer.php - - src/Core/JsonApi/EventListener/TransformFieldsetsParametersListener.php - - src/Core/JsonApi/EventListener/TransformFilteringParametersListener.php - - src/Core/JsonApi/EventListener/TransformPaginationParametersListener.php - - src/Core/JsonApi/EventListener/TransformSortingParametersListener.php - - src/Core/JsonApi/Serializer/CollectionNormalizer.php - - src/Core/JsonApi/Serializer/ConstraintViolationListNormalizer.php - - src/Core/JsonApi/Serializer/EntrypointNormalizer.php - - src/Core/JsonApi/Serializer/ErrorNormalizer.php - - src/Core/JsonApi/Serializer/ItemNormalizer.php - - src/Core/JsonApi/Serializer/ObjectNormalizer.php - - src/Core/JsonApi/Serializer/ReservedAttributeNameConverter.php - - src/Core/JsonLd/Action/ContextAction.php - - src/Core/JsonLd/ContextBuilder.php - - src/Core/JsonLd/Serializer/ItemNormalizer.php - - src/Core/JsonLd/Serializer/ObjectNormalizer.php - - src/Core/JsonSchema/Command/JsonSchemaGenerateCommand.php - - src/Core/JsonSchema/Schema.php - - src/Core/JsonSchema/SchemaFactory.php - - src/Core/JsonSchema/TypeFactory.php - - src/Core/Mercure/EventListener/AddLinkHeaderListener.php - - src/Core/Metadata/Property/Factory/CachedPropertyNameCollectionFactory.php - - src/Core/Metadata/Property/Factory/ExtractorPropertyNameCollectionFactory.php - - src/Core/Metadata/Property/PropertyNameCollection.php - - src/Core/OpenApi/Model/Components.php - - src/Core/OpenApi/Model/Contact.php - - src/Core/OpenApi/Model/Encoding.php - - src/Core/OpenApi/Model/ExternalDocumentation.php - - src/Core/OpenApi/Model/Info.php - - src/Core/OpenApi/Model/License.php - - src/Core/OpenApi/Model/Link.php - - src/Core/OpenApi/Model/MediaType.php - - src/Core/OpenApi/Model/OAuthFlow.php - - src/Core/OpenApi/Model/OAuthFlows.php - - src/Core/OpenApi/Model/Operation.php - - src/Core/OpenApi/Model/Parameter.php - - src/Core/OpenApi/Model/PathItem.php - - src/Core/OpenApi/Model/Paths.php - - src/Core/OpenApi/Model/RequestBody.php - - src/Core/OpenApi/Model/Response.php - - src/Core/OpenApi/Model/Schema.php - - src/Core/OpenApi/Model/SecurityScheme.php - - src/Core/OpenApi/Model/Server.php - - src/Core/OpenApi/OpenApi.php - - src/Core/OpenApi/Options.php - - src/Core/OpenApi/Serializer/OpenApiNormalizer.php - - src/Core/Operation/DashPathSegmentNameGenerator.php - - src/Core/Operation/UnderscorePathSegmentNameGenerator.php - - src/Core/PathResolver/CustomOperationPathResolver.php - - src/Core/PathResolver/OperationPathResolver.php - - src/Core/Problem/Serializer/ConstraintViolationListNormalizer.php - - src/Core/Problem/Serializer/ErrorNormalizer.php - - src/Core/Security/Core/Authorization/ExpressionLanguageProvider.php - - src/Core/Security/EventListener/DenyAccessListener.php - - src/Core/Security/ResourceAccessChecker.php - - src/Core/Serializer/AbstractItemNormalizer.php - - src/Core/Serializer/AbstractCollectionNormalizer.php - - src/Core/Serializer/AbstractConstraintViolationListNormalizer.php - - src/Core/Serializer/Filter/GroupFilter.php - - src/Core/Serializer/Filter/PropertyFilter.php - - src/Core/Serializer/JsonEncoder.php - - src/Core/Serializer/Mapping/Factory/ClassMetadataFactory.php - - src/Core/Serializer/SerializerContextBuilder.php - - src/Core/Serializer/SerializerFilterContextBuilder.php - - src/Core/Swagger/Serializer/ApiGatewayNormalizer.php - - src/Core/Swagger/Serializer/DocumentationNormalizer.php - - src/Core/Test/DoctrineMongoDbOdmFilterTestCase.php - - src/Core/Test/DoctrineOrmFilterTestCase.php - - src/Core/Upgrade/SubresourceTransformer.php - - src/Core/Upgrade/UpgradeApiResourceVisitor.php - - src/Core/Upgrade/UpgradeApiSubresourceVisitor.php - - src/Core/Util/AttributesExtractor.php - - src/Core/Util/ErrorFormatGuesser.php - - src/Core/Util/Inflector.php - - src/Core/Util/IriHelper.php - - src/Core/Util/Reflection.php - - src/Core/Util/ReflectionClassRecursiveIterator.php - - src/Core/Util/RequestAttributesExtractor.php - - src/Core/Util/RequestParser.php - - src/Core/Validator/EventListener/ValidateListener.php # Symfony cache - tests/Fixtures/app/var/cache - # Deprecated integrations (will be removed in API Platform 3) - - src/Core/Bridge/NelmioApiDoc/* - - tests/Core/Bridge/NelmioApiDoc/* - - src/Core/Bridge/FosUser/* # BC layer - src/deprecated_interfaces.php - - tests/Symfony/Bundle/DependencyInjection/Compiler/AnnotationFilterPassTest.php - - tests/Core/Annotation/ApiResourceTest.php - - tests/Core/Annotation/ApiPropertyTest.php - - tests/Core/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php - tests/Fixtures/TestBundle/BrowserKit/Client.php # The Symfony Configuration API isn't good enough to be analysed - src/Symfony/Bundle/DependencyInjection/Configuration.php @@ -251,17 +28,9 @@ parameters: # Imported code (temporary) - src/Symfony/Bundle/Test/BrowserKitAssertionsTrait.php - tests/Symfony/Bundle/Test/WebTestCaseTest.php - - tests/Core/ProphecyTrait.php - - tests/Core/Behat/CoverageContext.php - - tests/Core/Behat/DoctrineContext.php - tests/Fixtures/TestBundle/Security/AbstractSecurityUser.php # Templates for Maker - - src/Core/Bridge/Symfony/Maker/Resources/skeleton - src/Bridge/Symfony/Maker/Resources/skeleton - # Rector because new API Platform 3.0 classes don't exist yet - - src/Core/Bridge/Rector - - src/Core/Bridge/Symfony/Bundle/Command/RectorCommand.php - - tests/Core/Bridge/Rector/Rules earlyTerminatingMethodCalls: PHPUnit\Framework\Constraint\Constraint: - fail @@ -274,7 +43,6 @@ parameters: paths: - tests/Fixtures/TestBundle/Document/ - tests/Fixtures/TestBundle/Entity/ - - src/Core/Identifier/ - src/OpenApi/Factory/OpenApiFactory.php - message: '#is never written, only read.#' @@ -286,9 +54,6 @@ parameters: paths: - src/Doctrine/Common/PropertyHelperTrait.php - '#Access to an undefined property Prophecy\\Prophecy\\ObjectProphecy<(\\?[a-zA-Z0-9_]+)+>::\$[a-zA-Z0-9_]+#' - - - message: '#Call to an undefined method Doctrine\\Persistence\\ObjectManager::getConnection\(\)#' - path: src/Core/Bridge/Doctrine/Common/Util/IdentifierManagerTrait.php # https://github.com/willdurand/Negotiation/issues/89#issuecomment-513283286 - message: '#Call to an undefined method Negotiation\\AcceptHeader::getType\(\)\.#' @@ -339,9 +104,6 @@ parameters: - '#Method ApiPlatform\\Doctrine\\Orm\\Filter\\(Abstract|Exists|Order)Filter::filterProperty\(\) invoked with 7 parameters, 5-6 required\.#' - '#Method ApiPlatform\\Doctrine\\Orm\\Filter\\(AbstractFilter|FilterInterface)::apply\(\) invoked with 5 parameters, 3-4 required\.#' - '#Method ApiPlatform\\PathResolver\\OperationPathResolverInterface::resolveOperationPath\(\) invoked with 4 parameters, 3 required\.#' - - - message: '#If condition is always false.#' - path: src/Core # Expected, due to backward compatibility - From a8087b94eb3c9e284ea51151c478e4df02d9e7d2 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 1 Jun 2022 12:16:52 +0200 Subject: [PATCH 28/56] temp --- src/Action/ExceptionAction.php | 3 +-- src/Hydra/Serializer/DocumentationNormalizer.php | 2 +- .../Factory/AttributesResourceMetadataCollectionFactory.php | 3 ++- tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Action/ExceptionAction.php b/src/Action/ExceptionAction.php index 433fbcb0cbf..fe1e39061d8 100644 --- a/src/Action/ExceptionAction.php +++ b/src/Action/ExceptionAction.php @@ -38,13 +38,12 @@ final class ExceptionAction private $serializer; private $errorFormats; private $exceptionToStatus; - private $resourceMetadataCollectionFactory; /** * @param array $errorFormats A list of enabled error formats * @param array $exceptionToStatus A list of exceptions mapped to their HTTP status code */ - public function __construct(SerializerInterface $serializer, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, array $errorFormats, array $exceptionToStatus = []) + public function __construct(SerializerInterface $serializer, array $errorFormats, array $exceptionToStatus = [], ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null) { $this->serializer = $serializer; $this->errorFormats = $errorFormats; diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index 483bc5567cd..1832a6b9e8a 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -480,7 +480,7 @@ private function getProperty(ApiProperty $propertyMetadata, string $propertyName $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; - if ([] !== $type && !$type->isCollection() && (null !== $className = $type->getClassName()) && $this->resourceClassResolver->isResourceClass($className)) { + if (null !== $type && [] !== $type && !$type->isCollection() && (null !== $className = $type->getClassName()) && $this->resourceClassResolver->isResourceClass($className)) { $propertyData['owl:maxCardinality'] = 1; } diff --git a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php index 58fdffab7f4..e08a5ff8451 100644 --- a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php @@ -236,6 +236,7 @@ private function getOperationWithDefaults(ApiResource $resource, Operation $oper */ private function addGlobalDefaults($operation) { + $extraProperties = []; foreach ($this->defaults as $key => $value) { $upperKey = ucfirst($this->camelCaseToSnakeCaseNameConverter->denormalize($key)); $getter = 'get'.$upperKey; @@ -249,7 +250,7 @@ private function addGlobalDefaults($operation) } } - return $operation->withExtraProperties($extraProperties); + return $operation->withExtraProperties(array_merge($extraProperties, $operation->getExtraProperties())); } private function getResourceWithDefaults(string $resourceClass, string $shortName, ApiResource $resource): ApiResource diff --git a/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php b/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php index dbef8b3f7b4..6938819c6d3 100644 --- a/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php +++ b/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php @@ -52,21 +52,21 @@ public function testExecuteWithoutOption() public function testExecuteWithItemOperationGet() { - $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => 'api_dummies_get_item', '--type' => 'output']); + $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => '_api_/dummies/{id}.{_format}_get', '--type' => 'output']); $this->assertJson($this->tester->getDisplay()); } public function testExecuteWithCollectionOperationGet() { - $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => 'api_dummies_get_collection', '--type' => 'output']); + $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => '_api_/dummies.{_format}_get_collection', '--type' => 'output']); $this->assertJson($this->tester->getDisplay()); } public function testExecuteWithJsonldFormatOption() { - $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => 'api_dummies_post_collection', '--format' => 'jsonld']); + $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--operation' => '_api_/dummies.{_format}_post', '--format' => 'jsonld']); $result = $this->tester->getDisplay(); $this->assertStringContainsString('@id', $result); From b2972b2c1ddfda09396e4c7e1e485044b0ec267b Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Thu, 26 May 2022 10:04:50 +0200 Subject: [PATCH 29/56] fix(json-ld): property metadata types and iris (#4769) --- .../Serializer/DocumentationNormalizer.php | 276 ++++++++++++++---- src/JsonLd/ContextBuilder.php | 86 +++++- .../Factory/LegacyPropertyMetadataFactory.php | 88 ++++++ .../DocumentationNormalizerTest.php | 138 +++++++-- .../PropertyMetadataCompatibilityTest.php | 2 +- 5 files changed, 498 insertions(+), 92 deletions(-) create mode 100644 src/Metadata/Property/Factory/LegacyPropertyMetadataFactory.php diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index 1832a6b9e8a..ed072965c89 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -15,6 +15,15 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; +use ApiPlatform\Core\Api\OperationMethodResolverInterface; +use ApiPlatform\Core\Api\OperationType; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; +use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Documentation\Documentation; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\ApiProperty; @@ -24,7 +33,6 @@ use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use Symfony\Component\PropertyInfo\Type; @@ -42,20 +50,44 @@ final class DocumentationNormalizer implements NormalizerInterface, CacheableSup { public const FORMAT = 'jsonld'; + /** + * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface + */ private $resourceMetadataFactory; private $propertyNameCollectionFactory; + + /** + * @var PropertyMetadataFactoryInterface|LegacyPropertyMetadataFactoryInterface + */ private $propertyMetadataFactory; private $resourceClassResolver; + private $operationMethodResolver; private $urlGenerator; + private $subresourceOperationFactory; private $nameConverter; - public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, UrlGeneratorInterface $urlGenerator, NameConverterInterface $nameConverter = null) + public function __construct($resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver = null, UrlGeneratorInterface $urlGenerator, SubresourceOperationFactoryInterface $subresourceOperationFactory = null, NameConverterInterface $nameConverter = null) { + if ($operationMethodResolver) { + @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', OperationMethodResolverInterface::class, __METHOD__), \E_USER_DEPRECATED); + } + $this->resourceMetadataFactory = $resourceMetadataFactory; + + if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { + trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); + } + + if ($subresourceOperationFactory) { + trigger_deprecation('api-platform/core', '2.7', sprintf('Using "%s" is deprecated and will be removed.', SubresourceOperationFactoryInterface::class)); + } + $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; $this->resourceClassResolver = $resourceClassResolver; + $this->operationMethodResolver = $operationMethodResolver; $this->urlGenerator = $urlGenerator; + $this->subresourceOperationFactory = $subresourceOperationFactory; $this->nameConverter = $nameConverter; } @@ -71,10 +103,20 @@ public function normalize($object, $format = null, array $context = []) foreach ($object->getResourceNameCollection() as $resourceClass) { $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); + + if ($resourceMetadataCollection instanceof ResourceMetadata) { + $shortName = $resourceMetadataCollection->getShortName(); + $prefixedShortName = $resourceMetadataCollection->getIri() ?? "#$shortName"; + + $this->populateEntrypointProperties($resourceClass, $resourceMetadataCollection, $shortName, $prefixedShortName, $entrypointProperties); + $classes[] = $this->getClass($resourceClass, $resourceMetadataCollection, $shortName, $prefixedShortName, $context); + continue; + } + $resourceMetadata = $resourceMetadataCollection[0]; $shortName = $resourceMetadata->getShortName(); $prefixedShortName = $resourceMetadata->getTypes()[0] ?? "#$shortName"; - $this->populateEntrypointProperties($resourceMetadata, $shortName, $prefixedShortName, $entrypointProperties, $resourceMetadataCollection); + $this->populateEntrypointProperties($resourceClass, $resourceMetadata, $shortName, $prefixedShortName, $entrypointProperties, $resourceMetadataCollection); $classes[] = $this->getClass($resourceClass, $resourceMetadata, $shortName, $prefixedShortName, $context, $resourceMetadataCollection); } @@ -83,10 +125,12 @@ public function normalize($object, $format = null, array $context = []) /** * Populates entrypoint properties. + * + * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function populateEntrypointProperties(ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array &$entrypointProperties, ?ResourceMetadataCollection $resourceMetadataCollection = null) + private function populateEntrypointProperties(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array &$entrypointProperties, ?ResourceMetadataCollection $resourceMetadataCollection = null) { - $hydraCollectionOperations = $this->getHydraOperations(true, $resourceMetadataCollection); + $hydraCollectionOperations = $this->getHydraOperations($resourceClass, $resourceMetadata, $prefixedShortName, true, $resourceMetadataCollection); if (empty($hydraCollectionOperations)) { return; } @@ -114,7 +158,7 @@ private function populateEntrypointProperties(ApiResource $resourceMetadata, str 'hydra:writeable' => false, ]; - if ($resourceMetadata->getDeprecationReason()) { + if ($resourceMetadata instanceof ResourceMetadata ? $resourceMetadata->getCollectionOperationAttribute('GET', 'deprecation_reason', null, true) : $resourceMetadata->getDeprecationReason()) { $entrypointProperty['owl:deprecated'] = true; } @@ -123,11 +167,18 @@ private function populateEntrypointProperties(ApiResource $resourceMetadata, str /** * Gets a Hydra class. + * + * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getClass(string $resourceClass, ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array $context, ?ResourceMetadataCollection $resourceMetadataCollection = null): array + private function getClass(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array $context, ?ResourceMetadataCollection $resourceMetadataCollection = null): array { - $description = $resourceMetadata->getDescription(); - $isDeprecated = $resourceMetadata->getDeprecationReason(); + if ($resourceMetadata instanceof ApiResource) { + $description = $resourceMetadata->getDescription(); + $isDeprecated = $resourceMetadata->getDeprecationReason(); + } else { + $description = $resourceMetadata->getDescription(); + $isDeprecated = $resourceMetadata->getAttribute('deprecation_reason'); + } $class = [ '@id' => $prefixedShortName, @@ -135,7 +186,7 @@ private function getClass(string $resourceClass, ApiResource $resourceMetadata, 'rdfs:label' => $shortName, 'hydra:title' => $shortName, 'hydra:supportedProperty' => $this->getHydraProperties($resourceClass, $resourceMetadata, $shortName, $prefixedShortName, $context), - 'hydra:supportedOperation' => $this->getHydraOperations(false, $resourceMetadataCollection), + 'hydra:supportedOperation' => $this->getHydraOperations($resourceClass, $resourceMetadata, $prefixedShortName, false, $resourceMetadataCollection), ]; if (null !== $description) { @@ -149,6 +200,35 @@ private function getClass(string $resourceClass, ApiResource $resourceMetadata, return $class; } + /** + * Gets the context for the property name factory. + */ + private function getPropertyNameCollectionFactoryContext(ResourceMetadata $resourceMetadata): array + { + $attributes = $resourceMetadata->getAttributes(); + $context = []; + + if (isset($attributes['normalization_context'][AbstractNormalizer::GROUPS])) { + $context['serializer_groups'] = (array) $attributes['normalization_context'][AbstractNormalizer::GROUPS]; + } + + if (!isset($attributes['denormalization_context'][AbstractNormalizer::GROUPS])) { + return $context; + } + + if (isset($context['serializer_groups'])) { + foreach ((array) $attributes['denormalization_context'][AbstractNormalizer::GROUPS] as $groupName) { + $context['serializer_groups'][] = $groupName; + } + + return $context; + } + + $context['serializer_groups'] = (array) $attributes['denormalization_context'][AbstractNormalizer::GROUPS]; + + return $context; + } + /** * Creates context for property metatata factories. */ @@ -185,36 +265,54 @@ private function getPropertyMetadataFactoryContext(ApiResource $resourceMetadata /** * Gets Hydra properties. + * + * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getHydraProperties(string $resourceClass, ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array $context): array + private function getHydraProperties(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array $context): array { $classes = []; - foreach ($resourceMetadata->getOperations() as $operation) { - /** @var Operation $operation */ - if (!$operation instanceof CollectionOperationInterface) { - continue; - } + if ($resourceMetadata instanceof ResourceMetadata) { + foreach ($resourceMetadata->getCollectionOperations() as $operationName => $operation) { + $inputMetadata = $resourceMetadata->getTypedOperationAttribute(OperationType::COLLECTION, $operationName, 'input', ['class' => $resourceClass], true); + if (null !== $inputClass = $inputMetadata['class'] ?? null) { + $classes[$inputClass] = true; + } - $inputMetadata = $operation->getInput(); - if (null !== $inputClass = $inputMetadata['class'] ?? null) { - $classes[$inputClass] = true; + $outputMetadata = $resourceMetadata->getTypedOperationAttribute(OperationType::COLLECTION, $operationName, 'output', ['class' => $resourceClass], true); + if (null !== $outputClass = $outputMetadata['class'] ?? null) { + $classes[$outputClass] = true; + } } + } else { + $classes[$resourceClass] = true; + foreach ($resourceMetadata->getOperations() as $operation) { + /** @var Operation $operation */ + if (!$operation instanceof CollectionOperationInterface) { + continue; + } - $outputMetadata = $operation->getOutput(); - if (null !== $outputClass = $outputMetadata['class'] ?? null) { - $classes[$outputClass] = true; - } - } + $inputMetadata = $operation->getInput(); + if (null !== $inputClass = $inputMetadata['class'] ?? null) { + $classes[$inputClass] = true; + } - if (!$classes) { - $classes[$resourceClass] = true; + $outputMetadata = $operation->getOutput(); + if (null !== $outputClass = $outputMetadata['class'] ?? null) { + $classes[$outputClass] = true; + } + } } /** @var string[] $classes */ $classes = array_keys($classes); $properties = []; - [$propertyNameContext, $propertyContext] = $this->getPropertyMetadataFactoryContext($resourceMetadata); + if ($resourceMetadata instanceof ResourceMetadata) { + $propertyNameContext = $this->getPropertyNameCollectionFactoryContext($resourceMetadata); + $propertyContext = []; + } else { + [$propertyNameContext, $propertyContext] = $this->getPropertyMetadataFactoryContext($resourceMetadata); + } foreach ($classes as $class) { foreach ($this->propertyNameCollectionFactory->create($class, $propertyNameContext) as $propertyName) { @@ -237,17 +335,38 @@ private function getHydraProperties(string $resourceClass, ApiResource $resource /** * Gets Hydra operations. + * + * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getHydraOperations(bool $collection, ?ResourceMetadataCollection $resourceMetadataCollection = null): array + private function getHydraOperations(string $resourceClass, $resourceMetadata, string $prefixedShortName, bool $collection, ?ResourceMetadataCollection $resourceMetadataCollection = null): array { - $hydraOperations = []; - foreach ($resourceMetadataCollection as $resourceMetadata) { - foreach ($resourceMetadata->getOperations() as $operation) { - if (($operation instanceof Post || $operation instanceof CollectionOperationInterface) !== $collection) { - continue; + if ($resourceMetadata instanceof ResourceMetadata) { + if (null === $operations = $collection ? $resourceMetadata->getCollectionOperations() : $resourceMetadata->getItemOperations()) { + return []; + } + + $hydraOperations = []; + foreach ($operations as $operationName => $operation) { + $hydraOperations[] = $this->getHydraOperation($resourceClass, $resourceMetadata, $operationName, $operation, $prefixedShortName, $collection ? OperationType::COLLECTION : OperationType::ITEM); + } + } else { + $hydraOperations = []; + foreach ($resourceMetadataCollection as $resourceMetadata) { + foreach ($resourceMetadata->getOperations() as $operationName => $operation) { + if (($operation instanceof Post || $operation instanceof CollectionOperationInterface) !== $collection) { + continue; + } + + $hydraOperations[] = $this->getHydraOperation($resourceClass, $resourceMetadata, $operationName, $operation, $operation->getTypes()[0] ?? "#{$operation->getShortName()}", null); } + } + } - $hydraOperations[] = $this->getHydraOperation($operation, $operation->getTypes()[0] ?? "#{$operation->getShortName()}"); + if (null !== $this->subresourceOperationFactory && !$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { + foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) { + $subresourceMetadata = $this->resourceMetadataFactory->create($operation['resource_class']); + $propertyMetadata = $this->propertyMetadataFactory->create(end($operation['identifiers'])[0], $operation['property']); + $hydraOperations[] = $this->getHydraOperation($resourceClass, $subresourceMetadata, $operation['route_name'], $operation, "#{$subresourceMetadata->getShortName()}", OperationType::SUBRESOURCE, $propertyMetadata->getSubresource()); } } @@ -256,27 +375,58 @@ private function getHydraOperations(bool $collection, ?ResourceMetadataCollectio /** * Gets and populates if applicable a Hydra operation. + * + * @param ResourceMetadata|ApiResource $resourceMetadata + * @param SubresourceMetadata $subresourceMetadata + * @param array|HttpOperation $operation */ - private function getHydraOperation(HttpOperation $operation, string $prefixedShortName): array + private function getHydraOperation(string $resourceClass, $resourceMetadata, string $operationName, $operation, string $prefixedShortName, ?string $operationType = null, SubresourceMetadata $subresourceMetadata = null): array { - $method = $operation->getMethod() ?: HttpOperation::METHOD_GET; + if ($operation instanceof HttpOperation) { + $method = $operation->getMethod() ?: HttpOperation::METHOD_GET; + } elseif ($this->operationMethodResolver) { + if (OperationType::COLLECTION === $operationType) { + $method = $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); + } elseif (OperationType::ITEM === $operationType) { + $method = $this->operationMethodResolver->getItemOperationMethod($resourceClass, $operationName); + } else { + $method = 'GET'; + } + } else { + $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); + } + $hydraOperation = $operation instanceof HttpOperation ? ($operation->getHydraContext() ?? []) : ($operation['hydra_context'] ?? []); - if ($operation->getDeprecationReason()) { + if ($operation instanceof HttpOperation ? $operation->getDeprecationReason() : $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', null, true)) { $hydraOperation['owl:deprecated'] = true; } - $shortName = $operation->getShortName(); - $inputMetadata = $operation->getInput() ?? []; - $outputMetadata = $operation->getOutput() ?? []; + if ($operation instanceof HttpOperation) { + $shortName = $operation->getShortName(); + $inputMetadata = $operation->getInput() ?? []; + $outputMetadata = $operation->getOutput() ?? []; + $operationType = $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM; + } else { + $shortName = $resourceMetadata->getShortName(); + $inputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input', ['class' => false]); + $outputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output', ['class' => false]); + } + $inputClass = \array_key_exists('class', $inputMetadata) ? $inputMetadata['class'] : false; $outputClass = \array_key_exists('class', $outputMetadata) ? $outputMetadata['class'] : false; - if ('GET' === $method && $operation instanceof CollectionOperationInterface) { + if ('GET' === $method && OperationType::COLLECTION === $operationType) { $hydraOperation += [ '@type' => ['hydra:Operation', 'schema:FindAction'], 'hydra:title' => "Retrieves the collection of $shortName resources.", 'returns' => 'hydra:Collection', ]; + } elseif ('GET' === $method && OperationType::SUBRESOURCE === $operationType) { + $hydraOperation += [ + '@type' => ['hydra:Operation', 'schema:FindAction'], + 'hydra:title' => $subresourceMetadata && $subresourceMetadata->isCollection() ? "Retrieves the collection of $shortName resources." : "Retrieves a $shortName resource.", + 'returns' => null === $outputClass ? 'owl:Nothing' : "#$shortName", + ]; } elseif ('GET' === $method) { $hydraOperation += [ '@type' => ['hydra:Operation', 'schema:FindAction'], @@ -325,17 +475,20 @@ private function getHydraOperation(HttpOperation $operation, string $prefixedSho /** * Gets the range of the property. + * + * @param ApiProperty|PropertyMetadata $propertyMetadata */ - private function getRange(ApiProperty $propertyMetadata): ?string + private function getRange($propertyMetadata): ?string { - $jsonldContext = $propertyMetadata->getJsonldContext(); + $jsonldContext = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttributes()['jsonld_context'] ?? [] : $propertyMetadata->getJsonldContext(); if (isset($jsonldContext['@type'])) { return $jsonldContext['@type']; } - $type = $propertyMetadata->getBuiltinTypes()[0] ?? []; - if ([] === $type) { + // TODO: 3.0 support multiple types, default value of types will be [] instead of null + $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; + if (null === $type) { return null; } @@ -363,13 +516,17 @@ private function getRange(ApiProperty $propertyMetadata): ?string if ($this->resourceClassResolver->isResourceClass($className)) { $resourceMetadata = $this->resourceMetadataFactory->create($className); - $operation = $resourceMetadata->getOperation(); + if ($resourceMetadata instanceof ResourceMetadataCollection) { + $operation = $resourceMetadata->getOperation(); - if (!$operation instanceof HttpOperation) { - return "#{$operation->getShortName()}"; + if (!$operation instanceof HttpOperation) { + return "#{$operation->getShortName()}"; + } + + return $operation->getTypes()[0] ?? "#{$operation->getShortName()}"; } - return $operation->getTypes()[0] ?? "#{$operation->getShortName()}"; + return $resourceMetadata->getIri() ?? "#{$resourceMetadata->getShortName()}"; } } @@ -460,11 +617,17 @@ private function getClasses(array $entrypointProperties, array $classes): array /** * Gets a property definition. + * + * @param ApiProperty|PropertyMetadata $propertyMetadata */ - private function getProperty(ApiProperty $propertyMetadata, string $propertyName, string $prefixedShortName, string $shortName): array + private function getProperty($propertyMetadata, string $propertyName, string $prefixedShortName, string $shortName): array { - if ($iri = $propertyMetadata->getIris()) { - $iri = 1 === \count($iri) ? $iri[0] : $iri; + if ($propertyMetadata instanceof PropertyMetadata) { + $iri = $propertyMetadata->getIri(); + } else { + if ($iri = $propertyMetadata->getIris()) { + $iri = 1 === \count($iri) ? $iri[0] : $iri; + } } if (!isset($iri)) { @@ -478,9 +641,10 @@ private function getProperty(ApiProperty $propertyMetadata, string $propertyName 'domain' => $prefixedShortName, ]; - $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; + // TODO: 3.0 support multiple types, default value of types will be [] instead of null + $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; - if (null !== $type && [] !== $type && !$type->isCollection() && (null !== $className = $type->getClassName()) && $this->resourceClassResolver->isResourceClass($className)) { + if (null !== $type && !$type->isCollection() && (null !== $className = $type->getClassName()) && $this->resourceClassResolver->isResourceClass($className)) { $propertyData['owl:maxCardinality'] = 1; } @@ -501,7 +665,7 @@ private function getProperty(ApiProperty $propertyMetadata, string $propertyName $property['hydra:description'] = $description; } - if ($propertyMetadata->getDeprecationReason()) { + if ($deprecationReason = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('deprecation_reason') : $propertyMetadata->getDeprecationReason()) { $property['owl:deprecated'] = true; } @@ -566,3 +730,5 @@ public function hasCacheableSupportsMethod(): bool return true; } } + +class_alias(DocumentationNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\DocumentationNormalizer::class); diff --git a/src/JsonLd/ContextBuilder.php b/src/JsonLd/ContextBuilder.php index a28456253ab..3b14141db8d 100644 --- a/src/JsonLd/ContextBuilder.php +++ b/src/JsonLd/ContextBuilder.php @@ -14,8 +14,12 @@ namespace ApiPlatform\JsonLd; use ApiPlatform\Api\UrlGeneratorInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\ApiProperty; -use ApiPlatform\Metadata\Operation; +use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -25,6 +29,7 @@ /** * {@inheritdoc} + * TODO: 3.0 simplify or remove the class. * * @author Kévin Dunglas */ @@ -35,8 +40,17 @@ final class ContextBuilder implements AnonymousContextBuilderInterface public const FORMAT = 'jsonld'; private $resourceNameCollectionFactory; + /** + * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory + */ private $resourceMetadataFactory; + /** + * @var LegacyPropertyNameCollectionFactoryInterface|PropertyNameCollectionFactoryInterface + */ private $propertyNameCollectionFactory; + /** + * @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface + */ private $propertyMetadataFactory; private $urlGenerator; @@ -45,7 +59,7 @@ final class ContextBuilder implements AnonymousContextBuilderInterface */ private $nameConverter; - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, UrlGeneratorInterface $urlGenerator, NameConverterInterface $nameConverter = null) + public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, UrlGeneratorInterface $urlGenerator, NameConverterInterface $nameConverter = null) { $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; $this->resourceMetadataFactory = $resourceMetadataFactory; @@ -53,6 +67,10 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName $this->propertyMetadataFactory = $propertyMetadataFactory; $this->urlGenerator = $urlGenerator; $this->nameConverter = $nameConverter; + + if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { + trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); + } } /** @@ -74,7 +92,12 @@ public function getEntrypointContext(int $referenceType = UrlGeneratorInterface: $context = $this->getBaseContext($referenceType); foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - $shortName = $this->resourceMetadataFactory->create($resourceClass)[0]->getShortName(); + // TODO: remove in 3.0 + if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { + $shortName = $this->resourceMetadataFactory->create($resourceClass)->getShortName(); + } else { + $shortName = $this->resourceMetadataFactory->create($resourceClass)[0]->getShortName(); + } $resourceName = lcfirst($shortName); @@ -92,6 +115,23 @@ public function getEntrypointContext(int $referenceType = UrlGeneratorInterface: */ public function getResourceContext(string $resourceClass, int $referenceType = UrlGeneratorInterface::ABS_PATH): array { + // TODO: Remove in 3.0 + if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { + $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); + if (null === $shortName = $resourceMetadata->getShortName()) { + return []; + } + + if ($resourceMetadata->getAttribute('normalization_context')['iri_only'] ?? false) { + $context = $this->getBaseContext($referenceType); + $context['hydra:member']['@type'] = '@id'; + + return $context; + } + + return $this->getResourceContextWithShortname($resourceClass, $referenceType, $shortName); + } + $operation = $this->resourceMetadataFactory->create($resourceClass)->getOperation(); if (null === $shortName = $operation->getShortName()) { return []; @@ -112,6 +152,16 @@ public function getResourceContext(string $resourceClass, int $referenceType = U */ public function getResourceContextUri(string $resourceClass, int $referenceType = null): string { + // TODO: remove in 3.0 + if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { + $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); + if (null === $referenceType) { + $referenceType = $resourceMetadata->getAttribute('url_generation_strategy'); + } + + return $this->urlGenerator->generate('api_jsonld_context', ['shortName' => $resourceMetadata->getShortName()], $referenceType); + } + $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass)[0]; if (null === $referenceType) { $referenceType = $resourceMetadata->getUrlGenerationStrategy(); @@ -147,19 +197,27 @@ public function getAnonymousResourceContext($object, array $context = [], int $r // here the object can be different from the resource given by the $context['api_resource'] value if (isset($context['api_resource'])) { - $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))[0]->getShortName(); + if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { + $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))->getShortName(); + } else { + $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))[0]->getShortName(); + } } return $jsonLdContext; } - private function getResourceContextWithShortname(string $resourceClass, int $referenceType, string $shortName, ?Operation $operation = null): array + private function getResourceContextWithShortname(string $resourceClass, int $referenceType, string $shortName, ?HttpOperation $operation = null): array { $context = $this->getBaseContext($referenceType); - $propertyContext = $operation ? ['normalization_groups' => $operation->getNormalizationContext()['groups'] ?? null, 'denormalization_groups' => $operation->getDenormalizationContext()['groups'] ?? null] : ['normalization_groups' => [], 'denormalization_groups' => []]; + if ($this->propertyMetadataFactory instanceof LegacyPropertyMetadataFactoryInterface) { + $propertyContext = []; + } else { + $propertyContext = $operation ? ['normalization_groups' => $operation->getNormalizationContext()['groups'] ?? null, 'denormalization_groups' => $operation->getDenormalizationContext()['groups'] ?? null] : ['normalization_groups' => [], 'denormalization_groups' => []]; + } foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - /** @var ApiProperty */ + /** @var PropertyMetadata|ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName, $propertyContext); if ($propertyMetadata->isIdentifier() && true !== $propertyMetadata->isWritable()) { @@ -167,8 +225,16 @@ private function getResourceContextWithShortname(string $resourceClass, int $ref } $convertedName = $this->nameConverter ? $this->nameConverter->normalize($propertyName, $resourceClass, self::FORMAT) : $propertyName; - $jsonldContext = $propertyMetadata->getJsonldContext() ?? []; - $id = $propertyMetadata->getTypes()[0] ?? null; + if ($propertyMetadata instanceof PropertyMetadata) { + $jsonldContext = ($propertyMetadata->getAttributes() ?? [])['jsonld_context'] ?? []; + $id = $propertyMetadata->getIri(); + } else { + $jsonldContext = $propertyMetadata->getJsonldContext() ?? []; + + if ($id = $propertyMetadata->getIris()) { + $id = 1 === \count($id) ? $id[0] : $id; + } + } if (!$id) { $id = sprintf('%s/%s', $shortName, $convertedName); @@ -193,3 +259,5 @@ private function getResourceContextWithShortname(string $resourceClass, int $ref return $context; } } + +class_alias(ContextBuilder::class, \ApiPlatform\Core\JsonLd\ContextBuilder::class); diff --git a/src/Metadata/Property/Factory/LegacyPropertyMetadataFactory.php b/src/Metadata/Property/Factory/LegacyPropertyMetadataFactory.php new file mode 100644 index 00000000000..cd61f123f49 --- /dev/null +++ b/src/Metadata/Property/Factory/LegacyPropertyMetadataFactory.php @@ -0,0 +1,88 @@ + + * + * 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\Metadata\Property\Factory; + +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; +use ApiPlatform\Exception\PropertyNotFoundException; +use ApiPlatform\Exception\ResourceClassNotFoundException; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Property\DeprecationMetadataTrait; + +final class LegacyPropertyMetadataFactory implements PropertyMetadataFactoryInterface +{ + use DeprecationMetadataTrait; + + private $legacyPropertyMetadataFactory; + private $decorated; + + public function __construct(LegacyPropertyMetadataFactoryInterface $legacyPropertyMetadataFactory, PropertyMetadataFactoryInterface $decorated = null) + { + $this->legacyPropertyMetadataFactory = $legacyPropertyMetadataFactory; + $this->decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function create(string $resourceClass, string $property, array $options = []): ApiProperty + { + if (null === $this->decorated) { + $propertyMetadata = new ApiProperty(); + } else { + try { + $propertyMetadata = $this->decorated->create($resourceClass, $property, $options); + } catch (PropertyNotFoundException $propertyNotFoundException) { + $propertyMetadata = new ApiProperty(); + } + } + + try { + $legacyPropertyMetadata = $this->legacyPropertyMetadataFactory->create($resourceClass, $property, ['deprecate' => false] + $options); + } catch (PropertyNotFoundException|ResourceClassNotFoundException $propertyNotFoundException) { + return $propertyMetadata; + } + + foreach (get_class_methods($legacyPropertyMetadata) as $method) { + if (0 !== strpos($method, 'get') && 0 !== strpos($method, 'is')) { + continue; + } + + if ('getIri' === $method) { + if (!$legacyPropertyMetadata->getIri()) { + continue; + } + + $propertyMetadata = $propertyMetadata->withIris([$legacyPropertyMetadata->getIri()]); + continue; + } + + if ('getType' === $method) { + if (!$legacyPropertyMetadata->getType()) { + continue; + } + + $propertyMetadata = $propertyMetadata->withBuiltinTypes([$legacyPropertyMetadata->getType()]); + continue; + } + + $wither = str_replace(['get', 'is'], 'with', $method); + + if (method_exists($propertyMetadata, $wither) && null !== $legacyPropertyMetadata->{$method}() && null === $propertyMetadata->{$method}()) { + $propertyMetadata = $propertyMetadata->{$wither}($legacyPropertyMetadata->{$method}()); + } + } + + return $this->withDeprecatedAttributes($propertyMetadata, $legacyPropertyMetadata->getAttributes() ?? []); + } +} diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index 9ee79fc1ba8..282366f3ea0 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -15,6 +15,14 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; +use ApiPlatform\Core\Api\OperationMethodResolverInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; +use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; +use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Hydra\Serializer\DocumentationNormalizer; use ApiPlatform\Metadata\ApiProperty; @@ -31,18 +39,28 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; -use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; /** * @author Amrouche Hamza + * @group legacy */ class DocumentationNormalizerTest extends TestCase { use ProphecyTrait; + public function testNormalizeLegacyResourceMetadata(): void + { + $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); + $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummy')); + + $this->doTestNormalize(null, $resourceMetadataFactoryProphecy->reveal()); + } + public function testNormalize(): void { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); @@ -59,10 +77,25 @@ public function testNormalize(): void (new ApiResource())->withShortName('relatedDummy')->withOperations(new Operations(['get' => (new Get())->withShortName('relatedDummy')])), ])); - $this->doTestNormalize($resourceMetadataFactoryProphecy->reveal()); + $this->doTestNormalize(null, $resourceMetadataFactoryProphecy->reveal()); + } + + public function testLegacyNormalize(): void + { + $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); + $operationMethodResolverProphecy->getItemOperationMethod('dummy', 'get')->shouldBeCalled()->willReturn('GET'); + $operationMethodResolverProphecy->getItemOperationMethod('dummy', 'put')->shouldBeCalled()->willReturn('PUT'); + $operationMethodResolverProphecy->getCollectionOperationMethod('dummy', 'get')->shouldBeCalled()->willReturn('GET'); + $operationMethodResolverProphecy->getCollectionOperationMethod('dummy', 'post')->shouldBeCalled()->willReturn('POST'); + $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); + $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummy')); + + $this->doTestNormalize($operationMethodResolverProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); } - private function doTestNormalize($resourceMetadataFactory = null): void + private function doTestNormalize(OperationMethodResolverInterface $operationMethodResolver = null, $resourceMetadataFactory = null): void { $title = 'Test Api'; $desc = 'test ApiGerard'; @@ -72,20 +105,54 @@ private function doTestNormalize($resourceMetadataFactory = null): void $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create('dummy', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['name', 'description', 'nameConverted', 'relatedDummy', 'iri'])); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@type' => '@id']) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy'))])->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withIris(['https://schema.org/Dummy'])); + if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { + $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); + $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( + (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( + (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withAttributes(['jsonld_context' => ['@type' => '@id']]) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( + (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy')))->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); + $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new PropertyMetadata())->withIri('https://schema.org/Dummy')); + } else { + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@type' => '@id']) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy'))])->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); + $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withIris(['https://schema.org/Dummy'])); + } $subresourceOperationFactoryProphecy = null; + if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { + $subresourceMetadata = new SubresourceMetadata('relatedDummy', false); + $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy')->shouldBeCalled()->willReturn((new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy')))->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withSubresource($subresourceMetadata)); + $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); + $subresourceOperationFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn([ + 'api_dummies_subresource_get_related_dummy' => [ + 'property' => 'relatedDummy', + 'collection' => false, + 'resource_class' => 'relatedDummy', + 'shortNames' => ['relatedDummy'], + 'identifiers' => [ + 'id' => ['dummy', 'id', true], + ], + 'route_name' => 'api_dummies_subresource_get_related_dummy', + 'path' => '/dummies/{id}/related_dummy.{_format}', + ], + ]); + } + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(true); @@ -100,7 +167,9 @@ private function doTestNormalize($resourceMetadataFactory = null): void $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), + $operationMethodResolver, $urlGenerator->reveal(), + $subresourceOperationFactoryProphecy ? $subresourceOperationFactoryProphecy->reveal() : null, new CustomConverter() ); @@ -358,6 +427,15 @@ private function doTestNormalize($resourceMetadataFactory = null): void 'hydra:entrypoint' => '/', ]; + if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { + $expected['hydra:supportedClass'][1]['hydra:supportedProperty'][0]['hydra:property']['hydra:supportedOperation'][] = [ + '@type' => ['hydra:Operation', 'schema:FindAction'], + 'hydra:method' => 'GET', + 'hydra:title' => 'Retrieves a relatedDummy resource.', + 'rdfs:label' => 'Retrieves a relatedDummy resource.', + 'returns' => '#relatedDummy', + ]; + } $this->assertEquals($expected, $documentationNormalizer->normalize($documentation)); $this->assertTrue($documentationNormalizer->supportsNormalization($documentation, 'jsonld')); $this->assertFalse($documentationNormalizer->supportsNormalization($documentation, 'hal')); @@ -375,18 +453,23 @@ public function testNormalizeInputOutputClass() $propertyNameCollectionFactoryProphecy->create('inputClass', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['a', 'b'])); $propertyNameCollectionFactoryProphecy->create('outputClass', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['c', 'd'])); - $dummyMetadata = new ResourceMetadataCollection('dummy', [ - (new ApiResource()) - ->withShortName('dummy') - ->withDescription('dummy') - ->withOperations(new Operations([ - 'get_collection' => (new GetCollection())->withShortName('dummy')->withInput(['class' => 'inputClass'])->withOutput(['class' => 'outputClass']), - 'post' => (new Post())->withShortName('dummy')->withInput(['class' => 'inputClass'])->withOutput(['class' => null]), - 'get' => (new Get())->withShortName('dummy')->withInput(['class' => 'inputClass'])->withOutput(['class' => 'outputClass']), - 'put' => (new Put())->withShortName('dummy')->withInput(['class' => null])->withOutput(['class' => 'outputClass']), - ])), - ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $dummyMetadata = new ResourceMetadata( + 'dummy', + 'dummy', + '#dummy', + [ + 'get' => ['method' => 'GET'], + 'put' => ['method' => 'PUT', 'input' => ['class' => null]], + ], + [ + 'get' => ['method' => 'GET'], + 'post' => ['method' => 'POST', 'output' => ['class' => null]], + ], + [ + 'input' => ['class' => 'inputClass'], + 'output' => ['class' => 'outputClass'], + ]); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); @@ -408,6 +491,7 @@ public function testNormalizeInputOutputClass() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), + null, $urlGenerator->reveal() ); diff --git a/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php b/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php index b3ac23e40b3..98e83ff367d 100644 --- a/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php +++ b/tests/Metadata/Extractor/PropertyMetadataCompatibilityTest.php @@ -71,7 +71,7 @@ final class PropertyMetadataCompatibilityTest extends TestCase 'extraProperties' => [ 'custom_property' => 'Lorem ipsum dolor sit amet', ], - 'iri' => false, + 'iris' => ['https://schema.org/totalPrice'], ]; /** From d329d53d536c03abbd43ab31130242f74698ffc9 Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Mon, 30 May 2022 15:25:32 +0200 Subject: [PATCH 30/56] most of the tests --- .../EventListener/PurgeHttpCacheListener.php | 8 +- src/Doctrine/EventListener/WriteListener.php | 86 -- src/GraphQl/Resolver/Stage/ReadStage.php | 11 - .../Serializer/DocumentationNormalizer.php | 274 ++----- src/JsonApi/Serializer/ItemNormalizer.php | 7 +- src/JsonSchema/SchemaFactory.php | 2 + src/OpenApi/Factory/OpenApiFactory.php | 7 +- src/OpenApi/Model/Schema.php | 7 +- src/Serializer/AbstractItemNormalizer.php | 6 +- src/State/UriVariablesResolverTrait.php | 8 +- .../DataCollector/RequestDataCollector.php | 3 +- .../ApiPlatformExtension.php | 22 - src/Symfony/Bundle/Resources/config/api.xml | 4 - .../Bundle/Resources/config/graphql.xml | 6 +- src/Symfony/Bundle/Resources/config/hal.xml | 9 +- .../Bundle/Resources/config/http_cache.xml | 2 +- src/Symfony/Bundle/Resources/config/hydra.xml | 3 + .../Bundle/Resources/config/json_schema.xml | 3 +- .../Bundle/Resources/config/jsonapi.xml | 4 +- .../Bundle/Resources/config/jsonld.xml | 7 +- .../Bundle/Resources/config/legacy/hal.xml | 17 - .../Bundle/Resources/config/legacy/hydra.xml | 17 - .../Resources/config/legacy/json_schema.xml | 30 - .../Bundle/Resources/config/mercure.xml | 2 +- src/Symfony/Bundle/Resources/config/state.xml | 5 +- .../Resources/config/symfony/events.xml | 3 +- .../Resources/config/symfony/validator.xml | 2 +- .../Bundle/Resources/config/v3/hal.xml | 17 - .../Bundle/Resources/config/v3/hydra.xml | 17 - .../Resources/config/v3/json_schema.xml | 29 - .../Bundle/SwaggerUi/SwaggerUiAction.php | 24 +- .../Bundle/Test/Constraint/ArraySubset.php | 23 +- .../Test/Constraint/ArraySubsetLegacy.php | 34 - .../Bundle/Test/Constraint/ArraySubsetV9.php | 34 - .../EventListener/AddFormatListener.php | 44 +- .../EventListener/AddLinkHeaderListener.php | 48 +- .../EventListener/DenyAccessListener.php | 93 +-- .../EventListener/DeserializeListener.php | 11 +- .../TransformFieldsetsParametersListener.php | 21 +- .../TransformPaginationParametersListener.php | 3 - .../QueryParameterValidateListener.php | 18 +- src/Symfony/EventListener/ReadListener.php | 2 +- src/Symfony/EventListener/RespondListener.php | 82 +- .../EventListener/SerializeListener.php | 6 +- src/Symfony/EventListener/WriteListener.php | 20 +- src/Symfony/Validator/Validator.php | 4 - src/Util/IriHelper.php | 5 - .../PublishMercureUpdatesListenerTest.php | 7 - .../PurgeHttpCacheListenerTest.php | 1 - .../EventListener/WriteListenerTest.php | 146 ---- tests/Fixtures/app/AppKernel.php | 3 - tests/Fixtures/app/config/config_common.yml | 2 - .../GraphQl/Resolver/Stage/ReadStageTest.php | 36 - .../SecurityPostDenormalizeStageTest.php | 3 - .../GraphQl/Serializer/ItemNormalizerTest.php | 3 - .../MercureSubscriptionIriGeneratorTest.php | 9 - tests/Hal/JsonSchema/SchemaFactoryTest.php | 3 - .../Serializer/CollectionNormalizerTest.php | 1 - .../Serializer/EntrypointNormalizerTest.php | 1 - tests/Hal/Serializer/ItemNormalizerTest.php | 7 - .../Serializer/CollectionNormalizerTest.php | 1 - .../DocumentationNormalizerTest.php | 142 +--- .../Serializer/EntrypointNormalizerTest.php | 1 - .../PartialCollectionViewNormalizerTest.php | 1 - .../Serializer/CollectionNormalizerTest.php | 1 - .../JsonApi/Serializer/ItemNormalizerTest.php | 25 +- tests/OpenApi/Model/SchemaTest.php | 33 - tests/Serializer/ItemNormalizerTest.php | 3 - .../Bundle/Action/SwaggerUiActionTest.php | 225 ------ .../PayloadArgumentResolverTest.php | 1 - .../Bundle/Command/OpenApiCommandTest.php | 13 +- .../RequestDataCollectorTest.php | 163 +--- .../ApiPlatformExtensionTest.php | 744 ++---------------- .../DependencyInjection/ConfigurationTest.php | 36 - .../Bundle/SwaggerUi/SwaggerUiActionTest.php | 39 +- tests/Symfony/Bundle/Test/ApiTestCaseTest.php | 3 - tests/Symfony/Bundle/Test/ClientTest.php | 3 - .../Twig/ApiPlatformProfilerPanelTest.php | 27 - .../EventListener/AddFormatListenerTest.php | 264 +++---- .../AddLinkHeaderListenerTest.php | 138 +--- .../EventListener/DenyAccessListenerTest.php | 237 +----- .../EventListener/DeserializeListenerTest.php | 155 ++-- .../EventListener/ExceptionListenerTest.php | 2 +- ...ansformFieldsetsParametersListenerTest.php | 17 +- ...nsformPaginationParametersListenerTest.php | 2 +- .../QueryParameterValidateListenerTest.php | 69 +- .../EventListener/RespondListenerTest.php | 52 +- .../EventListener/SerializeListenerTest.php | 35 +- .../EventListener/WriteListenerTest.php | 42 +- .../Validator/Metadata/ValidatorTest.php | 27 - tests/Util/IriHelperTest.php | 56 -- 91 files changed, 653 insertions(+), 3216 deletions(-) delete mode 100644 src/Doctrine/EventListener/WriteListener.php delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/hal.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/hydra.xml delete mode 100644 src/Symfony/Bundle/Resources/config/legacy/json_schema.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/hal.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/hydra.xml delete mode 100644 src/Symfony/Bundle/Resources/config/v3/json_schema.xml delete mode 100644 src/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php delete mode 100644 src/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php delete mode 100644 tests/Doctrine/EventListener/WriteListenerTest.php delete mode 100644 tests/OpenApi/Model/SchemaTest.php delete mode 100644 tests/Symfony/Bundle/Action/SwaggerUiActionTest.php diff --git a/src/Doctrine/EventListener/PurgeHttpCacheListener.php b/src/Doctrine/EventListener/PurgeHttpCacheListener.php index 59534ee8985..efb7e7967d3 100644 --- a/src/Doctrine/EventListener/PurgeHttpCacheListener.php +++ b/src/Doctrine/EventListener/PurgeHttpCacheListener.php @@ -45,14 +45,10 @@ final class PurgeHttpCacheListener private $propertyAccessor; private $tags = []; - public function __construct(PurgerInterface $purger, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null) + public function __construct(PurgerInterface $purger, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null) { $this->purger = $purger; $this->iriConverter = $iriConverter; - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } - $this->resourceClassResolver = $resourceClassResolver; $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor(); } @@ -120,7 +116,7 @@ private function gatherResourceAndItemTags($entity, bool $purgeItem): void { try { $resourceClass = $this->resourceClassResolver->getResourceClass($entity); - $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromResourceClass($resourceClass) : $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_PATH, new GetCollection()); + $iri = $this->iriConverter->getIriFromResource($resourceClass, UrlGeneratorInterface::ABS_PATH, new GetCollection()); $this->tags[$iri] = $iri; if ($purgeItem) { diff --git a/src/Doctrine/EventListener/WriteListener.php b/src/Doctrine/EventListener/WriteListener.php deleted file mode 100644 index 808d298f34f..00000000000 --- a/src/Doctrine/EventListener/WriteListener.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * 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\Doctrine\EventListener; - -use ApiPlatform\Core\EventListener\WriteListener as BaseWriteListener; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use Symfony\Component\HttpKernel\Event\ViewEvent; - -/** - * Bridges Doctrine and the API system. - * - * @deprecated - * - * @author Kévin Dunglas - */ -final class WriteListener -{ - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry) - { - @trigger_error(sprintf('The %s class is deprecated since version 2.2 and will be removed in 3.0. Use the %s class instead.', __CLASS__, BaseWriteListener::class), \E_USER_DEPRECATED); - - $this->managerRegistry = $managerRegistry; - } - - /** - * Persists, updates or delete data return by the controller if applicable. - */ - public function onKernelView(ViewEvent $event): void - { - $request = $event->getRequest(); - if ($request->isMethodSafe()) { - return; - } - - $resourceClass = $request->attributes->get('_api_resource_class'); - if (null === $resourceClass) { - return; - } - - $controllerResult = $event->getControllerResult(); - if (null === $objectManager = $this->getManager($resourceClass, $controllerResult)) { - return; - } - - switch ($request->getMethod()) { - case 'POST': - $objectManager->persist($controllerResult); - break; - case 'DELETE': - $objectManager->remove($controllerResult); - $event->setControllerResult(null); - break; - } - - $objectManager->flush(); - } - - /** - * Gets the manager if applicable. - * - * @param mixed $data - */ - private function getManager(string $resourceClass, $data): ?ObjectManager - { - $objectManager = $this->managerRegistry->getManagerForClass($resourceClass); - if (null === $objectManager || !\is_object($data)) { - return null; - } - - return $objectManager; - } -} diff --git a/src/GraphQl/Resolver/Stage/ReadStage.php b/src/GraphQl/Resolver/Stage/ReadStage.php index 867eb4a485e..d0a180fcc5a 100644 --- a/src/GraphQl/Resolver/Stage/ReadStage.php +++ b/src/GraphQl/Resolver/Stage/ReadStage.php @@ -127,17 +127,6 @@ private function getNormalizedFilters(array $args): array // If the value contains arrays, we need to merge them for the filters to understand this syntax, proper to GraphQL to preserve the order of the arguments. if ($this->isSequentialArrayOfArrays($value)) { - if (\count($value[0]) > 1) { - $deprecationMessage = "The filter syntax \"$name: {"; - $filterArgsOld = []; - $filterArgsNew = []; - foreach ($value[0] as $filterArgName => $filterArgValue) { - $filterArgsOld[] = "$filterArgName: \"$filterArgValue\""; - $filterArgsNew[] = sprintf('{%s: "%s"}', $filterArgName, $filterArgValue); - } - $deprecationMessage .= sprintf('%s}" is deprecated since API Platform 2.6, use the following syntax instead: "%s: [%s]".', implode(', ', $filterArgsOld), $name, implode(', ', $filterArgsNew)); - @trigger_error($deprecationMessage, \E_USER_DEPRECATED); - } $value = array_merge(...$value); } $filters[$name] = $this->getNormalizedFilters($value); diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index ed072965c89..5638b043a29 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -15,15 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Api\OperationType; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; use ApiPlatform\Documentation\Documentation; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\ApiProperty; @@ -33,6 +24,7 @@ use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use Symfony\Component\PropertyInfo\Type; @@ -50,44 +42,20 @@ final class DocumentationNormalizer implements NormalizerInterface, CacheableSup { public const FORMAT = 'jsonld'; - /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface - */ - private $resourceMetadataFactory; - private $propertyNameCollectionFactory; + private ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory; + private PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory; + private PropertyMetadataFactoryInterface $propertyMetadataFactory; + private ResourceClassResolverInterface $resourceClassResolver; + private UrlGeneratorInterface $urlGenerator; + private ?NameConverterInterface $nameConverter; - /** - * @var PropertyMetadataFactoryInterface|LegacyPropertyMetadataFactoryInterface - */ - private $propertyMetadataFactory; - private $resourceClassResolver; - private $operationMethodResolver; - private $urlGenerator; - private $subresourceOperationFactory; - private $nameConverter; - - public function __construct($resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver = null, UrlGeneratorInterface $urlGenerator, SubresourceOperationFactoryInterface $subresourceOperationFactory = null, NameConverterInterface $nameConverter = null) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, UrlGeneratorInterface $urlGenerator, NameConverterInterface $nameConverter = null) { - if ($operationMethodResolver) { - @trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.5 and will be removed in 3.0.', OperationMethodResolverInterface::class, __METHOD__), \E_USER_DEPRECATED); - } - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - if ($subresourceOperationFactory) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Using "%s" is deprecated and will be removed.', SubresourceOperationFactoryInterface::class)); - } - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; $this->propertyMetadataFactory = $propertyMetadataFactory; $this->resourceClassResolver = $resourceClassResolver; - $this->operationMethodResolver = $operationMethodResolver; $this->urlGenerator = $urlGenerator; - $this->subresourceOperationFactory = $subresourceOperationFactory; $this->nameConverter = $nameConverter; } @@ -104,15 +72,6 @@ public function normalize($object, $format = null, array $context = []) foreach ($object->getResourceNameCollection() as $resourceClass) { $resourceMetadataCollection = $this->resourceMetadataFactory->create($resourceClass); - if ($resourceMetadataCollection instanceof ResourceMetadata) { - $shortName = $resourceMetadataCollection->getShortName(); - $prefixedShortName = $resourceMetadataCollection->getIri() ?? "#$shortName"; - - $this->populateEntrypointProperties($resourceClass, $resourceMetadataCollection, $shortName, $prefixedShortName, $entrypointProperties); - $classes[] = $this->getClass($resourceClass, $resourceMetadataCollection, $shortName, $prefixedShortName, $context); - continue; - } - $resourceMetadata = $resourceMetadataCollection[0]; $shortName = $resourceMetadata->getShortName(); $prefixedShortName = $resourceMetadata->getTypes()[0] ?? "#$shortName"; @@ -125,10 +84,8 @@ public function normalize($object, $format = null, array $context = []) /** * Populates entrypoint properties. - * - * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function populateEntrypointProperties(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array &$entrypointProperties, ?ResourceMetadataCollection $resourceMetadataCollection = null) + private function populateEntrypointProperties(string $resourceClass, ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array &$entrypointProperties, ?ResourceMetadataCollection $resourceMetadataCollection = null) { $hydraCollectionOperations = $this->getHydraOperations($resourceClass, $resourceMetadata, $prefixedShortName, true, $resourceMetadataCollection); if (empty($hydraCollectionOperations)) { @@ -158,7 +115,7 @@ private function populateEntrypointProperties(string $resourceClass, $resourceMe 'hydra:writeable' => false, ]; - if ($resourceMetadata instanceof ResourceMetadata ? $resourceMetadata->getCollectionOperationAttribute('GET', 'deprecation_reason', null, true) : $resourceMetadata->getDeprecationReason()) { + if ($resourceMetadata->getDeprecationReason()) { $entrypointProperty['owl:deprecated'] = true; } @@ -167,18 +124,11 @@ private function populateEntrypointProperties(string $resourceClass, $resourceMe /** * Gets a Hydra class. - * - * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getClass(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array $context, ?ResourceMetadataCollection $resourceMetadataCollection = null): array + private function getClass(string $resourceClass, ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array $context, ?ResourceMetadataCollection $resourceMetadataCollection = null): array { - if ($resourceMetadata instanceof ApiResource) { - $description = $resourceMetadata->getDescription(); - $isDeprecated = $resourceMetadata->getDeprecationReason(); - } else { - $description = $resourceMetadata->getDescription(); - $isDeprecated = $resourceMetadata->getAttribute('deprecation_reason'); - } + $description = $resourceMetadata->getDescription(); + $isDeprecated = $resourceMetadata->getDeprecationReason(); $class = [ '@id' => $prefixedShortName, @@ -200,35 +150,6 @@ private function getClass(string $resourceClass, $resourceMetadata, string $shor return $class; } - /** - * Gets the context for the property name factory. - */ - private function getPropertyNameCollectionFactoryContext(ResourceMetadata $resourceMetadata): array - { - $attributes = $resourceMetadata->getAttributes(); - $context = []; - - if (isset($attributes['normalization_context'][AbstractNormalizer::GROUPS])) { - $context['serializer_groups'] = (array) $attributes['normalization_context'][AbstractNormalizer::GROUPS]; - } - - if (!isset($attributes['denormalization_context'][AbstractNormalizer::GROUPS])) { - return $context; - } - - if (isset($context['serializer_groups'])) { - foreach ((array) $attributes['denormalization_context'][AbstractNormalizer::GROUPS] as $groupName) { - $context['serializer_groups'][] = $groupName; - } - - return $context; - } - - $context['serializer_groups'] = (array) $attributes['denormalization_context'][AbstractNormalizer::GROUPS]; - - return $context; - } - /** * Creates context for property metatata factories. */ @@ -265,54 +186,33 @@ private function getPropertyMetadataFactoryContext(ApiResource $resourceMetadata /** * Gets Hydra properties. - * - * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getHydraProperties(string $resourceClass, $resourceMetadata, string $shortName, string $prefixedShortName, array $context): array + private function getHydraProperties(string $resourceClass, ApiResource $resourceMetadata, string $shortName, string $prefixedShortName, array $context): array { $classes = []; - if ($resourceMetadata instanceof ResourceMetadata) { - foreach ($resourceMetadata->getCollectionOperations() as $operationName => $operation) { - $inputMetadata = $resourceMetadata->getTypedOperationAttribute(OperationType::COLLECTION, $operationName, 'input', ['class' => $resourceClass], true); - if (null !== $inputClass = $inputMetadata['class'] ?? null) { - $classes[$inputClass] = true; - } - - $outputMetadata = $resourceMetadata->getTypedOperationAttribute(OperationType::COLLECTION, $operationName, 'output', ['class' => $resourceClass], true); - if (null !== $outputClass = $outputMetadata['class'] ?? null) { - $classes[$outputClass] = true; - } + $classes[$resourceClass] = true; + foreach ($resourceMetadata->getOperations() as $operation) { + /** @var Operation $operation */ + if (!$operation instanceof CollectionOperationInterface) { + continue; } - } else { - $classes[$resourceClass] = true; - foreach ($resourceMetadata->getOperations() as $operation) { - /** @var Operation $operation */ - if (!$operation instanceof CollectionOperationInterface) { - continue; - } - $inputMetadata = $operation->getInput(); - if (null !== $inputClass = $inputMetadata['class'] ?? null) { - $classes[$inputClass] = true; - } + $inputMetadata = $operation->getInput(); + if (null !== $inputClass = $inputMetadata['class'] ?? null) { + $classes[$inputClass] = true; + } - $outputMetadata = $operation->getOutput(); - if (null !== $outputClass = $outputMetadata['class'] ?? null) { - $classes[$outputClass] = true; - } + $outputMetadata = $operation->getOutput(); + if (null !== $outputClass = $outputMetadata['class'] ?? null) { + $classes[$outputClass] = true; } } /** @var string[] $classes */ $classes = array_keys($classes); $properties = []; - if ($resourceMetadata instanceof ResourceMetadata) { - $propertyNameContext = $this->getPropertyNameCollectionFactoryContext($resourceMetadata); - $propertyContext = []; - } else { - [$propertyNameContext, $propertyContext] = $this->getPropertyMetadataFactoryContext($resourceMetadata); - } + [$propertyNameContext, $propertyContext] = $this->getPropertyMetadataFactoryContext($resourceMetadata); foreach ($classes as $class) { foreach ($this->propertyNameCollectionFactory->create($class, $propertyNameContext) as $propertyName) { @@ -335,38 +235,17 @@ private function getHydraProperties(string $resourceClass, $resourceMetadata, st /** * Gets Hydra operations. - * - * @param ResourceMetadata|ApiResource $resourceMetadata */ - private function getHydraOperations(string $resourceClass, $resourceMetadata, string $prefixedShortName, bool $collection, ?ResourceMetadataCollection $resourceMetadataCollection = null): array + private function getHydraOperations(string $resourceClass, ApiResource $resourceMetadata, string $prefixedShortName, bool $collection, ?ResourceMetadataCollection $resourceMetadataCollection = null): array { - if ($resourceMetadata instanceof ResourceMetadata) { - if (null === $operations = $collection ? $resourceMetadata->getCollectionOperations() : $resourceMetadata->getItemOperations()) { - return []; - } - - $hydraOperations = []; - foreach ($operations as $operationName => $operation) { - $hydraOperations[] = $this->getHydraOperation($resourceClass, $resourceMetadata, $operationName, $operation, $prefixedShortName, $collection ? OperationType::COLLECTION : OperationType::ITEM); - } - } else { - $hydraOperations = []; - foreach ($resourceMetadataCollection as $resourceMetadata) { - foreach ($resourceMetadata->getOperations() as $operationName => $operation) { - if (($operation instanceof Post || $operation instanceof CollectionOperationInterface) !== $collection) { - continue; - } - - $hydraOperations[] = $this->getHydraOperation($resourceClass, $resourceMetadata, $operationName, $operation, $operation->getTypes()[0] ?? "#{$operation->getShortName()}", null); + $hydraOperations = []; + foreach ($resourceMetadataCollection as $resourceMetadata) { + foreach ($resourceMetadata->getOperations() as $operationName => $operation) { + if (($operation instanceof Post || $operation instanceof CollectionOperationInterface) !== $collection) { + continue; } - } - } - if (null !== $this->subresourceOperationFactory && !$this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) { - $subresourceMetadata = $this->resourceMetadataFactory->create($operation['resource_class']); - $propertyMetadata = $this->propertyMetadataFactory->create(end($operation['identifiers'])[0], $operation['property']); - $hydraOperations[] = $this->getHydraOperation($resourceClass, $subresourceMetadata, $operation['route_name'], $operation, "#{$subresourceMetadata->getShortName()}", OperationType::SUBRESOURCE, $propertyMetadata->getSubresource()); + $hydraOperations[] = $this->getHydraOperation($resourceClass, $resourceMetadata, $operationName, $operation, $operation->getTypes()[0] ?? "#{$operation->getShortName()}", null); } } @@ -375,57 +254,28 @@ private function getHydraOperations(string $resourceClass, $resourceMetadata, st /** * Gets and populates if applicable a Hydra operation. - * - * @param ResourceMetadata|ApiResource $resourceMetadata - * @param SubresourceMetadata $subresourceMetadata - * @param array|HttpOperation $operation */ - private function getHydraOperation(string $resourceClass, $resourceMetadata, string $operationName, $operation, string $prefixedShortName, ?string $operationType = null, SubresourceMetadata $subresourceMetadata = null): array + private function getHydraOperation(string $resourceClass, ApiResource $resourceMetadata, string $operationName, HttpOperation $operation, string $prefixedShortName, ?string $operationType = null): array { - if ($operation instanceof HttpOperation) { - $method = $operation->getMethod() ?: HttpOperation::METHOD_GET; - } elseif ($this->operationMethodResolver) { - if (OperationType::COLLECTION === $operationType) { - $method = $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName); - } elseif (OperationType::ITEM === $operationType) { - $method = $this->operationMethodResolver->getItemOperationMethod($resourceClass, $operationName); - } else { - $method = 'GET'; - } - } else { - $method = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'method', 'GET'); - } + $method = $operation->getMethod() ?: HttpOperation::METHOD_GET; - $hydraOperation = $operation instanceof HttpOperation ? ($operation->getHydraContext() ?? []) : ($operation['hydra_context'] ?? []); - if ($operation instanceof HttpOperation ? $operation->getDeprecationReason() : $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'deprecation_reason', null, true)) { + $hydraOperation = $operation->getHydraContext() ?? []; + if ($operation->getDeprecationReason()) { $hydraOperation['owl:deprecated'] = true; } - if ($operation instanceof HttpOperation) { - $shortName = $operation->getShortName(); - $inputMetadata = $operation->getInput() ?? []; - $outputMetadata = $operation->getOutput() ?? []; - $operationType = $operation instanceof CollectionOperationInterface ? OperationType::COLLECTION : OperationType::ITEM; - } else { - $shortName = $resourceMetadata->getShortName(); - $inputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'input', ['class' => false]); - $outputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output', ['class' => false]); - } + $shortName = $operation->getShortName(); + $inputMetadata = $operation->getInput() ?? []; + $outputMetadata = $operation->getOutput() ?? []; $inputClass = \array_key_exists('class', $inputMetadata) ? $inputMetadata['class'] : false; $outputClass = \array_key_exists('class', $outputMetadata) ? $outputMetadata['class'] : false; - if ('GET' === $method && OperationType::COLLECTION === $operationType) { + if ('GET' === $method && $operation instanceof CollectionOperationInterface) { $hydraOperation += [ '@type' => ['hydra:Operation', 'schema:FindAction'], 'hydra:title' => "Retrieves the collection of $shortName resources.", - 'returns' => 'hydra:Collection', - ]; - } elseif ('GET' === $method && OperationType::SUBRESOURCE === $operationType) { - $hydraOperation += [ - '@type' => ['hydra:Operation', 'schema:FindAction'], - 'hydra:title' => $subresourceMetadata && $subresourceMetadata->isCollection() ? "Retrieves the collection of $shortName resources." : "Retrieves a $shortName resource.", - 'returns' => null === $outputClass ? 'owl:Nothing' : "#$shortName", + 'returns' => null === $outputClass ? 'owl:Nothing' : 'hydra:Collection', ]; } elseif ('GET' === $method) { $hydraOperation += [ @@ -475,19 +325,17 @@ private function getHydraOperation(string $resourceClass, $resourceMetadata, str /** * Gets the range of the property. - * - * @param ApiProperty|PropertyMetadata $propertyMetadata */ - private function getRange($propertyMetadata): ?string + private function getRange(ApiProperty $propertyMetadata): ?string { - $jsonldContext = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttributes()['jsonld_context'] ?? [] : $propertyMetadata->getJsonldContext(); + $jsonldContext = $propertyMetadata->getJsonldContext(); if (isset($jsonldContext['@type'])) { return $jsonldContext['@type']; } // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; if (null === $type) { return null; } @@ -516,17 +364,13 @@ private function getRange($propertyMetadata): ?string if ($this->resourceClassResolver->isResourceClass($className)) { $resourceMetadata = $this->resourceMetadataFactory->create($className); - if ($resourceMetadata instanceof ResourceMetadataCollection) { - $operation = $resourceMetadata->getOperation(); + $operation = $resourceMetadata->getOperation(); - if (!$operation instanceof HttpOperation) { - return "#{$operation->getShortName()}"; - } - - return $operation->getTypes()[0] ?? "#{$operation->getShortName()}"; + if (!$operation instanceof HttpOperation) { + return "#{$operation->getShortName()}"; } - return $resourceMetadata->getIri() ?? "#{$resourceMetadata->getShortName()}"; + return $operation->getTypes()[0] ?? "#{$operation->getShortName()}"; } } @@ -617,17 +461,11 @@ private function getClasses(array $entrypointProperties, array $classes): array /** * Gets a property definition. - * - * @param ApiProperty|PropertyMetadata $propertyMetadata */ - private function getProperty($propertyMetadata, string $propertyName, string $prefixedShortName, string $shortName): array + private function getProperty(ApiProperty $propertyMetadata, string $propertyName, string $prefixedShortName, string $shortName): array { - if ($propertyMetadata instanceof PropertyMetadata) { - $iri = $propertyMetadata->getIri(); - } else { - if ($iri = $propertyMetadata->getIris()) { - $iri = 1 === \count($iri) ? $iri[0] : $iri; - } + if ($iri = $propertyMetadata->getIris()) { + $iri = 1 === \count($iri) ? $iri[0] : $iri; } if (!isset($iri)) { @@ -642,7 +480,7 @@ private function getProperty($propertyMetadata, string $propertyName, string $pr ]; // TODO: 3.0 support multiple types, default value of types will be [] instead of null - $type = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getType() : $propertyMetadata->getBuiltinTypes()[0] ?? null; + $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; if (null !== $type && !$type->isCollection() && (null !== $className = $type->getClassName()) && $this->resourceClassResolver->isResourceClass($className)) { $propertyData['owl:maxCardinality'] = 1; @@ -665,7 +503,7 @@ private function getProperty($propertyMetadata, string $propertyName, string $pr $property['hydra:description'] = $description; } - if ($deprecationReason = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('deprecation_reason') : $propertyMetadata->getDeprecationReason()) { + if ($deprecationReason = $propertyMetadata->getDeprecationReason()) { $property['owl:deprecated'] = true; } @@ -730,5 +568,3 @@ public function hasCacheableSupportsMethod(): bool return true; } } - -class_alias(DocumentationNormalizer::class, \ApiPlatform\Core\Hydra\Serializer\DocumentationNormalizer::class); diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index 2a47e8f8753..028b79b5023 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -13,9 +13,11 @@ namespace ApiPlatform\JsonApi\Serializer; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Serializer\AbstractItemNormalizer; @@ -29,6 +31,7 @@ use Symfony\Component\Serializer\Exception\NotNormalizableValueException; use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -49,9 +52,9 @@ final class ItemNormalizer extends AbstractItemNormalizer private $componentsCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor, ?NameConverterInterface $nameConverter, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, null, $defaultContext, $resourceMetadataCollectionFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $defaultContext, $resourceMetadataCollectionFactory, $resourceAccessChecker); } /** diff --git a/src/JsonSchema/SchemaFactory.php b/src/JsonSchema/SchemaFactory.php index 0c6c51986a4..5b86a687234 100644 --- a/src/JsonSchema/SchemaFactory.php +++ b/src/JsonSchema/SchemaFactory.php @@ -119,6 +119,8 @@ public function buildSchema(string $className, string $format = 'json', string $ // see https://github.com/json-schema-org/json-schema-spec/pull/737 if (Schema::VERSION_SWAGGER !== $version && $operation && $operation->getDeprecationReason()) { $definition['deprecated'] = true; + } else { + $definition['deprecated'] = false; } // externalDocs is an OpenAPI specific extension, but JSON Schema allows additional keys, so we always add it diff --git a/src/OpenApi/Factory/OpenApiFactory.php b/src/OpenApi/Factory/OpenApiFactory.php index c0608089733..ffc9ced1362 100644 --- a/src/OpenApi/Factory/OpenApiFactory.php +++ b/src/OpenApi/Factory/OpenApiFactory.php @@ -148,7 +148,7 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection [$requestMimeTypes, $responseMimeTypes] = $this->getMimeTypes($operation); - $operationId = $operation->getOpenapiContext()['operationId'] ?? $operationName; + $operationId = $operation->getOpenapiContext()['operationId'] ?? $this->normalizeOperationName($operationName); if ($path) { $pathItem = $paths->getPath($path) ?: new Model\PathItem(); @@ -556,4 +556,9 @@ private function hasParameter(Model\Parameter $parameter, array $parameters): bo return false; } + + private function normalizeOperationName(string $operationName): string + { + return preg_replace('/^_/', '', str_replace(['/', '.{_format}', '{', '}'], ['', '', '_', ''], $operationName)); + } } diff --git a/src/OpenApi/Model/Schema.php b/src/OpenApi/Model/Schema.php index 68a31abf779..bf3fd3eb67c 100644 --- a/src/OpenApi/Model/Schema.php +++ b/src/OpenApi/Model/Schema.php @@ -19,7 +19,6 @@ final class Schema extends \ArrayObject { use ExtensionTrait; - private $nullable; private $discriminator; private $readOnly; private $writeOnly; @@ -29,12 +28,8 @@ final class Schema extends \ArrayObject private $deprecated; private $schema; - public function __construct(bool $nullable = null, $discriminator = null, bool $readOnly = false, bool $writeOnly = false, string $xml = null, $externalDocs = null, $example = null, bool $deprecated = false) + public function __construct($discriminator = null, bool $readOnly = false, bool $writeOnly = false, string $xml = null, $externalDocs = null, $example = null, bool $deprecated = false) { - if (null !== $nullable) { - @trigger_error('The nullable keyword has been removed from the Schema Object (null can be used as a type value). This behaviour will not be possible anymore in API Platform 3.0.', \E_USER_DEPRECATED); - $this->nullable = $nullable; - } $this->discriminator = $discriminator; $this->readOnly = $readOnly; $this->writeOnly = $writeOnly; diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index dbcf1ddd4a3..9dcd9d26166 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Serializer; use ApiPlatform\Api\IriConverterInterface; +use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\InvalidValueException; @@ -57,9 +58,6 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer public const IS_TRANSFORMED_TO_SAME_CLASS = 'is_transformed_to_same_class'; - /** - * @var PropertyNameCollectionFactoryInterface - */ protected $propertyNameCollectionFactory; protected $propertyMetadataFactory; protected $iriConverter; @@ -68,7 +66,7 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer protected $propertyAccessor; protected $localCache = []; - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) { if (!isset($defaultContext['circular_reference_handler'])) { $defaultContext['circular_reference_handler'] = function ($object) { diff --git a/src/State/UriVariablesResolverTrait.php b/src/State/UriVariablesResolverTrait.php index 4504173022f..87d36ba93cd 100644 --- a/src/State/UriVariablesResolverTrait.php +++ b/src/State/UriVariablesResolverTrait.php @@ -14,9 +14,6 @@ namespace ApiPlatform\State; use ApiPlatform\Api\UriVariablesConverterInterface; -use ApiPlatform\Core\Identifier\CompositeIdentifierParser; -use ApiPlatform\Core\Identifier\ContextAwareIdentifierConverterInterface; -use ApiPlatform\Core\Identifier\IdentifierConverterInterface; use ApiPlatform\Exception\InvalidIdentifierException; use ApiPlatform\Metadata\HttpOperation; @@ -25,8 +22,7 @@ */ trait UriVariablesResolverTrait { - /** @var ContextAwareIdentifierConverterInterface|IdentifierConverterInterface|UriVariablesConverterInterface|null */ - private $uriVariablesConverter = null; + private ?UriVariablesConverterInterface $uriVariablesConverter = null; /** * Resolves an operation's UriVariables to their identifiers values. @@ -67,7 +63,7 @@ private function getOperationUriVariables(?HttpOperation $operation = null, arra if ($this->uriVariablesConverter) { $context = ['operation' => $operation]; - $identifiers = $this->uriVariablesConverter instanceof IdentifierConverterInterface ? $this->uriVariablesConverter->convert($identifiers, $operation->getClass() ?? $resourceClass) : $this->uriVariablesConverter->convert($identifiers, $operation->getClass() ?? $resourceClass, $context); + $identifiers = $this->uriVariablesConverter->convert($identifiers, $operation->getClass() ?? $resourceClass, $context); } return $identifiers; diff --git a/src/Symfony/Bundle/DataCollector/RequestDataCollector.php b/src/Symfony/Bundle/DataCollector/RequestDataCollector.php index cf2901766ac..0caafda4f3a 100644 --- a/src/Symfony/Bundle/DataCollector/RequestDataCollector.php +++ b/src/Symfony/Bundle/DataCollector/RequestDataCollector.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Symfony\Bundle\DataCollector; use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\RequestAttributesExtractor; use PackageVersions\Versions; use Psr\Container\ContainerInterface; @@ -31,7 +32,7 @@ final class RequestDataCollector extends DataCollector private $filterLocator; public function __construct( - $metadataFactory, + ResourceMetadataCollectionFactoryInterface $metadataFactory, ContainerInterface $filterLocator, ) { $this->metadataFactory = $metadataFactory; diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 8b062f8fc0a..208dfe29316 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -397,10 +397,6 @@ private function registerSwaggerConfiguration(ContainerBuilder $container, array throw new RuntimeException('You can not set "swagger_ui_extra_configuration" twice - in "openapi" and "swagger" section.'); } $container->setParameter('api_platform.swagger_ui.extra_configuration', $config['openapi']['swagger_ui_extra_configuration'] ?: $config['swagger']['swagger_ui_extra_configuration']); - - // for swagger 2 support - $loader->load('openapi.xml'); - $loader->load('swagger_ui.xml'); } private function registerJsonApiConfiguration(array $formats, XmlFileLoader $loader): void @@ -421,12 +417,6 @@ private function registerJsonLdHydraConfiguration(ContainerBuilder $container, a $loader->load('jsonld.xml'); $loader->load('hydra.xml'); - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/hydra.xml'); - } else { - $loader->load('v3/hydra.xml'); - } - if (!$container->has('api_platform.json_schema.schema_factory')) { $container->removeDefinition('api_platform.hydra.json_schema.schema_factory'); } @@ -443,12 +433,6 @@ private function registerJsonHalConfiguration(array $formats, XmlFileLoader $loa } $loader->load('hal.xml'); - - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/hal.xml'); - } else { - $loader->load('v3/hal.xml'); - } } private function registerJsonProblemConfiguration(array $errorFormats, XmlFileLoader $loader): void @@ -719,12 +703,6 @@ private function registerOpenApiConfiguration(ContainerBuilder $container, array $container->setParameter('api_platform.openapi.license.url', $config['openapi']['license']['url']); $loader->load('json_schema.xml'); - - if ($config['metadata_backward_compatibility_layer']) { - $loader->load('legacy/json_schema.xml'); - } else { - $loader->load('v3/json_schema.xml'); - } } private function registerMakerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void diff --git a/src/Symfony/Bundle/Resources/config/api.xml b/src/Symfony/Bundle/Resources/config/api.xml index 52f8d28ecdf..2e61d6c4652 100644 --- a/src/Symfony/Bundle/Resources/config/api.xml +++ b/src/Symfony/Bundle/Resources/config/api.xml @@ -63,11 +63,7 @@ - - - %api_platform.allow_plain_identifiers% null - diff --git a/src/Symfony/Bundle/Resources/config/graphql.xml b/src/Symfony/Bundle/Resources/config/graphql.xml index 05e0f868368..34b50ac495a 100644 --- a/src/Symfony/Bundle/Resources/config/graphql.xml +++ b/src/Symfony/Bundle/Resources/config/graphql.xml @@ -204,7 +204,7 @@ - + @@ -229,11 +229,7 @@ - - - %api_platform.allow_plain_identifiers% null - diff --git a/src/Symfony/Bundle/Resources/config/hal.xml b/src/Symfony/Bundle/Resources/config/hal.xml index a4806bb5c22..d1afa9c33e3 100644 --- a/src/Symfony/Bundle/Resources/config/hal.xml +++ b/src/Symfony/Bundle/Resources/config/hal.xml @@ -5,6 +5,12 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + + + + + jsonhal @@ -36,10 +42,7 @@ - null - false - diff --git a/src/Symfony/Bundle/Resources/config/http_cache.xml b/src/Symfony/Bundle/Resources/config/http_cache.xml index b3f251ca124..77b0225af96 100644 --- a/src/Symfony/Bundle/Resources/config/http_cache.xml +++ b/src/Symfony/Bundle/Resources/config/http_cache.xml @@ -11,7 +11,7 @@ %api_platform.http_cache.shared_max_age% %api_platform.http_cache.vary% %api_platform.http_cache.public% - api_platform.metadata.resource.metadata_collection_factory.retro_compatible + diff --git a/src/Symfony/Bundle/Resources/config/hydra.xml b/src/Symfony/Bundle/Resources/config/hydra.xml index c94ad71262e..0a5b331bf95 100644 --- a/src/Symfony/Bundle/Resources/config/hydra.xml +++ b/src/Symfony/Bundle/Resources/config/hydra.xml @@ -5,6 +5,9 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + + diff --git a/src/Symfony/Bundle/Resources/config/json_schema.xml b/src/Symfony/Bundle/Resources/config/json_schema.xml index da605582af7..864e12900f2 100644 --- a/src/Symfony/Bundle/Resources/config/json_schema.xml +++ b/src/Symfony/Bundle/Resources/config/json_schema.xml @@ -17,7 +17,7 @@ - + @@ -30,6 +30,7 @@ %api_platform.formats% + diff --git a/src/Symfony/Bundle/Resources/config/jsonapi.xml b/src/Symfony/Bundle/Resources/config/jsonapi.xml index 160cb912ad3..546c64b90f0 100644 --- a/src/Symfony/Bundle/Resources/config/jsonapi.xml +++ b/src/Symfony/Bundle/Resources/config/jsonapi.xml @@ -39,9 +39,9 @@ - + - + diff --git a/src/Symfony/Bundle/Resources/config/jsonld.xml b/src/Symfony/Bundle/Resources/config/jsonld.xml index a7437a579cb..abfae0e1213 100644 --- a/src/Symfony/Bundle/Resources/config/jsonld.xml +++ b/src/Symfony/Bundle/Resources/config/jsonld.xml @@ -7,7 +7,7 @@ - + @@ -16,7 +16,7 @@ - + @@ -26,7 +26,6 @@ - @@ -53,7 +52,7 @@ - + diff --git a/src/Symfony/Bundle/Resources/config/legacy/hal.xml b/src/Symfony/Bundle/Resources/config/legacy/hal.xml deleted file mode 100644 index dab3af931ca..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/hal.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/hydra.xml b/src/Symfony/Bundle/Resources/config/legacy/hydra.xml deleted file mode 100644 index 14e86ebf8da..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/hydra.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/legacy/json_schema.xml b/src/Symfony/Bundle/Resources/config/legacy/json_schema.xml deleted file mode 100644 index 90943ab4059..00000000000 --- a/src/Symfony/Bundle/Resources/config/legacy/json_schema.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/mercure.xml b/src/Symfony/Bundle/Resources/config/mercure.xml index 4f1f652cec9..5dde0e384bb 100644 --- a/src/Symfony/Bundle/Resources/config/mercure.xml +++ b/src/Symfony/Bundle/Resources/config/mercure.xml @@ -8,8 +8,8 @@ - + diff --git a/src/Symfony/Bundle/Resources/config/state.xml b/src/Symfony/Bundle/Resources/config/state.xml index b18400712f7..2f384a4008b 100644 --- a/src/Symfony/Bundle/Resources/config/state.xml +++ b/src/Symfony/Bundle/Resources/config/state.xml @@ -9,13 +9,12 @@ - + %api_platform.collection.pagination% %api_platform.graphql.collection.pagination% - - + diff --git a/src/Symfony/Bundle/Resources/config/symfony/events.xml b/src/Symfony/Bundle/Resources/config/symfony/events.xml index 871e3810c43..c136206d5ed 100644 --- a/src/Symfony/Bundle/Resources/config/symfony/events.xml +++ b/src/Symfony/Bundle/Resources/config/symfony/events.xml @@ -28,8 +28,8 @@ - + @@ -47,7 +47,6 @@ - diff --git a/src/Symfony/Bundle/Resources/config/symfony/validator.xml b/src/Symfony/Bundle/Resources/config/symfony/validator.xml index 5dfeaa54e34..f5ec4ddbc8a 100644 --- a/src/Symfony/Bundle/Resources/config/symfony/validator.xml +++ b/src/Symfony/Bundle/Resources/config/symfony/validator.xml @@ -23,8 +23,8 @@ - + %api_platform.validator.query_parameter_validation% diff --git a/src/Symfony/Bundle/Resources/config/v3/hal.xml b/src/Symfony/Bundle/Resources/config/v3/hal.xml deleted file mode 100644 index 6d5bc64890a..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/hal.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/hydra.xml b/src/Symfony/Bundle/Resources/config/v3/hydra.xml deleted file mode 100644 index 52c1128348d..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/hydra.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/Resources/config/v3/json_schema.xml b/src/Symfony/Bundle/Resources/config/v3/json_schema.xml deleted file mode 100644 index 21f1c5334fd..00000000000 --- a/src/Symfony/Bundle/Resources/config/v3/json_schema.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php b/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php index 0a87bb126fa..4bd2c3d2cf9 100644 --- a/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php +++ b/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php @@ -13,8 +13,8 @@ namespace ApiPlatform\Symfony\Bundle\SwaggerUi; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Exception\RuntimeException; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Options; use Symfony\Component\HttpFoundation\Request; @@ -42,7 +42,7 @@ final class SwaggerUiAction private $oauthClientSecret; private $oauthPkce; - public function __construct($resourceMetadataFactory, ?TwigEnvironment $twig, UrlGeneratorInterface $urlGenerator, NormalizerInterface $normalizer, OpenApiFactoryInterface $openApiFactory, Options $openApiOptions, SwaggerUiContext $swaggerUiContext, array $formats = [], string $oauthClientId = null, string $oauthClientSecret = null, bool $oauthPkce = false) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, ?TwigEnvironment $twig, UrlGeneratorInterface $urlGenerator, NormalizerInterface $normalizer, OpenApiFactoryInterface $openApiFactory, Options $openApiOptions, SwaggerUiContext $swaggerUiContext, array $formats = [], string $oauthClientId = null, string $oauthClientSecret = null, bool $oauthPkce = false) { $this->resourceMetadataFactory = $resourceMetadataFactory; $this->twig = $twig; @@ -72,8 +72,7 @@ public function __invoke(Request $request) 'showWebby' => $this->swaggerUiContext->isWebbyShown(), 'swaggerUiEnabled' => $this->swaggerUiContext->isSwaggerUiEnabled(), 'reDocEnabled' => $this->swaggerUiContext->isRedocEnabled(), - // FIXME: typo graphql => graphQl - 'graphqlEnabled' => $this->swaggerUiContext->isGraphQlEnabled(), + 'graphQlEnabled' => $this->swaggerUiContext->isGraphQlEnabled(), 'graphiQlEnabled' => $this->swaggerUiContext->isGraphiQlEnabled(), 'graphQlPlaygroundEnabled' => $this->swaggerUiContext->isGraphQlPlaygroundEnabled(), 'assetPackage' => $this->swaggerUiContext->getAssetPackage(), @@ -100,21 +99,10 @@ public function __invoke(Request $request) $swaggerData['id'] = $request->attributes->get('id'); $swaggerData['queryParameters'] = $request->query->all(); - $metadata = $this->resourceMetadataFactory->create($resourceClass); + $metadata = $this->resourceMetadataFactory->create($resourceClass)->getOperation($request->attributes->get('_api_operation_name')); - if ($metadata instanceof ResourceMetadata) { - $swaggerData['shortName'] = $metadata->getShortName(); - if (null !== $collectionOperationName = $request->attributes->get('_api_collection_operation_name')) { - $swaggerData['operationId'] = sprintf('%s%sCollection', $collectionOperationName, ucfirst($swaggerData['shortName'])); - } elseif (null !== $itemOperationName = $request->attributes->get('_api_item_operation_name')) { - $swaggerData['operationId'] = sprintf('%s%sItem', $itemOperationName, ucfirst($swaggerData['shortName'])); - } elseif (null !== $subresourceOperationContext = $request->attributes->get('_api_subresource_context')) { - $swaggerData['operationId'] = $subresourceOperationContext['operationId']; - } - } else { - $swaggerData['shortName'] = $metadata[0]->getShortName(); - $swaggerData['operationId'] = $request->attributes->get('_api_operation_name'); - } + $swaggerData['shortName'] = $metadata->getShortName(); + $swaggerData['operationId'] = $metadata->getName(); [$swaggerData['path'], $swaggerData['method']] = $this->getPathAndMethod($swaggerData); } diff --git a/src/Symfony/Bundle/Test/Constraint/ArraySubset.php b/src/Symfony/Bundle/Test/Constraint/ArraySubset.php index 758e4063b58..1078a7a4135 100644 --- a/src/Symfony/Bundle/Test/Constraint/ArraySubset.php +++ b/src/Symfony/Bundle/Test/Constraint/ArraySubset.php @@ -13,13 +13,22 @@ namespace ApiPlatform\Symfony\Bundle\Test\Constraint; -use PHPUnit\Runner\Version; -use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure; -use SebastianBergmann\Comparator\ComparisonFailure as LegacyComparisonFailure; +use PHPUnit\Framework\Constraint\Constraint; -if (!class_exists(ComparisonFailure::class) && class_exists(LegacyComparisonFailure::class)) { -} +/** + * Is used for phpunit >= 9. + * + * @internal + */ +final class ArraySubset extends Constraint +{ + use ArraySubsetTrait; -// Aliases as string to avoid loading the class -if (\PHP_VERSION_ID >= 80000 || (float) Version::series() >= 9) { + /** + * {@inheritdoc} + */ + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + return $this->_evaluate($other, $description, $returnResult); + } } diff --git a/src/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php b/src/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php deleted file mode 100644 index 139baae9a5f..00000000000 --- a/src/Symfony/Bundle/Test/Constraint/ArraySubsetLegacy.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\Symfony\Bundle\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; - -/** - * Is used for phpunit < 8. - * - * @internal - */ -final class ArraySubsetLegacy extends Constraint -{ - use ArraySubsetTrait; - - /** - * {@inheritdoc} - */ - public function evaluate($other, $description = '', $returnResult = false): ?bool - { - return $this->_evaluate($other, $description, $returnResult); - } -} diff --git a/src/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php b/src/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php deleted file mode 100644 index 195657f4dd9..00000000000 --- a/src/Symfony/Bundle/Test/Constraint/ArraySubsetV9.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\Symfony\Bundle\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; - -/** - * Is used for phpunit >= 9. - * - * @internal - */ -final class ArraySubsetV9 extends Constraint -{ - use ArraySubsetTrait; - - /** - * {@inheritdoc} - */ - public function evaluate($other, string $description = '', bool $returnResult = false): ?bool - { - return $this->_evaluate($other, $description, $returnResult); - } -} diff --git a/src/Symfony/EventListener/AddFormatListener.php b/src/Symfony/EventListener/AddFormatListener.php index f4896f59b03..26775e77a5d 100644 --- a/src/Symfony/EventListener/AddFormatListener.php +++ b/src/Symfony/EventListener/AddFormatListener.php @@ -14,8 +14,6 @@ namespace ApiPlatform\Symfony\EventListener; use ApiPlatform\Api\FormatMatcher; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; @@ -35,35 +33,13 @@ final class AddFormatListener use OperationRequestInitiatorTrait; private $negotiator; - private $resourceMetadataFactory; private $formats = []; - private $formatsProvider; - private $formatMatcher; - /** - * @param ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface|FormatsProviderInterface|array $resourceMetadataFactory - */ - public function __construct(Negotiator $negotiator, $resourceMetadataFactory, array $formats = []) + public function __construct(Negotiator $negotiator, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, array $formats = []) { - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && !$resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-plaform/core', '2.5', sprintf('Passing an array or an instance of "%s" as 2nd parameter of the constructor of "%s" is deprecated since API Platform 2.5, pass an instance of "%s" instead', FormatsProviderInterface::class, __CLASS__, ResourceMetadataFactoryInterface::class)); - } - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && $resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - $this->negotiator = $negotiator; - $this->resourceMetadataFactory = $resourceMetadataFactory instanceof ResourceMetadataFactoryInterface ? $resourceMetadataFactory : null; $this->formats = $formats; - - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface ? $resourceMetadataFactory : null; - - if (\is_array($resourceMetadataFactory)) { - $this->formats = $resourceMetadataFactory; - } elseif ($resourceMetadataFactory instanceof FormatsProviderInterface) { - $this->formatsProvider = $resourceMetadataFactory; - } + $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; } /** @@ -86,21 +62,7 @@ public function onKernelRequest(RequestEvent $event): void } $attributes = RequestAttributesExtractor::extractAttributes($request); - $formats = $this->formats; - - // BC check to be removed in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && $attributes) { - // TODO: Subresource operation metadata aren't available by default, for now we have to fallback on default formats. - // TODO: A better approach would be to always populate the subresource operation array. - $formats = $this - ->resourceMetadataFactory - ->create($attributes['resource_class']) - ->getOperationAttribute($attributes, 'output_formats', $this->formats, true); - } elseif ($this->formatsProvider instanceof FormatsProviderInterface) { - $formats = $this->formatsProvider->getFormatsFromAttributes($attributes); - } elseif ($operation && $operation->getOutputFormats()) { - $formats = $operation->getOutputFormats(); - } + $formats = $operation?->getOutputFormats() ?? $this->formats; $this->addRequestFormats($request, $formats); $this->formatMatcher = new FormatMatcher($formats); diff --git a/src/Symfony/EventListener/AddLinkHeaderListener.php b/src/Symfony/EventListener/AddLinkHeaderListener.php index 18b8ce1ed8c..6083522c956 100644 --- a/src/Symfony/EventListener/AddLinkHeaderListener.php +++ b/src/Symfony/EventListener/AddLinkHeaderListener.php @@ -13,12 +13,10 @@ namespace ApiPlatform\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\CorsTrait; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; -use Fig\Link\GenericLinkProvider; use Fig\Link\Link; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\Mercure\Discovery; @@ -33,28 +31,12 @@ final class AddLinkHeaderListener use CorsTrait; use OperationRequestInitiatorTrait; - /** - * @var ResourceMetadataCollectionFactoryInterface|ResourceMetadataFactoryInterface - */ - private $resourceMetadataFactory; - private $discovery; + private Discovery $discovery; - /** - * @param Discovery|string $discovery - * @param mixed $resourceMetadataFactory - */ - public function __construct($resourceMetadataFactory, $discovery) + public function __construct(Discovery $discovery, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null) { - $this->resourceMetadataFactory = $resourceMetadataFactory; - if ($resourceMetadataFactory && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - if ($resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } - $this->discovery = $discovery; + $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; } /** @@ -63,10 +45,6 @@ public function __construct($resourceMetadataFactory, $discovery) public function onKernelResponse(ResponseEvent $event): void { $request = $event->getRequest(); - if ($this->isPreflightRequest($request)) { - return; - } - $operation = $this->initializeOperation($request); if ( @@ -76,31 +54,13 @@ public function onKernelResponse(ResponseEvent $event): void return; } - $mercure = $operation ? $operation->getMercure() : ($attributes['mercure'] ?? false); - // TODO: remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $mercure = $this->resourceMetadataFactory->create($resourceClass)->getAttribute('mercure', false); - } + $mercure = $operation?->getMercure() ?? ($attributes['mercure'] ?? false); if (!$mercure) { return; } - if (!$this->discovery instanceof Discovery) { - $link = new Link('mercure', $this->discovery); - if (null === $linkProvider = $request->attributes->get('_links')) { - $request->attributes->set('_links', new GenericLinkProvider([$link])); - - return; - } - - $request->attributes->set('_links', $linkProvider->withLink($link)); - - return; - } - $hub = \is_array($mercure) ? ($mercure['hub'] ?? null) : null; - $this->discovery->addLink($request, $hub); } } diff --git a/src/Symfony/EventListener/DenyAccessListener.php b/src/Symfony/EventListener/DenyAccessListener.php index e40ca7cd4dc..7668b5e0a3e 100644 --- a/src/Symfony/EventListener/DenyAccessListener.php +++ b/src/Symfony/EventListener/DenyAccessListener.php @@ -13,21 +13,14 @@ namespace ApiPlatform\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Symfony\Security\ExpressionLanguage; -use ApiPlatform\Symfony\Security\ResourceAccessChecker; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; /** * Denies access to the current resource if the logged user doesn't have sufficient permissions. @@ -38,39 +31,12 @@ final class DenyAccessListener { use OperationRequestInitiatorTrait; - /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface - */ - private $resourceMetadataFactory; - /** - * @var ResourceAccessCheckerInterface - */ - private $resourceAccessChecker; + private ?ResourceAccessCheckerInterface $resourceAccessChecker; - public function __construct($resourceMetadataFactory, /* ResourceAccessCheckerInterface */ $resourceAccessCheckerOrExpressionLanguage = null, AuthenticationTrustResolverInterface $authenticationTrustResolver = null, RoleHierarchyInterface $roleHierarchy = null, TokenStorageInterface $tokenStorage = null, AuthorizationCheckerInterface $authorizationChecker = null) + public function __construct(?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ?ResourceAccessCheckerInterface $resourceAccessChecker = null) { - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if ($resourceAccessCheckerOrExpressionLanguage instanceof ResourceAccessCheckerInterface) { - $this->resourceAccessChecker = $resourceAccessCheckerOrExpressionLanguage; - - return; - } - - $this->resourceAccessChecker = new ResourceAccessChecker($resourceAccessCheckerOrExpressionLanguage, $authenticationTrustResolver, $roleHierarchy, $tokenStorage, $authorizationChecker); - @trigger_error(sprintf('Passing an instance of "%s" or null as second argument of "%s" is deprecated since API Platform 2.2 and will not be possible anymore in API Platform 3. Pass an instance of "%s" and no extra argument instead.', ExpressionLanguage::class, self::class, ResourceAccessCheckerInterface::class), \E_USER_DEPRECATED); - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } else { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } - } - - public function onKernelRequest(RequestEvent $event): void - { - @trigger_error(sprintf('Method "%1$s::onKernelRequest" is deprecated since API Platform 2.4 and will not be available anymore in API Platform 3. Prefer calling "%1$s::onSecurity" instead.', self::class), \E_USER_DEPRECATED); - $this->onSecurityPostDenormalize($event); + $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; + $this->resourceAccessChecker = $resourceAccessChecker; } public function onSecurity(RequestEvent $event): void @@ -99,7 +65,7 @@ public function onSecurityPostValidation(ViewEvent $event): void */ private function checkSecurity(Request $request, string $attribute, bool $backwardCompatibility, array $extraVariables = []): void { - if (!$attributes = RequestAttributesExtractor::extractAttributes($request)) { + if (!$this->resourceAccessChecker || !$attributes = RequestAttributesExtractor::extractAttributes($request)) { return; } @@ -107,38 +73,23 @@ private function checkSecurity(Request $request, string $attribute, bool $backwa $isGranted = null; $message = $attributes[$attribute.'_message'] ?? 'Access Denied.'; - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - - $isGranted = $resourceMetadata->getOperationAttribute($attributes, $attribute, null, true); - if ($backwardCompatibility && null === $isGranted) { - // Backward compatibility - $isGranted = $resourceMetadata->getOperationAttribute($attributes, 'access_control', null, true); - if (null !== $isGranted) { - @trigger_error('Using "access_control" attribute is deprecated since API Platform 2.4 and will not be possible anymore in API Platform 3. Use "security" attribute instead.', \E_USER_DEPRECATED); - } - } - - $message = $resourceMetadata->getOperationAttribute($attributes, $attribute.'_message', 'Access Denied.', true); - } elseif ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $operation = $this->initializeOperation($request); - if (!$operation) { - return; - } - - switch ($attribute) { - case 'security_post_denormalize': - $isGranted = $operation->getSecurityPostDenormalize(); - $message = $operation->getSecurityPostDenormalizeMessage(); - break; - case 'security_post_validation': - $isGranted = $operation->getSecurityPostValidation(); - $message = $operation->getSecurityPostValidationMessage(); - break; - default: - $isGranted = $operation->getSecurity(); - $message = $operation->getSecurityMessage(); - } + $operation = $this->initializeOperation($request); + if (!$operation) { + return; + } + + switch ($attribute) { + case 'security_post_denormalize': + $isGranted = $operation->getSecurityPostDenormalize(); + $message = $operation->getSecurityPostDenormalizeMessage(); + break; + case 'security_post_validation': + $isGranted = $operation->getSecurityPostValidation(); + $message = $operation->getSecurityPostValidationMessage(); + break; + default: + $isGranted = $operation->getSecurity(); + $message = $operation->getSecurityMessage(); } if (null === $isGranted) { diff --git a/src/Symfony/EventListener/DeserializeListener.php b/src/Symfony/EventListener/DeserializeListener.php index 44049bf7c3e..dd46568282c 100644 --- a/src/Symfony/EventListener/DeserializeListener.php +++ b/src/Symfony/EventListener/DeserializeListener.php @@ -38,7 +38,7 @@ final class DeserializeListener private $serializer; private $serializerContextBuilder; - public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) + public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null) { $this->serializer = $serializer; $this->serializerContextBuilder = $serializerContextBuilder; @@ -55,19 +55,18 @@ public function onKernelRequest(RequestEvent $event): void $request = $event->getRequest(); $method = $request->getMethod(); - $operation = $this->initializeOperation($request); - if ( 'DELETE' === $method || $request->isMethodSafe() || !($attributes = RequestAttributesExtractor::extractAttributes($request)) + || !$attributes['receive'] ) { return; } - if ($this->resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface && - (!$operation || !($operation->canDeserialize() ?? true) || !$attributes['receive']) - ) { + $operation = $this->initializeOperation($request); + + if (!($operation?->canDeserialize() ?? true)) { return; } diff --git a/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php index 6716d8a49fd..3ab911a4a79 100644 --- a/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListener.php @@ -13,10 +13,7 @@ namespace ApiPlatform\Symfony\EventListener\JsonApi; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use Symfony\Component\HttpKernel\Event\RequestEvent; /** @@ -27,18 +24,11 @@ */ final class TransformFieldsetsParametersListener { - /** - * @var ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface - */ - private $resourceMetadataFactory; + private $resourceMetadataCollectionFactory; - public function __construct($resourceMetadataFactory) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory) { - $this->resourceMetadataFactory = $resourceMetadataFactory; - - if (!$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } + $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; } public function onKernelRequest(RequestEvent $event): void @@ -66,9 +56,8 @@ public function onKernelRequest(RequestEvent $event): void return; } - /** @var ResourceMetadata|ResourceMetadataCollection */ - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - $resourceShortName = $resourceMetadata instanceof ResourceMetadata ? $resourceMetadata->getShortName() : $resourceMetadata->getOperation()->getShortName(); + $resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass); + $resourceShortName = $resourceMetadata->getOperation()->getShortName(); $properties = []; foreach ($fieldsParameter as $resourceType => $fields) { diff --git a/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php b/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php index ec5cd2fd49f..9036fc8a8e0 100644 --- a/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php +++ b/src/Symfony/EventListener/JsonApi/TransformPaginationParametersListener.php @@ -38,8 +38,5 @@ public function onKernelRequest(RequestEvent $event): void $filters = $request->attributes->get('_api_filters', []); $request->attributes->set('_api_filters', array_merge($pageParameter, $filters)); - - /* @TODO remove the `_api_pagination` attribute in 3.0 (@meyerbaptiste) */ - $request->attributes->set('_api_pagination', $pageParameter); } } diff --git a/src/Symfony/EventListener/QueryParameterValidateListener.php b/src/Symfony/EventListener/QueryParameterValidateListener.php index ed6445416fe..950552558fb 100644 --- a/src/Symfony/EventListener/QueryParameterValidateListener.php +++ b/src/Symfony/EventListener/QueryParameterValidateListener.php @@ -32,15 +32,12 @@ final class QueryParameterValidateListener public const OPERATION_ATTRIBUTE_KEY = 'query_parameter_validate'; - private $resourceMetadataFactory; + private QueryParameterValidator $queryParameterValidator; + private bool $enabled; - private $queryParameterValidator; - - private $enabled; - - public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, QueryParameterValidator $queryParameterValidator, bool $enabled = true) + public function __construct(QueryParameterValidator $queryParameterValidator, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, bool $enabled = true) { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; + $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; $this->queryParameterValidator = $queryParameterValidator; $this->enabled = $enabled; } @@ -48,7 +45,6 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource public function onKernelRequest(RequestEvent $event) { $request = $event->getRequest(); - $operation = $this->initializeOperation($request); if ( !$request->isMethodSafe() @@ -58,12 +54,14 @@ public function onKernelRequest(RequestEvent $event) return; } - if (!$operation || !($operation->getQueryParameterValidationEnabled() ?? true) || !$operation instanceof CollectionOperationInterface) { + $operation = $this->initializeOperation($request); + + if (!($operation?->getQueryParameterValidationEnabled() ?? true) || !$operation instanceof CollectionOperationInterface) { return; } $queryString = RequestParser::getQueryString($request); $queryParameters = $queryString ? RequestParser::parseRequestParams($queryString) : []; - $this->queryParameterValidator->validateFilters($attributes['resource_class'], $operation->getFilters() ?? [], $queryParameters); + $this->queryParameterValidator->validateFilters($attributes['resource_class'], $operation?->getFilters() ?? [], $queryParameters); } } diff --git a/src/Symfony/EventListener/ReadListener.php b/src/Symfony/EventListener/ReadListener.php index 17ffd741a33..607e445a472 100644 --- a/src/Symfony/EventListener/ReadListener.php +++ b/src/Symfony/EventListener/ReadListener.php @@ -43,7 +43,7 @@ final class ReadListener private $serializerContextBuilder; private $provider; - public function __construct(ProviderInterface $provider, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, SerializerContextBuilderInterface $serializerContextBuilder = null, UriVariablesConverterInterface $uriVariablesConverter = null) + public function __construct(ProviderInterface $provider, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, SerializerContextBuilderInterface $serializerContextBuilder = null, UriVariablesConverterInterface $uriVariablesConverter = null) { $this->provider = $provider; $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; diff --git a/src/Symfony/EventListener/RespondListener.php b/src/Symfony/EventListener/RespondListener.php index 6e8645808d2..d4d4b8aa911 100644 --- a/src/Symfony/EventListener/RespondListener.php +++ b/src/Symfony/EventListener/RespondListener.php @@ -15,8 +15,6 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; @@ -37,20 +35,11 @@ final class RespondListener 'DELETE' => Response::HTTP_NO_CONTENT, ]; - private $resourceMetadataFactory; private $iriConverter; - public function __construct($resourceMetadataFactory = null, IriConverterInterface $iriConverter = null) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null, IriConverterInterface $iriConverter = null) { - if ($resourceMetadataFactory && !$resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } - - if ($resourceMetadataFactory instanceof ResourceMetadataCollectionFactoryInterface) { - $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; - } - - $this->resourceMetadataFactory = $resourceMetadataFactory; + $this->resourceMetadataCollectionFactory = $resourceMetadataFactory; $this->iriConverter = $iriConverter; } @@ -82,36 +71,24 @@ public function onKernelView(ViewEvent $event): void 'X-Frame-Options' => 'deny', ]; - $status = $operation ? $operation->getStatus() : null; - - // TODO: remove this in 3.x - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface && $attributes) { - $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); - - if ($sunset = $resourceMetadata->getOperationAttribute($attributes, 'sunset', null, true)) { - $headers['Sunset'] = (new \DateTimeImmutable($sunset))->format(\DateTime::RFC1123); - } + $status = $operation?->getStatus(); - $headers = $this->addAcceptPatchHeader($headers, $attributes, $resourceMetadata); - $status = $resourceMetadata->getOperationAttribute($attributes, 'status'); - } elseif ($operation) { - if ($sunset = $operation->getSunset()) { - $headers['Sunset'] = (new \DateTimeImmutable($sunset))->format(\DateTime::RFC1123); - } + if ($sunset = $operation?->getSunset()) { + $headers['Sunset'] = (new \DateTimeImmutable($sunset))->format(\DateTime::RFC1123); + } - if ($acceptPatch = $operation->getAcceptPatch()) { - $headers['Accept-Patch'] = $acceptPatch; - } + if ($acceptPatch = $operation?->getAcceptPatch()) { + $headers['Accept-Patch'] = $acceptPatch; + } - if ( - $this->iriConverter && - ($operation->getExtraProperties()['is_alternate_resource_metadata'] ?? false) && - !($operation->getExtraProperties()['is_legacy_subresource'] ?? false) - && 301 === $operation->getStatus() - ) { - $status = 301; - $headers['Location'] = $this->iriConverter->getIriFromResource($request->attributes->get('data'), UrlGeneratorInterface::ABS_PATH, $operation); - } + if ( + $this->iriConverter && + $operation && + ($operation->getExtraProperties()['is_alternate_resource_metadata'] ?? false) + && 301 === $operation->getStatus() + ) { + $status = 301; + $headers['Location'] = $this->iriConverter->getIriFromResource($request->attributes->get('data'), UrlGeneratorInterface::ABS_PATH, $operation); } $status = $status ?? self::METHOD_TO_CODE[$request->getMethod()] ?? Response::HTTP_OK; @@ -130,29 +107,4 @@ public function onKernelView(ViewEvent $event): void $headers )); } - - private function addAcceptPatchHeader(array $headers, array $attributes, ResourceMetadata $resourceMetadata): array - { - if (!isset($attributes['item_operation_name'])) { - return $headers; - } - - $patchMimeTypes = []; - foreach ($resourceMetadata->getItemOperations() as $operation) { - if ('PATCH' !== ($operation['method'] ?? '') || !isset($operation['input_formats'])) { - continue; - } - - foreach ($operation['input_formats'] as $mimeTypes) { - foreach ($mimeTypes as $mimeType) { - $patchMimeTypes[] = $mimeType; - } - } - $headers['Accept-Patch'] = implode(', ', $patchMimeTypes); - - return $headers; - } - - return $headers; - } } diff --git a/src/Symfony/EventListener/SerializeListener.php b/src/Symfony/EventListener/SerializeListener.php index 07fcb569e2f..891fd2ef4ba 100644 --- a/src/Symfony/EventListener/SerializeListener.php +++ b/src/Symfony/EventListener/SerializeListener.php @@ -42,7 +42,7 @@ final class SerializeListener private $serializer; private $serializerContextBuilder; - public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory) + public function __construct(SerializerInterface $serializer, SerializerContextBuilderInterface $serializerContextBuilder, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null) { $this->serializer = $serializer; $this->serializerContextBuilder = $serializerContextBuilder; @@ -56,7 +56,6 @@ public function onKernelView(ViewEvent $event): void { $controllerResult = $event->getControllerResult(); $request = $event->getRequest(); - $operation = $this->initializeOperation($request); if ($controllerResult instanceof Response) { return; @@ -68,7 +67,8 @@ public function onKernelView(ViewEvent $event): void return; } - if (!$operation || !($operation->canSerialize() ?? true)) { + $operation = $this->initializeOperation($request); + if (!($operation?->canSerialize() ?? true)) { return; } diff --git a/src/Symfony/EventListener/WriteListener.php b/src/Symfony/EventListener/WriteListener.php index a9cb3f2a017..0ae832f91ce 100644 --- a/src/Symfony/EventListener/WriteListener.php +++ b/src/Symfony/EventListener/WriteListener.php @@ -20,9 +20,9 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\State\ProcessorInterface; use ApiPlatform\State\UriVariablesResolverTrait; +use ApiPlatform\Util\ClassInfoTrait; use ApiPlatform\Util\OperationRequestInitiatorTrait; use ApiPlatform\Util\RequestAttributesExtractor; -use ApiPlatform\Util\ResourceClassInfoTrait; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -35,23 +35,21 @@ */ final class WriteListener { + use ClassInfoTrait; use OperationRequestInitiatorTrait; - use ResourceClassInfoTrait; - use UriVariablesResolverTrait; public const OPERATION_ATTRIBUTE_KEY = 'write'; - private $processor; - private $iriConverter; + private ResourceClassResolverInterface $resourceClassResolver; + private ProcessorInterface $processor; + private IriConverterInterface $iriConverter; - public function __construct(ProcessorInterface $processor, IriConverterInterface $iriConverter, ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, ResourceClassResolverInterface $resourceClassResolver, ?UriVariablesConverterInterface $uriVariablesConverter = null) + public function __construct(ProcessorInterface $processor, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ?UriVariablesConverterInterface $uriVariablesConverter = null) { $this->processor = $processor; $this->iriConverter = $iriConverter; $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; - // TODO 3.0: see ResourceClassInfoTrait - $this->resourceMetadataFactory = $resourceMetadataCollectionFactory; $this->resourceClassResolver = $resourceClassResolver; $this->uriVariablesConverter = $uriVariablesConverter; } @@ -73,11 +71,11 @@ public function onKernelView(ViewEvent $event): void return; } - if (!$operation || ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) || !($operation->canWrite() ?? true) || !$attributes['persist']) { + if (!($operation?->canWrite() ?? true) || !$attributes['persist']) { return; } - if (!$operation->getProcessor()) { + if (!$operation?->getProcessor()) { return; } @@ -109,7 +107,7 @@ public function onKernelView(ViewEvent $event): void break; } - if ($this->isResourceClass($this->getObjectClass($controllerResult))) { + if ($this->resourceClassResolver->isResourceClass($this->getObjectClass($controllerResult))) { $request->attributes->set('_api_write_item_iri', $this->iriConverter->getIriFromResource($controllerResult)); } diff --git a/src/Symfony/Validator/Validator.php b/src/Symfony/Validator/Validator.php index 5631872a282..a26b8a4f0f5 100644 --- a/src/Symfony/Validator/Validator.php +++ b/src/Symfony/Validator/Validator.php @@ -50,10 +50,6 @@ public function validate($data, array $context = []) ($service = $this->container->get($validationGroups)) && \is_callable($service) ) { - if (!$service instanceof ValidationGroupsGeneratorInterface) { - @trigger_error(sprintf('Using a public validation groups generator service not implementing "%s" is deprecated since 2.6 and will be removed in 3.0.', ValidationGroupsGeneratorInterface::class), \E_USER_DEPRECATED); - } - $validationGroups = $service($data); } elseif (\is_callable($validationGroups)) { $validationGroups = $validationGroups($data); diff --git a/src/Util/IriHelper.php b/src/Util/IriHelper.php index 8c6a6a24591..e71bd762383 100644 --- a/src/Util/IriHelper.php +++ b/src/Util/IriHelper.php @@ -64,11 +64,6 @@ public static function createIri(array $parts, array $parameters, string $pagePa $parameters[$pageParameterName] = $page; } - if (\is_bool($urlGenerationStrategy)) { - @trigger_error(sprintf('Passing a bool as 5th parameter to "%s::createIri()" is deprecated since API Platform 2.6. Pass an "%s" constant (int) instead.', __CLASS__, UrlGeneratorInterface::class), \E_USER_DEPRECATED); - $urlGenerationStrategy = $urlGenerationStrategy ? UrlGeneratorInterface::ABS_URL : UrlGeneratorInterface::ABS_PATH; - } - $query = http_build_query($parameters, '', '&', \PHP_QUERY_RFC3986); $parts['query'] = preg_replace('/%5B\d+%5D/', '%5B%5D', $query); diff --git a/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php b/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php index 772b12851cd..3563a20f0cc 100644 --- a/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php +++ b/tests/Doctrine/EventListener/PublishMercureUpdatesListenerTest.php @@ -46,15 +46,11 @@ /** * @author Kévin Dunglas - * @group legacy */ class PublishMercureUpdatesListenerTest extends TestCase { use ProphecyTrait; - /** - * @group legacy - */ public function testLegacyPublishUpdate(): void { if (method_exists(Update::class, 'isPrivate')) { @@ -144,9 +140,6 @@ public function testLegacyPublishUpdate(): void $this->assertSame([['enable_async_update' => true], ['enable_async_update' => true], ['enable_async_update' => true], ['foo', 'bar', 'enable_async_update' => true]], $targets); } - /** - * @group legacy - */ public function testPublishUpdateWithLegacySignature(): void { if (!method_exists(Update::class, 'isPrivate')) { diff --git a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php index 23429e167b8..e7b5d230dd4 100644 --- a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php +++ b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php @@ -36,7 +36,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class PurgeHttpCacheListenerTest extends TestCase { diff --git a/tests/Doctrine/EventListener/WriteListenerTest.php b/tests/Doctrine/EventListener/WriteListenerTest.php deleted file mode 100644 index 0e4cad1aa2a..00000000000 --- a/tests/Doctrine/EventListener/WriteListenerTest.php +++ /dev/null @@ -1,146 +0,0 @@ - - * - * 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\Tests\Doctrine\EventListener; - -use ApiPlatform\Doctrine\EventListener\WriteListener; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use ApiPlatform\Tests\ProphecyTrait; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * @group legacy - */ -class WriteListenerTest extends TestCase -{ - use ProphecyTrait; - - /** - * @expectedDeprecation The ApiPlatform\Doctrine\EventListener\WriteListener class is deprecated since version 2.2 and will be removed in 3.0. Use the ApiPlatform\Core\EventListener\WriteListener class instead. - */ - public function testOnKernelViewWithControllerResultAndPostMethod() - { - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->persist($dummy)->shouldBeCalled(); - $objectManagerProphecy->flush()->shouldBeCalled(); - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass('Dummy')->willReturn($objectManagerProphecy); - - $writeListener = new WriteListener($managerRegistryProphecy->reveal()); - $httpKernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request(); - $request->setMethod('POST'); - $request->attributes->set('_api_resource_class', 'Dummy'); - $event = new ViewEvent($httpKernelProphecy->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $dummy); - - $writeListener->onKernelView($event); - } - - /** - * @expectedDeprecation The ApiPlatform\Doctrine\EventListener\WriteListener class is deprecated since version 2.2 and will be removed in 3.0. Use the ApiPlatform\Core\EventListener\WriteListener class instead. - */ - public function testOnKernelViewWithControllerResultAndDeleteMethod() - { - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->remove($dummy)->shouldBeCalled(); - $objectManagerProphecy->flush()->shouldBeCalled(); - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass('Dummy')->willReturn($objectManagerProphecy); - - $writeListener = new WriteListener($managerRegistryProphecy->reveal()); - $request = new Request(); - $request->setMethod('DELETE'); - $request->attributes->set('_api_resource_class', 'Dummy'); - - $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $dummy); - $writeListener->onKernelView($event); - } - - /** - * @expectedDeprecation The ApiPlatform\Doctrine\EventListener\WriteListener class is deprecated since version 2.2 and will be removed in 3.0. Use the ApiPlatform\Core\EventListener\WriteListener class instead. - */ - public function testOnKernelViewWithSafeMethod() - { - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->flush()->shouldNotBeCalled(); - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass('Dummy')->willReturn($objectManagerProphecy); - - $writeListener = new WriteListener($managerRegistryProphecy->reveal()); - $httpKernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request(); - $request->setMethod('HEAD'); - $request->attributes->set('_api_resource_class', 'Dummy'); - $event = new ViewEvent($httpKernelProphecy->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $dummy); - - $writeListener->onKernelView($event); - } - - /** - * @expectedDeprecation The ApiPlatform\Doctrine\EventListener\WriteListener class is deprecated since version 2.2 and will be removed in 3.0. Use the ApiPlatform\Core\EventListener\WriteListener class instead. - */ - public function testOnKernelViewWithNoResourceClass() - { - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $objectManagerProphecy = $this->prophesize(ObjectManager::class); - $objectManagerProphecy->flush()->shouldNotBeCalled(); - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass('Dummy')->willReturn($objectManagerProphecy); - - $writeListener = new WriteListener($managerRegistryProphecy->reveal()); - $httpKernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request(); - $request->setMethod('POST'); - $event = new ViewEvent($httpKernelProphecy->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $dummy); - - $writeListener->onKernelView($event); - } - - /** - * @expectedDeprecation The ApiPlatform\Doctrine\EventListener\WriteListener class is deprecated since version 2.2 and will be removed in 3.0. Use the ApiPlatform\Core\EventListener\WriteListener class instead. - * @doesNotPerformAssertions - */ - public function testOnKernelViewWithNoManager() - { - $dummy = new Dummy(); - $dummy->setName('Dummyrino'); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass('Dummy')->willReturn(null); - - $writeListener = new WriteListener($managerRegistryProphecy->reveal()); - $httpKernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request(); - $request->setMethod('DELETE'); - $request->attributes->set('_api_resource_class', 'Dummy'); - $event = new ViewEvent($httpKernelProphecy->reveal(), $request, \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $dummy); - - $writeListener->onKernelView($event); - } -} diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index 15f820c1009..6f519d0edf6 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -242,9 +242,6 @@ class_exists(NativePasswordHasher::class) ? 'password_hashers' : 'encoders' => [ $c->prependExtensionConfig('api_platform', ['enable_nelmio_api_doc' => true]); } - $metadataBackwardCompatibilityLayer = (bool) ($_SERVER['METADATA_BACKWARD_COMPATIBILITY_LAYER'] ?? false); - $c->prependExtensionConfig('api_platform', ['metadata_backward_compatibility_layer' => $metadataBackwardCompatibilityLayer]); - $loader->load(__DIR__.'/config/config.yml'); $c->prependExtensionConfig('api_platform', [ 'mapping' => [ diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index 546b7fb24b9..b1933e6fcfa 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -63,8 +63,6 @@ api_platform: enabled: true xkey: glue: ' ' - openapi: - backward_compatibility_layer: false defaults: pagination_client_enabled: true pagination_client_items_per_page: true diff --git a/tests/GraphQl/Resolver/Stage/ReadStageTest.php b/tests/GraphQl/Resolver/Stage/ReadStageTest.php index 29f34cd7dd2..6b2d9330177 100644 --- a/tests/GraphQl/Resolver/Stage/ReadStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ReadStageTest.php @@ -28,7 +28,6 @@ use GraphQL\Type\Definition\ResolveInfo; use PHPUnit\Framework\TestCase; use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** @@ -36,7 +35,6 @@ */ class ReadStageTest extends TestCase { - use ExpectDeprecationTrait; use ProphecyTrait; /** @var ReadStage */ @@ -283,38 +281,4 @@ public function collectionProvider(): array ], ]; } - - /** - * @group legacy - */ - public function testApplyCollectionWithDeprecatedFilterSyntax(): void - { - $operationName = 'collection_query'; - $resourceClass = 'myResource'; - $info = $this->prophesize(ResolveInfo::class)->reveal(); - $fieldName = 'subresource'; - $info->fieldName = $fieldName; - $context = [ - 'is_collection' => true, - 'is_mutation' => false, - 'is_subscription' => false, - 'args' => ['filter' => [['filterArg1' => 'filterValue1', 'filterArg2' => 'filterValue2']]], - 'info' => $info, - 'source' => null, - ]; - $filters = ['filter' => ['filterArg1' => 'filterValue1', 'filterArg2' => 'filterValue2']]; - /** @var Operation $operation */ - $operation = (new QueryCollection())->withName($operationName)->withClass($resourceClass)->withFilters($filters); - - $normalizationContext = ['normalization' => true, 'operation' => $operation]; - $this->serializerContextBuilderProphecy->create($resourceClass, $operationName, $context, true)->shouldBeCalled()->willReturn($normalizationContext); - - $this->providerProphecy->provide($operation, [], $normalizationContext + ['filters' => $filters])->willReturn([]); - - $this->expectDeprecation('The filter syntax "filter: {filterArg1: "filterValue1", filterArg2: "filterValue2"}" is deprecated since API Platform 2.6, use the following syntax instead: "filter: [{filterArg1: "filterValue1"}, {filterArg2: "filterValue2"}]".'); - - $result = ($this->readStage)($resourceClass, 'myResource', $operation, $context); - - $this->assertSame([], $result); - } } diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php index 47254665c7c..a411e2ddcd5 100644 --- a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php +++ b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php @@ -72,9 +72,6 @@ public function testGranted(): void ($this->securityPostDenormalizeStage)($resourceClass, $operation, ['extra_variables' => $extraVariables]); } - /** - * @group legacy - */ public function testGrantedLegacy(): void { self::markTestSkipped('The deprecation is handled in the Metadata transformation, this is not required anymore.'); // @phpstan-ignore-next-line diff --git a/tests/GraphQl/Serializer/ItemNormalizerTest.php b/tests/GraphQl/Serializer/ItemNormalizerTest.php index c457c5d6a49..3353e5363c8 100644 --- a/tests/GraphQl/Serializer/ItemNormalizerTest.php +++ b/tests/GraphQl/Serializer/ItemNormalizerTest.php @@ -37,9 +37,6 @@ class ItemNormalizerTest extends TestCase { use ProphecyTrait; - /** - * @group legacy - */ public function testSupportNormalization() { $std = new \stdClass(); diff --git a/tests/GraphQl/Subscription/MercureSubscriptionIriGeneratorTest.php b/tests/GraphQl/Subscription/MercureSubscriptionIriGeneratorTest.php index 8ec4633adf3..79a7405d20c 100644 --- a/tests/GraphQl/Subscription/MercureSubscriptionIriGeneratorTest.php +++ b/tests/GraphQl/Subscription/MercureSubscriptionIriGeneratorTest.php @@ -49,9 +49,6 @@ protected function setUp(): void $this->mercureSubscriptionIriGenerator = new MercureSubscriptionIriGenerator($this->requestContext, $this->registry); } - /** - * @group legacy - */ public function testGenerateTopicIriWithLegacySignature(): void { $mercureSubscriptionIriGenerator = new MercureSubscriptionIriGenerator(new RequestContext('', 'GET', 'example.com'), 'https://example.com/.well-known/mercure'); @@ -59,9 +56,6 @@ public function testGenerateTopicIriWithLegacySignature(): void $this->assertSame('http://example.com/subscriptions/subscription-id', $mercureSubscriptionIriGenerator->generateTopicIri('subscription-id')); } - /** - * @group legacy - */ public function testGenerateDefaultTopicIriWithLegacySignature(): void { $mercureSubscriptionIriGenerator = new MercureSubscriptionIriGenerator(new RequestContext('', 'GET', '', ''), 'https://example.com/.well-known/mercure'); @@ -69,9 +63,6 @@ public function testGenerateDefaultTopicIriWithLegacySignature(): void $this->assertSame('https://api-platform.com/subscriptions/subscription-id', $mercureSubscriptionIriGenerator->generateTopicIri('subscription-id')); } - /** - * @group legacy - */ public function testGenerateMercureUrlWithLegacySignature(): void { $mercureSubscriptionIriGenerator = new MercureSubscriptionIriGenerator(new RequestContext('', 'GET', 'example.com'), 'https://example.com/.well-known/mercure'); diff --git a/tests/Hal/JsonSchema/SchemaFactoryTest.php b/tests/Hal/JsonSchema/SchemaFactoryTest.php index 0f2171c5ad2..da354a84cb4 100644 --- a/tests/Hal/JsonSchema/SchemaFactoryTest.php +++ b/tests/Hal/JsonSchema/SchemaFactoryTest.php @@ -31,9 +31,6 @@ use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; -/** - * @group legacy - */ class SchemaFactoryTest extends TestCase { use ProphecyTrait; diff --git a/tests/Hal/Serializer/CollectionNormalizerTest.php b/tests/Hal/Serializer/CollectionNormalizerTest.php index a5bf0749496..558a946b0d5 100644 --- a/tests/Hal/Serializer/CollectionNormalizerTest.php +++ b/tests/Hal/Serializer/CollectionNormalizerTest.php @@ -28,7 +28,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class CollectionNormalizerTest extends TestCase { diff --git a/tests/Hal/Serializer/EntrypointNormalizerTest.php b/tests/Hal/Serializer/EntrypointNormalizerTest.php index c4a3bb23ead..cc031af7b40 100644 --- a/tests/Hal/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hal/Serializer/EntrypointNormalizerTest.php @@ -29,7 +29,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class EntrypointNormalizerTest extends TestCase { diff --git a/tests/Hal/Serializer/ItemNormalizerTest.php b/tests/Hal/Serializer/ItemNormalizerTest.php index c5e98d48f83..e73a8ac93b2 100644 --- a/tests/Hal/Serializer/ItemNormalizerTest.php +++ b/tests/Hal/Serializer/ItemNormalizerTest.php @@ -38,15 +38,11 @@ /** * @author Kévin Dunglas - * @group legacy */ class ItemNormalizerTest extends TestCase { use ProphecyTrait; - /** - * @group legacy - */ public function testDoesNotSupportDenormalization() { $this->expectException(LogicException::class); @@ -71,9 +67,6 @@ public function testDoesNotSupportDenormalization() $normalizer->denormalize(['foo'], 'Foo'); } - /** - * @group legacy - */ public function testSupportsNormalization() { $std = new \stdClass(); diff --git a/tests/Hydra/Serializer/CollectionNormalizerTest.php b/tests/Hydra/Serializer/CollectionNormalizerTest.php index 63cf4d47d90..456a387824d 100644 --- a/tests/Hydra/Serializer/CollectionNormalizerTest.php +++ b/tests/Hydra/Serializer/CollectionNormalizerTest.php @@ -33,7 +33,6 @@ /** * @author Amrouche Hamza * @author Kévin Dunglas - * @group legacy */ class CollectionNormalizerTest extends TestCase { diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index 282366f3ea0..056e075aaaa 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -15,14 +15,6 @@ use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\OperationMethodResolverInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\SubresourceMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface; -use ApiPlatform\Core\Tests\ProphecyTrait; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Hydra\Serializer\DocumentationNormalizer; use ApiPlatform\Metadata\ApiProperty; @@ -39,28 +31,18 @@ use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter; +use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\PropertyInfo\Type; /** * @author Amrouche Hamza - * @group legacy */ class DocumentationNormalizerTest extends TestCase { use ProphecyTrait; - public function testNormalizeLegacyResourceMetadata(): void - { - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummy')); - - $this->doTestNormalize(null, $resourceMetadataFactoryProphecy->reveal()); - } - public function testNormalize(): void { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); @@ -77,25 +59,10 @@ public function testNormalize(): void (new ApiResource())->withShortName('relatedDummy')->withOperations(new Operations(['get' => (new Get())->withShortName('relatedDummy')])), ])); - $this->doTestNormalize(null, $resourceMetadataFactoryProphecy->reveal()); + $this->doTestNormalize($resourceMetadataFactoryProphecy->reveal()); } - public function testLegacyNormalize(): void - { - $operationMethodResolverProphecy = $this->prophesize(OperationMethodResolverInterface::class); - $operationMethodResolverProphecy->getItemOperationMethod('dummy', 'get')->shouldBeCalled()->willReturn('GET'); - $operationMethodResolverProphecy->getItemOperationMethod('dummy', 'put')->shouldBeCalled()->willReturn('PUT'); - $operationMethodResolverProphecy->getCollectionOperationMethod('dummy', 'get')->shouldBeCalled()->willReturn('GET'); - $operationMethodResolverProphecy->getCollectionOperationMethod('dummy', 'post')->shouldBeCalled()->willReturn('POST'); - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); - $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummy')); - - $this->doTestNormalize($operationMethodResolverProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - } - - private function doTestNormalize(OperationMethodResolverInterface $operationMethodResolver = null, $resourceMetadataFactory = null): void + private function doTestNormalize($resourceMetadataFactory = null): void { $title = 'Test Api'; $desc = 'test ApiGerard'; @@ -105,53 +72,18 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create('dummy', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['name', 'description', 'nameConverted', 'relatedDummy', 'iri'])); - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $propertyMetadataFactoryProphecy = $this->prophesize(LegacyPropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( - (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( - (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withAttributes(['jsonld_context' => ['@type' => '@id']]) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( - (new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_STRING))->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy')))->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new PropertyMetadata())->withIri('https://schema.org/Dummy')); - } else { - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@type' => '@id']) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( - (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) - ); - $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy'))])->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); - $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withIris(['https://schema.org/Dummy'])); - } - - $subresourceOperationFactoryProphecy = null; - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $subresourceMetadata = new SubresourceMetadata('relatedDummy', false); - $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy')->shouldBeCalled()->willReturn((new PropertyMetadata())->withType(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy')))->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withSubresource($subresourceMetadata)); - $subresourceOperationFactoryProphecy = $this->prophesize(SubresourceOperationFactoryInterface::class); - $subresourceOperationFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn([ - 'api_dummies_subresource_get_related_dummy' => [ - 'property' => 'relatedDummy', - 'collection' => false, - 'resource_class' => 'relatedDummy', - 'shortNames' => ['relatedDummy'], - 'identifiers' => [ - 'id' => ['dummy', 'id', true], - ], - 'route_name' => 'api_dummies_subresource_get_related_dummy', - 'path' => '/dummies/{id}/related_dummy.{_format}', - ], - ]); - } + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('description')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)->withJsonldContext(['@type' => '@id']) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('name converted')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy'))])->withDescription('This is a name.')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); + $propertyMetadataFactoryProphecy->create('dummy', 'iri', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withIris(['https://schema.org/Dummy'])); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(true); @@ -167,9 +99,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - $operationMethodResolver, $urlGenerator->reveal(), - $subresourceOperationFactoryProphecy ? $subresourceOperationFactoryProphecy->reveal() : null, new CustomConverter() ); @@ -427,15 +357,6 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth 'hydra:entrypoint' => '/', ]; - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $expected['hydra:supportedClass'][1]['hydra:supportedProperty'][0]['hydra:property']['hydra:supportedOperation'][] = [ - '@type' => ['hydra:Operation', 'schema:FindAction'], - 'hydra:method' => 'GET', - 'hydra:title' => 'Retrieves a relatedDummy resource.', - 'rdfs:label' => 'Retrieves a relatedDummy resource.', - 'returns' => '#relatedDummy', - ]; - } $this->assertEquals($expected, $documentationNormalizer->normalize($documentation)); $this->assertTrue($documentationNormalizer->supportsNormalization($documentation, 'jsonld')); $this->assertFalse($documentationNormalizer->supportsNormalization($documentation, 'hal')); @@ -450,27 +371,19 @@ public function testNormalizeInputOutputClass() $documentation = new Documentation(new ResourceNameCollection(['dummy' => 'dummy']), $title, $desc, $version); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create('inputClass', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['a', 'b'])); - $propertyNameCollectionFactoryProphecy->create('outputClass', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['c', 'd'])); + $propertyNameCollectionFactoryProphecy->create('inputClass', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyNameCollection(['a', 'b'])); + $propertyNameCollectionFactoryProphecy->create('outputClass', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyNameCollection(['c', 'd'])); + $propertyNameCollectionFactoryProphecy->create('dummy', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyNameCollection([])); - $dummyMetadata = new ResourceMetadata( - 'dummy', - 'dummy', - '#dummy', - [ - 'get' => ['method' => 'GET'], - 'put' => ['method' => 'PUT', 'input' => ['class' => null]], - ], - [ - 'get' => ['method' => 'GET'], - 'post' => ['method' => 'POST', 'output' => ['class' => null]], - ], - [ - 'input' => ['class' => 'inputClass'], - 'output' => ['class' => 'outputClass'], - ]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('dummy', [ + (new ApiResource())->withShortName('dummy')->withDescription('dummy')->withTypes(['#dummy'])->withOperations(new Operations([ + 'get' => (new Get())->withTypes(['#dummy'])->withShortName('dummy')->withInput(['class' => 'inputClass'])->withOutput(['class' => 'outputClass']), + 'put' => (new Put())->withShortName('dummy')->withInput(['class' => null])->withOutput(['class' => 'outputClass']), + 'get_collection' => (new GetCollection())->withShortName('dummy')->withInput(['class' => 'inputClass'])->withOutput(['class' => 'outputClass']), + 'post' => (new Post())->withShortName('dummy')->withOutput(['class' => null])->withInput(['class' => 'inputClass']), + ])), + ])); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $propertyMetadataFactoryProphecy->create('inputClass', 'a', Argument::type('array'))->shouldBeCalled()->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withDescription('a')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true)); @@ -491,7 +404,6 @@ public function testNormalizeInputOutputClass() $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceClassResolverProphecy->reveal(), - null, $urlGenerator->reveal() ); diff --git a/tests/Hydra/Serializer/EntrypointNormalizerTest.php b/tests/Hydra/Serializer/EntrypointNormalizerTest.php index 5f9ff6ed083..50085ca8669 100644 --- a/tests/Hydra/Serializer/EntrypointNormalizerTest.php +++ b/tests/Hydra/Serializer/EntrypointNormalizerTest.php @@ -31,7 +31,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class EntrypointNormalizerTest extends TestCase { diff --git a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php index 774aea9b632..cd0c121ca42 100644 --- a/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php +++ b/tests/Hydra/Serializer/PartialCollectionViewNormalizerTest.php @@ -31,7 +31,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class PartialCollectionViewNormalizerTest extends TestCase { diff --git a/tests/JsonApi/Serializer/CollectionNormalizerTest.php b/tests/JsonApi/Serializer/CollectionNormalizerTest.php index c4d3c26c1d8..3bda3fb1cbc 100644 --- a/tests/JsonApi/Serializer/CollectionNormalizerTest.php +++ b/tests/JsonApi/Serializer/CollectionNormalizerTest.php @@ -29,7 +29,6 @@ /** * @author Amrouche Hamza - * @group legacy */ class CollectionNormalizerTest extends TestCase { diff --git a/tests/JsonApi/Serializer/ItemNormalizerTest.php b/tests/JsonApi/Serializer/ItemNormalizerTest.php index a2b335cf66e..215ef70212d 100644 --- a/tests/JsonApi/Serializer/ItemNormalizerTest.php +++ b/tests/JsonApi/Serializer/ItemNormalizerTest.php @@ -98,8 +98,9 @@ public function testNormalize(): void $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), + null, + [], $resourceMetadataCollectionFactoryProphecy->reveal(), - [] ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -141,8 +142,9 @@ public function testNormalizeCircularReference() $resourceClassResolverProphecy->reveal(), $this->prophesize(PropertyAccessorInterface::class)->reveal(), new ReservedAttributeNameConverter(), + null, + [], $resourceMetadataCollectionFactoryProphecy->reveal(), - [] ); $normalizer->setSerializer($this->prophesize(SerializerInterface::class)->reveal()); @@ -204,8 +206,9 @@ public function testNormalizeNonExistentProperty() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), + null, + [], $resourceMetadataCollectionFactoryProphecy->reveal(), - [] ); $normalizer->normalize($dummy, ItemNormalizer::FORMAT); @@ -290,8 +293,9 @@ public function testDenormalize() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), + null, + [], $resourceMetadataCollectionFactory->reveal(), - [] ); $normalizer->setSerializer($serializerProphecy->reveal()); @@ -308,10 +312,6 @@ public function testDenormalizeUpdateOperationNotAllowed() $this->prophesize(PropertyMetadataFactoryInterface::class)->reveal(), $this->prophesize(IriConverterInterface::class)->reveal(), $this->prophesize(ResourceClassResolverInterface::class)->reveal(), - null, - null, - $this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal(), - [] ); $normalizer->denormalize( @@ -376,8 +376,9 @@ public function testDenormalizeCollectionIsNotArray() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), + null, + [], $resourceMetadataCollectionFactory->reveal(), - [] ); $normalizer->denormalize($data, Dummy::class, ItemNormalizer::FORMAT); @@ -433,8 +434,9 @@ public function testDenormalizeCollectionWithInvalidKey() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), + null, + [], $resourceMetadataCollectionFactory->reveal(), - [] ); $normalizer->denormalize($data, Dummy::class, ItemNormalizer::FORMAT); @@ -486,8 +488,9 @@ public function testDenormalizeRelationIsNotResourceLinkage() $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal(), new ReservedAttributeNameConverter(), + null, + [], $resourceMetadataCollectionFactory->reveal(), - [] ); $normalizer->denormalize($data, Dummy::class, ItemNormalizer::FORMAT); diff --git a/tests/OpenApi/Model/SchemaTest.php b/tests/OpenApi/Model/SchemaTest.php deleted file mode 100644 index 49ded2f8597..00000000000 --- a/tests/OpenApi/Model/SchemaTest.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * 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\Tests\OpenApi\Model; - -use ApiPlatform\OpenApi\Model\Schema; -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; - -class SchemaTest extends TestCase -{ - use ExpectDeprecationTrait; - - /** - * @group legacy - */ - public function testLegacySchema() - { - $this->expectDeprecation('The nullable keyword has been removed from the Schema Object (null can be used as a type value). This behaviour will not be possible anymore in API Platform 3.0.'); - - $schema = new Schema(true); - } -} diff --git a/tests/Serializer/ItemNormalizerTest.php b/tests/Serializer/ItemNormalizerTest.php index 7cbf7ae306d..aaf801a4147 100644 --- a/tests/Serializer/ItemNormalizerTest.php +++ b/tests/Serializer/ItemNormalizerTest.php @@ -38,9 +38,6 @@ class ItemNormalizerTest extends TestCase use ExpectDeprecationTrait; use ProphecyTrait; - /** - * @group legacy - */ public function testSupportNormalization() { $std = new \stdClass(); diff --git a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php b/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php deleted file mode 100644 index a298918a51c..00000000000 --- a/tests/Symfony/Bundle/Action/SwaggerUiActionTest.php +++ /dev/null @@ -1,225 +0,0 @@ - - * - * 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\Tests\Symfony\Bundle\Action; - -use ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; -use ApiPlatform\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Generator\UrlGenerator; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Twig\Environment as TwigEnvironment; - -/** - * @author Kévin Dunglas - * @group legacy - */ -class SwaggerUiActionTest extends TestCase -{ - use ExpectDeprecationTrait; - use ProphecyTrait; - - public const SPEC = [ - 'paths' => [ - '/fs' => ['get' => ['operationId' => 'getFCollection']], - '/fs/{id}' => ['get' => ['operationId' => 'getFItem']], - ], - ]; - - /** - * @dataProvider getInvokeParameters - * @group legacy - * - * @param mixed $twigProphecy - */ - public function testInvoke(Request $request, $twigProphecy) - { - $this->expectDeprecation('The use of "ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction" is deprecated since API Platform 2.6, use "ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction" instead.'); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['Foo', 'Bar']))->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata('F'))->shouldBeCalled(); - - $normalizerProphecy = $this->prophesize(NormalizerInterface::class); - $normalizerProphecy->normalize(Argument::type(Documentation::class), 'json', Argument::type('array'))->willReturn(self::SPEC)->shouldBeCalled(); - - $urlGeneratorProphecy = $this->prophesize(UrlGenerator::class); - $urlGeneratorProphecy->generate('api_doc', ['format' => 'json'])->willReturn('/url')->shouldBeCalled(); - - $action = new SwaggerUiAction( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $normalizerProphecy->reveal(), - $twigProphecy->reveal(), - $urlGeneratorProphecy->reveal() - ); - $action($request); - } - - public function getInvokeParameters() - { - $twigCollectionProphecy = $this->prophesize(TwigEnvironment::class); - $twigCollectionProphecy->render('@ApiPlatform/SwaggerUi/index.html.twig', [ - 'title' => '', - 'description' => '', - 'formats' => [], - 'showWebby' => true, - 'swaggerUiEnabled' => false, - 'reDocEnabled' => false, - 'graphqlEnabled' => false, - 'graphiQlEnabled' => false, - 'graphQlPlaygroundEnabled' => false, - 'assetPackage' => null, - 'swagger_data' => [ - 'url' => '/url', - 'spec' => self::SPEC, - 'extraConfiguration' => [], - 'oauth' => [ - 'enabled' => false, - 'clientId' => '', - 'clientSecret' => '', - 'type' => '', - 'flow' => '', - 'tokenUrl' => '', - 'authorizationUrl' => '', - 'scopes' => [], - 'pkce' => false, - ], - 'shortName' => 'F', - 'operationId' => 'getFCollection', - 'id' => null, - 'queryParameters' => [], - 'path' => '/fs', - 'method' => 'get', - ], - ])->shouldBeCalled()->willReturn(''); - - $twigItemProphecy = $this->prophesize(TwigEnvironment::class); - $twigItemProphecy->render('@ApiPlatform/SwaggerUi/index.html.twig', [ - 'title' => '', - 'description' => '', - 'formats' => [], - 'swaggerUiEnabled' => false, - 'showWebby' => true, - 'reDocEnabled' => false, - 'graphqlEnabled' => false, - 'graphiQlEnabled' => false, - 'graphQlPlaygroundEnabled' => false, - 'assetPackage' => null, - 'swagger_data' => [ - 'url' => '/url', - 'spec' => self::SPEC, - 'extraConfiguration' => [], - 'oauth' => [ - 'enabled' => false, - 'clientId' => '', - 'clientSecret' => '', - 'type' => '', - 'flow' => '', - 'tokenUrl' => '', - 'authorizationUrl' => '', - 'scopes' => [], - 'pkce' => false, - ], - 'shortName' => 'F', - 'operationId' => 'getFItem', - 'id' => null, - 'queryParameters' => [], - 'path' => '/fs/{id}', - 'method' => 'get', - ], - ])->shouldBeCalled()->willReturn(''); - - return [ - [new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']), $twigCollectionProphecy], - [new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']), $twigItemProphecy], - [new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get'], [], [], ['REQUEST_URI' => '/docs', 'SCRIPT_FILENAME' => '/docs']), $twigItemProphecy], - ]; - } - - /** - * @dataProvider getDoNotRunCurrentRequestParameters - * @group legacy - */ - public function testDoNotRunCurrentRequest(Request $request) - { - $this->expectDeprecation('The use of "ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction" is deprecated since API Platform 2.6, use "ApiPlatform\Symfony\Bundle\SwaggerUi\SwaggerUiAction" instead.'); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['Foo', 'Bar']))->shouldBeCalled(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); - - $normalizerProphecy = $this->prophesize(NormalizerInterface::class); - $normalizerProphecy->normalize(Argument::type(Documentation::class), 'json', Argument::type('array'))->willReturn(self::SPEC)->shouldBeCalled(); - - $twigProphecy = $this->prophesize(TwigEnvironment::class); - $twigProphecy->render('@ApiPlatform/SwaggerUi/index.html.twig', [ - 'title' => '', - 'description' => '', - 'formats' => [], - 'showWebby' => true, - 'swaggerUiEnabled' => false, - 'reDocEnabled' => false, - 'graphqlEnabled' => false, - 'graphiQlEnabled' => false, - 'graphQlPlaygroundEnabled' => false, - 'assetPackage' => null, - 'swagger_data' => [ - 'url' => '/url', - 'spec' => self::SPEC, - 'extraConfiguration' => [], - 'oauth' => [ - 'enabled' => false, - 'clientId' => '', - 'clientSecret' => '', - 'type' => '', - 'flow' => '', - 'tokenUrl' => '', - 'authorizationUrl' => '', - 'scopes' => [], - 'pkce' => false, - ], - ], - ])->shouldBeCalled()->willReturn(''); - - $urlGeneratorProphecy = $this->prophesize(UrlGenerator::class); - $urlGeneratorProphecy->generate('api_doc', ['format' => 'json'])->willReturn('/url')->shouldBeCalled(); - - $action = new SwaggerUiAction( - $resourceNameCollectionFactoryProphecy->reveal(), - $resourceMetadataFactoryProphecy->reveal(), - $normalizerProphecy->reveal(), - $twigProphecy->reveal(), - $urlGeneratorProphecy->reveal() - ); - $action($request); - } - - public function getDoNotRunCurrentRequestParameters(): iterable - { - $nonSafeRequest = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post']); - $nonSafeRequest->setMethod('POST'); - yield [$nonSafeRequest]; - yield [new Request()]; - } -} diff --git a/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php b/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php index aab2eb2e472..743cca3cbbf 100644 --- a/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php +++ b/tests/Symfony/Bundle/ArgumentResolver/PayloadArgumentResolverTest.php @@ -186,7 +186,6 @@ public function provideUnsupportedArguments(): iterable /** * @requires PHP 8.0 * @dataProvider provideIntegrationCases - * @group legacy */ public function testIntegration(Request $request, callable $controller, array $expectedArguments): void { diff --git a/tests/Symfony/Bundle/Command/OpenApiCommandTest.php b/tests/Symfony/Bundle/Command/OpenApiCommandTest.php index b9aaec0f4e2..eb1176fe6a2 100644 --- a/tests/Symfony/Bundle/Command/OpenApiCommandTest.php +++ b/tests/Symfony/Bundle/Command/OpenApiCommandTest.php @@ -22,8 +22,6 @@ /** * @author Amrouche Hamza - * - * @group legacy */ class OpenApiCommandTest extends KernelTestCase { @@ -31,7 +29,6 @@ class OpenApiCommandTest extends KernelTestCase * @var ApplicationTester */ private $tester; - private $legacy; protected function setUp(): void { @@ -41,15 +38,9 @@ protected function setUp(): void $application->setCatchExceptions(false); $application->setAutoExit(false); - $this->legacy = static::$kernel->getContainer()->getParameter('api_platform.metadata_backward_compatibility_layer'); $this->tester = new ApplicationTester($application); } - /** - * TODO: change this once we support #[Resource]. - * - * @group legacy - */ public function testExecute() { $this->tester->run(['command' => 'api:openapi:export']); @@ -63,7 +54,7 @@ public function testExecuteWithYaml() $result = $this->tester->getDisplay(); $this->assertYaml($result); - $operationId = $this->legacy ? 'getDummyCarCollection' : 'api_dummy_cars_get_collection'; + $operationId = 'api_dummy_cars_get_collection'; $expected = <<assertStringContainsString(str_replace(\PHP_EOL, "\n", $expected), $result, 'nested object should be present.'); - $operationId = $this->legacy ? 'getDummyCarItem' : 'api_dummy_cars_get_item'; + $operationId = 'api_dummy_cars_id_get'; $expected = <<assertSame(['foo', 'bar'], $dataCollector->getAcceptableContentTypes()); $this->assertNull($dataCollector->getResourceClass()); $this->assertEmpty($dataCollector->getResourceMetadataCollection()->getValue()); - - $expected = ['context' => [], 'responses' => []]; - $this->assertSame($expected, $dataCollector->getCollectionDataProviders()); - $this->assertSame($expected, $dataCollector->getItemDataProviders()); - $this->assertSame($expected, $dataCollector->getSubresourceDataProviders()); - $this->assertSame(['responses' => []], $dataCollector->getDataPersisters()); } public function testNotCallingCollect() @@ -110,17 +94,11 @@ public function testNotCallingCollect() $this->assertSame([], $dataCollector->getCounters()); $this->assertNull($dataCollector->getResourceClass()); $this->assertNull($dataCollector->getResourceMetadataCollection()); - - $expected = ['context' => [], 'responses' => []]; - $this->assertSame($expected, $dataCollector->getCollectionDataProviders()); - $this->assertSame($expected, $dataCollector->getItemDataProviders()); - $this->assertSame($expected, $dataCollector->getSubresourceDataProviders()); - $this->assertSame(['responses' => []], $dataCollector->getDataPersisters()); } public function testWithResource() { - $this->apiResourceClassWillReturn(DummyEntity::class, ['_api_item_operation_name' => 'get', '_api_receive' => true]); + $this->apiResourceClassWillReturn(DummyEntity::class, ['_api_operation_name' => 'get', '_api_receive' => true]); $this->request->attributes = $this->attributes->reveal(); $this->filterLocator->has('foo')->willReturn(false)->shouldBeCalled(); @@ -129,11 +107,7 @@ public function testWithResource() $dataCollector = new RequestDataCollector( $this->metadataFactory->reveal(), - $this->filterLocator->reveal(), - new ChainCollectionDataProvider([]), - new ChainItemDataProvider([]), - new ChainSubresourceDataProvider([]), - new ChainDataPersister([]) + $this->filterLocator->reveal() ); $dataCollector->collect( @@ -144,8 +118,7 @@ public function testWithResource() $this->assertSame([ 'resource_class' => DummyEntity::class, 'has_composite_identifier' => false, - 'identifiers' => ['id' => [DummyEntity::class, 'id']], - 'item_operation_name' => 'get', + 'operation_name' => 'get', 'receive' => true, 'respond' => true, 'persist' => true, @@ -155,12 +128,6 @@ public function testWithResource() $this->assertSame([['foo' => null, 'a_filter' => \stdClass::class]], $dataCollector->getFilters()); $this->assertSame(['ignored_filters' => 1], $dataCollector->getCounters()); $this->assertInstanceOf(Data::class, $dataCollector->getResourceMetadataCollection()); - - $expected = ['context' => [], 'responses' => []]; - $this->assertSame($expected, $dataCollector->getCollectionDataProviders()); - $this->assertSame($expected, $dataCollector->getItemDataProviders()); - $this->assertSame($expected, $dataCollector->getSubresourceDataProviders()); - $this->assertSame(['responses' => []], $dataCollector->getDataPersisters()); } public function testWithResourceWithTraceables() @@ -170,50 +137,12 @@ public function testWithResourceWithTraceables() $dataCollector = new RequestDataCollector( $this->metadataFactory->reveal(), $this->filterLocator->reveal(), - $this->getUsedCollectionDataProvider(), - $this->getUsedItemDataProvider(), - $this->getUsedSubresourceDataProvider(), - $this->getUsedPersister() ); $dataCollector->collect( $this->request->reveal(), $this->response ); - - $dataProvider = $dataCollector->getCollectionDataProviders(); - foreach ($dataProvider['responses'] as $class => $response) { - $this->assertStringContainsString('@anonymous', $class); - - $this->assertTrue($response); - } - $context = $dataProvider['context']; - $this->assertInstanceOf(Data::class, $context); - $this->assertSame(['collection_context'], $context->getValue(true)); // @phpstan-ignore-line - - $dataProvider = $dataCollector->getItemDataProviders(); - foreach ($dataProvider['responses'] as $class => $response) { - $this->assertStringContainsString('@anonymous', $class); - $this->assertTrue($response); - } - $context = $dataProvider['context']; - $this->assertInstanceOf(Data::class, $context); - $this->assertSame(['item_context'], $context->getValue(true)); // @phpstan-ignore-line - - $dataProvider = $dataCollector->getSubresourceDataProviders(); - foreach ($dataProvider['responses'] as $class => $response) { - $this->assertStringContainsString('@anonymous', $class); - $this->assertTrue($response); - } - $context = $dataProvider['context']; - $this->assertInstanceOf(Data::class, $context); - $this->assertSame(['subresource_context'], $context->getValue(true)); // @phpstan-ignore-line - - $dataPersister = $dataCollector->getDataPersisters(); - foreach ($dataPersister['responses'] as $class => $response) { - $this->assertStringContainsString('@anonymous', $class); - $this->assertTrue($response); - } } public function testVersionCollection() @@ -223,10 +152,6 @@ public function testVersionCollection() $dataCollector = new RequestDataCollector( $this->metadataFactory->reveal(), $this->filterLocator->reveal(), - $this->getUsedCollectionDataProvider(), - $this->getUsedItemDataProvider(), - $this->getUsedSubresourceDataProvider(), - $this->getUsedPersister() ); $dataCollector->collect( @@ -242,7 +167,7 @@ public function testWithPreviousData() $data = new \stdClass(); $data->a = $data; - $this->apiResourceClassWillReturn(DummyEntity::class, ['_api_item_operation_name' => 'get', '_api_receive' => true, 'previous_data' => $data]); + $this->apiResourceClassWillReturn(DummyEntity::class, ['_api_operation_name' => 'get', '_api_receive' => true, 'previous_data' => $data]); $this->request->attributes = $this->attributes->reveal(); $this->filterLocator->has('foo')->willReturn(false); @@ -251,11 +176,7 @@ public function testWithPreviousData() $dataCollector = new RequestDataCollector( $this->metadataFactory->reveal(), - $this->filterLocator->reveal(), - new ChainCollectionDataProvider([]), - new ChainItemDataProvider([]), - new ChainSubresourceDataProvider([]), - new ChainDataPersister([]) + $this->filterLocator->reveal() ); $dataCollector->collect( @@ -284,76 +205,8 @@ private function apiResourceClassWillReturn($data, $context = []) ->create($data) ->shouldBeCalled() ->willReturn( - new ResourceMetadataCollection($data, [(new ApiResource())->withFilters(['foo', 'a_filter'])]) + new ResourceMetadataCollection($data, [(new ApiResource(operations: [new Get(filters: ['foo', 'a_filter'], uriVariables: ['id' => new Link(parameterName: 'id')])]))->withFilters(['foo', 'a_filter'])]) ); } } - - private function getUsedCollectionDataProvider(): TraceableChainCollectionDataProvider - { - $collectionDataProvider = new TraceableChainCollectionDataProvider(new ChainCollectionDataProvider([ - new class() implements CollectionDataProviderInterface { - public function getCollection(string $resourceClass, string $operationName = null) - { - return []; - } - }, - ])); - $collectionDataProvider->getCollection('', '', ['collection_context']); - - return $collectionDataProvider; - } - - private function getUsedItemDataProvider(): TraceableChainItemDataProvider - { - $itemDataProvider = new TraceableChainItemDataProvider(new ChainItemDataProvider([ - new class() implements ItemDataProviderInterface { - public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []) - { - return null; - } - }, - ])); - $itemDataProvider->getItem('', [], null, ['item_context']); - - return $itemDataProvider; - } - - private function getUsedSubresourceDataProvider(): TraceableChainSubresourceDataProvider - { - $subresourceDataProvider = new TraceableChainSubresourceDataProvider(new ChainSubresourceDataProvider([ - new class() implements SubresourceDataProviderInterface { - public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null) - { - return null; - } - }, - ])); - $subresourceDataProvider->getSubresource('', [], ['subresource_context']); - - return $subresourceDataProvider; - } - - private function getUsedPersister(): TraceableChainDataPersister - { - $dataPersister = new TraceableChainDataPersister(new ChainDataPersister([ - new class() implements DataPersisterInterface { - public function supports($data): bool - { - return true; - } - - public function persist($data) - { - } - - public function remove($data) - { - } - }, - ])); - $dataPersister->persist(''); - - return $dataPersister; - } } diff --git a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index b556217ce99..ae73d4b30a1 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -15,12 +15,6 @@ use ApiPlatform\Api\FilterInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; -use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface; -use ApiPlatform\Core\DataTransformer\DataTransformerInterface; use ApiPlatform\Doctrine\Common\State\PersistProcessor; use ApiPlatform\Doctrine\Common\State\RemoveProcessor; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; @@ -49,7 +43,6 @@ use ApiPlatform\Tests\Fixtures\TestBundle\TestBundle; use ApiPlatform\Tests\ProphecyTrait; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; -use Doctrine\Common\Annotations\Annotation; use Doctrine\ORM\OptimisticLockException; use phpDocumentor\Reflection\DocBlockFactoryInterface; use PHPUnit\Framework\TestCase; @@ -202,74 +195,66 @@ public function testCommonConfiguration(): void (new ApiPlatformExtension())->load($config, $this->container); $services = [ - // api.xml + 'api_platform.action.documentation', + 'api_platform.action.entrypoint', + 'api_platform.action.exception', + 'api_platform.action.not_found', + 'api_platform.action.placeholder', + 'api_platform.api.identifiers_extractor', + 'api_platform.filter_collection_factory', + 'api_platform.filter_locator', + 'api_platform.filters', + 'api_platform.identifier.uuid_normalizer', 'api_platform.negotiator', + 'api_platform.pagination', + 'api_platform.pagination_options', + 'api_platform.path_segment_name_generator.dash', + 'api_platform.path_segment_name_generator.underscore', + 'api_platform.ramsey_uuid.uri_variables.transformer.uuid', 'api_platform.resource_class_resolver', + 'api_platform.route_loader', 'api_platform.route_name_resolver', 'api_platform.route_name_resolver.cached', 'api_platform.router', 'api_platform.serializer.context_builder', 'api_platform.serializer.context_builder.filter', - 'api_platform.serializer.property_filter', 'api_platform.serializer.group_filter', - 'api_platform.serializer.normalizer.item', 'api_platform.serializer.mapping.class_metadata_factory', - 'api_platform.operation_path_resolver.custom', - 'api_platform.operation_path_resolver.generator', - 'api_platform.path_segment_name_generator.underscore', - 'api_platform.path_segment_name_generator.dash', - 'api_platform.action.placeholder', - 'api_platform.action.not_found', - 'api_platform.action.entrypoint', - 'api_platform.action.documentation', - 'api_platform.action.exception', - - // data_persister.xml - 'api_platform.data_persister', - - // data_provider.xml - 'api_platform.serializer_locator', - 'api_platform.pagination_options', - - // filter.xml - 'api_platform.filter_locator', - 'api_platform.filter_collection_factory', - 'api_platform.filters', - - // ramsey_uuid.xml - 'api_platform.identifier.uuid_normalizer', + 'api_platform.serializer.normalizer.item', + 'api_platform.serializer.property_filter', 'api_platform.serializer.uuid_denormalizer', - 'api_platform.ramsey_uuid.uri_variables.transformer.uuid', + 'api_platform.serializer_locator', + 'api_platform.symfony.iri_converter', + 'api_platform.uri_variables.converter', + 'api_platform.uri_variables.transformer.date_time', + 'api_platform.uri_variables.transformer.integer', ]; $aliases = [ - // api.xml - 'api_platform.serializer', - 'api_platform.property_accessor', - 'api_platform.property_info', + 'ApiPlatform\Action\NotFoundAction', + 'ApiPlatform\Api\IdentifiersExtractorInterface', + 'ApiPlatform\Api\IriConverterInterface', 'ApiPlatform\Api\ResourceClassResolverInterface', 'ApiPlatform\Api\UrlGeneratorInterface', - 'ApiPlatform\Serializer\SerializerContextBuilderInterface', - 'ApiPlatform\Serializer\Filter\PropertyFilter', 'ApiPlatform\Serializer\Filter\GroupFilter', - 'api_platform.operation_path_resolver', + 'ApiPlatform\Serializer\Filter\PropertyFilter', + 'ApiPlatform\Serializer\SerializerContextBuilderInterface', + 'ApiPlatform\State\Pagination\Pagination', + 'ApiPlatform\State\Pagination\PaginationOptions', + 'api_platform.action.delete_item', 'api_platform.action.get_collection', - 'api_platform.action.post_collection', 'api_platform.action.get_item', + 'api_platform.action.get_subresource', 'api_platform.action.patch_item', + 'api_platform.action.post_collection', 'api_platform.action.put_item', - 'api_platform.action.delete_item', - 'api_platform.action.get_subresource', - 'ApiPlatform\Action\NotFoundAction', - - // data_persister.xml - 'ApiPlatform\Core\DataPersister\DataPersisterInterface', - - // data_provider.xml - 'ApiPlatform\State\Pagination\PaginationOptions', - + 'api_platform.identifiers_extractor', + 'api_platform.iri_converter', 'api_platform.operation_path_resolver.default', 'api_platform.path_segment_name_generator', + 'api_platform.property_accessor', + 'api_platform.property_info', + 'api_platform.serializer', ]; $this->assertContainerHas($services, $aliases); @@ -283,6 +268,11 @@ public function testCommonConfiguration(): void $this->assertServiceHasTags('api_platform.identifier.uuid_normalizer', ['api_platform.identifier.denormalizer']); $this->assertServiceHasTags('api_platform.serializer.uuid_denormalizer', ['serializer.normalizer']); $this->assertServiceHasTags('api_platform.ramsey_uuid.uri_variables.transformer.uuid', ['api_platform.uri_variables.transformer']); + + // api.xml + $this->assertServiceHasTags('api_platform.route_loader', ['routing.loader']); + $this->assertServiceHasTags('api_platform.uri_variables.transformer.integer', ['api_platform.uri_variables.transformer']); + $this->assertServiceHasTags('api_platform.uri_variables.transformer.date_time', ['api_platform.uri_variables.transformer']); } public function testCommonConfigurationAbstractUid(): void @@ -333,141 +323,6 @@ public function testCommonConfigurationAliasNameConverter($nameConverterConfig, $this->assertSame($aliasIsExected, $this->container->hasAlias('api_platform.name_converter')); } - public function testCommonConfigurationWithMetadataBackwardCompatibilityLayer() - { - $config = self::DEFAULT_CONFIG; - $config['api_platform']['metadata_backward_compatibility_layer'] = true; - - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/api.xml - 'api_platform.operation_method_resolver', - 'api_platform.formats_provider', - 'api_platform.route_loader.legacy', - 'api_platform.operation_path_resolver.router', - 'api_platform.iri_converter.legacy', - 'api_platform.listener.request.add_format', - 'api_platform.listener.request.deserialize', - 'api_platform.listener.view.serialize', - 'api_platform.listener.view.respond', - 'api_platform.listener.exception.validation', - 'api_platform.listener.exception', - 'api_platform.identifier.integer', - 'api_platform.identifier.date_normalizer', - 'api_platform.operation_path_resolver.underscore', - 'api_platform.operation_path_resolver.dash', - 'api_platform.listener.view.write.legacy', - 'api_platform.listener.request.read.legacy', - 'api_platform.operation_path_resolver.router', - - // legacy/data_provider.xml - 'api_platform.item_data_provider', - 'api_platform.collection_data_provider', - 'api_platform.subresource_data_provider', - 'api_platform.pagination.legacy', - ]; - $aliases = [ - // legacy/api.xml - 'api_platform.operation_path_resolver', - 'api_platform.metadata.resource.metadata_collection_factory.retro_compatible', - 'ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface', - 'ApiPlatform\Core\Api\IriConverterInterface', - 'api_platform.operation_path_resolver.legacy', - - // legacy/data_provider.xml - 'ApiPlatform\Core\DataProvider\ItemDataProviderInterface', - 'ApiPlatform\Core\DataProvider\CollectionDataProviderInterface', - 'ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface', - 'ApiPlatform\Core\DataProvider\Pagination', - - // legacy/backward_compatibility.xml - 'api_platform.metadata.property.metadata_factory', - 'api_platform.metadata.resource.name_collection_factory', - 'api_platform.route_loader', - 'api_platform.iri_converter', - 'api_platform.identifiers_extractor', - 'api_platform.pagination', - 'api_platform.cache.metadata.property', - 'api_platform.openapi.factory', - ]; - - $this->assertContainerHas($services, $aliases); - - // legacy/api.xml - $this->assertServiceHasTags('api_platform.route_loader.legacy', ['routing.loader']); - $this->assertServiceHasTags('api_platform.listener.request.add_format', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.request.deserialize', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.view.serialize', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.view.respond', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.exception.validation', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.exception', ['kernel.event_listener', 'monolog.logger']); - $this->assertServiceHasTags('api_platform.identifier.integer', ['api_platform.identifier.denormalizer']); - $this->assertServiceHasTags('api_platform.identifier.date_normalizer', ['api_platform.identifier.denormalizer']); - $this->assertServiceHasTags('api_platform.listener.view.write.legacy', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.request.read.legacy', ['kernel.event_listener']); - } - - public function testCommonConfigurationWithoutMetadataBackwardCompatibilityLayer() - { - $config = self::DEFAULT_CONFIG; - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // v3/api.xml - 'api_platform.route_loader', - 'api_platform.symfony.iri_converter', - 'api_platform.api.identifiers_extractor', - 'api_platform.uri_variables.converter', - 'api_platform.uri_variables.transformer.integer', - 'api_platform.uri_variables.transformer.date_time', - - // legacy/data_provider.xml - 'api_platform.item_data_provider', - 'api_platform.collection_data_provider', - 'api_platform.subresource_data_provider', - 'api_platform.pagination.legacy', - - // v3/state.xml - 'api_platform.pagination.next', - - // v3/backward_compatibility.xml - 'api_platform.metadata.resource.metadata_collection_factory.legacy_resource_metadata', - 'api_platform.metadata.resource.metadata_collection_factory.legacy_subresource_metadata', - 'api_platform.listener.view.write.legacy', - 'api_platform.listener.request.read.legacy', - ]; - - $aliases = [ - // v3/api.xml - 'api_platform.iri_converter', - 'ApiPlatform\Api\IriConverterInterface', - 'api_platform.identifiers_extractor', - 'ApiPlatform\Api\IdentifiersExtractorInterface', - - // legacy/data_provider.xml - 'ApiPlatform\Core\DataProvider\ItemDataProviderInterface', - 'ApiPlatform\Core\DataProvider\CollectionDataProviderInterface', - 'ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface', - 'ApiPlatform\Core\DataProvider\Pagination', - - // v3/state.xml - 'ApiPlatform\State\Pagination\Pagination', - 'api_platform.pagination', - ]; - - $this->assertContainerHas($services, $aliases); - - // v3/api.xml - $this->assertServiceHasTags('api_platform.route_loader', ['routing.loader']); - $this->assertServiceHasTags('api_platform.uri_variables.transformer.integer', ['api_platform.uri_variables.transformer']); - $this->assertServiceHasTags('api_platform.uri_variables.transformer.date_time', ['api_platform.uri_variables.transformer']); - - // v3/backward_compatibility.xml - $this->assertServiceHasTags('api_platform.listener.view.write.legacy', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.request.read.legacy', ['kernel.event_listener']); - } - public function testMetadataConfiguration(): void { $config = self::DEFAULT_CONFIG; @@ -483,28 +338,6 @@ public function testMetadataConfiguration(): void 'api_platform.metadata.property.name_collection_factory.cached', 'api_platform.metadata.property.name_collection_factory.xml', - // legacy/metadata.xml - 'api_platform.metadata.resource.metadata_factory.input_output', - 'api_platform.metadata.resource.metadata_factory.short_name', - 'api_platform.metadata.resource.metadata_factory.operation', - 'api_platform.metadata.resource.metadata_factory.formats', - 'api_platform.metadata.resource.metadata_factory.cached', - 'api_platform.cache.metadata.resource.legacy', - 'api_platform.metadata.property.metadata_factory.property_info.legacy', - 'api_platform.metadata.property.metadata_factory.serializer.legacy', - 'api_platform.metadata.subresource.metadata_factory.annotation.legacy', - 'api_platform.metadata.property.metadata_factory.annotation.legacy', - 'api_platform.metadata.property.metadata_factory.cached.legacy', - 'api_platform.metadata.property.metadata_factory.default_property.legacy', - 'api_platform.metadata.extractor.xml.legacy', - 'api_platform.metadata.property.metadata_factory.xml.legacy', - 'api_platform.cache.metadata.property.legacy', - 'api_platform.metadata.resource.metadata_factory.xml', - 'api_platform.metadata.resource.name_collection_factory.xml.legacy', - 'api_platform.subresource_operation_factory.cached', - 'api_platform.cache.subresource_operation_factory', - 'api_platform.subresource_operation_factory', - // metadata/links.xml 'api_platform.metadata.resource.link_factory', @@ -559,12 +392,6 @@ public function testMetadataConfiguration(): void 'ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface', 'ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface', - // legacy/metadata.xml - 'ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface', - 'api_platform.metadata.property.metadata_factory.legacy', - 'ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface', - 'api_platform.metadata.resource.metadata_factory', - // metadata/property.xml 'api_platform.metadata.property.identifier_metadata_factory', @@ -588,11 +415,6 @@ public function testMetadataConfiguration(): void $this->assertContainerHas($services, $aliases); - // legacy/metadata.xml - $this->assertServiceHasTags('api_platform.cache.metadata.resource.legacy', ['cache.pool']); - $this->assertServiceHasTags('api_platform.cache.metadata.property.legacy', ['cache.pool']); - $this->assertServiceHasTags('api_platform.cache.subresource_operation_factory', ['cache.pool']); - // metadata/property.xml $this->assertServiceHasTags('api_platform.cache.metadata.property', ['cache.pool']); @@ -603,25 +425,6 @@ public function testMetadataConfiguration(): void $this->assertServiceHasTags('api_platform.cache.metadata.resource', ['cache.pool']); } - public function testMetadataConfigurationAnnotation() - { - if (!class_exists(Annotation::class)) { - $this->markTestSkipped('class Doctrine\Common\Annotations\Annotation does not exist'); - } - - $config = self::DEFAULT_CONFIG; - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/metadata_annotation.xml - 'api_platform.metadata.resource.name_collection_factory.annotation', - 'api_platform.metadata.resource.metadata_factory.annotation', - 'api_platform.metadata.resource.filter_metadata_factory.annotation', - ]; - - $this->assertContainerHas($services, []); - } - public function testMetadataConfigurationDocBlockFactoryInterface() { if (!class_exists(DocBlockFactoryInterface::class)) { @@ -632,9 +435,6 @@ public function testMetadataConfigurationDocBlockFactoryInterface() (new ApiPlatformExtension())->load($config, $this->container); $services = [ - // legacy/metadata_php_doc.xml - 'api_platform.metadata.resource.metadata_factory.php_doc', - // metadata/php_doc.xml 'api_platform.metadata.resource.metadata_collection_factory.php_doc', ]; @@ -642,26 +442,6 @@ public function testMetadataConfigurationDocBlockFactoryInterface() $this->assertContainerHas($services, []); } - public function testMetadataConfigurationYaml() - { - if (!class_exists(Yaml::class)) { - $this->markTestSkipped('class Symfony\Component\Yaml\Yaml does not exist'); - } - - $config = self::DEFAULT_CONFIG; - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/metadata_yaml.xml - 'api_platform.metadata.extractor.yaml.legacy', - 'api_platform.metadata.property.metadata_factory.yaml.legacy', - 'api_platform.metadata.resource.metadata_factory.yaml', - 'api_platform.metadata.resource.name_collection_factory.yaml.legacy', - ]; - - $this->assertContainerHas($services, []); - } - public function testSwaggerConfiguration() { $config = self::DEFAULT_CONFIG; @@ -681,14 +461,12 @@ public function testSwaggerConfiguration() 'api_platform.openapi.options', 'api_platform.openapi.command', 'api_platform.openapi.normalizer.api_gateway', + 'api_platform.openapi.factory', // swagger_ui.xml 'api_platform.swagger.listener.ui', 'api_platform.swagger_ui.context', - 'api_platform.swagger.action.ui', - - // v3/openapi.xml - 'api_platform.openapi.factory.next', + 'api_platform.swagger_ui.action', // v3/swagger_ui.xml 'api_platform.swagger_ui.action', @@ -708,7 +486,6 @@ public function testSwaggerConfiguration() // v3/openapi.xml 'ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface', - 'api_platform.openapi.factory', ]; $this->assertContainerHas($services, $aliases); @@ -725,36 +502,6 @@ public function testSwaggerConfiguration() $this->assertServiceHasTags('api_platform.swagger.listener.ui', ['kernel.event_listener']); } - public function testSwaggerConfigurationMetadataBackwardCompatibilityLayer() - { - $config = self::DEFAULT_CONFIG; - $config['api_platform']['enable_swagger'] = true; - $config['api_platform']['enable_swagger_ui'] = true; - $config['api_platform']['metadata_backward_compatibility_layer'] = true; - - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/swagger.xml - 'api_platform.swagger.normalizer.documentation', - 'api_platform.swagger.normalizer.api_gateway', - 'api_platform.swagger.command.swagger_command', - - // legacy/openapi.xml - 'api_platform.openapi.factory.legacy', - - // legacy/swagger_ui.xml - 'api_platform.swagger_ui.action', - ]; - - $this->assertContainerHas($services, []); - - // legacy/swagger.xml - $this->assertServiceHasTags('api_platform.swagger.normalizer.documentation', ['serializer.normalizer']); - $this->assertServiceHasTags('api_platform.swagger.normalizer.api_gateway', ['serializer.normalizer']); - $this->assertServiceHasTags('api_platform.swagger.command.swagger_command', ['console.command']); - } - public function testJsonApiConfiguration(): void { $config = self::DEFAULT_CONFIG; @@ -969,7 +716,7 @@ public function testGraphQlConfigurationMetadataBackwardCompatibilityLayer(): vo (new ApiPlatformExtension())->load($config, $this->container); $services = [ - // legacy/graphql.xml + // graphql.xml 'api_platform.graphql.executor', 'api_platform.graphql.resolver.factory.item', 'api_platform.graphql.resolver.factory.collection', @@ -1012,7 +759,7 @@ public function testGraphQlConfigurationMetadataBackwardCompatibilityLayer(): vo $this->assertContainerHas($services, []); - // legacy/graphql.xml + // graphql.xml $this->assertServiceHasTags('api_platform.graphql.query_resolver_locator', ['container.service_locator']); $this->assertServiceHasTags('api_platform.graphql.mutation_resolver_locator', ['container.service_locator']); $this->assertServiceHasTags('api_platform.graphql.iterable_type', ['api_platform.graphql.type']); @@ -1029,103 +776,6 @@ public function testGraphQlConfigurationMetadataBackwardCompatibilityLayer(): vo $this->assertServiceHasTags('api_platform.graphql.command.export_command', ['console.command']); } - /** - * @group legacy - */ - public function testLegacyPlainIdentifier() - { - // There's an issue with deprecations being different on lower versions - if (\PHP_VERSION_ID < 80000) { - $this->markTestSkipped(); - } - - $config = self::DEFAULT_CONFIG; - $config['api_platform']['allow_plain_identifiers'] = false; - $this->expectDeprecation('Since api-platform/core 2.7: The use of `allow_plain_identifiers` has been deprecated in 2.7 and will be removed in 3.0.'); - (new ApiPlatformExtension())->load($config, $this->container); - } - - /** - * @group legacy - */ - public function testLegacyPaginationCollectionOptions() - { - // There's an issue with deprecations being different on lower versions - if (\PHP_VERSION_ID < 80000) { - $this->markTestSkipped(); - } - - $config = self::DEFAULT_CONFIG; - - $config['api_platform']['collection']['pagination'] = [ - 'client_enabled' => false, - 'client_items_per_page' => false, - 'enabled' => true, - 'items_per_page' => 30, - 'maximum_items_per_page' => 30, - 'partial' => false, - 'client_partial' => false, - ]; - - $this->expectDeprecation('Since api-platform/core 2.6: The use of the `collection.pagination.enabled` has been deprecated in 2.6 and will be removed in 3.0. Use `defaults.pagination_enabled` instead.'); - $this->expectDeprecation('Since api-platform/core 2.6: The use of the `collection.pagination.partial` has been deprecated in 2.6 and will be removed in 3.0. Use `defaults.pagination_partial` instead.'); - $this->expectDeprecation('Since api-platform/core 2.6: The use of the `collection.pagination.client_enabled` has been deprecated in 2.6 and will be removed in 3.0. Use `defaults.pagination_client_enabled` instead.'); - $this->expectDeprecation('Since api-platform/core 2.6: The use of the `collection.pagination.client_items_per_page` has been deprecated in 2.6 and will be removed in 3.0. Use `defaults.pagination_client_items_per_page` instead.'); - $this->expectDeprecation('Since api-platform/core 2.6: The use of the `collection.pagination.client_partial` has been deprecated in 2.6 and will be removed in 3.0. Use `defaults.pagination_client_partial` instead.'); - $this->expectDeprecation('Since api-platform/core 2.6: The use of the `collection.pagination.items_per_page` has been deprecated in 2.6 and will be removed in 3.0. Use `defaults.pagination_items_per_page` instead.'); - $this->expectDeprecation('Since api-platform/core 2.6: The use of the `collection.pagination.maximum_items_per_page` has been deprecated in 2.6 and will be removed in 3.0. Use `defaults.pagination_maximum_items_per_page` instead.'); - - (new ApiPlatformExtension())->load($config, $this->container); - } - - public function testLegacyBundlesConfigurationFosUserBundle(): void - { - $config = self::DEFAULT_CONFIG; - $config['api_platform']['enable_fos_user'] = true; - (new ApiPlatformExtension())->load($config, $this->container); - - $bundles = $this->container->getParameter('kernel.bundles'); - - if (!isset($bundles['FOSUserBundle'])) { - $this->markTestSkipped('bundle FOSUserBundle does not exist'); - } - - $services = [ - // fos_user.xml - 'api_platform.fos_user.event_listener', - ]; - - $this->assertContainerHas($services, []); - - // fos_user.xml - $this->assertServiceHasTags('api_platform.fos_user.event_listener', ['kernel.event_listener']); - } - - public function testLegacyBundlesConfigurationNelmioApiDocBundle(): void - { - $config = self::DEFAULT_CONFIG; - $config['api_platform']['enable_nelmio_api_doc'] = true; - (new ApiPlatformExtension())->load($config, $this->container); - - $bundles = $this->container->getParameter('kernel.bundles'); - - if (!isset($bundles['NelmioApiDocBundle'])) { - $this->markTestSkipped('bundle NelmioApiDocBundle does not exist'); - } - - $services = [ - // nelmio_api_doc.xml - 'api_platform.nelmio_api_doc.annotations_provider', - 'api_platform.nelmio_api_doc.parser', - ]; - - $this->assertContainerHas($services, []); - - // nelmio_api_doc.xml - $this->assertServiceHasTags('api_platform.nelmio_api_doc.annotations_provider', ['nelmio_api_doc.extractor.annotations_provider']); - $this->assertServiceHasTags('api_platform.nelmio_api_doc.parser', ['nelmio_api_doc.extractor.parser']); - } - public function testDoctrineOrmConfiguration(): void { $config = self::DEFAULT_CONFIG; @@ -1147,16 +797,6 @@ public function testDoctrineOrmConfiguration(): void 'api_platform.doctrine.orm.query_extension.filter_eager_loading', 'api_platform.doctrine.orm.query_extension.pagination', 'api_platform.doctrine.orm.query_extension.order', - - // legacy/doctrine_orm.xml - 'api_platform.doctrine.orm.data_persister', - 'api_platform.doctrine.orm.collection_data_provider', - 'api_platform.doctrine.orm.item_data_provider', - 'api_platform.doctrine.orm.subresource_data_provider', - 'api_platform.doctrine.orm.default.collection_data_provider', - 'api_platform.doctrine.orm.default.item_data_provider', - 'api_platform.doctrine.orm.default.subresource_data_provider', - 'api_platform.doctrine.orm.metadata.property.metadata_factory.legacy', ]; $aliases = [ @@ -1186,12 +826,6 @@ public function testDoctrineOrmConfiguration(): void $this->assertServiceHasTags('api_platform.doctrine.orm.query_extension.filter_eager_loading', ['api_platform.doctrine.orm.query_extension.collection']); $this->assertServiceHasTags('api_platform.doctrine.orm.query_extension.pagination', ['api_platform.doctrine.orm.query_extension.collection']); $this->assertServiceHasTags('api_platform.doctrine.orm.query_extension.order', ['api_platform.doctrine.orm.query_extension.collection']); - - // legacy/doctrine_orm.xml - $this->assertServiceHasTags('api_platform.doctrine.orm.data_persister', ['api_platform.data_persister']); - $this->assertServiceHasTags('api_platform.doctrine.orm.default.collection_data_provider', ['api_platform.collection_data_provider']); - $this->assertServiceHasTags('api_platform.doctrine.orm.default.item_data_provider', ['api_platform.item_data_provider']); - $this->assertServiceHasTags('api_platform.doctrine.orm.default.subresource_data_provider', ['api_platform.subresource_data_provider']); } public function testDoctrineMongoDbOdmConfiguration(): void @@ -1220,15 +854,6 @@ public function testDoctrineMongoDbOdmConfiguration(): void 'api_platform.doctrine_mongodb.odm.aggregation_extension.pagination', 'api_platform.doctrine_mongodb.odm.aggregation_extension.order', 'api_platform.doctrine_mongodb.odm.metadata.property.identifier_metadata_factory', - - // legacy/doctrine_odm.xml - 'api_platform.doctrine_mongodb.odm.data_persister', - 'api_platform.doctrine_mongodb.odm.collection_data_provider', - 'api_platform.doctrine_mongodb.odm.item_data_provider', - 'api_platform.doctrine_mongodb.odm.subresource_data_provider', - 'api_platform.doctrine_mongodb.odm.default.collection_data_provider', - 'api_platform.doctrine_mongodb.odm.default.item_data_provider', - 'api_platform.doctrine_mongodb.odm.default.subresource_data_provider', ]; $aliases = [ @@ -1256,12 +881,6 @@ public function testDoctrineMongoDbOdmConfiguration(): void $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.aggregation_extension.filter', ['api_platform.doctrine_mongodb.odm.aggregation_extension.collection']); $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.aggregation_extension.pagination', ['api_platform.doctrine_mongodb.odm.aggregation_extension.collection']); $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.aggregation_extension.order', ['api_platform.doctrine_mongodb.odm.aggregation_extension.collection']); - - // legacy/doctrine_odm.xml - $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.data_persister', ['api_platform.data_persister']); - $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.default.collection_data_provider', ['api_platform.collection_data_provider']); - $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.default.item_data_provider', ['api_platform.item_data_provider']); - $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.default.subresource_data_provider', ['api_platform.subresource_data_provider']); } public function testHttpCacheConfiguration(): void @@ -1364,64 +983,6 @@ public function testValidatorConfiguration(): void $this->assertServiceHasTags('api_platform.listener.view.validate_query_parameters', ['kernel.event_listener']); } - public function testValidatorConfigurationMetadataBackwardCompatibilityLayer(): void - { - if (!interface_exists(ValidatorInterface::class)) { - $this->markTestSkipped('interface Symfony\Component\Validator\Validator\ValidatorInterface does not exist'); - } - - $config = self::DEFAULT_CONFIG; - $config['api_platform']['metadata_backward_compatibility_layer'] = true; - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/validator.xml - 'api_platform.metadata.property.metadata_factory.validator.legacy', - 'api_platform.metadata.property_schema.choice_restriction', - 'api_platform.metadata.property_schema.collection_restriction', - 'api_platform.metadata.property_schema.count_restriction', - 'api_platform.metadata.property_schema.greater_than_or_equal_restriction', - 'api_platform.metadata.property_schema.greater_than_restriction', - 'api_platform.metadata.property_schema.length_restriction', - 'api_platform.metadata.property_schema.less_than_or_equal_restriction', - 'api_platform.metadata.property_schema.less_than_restriction', - 'api_platform.metadata.property_schema.one_of_restriction', - 'api_platform.metadata.property_schema.range_restriction', - 'api_platform.metadata.property_schema.regex_restriction', - 'api_platform.metadata.property_schema.format_restriction', - 'api_platform.metadata.property_schema.unique_restriction', - 'api_platform.validator', - 'api_platform.listener.view.validate', - 'api_platform.validator.query_parameter_validator', - 'api_platform.listener.view.validate_query_parameters', - ]; - - $aliases = [ - // legacy/validator.xml - 'ApiPlatform\Validator\ValidatorInterface', - 'ApiPlatform\Core\Validator\ValidatorInterface', - ]; - - $this->assertContainerHas($services, $aliases); - - // legacy/validator.xml - $this->assertServiceHasTags('api_platform.metadata.property_schema.choice_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.collection_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.count_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.greater_than_or_equal_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.greater_than_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.length_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.less_than_or_equal_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.less_than_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.one_of_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.range_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.regex_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.format_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.metadata.property_schema.unique_restriction', ['api_platform.metadata.property_schema_restriction']); - $this->assertServiceHasTags('api_platform.listener.view.validate', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.view.validate_query_parameters', ['kernel.event_listener']); - } - public function testDataCollectorConfiguration(): void { $config = self::DEFAULT_CONFIG; @@ -1450,31 +1011,6 @@ public function testDataCollectorConfiguration(): void $this->assertServiceHasTags('debug.api_platform.debug_resource.command', ['console.command']); } - public function testDataCollectorConfigurationMetadataBackwardCompatibilityLayer(): void - { - $config = self::DEFAULT_CONFIG; - $config['api_platform']['enable_profiler'] = true; - $config['api_platform']['metadata_backward_compatibility_layer'] = true; - $this->container->setParameter('kernel.debug', true); - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/data_collector.xml - 'api_platform.data_collector.request', - - // legacy/debug.xml - 'debug.api_platform.collection_data_provider', - 'debug.api_platform.item_data_provider', - 'debug.api_platform.subresource_data_provider', - 'debug.api_platform.data_persister', - ]; - - $this->assertContainerHas($services, []); - - // legacy/data_collector.xml - $this->assertServiceHasTags('api_platform.data_collector.request', ['data_collector']); - } - public function testMercureConfiguration(): void { $config = self::DEFAULT_CONFIG; @@ -1520,45 +1056,6 @@ public function testMercureConfiguration(): void ], $this->container->getDefinition('api_platform.doctrine_mongodb.odm.listener.mercure.publish')->getTag('doctrine_mongodb.odm.event_listener')); } - public function testMercureConfigurationMetadataBackwardCompatibilityLayer(): void - { - $config = self::DEFAULT_CONFIG; - $config['api_platform']['mercure']['enabled'] = true; - $config['api_platform']['doctrine']['enabled'] = true; - $config['api_platform']['doctrine_mongodb_odm']['enabled'] = true; - $config['api_platform']['graphql']['enabled'] = true; - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/doctrine_orm_mercure_publisher.xml - 'api_platform.doctrine.orm.listener.mercure.publish', - - // legacy/doctrine_odm_mercure_publisher.xml - 'api_platform.doctrine_mongodb.odm.listener.mercure.publish', - - // legacy/graphql_mercure.xml - 'api_platform.graphql.subscription.mercure_iri_generator', - ]; - - $this->assertContainerHas($services, []); - - // legacy/doctrine_orm_mercure_publisher.xml - $this->assertServiceHasTags('api_platform.doctrine.orm.listener.mercure.publish', ['doctrine.event_listener']); - - // legacy/doctrine_odm_mercure_publisher.xml - $this->assertServiceHasTags('api_platform.doctrine_mongodb.odm.listener.mercure.publish', ['doctrine_mongodb.odm.event_listener']); - - $this->assertSame([ - ['event' => 'onFlush'], - ['event' => 'postFlush'], - ], $this->container->getDefinition('api_platform.doctrine.orm.listener.mercure.publish')->getTag('doctrine.event_listener')); - - $this->assertSame([ - ['event' => 'onFlush'], - ['event' => 'postFlush'], - ], $this->container->getDefinition('api_platform.doctrine_mongodb.odm.listener.mercure.publish')->getTag('doctrine_mongodb.odm.event_listener')); - } - public function testMessengerConfiguration(): void { $config = self::DEFAULT_CONFIG; @@ -1566,8 +1063,6 @@ public function testMessengerConfiguration(): void $services = [ // messenger.xml - 'api_platform.messenger.data_persister', - 'api_platform.messenger.data_transformer', MessengerProcessor::class, ]; @@ -1578,9 +1073,6 @@ public function testMessengerConfiguration(): void $this->assertContainerHas($services, $aliases); - // messenger.xml - $this->assertServiceHasTags('api_platform.messenger.data_persister', ['api_platform.data_persister']); - $this->assertServiceHasTags('api_platform.messenger.data_transformer', ['api_platform.data_transformer']); $this->assertServiceHasTags(MessengerProcessor::class, ['api_platform.state_processor']); } @@ -1601,12 +1093,9 @@ public function testElasticsearchConfiguration(): void 'api_platform.elasticsearch.metadata.document.metadata_factory.attribute', 'api_platform.elasticsearch.metadata.document.metadata_factory.cat', 'api_platform.elasticsearch.metadata.document.metadata_factory.cached', - 'api_platform.elasticsearch.identifier_extractor', 'api_platform.elasticsearch.name_converter.inner_fields', 'api_platform.elasticsearch.normalizer.item', 'api_platform.elasticsearch.normalizer.document', - 'api_platform.elasticsearch.item_data_provider', - 'api_platform.elasticsearch.collection_data_provider', 'api_platform.elasticsearch.request_body_search_extension.filter', 'api_platform.elasticsearch.request_body_search_extension.constant_score_filter', 'api_platform.elasticsearch.request_body_search_extension.sort_filter', @@ -1621,7 +1110,6 @@ public function testElasticsearchConfiguration(): void // elasticsearch.xml 'api_platform.elasticsearch.metadata.document.metadata_factory', 'ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface', - 'ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface', 'ApiPlatform\Elasticsearch\Filter\TermFilter', 'ApiPlatform\Elasticsearch\Filter\MatchFilter', 'ApiPlatform\Elasticsearch\Filter\OrderFilter', @@ -1678,21 +1166,10 @@ public function testSecurityConfiguration(): void public function testMakerConfiguration(): void { + $this->markTestSkipped('Missing maker feature'); $config = self::DEFAULT_CONFIG; $config['api_platform']['maker']['enabled'] = true; (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // maker.xml - 'api_platform.maker.command.data_provider', - 'api_platform.maker.command.data_persister', - ]; - - $this->assertContainerHas($services, []); - - // maker.xml - $this->assertServiceHasTags('api_platform.maker.command.data_provider', ['maker.command']); - $this->assertServiceHasTags('api_platform.maker.command.data_persister', ['maker.command']); } public function testArgumentResolverConfiguration(): void @@ -1711,125 +1188,6 @@ public function testArgumentResolverConfiguration(): void $this->assertServiceHasTags('api_platform.argument_resolver.payload', ['controller.argument_value_resolver']); } - public function testLegacyServices(): void - { - $config = self::DEFAULT_CONFIG; - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/identifiers.xml - 'api_platform.identifiers_extractor.legacy', - 'api_platform.identifiers_extractor.cached', - 'api_platform.cache.identifiers_extractor', - 'api_platform.identifier.converter', - - // symfony.xml - 'api_platform.listener.request.add_format', - 'api_platform.listener.request.read', - 'api_platform.listener.view.write', - 'api_platform.listener.request.deserialize', - 'api_platform.listener.view.serialize', - 'api_platform.listener.view.respond', - 'api_platform.listener.exception.validation', - 'api_platform.listener.exception', - 'api_platform.cache_warmer.cache_pool_clearer', - ]; - - $aliases = [ - // legacy/identifiers.xml - 'ApiPlatform\Core\Api\IdentifiersExtractorInterface', - ]; - - $this->assertContainerHas($services, $aliases); - - // legacy/identifiers.xml - $this->assertServiceHasTags('api_platform.cache.identifiers_extractor', ['cache.pool']); - - // symfony.xml - $this->assertServiceHasTags('api_platform.listener.request.add_format', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.request.read', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.view.write', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.request.deserialize', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.view.serialize', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.view.respond', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.exception.validation', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.exception', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.exception', ['monolog.logger']); - $this->assertServiceHasTags('api_platform.cache_warmer.cache_pool_clearer', ['kernel.cache_warmer']); - } - - public function testLegacyServicesMetadataBackwardCompatibilityLayer(): void - { - $config = self::DEFAULT_CONFIG; - $config['api_platform']['metadata_backward_compatibility_layer'] = true; - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/api.xml - 'api_platform.operation_method_resolver', - 'api_platform.formats_provider', - 'api_platform.route_loader.legacy', - 'api_platform.operation_path_resolver.router', - 'api_platform.iri_converter.legacy', - 'api_platform.listener.request.add_format', - 'api_platform.listener.request.deserialize', - 'api_platform.listener.view.serialize', - 'api_platform.listener.view.respond', - 'api_platform.listener.exception.validation', - 'api_platform.listener.exception', - 'api_platform.identifier.integer', - 'api_platform.identifier.date_normalizer', - 'api_platform.operation_path_resolver.underscore', - 'api_platform.operation_path_resolver.dash', - 'api_platform.listener.view.write.legacy', - 'api_platform.listener.request.read.legacy', - 'api_platform.operation_path_resolver.router', - ]; - - $aliases = [ - // legacy/api.xml - 'api_platform.operation_path_resolver', - 'api_platform.metadata.resource.metadata_collection_factory.retro_compatible', - 'ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface', - 'ApiPlatform\Core\Api\IriConverterInterface', - 'api_platform.operation_path_resolver.legacy', - ]; - - $this->assertContainerHas($services, $aliases); - - // legacy/api.xml - $this->assertServiceHasTags('api_platform.route_loader.legacy', ['routing.loader']); - $this->assertServiceHasTags('api_platform.listener.request.add_format', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.request.deserialize', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.view.serialize', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.view.respond', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.exception.validation', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.exception', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.exception', ['monolog.logger']); - $this->assertServiceHasTags('api_platform.identifier.integer', ['api_platform.identifier.denormalizer']); - $this->assertServiceHasTags('api_platform.identifier.date_normalizer', ['api_platform.identifier.denormalizer']); - $this->assertServiceHasTags('api_platform.listener.view.write.legacy', ['kernel.event_listener']); - $this->assertServiceHasTags('api_platform.listener.request.read.legacy', ['kernel.event_listener']); - - $this->assertNotContainerHasService('api_platform.doctrine_mongodb.odm.metadata.property.identifier_metadata_factory'); - } - - public function testRectorConfiguration(): void - { - $config = self::DEFAULT_CONFIG; - $config['api_platform']['metadata_backward_compatibility_layer'] = true; - (new ApiPlatformExtension())->load($config, $this->container); - - $services = [ - // legacy/upgrade.xml - 'api_platform.upgrade.subresource_transformer', - 'api_platform.upgrade_resource.command', - ]; - - $this->assertContainerHas($services, []); - $this->assertServiceHasTags('api_platform.upgrade_resource.command', ['console.command']); - } - public function testAutoConfigurableInterfaces(): void { $config = self::DEFAULT_CONFIG; @@ -1837,12 +1195,6 @@ public function testAutoConfigurableInterfaces(): void $interfaces = [ FilterInterface::class => 'api_platform.filter', - DataPersisterInterface::class => 'api_platform.data_persister', - ItemDataProviderInterface::class => 'api_platform.item_data_provider', - CollectionDataProviderInterface::class => 'api_platform.collection_data_provider', - SubresourceDataProviderInterface::class => 'api_platform.subresource_data_provider', - DataTransformerInterface::class => 'api_platform.data_transformer', - DataTransformerInitializerInterface::class => 'api_platform.data_transformer', ValidationGroupsGeneratorInterface::class => 'api_platform.validation_groups_generator', PropertySchemaRestrictionMetadataInterface::class => 'api_platform.metadata.property_schema_restriction', QueryItemResolverInterface::class => 'api_platform.graphql.query_resolver', diff --git a/tests/Symfony/Bundle/DependencyInjection/ConfigurationTest.php b/tests/Symfony/Bundle/DependencyInjection/ConfigurationTest.php index c31752fbc6c..ff2260608cb 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ConfigurationTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ConfigurationTest.php @@ -234,42 +234,6 @@ private function runDefaultConfigTests(array $doctrineIntegrationsToLoad = ['orm ], $config); } - /** - * @group legacy - * @expectedDeprecation Using a string "HTTP_INTERNAL_SERVER_ERROR" as a constant of the "Symfony\Component\HttpFoundation\Response" class is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3. Use the Symfony's custom YAML extension for PHP constants instead (i.e. "!php/const Symfony\Component\HttpFoundation\Response::HTTP_INTERNAL_SERVER_ERROR"). - */ - public function testLegacyExceptionToStatusConfig() - { - $config = $this->processor->processConfiguration($this->configuration, [ - 'api_platform' => [ - 'exception_to_status' => [ - \InvalidArgumentException::class => Response::HTTP_BAD_REQUEST, - \RuntimeException::class => 'HTTP_INTERNAL_SERVER_ERROR', - ], - ], - ]); - - $this->assertTrue(isset($config['exception_to_status'])); - $this->assertSame([ - \InvalidArgumentException::class => Response::HTTP_BAD_REQUEST, - \RuntimeException::class => Response::HTTP_INTERNAL_SERVER_ERROR, - ], $config['exception_to_status']); - } - - /** - * @group legacy - */ - public function testLegacyDefaultOperationPathResolver() - { - $config = $this->processor->processConfiguration($this->configuration, [ - 'api_platform' => [ - 'default_operation_path_resolver' => 'api_platform.operation_path_resolver.dash', - ], - ]); - - $this->assertTrue(isset($config['default_operation_path_resolver'])); - } - public function invalidHttpStatusCodeProvider() { return [ diff --git a/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php b/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php index 596be0e4524..9384b858f99 100644 --- a/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php +++ b/tests/Symfony/Bundle/SwaggerUi/SwaggerUiActionTest.php @@ -13,9 +13,12 @@ namespace ApiPlatform\Tests\Symfony\Bundle\SwaggerUi; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Documentation\DocumentationInterface; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Model\Info; use ApiPlatform\OpenApi\Model\Paths; @@ -33,7 +36,6 @@ /** * @author Antoine Bluchet - * @group legacy */ class SwaggerUiActionTest extends TestCase { @@ -53,8 +55,13 @@ class SwaggerUiActionTest extends TestCase */ public function testInvoke(Request $request, $twigProphecy) { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata('F'))->shouldBeCalled(); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'getFItem' => new Get(shortName: 'F', name: 'getFItem'), + 'getFCollection' => new GetCollection(shortName: 'F', name: 'getFCollection'), + ])), + ])); $normalizerProphecy = $this->prophesize(NormalizerInterface::class); $normalizerProphecy->normalize(Argument::type(DocumentationInterface::class), 'json', Argument::type('array'))->willReturn(self::SPEC)->shouldBeCalled(); @@ -88,7 +95,7 @@ public function getInvokeParameters() 'showWebby' => true, 'swaggerUiEnabled' => false, 'reDocEnabled' => false, - 'graphqlEnabled' => false, + 'graphQlEnabled' => false, 'graphiQlEnabled' => false, 'graphQlPlaygroundEnabled' => false, 'assetPackage' => null, @@ -124,7 +131,7 @@ public function getInvokeParameters() 'swaggerUiEnabled' => false, 'showWebby' => true, 'reDocEnabled' => false, - 'graphqlEnabled' => false, + 'graphQlEnabled' => false, 'graphiQlEnabled' => false, 'graphQlPlaygroundEnabled' => false, 'assetPackage' => null, @@ -153,9 +160,9 @@ public function getInvokeParameters() ])->shouldBeCalled()->willReturn(''); return [ - [new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']), $twigCollectionProphecy], - [new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']), $twigItemProphecy], - [new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get'], [], [], ['REQUEST_URI' => '/docs', 'SCRIPT_FILENAME' => '/docs']), $twigItemProphecy], + [new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'getFCollection']), $twigCollectionProphecy], + [new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'getFItem']), $twigItemProphecy], + [new Request([], [], ['_api_resource_class' => 'Foo'], [], [], ['REQUEST_URI' => '/docs', 'SCRIPT_FILENAME' => '/docs']), $twigItemProphecy], ]; } @@ -164,8 +171,12 @@ public function getInvokeParameters() */ public function testDoNotRunCurrentRequest(Request $request) { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(), + ])), + ])); $normalizerProphecy = $this->prophesize(NormalizerInterface::class); $normalizerProphecy->normalize(Argument::type(DocumentationInterface::class), 'json', Argument::type('array'))->willReturn(self::SPEC)->shouldBeCalled(); @@ -178,7 +189,7 @@ public function testDoNotRunCurrentRequest(Request $request) 'showWebby' => true, 'swaggerUiEnabled' => false, 'reDocEnabled' => false, - 'graphqlEnabled' => false, + 'graphQlEnabled' => false, 'graphiQlEnabled' => false, 'graphQlPlaygroundEnabled' => false, 'assetPackage' => null, @@ -221,7 +232,7 @@ public function testDoNotRunCurrentRequest(Request $request) public function getDoNotRunCurrentRequestParameters(): iterable { - $nonSafeRequest = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post']); + $nonSafeRequest = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'post']); $nonSafeRequest->setMethod('POST'); yield [$nonSafeRequest]; yield [new Request()]; diff --git a/tests/Symfony/Bundle/Test/ApiTestCaseTest.php b/tests/Symfony/Bundle/Test/ApiTestCaseTest.php index 5bda0a07223..8c3fc8a323b 100644 --- a/tests/Symfony/Bundle/Test/ApiTestCaseTest.php +++ b/tests/Symfony/Bundle/Test/ApiTestCaseTest.php @@ -23,9 +23,6 @@ use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Runner\Version; -/** - * @group legacy - */ class ApiTestCaseTest extends ApiTestCase { public function testAssertJsonContains(): void diff --git a/tests/Symfony/Bundle/Test/ClientTest.php b/tests/Symfony/Bundle/Test/ClientTest.php index 76abd6405d1..3f9942ad205 100644 --- a/tests/Symfony/Bundle/Test/ClientTest.php +++ b/tests/Symfony/Bundle/Test/ClientTest.php @@ -22,9 +22,6 @@ use Symfony\Component\HttpKernel\Profiler\Profile; use Symfony\Component\Security\Core\User\InMemoryUser; -/** - * @group legacy - */ class ClientTest extends ApiTestCase { protected function setUp(): void diff --git a/tests/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php b/tests/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php index 26dec830679..dd1d59d61df 100644 --- a/tests/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php +++ b/tests/Symfony/Bundle/Twig/ApiPlatformProfilerPanelTest.php @@ -22,7 +22,6 @@ /** * @author Anthony GRASSIOT - * @group legacy */ class ApiPlatformProfilerPanelTest extends WebTestCase { @@ -32,14 +31,12 @@ class ApiPlatformProfilerPanelTest extends WebTestCase private $manager; private $schemaTool; private $env; - private $legacy; protected function setUp(): void { parent::setUp(); $kernel = self::bootKernel(); $this->env = $kernel->getEnvironment(); - $this->legacy = $kernel->getContainer()->getParameter('api_platform.metadata_backward_compatibility_layer'); /** @var ManagerRegistry $doctrine */ $doctrine = $kernel->getContainer()->get('doctrine'); @@ -65,12 +62,6 @@ protected function tearDown(): void public function testDebugBarContentNotResourceClass() { - if ($this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - $client = static::createClient(); $client->enableProfiler(); // Using html to get default Swagger UI @@ -90,12 +81,6 @@ public function testDebugBarContentNotResourceClass() public function testDebugBarContent() { - if ($this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - $client = static::createClient(); $client->enableProfiler(); $client->request('GET', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json']); @@ -114,12 +99,6 @@ public function testDebugBarContent() public function testProfilerGeneralLayoutNotResourceClass() { - if ($this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - $client = static::createClient(); $client->enableProfiler(); // Using html to get default Swagger UI @@ -141,12 +120,6 @@ public function testProfilerGeneralLayoutNotResourceClass() public function testProfilerGeneralLayout() { - if ($this->legacy) { - $this->markTestSkipped('Legacy test.'); - - return; - } - $client = static::createClient(); $client->enableProfiler(); $client->request('GET', '/dummies', [], [], ['HTTP_ACCEPT' => 'application/ld+json']); diff --git a/tests/Symfony/EventListener/AddFormatListenerTest.php b/tests/Symfony/EventListener/AddFormatListenerTest.php index 98d325089d1..5c8a034256f 100644 --- a/tests/Symfony/EventListener/AddFormatListenerTest.php +++ b/tests/Symfony/EventListener/AddFormatListenerTest.php @@ -13,14 +13,14 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Symfony\EventListener\AddFormatListener; use ApiPlatform\Tests\ProphecyTrait; use Negotiation\Negotiator; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; @@ -29,7 +29,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class AddFormatListenerTest extends TestCase { @@ -44,9 +43,7 @@ public function testNoResourceClass() $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $formatsProviderProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); + $listener = new AddFormatListener(new Negotiator()); $listener->onKernelRequest($event); $this->assertNull($request->getRequestFormat(null)); @@ -54,36 +51,21 @@ public function testNoResourceClass() public function testSupportedRequestFormat(): void { - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => ['xml' => ['text/xml']]]] - )); - - $this->doTestSupportedRequestFormat($resourceMetadataFactory->reveal()); - } - - public function testLegacySupportedRequestFormat(): void - { - $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); - $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['xml' => ['text/xml']]); - - $this->doTestSupportedRequestFormat($formatsProviderProphecy->reveal()); - } - - private function doTestSupportedRequestFormat($resourceMetadataFactory): void - { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: ['xml' => ['text/xml']]), + ])), + ])); + + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->setRequestFormat('xml'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactory); + $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); $this->assertSame('xml', $request->getRequestFormat()); @@ -99,9 +81,7 @@ public function testRespondFlag(): void $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - - $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactory->reveal(), ['xml' => ['text/xml']]); + $listener = new AddFormatListener(new Negotiator(), null, ['xml' => ['text/xml']]); $listener->onKernelRequest($event); $this->assertSame('xml', $request->getRequestFormat()); @@ -113,23 +93,21 @@ public function testUnsupportedRequestFormat(): void $this->expectException(NotAcceptableHttpException::class); $this->expectExceptionMessage('Requested format "text/xml" is not supported. Supported MIME types are "application/json".'); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->setRequestFormat('xml'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => ['json' => ['application/json']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: ['json' => ['application/json']]), + ])), + ])); - $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactory->reveal()); + $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); $this->assertSame('json', $request->getRequestFormat()); @@ -137,26 +115,24 @@ public function testUnsupportedRequestFormat(): void public function testSupportedAcceptHeader(): void { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->headers->set('Accept', 'text/html, application/xhtml+xml, application/xml, application/json;q=0.9, */*;q=0.8'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => [ - 'binary' => ['application/octet-stream'], - 'json' => ['application/json'], ], - ]] - )); - - $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactory->reveal()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'binary' => ['application/octet-stream'], + 'json' => ['application/json'], + ]), + ])), + ])); + + $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); $this->assertSame('json', $request->getRequestFormat()); @@ -164,23 +140,23 @@ public function testSupportedAcceptHeader(): void public function testSupportedAcceptHeaderSymfonyBuiltInFormat(): void { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->headers->set('Accept', 'application/json'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => ['jsonld' => ['application/ld+json', 'application/json']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'jsonld' => ['application/ld+json', 'application/json'], + ]), + ])), + ])); - $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactory->reveal()); + $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); $this->assertSame('jsonld', $request->getRequestFormat()); @@ -188,23 +164,24 @@ public function testSupportedAcceptHeaderSymfonyBuiltInFormat(): void public function testAcceptAllHeader(): void { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->headers->set('Accept', 'text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactory->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => ['binary' => ['application/octet-stream'], 'json' => ['application/json']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'binary' => ['application/octet-stream'], + 'json' => ['application/json'], + ]), + ])), + ])); - $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactory->reveal()); + $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); $this->assertSame('binary', $request->getRequestFormat()); @@ -216,21 +193,22 @@ public function testUnsupportedAcceptHeader(): void $this->expectException(NotAcceptableHttpException::class); $this->expectExceptionMessage('Requested format "text/html, application/xhtml+xml, application/xml;q=0.9" is not supported. Supported MIME types are "application/octet-stream", "application/json".'); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->headers->set('Accept', 'text/html, application/xhtml+xml, application/xml;q=0.9'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => ['binary' => ['application/octet-stream'], 'json' => ['application/json']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'binary' => ['application/octet-stream'], + 'json' => ['application/json'], + ]), + ])), + ])); $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); @@ -241,21 +219,21 @@ public function testUnsupportedAcceptHeaderSymfonyBuiltInFormat(): void $this->expectException(NotAcceptableHttpException::class); $this->expectExceptionMessage('Requested format "text/xml" is not supported. Supported MIME types are "application/json".'); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->headers->set('Accept', 'text/xml'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => ['json' => ['application/json']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'json' => ['application/json'], + ]), + ])), + ])); $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); @@ -266,21 +244,21 @@ public function testInvalidAcceptHeader(): void $this->expectException(NotAcceptableHttpException::class); $this->expectExceptionMessage('Requested format "invalid" is not supported. Supported MIME types are "application/json".'); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->headers->set('Accept', 'invalid'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => ['json' => ['application/json']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'json' => ['application/json'], + ]), + ])), + ])); $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); @@ -288,7 +266,7 @@ public function testInvalidAcceptHeader(): void public function testAcceptHeaderTakePrecedenceOverRequestFormat(): void { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->headers->set('Accept', 'application/json'); $request->setRequestFormat('xml'); @@ -296,14 +274,15 @@ public function testAcceptHeaderTakePrecedenceOverRequestFormat(): void $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - [], - ['get' => ['output_formats' => ['xml' => ['application/xml'], 'json' => ['application/json']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'xml' => ['application/xml'], + 'json' => ['application/json'], + ]), + ])), + ])); $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); @@ -316,21 +295,20 @@ public function testInvalidRouteFormat(): void $this->expectException(NotFoundHttpException::class); $this->expectExceptionMessage('Format "invalid" is not supported'); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_format' => 'invalid']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_format' => 'invalid']); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); $event = $eventProphecy->reveal(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - null, - ['formats' => ['json' => ['application/json']]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'json' => ['application/json'], + ]), + ])), + ])); $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); @@ -338,21 +316,21 @@ public function testInvalidRouteFormat(): void public function testResourceClassSupportedRequestFormat(): void { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->setRequestFormat('csv'); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['get' => ['output_formats' => ['csv' => ['text/csv']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(outputFormats: [ + 'csv' => ['text/csv'], + ]), + ])), + ])); $listener = new AddFormatListener(new Negotiator(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelRequest($event); @@ -360,22 +338,4 @@ public function testResourceClassSupportedRequestFormat(): void $this->assertSame('csv', $request->getRequestFormat()); $this->assertSame('text/csv', $request->getMimeType($request->getRequestFormat())); } - - /** - * @group legacy - * @dataProvider legacyFormatsProvider - * - * @param mixed $formatsProvider - */ - public function testLegacyFormatsParameter($formatsProvider): void - { - $this->expectDeprecation('Since api-plaform/core 2.5: Passing an array or an instance of "ApiPlatform\Core\Api\FormatsProviderInterface" as 2nd parameter of the constructor of "ApiPlatform\Symfony\EventListener\AddFormatListener" is deprecated since API Platform 2.5, pass an instance of "ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface" instead'); - new AddFormatListener(new Negotiator(), $formatsProvider); - } - - public function legacyFormatsProvider(): iterable - { - yield [['xml' => ['text/xml']]]; - yield [$this->prophesize(FormatsProviderInterface::class)->reveal()]; - } } diff --git a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php index 77bc4c24f2c..7d67b52a9e8 100644 --- a/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Symfony/EventListener/AddLinkHeaderListenerTest.php @@ -13,8 +13,10 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Symfony\EventListener\AddLinkHeaderListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; @@ -33,7 +35,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class AddLinkHeaderListenerTest extends TestCase { @@ -44,12 +45,14 @@ class AddLinkHeaderListenerTest extends TestCase */ public function testAddLinkHeader(string $expected, Request $request) { - if (!class_exists(Discovery::class)) { - $this->markTestSkipped(); - } - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => ['hub' => 'managed']])); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'get' => new Get(mercure: [ + 'hub' => 'managed', + ]), + ])), + ])); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), @@ -64,39 +67,16 @@ public function testAddLinkHeader(string $expected, Request $request) $mercure = new HubRegistry($defaultHub, ['default' => $defaultHub, 'managed' => $managedHub]); $discovery = new Discovery($mercure); - $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), $discovery); + $listener = new AddLinkHeaderListener($discovery, $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelResponse($event); - - $this->assertSame($expected, (new HttpHeaderSerializer())->serialize($request->attributes->get('_links')->getLinks())); - } - - /** - * @dataProvider addProvider - * @group legacy - */ - public function testAddLinkHeaderWithLegacySignature(string $expected, Request $request) - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => true])); - - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - new Response() - ); - - $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://managed.mercure.rocks/.well-known/mercure'); - $listener->onKernelResponse($event); - $this->assertSame($expected, (new HttpHeaderSerializer())->serialize($request->attributes->get('_links')->getLinks())); } public function addProvider(): array { return [ - ['; rel="mercure"', new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get'])], - ['; rel="http://www.w3.org/ns/hydra/core#apiDocumentation",; rel="mercure"', new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_links' => new GenericLinkProvider([new Link('http://www.w3.org/ns/hydra/core#apiDocumentation', 'http://example.com/docs')])])], + ['; rel="mercure"', new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get'])], + ['; rel="http://www.w3.org/ns/hydra/core#apiDocumentation",; rel="mercure"', new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get', '_links' => new GenericLinkProvider([new Link('http://www.w3.org/ns/hydra/core#apiDocumentation', 'http://example.com/docs')])])], ]; } @@ -105,12 +85,10 @@ public function addProvider(): array */ public function testDoNotAddHeader(Request $request) { - if (!class_exists(Discovery::class)) { - $this->markTestSkipped(); - } - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [new Get()])), + ])); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), @@ -121,52 +99,7 @@ public function testDoNotAddHeader(Request $request) $defaultHub = new Hub('https://internal/.well-known/mercure', new StaticTokenProvider('xxx'), null, 'https://external/.well-known/mercure'); $registry = new HubRegistry($defaultHub, ['default' => $defaultHub]); - $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), new Discovery($registry)); - $listener->onKernelResponse($event); - - $this->assertNull($request->attributes->get('_links')); - } - - /** - * @dataProvider doNotAddProvider - * - * @group legacy - */ - public function testDoNotAddHeaderLegacy(Request $request) - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - new Response() - ); - - $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://external/.well-known/mercure'); - $listener->onKernelResponse($event); - - $this->assertNull($request->attributes->get('_links')); - } - - /** - * @dataProvider doNotAddProvider - * @group legacy - */ - public function testDoNotAddHeaderWithLegacySignature(Request $request) - { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - new Response() - ); - - $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); + $listener = new AddLinkHeaderListener(new Discovery($registry), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelResponse($event); $this->assertNull($request->attributes->get('_links')); @@ -182,10 +115,6 @@ public function doNotAddProvider(): array public function testSkipWhenPreflightRequest(): void { - if (!class_exists(Discovery::class)) { - $this->markTestSkipped(); - } - $request = new Request(); $request->setMethod('OPTIONS'); $request->headers->set('Access-Control-Request-Method', 'POST'); @@ -197,34 +126,9 @@ public function testSkipWhenPreflightRequest(): void new Response() ); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $defaultHub = new Hub('https://internal/.well-known/mercure', new StaticTokenProvider('xxx'), null, 'https://external/.well-known/mercure'); $registry = new HubRegistry($defaultHub, ['default' => $defaultHub]); - $listener = new AddLinkHeaderListener($resourceMetadataFactory->reveal(), new Discovery($registry)); - $listener->onKernelResponse($event); - - $this->assertFalse($request->attributes->has('_links')); - } - - /** - * @group legacy - */ - public function testSkipWhenPreflightRequestWithLegacySignature(): void - { - $request = new Request(); - $request->setMethod('OPTIONS'); - $request->headers->set('Access-Control-Request-Method', 'POST'); - - $event = new ResponseEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, - new Response() - ); - - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); - $listener = new AddLinkHeaderListener($resourceMetadataFactory->reveal(), 'http://example.com/.well-known/mercure'); + $listener = new AddLinkHeaderListener(new Discovery($registry)); $listener->onKernelResponse($event); $this->assertFalse($request->attributes->has('_links')); diff --git a/tests/Symfony/EventListener/DenyAccessListenerTest.php b/tests/Symfony/EventListener/DenyAccessListenerTest.php index 5050a51649c..a7bfb7e2ab0 100644 --- a/tests/Symfony/EventListener/DenyAccessListenerTest.php +++ b/tests/Symfony/EventListener/DenyAccessListenerTest.php @@ -13,30 +13,21 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Symfony\EventListener\DenyAccessListener; -use ApiPlatform\Symfony\Security\ExpressionLanguage; use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface; -use ApiPlatform\Tests\Fixtures\Serializable; use ApiPlatform\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; -use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Symfony\Component\Security\Core\Role\RoleHierarchy; -use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; -use Symfony\Component\Security\Core\User\UserInterface; /** * @author Kévin Dunglas - * @group legacy */ class DenyAccessListenerTest extends TestCase { @@ -50,8 +41,8 @@ public function testNoResourceClass() $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create()->shouldNotBeCalled(); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldNotBeCalled(); $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $listener = $this->getListener($resourceMetadataFactory); @@ -60,16 +51,18 @@ public function testNoResourceClass() public function testNoIsGrantedAttribute() { - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(), + ])), + ])); $listener = $this->getListener($resourceMetadataFactoryProphecy->reveal()); $listener->onSecurity($event); @@ -78,16 +71,18 @@ public function testNoIsGrantedAttribute() public function testIsGranted() { $data = new \stdClass(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', 'data' => $data]); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', 'data' => $data]); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(security: 'is_granted("ROLE_ADMIN")'), + ])), + ])); $resourceAccessCheckerProphecy = $this->prophesize(ResourceAccessCheckerInterface::class); $resourceAccessCheckerProphecy->isGranted('Foo', 'is_granted("ROLE_ADMIN")', Argument::type('array'))->willReturn(true)->shouldBeCalled(); @@ -96,44 +91,22 @@ public function testIsGranted() $listener->onSecurity($event); } - /** - * @group legacy - */ - public function testAccessControl() - { - $data = new \stdClass(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', 'data' => $data]); - - $eventProphecy = $this->prophesize(RequestEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $event = $eventProphecy->reveal(); - - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'is_granted("ROLE_ADMIN")']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $resourceAccessCheckerProphecy = $this->prophesize(ResourceAccessCheckerInterface::class); - $resourceAccessCheckerProphecy->isGranted('Foo', 'is_granted("ROLE_ADMIN")', Argument::type('array'))->willReturn(true)->shouldBeCalled(); - - $listener = $this->getListener($resourceMetadataFactoryProphecy->reveal(), $resourceAccessCheckerProphecy->reveal()); - $listener->onKernelRequest($event); - } - public function testIsNotGranted() { $this->expectException(AccessDeniedException::class); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(security: 'is_granted("ROLE_ADMIN")'), + ])), + ])); $resourceAccessCheckerProphecy = $this->prophesize(ResourceAccessCheckerInterface::class); $resourceAccessCheckerProphecy->isGranted('Foo', 'is_granted("ROLE_ADMIN")', Argument::type('array'))->willReturn(false)->shouldBeCalled(); @@ -147,16 +120,18 @@ public function testSecurityMessage() $this->expectException(AccessDeniedException::class); $this->expectExceptionMessage('You are not admin.'); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")', 'security_message' => 'You are not admin.']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'get' => new Get(security: 'is_granted("ROLE_ADMIN")', securityMessage: 'You are not admin.'), + ])), + ])); $resourceAccessCheckerProphecy = $this->prophesize(ResourceAccessCheckerInterface::class); $resourceAccessCheckerProphecy->isGranted('Foo', 'is_granted("ROLE_ADMIN")', Argument::type('array'))->willReturn(false)->shouldBeCalled(); @@ -165,161 +140,27 @@ public function testSecurityMessage() $listener->onSecurity($event); } - /** - * @group legacy - */ - public function testIsGrantedLegacy() - { - $data = new \stdClass(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', 'data' => $data]); - - $eventProphecy = $this->prophesize(RequestEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $event = $eventProphecy->reveal(); - - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $expressionLanguageProphecy = $this->prophesize(ExpressionLanguage::class); - $expressionLanguageProphecy->evaluate('is_granted("ROLE_ADMIN")', Argument::type('array'))->willReturn(true)->shouldBeCalled(); - - $listener = $this->getLegacyListener($resourceMetadataFactoryProphecy->reveal(), $expressionLanguageProphecy->reveal()); - $listener->onSecurity($event); - } - - /** - * @group legacy - */ - public function testIsNotGrantedLegacy() - { - $this->expectException(AccessDeniedException::class); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - - $eventProphecy = $this->prophesize(RequestEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $event = $eventProphecy->reveal(); - - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $expressionLanguageProphecy = $this->prophesize(ExpressionLanguage::class); - $expressionLanguageProphecy->evaluate('is_granted("ROLE_ADMIN")', Argument::type('array'))->willReturn(false)->shouldBeCalled(); - - $listener = $this->getLegacyListener($resourceMetadataFactoryProphecy->reveal(), $expressionLanguageProphecy->reveal()); - $listener->onSecurity($event); - } - - /** - * @group legacy - */ public function testSecurityComponentNotAvailable() { - $this->expectException(\LogicException::class); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); $event = $eventProphecy->reveal(); - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldNotBeCalled(); $listener = new DenyAccessListener($resourceMetadataFactoryProphecy->reveal()); $listener->onSecurity($event); } - /** - * @group legacy - */ - public function testExpressionLanguageNotInstalled() - { - $this->expectException(\LogicException::class); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - - $eventProphecy = $this->prophesize(RequestEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $event = $eventProphecy->reveal(); - - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $authenticationTrustResolverProphecy = $this->prophesize(AuthenticationTrustResolverInterface::class); - $tokenStorageProphecy = $this->prophesize(TokenStorageInterface::class); - $tokenStorageProphecy->getToken()->willReturn($this->prophesize(TokenInterface::class)->willImplement(Serializable::class)->reveal()); - - $listener = new DenyAccessListener($resourceMetadataFactoryProphecy->reveal(), null, $authenticationTrustResolverProphecy->reveal(), null, $tokenStorageProphecy->reveal()); - $listener->onSecurity($event); - } - - /** - * @group legacy - */ - public function testNotBehindAFirewall() - { - $this->expectException(\LogicException::class); - - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - - $eventProphecy = $this->prophesize(RequestEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $event = $eventProphecy->reveal(); - - $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['security' => 'is_granted("ROLE_ADMIN")']); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); - - $authenticationTrustResolverProphecy = $this->prophesize(AuthenticationTrustResolverInterface::class); - $tokenStorageProphecy = $this->prophesize(TokenStorageInterface::class); - - $listener = new DenyAccessListener($resourceMetadataFactoryProphecy->reveal(), null, $authenticationTrustResolverProphecy->reveal(), null, $tokenStorageProphecy->reveal()); - $listener->onSecurity($event); - } - - private function getListener(ResourceMetadataFactoryInterface $resourceMetadataFactory, ResourceAccessCheckerInterface $resourceAccessChecker = null) + private function getListener(ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, ResourceAccessCheckerInterface $resourceAccessChecker = null) { if (null === $resourceAccessChecker) { $resourceAccessChecker = $this->prophesize(ResourceAccessCheckerInterface::class)->reveal(); } - return new DenyAccessListener($resourceMetadataFactory, $resourceAccessChecker); - } - - private function getLegacyListener(ResourceMetadataFactoryInterface $resourceMetadataFactory, ExpressionLanguage $expressionLanguage) - { - $authenticationTrustResolverProphecy = $this->prophesize(AuthenticationTrustResolverInterface::class); - - $roleHierarchyInterfaceProphecy = $this->prophesize(RoleHierarchyInterface::class); - $roleHierarchyInterfaceProphecy->{method_exists(RoleHierarchy::class, 'getReachableRoleNames') ? 'getReachableRoleNames' : 'getReachableRoles'}(Argument::type('array'))->willReturn([]); - - $userProphecy = $this->prophesize(UserInterface::class); - $tokenProphecy = $this->prophesize(AbstractToken::class); - $tokenProphecy->getUser()->willReturn($userProphecy->reveal()); - $tokenProphecy->{method_exists(AbstractToken::class, 'getRoleNames') ? 'getRoleNames' : 'getRoles'}()->willReturn([]); - - $tokenStorageProphecy = $this->prophesize(TokenStorageInterface::class); - $tokenStorageProphecy->getToken()->willReturn($tokenProphecy)->shouldBeCalled(); - - $authorizationCheckerInterface = $this->prophesize(AuthorizationCheckerInterface::class); - - return new DenyAccessListener( - $resourceMetadataFactory, - $expressionLanguage, - $authenticationTrustResolverProphecy->reveal(), - $roleHierarchyInterfaceProphecy->reveal(), - $tokenStorageProphecy->reveal(), - $authorizationCheckerInterface->reveal() - ); + return new DenyAccessListener($resourceMetadataCollectionFactory, $resourceAccessChecker); } } diff --git a/tests/Symfony/EventListener/DeserializeListenerTest.php b/tests/Symfony/EventListener/DeserializeListenerTest.php index 89fff6ef9d3..1f522508454 100644 --- a/tests/Symfony/EventListener/DeserializeListenerTest.php +++ b/tests/Symfony/EventListener/DeserializeListenerTest.php @@ -13,9 +13,11 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\DeserializeListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; @@ -30,7 +32,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class DeserializeListenerTest extends TestCase { @@ -52,7 +53,7 @@ public function testDoNotCallWhenRequestMethodIsSafe(): void $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), false, Argument::type('array'))->shouldNotBeCalled(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactory->create()->shouldNotBeCalled(); $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $resourceMetadataFactory->reveal()); @@ -73,7 +74,7 @@ public function testDoNotCallWhenRequestNotManaged(): void $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), false, Argument::type('array'))->shouldNotBeCalled(); - $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactory->create()->shouldNotBeCalled(); $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $resourceMetadataFactory->reveal()); @@ -87,10 +88,10 @@ public function testDoNotDeserializeWhenReceiveFlagIsFalse(): void $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); $resourceMetadataFactoryProphecy->create()->shouldNotBeCalled(); - $request = new Request([], [], ['data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post', '_api_receive' => false]); + $request = new Request([], [], ['data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_operation_name' => 'post', '_api_receive' => false]); $request->setMethod('POST'); $eventProphecy = $this->prophesize(RequestEvent::class); @@ -107,16 +108,14 @@ public function testDoNotDeserializeWhenDisabledInOperationAttribute(): void $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ - 'post' => [ - 'deserialize' => false, - ], - ]); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'post' => new Post(deserialize: false), + ])), + ])); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); - - $request = new Request([], [], ['data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); + $request = new Request([], [], ['data' => new Dummy(), '_api_resource_class' => Dummy::class, '_api_operation_name' => 'post']); $request->setMethod('POST'); $eventProphecy = $this->prophesize(RequestEvent::class); @@ -131,35 +130,23 @@ public function testDoNotDeserializeWhenDisabledInOperationAttribute(): void */ public function testDeserialize(string $method, bool $populateObject): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - ['put' => ['input_formats' => self::FORMATS]], - ['post' => ['input_formats' => self::FORMATS]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'put' => new Put(inputFormats: self::FORMATS), + 'post' => new Post(inputFormats: self::FORMATS), + ])), + ])); $this->doTestDeserialize($method, $populateObject, $resourceMetadataFactoryProphecy->reveal()); } - /** - * @dataProvider methodProvider - */ - public function legacyTestDeserialize(string $method, bool $populateObject): void - { - $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); - $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->willReturn(self::FORMATS)->shouldBeCalled(); - - $this->doTestDeserialize($method, $populateObject, $formatsProviderProphecy->reveal()); - } - private function doTestDeserialize(string $method, bool $populateObject, $resourceMetadataFactory): void { $result = $populateObject ? new \stdClass() : null; $eventProphecy = $this->prophesize(RequestEvent::class); - $request = new Request([], [], ['data' => $result, '_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); + $request = new Request([], [], ['data' => $result, '_api_resource_class' => 'Foo', '_api_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod($method); $request->headers->set('Content-Type', 'application/json'); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); @@ -183,35 +170,22 @@ private function doTestDeserialize(string $method, bool $populateObject, $resour */ public function testDeserializeResourceClassSupportedFormat(string $method, bool $populateObject): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['post' => ['input_formats' => self::FORMATS]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'post' => new Post(inputFormats: self::FORMATS), + ])), + ])); $this->doTestDeserializeResourceClassSupportedFormat($method, $populateObject, $resourceMetadataFactoryProphecy->reveal()); } - /** - * @dataProvider methodProvider - */ - public function testLegacyDeserializeResourceClassSupportedFormat(string $method, bool $populateObject): void - { - $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); - $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->willReturn(self::FORMATS)->shouldBeCalled(); - - $this->doTestDeserializeResourceClassSupportedFormat($method, $populateObject, $formatsProviderProphecy->reveal()); - } - private function doTestDeserializeResourceClassSupportedFormat(string $method, bool $populateObject, $resourceMetadataFactory): void { $result = $populateObject ? new \stdClass() : null; $eventProphecy = $this->prophesize(RequestEvent::class); - $request = new Request([], [], ['data' => $result, '_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); + $request = new Request([], [], ['data' => $result, '_api_resource_class' => 'Foo', '_api_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod($method); $request->headers->set('Content-Type', 'application/json'); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); @@ -239,31 +213,21 @@ public function methodProvider(): iterable public function testContentNegotiation(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['post' => ['input_formats' => ['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'post' => new Post(inputFormats: ['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']]), + ])), + ])); $this->doTestContentNegotiation($resourceMetadataFactoryProphecy->reveal()); } - public function testLegacyContentNegotiation(): void - { - $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); - $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->willReturn(['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']])->shouldBeCalled(); - - $this->doTestContentNegotiation($formatsProviderProphecy->reveal()); - } - private function doTestContentNegotiation($resourceMetadataFactory): void { $eventProphecy = $this->prophesize(RequestEvent::class); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod('POST'); $request->headers->set('Content-Type', 'text/xml'); $request->setFormat('xml', 'text/xml'); // Workaround to avoid weird behaviors @@ -292,7 +256,7 @@ public function testNotSupportedContentType(): void $eventProphecy = $this->prophesize(RequestEvent::class); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod('POST'); $request->headers->set('Content-Type', 'application/rdf+xml'); $request->setRequestFormat('xml'); @@ -304,14 +268,12 @@ public function testNotSupportedContentType(): void $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), false, Argument::type('array'))->willReturn(['input' => ['class' => 'Foo'], 'output' => ['class' => 'Foo']]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata( - null, - null, - null, - null, - ['post' => ['input_formats' => ['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']]]] - )); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'post' => new Post(inputFormats: ['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']]), + ])), + ])); $listener = new DeserializeListener( $serializerProphecy->reveal(), @@ -328,7 +290,7 @@ public function testNoContentType(): void $eventProphecy = $this->prophesize(RequestEvent::class); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod('POST'); $request->setRequestFormat('unknown'); $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); @@ -339,8 +301,12 @@ public function testNoContentType(): void $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), false, Argument::type('array'))->willReturn(['input' => ['class' => 'Foo'], 'output' => ['class' => 'Foo']]); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, null, null, ['formats' => ['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']]])); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('Foo')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('Foo', [ + (new ApiResource(operations: [ + 'post' => new Post(formats: ['jsonld' => ['application/ld+json'], 'xml' => ['text/xml']]), + ])), + ])); $listener = new DeserializeListener( $serializerProphecy->reveal(), @@ -349,21 +315,4 @@ public function testNoContentType(): void ); $listener->onKernelRequest($eventProphecy->reveal()); } - - /** - * @group legacy - * @expectedDeprecation Passing an array or an instance of "ApiPlatform\Core\Api\FormatsProviderInterface" as 3rd parameter of the constructor of "ApiPlatform\Symfony\EventListener\DeserializeListener" is deprecated since API Platform 2.5, pass an instance of "ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface" instead - */ - public function testLegacyFormatsParameter(): void - { - $serializerProphecy = $this->prophesize(SerializerInterface::class); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - - new DeserializeListener( - $serializerProphecy->reveal(), - $serializerContextBuilderProphecy->reveal(), - self::FORMATS - ); - } } diff --git a/tests/Symfony/EventListener/ExceptionListenerTest.php b/tests/Symfony/EventListener/ExceptionListenerTest.php index 0df0d81f307..4c284e3c110 100644 --- a/tests/Symfony/EventListener/ExceptionListenerTest.php +++ b/tests/Symfony/EventListener/ExceptionListenerTest.php @@ -48,7 +48,7 @@ public function testOnKernelException(Request $request) public function getRequest() { return [ - [new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get'])], + [new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get'])], [new Request([], [], ['_api_respond' => true])], ]; } diff --git a/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php index 0843ea0e342..94085ab732c 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformFieldsetsParametersListenerTest.php @@ -13,8 +13,10 @@ namespace ApiPlatform\Tests\Symfony\EventListener\JsonApi; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Symfony\EventListener\JsonApi\TransformFieldsetsParametersListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; @@ -22,9 +24,6 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; -/** - * @group legacy - */ class TransformFieldsetsParametersListenerTest extends TestCase { use ProphecyTrait; @@ -33,8 +32,12 @@ class TransformFieldsetsParametersListenerTest extends TestCase protected function setUp(): void { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata('dummy')); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'get' => new Get(shortName: 'dummy'), + ])), + ])); $this->listener = new TransformFieldsetsParametersListener($resourceMetadataFactoryProphecy->reveal()); } diff --git a/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php b/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php index c8d74aea832..125d5ef710e 100644 --- a/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php +++ b/tests/Symfony/EventListener/JsonApi/TransformPaginationParametersListenerTest.php @@ -82,7 +82,7 @@ public function testOnKernelRequest() $filters = ['size' => 5, 'number' => 3, 'error' => -1]; - $expectedRequest = new Request(['page' => $filters], [], ['_api_pagination' => $filters, '_api_filters' => $filters]); + $expectedRequest = new Request(['page' => $filters], [], ['_api_filters' => $filters]); $expectedRequest->setRequestFormat('jsonapi'); $this->assertEquals($expectedRequest, $request); diff --git a/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php b/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php index fe56e285333..65f01a10bb1 100644 --- a/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php +++ b/tests/Symfony/EventListener/QueryParameterValidateListenerTest.php @@ -13,10 +13,13 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Filter\QueryParameterValidator; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Api\QueryParameterValidator\QueryParameterValidator; use ApiPlatform\Exception\FilterValidationException; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Symfony\EventListener\QueryParameterValidateListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; @@ -25,9 +28,6 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; -/** - * @group legacy - */ class QueryParameterValidateListenerTest extends TestCase { use ProphecyTrait; @@ -55,14 +55,14 @@ public function testOnKernelRequestWithUnsafeMethod() public function testDoNotValidateWhenDisabledGlobally(): void { - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ - 'get' => [], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'get' => new Get(), + ])), + ])); - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); @@ -71,8 +71,8 @@ public function testDoNotValidateWhenDisabledGlobally(): void $queryParameterValidator->validateFilters(Argument::cetera())->shouldNotBeCalled(); $listener = new QueryParameterValidateListener( - $resourceMetadataFactoryProphecy->reveal(), $queryParameterValidator->reveal(), + $resourceMetadataFactoryProphecy->reveal(), false ); @@ -81,16 +81,14 @@ public function testDoNotValidateWhenDisabledGlobally(): void public function testDoNotValidateWhenDisabledInOperationAttribute(): void { - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ - 'get' => [ - 'query_parameter_validate' => false, - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'get' => new Get(queryParameterValidationEnabled: false), + ])), + ])); - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $eventProphecy = $this->prophesize(RequestEvent::class); $eventProphecy->getRequest()->willReturn($request); @@ -99,8 +97,8 @@ public function testDoNotValidateWhenDisabledInOperationAttribute(): void $queryParameterValidator->validateFilters(Argument::cetera())->shouldNotBeCalled(); $listener = new QueryParameterValidateListener( + $queryParameterValidator->reveal(), $resourceMetadataFactoryProphecy->reveal(), - $queryParameterValidator->reveal() ); $listener->onKernelRequest($eventProphecy->reveal()); @@ -113,7 +111,7 @@ public function testOnKernelRequestWithWrongFilter() { $this->setUpWithFilters(['some_inexistent_filter']); - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $request->setMethod('GET'); $eventProphecy = $this->prophesize(RequestEvent::class); @@ -133,7 +131,7 @@ public function testOnKernelRequestWithRequiredFilterNotSet() { $this->setUpWithFilters(['some_filter']); - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $request->setMethod('GET'); $eventProphecy = $this->prophesize(RequestEvent::class); @@ -158,7 +156,7 @@ public function testOnKernelRequestWithRequiredFilter() $request = new Request( [], [], - ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get'], + ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get'], [], [], ['QUERY_STRING' => 'required=foo'] @@ -179,21 +177,18 @@ public function testOnKernelRequestWithRequiredFilter() private function setUpWithFilters(array $filters = []) { - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy - ->create(Dummy::class) - ->willReturn( - (new ResourceMetadata('dummy')) - ->withAttributes([ - 'filters' => $filters, - ]) - ); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'get' => new GetCollection(filters: $filters), + ])), + ])); $this->queryParameterValidator = $this->prophesize(QueryParameterValidator::class); $this->testedInstance = new QueryParameterValidateListener( + $this->queryParameterValidator->reveal(), $resourceMetadataFactoryProphecy->reveal(), - $this->queryParameterValidator->reveal() ); } } diff --git a/tests/Symfony/EventListener/RespondListenerTest.php b/tests/Symfony/EventListener/RespondListenerTest.php index b60cee1fb06..73b9cf44464 100644 --- a/tests/Symfony/EventListener/RespondListenerTest.php +++ b/tests/Symfony/EventListener/RespondListenerTest.php @@ -13,8 +13,11 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Symfony\EventListener\RespondListener; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\ProphecyTrait; @@ -26,7 +29,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class RespondListenerTest extends TestCase { @@ -81,7 +83,7 @@ public function testCreate200Response() public function testPost200WithoutLocation() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true, '_api_write_item_iri' => '/dummy_entities/1']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'post', '_api_respond' => true, '_api_write_item_iri' => '/dummy_entities/1']); $request->setMethod('POST'); $event = new ViewEvent( @@ -90,8 +92,12 @@ public function testPost200WithoutLocation() \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, 'bar' ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['status' => Response::HTTP_OK]])); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'post' => new Post(status: Response::HTTP_OK), + ])), + ])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); @@ -103,7 +109,7 @@ public function testPost200WithoutLocation() public function testPost301WithLocation() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true, '_api_write_item_iri' => '/dummy_entities/1']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get', '_api_respond' => true, '_api_write_item_iri' => '/dummy_entities/1']); $request->setMethod('POST'); $event = new ViewEvent( @@ -112,8 +118,13 @@ public function testPost301WithLocation() \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, 'bar' ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['status' => Response::HTTP_MOVED_PERMANENTLY]])); + + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'get' => new Get(status: Response::HTTP_MOVED_PERMANENTLY), + ])), + ])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); @@ -181,12 +192,17 @@ public function testSetSunsetHeader() { $event = new ViewEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get', '_api_respond' => true]), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, 'bar' ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['sunset' => 'tomorrow']])); + + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'get' => new Get(sunset: 'tomorrow'), + ])), + ])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); @@ -201,12 +217,16 @@ public function testSetCustomStatus() { $event = new ViewEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get', '_api_respond' => true]), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, 'bar' ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['status' => Response::HTTP_ACCEPTED]])); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'get' => new Get(status: Response::HTTP_ACCEPTED), + ])), + ])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); @@ -221,7 +241,7 @@ public function testHandleResponse() $response = new Response(); $event = new ViewEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get', '_api_respond' => true]), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); diff --git a/tests/Symfony/EventListener/SerializeListenerTest.php b/tests/Symfony/EventListener/SerializeListenerTest.php index ece915bed83..72405f8c30a 100644 --- a/tests/Symfony/EventListener/SerializeListenerTest.php +++ b/tests/Symfony/EventListener/SerializeListenerTest.php @@ -13,8 +13,10 @@ namespace ApiPlatform\Tests\Symfony\EventListener; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Serializer\ResourceList; use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Symfony\EventListener\SerializeListener; @@ -30,7 +32,6 @@ /** * @author Kévin Dunglas - * @group legacy */ class SerializeListenerTest extends TestCase { @@ -66,7 +67,7 @@ public function testDoNotSerializeWhenRespondFlagIsFalse() $dummy = new Dummy(); - $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post', '_api_respond' => false]); + $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => Dummy::class, '_api_operation_name' => 'post', '_api_respond' => false]); $request->setMethod('POST'); $event = new ViewEvent( @@ -89,17 +90,15 @@ public function testDoNotSerializeWhenDisabledInOperationAttribute() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $resourceMetadata = new ResourceMetadata('Dummy', null, null, [], [ - 'post' => [ - 'serialize' => false, - ], - ]); - - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource(operations: [ + 'post' => new Post(serialize: false), + ])), + ])); $dummy = new Dummy(); - $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); + $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => Dummy::class, '_api_operation_name' => 'post']); $request->setMethod('POST'); $event = new ViewEvent( @@ -139,7 +138,7 @@ public function testSerializeCollectionOperation() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->setRequestFormat('xml'); $event = new ViewEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), @@ -162,7 +161,7 @@ public function testSerializeCollectionOperationWithOutputClassDisabled() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_api_output_class' => false]); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_output_class' => false]); $request->setRequestFormat('xml'); $event = new ViewEvent( @@ -180,7 +179,7 @@ public function testSerializeCollectionOperationWithOutputClassDisabled() public function testSerializeItemOperation() { - $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'item_operation_name' => 'get']; + $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'operation_name' => 'get']; $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy ->serialize( @@ -192,7 +191,7 @@ public function testSerializeItemOperation() }), Argument::withEntry('request_uri', ''), Argument::withEntry('resource_class', 'Foo'), - Argument::withEntry('item_operation_name', 'get') + Argument::withEntry('operation_name', 'get') ) ) ->willReturn('bar') @@ -201,7 +200,7 @@ public function testSerializeItemOperation() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_operation_name' => 'get']); $request->setRequestFormat('xml'); $event = new ViewEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), diff --git a/tests/Symfony/EventListener/WriteListenerTest.php b/tests/Symfony/EventListener/WriteListenerTest.php index da8f5f2363d..2df0ada6d18 100644 --- a/tests/Symfony/EventListener/WriteListenerTest.php +++ b/tests/Symfony/EventListener/WriteListenerTest.php @@ -14,7 +14,7 @@ namespace ApiPlatform\Tests\Symfony\EventListener; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\ResourceClassResolverInterface; +use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -63,9 +63,6 @@ protected function setUp(): void $this->resourceClassResolver = $this->prophesize(ResourceClassResolverInterface::class); } - /** - * @requires PHP 8.0 - */ public function testOnKernelViewWithControllerResultAndPersist() { $operationResource = new OperationResource(1, 'foo'); @@ -95,15 +92,12 @@ public function testOnKernelViewWithControllerResultAndPersist() $request->setMethod($httpMethod); $request->attributes->set('_api_operation_name', sprintf('_api_%s_%s%s', 'OperationResource', strtolower($httpMethod), 'POST' === $httpMethod ? '_collection' : '')); - (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceMetadataCollectionFactory->reveal(), $this->resourceClassResolver->reveal()))->onKernelView($event); + (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceClassResolver->reveal(), $this->resourceMetadataCollectionFactory->reveal()))->onKernelView($event); $this->assertSame($operationResource, $event->getControllerResult()); $this->assertEquals('/operation_resources/1', $request->attributes->get('_api_write_item_iri')); } } - /** - * @requires PHP 8.0 - */ public function testOnKernelViewDoNotCallIriConverterWhenOutputClassDisabled() { $operationResource = new OperationResource(1, 'foo'); @@ -129,12 +123,9 @@ public function testOnKernelViewDoNotCallIriConverterWhenOutputClassDisabled() $operationResource ); - (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceMetadataCollectionFactory->reveal(), $this->resourceClassResolver->reveal()))->onKernelView($event); + (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceClassResolver->reveal(), $this->resourceMetadataCollectionFactory->reveal()))->onKernelView($event); } - /** - * @requires PHP 8.0 - */ public function testOnKernelViewWithControllerResultAndRemove() { $operationResource = new OperationResource(1, 'foo'); @@ -158,12 +149,9 @@ public function testOnKernelViewWithControllerResultAndRemove() $operationResource ); - (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceMetadataCollectionFactory->reveal(), $this->resourceClassResolver->reveal()))->onKernelView($event); + (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceClassResolver->reveal(), $this->resourceMetadataCollectionFactory->reveal()))->onKernelView($event); } - /** - * @requires PHP 8.0 - */ public function testOnKernelViewWithSafeMethod() { $operationResource = new OperationResource(1, 'foo'); @@ -189,12 +177,9 @@ public function testOnKernelViewWithSafeMethod() $operationResource ); - (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceMetadataCollectionFactory->reveal(), $this->resourceClassResolver->reveal()))->onKernelView($event); + (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceClassResolver->reveal(), $this->resourceMetadataCollectionFactory->reveal()))->onKernelView($event); } - /** - * @requires PHP 8.0 - */ public function testDoNotWriteWhenControllerResultIsResponse() { $this->processorProphecy->process(Argument::cetera())->shouldNotBeCalled(); @@ -210,12 +195,9 @@ public function testDoNotWriteWhenControllerResultIsResponse() $response ); - (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceMetadataCollectionFactory->reveal(), $this->resourceClassResolver->reveal()))->onKernelView($event); + (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceClassResolver->reveal(), $this->resourceMetadataCollectionFactory->reveal()))->onKernelView($event); } - /** - * @requires PHP 8.0 - */ public function testDoNotWriteWhenCant() { $operationResource = new OperationResource(1, 'foo'); @@ -238,12 +220,9 @@ public function testDoNotWriteWhenCant() $operationResource ); - (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceMetadataCollectionFactory->reveal(), $this->resourceClassResolver->reveal()))->onKernelView($event); + (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceClassResolver->reveal(), $this->resourceMetadataCollectionFactory->reveal()))->onKernelView($event); } - /** - * @requires PHP 8.0 - */ public function testOnKernelViewWithNoResourceClass() { $operationResource = new OperationResource(1, 'foo'); @@ -263,12 +242,9 @@ public function testOnKernelViewWithNoResourceClass() $operationResource ); - (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceMetadataCollectionFactory->reveal(), $this->resourceClassResolver->reveal()))->onKernelView($event); + (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceClassResolver->reveal(), $this->resourceMetadataCollectionFactory->reveal()))->onKernelView($event); } - /** - * @requires PHP 8.0 - */ public function testOnKernelViewInvalidIdentifiers() { $attributeResource = new AttributeResource(1, 'name'); @@ -297,6 +273,6 @@ public function testOnKernelViewInvalidIdentifiers() $attributeResource ); - (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceMetadataCollectionFactory->reveal(), $this->resourceClassResolver->reveal()))->onKernelView($event); + (new WriteListener($this->processorProphecy->reveal(), $this->iriConverterProphecy->reveal(), $this->resourceClassResolver->reveal(), $this->resourceMetadataCollectionFactory->reveal()))->onKernelView($event); } } diff --git a/tests/Symfony/Validator/Metadata/ValidatorTest.php b/tests/Symfony/Validator/Metadata/ValidatorTest.php index 9e72faf6cc1..daa88a85276 100644 --- a/tests/Symfony/Validator/Metadata/ValidatorTest.php +++ b/tests/Symfony/Validator/Metadata/ValidatorTest.php @@ -105,33 +105,6 @@ public function __invoke($data): array $validator->validate(new DummyEntity(), ['groups' => 'groups_builder']); } - /** - * @group legacy - * @expectedDeprecation Using a public validation groups generator service not implementing "ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface" is deprecated since 2.6 and will be removed in 3.0. - */ - public function testValidateGetGroupsFromLegacyService(): void - { - $data = new DummyEntity(); - - $constraintViolationListProphecy = $this->prophesize(ConstraintViolationListInterface::class); - $constraintViolationListProphecy->count()->willReturn(0); - - $symfonyValidatorProphecy = $this->prophesize(SymfonyValidatorInterface::class); - $symfonyValidatorProphecy->validate($data, null, ['a', 'b', 'c'])->willReturn($constraintViolationListProphecy); - - $containerProphecy = $this->prophesize(ContainerInterface::class); - $containerProphecy->has('groups_builder')->willReturn(true); - $containerProphecy->get('groups_builder')->willReturn(new class() { - public function __invoke($data): array - { - return $data instanceof DummyEntity ? ['a', 'b', 'c'] : []; - } - }); - - $validator = new Validator($symfonyValidatorProphecy->reveal(), $containerProphecy->reveal()); - $validator->validate(new DummyEntity(), ['groups' => 'groups_builder']); - } - public function testValidatorWithScalarGroup() { $data = new DummyEntity(); diff --git a/tests/Util/IriHelperTest.php b/tests/Util/IriHelperTest.php index bea2ff7e835..4771bec0ecc 100644 --- a/tests/Util/IriHelperTest.php +++ b/tests/Util/IriHelperTest.php @@ -43,62 +43,6 @@ public function testHelpers() $this->assertEquals('/hello.json?foo=bar&bar=3&page=2', IriHelper::createIri($parsed['parts'], $parsed['parameters'], 'page', 2.)); } - /** - * @group legacy - */ - public function testLegacyHelpers() - { - $this->expectDeprecation('Passing a bool as 5th parameter to "ApiPlatform\Util\IriHelper::createIri()" is deprecated since API Platform 2.6. Pass an "ApiPlatform\Api\UrlGeneratorInterface" constant (int) instead.'); - $parsed = [ - 'parts' => [ - 'path' => '/hello.json', - 'query' => 'foo=bar&page=2&bar=3', - ], - 'parameters' => [ - 'foo' => 'bar', - 'bar' => '3', - ], - ]; - - $this->assertEquals($parsed, IriHelper::parseIri('/hello.json?foo=bar&page=2&bar=3', 'page')); - $this->assertEquals('/hello.json?foo=bar&bar=3&page=2', IriHelper::createIri($parsed['parts'], $parsed['parameters'], 'page', 2., false)); - } - - /** - * @group legacy - */ - public function testLegacyHelpersWithAbsoluteUrl() - { - $this->expectDeprecation('Passing a bool as 5th parameter to "ApiPlatform\Util\IriHelper::createIri()" is deprecated since API Platform 2.6. Pass an "ApiPlatform\Api\UrlGeneratorInterface" constant (int) instead.'); - $parsed = [ - 'parts' => [ - 'path' => '/hello.json', - 'query' => 'foo=bar&page=2&bar=3', - 'scheme' => 'http', - 'user' => 'foo', - 'pass' => 'bar', - 'host' => 'localhost', - 'port' => 8080, - 'fragment' => 'foo', - ], - 'parameters' => [ - 'foo' => 'bar', - 'bar' => '3', - ], - ]; - - $this->assertEquals($parsed, IriHelper::parseIri('http://foo:bar@localhost:8080/hello.json?foo=bar&page=2&bar=3#foo', 'page')); - $this->assertEquals('http://foo:bar@localhost:8080/hello.json?foo=bar&bar=3&page=2#foo', IriHelper::createIri($parsed['parts'], $parsed['parameters'], 'page', 2., true)); - - unset($parsed['parts']['scheme']); - - $this->assertEquals('http://foo:bar@localhost:8080/hello.json?foo=bar&bar=3&page=2#foo', IriHelper::createIri($parsed['parts'], $parsed['parameters'], 'page', 2., true)); - - $parsed['parts']['port'] = 443; - - $this->assertEquals('https://foo:bar@localhost:443/hello.json?foo=bar&bar=3&page=2#foo', IriHelper::createIri($parsed['parts'], $parsed['parameters'], 'page', 2., true)); - } - public function testHelpersWithNetworkPath() { $parsed = [ From 29cf16c023c22f668b12cf02c8f001bbaf285507 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 2 Jun 2022 17:49:49 +0200 Subject: [PATCH 31/56] compile --- src/Doctrine/Orm/Extension/EagerLoadingExtension.php | 2 ++ src/Symfony/Bundle/Resources/config/api.xml | 8 ++++---- src/Symfony/Bundle/Resources/config/doctrine_orm.xml | 2 -- src/Symfony/Bundle/Resources/config/state.xml | 1 - tests/Fixtures/TestBundle/Entity/DummyCar.php | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Doctrine/Orm/Extension/EagerLoadingExtension.php b/src/Doctrine/Orm/Extension/EagerLoadingExtension.php index 61641a8124b..5cd77106ea9 100644 --- a/src/Doctrine/Orm/Extension/EagerLoadingExtension.php +++ b/src/Doctrine/Orm/Extension/EagerLoadingExtension.php @@ -45,6 +45,8 @@ final class EagerLoadingExtension implements QueryCollectionExtensionInterface, private PropertyMetadataFactoryInterface $propertyMetadataFactory; private ?ClassMetadataFactoryInterface $classMetadataFactory; private int $maxJoins; + private bool $forceEager; + private bool $fetchPartial; public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, int $maxJoins = 30, bool $forceEager = true, bool $fetchPartial = false, ClassMetadataFactoryInterface $classMetadataFactory = null) { diff --git a/src/Symfony/Bundle/Resources/config/api.xml b/src/Symfony/Bundle/Resources/config/api.xml index 2e61d6c4652..155e175ab46 100644 --- a/src/Symfony/Bundle/Resources/config/api.xml +++ b/src/Symfony/Bundle/Resources/config/api.xml @@ -34,12 +34,12 @@ - + - + @@ -64,7 +64,7 @@ null - + @@ -108,9 +108,9 @@ - %api_platform.error_formats% %api_platform.exception_to_status% + diff --git a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml index fc3bd048d13..ce2b5ec331a 100644 --- a/src/Symfony/Bundle/Resources/config/doctrine_orm.xml +++ b/src/Symfony/Bundle/Resources/config/doctrine_orm.xml @@ -75,8 +75,6 @@ %api_platform.eager_loading.max_joins% %api_platform.eager_loading.force_eager% - null - null %api_platform.eager_loading.fetch_partial% diff --git a/src/Symfony/Bundle/Resources/config/state.xml b/src/Symfony/Bundle/Resources/config/state.xml index 2f384a4008b..123c296ef4e 100644 --- a/src/Symfony/Bundle/Resources/config/state.xml +++ b/src/Symfony/Bundle/Resources/config/state.xml @@ -10,7 +10,6 @@ - %api_platform.collection.pagination% %api_platform.graphql.collection.pagination% diff --git a/tests/Fixtures/TestBundle/Entity/DummyCar.php b/tests/Fixtures/TestBundle/Entity/DummyCar.php index 602626d8caf..2d01485dd1b 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCar.php @@ -69,7 +69,7 @@ class DummyCar * @var mixed Something else */ #[ApiFilter(SearchFilter::class, strategy: 'exact')] - #[ORM\ManyToMany(targetEntity: 'UuidIdentifierDummy', indexBy: 'uuid')] + #[ORM\ManyToMany(targetEntity: UuidIdentifierDummy::class, indexBy: 'uuid', mappedBy: 'uuid')] #[Serializer\Groups(['colors'])] private mixed $uuid = null; #[ApiFilter(SearchFilter::class, strategy: 'partial')] From 6157a981b5199d5413e9ab4c2e2edd4b4d556e85 Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 10 Jun 2022 15:28:37 +0200 Subject: [PATCH 32/56] work on behat tests --- ...custom_identifier_with_subresource.feature | 2 +- features/main/custom_operation.feature | 2 +- src/Api/CompositeIdentifierParser.php | 64 +++++ src/Api/IdentifiersExtractor.php | 4 +- src/Doctrine/Orm/Filter/ExistsFilter.php | 2 +- .../Action/DocumentationAction.php | 23 +- src/Documentation/Documentation.php | 22 +- .../SerializerPropertyMetadataFactory.php | 2 +- ...ltersResourceMetadataCollectionFactory.php | 9 +- src/Serializer/AbstractItemNormalizer.php | 8 - src/State/UriVariablesResolverTrait.php | 1 + src/Symfony/Bundle/ApiPlatformBundle.php | 4 + .../Compiler/AttributeFilterPass.php | 93 ++++++ src/Symfony/Bundle/Resources/config/api.xml | 2 - src/Symfony/Routing/IriConverter.php | 3 +- src/Util/AttributeFilterExtractorTrait.php | 140 +++++++++ tests/Api/CompositeIdentifierParserTest.php | 67 +++++ .../Action/DocumentationActionTest.php | 28 +- .../MongoDbOdm/CustomActionController.php | 8 +- .../Controller/Orm/CustomActionController.php | 8 +- tests/Fixtures/TestBundle/Entity/DummyCar.php | 8 +- .../TestBundle/Entity/SlugParentDummy.php | 5 +- .../TestBundle/Entity/UuidIdentifierDummy.php | 2 +- tests/Fixtures/app/config/config_common.yml | 2 + .../EventListener/AddHeadersListenerTest.php | 6 +- .../EventListener/AddTagsListenerTest.php | 6 +- .../Compiler/AttributeFilterPassTest.php | 269 ++++++++++++++++++ 27 files changed, 688 insertions(+), 102 deletions(-) create mode 100644 src/Api/CompositeIdentifierParser.php create mode 100644 src/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPass.php create mode 100644 src/Util/AttributeFilterExtractorTrait.php create mode 100644 tests/Api/CompositeIdentifierParserTest.php create mode 100644 tests/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPassTest.php diff --git a/features/main/custom_identifier_with_subresource.feature b/features/main/custom_identifier_with_subresource.feature index cf18a15a3c9..773dd872866 100644 --- a/features/main/custom_identifier_with_subresource.feature +++ b/features/main/custom_identifier_with_subresource.feature @@ -84,7 +84,7 @@ Feature: Using custom parent identifier for subresources """ { "@context": "/contexts/SlugParentDummy", - "@id": "/slug_parent_dummies/parent-dummy", + "@id": "/slug_child_dummies/child-dummy/parent_dummy", "@type": "SlugParentDummy", "id": 1, "slug": "parent-dummy", diff --git a/features/main/custom_operation.feature b/features/main/custom_operation.feature index 6b8e4a7bc82..9fa829ec5c7 100644 --- a/features/main/custom_operation.feature +++ b/features/main/custom_operation.feature @@ -64,7 +64,7 @@ Feature: Custom operation """ { "@context": "/contexts/CustomActionDummy", - "@id": "/custom_action_dummies/1", + "@id": "/custom_action_collection_dummies/1", "@type": "CustomActionDummy", "id": 1, "foo": "custom!" diff --git a/src/Api/CompositeIdentifierParser.php b/src/Api/CompositeIdentifierParser.php new file mode 100644 index 00000000000..953ef5e1b69 --- /dev/null +++ b/src/Api/CompositeIdentifierParser.php @@ -0,0 +1,64 @@ + + * + * 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\Api; + +/** + * Normalizes a composite identifier. + * + * @author Antoine Bluchet + */ +final class CompositeIdentifierParser +{ + public const COMPOSITE_IDENTIFIER_REGEXP = '/(\w+)=(?<=\w=)(.*?)(?=;\w+=)|(\w+)=([^;]*);?$/'; + + private function __construct() + { + } + + /* + * Normalize takes a string and gives back an array of identifiers. + * + * For example: foo=0;bar=2 returns ['foo' => 0, 'bar' => 2]. + */ + public static function parse(string $identifier): array + { + $matches = []; + $identifiers = []; + $num = preg_match_all(self::COMPOSITE_IDENTIFIER_REGEXP, $identifier, $matches, \PREG_SET_ORDER); + + foreach ($matches as $i => $match) { + if ($i === $num - 1) { + $identifiers[$match[3]] = $match[4]; + continue; + } + $identifiers[$match[1]] = $match[2]; + } + + return $identifiers; + } + + /** + * Renders composite identifiers to string using: key=value;key2=value2. + */ + public static function stringify(array $identifiers): string + { + $composite = []; + foreach ($identifiers as $name => $value) { + $composite[] = sprintf('%s=%s', $name, $value); + } + + return implode(';', $composite); + } +} + diff --git a/src/Api/IdentifiersExtractor.php b/src/Api/IdentifiersExtractor.php index eddfb87ebb1..7b1bef680b4 100644 --- a/src/Api/IdentifiersExtractor.php +++ b/src/Api/IdentifiersExtractor.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Api; -use ApiPlatform\Core\Identifier\CompositeIdentifierParser; +use ApiPlatform\Api\CompositeIdentifierParser; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation; use ApiPlatform\Metadata\HttpOperation; @@ -72,7 +72,7 @@ public function getIdentifiersFromItem($item, Operation $operation = null, array $compositeIdentifiers[$identifier] = $this->getIdentifierValue($item, $link->getFromClass() ?? $resourceClass, $identifier, $link->getParameterName()); } - $identifiers[($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) ? 'id' : $link->getParameterName()] = CompositeIdentifierParser::stringify($compositeIdentifiers); + $identifiers[$link->getParameterName()] = CompositeIdentifierParser::stringify($compositeIdentifiers); continue; } diff --git a/src/Doctrine/Orm/Filter/ExistsFilter.php b/src/Doctrine/Orm/Filter/ExistsFilter.php index faee5500c80..265878470ec 100644 --- a/src/Doctrine/Orm/Filter/ExistsFilter.php +++ b/src/Doctrine/Orm/Filter/ExistsFilter.php @@ -53,7 +53,7 @@ public function __construct(ManagerRegistry $managerRegistry, LoggerInterface $l */ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { - foreach ($context['filters'][$this->existsParameterName] as $property => $value) { + foreach ($context['filters'][$this->existsParameterName] ?? [] as $property => $value) { $this->filterProperty($this->denormalizePropertyName($property), $value, $queryBuilder, $queryNameGenerator, $resourceClass, $operation, $context); } } diff --git a/src/Documentation/Action/DocumentationAction.php b/src/Documentation/Action/DocumentationAction.php index 34177f31cbe..2a777e3de29 100644 --- a/src/Documentation/Action/DocumentationAction.php +++ b/src/Documentation/Action/DocumentationAction.php @@ -29,27 +29,18 @@ */ final class DocumentationAction { - private $resourceNameCollectionFactory; - private $title; - private $description; - private $version; - private $formats; - private $formatsProvider; - private $swaggerVersions; - private $openApiFactory; + private ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory; + private string $title; + private string $description; + private string $version; + private OpenApiFactoryInterface $openApiFactory; - /** - * @param int[] $swaggerVersions - * @param mixed|array|FormatsProviderInterface $formatsProvider - * @param LegacyOpenApiFactoryInterface|OpenApiFactoryInterface $openApiFactory - */ - public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, string $title = '', string $description = '', string $version = '', array $swaggerVersions = [2, 3], OpenApiFactoryInterface $openApiFactory = null) + public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, string $title = '', string $description = '', string $version = '', OpenApiFactoryInterface $openApiFactory = null) { $this->resourceNameCollectionFactory = $resourceNameCollectionFactory; $this->title = $title; $this->description = $description; $this->version = $version; - $this->swaggerVersions = $swaggerVersions; $this->openApiFactory = $openApiFactory; } @@ -69,6 +60,6 @@ public function __invoke(Request $request = null): DocumentationInterface return $this->openApiFactory->__invoke($context ?? []); } - return new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version, $this->formats); + return new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version); } } diff --git a/src/Documentation/Documentation.php b/src/Documentation/Documentation.php index 8f674167489..82b8e7e802a 100644 --- a/src/Documentation/Documentation.php +++ b/src/Documentation/Documentation.php @@ -26,33 +26,13 @@ final class Documentation implements DocumentationInterface private $title; private $description; private $version; - private $mimeTypes = []; - public function __construct(ResourceNameCollection $resourceNameCollection, string $title = '', string $description = '', string $version = '', array $formats = null) + public function __construct(ResourceNameCollection $resourceNameCollection, string $title = '', string $description = '', string $version = '') { $this->resourceNameCollection = $resourceNameCollection; $this->title = $title; $this->description = $description; $this->version = $version; - - if (null === $formats) { - return; - } - - @trigger_error(sprintf('Passing a 5th parameter to the constructor of "%s" is deprecated since API Platform 2.5', __CLASS__), \E_USER_DEPRECATED); - - foreach ($formats as $mimeTypes) { - foreach ($mimeTypes as $mimeType) { - $this->mimeTypes[] = $mimeType; - } - } - } - - public function getMimeTypes(): array - { - @trigger_error(sprintf('The method "%s" is deprecated since API Platform 2.5, use the "formats" attribute instead', __METHOD__), \E_USER_DEPRECATED); - - return $this->mimeTypes; } public function getVersion(): string diff --git a/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php b/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php index 3e89393ebfb..e43e513f76c 100644 --- a/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php @@ -158,7 +158,7 @@ private function transformLinkStatus(ApiProperty $propertyMetadata, array $norma * Groups are extracted in the following order: * * - From the "serializer_groups" key of the $options array. - * - From metadata of the given operation ("collection_operation_name" and "item_operation_name" keys). + * - From metadata of the given operation ("operation_name" key). * - From metadata of the current resource. * * @throws ResourceClassNotFoundException diff --git a/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php index 9fd6af348eb..a644a8af63e 100644 --- a/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php @@ -15,6 +15,7 @@ use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; +use ApiPlatform\Util\AttributeFilterExtractorTrait; /** * Creates a resource metadata from {@see Resource} annotations. @@ -24,6 +25,8 @@ */ final class FiltersResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface { + use AttributeFilterExtractorTrait; + private $decorated; public function __construct(ResourceMetadataCollectionFactoryInterface $decorated = null) @@ -48,15 +51,17 @@ public function create(string $resourceClass): ResourceMetadataCollection throw new ResourceClassNotFoundException(sprintf('Resource "%s" not found.', $resourceClass)); } + $filters = array_keys($this->readFilterAttributes($reflectionClass)); + foreach ($resourceMetadataCollection as $i => $resource) { foreach ($operations = $resource->getOperations() as $operationName => $operation) { - $operations->add($operationName, $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? [])))); + $operations->add($operationName, $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? [], $filters)))); } $resourceMetadataCollection[$i] = $resource->withOperations($operations); foreach ($graphQlOperations = $resource->getGraphQlOperations() ?? [] as $operationName => $operation) { - $graphQlOperations[$operationName] = $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? []))); + $graphQlOperations[$operationName] = $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? [], $filters))); } $resourceMetadataCollection[$i] = $resource->withGraphQlOperations($graphQlOperations); diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 9dcd9d26166..30e811a7ebe 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -567,14 +567,6 @@ protected function getFactoryOptions(array $context): array $options['operation_name'] = $context['operation_name']; } - if (isset($context['collection_operation_name'])) { - $options['collection_operation_name'] = $context['collection_operation_name']; - } - - if (isset($context['item_operation_name'])) { - $options['item_operation_name'] = $context['item_operation_name']; - } - return $options; } diff --git a/src/State/UriVariablesResolverTrait.php b/src/State/UriVariablesResolverTrait.php index 87d36ba93cd..773c1e86fc0 100644 --- a/src/State/UriVariablesResolverTrait.php +++ b/src/State/UriVariablesResolverTrait.php @@ -13,6 +13,7 @@ namespace ApiPlatform\State; +use ApiPlatform\Api\CompositeIdentifierParser; use ApiPlatform\Api\UriVariablesConverterInterface; use ApiPlatform\Exception\InvalidIdentifierException; use ApiPlatform\Metadata\HttpOperation; diff --git a/src/Symfony/Bundle/ApiPlatformBundle.php b/src/Symfony/Bundle/ApiPlatformBundle.php index 7de347e70a7..a87bb2f993a 100644 --- a/src/Symfony/Bundle/ApiPlatformBundle.php +++ b/src/Symfony/Bundle/ApiPlatformBundle.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Symfony\Bundle; +use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AttributeFilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; @@ -23,6 +24,7 @@ use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlTypePass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; @@ -41,6 +43,8 @@ public function build(ContainerBuilder $container) parent::build($container); $container->addCompilerPass(new DataProviderPass()); + // Run the compiler pass before the {@see ResolveInstanceofConditionalsPass} to allow autoconfiguration of generated filter definitions. + $container->addCompilerPass(new AttributeFilterPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 101); $container->addCompilerPass(new FilterPass()); $container->addCompilerPass(new ElasticsearchClientPass()); $container->addCompilerPass(new GraphQlTypePass()); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPass.php new file mode 100644 index 00000000000..276c5276b5d --- /dev/null +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPass.php @@ -0,0 +1,93 @@ + + * + * 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\Symfony\Bundle\DependencyInjection\Compiler; + +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ConvertedBoolean; +use ApiPlatform\Util\AttributeFilterExtractorTrait; +use ApiPlatform\Util\ReflectionClassRecursiveIterator; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * Registers filter services from {@see ApiFilter} attribute. + * + * @internal + * + * @author Antoine Bluchet + */ +final class AttributeFilterPass implements CompilerPassInterface +{ + use AttributeFilterExtractorTrait; + + private const TAG_FILTER_NAME = 'api_platform.filter'; + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container): void + { + $resourceClassDirectories = $container->getParameter('api_platform.resource_class_directories'); + + foreach (ReflectionClassRecursiveIterator::getReflectionClassesFromDirectories($resourceClassDirectories) as $className => $reflectionClass) { + $this->createFilterDefinitions($reflectionClass, $container); + } + } + + /** + * @throws InvalidArgumentException + */ + private function createFilterDefinitions(\ReflectionClass $resourceReflectionClass, ContainerBuilder $container): void + { + foreach ($this->readFilterAttributes($resourceReflectionClass) as $id => [$arguments, $filterClass]) { + if ($container->has($id)) { + continue; + } + + if (null === $filterReflectionClass = $container->getReflectionClass($filterClass, false)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $filterClass, $id)); + } + + if ($container->has($filterClass) && ($parentDefinition = $container->findDefinition($filterClass))->isAbstract()) { + $definition = new ChildDefinition($parentDefinition->getClass()); + } else { + $definition = new Definition($filterReflectionClass->getName()); + $definition->setAutoconfigured(true); + } + + $definition->addTag(self::TAG_FILTER_NAME); + $definition->setAutowired(true); + + $parameterNames = []; + if (null !== $constructorReflectionMethod = $filterReflectionClass->getConstructor()) { + foreach ($constructorReflectionMethod->getParameters() as $reflectionParameter) { + $parameterNames[$reflectionParameter->name] = true; + } + } + + foreach ($arguments as $key => $value) { + if (!isset($parameterNames[$key])) { + throw new InvalidArgumentException(sprintf('Class "%s" does not have argument "$%s".', $filterClass, $key)); + } + + $definition->setArgument("$$key", $value); + } + + $container->setDefinition($id, $definition); + } + } +} diff --git a/src/Symfony/Bundle/Resources/config/api.xml b/src/Symfony/Bundle/Resources/config/api.xml index 155e175ab46..1b256367d42 100644 --- a/src/Symfony/Bundle/Resources/config/api.xml +++ b/src/Symfony/Bundle/Resources/config/api.xml @@ -101,8 +101,6 @@ %api_platform.title% %api_platform.description% %api_platform.version% - null - %api_platform.swagger.versions% diff --git a/src/Symfony/Routing/IriConverter.php b/src/Symfony/Routing/IriConverter.php index ac07b31aefa..da1d6d10115 100644 --- a/src/Symfony/Routing/IriConverter.php +++ b/src/Symfony/Routing/IriConverter.php @@ -77,8 +77,7 @@ public function getResourceFromIri(string $iri, array $context = [], ?Operation throw new InvalidArgumentException(sprintf('No route matches "%s".', $iri), $e->getCode(), $e); } - // TODO: 3.0 remove collection/item - $parameters['_api_operation_name'] = $parameters['_api_operation_name'] ?? $parameters['_api_collection_operation_name'] ?? $parameters['_api_item_operation_name'] ?? $parameters['_api_subresource_operation_name'] ?? null; + $parameters['_api_operation_name'] = $parameters['_api_operation_name'] ?? null; if (!isset($parameters['_api_resource_class'], $parameters['_api_operation_name'])) { throw new InvalidArgumentException(sprintf('No resource associated to "%s".', $iri)); diff --git a/src/Util/AttributeFilterExtractorTrait.php b/src/Util/AttributeFilterExtractorTrait.php new file mode 100644 index 00000000000..f63535b4e70 --- /dev/null +++ b/src/Util/AttributeFilterExtractorTrait.php @@ -0,0 +1,140 @@ + + * + * 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\Util; + +use ApiPlatform\Metadata\ApiFilter; + +/** + * Generates a service id for a generic filter. + * + * @internal + * + * @author Antoine Bluchet + */ +trait AttributeFilterExtractorTrait +{ + /** + * Filters annotations to get back only ApiFilter annotations. + * + * @param \ReflectionClass|\ReflectionProperty $reflector + * + * @return \Iterator only ApiFilter annotations + */ + private function getFilterAttributes(\Reflector $reflector): \Iterator + { + $attributes = $reflector->getAttributes(ApiFilter::class); + + foreach ($attributes as $attribute) { + yield $attribute->newInstance(); + } + } + + /** + * Given a filter attribute and reflection elements, find out the properties where the filter is applied. + */ + private function getFilterProperties(ApiFilter $filterAttribute, \ReflectionClass $reflectionClass, \ReflectionProperty $reflectionProperty = null): array + { + $properties = []; + + if ($filterAttribute->properties) { + foreach ($filterAttribute->properties as $property => $strategy) { + if (\is_int($property)) { + $properties[$strategy] = null; + } else { + $properties[$property] = $strategy; + } + } + + return $properties; + } + + if (null !== $reflectionProperty) { + $properties[$reflectionProperty->getName()] = $filterAttribute->strategy ?: null; + + return $properties; + } + + if ($filterAttribute->strategy) { + foreach ($reflectionClass->getProperties() as $reflectionProperty) { + $properties[$reflectionProperty->getName()] = $filterAttribute->strategy; + } + } + + return $properties; + } + + /** + * Reads filter attribute from a ReflectionClass. + * + * @return array Key is the filter id. It has two values, properties and the ApiFilter instance + */ + private function readFilterAttributes(\ReflectionClass $reflectionClass): array + { + $filters = []; + + foreach ($this->getFilterAttributes($reflectionClass) as $filterAttribute) { + $filterClass = $filterAttribute->filterClass; + $id = $this->generateFilterId($reflectionClass, $filterClass, $filterAttribute->id); + + if (!isset($filters[$id])) { + $filters[$id] = [$filterAttribute->arguments, $filterClass]; + } + + if ($properties = $this->getFilterProperties($filterAttribute, $reflectionClass)) { + $filters[$id][0]['properties'] = $properties; + } + } + + foreach ($reflectionClass->getProperties() as $reflectionProperty) { + foreach ($this->getFilterAttributes($reflectionProperty) as $filterAttribute) { + $filterClass = $filterAttribute->filterClass; + $id = $this->generateFilterId($reflectionClass, $filterClass, $filterAttribute->id); + + if (!isset($filters[$id])) { + $filters[$id] = [$filterAttribute->arguments, $filterClass]; + } + + if ($properties = $this->getFilterProperties($filterAttribute, $reflectionClass, $reflectionProperty)) { + if (isset($filters[$id][0]['properties'])) { + $filters[$id][0]['properties'] = array_merge($filters[$id][0]['properties'], $properties); + } else { + $filters[$id][0]['properties'] = $properties; + } + } + } + } + + $parent = $reflectionClass->getParentClass(); + + if (false !== $parent) { + return array_merge($filters, $this->readFilterAttributes($parent)); + } + + return $filters; + } + + /** + * Generates a unique, per-class and per-filter identifier prefixed by `annotated_`. + * + * @param \ReflectionClass $reflectionClass the reflection class of a Resource + * @param string $filterClass the filter class + * @param string|null $filterId the filter id + */ + private function generateFilterId(\ReflectionClass $reflectionClass, string $filterClass, string $filterId = null): string + { + $suffix = null !== $filterId ? '_'.$filterId : $filterId; + + return 'annotated_'.Inflector::tableize(str_replace('\\', '', $reflectionClass->getName().(new \ReflectionClass($filterClass))->getName().$suffix)); + } +} diff --git a/tests/Api/CompositeIdentifierParserTest.php b/tests/Api/CompositeIdentifierParserTest.php new file mode 100644 index 00000000000..af119464b8b --- /dev/null +++ b/tests/Api/CompositeIdentifierParserTest.php @@ -0,0 +1,67 @@ + + * + * 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\Tests\Api; + +use ApiPlatform\Api\CompositeIdentifierParser; +use PHPUnit\Framework\TestCase; + +class CompositeIdentifierParserTest extends TestCase +{ + /** + * @dataProvider variousIdentifiers + */ + public function testNormalizeCompositeCorrectly(array $identifiers) + { + foreach ($identifiers as $string => $expected) { + $this->assertEquals(CompositeIdentifierParser::parse($string), $expected); + } + } + + public function variousIdentifiers(): array + { + return [[[ + 'a=bd;dc=d' => ['a' => 'bd', 'dc' => 'd'], + 'a=b;c=d foo;d23i=e' => ['a' => 'b', 'c' => 'd foo', 'd23i' => 'e'], + 'a=1;c=2;d=10-30-24' => ['a' => '1', 'c' => '2', 'd' => '10-30-24'], + 'a=test;b=bar;foo;c=123' => ['a' => 'test', 'b' => 'bar;foo', 'c' => '123'], + 'a=test;b=bar ;foo;c=123;459;barz=123asgfjasdg4;' => ['a' => 'test', 'b' => 'bar ;foo', 'c' => '123;459', 'barz' => '123asgfjasdg4'], + 'foo=test=bar;;bar=bazzz;' => ['foo' => 'test=bar;', 'bar' => 'bazzz'], + 'foo=test=bar;bar=;test=foo' => ['foo' => 'test=bar', 'bar' => '', 'test' => 'foo'], + 'foo=test=bar;bar=' => ['foo' => 'test=bar', 'bar' => ''], + ]]]; + } + + /** + * @dataProvider compositeIdentifiers + */ + public function testStringify(array $identifiers) + { + foreach ($identifiers as $string => $arr) { + $this->assertEquals(CompositeIdentifierParser::stringify($arr), $string); + } + } + + public function compositeIdentifiers(): array + { + return [[[ + 'a=bd;dc=d' => ['a' => 'bd', 'dc' => 'd'], + 'a=b;c=d foo;d23i=e' => ['a' => 'b', 'c' => 'd foo', 'd23i' => 'e'], + 'a=1;c=2;d=10-30-24' => ['a' => '1', 'c' => '2', 'd' => '10-30-24'], + 'a=test;b=bar;foo;c=123' => ['a' => 'test', 'b' => 'bar;foo', 'c' => '123'], + 'foo=test=bar;;bar=bazzz' => ['foo' => 'test=bar;', 'bar' => 'bazzz'], + 'foo=test=bar;bar=;test=foo' => ['foo' => 'test=bar', 'bar' => '', 'test' => 'foo'], + 'foo=test=bar;bar=' => ['foo' => 'test=bar', 'bar' => ''], + ]]]; + } +} diff --git a/tests/Documentation/Action/DocumentationActionTest.php b/tests/Documentation/Action/DocumentationActionTest.php index 184c6a2fc2c..7c128e953d9 100644 --- a/tests/Documentation/Action/DocumentationActionTest.php +++ b/tests/Documentation/Action/DocumentationActionTest.php @@ -35,29 +35,7 @@ class DocumentationActionTest extends TestCase { use ProphecyTrait; - public function testDocumentationActionV2(): void - { - $openApiFactoryProphecy = $this->prophesize(OpenApiFactoryInterface::class); - $requestProphecy = $this->prophesize(Request::class); - $requestProphecy->getRequestFormat()->willReturn('json'); - $attributesProphecy = $this->prophesize(ParameterBagInterface::class); - $queryProphecy = $this->prophesize(ParameterBag::class); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummies'])); - $requestProphecy->attributes = $attributesProphecy->reveal(); - $requestProphecy->query = $queryProphecy->reveal(); - $requestProphecy->getBaseUrl()->willReturn('/api')->shouldBeCalledTimes(1); - $queryProphecy->getBoolean('api_gateway')->willReturn(true)->shouldBeCalledTimes(1); - $queryProphecy->getInt('spec_version', 2)->willReturn(2)->shouldBeCalledTimes(1); - $attributesProphecy->all()->willReturn(['_api_normalization_context' => ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2]])->shouldBeCalledTimes(1); - $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); - $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 2])->shouldBeCalledTimes(1); - - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', [2, 3], $openApiFactoryProphecy->reveal()); - $this->assertEquals(new Documentation(new ResourceNameCollection(['dummies']), 'My happy hippie api', 'lots of chocolate', '1.0.0'), $documentation($requestProphecy->reveal())); - } - - public function testDocumentationActionV3(): void + public function testDocumentationAction(): void { $openApi = new OpenApi(new Info('my api', '1.0.0'), [], new Paths()); $openApiFactoryProphecy = $this->prophesize(OpenApiFactoryInterface::class); @@ -66,8 +44,6 @@ public function testDocumentationActionV3(): void $requestProphecy->getRequestFormat()->willReturn('json'); $attributesProphecy = $this->prophesize(ParameterBagInterface::class); $queryProphecy = $this->prophesize(ParameterBag::class); - $resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class); - $resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection(['dummies'])); $requestProphecy->attributes = $attributesProphecy->reveal(); $requestProphecy->query = $queryProphecy->reveal(); $requestProphecy->getBaseUrl()->willReturn('/api')->shouldBeCalledTimes(1); @@ -77,7 +53,7 @@ public function testDocumentationActionV3(): void $attributesProphecy->get('_api_normalization_context', [])->willReturn(['foo' => 'bar'])->shouldBeCalledTimes(1); $attributesProphecy->set('_api_normalization_context', ['foo' => 'bar', 'base_url' => '/api', 'api_gateway' => true, 'spec_version' => 3])->shouldBeCalledTimes(1); - $documentation = new DocumentationAction($resourceNameCollectionFactoryProphecy->reveal(), 'My happy hippie api', 'lots of chocolate', '1.0.0', [2, 3], $openApiFactoryProphecy->reveal()); + $documentation = new DocumentationAction($openApiFactoryProphecy->reveal()); $this->assertInstanceOf(OpenApi::class, $documentation($requestProphecy->reveal())); } } diff --git a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php index 4091bb30db2..64f5d9ff995 100644 --- a/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php +++ b/tests/Fixtures/TestBundle/Controller/MongoDbOdm/CustomActionController.php @@ -23,7 +23,7 @@ */ class CustomActionController extends AbstractController { - #[Route(methods: ['GET'], name: 'custom_normalization', path: '/custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] + #[Route(methods: ['GET'], name: 'custom_normalization', path: '/custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_operation_name' => 'custom_normalization'])] public function customNormalizationAction(CustomActionDummy $data) { $data->setFoo('foo'); @@ -31,7 +31,7 @@ public function customNormalizationAction(CustomActionDummy $data) return $this->json($data); } - #[Route(methods: ['POST'], name: 'custom_denormalization', path: '/custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] + #[Route(methods: ['POST'], name: 'custom_denormalization', path: '/custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function customDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { @@ -43,7 +43,7 @@ public function customDenormalizationAction(Request $request) return $object; } - #[Route(methods: ['GET'], name: 'short_custom_normalization', path: '/short_custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] + #[Route(methods: ['GET'], name: 'short_custom_normalization', path: '/short_custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_operation_name' => 'custom_normalization'])] public function shortCustomNormalizationAction(CustomActionDummy $data) { $data->setFoo('short'); @@ -51,7 +51,7 @@ public function shortCustomNormalizationAction(CustomActionDummy $data) return $this->json($data); } - #[Route(methods: ['POST'], name: 'short_custom_denormalization', path: '/short_custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] + #[Route(methods: ['POST'], name: 'short_custom_denormalization', path: '/short_custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function shortCustomDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { diff --git a/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php b/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php index c9bea651d10..b39e1d800f3 100644 --- a/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php +++ b/tests/Fixtures/TestBundle/Controller/Orm/CustomActionController.php @@ -23,7 +23,7 @@ */ class CustomActionController extends AbstractController { - #[Route(methods: ['GET'], name: 'custom_normalization', path: '/custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] + #[Route(methods: ['GET'], name: 'custom_normalization', path: '/custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_operation_name' => 'custom_normalization'])] public function customNormalizationAction(CustomActionDummy $data) { $data->setFoo('foo'); @@ -31,7 +31,7 @@ public function customNormalizationAction(CustomActionDummy $data) return $this->json($data); } - #[Route(methods: ['POST'], name: 'custom_denormalization', path: '/custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] + #[Route(methods: ['POST'], name: 'custom_denormalization', path: '/custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function customDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { @@ -43,7 +43,7 @@ public function customDenormalizationAction(Request $request) return $object; } - #[Route(methods: ['GET'], name: 'short_custom_normalization', path: '/short_custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_item_operation_name' => 'custom_normalization'])] + #[Route(methods: ['GET'], name: 'short_custom_normalization', path: '/short_custom/{id}/normalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_operation_name' => 'custom_normalization'])] public function shortCustomNormalizationAction(CustomActionDummy $data) { $data->setFoo('short'); @@ -51,7 +51,7 @@ public function shortCustomNormalizationAction(CustomActionDummy $data) return $this->json($data); } - #[Route(methods: ['POST'], name: 'short_custom_denormalization', path: '/short_custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_collection_operation_name' => 'custom_denormalization', '_api_receive' => false])] + #[Route(methods: ['POST'], name: 'short_custom_denormalization', path: '/short_custom/denormalization', defaults: ['_api_resource_class' => CustomActionDummy::class, '_api_operation_name' => 'custom_denormalization', '_api_receive' => false])] public function shortCustomDenormalizationAction(Request $request) { if ($request->attributes->has('data')) { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCar.php b/tests/Fixtures/TestBundle/Entity/DummyCar.php index 2d01485dd1b..5e15af8c267 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCar.php @@ -69,9 +69,13 @@ class DummyCar * @var mixed Something else */ #[ApiFilter(SearchFilter::class, strategy: 'exact')] - #[ORM\ManyToMany(targetEntity: UuidIdentifierDummy::class, indexBy: 'uuid', mappedBy: 'uuid')] + #[ORM\ManyToMany(targetEntity: UuidIdentifierDummy::class, indexBy: 'uuid')] + #[ORM\JoinColumn(name: 'car_id', referencedColumnName: 'id_id')] + #[ORM\InverseJoinColumn(name: 'uuid_uuid', referencedColumnName: 'uuid')] + #[ORM\JoinTable(name: 'uuid_cars')] #[Serializer\Groups(['colors'])] - private mixed $uuid = null; + private $uuid = null; + #[ApiFilter(SearchFilter::class, strategy: 'partial')] #[ORM\Column(type: 'string')] private ?string $name = null; diff --git a/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php b/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php index 9d48c141ad3..884a181ce7a 100644 --- a/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SlugParentDummy.php @@ -44,11 +44,12 @@ class SlugParentDummy #[ApiProperty(identifier: true)] #[ORM\Column(type: 'string', length: 255, unique: true)] private ?string $slug = null; + /** - * @var \Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: \ApiPlatform\Tests\Fixtures\TestBundle\Entity\SlugChildDummy::class, mappedBy: 'parentDummy')] - private \Collection $childDummies; + private Collection $childDummies; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php b/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php index 1723be3103e..4d665cb3f7e 100644 --- a/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php +++ b/tests/Fixtures/TestBundle/Entity/UuidIdentifierDummy.php @@ -28,7 +28,7 @@ class UuidIdentifierDummy */ #[ORM\Column(type: 'guid')] #[ORM\Id] - private ?string $uuid = null; + private $uuid; /** * @var string The dummy name */ diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index b1933e6fcfa..73fdaedce0b 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -64,6 +64,8 @@ api_platform: xkey: glue: ' ' defaults: + normalization_context: + skip_null_values: false pagination_client_enabled: true pagination_client_items_per_page: true pagination_client_partial: true diff --git a/tests/HttpCache/EventListener/AddHeadersListenerTest.php b/tests/HttpCache/EventListener/AddHeadersListenerTest.php index 457e296bfe1..e77e0d3503d 100644 --- a/tests/HttpCache/EventListener/AddHeadersListenerTest.php +++ b/tests/HttpCache/EventListener/AddHeadersListenerTest.php @@ -35,7 +35,7 @@ class AddHeadersListenerTest extends TestCase public function testDoNotSetHeaderWhenMethodNotCacheable() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $request->setMethod('PUT'); $response = new Response(); $event = new ResponseEvent( @@ -53,7 +53,7 @@ public function testDoNotSetHeaderWhenMethodNotCacheable() public function testDoNotSetHeaderOnUnsuccessfulResponse() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $response = new Response('{}', Response::HTTP_BAD_REQUEST); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), @@ -89,7 +89,7 @@ public function testDoNotSetHeaderWhenNoContent() $response = new Response(); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); diff --git a/tests/HttpCache/EventListener/AddTagsListenerTest.php b/tests/HttpCache/EventListener/AddTagsListenerTest.php index 371f9ad4a64..2e3e815e167 100644 --- a/tests/HttpCache/EventListener/AddTagsListenerTest.php +++ b/tests/HttpCache/EventListener/AddTagsListenerTest.php @@ -42,7 +42,7 @@ public function testDoNotSetHeaderWhenMethodNotCacheable() { $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $request = new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $request->setMethod('PUT'); $response = new Response(); @@ -66,7 +66,7 @@ public function testDoNotSetHeaderWhenResponseNotCacheable() { $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $request = new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']); $response = new Response(); $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), @@ -112,7 +112,7 @@ public function testDoNotSetHeaderWhenEmptyTagList() $event = new ResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), - new Request([], [], ['_resources' => [], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + new Request([], [], ['_resources' => [], '_api_resource_class' => Dummy::class, '_api_operation_name' => 'get']), \defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST, $response ); diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPassTest.php new file mode 100644 index 00000000000..37384f2714d --- /dev/null +++ b/tests/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPassTest.php @@ -0,0 +1,269 @@ + + * + * 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\Tests\Symfony\Bundle\DependencyInjection\Compiler; + +use ApiPlatform\Api\FilterInterface; +use ApiPlatform\Core\Annotation\ApiFilter; +use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Core\Tests\ProphecyTrait; +use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Serializer\Filter\GroupFilter; +use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AnnotationFilterPass; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; +use ApiPlatform\Tests\Fixtures\TestBundle\Filter\DoesNotImplementInterfaceFilter; +use ApiPlatform\Tests\Fixtures\TestBundle\Filter\NoConstructorFilter; +use ApiPlatform\Tests\Fixtures\TestBundle\Filter\NoPropertiesArgumentFilter; +use Doctrine\Common\Annotations\Reader; +use PHPUnit\Framework\TestCase; +use Prophecy\Argument; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException as DependencyInjectionInvalidArgumentException; + +/** + * @author Antoine Bluchet + */ +class AttributeFilterPassTest extends TestCase +{ + use ProphecyTrait; + + public function testConstruct(): void + { + $annotationFilterPass = new AnnotationFilterPass(); + + $this->assertInstanceOf(CompilerPassInterface::class, $annotationFilterPass); + } + + public function testProcess(): void + { + $readerProphecy = $this->prophesize(Reader::class); + $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); + $readerProphecy->getClassAnnotations(Argument::allOf( + Argument::type(\ReflectionClass::class), + Argument::which('getName', Dummy::class) + ))->willReturn([ + new ApiFilter(['value' => SearchFilter::class, 'strategy' => 'exact', 'properties' => ['description', 'relatedDummy.name', 'name']]), + new ApiFilter(['value' => GroupFilter::class, 'arguments' => ['parameterName' => 'foobar']]), + ]); + $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); + $readerProphecy->getPropertyAnnotations(Argument::allOf( + Argument::type(\ReflectionProperty::class), + Argument::that(function (\ReflectionProperty $reflectionProperty): bool { + return Dummy::class === $reflectionProperty->getDeclaringClass()->getName(); + }), + Argument::which('getName', 'dummyDate') + ))->willReturn([ + new ApiFilter(['value' => DateFilter::class]), + ]); + + $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); + $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ + __DIR__.'/../../../../Fixtures/TestBundle/Entity/', + ]); + $containerBuilderProphecy->has('annotation_reader')->willReturn(true); + $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(false); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_serializer_filter_group_filter')->willReturn(false); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_doctrine_orm_filter_date_filter')->willReturn(false); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(false); + $containerBuilderProphecy->has(SearchFilter::class)->willReturn(false); + $containerBuilderProphecy->has(GroupFilter::class)->willReturn(false); + $containerBuilderProphecy->has(DateFilter::class)->willReturn(true); + $containerBuilderProphecy->findDefinition(DateFilter::class)->willReturn((new Definition(DateFilter::class))->setAbstract(true)); + $containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(new \ReflectionClass(SearchFilter::class)); + $containerBuilderProphecy->getReflectionClass(GroupFilter::class, false)->willReturn(new \ReflectionClass(GroupFilter::class)); + $containerBuilderProphecy->getReflectionClass(DateFilter::class, false)->willReturn(new \ReflectionClass(DateFilter::class)); + $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter', Argument::allOf( + Argument::type(Definition::class), + Argument::that(function (Definition $definition): bool { + return SearchFilter::class === $definition->getClass() && ['$properties' => ['description' => null, 'relatedDummy.name' => null, 'name' => null]] === $definition->getArguments(); + }) + ))->shouldBeCalled(); + $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_serializer_filter_group_filter', Argument::allOf( + Argument::type(Definition::class), + Argument::that(function (Definition $definition): bool { + return GroupFilter::class === $definition->getClass() && ['$parameterName' => 'foobar'] === $definition->getArguments(); + }) + ))->shouldBeCalled(); + $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_doctrine_orm_filter_date_filter', Argument::allOf( + Argument::type(ChildDefinition::class), + Argument::that(function (ChildDefinition $definition): bool { + return DateFilter::class === $definition->getParent() && ['$properties' => ['dummyDate' => null]] === $definition->getArguments(); + }) + ))->shouldBeCalled(); + if (\PHP_VERSION_ID >= 80000) { + $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter', Argument::allOf( + Argument::type(Definition::class), + Argument::that(function (Definition $definition): bool { + return SearchFilter::class === $definition->getClass() && ['$properties' => ['filtered' => null]] === $definition->getArguments(); + }) + ))->shouldBeCalled(); + } + + $annotationFilterPass = new AnnotationFilterPass(); + $annotationFilterPass->process($containerBuilderProphecy->reveal()); + } + + public function testProcessFilterWhichDoesNotImplementRequiredInterface(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(sprintf('The filter class "%s" does not implement "%s".', DoesNotImplementInterfaceFilter::class, FilterInterface::class)); + + $readerProphecy = $this->prophesize(Reader::class); + $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); + $readerProphecy->getClassAnnotations(Argument::allOf( + Argument::type(\ReflectionClass::class), + Argument::which('getName', Dummy::class) + ))->willReturn([ + new ApiFilter(['value' => DoesNotImplementInterfaceFilter::class]), + ]); + $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); + + $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); + $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ + __DIR__.'/../../../../Fixtures/TestBundle/Entity/', + ]); + $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); + + $annotationFilterPass = new AnnotationFilterPass(); + $annotationFilterPass->process($containerBuilderProphecy->reveal()); + } + + public function testProcessFilterWhichHasAlreadyBeenRegistered(): void + { + $readerProphecy = $this->prophesize(Reader::class); + $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); + $readerProphecy->getClassAnnotations(Argument::allOf( + Argument::type(\ReflectionClass::class), + Argument::which('getName', Dummy::class) + ))->willReturn([ + new ApiFilter(['value' => SearchFilter::class]), + ]); + $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); + + $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); + $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ + __DIR__.'/../../../../Fixtures/TestBundle/Entity/', + ]); + $containerBuilderProphecy->has('annotation_reader')->willReturn(true); + $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(true); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(true); + $containerBuilderProphecy->setDefinition(Argument::cetera())->shouldNotBeCalled(); + + $annotationFilterPass = new AnnotationFilterPass(); + $annotationFilterPass->process($containerBuilderProphecy->reveal()); + } + + public function testProcessInvalidFilterClass(): void + { + $this->expectException(DependencyInjectionInvalidArgumentException::class); + $this->expectExceptionMessage(sprintf('Class "%s" used for service "annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter" cannot be found.', SearchFilter::class)); + + $readerProphecy = $this->prophesize(Reader::class); + $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); + $readerProphecy->getClassAnnotations(Argument::allOf( + Argument::type(\ReflectionClass::class), + Argument::which('getName', Dummy::class) + ))->willReturn([ + new ApiFilter(['value' => SearchFilter::class]), + ]); + $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); + + $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); + $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ + __DIR__.'/../../../../Fixtures/TestBundle/Entity/', + ]); + $containerBuilderProphecy->has('annotation_reader')->willReturn(true); + $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(false); + $containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(null); + + $annotationFilterPass = new AnnotationFilterPass(); + $annotationFilterPass->process($containerBuilderProphecy->reveal()); + } + + public function testProcessFilterWithoutConstructor(): void + { + $readerProphecy = $this->prophesize(Reader::class); + $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); + $readerProphecy->getClassAnnotations(Argument::allOf( + Argument::type(\ReflectionClass::class), + Argument::which('getName', Dummy::class) + ))->willReturn([ + new ApiFilter(['value' => NoConstructorFilter::class]), + ]); + $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); + + $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); + $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ + __DIR__.'/../../../../Fixtures/TestBundle/Entity/', + ]); + $containerBuilderProphecy->has('annotation_reader')->willReturn(true); + $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_filter_no_constructor_filter')->willReturn(false); + $containerBuilderProphecy->getReflectionClass(NoConstructorFilter::class, false)->willReturn(new \ReflectionClass(NoConstructorFilter::class)); + $containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(new \ReflectionClass(SearchFilter::class)); + $containerBuilderProphecy->has(NoConstructorFilter::class)->willReturn(true); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(true); + $containerBuilderProphecy->findDefinition(NoConstructorFilter::class)->willReturn((new Definition(NoConstructorFilter::class))->setAbstract(false)); + $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_filter_no_constructor_filter', Argument::allOf( + Argument::type(Definition::class), + Argument::that(function (Definition $definition): bool { + return NoConstructorFilter::class === $definition->getClass() && [] === $definition->getArguments(); + }) + ))->shouldBeCalled(); + + $annotationFilterPass = new AnnotationFilterPass(); + $annotationFilterPass->process($containerBuilderProphecy->reveal()); + } + + public function testProcessFilterWithoutPropertiesArgument(): void + { + $readerProphecy = $this->prophesize(Reader::class); + $readerProphecy->getClassAnnotations(Argument::type(\ReflectionClass::class))->willReturn([]); + $readerProphecy->getClassAnnotations(Argument::allOf( + Argument::type(\ReflectionClass::class), + Argument::which('getName', Dummy::class) + ))->willReturn([ + new ApiFilter(['value' => NoPropertiesArgumentFilter::class]), + ]); + $readerProphecy->getPropertyAnnotations(Argument::type(\ReflectionProperty::class))->willReturn([]); + + $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); + $containerBuilderProphecy->getParameter('api_platform.resource_class_directories')->willReturn([ + __DIR__.'/../../../../Fixtures/TestBundle/Entity/', + ]); + $containerBuilderProphecy->has('annotation_reader')->willReturn(true); + $containerBuilderProphecy->get('annotation_reader')->willReturn($readerProphecy); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_filter_no_properties_argument_filter')->willReturn(false); + $containerBuilderProphecy->has('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_php8_api_platform_core_bridge_doctrine_orm_filter_search_filter')->willReturn(true); + $containerBuilderProphecy->getReflectionClass(NoPropertiesArgumentFilter::class, false)->willReturn(new \ReflectionClass(NoPropertiesArgumentFilter::class)); + $containerBuilderProphecy->has(NoPropertiesArgumentFilter::class)->willReturn(true); + $containerBuilderProphecy->getReflectionClass(SearchFilter::class, false)->willReturn(new \ReflectionClass(SearchFilter::class)); + $containerBuilderProphecy->findDefinition(NoPropertiesArgumentFilter::class)->willReturn((new Definition(NoPropertiesArgumentFilter::class))->setAbstract(false)); + $containerBuilderProphecy->setDefinition('annotated_api_platform_tests_fixtures_test_bundle_entity_dummy_api_platform_tests_fixtures_test_bundle_filter_no_properties_argument_filter', Argument::allOf( + Argument::type(Definition::class), + Argument::that(function (Definition $definition): bool { + return NoPropertiesArgumentFilter::class === $definition->getClass() && [] === $definition->getArguments(); + }) + ))->shouldBeCalled(); + + $annotationFilterPass = new AnnotationFilterPass(); + $annotationFilterPass->process($containerBuilderProphecy->reveal()); + } +} From cc77bedfc8c238be9cea87d78cfa54b3e4aa345e Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Tue, 14 Jun 2022 17:19:29 +0200 Subject: [PATCH 33/56] fix(graphql): type builder output (#4791) * Revert "fix(graphql): output creates its own type in TypeBuilder (#4766)" This reverts commit 1f4085e973e3bfafe785b0d57682516916724fcc. * fix: resources order --- features/graphql/mutation.feature | 20 ----- features/graphql/query.feature | 26 ------ src/GraphQl/Type/TypeBuilder.php | 11 ++- src/Util/ReflectionClassRecursiveIterator.php | 6 +- .../Document/DummyCustomMutation.php | 78 ++++++++++++++---- .../TestBundle/Document/DummyCustomQuery.php | 55 +++++++++++-- .../TestBundle/Entity/DummyCustomMutation.php | 82 +++++++++++++++---- .../TestBundle/Entity/DummyCustomQuery.php | 59 +++++++++++-- tests/Fixtures/app/config/config_common.yml | 12 --- tests/GraphQl/Type/TypeBuilderTest.php | 10 +-- 10 files changed, 241 insertions(+), 118 deletions(-) diff --git a/features/graphql/mutation.feature b/features/graphql/mutation.feature index 4dadbdd19d9..01b38f97e17 100644 --- a/features/graphql/mutation.feature +++ b/features/graphql/mutation.feature @@ -819,26 +819,6 @@ Feature: GraphQL mutation support And the JSON node "data.testCustomArgumentsDummyCustomMutation.dummyCustomMutation.result" should be equal to "18" And the JSON node "data.testCustomArgumentsDummyCustomMutation.clientMutationId" should be equal to "myId" - Scenario: Execute a custom mutation with output - When I send the following GraphQL request: - """ - mutation { - testOutputDummyCustomMutation(input: {id: "/dummy_custom_mutations/1", operandA: 9, clientMutationId: "myId"}) { - dummyCustomMutation { - baz - bat - } - clientMutationId - } - } - """ - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/json" - And the JSON node "data.testOutputDummyCustomMutation.dummyCustomMutation.baz" should be equal to "98" - And the JSON node "data.testOutputDummyCustomMutation.dummyCustomMutation.bat" should be equal to "9" - And the JSON node "data.testOutputDummyCustomMutation.clientMutationId" should be equal to "myId" - Scenario: Uploading a file with a custom mutation Given I have the following file for a GraphQL request: | name | file | diff --git a/features/graphql/query.feature b/features/graphql/query.feature index 4a7a0464acd..4a893973062 100644 --- a/features/graphql/query.feature +++ b/features/graphql/query.feature @@ -432,32 +432,6 @@ Feature: GraphQL query support } """ - Scenario: Custom item query with output - Given there are 2 dummyCustomQuery objects - When I send the following GraphQL request: - """ - { - testItemOutputDummyCustomQuery(id: "/dummy_custom_queries/1",) { - baz - bat - } - } - """ - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/json" - And the JSON should be equal to: - """ - { - "data": { - "testItemOutputDummyCustomQuery": { - "baz": 46, - "bat": "Success!" - } - } - } - """ - @createSchema Scenario: Retrieve an item with different serialization groups for item_query and collection_query Given there are 1 dummy with different GraphQL serialization groups objects diff --git a/src/GraphQl/Type/TypeBuilder.php b/src/GraphQl/Type/TypeBuilder.php index 650023b02fd..af6774f7b5b 100644 --- a/src/GraphQl/Type/TypeBuilder.php +++ b/src/GraphQl/Type/TypeBuilder.php @@ -59,12 +59,6 @@ public function getResourceObjectType(?string $resourceClass, ResourceMetadataCo $shortName = $operation->getShortName(); $operationName = $operation->getName(); - $ioMetadata = $input ? $operation->getInput() : $operation->getOutput(); - if (null !== $ioMetadata && \array_key_exists('class', $ioMetadata) && null !== $ioMetadata['class']) { - $resourceClass = $ioMetadata['class']; - $shortName = $ioMetadata['name']; - } - if ($operation instanceof Mutation) { $shortName = $operationName.ucfirst($shortName); } @@ -108,6 +102,11 @@ public function getResourceObjectType(?string $resourceClass, ResourceMetadataCo return $resourceObjectType; } + $ioMetadata = $input ? $operation->getInput() : $operation->getOutput(); + if (null !== $ioMetadata && \array_key_exists('class', $ioMetadata) && null !== $ioMetadata['class']) { + $resourceClass = $ioMetadata['class']; + } + $wrapData = !$wrapped && ($operation instanceof Mutation || $operation instanceof Subscription) && !$input && $depth < 1; $configuration = [ diff --git a/src/Util/ReflectionClassRecursiveIterator.php b/src/Util/ReflectionClassRecursiveIterator.php index 8215c532c11..4fef953fc12 100644 --- a/src/Util/ReflectionClassRecursiveIterator.php +++ b/src/Util/ReflectionClassRecursiveIterator.php @@ -56,7 +56,11 @@ public static function getReflectionClassesFromDirectories(array $directories): } } - $declared = array_merge(get_declared_classes(), get_declared_interfaces()); + $sortedClasses = get_declared_classes(); + sort($sortedClasses); + $sortedInterfaces = get_declared_interfaces(); + sort($sortedInterfaces); + $declared = array_merge($sortedClasses, $sortedInterfaces); foreach ($declared as $className) { $reflectionClass = new \ReflectionClass($className); $sourceFile = $reflectionClass->getFileName(); diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php index f1f4e6ec018..36621125f89 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php @@ -13,31 +13,79 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\GraphQl\Mutation; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Core\Annotation\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy with a custom GraphQL mutation resolver. * + * @ODM\Document + * @ApiResource(graphql={ + * "sum"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom", + * "normalization_context"={"groups"={"result"}}, + * "denormalization_context"={"groups"={"sum"}} + * }, + * "sumNotPersisted"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted", + * "normalization_context"={"groups"={"result"}}, + * "denormalization_context"={"groups"={"sum"}} + * }, + * "sumNoWriteCustomResult"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result", + * "normalization_context"={"groups"={"result"}}, + * "denormalization_context"={"groups"={"sum"}}, + * "write"=false + * }, + * "sumOnlyPersist"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist_document", + * "normalization_context"={"groups"={"result"}}, + * "denormalization_context"={"groups"={"sum"}}, + * "read"=false, + * "deserialize"=false, + * "validate"=false, + * "serialize"=false + * }, + * "testCustomArguments"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom", + * "args"={"operandC"={"type"="Int!"}} + * } + * }) + * * @author Raoul Clais */ -#[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist_document', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']]), new Mutation(name: 'testOutput', resolver: 'app.graphql.mutation_resolver.dummy_custom', output: OutputDto::class)])] -#[ODM\Document] class DummyCustomMutation { - #[ODM\Id(strategy: 'INCREMENT', type: 'int')] - private ?int $id = null; - #[ODM\Field(type: 'int')] - private ?int $operandA = null; - #[Groups(['sum'])] - #[ODM\Field(type: 'int', nullable: true)] - private ?int $operandB = null; - #[Groups(['result'])] - #[ODM\Field(type: 'int', nullable: true)] - private ?int $result = null; + /** + * @var int|null + * + * @ODM\Id(strategy="INCREMENT", type="int") + */ + private $id; + + /** + * @var int|null + * + * @ODM\Field(type="int") + */ + private $operandA; + + /** + * @var int|null + * + * @Groups({"sum"}) + * @ODM\Field(type="int", nullable=true) + */ + private $operandB; + + /** + * @var int|null + * + * @Groups({"result"}) + * @ODM\Field(type="int", nullable=true) + */ + private $result; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php index 566b397485a..c8e0ba438f5 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php @@ -13,30 +13,71 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\GraphQl\Query; -use ApiPlatform\Metadata\GraphQl\QueryCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Core\Annotation\ApiResource; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** * Dummy with custom GraphQL query resolvers. * * @author Lukas Lücke + * + * @ApiResource(graphql={ + * "testItem"={ + * "item_query"="app.graphql.query_resolver.dummy_custom_item" + * }, + * "testNotRetrievedItem"={ + * "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item_document", + * "args"={} + * }, + * "testNoReadAndSerializeItem"={ + * "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document", + * "read"=false, + * "serialize"=false + * }, + * "testItemCustomArguments"={ + * "item_query"="app.graphql.query_resolver.dummy_custom_item", + * "args"={ + * "id"={"type"="ID"}, + * "customArgumentNullableBool"={"type"="Boolean"}, + * "customArgumentBool"={"type"="Boolean!"}, + * "customArgumentInt"={"type"="Int!"}, + * "customArgumentString"={"type"="String!"}, + * "customArgumentFloat"={"type"="Float!"}, + * "customArgumentIntArray"={"type"="[Int!]!"}, + * "customArgumentCustomType"={"type"="DateTime!"} + * } + * }, + * "testCollection"={ + * "collection_query"="app.graphql.query_resolver.dummy_custom_collection" + * }, + * "testCollectionNoReadAndSerialize"={ + * "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize", + * "read"=false, + * "serialize"=false + * }, + * "testCollectionCustomArguments"={ + * "collection_query"="app.graphql.query_resolver.dummy_custom_collection", + * "args"={ + * "customArgumentString"={"type"="String!"} + * } + * } + * }) + * @ODM\Document */ -#[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item_document', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new Query(name: 'testItemOutput', resolver: 'app.graphql.query_resolver.dummy_custom_item', output: OutputDto::class), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])] -#[ODM\Document] class DummyCustomQuery { /** * @var int + * + * @ODM\Id(strategy="INCREMENT", type="int") */ - #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; + /** * @var string */ public $message; + /** * @var array */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php index afc9d79681b..d14ccdb0f86 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php @@ -13,33 +13,81 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\GraphQl\Mutation; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Core\Annotation\ApiResource; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy with a custom GraphQL mutation resolver. * + * @ORM\Entity + * @ApiResource(graphql={ + * "sum"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom", + * "normalization_context"={"groups"={"result"}}, + * "denormalization_context"={"groups"={"sum"}} + * }, + * "sumNotPersisted"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted", + * "normalization_context"={"groups"={"result"}}, + * "denormalization_context"={"groups"={"sum"}} + * }, + * "sumNoWriteCustomResult"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result", + * "normalization_context"={"groups"={"result"}}, + * "denormalization_context"={"groups"={"sum"}}, + * "write"=false + * }, + * "sumOnlyPersist"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist", + * "normalization_context"={"groups"={"result"}}, + * "denormalization_context"={"groups"={"sum"}}, + * "read"=false, + * "deserialize"=false, + * "validate"=false, + * "serialize"=false + * }, + * "testCustomArguments"={ + * "mutation"="app.graphql.mutation_resolver.dummy_custom", + * "args"={"operandC"={"type"="Int!"}} + * } + * }) + * * @author Raoul Clais */ -#[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']]), new Mutation(name: 'testOutput', resolver: 'app.graphql.mutation_resolver.dummy_custom', output: OutputDto::class)])] -#[ORM\Entity] class DummyCustomMutation { - #[ORM\Column(type: 'integer')] - #[ORM\Id] - #[ORM\GeneratedValue(strategy: 'AUTO')] - private ?int $id = null; - #[ORM\Column(type: 'integer', nullable: true)] - private ?int $operandA = null; - #[Groups(['sum'])] - #[ORM\Column(type: 'integer', nullable: true)] - private ?int $operandB = null; - #[Groups(['result'])] - #[ORM\Column(type: 'integer', nullable: true)] - private ?int $result = null; + /** + * @var int|null + * + * @ORM\Column(type="integer") + * @ORM\Id + * @ORM\GeneratedValue(strategy="AUTO") + */ + private $id; + + /** + * @var int|null + * + * @ORM\Column(type="integer", nullable=true) + */ + private $operandA; + + /** + * @var int|null + * + * @Groups({"sum"}) + * @ORM\Column(type="integer", nullable=true) + */ + private $operandB; + + /** + * @var int|null + * + * @Groups({"result"}) + * @ORM\Column(type="integer", nullable=true) + */ + private $result; public function getId(): ?int { diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php index 53ef85c2944..56240c35a35 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php @@ -13,32 +13,73 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\GraphQl\Query; -use ApiPlatform\Metadata\GraphQl\QueryCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Core\Annotation\ApiResource; use Doctrine\ORM\Mapping as ORM; /** * Dummy with custom GraphQL query resolvers. * * @author Lukas Lücke + * + * @ApiResource(graphql={ + * "testItem"={ + * "item_query"="app.graphql.query_resolver.dummy_custom_item" + * }, + * "testNotRetrievedItem"={ + * "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item", + * "args"={} + * }, + * "testNoReadAndSerializeItem"={ + * "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize", + * "read"=false, + * "serialize"=false + * }, + * "testItemCustomArguments"={ + * "item_query"="app.graphql.query_resolver.dummy_custom_item", + * "args"={ + * "id"={"type"="ID"}, + * "customArgumentNullableBool"={"type"="Boolean"}, + * "customArgumentBool"={"type"="Boolean!"}, + * "customArgumentInt"={"type"="Int!"}, + * "customArgumentString"={"type"="String!"}, + * "customArgumentFloat"={"type"="Float!"}, + * "customArgumentIntArray"={"type"="[Int!]!"}, + * "customArgumentCustomType"={"type"="DateTime!"} + * } + * }, + * "testCollection"={ + * "collection_query"="app.graphql.query_resolver.dummy_custom_collection" + * }, + * "testCollectionNoReadAndSerialize"={ + * "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize", + * "read"=false, + * "serialize"=false + * }, + * "testCollectionCustomArguments"={ + * "collection_query"="app.graphql.query_resolver.dummy_custom_collection", + * "args"={ + * "customArgumentString"={"type"="String!"} + * } + * } + * }) + * @ORM\Entity */ -#[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new Query(name: 'testItemOutput', resolver: 'app.graphql.query_resolver.dummy_custom_item', output: OutputDto::class), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])] -#[ORM\Entity] class DummyCustomQuery { /** * @var int + * + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") */ - #[ORM\Id] - #[ORM\GeneratedValue] - #[ORM\Column(type: 'integer')] public $id; + /** * @var string */ public $message; + /** * @var array */ diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index 73fdaedce0b..d7339ea7b37 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -306,18 +306,6 @@ services: tags: - { name: 'api_platform.data_transformer' } - app.data_transformer.dummy_custom_query_dto: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\DummyCustomQueryDtoDataTransformer' - public: false - tags: - - { name: 'api_platform.data_transformer' } - - app.data_transformer.dummy_custom_mutation_dto: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\DummyCustomMutationDtoDataTransformer' - public: false - tags: - - { name: 'api_platform.data_transformer' } - app.data_transformer.custom_output_dto_fallback_same_class: class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\OutputDtoSameClassTransformer' public: false diff --git a/tests/GraphQl/Type/TypeBuilderTest.php b/tests/GraphQl/Type/TypeBuilderTest.php index 64adb22d7ca..00b2bf76a4d 100644 --- a/tests/GraphQl/Type/TypeBuilderTest.php +++ b/tests/GraphQl/Type/TypeBuilderTest.php @@ -103,23 +103,23 @@ public function testGetResourceObjectType(): void public function testGetResourceObjectTypeOutputClass(): void { $resourceMetadata = new ResourceMetadataCollection('resourceClass', []); - $this->typesContainerProphecy->has('outputName')->shouldBeCalled()->willReturn(false); - $this->typesContainerProphecy->set('outputName', Argument::type(ObjectType::class))->shouldBeCalled(); + $this->typesContainerProphecy->has('shortName')->shouldBeCalled()->willReturn(false); + $this->typesContainerProphecy->set('shortName', Argument::type(ObjectType::class))->shouldBeCalled(); $this->typesContainerProphecy->has('Node')->shouldBeCalled()->willReturn(false); $this->typesContainerProphecy->set('Node', Argument::type(InterfaceType::class))->shouldBeCalled(); /** @var Operation $operation */ - $operation = (new Query())->withShortName('shortName')->withDescription('description')->withOutput(['class' => 'outputClass', 'name' => 'outputName']); + $operation = (new Query())->withShortName('shortName')->withDescription('description')->withOutput(['class' => 'outputClass']); /** @var ObjectType $resourceObjectType */ $resourceObjectType = $this->typeBuilder->getResourceObjectType('resourceClass', $resourceMetadata, $operation, false); - $this->assertSame('outputName', $resourceObjectType->name); + $this->assertSame('shortName', $resourceObjectType->name); $this->assertSame('description', $resourceObjectType->description); $this->assertSame($this->defaultFieldResolver, $resourceObjectType->resolveFieldFn); $this->assertArrayHasKey('interfaces', $resourceObjectType->config); $this->assertArrayHasKey('fields', $resourceObjectType->config); $fieldsBuilderProphecy = $this->prophesize(FieldsBuilderInterface::class); - $fieldsBuilderProphecy->getResourceObjectTypeFields('outputClass', $operation, false, 0, ['class' => 'outputClass', 'name' => 'outputName'])->shouldBeCalled(); + $fieldsBuilderProphecy->getResourceObjectTypeFields('outputClass', $operation, false, 0, ['class' => 'outputClass'])->shouldBeCalled(); $this->fieldsBuilderLocatorProphecy->get('api_platform.graphql.fields_builder')->shouldBeCalled()->willReturn($fieldsBuilderProphecy->reveal()); $resourceObjectType->config['fields'](); } From 7a260bd2ac4527619bcb0f50a7b5f7f048aca6bb Mon Sep 17 00:00:00 2001 From: Danny v W Date: Wed, 15 Jun 2022 08:30:34 +0200 Subject: [PATCH 34/56] Fix binding for ORM AbstractFilter (#4789) --- .../Bundle/DependencyInjection/ApiPlatformExtension.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 208dfe29316..3a5be8d9e23 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -491,8 +491,7 @@ private function registerDoctrineOrmConfiguration(ContainerBuilder $container, a ->addTag('api_platform.doctrine.orm.query_extension.item'); $container->registerForAutoconfiguration(DoctrineQueryCollectionExtensionInterface::class) ->addTag('api_platform.doctrine.orm.query_extension.collection'); - $container->registerForAutoconfiguration(DoctrineOrmAbstractFilter::class) - ->setBindings(['$requestStack' => null]); + $container->registerForAutoconfiguration(DoctrineOrmAbstractFilter::class); $loader->load('doctrine_orm.xml'); From e6ad1574ab9bab147c121d7a7bd7f9cf3720fb5f Mon Sep 17 00:00:00 2001 From: Vincent Date: Wed, 15 Jun 2022 09:05:52 +0200 Subject: [PATCH 35/56] [BUG] Do not rely on api-platform/core attributes classes but on interfaces instead (#4785) * fix: do not rely on api-platform/core attributes classes but on interfaces instead * fix: use HttpOperation::METHOD_POST === ->getMethod() instead of PostOperationInterface --- src/Hydra/Serializer/DocumentationNormalizer.php | 3 +-- .../Factory/AttributesResourceMetadataCollectionFactory.php | 2 +- .../Factory/UriTemplateResourceMetadataCollectionFactory.php | 3 +-- src/OpenApi/Factory/OpenApiFactory.php | 3 +-- src/Symfony/Bundle/DependencyInjection/Configuration.php | 2 +- src/Symfony/Routing/IriConverter.php | 3 +-- 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index 5638b043a29..da91f1db980 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -22,7 +22,6 @@ use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Operation; -use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -241,7 +240,7 @@ private function getHydraOperations(string $resourceClass, ApiResource $resource $hydraOperations = []; foreach ($resourceMetadataCollection as $resourceMetadata) { foreach ($resourceMetadata->getOperations() as $operationName => $operation) { - if (($operation instanceof Post || $operation instanceof CollectionOperationInterface) !== $collection) { + if ((HttpOperation::METHOD_POST === $operation->getMethod() || $operation instanceof CollectionOperationInterface) !== $collection) { continue; } diff --git a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php index e08a5ff8451..1fbf30f0672 100644 --- a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php @@ -226,7 +226,7 @@ private function getOperationWithDefaults(ApiResource $resource, Operation $oper } return [ - sprintf('_api_%s_%s%s', $operation->getUriTemplate() ?: $operation->getShortName(), strtolower($operation->getMethod() ?? HttpOperation::METHOD_GET), $operation instanceof GetCollection ? '_collection' : ''), + sprintf('_api_%s_%s%s', $operation->getUriTemplate() ?: $operation->getShortName(), strtolower($operation->getMethod() ?? HttpOperation::METHOD_GET), $operation instanceof CollectionOperationInterface ? '_collection' : ''), $operation, ]; } diff --git a/src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php index 43abbee0f52..4851eb72b10 100644 --- a/src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php @@ -18,7 +18,6 @@ use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Link; use ApiPlatform\Metadata\Operations; -use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; use ApiPlatform\Operation\PathSegmentNameGeneratorInterface; use Symfony\Component\Routing\Route; @@ -137,7 +136,7 @@ private function configureUriVariables($operation) $operation = $this->normalizeUriVariables($operation); if (!($uriTemplate = $operation->getUriTemplate())) { - if ($operation instanceof Post) { + if ($operation instanceof HttpOperation && HttpOperation::METHOD_POST === $operation->getMethod()) { return $operation->withUriVariables([]); } diff --git a/src/OpenApi/Factory/OpenApiFactory.php b/src/OpenApi/Factory/OpenApiFactory.php index ffc9ced1362..3d41b3acde8 100644 --- a/src/OpenApi/Factory/OpenApiFactory.php +++ b/src/OpenApi/Factory/OpenApiFactory.php @@ -21,7 +21,6 @@ use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Operation; -use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -228,7 +227,7 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection break; } - if (!$operation instanceof CollectionOperationInterface && !$operation instanceof Post) { + if (!$operation instanceof CollectionOperationInterface && HttpOperation::METHOD_POST !== $operation->getMethod()) { $responses['404'] = new Model\Response('Resource not found'); } diff --git a/src/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/DependencyInjection/Configuration.php index 26d0f402d33..53d5ccd50fa 100644 --- a/src/Symfony/Bundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/DependencyInjection/Configuration.php @@ -14,11 +14,11 @@ namespace ApiPlatform\Symfony\Bundle\DependencyInjection; use ApiPlatform\Core\Annotation\ApiResource as LegacyApiResource; -use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface; use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata; use ApiPlatform\Exception\FilterValidationException; use ApiPlatform\Exception\InvalidArgumentException; +use ApiPlatform\Metadata\ApiResource; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle; use Doctrine\ORM\EntityManagerInterface; diff --git a/src/Symfony/Routing/IriConverter.php b/src/Symfony/Routing/IriConverter.php index da1d6d10115..1bc3b6abb02 100644 --- a/src/Symfony/Routing/IriConverter.php +++ b/src/Symfony/Routing/IriConverter.php @@ -28,7 +28,6 @@ use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Operation; -use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\State\ProviderInterface; use ApiPlatform\State\UriVariablesResolverTrait; @@ -137,7 +136,7 @@ public function getIriFromResource($item, int $referenceType = UrlGeneratorInter // In symfony the operation name is the route name, try to find one if none provided if ( !$operation->getName() - || $operation instanceof Post + || ($operation instanceof HttpOperation && HttpOperation::METHOD_POST === $operation->getMethod()) || $isLegacySubresource || $isLegacyCustomResource ) { From 8b666f1db37504c88e15de2decc0124ad59d837e Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 17 Jun 2022 10:22:27 +0200 Subject: [PATCH 36/56] fix targetentity as string-class --- .../TestBundle/Entity/AbsoluteUrlDummy.php | 2 +- .../Entity/AbsoluteUrlRelationDummy.php | 2 +- tests/Fixtures/TestBundle/Entity/Answer.php | 4 +-- .../TestBundle/Entity/CircularReference.php | 4 +-- .../TestBundle/Entity/CompositeItem.php | 2 +- .../TestBundle/Entity/CompositeRelation.php | 4 +-- .../TestBundle/Entity/ConvertedOwner.php | 2 +- tests/Fixtures/TestBundle/Entity/Customer.php | 2 +- tests/Fixtures/TestBundle/Entity/Dummy.php | 4 +-- .../TestBundle/Entity/DummyAggregateOffer.php | 4 +-- tests/Fixtures/TestBundle/Entity/DummyCar.php | 8 +++--- .../TestBundle/Entity/DummyCarColor.php | 2 +- .../TestBundle/Entity/DummyDtoCustom.php | 13 ++++++++- .../TestBundle/Entity/DummyDtoInputOutput.php | 2 +- .../TestBundle/Entity/DummyMercure.php | 2 +- .../Fixtures/TestBundle/Entity/DummyOffer.php | 2 +- .../TestBundle/Entity/DummyProduct.php | 8 +++--- .../Entity/DummyTableInheritance.php | 2 +- .../Entity/DummyTableInheritanceRelated.php | 2 +- .../TestBundle/Entity/DummyTravel.php | 4 +-- .../TestBundle/Entity/EmbeddedDummy.php | 4 +-- tests/Fixtures/TestBundle/Entity/FooDummy.php | 2 +- tests/Fixtures/TestBundle/Entity/Greeting.php | 4 +-- .../TestBundle/Entity/MaxDepthDummy.php | 2 +- .../TestBundle/Entity/MaxDepthEagerDummy.php | 2 +- .../TestBundle/Entity/NetworkPathDummy.php | 2 +- .../Entity/NetworkPathRelationDummy.php | 2 +- tests/Fixtures/TestBundle/Entity/Order.php | 4 +-- .../TestBundle/Entity/PatchDummyRelation.php | 2 +- tests/Fixtures/TestBundle/Entity/Person.php | 4 +-- .../TestBundle/Entity/PersonToPet.php | 4 +-- tests/Fixtures/TestBundle/Entity/Pet.php | 2 +- tests/Fixtures/TestBundle/Entity/Question.php | 2 +- .../TestBundle/Entity/RelatedDummy.php | 4 +-- .../Entity/RelatedNormalizedDummy.php | 2 +- .../TestBundle/Entity/RelatedOwnedDummy.php | 2 +- .../TestBundle/Entity/RelatedOwningDummy.php | 2 +- .../Entity/RelatedToDummyFriend.php | 4 +-- .../Fixtures/TestBundle/Entity/Relation1.php | 2 +- .../Fixtures/TestBundle/Entity/Relation2.php | 2 +- .../Fixtures/TestBundle/Entity/Relation3.php | 4 +-- .../TestBundle/Entity/RelationEmbedder.php | 4 +-- .../TestBundle/Entity/SecuredDummy.php | 12 ++++----- tests/Fixtures/TestBundle/Entity/Site.php | 2 +- .../Fixtures/TestBundle/Entity/ThirdLevel.php | 2 +- .../Fixtures/TestBundle/Entity/VoDummyCar.php | 2 +- .../TestBundle/Entity/VoDummyInspection.php | 2 +- .../TestBundle/Entity/VoDummyVehicle.php | 6 ++--- .../State/DummyDtoCustomProcessor.php | 27 +++++++++++++++++++ 49 files changed, 114 insertions(+), 76 deletions(-) create mode 100644 tests/Fixtures/TestBundle/State/DummyDtoCustomProcessor.php diff --git a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php index 7e77c5a4885..4c60538af40 100644 --- a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlDummy.php @@ -28,7 +28,7 @@ class AbsoluteUrlDummy #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private $id; - #[ORM\ManyToOne(targetEntity: 'AbsoluteUrlRelationDummy', inversedBy: 'absoluteUrlDummies')] + #[ORM\ManyToOne(targetEntity: AbsoluteUrlRelationDummy::class, inversedBy: 'absoluteUrlDummies')] public $absoluteUrlRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php index 325d559018f..ffc95fca949 100644 --- a/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/AbsoluteUrlRelationDummy.php @@ -26,7 +26,7 @@ class AbsoluteUrlRelationDummy #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private $id; - #[ORM\OneToMany(targetEntity: 'AbsoluteUrlDummy', mappedBy: 'absoluteUrlRelationDummy')] + #[ORM\OneToMany(targetEntity: AbsoluteUrlDummy::class, mappedBy: 'absoluteUrlRelationDummy')] public $absoluteUrlDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/Answer.php b/tests/Fixtures/TestBundle/Entity/Answer.php index 794abea9866..bbc89f5abb0 100644 --- a/tests/Fixtures/TestBundle/Entity/Answer.php +++ b/tests/Fixtures/TestBundle/Entity/Answer.php @@ -42,13 +42,13 @@ class Answer #[ORM\Column(nullable: false)] #[Serializer\Groups(['foobar'])] private $content; - #[ORM\OneToOne(targetEntity: 'Question', mappedBy: 'answer')] + #[ORM\OneToOne(targetEntity: Question::class, mappedBy: 'answer')] #[Serializer\Groups(['foobar'])] private $question; /** * @var \Collection */ - #[ORM\OneToMany(targetEntity: 'Question', mappedBy: 'answer')] + #[ORM\OneToMany(targetEntity: Question::class, mappedBy: 'answer')] #[Serializer\Groups(['foobar'])] private readonly \Collection $relatedQuestions; diff --git a/tests/Fixtures/TestBundle/Entity/CircularReference.php b/tests/Fixtures/TestBundle/Entity/CircularReference.php index fd39438fa51..7f8ee99ea55 100644 --- a/tests/Fixtures/TestBundle/Entity/CircularReference.php +++ b/tests/Fixtures/TestBundle/Entity/CircularReference.php @@ -31,10 +31,10 @@ class CircularReference #[ORM\Id] #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - #[ORM\ManyToOne(targetEntity: 'CircularReference', inversedBy: 'children')] + #[ORM\ManyToOne(targetEntity: CircularReference::class, inversedBy: 'children')] #[Groups(['circular'])] public $parent; - #[ORM\OneToMany(targetEntity: 'CircularReference', mappedBy: 'parent')] + #[ORM\OneToMany(targetEntity: CircularReference::class, mappedBy: 'parent')] #[Groups(['circular'])] public $children; diff --git a/tests/Fixtures/TestBundle/Entity/CompositeItem.php b/tests/Fixtures/TestBundle/Entity/CompositeItem.php index b3c3a3acd54..0bb9dd457dc 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeItem.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeItem.php @@ -32,7 +32,7 @@ class CompositeItem implements \Stringable #[ORM\Column(type: 'string', nullable: true)] #[Groups(['default'])] private $field1; - #[ORM\OneToMany(targetEntity: 'CompositeRelation', mappedBy: 'compositeItem', fetch: 'EAGER')] + #[ORM\OneToMany(targetEntity: CompositeRelation::class, mappedBy: 'compositeItem', fetch: 'EAGER')] #[Groups(['default'])] private $compositeValues; diff --git a/tests/Fixtures/TestBundle/Entity/CompositeRelation.php b/tests/Fixtures/TestBundle/Entity/CompositeRelation.php index 986190d039f..72d1c299467 100644 --- a/tests/Fixtures/TestBundle/Entity/CompositeRelation.php +++ b/tests/Fixtures/TestBundle/Entity/CompositeRelation.php @@ -28,12 +28,12 @@ class CompositeRelation #[Groups(['default'])] private $value; #[ORM\Id] - #[ORM\ManyToOne(targetEntity: 'CompositeItem', inversedBy: 'compositeValues')] + #[ORM\ManyToOne(targetEntity: CompositeItem::class, inversedBy: 'compositeValues')] #[ORM\JoinColumn(name: 'composite_item_id', referencedColumnName: 'id', nullable: false)] #[Groups(['default'])] private $compositeItem; #[ORM\Id] - #[ORM\ManyToOne(targetEntity: 'CompositeLabel')] + #[ORM\ManyToOne(targetEntity: CompositeLabel::class)] #[ORM\JoinColumn(name: 'composite_label_id', referencedColumnName: 'id', nullable: false)] #[Groups(['default'])] private $compositeLabel; diff --git a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php index 527bfa3e1b0..90c19e26681 100644 --- a/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php +++ b/tests/Fixtures/TestBundle/Entity/ConvertedOwner.php @@ -30,7 +30,7 @@ class ConvertedOwner /** * @var ConvertedRelated|null */ - #[ORM\ManyToOne(targetEntity: 'ConvertedRelated')] + #[ORM\ManyToOne(targetEntity: ConvertedRelated::class)] public $nameConverted; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Customer.php b/tests/Fixtures/TestBundle/Entity/Customer.php index 9b1cd169869..7ed79841afc 100644 --- a/tests/Fixtures/TestBundle/Entity/Customer.php +++ b/tests/Fixtures/TestBundle/Entity/Customer.php @@ -30,7 +30,7 @@ class Customer #[ORM\Column(type: 'string')] #[Groups(['order_read'])] public $name; - #[ORM\ManyToMany(targetEntity: 'Address')] + #[ORM\ManyToMany(targetEntity: Address::class)] #[ORM\JoinColumn(nullable: false)] #[Groups(['order_read'])] public $addresses; diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index 32439d08b7e..68f17887305 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -129,13 +129,13 @@ class Dummy /** * @var RelatedOwnedDummy|null */ - #[ORM\OneToOne(targetEntity: 'RelatedOwnedDummy', cascade: ['persist'], mappedBy: 'owningDummy')] + #[ORM\OneToOne(targetEntity: RelatedOwnedDummy::class, cascade: ['persist'], mappedBy: 'owningDummy')] public $relatedOwnedDummy; /** * @var RelatedOwningDummy|null */ - #[ORM\OneToOne(targetEntity: 'RelatedOwningDummy', cascade: ['persist'], inversedBy: 'ownedDummy')] + #[ORM\OneToOne(targetEntity: RelatedOwningDummy::class, cascade: ['persist'], inversedBy: 'ownedDummy')] public $relatedOwningDummy; public static function staticMethod() diff --git a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php index 0170447827f..6097e450a49 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php @@ -42,12 +42,12 @@ class DummyAggregateOffer /** * @var \Collection */ - #[ORM\OneToMany(targetEntity: 'DummyOffer', mappedBy: 'aggregate', cascade: ['persist'])] + #[ORM\OneToMany(targetEntity: DummyOffer::class, mappedBy: 'aggregate', cascade: ['persist'])] private \Collection $offers; /** * @var DummyProduct|null The dummy product */ - #[ORM\ManyToOne(targetEntity: 'DummyProduct', inversedBy: 'offers')] + #[ORM\ManyToOne(targetEntity: DummyProduct::class, inversedBy: 'offers')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyProduct $product = null; /** * @var int The dummy aggregate offer value diff --git a/tests/Fixtures/TestBundle/Entity/DummyCar.php b/tests/Fixtures/TestBundle/Entity/DummyCar.php index 5e15af8c267..c82faf6f1e1 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCar.php @@ -42,27 +42,27 @@ class DummyCar * @var DummyCarIdentifier The entity Id */ #[ORM\Id] - #[ORM\OneToOne(targetEntity: 'DummyCarIdentifier', cascade: ['persist'])] + #[ORM\OneToOne(targetEntity: DummyCarIdentifier::class, cascade: ['persist'])] private readonly \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCarIdentifier $id; /** * @var mixed Something else */ #[ApiFilter(SearchFilter::class, properties: ['colors.prop' => 'ipartial', 'colors' => 'exact'])] - #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[ORM\OneToMany(targetEntity: DummyCarColor::class, mappedBy: 'car')] #[Serializer\Groups(['colors'])] private $colors; /** * @var mixed Something else */ #[ApiFilter(SearchFilter::class, strategy: 'exact')] - #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[ORM\OneToMany(targetEntity: DummyCarColor::class, mappedBy: 'car')] #[Serializer\Groups(['colors'])] private mixed $secondColors = null; /** * @var mixed Something else */ #[ApiFilter(SearchFilter::class, strategy: 'exact')] - #[ORM\OneToMany(targetEntity: 'DummyCarColor', mappedBy: 'car')] + #[ORM\OneToMany(targetEntity: DummyCarColor::class, mappedBy: 'car')] #[Serializer\Groups(['colors'])] private mixed $thirdColors = null; /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php index 70bf44e4563..f50f25ffe7f 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCarColor.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCarColor.php @@ -31,7 +31,7 @@ class DummyCarColor #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private ?int $id = null; - #[ORM\ManyToOne(targetEntity: 'DummyCar', inversedBy: 'colors')] + #[ORM\ManyToOne(targetEntity: DummyCar::class, inversedBy: 'colors')] #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE', referencedColumnName: 'id_id')] #[Assert\NotBlank] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyCar $car = null; diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php index f6e3eae814b..abd19524d29 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php @@ -26,7 +26,18 @@ /** * DummyDtoCustom. */ -#[ApiResource(operations: [new Get(), new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), new Put(), new Delete(), new Post(input: CustomInputDto::class), new GetCollection(), new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output')])] +#[ApiResource( + operations: [ + new Get(), + new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), + new Put(), + new Delete(), + new Post(input: CustomInputDto::class), + new GetCollection(), + new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), + new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output') + ] +)] #[ORM\Entity] class DummyDtoCustom { diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php index fd64076d9df..926e94eeced 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php @@ -53,6 +53,6 @@ public function __construct() /** * @var Collection */ - #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] + #[ORM\ManyToMany(targetEntity: RelatedDummy::class)] public $relatedDummies; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyMercure.php b/tests/Fixtures/TestBundle/Entity/DummyMercure.php index a105d78c0ab..978d732d238 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyMercure.php +++ b/tests/Fixtures/TestBundle/Entity/DummyMercure.php @@ -31,6 +31,6 @@ class DummyMercure public $name; #[ORM\Column] public $description; - #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[ORM\ManyToOne(targetEntity: RelatedDummy::class)] public $relatedDummy; } diff --git a/tests/Fixtures/TestBundle/Entity/DummyOffer.php b/tests/Fixtures/TestBundle/Entity/DummyOffer.php index 83ca3822670..570ccb7da13 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyOffer.php @@ -47,7 +47,7 @@ class DummyOffer /** * @var DummyAggregateOffer|null The dummy aggregate offer value */ - #[ORM\ManyToOne(targetEntity: 'DummyAggregateOffer', inversedBy: 'offers')] + #[ORM\ManyToOne(targetEntity: DummyAggregateOffer::class, inversedBy: 'offers')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer $aggregate = null; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/DummyProduct.php b/tests/Fixtures/TestBundle/Entity/DummyProduct.php index df599baa2bd..f3184faea3a 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Entity/DummyProduct.php @@ -42,8 +42,8 @@ class DummyProduct /** * @var \Collection */ - #[ORM\OneToMany(targetEntity: 'DummyAggregateOffer', mappedBy: 'product', cascade: ['persist'])] - private \Collection $offers; + #[ORM\OneToMany(targetEntity: DummyAggregateOffer::class, mappedBy: 'product', cascade: ['persist'])] + private Collection $offers; /** * @var string The tour name */ @@ -52,8 +52,8 @@ class DummyProduct /** * @var \Collection */ - #[ORM\OneToMany(targetEntity: 'DummyProduct', mappedBy: 'parent')] - private \Collection $relatedProducts; + #[ORM\OneToMany(targetEntity: DummyProduct::class, mappedBy: 'parent')] + private Collection $relatedProducts; #[ORM\ManyToOne(targetEntity: 'DummyProduct', inversedBy: 'relatedProducts')] private $parent; diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php index 5ab4ee6d8a8..42a714da40e 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritance.php @@ -38,7 +38,7 @@ class DummyTableInheritance #[ORM\Column] #[Groups(['default'])] private ?string $name = null; - #[ORM\ManyToOne(targetEntity: 'DummyTableInheritanceRelated', inversedBy: 'children')] + #[ORM\ManyToOne(targetEntity: DummyTableInheritanceRelated::class, inversedBy: 'children')] #[ORM\JoinColumn(nullable: true, onDelete: 'CASCADE')] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceRelated $parent = null; diff --git a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php index a363fbc1207..c0a4145bbc4 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTableInheritanceRelated.php @@ -34,7 +34,7 @@ class DummyTableInheritanceRelated /** * @var Collection Related children */ - #[ORM\OneToMany(targetEntity: 'DummyTableInheritance', mappedBy: 'parent')] + #[ORM\OneToMany(targetEntity: DummyTableInheritance::class, mappedBy: 'parent')] #[ORM\OrderBy(['id' => 'ASC'])] #[Groups(['default'])] private \Doctrine\Common\Collections\Collection $children; diff --git a/tests/Fixtures/TestBundle/Entity/DummyTravel.php b/tests/Fixtures/TestBundle/Entity/DummyTravel.php index 67e220ebbee..eb334b103fd 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyTravel.php +++ b/tests/Fixtures/TestBundle/Entity/DummyTravel.php @@ -24,12 +24,12 @@ class DummyTravel #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private $id; - #[ORM\ManyToOne(targetEntity: 'DummyCar')] + #[ORM\ManyToOne(targetEntity: DummyCar::class)] #[ORM\JoinColumn(name: 'car_id', referencedColumnName: 'id_id')] public $car; #[ORM\Column(type: 'boolean')] public $confirmed; - #[ORM\ManyToOne(targetEntity: 'DummyPassenger')] + #[ORM\ManyToOne(targetEntity: DummyPassenger::class)] #[ORM\JoinColumn(name: 'passenger_id', referencedColumnName: 'id')] public $passenger; diff --git a/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php b/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php index 962086052b6..9dccc3c60ec 100644 --- a/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/EmbeddedDummy.php @@ -54,13 +54,13 @@ class EmbeddedDummy /** * @var EmbeddableDummy */ - #[ORM\Embedded(class: 'EmbeddableDummy')] + #[ORM\Embedded(class: EmbeddableDummy::class)] #[Groups(['embed'])] public $embeddedDummy; /** * @var RelatedDummy|null A related dummy */ - #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[ORM\ManyToOne(targetEntity: RelatedDummy::class)] public $relatedDummy; public static function staticMethod() diff --git a/tests/Fixtures/TestBundle/Entity/FooDummy.php b/tests/Fixtures/TestBundle/Entity/FooDummy.php index f86d52590a0..98af15d9073 100644 --- a/tests/Fixtures/TestBundle/Entity/FooDummy.php +++ b/tests/Fixtures/TestBundle/Entity/FooDummy.php @@ -41,7 +41,7 @@ class FooDummy /** * @var Dummy|null The foo dummy */ - #[ORM\ManyToOne(targetEntity: 'Dummy', cascade: ['persist'])] + #[ORM\ManyToOne(targetEntity: Dummy::class, cascade: ['persist'])] private ?\ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy $dummy = null; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/Greeting.php b/tests/Fixtures/TestBundle/Entity/Greeting.php index bb837e60f26..491d60dd2cb 100644 --- a/tests/Fixtures/TestBundle/Entity/Greeting.php +++ b/tests/Fixtures/TestBundle/Entity/Greeting.php @@ -29,10 +29,10 @@ class Greeting private $id; #[ORM\Column] public $message = ''; - #[ORM\ManyToOne(targetEntity: 'Person', inversedBy: 'sentGreetings')] + #[ORM\ManyToOne(targetEntity: Person::class, inversedBy: 'sentGreetings')] #[ORM\JoinColumn(name: 'sender_id')] public $sender; - #[ORM\ManyToOne(targetEntity: 'Person')] + #[ORM\ManyToOne(targetEntity: Person::class)] #[ORM\JoinColumn(name: 'recipient_id', nullable: true)] public $recipient; diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php index 68145c42e65..758710f9ac1 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php @@ -37,7 +37,7 @@ class MaxDepthDummy public $name; #[ApiProperty(fetchEager: false)] - #[ORM\ManyToOne(targetEntity: 'MaxDepthDummy', cascade: ['persist'])] + #[ORM\ManyToOne(targetEntity: MaxDepthDummy::class, cascade: ['persist'])] #[Groups(['default'])] #[MaxDepth(1)] public $child; diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php index decfa604b06..cf1e6d95233 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php @@ -36,7 +36,7 @@ class MaxDepthEagerDummy #[ORM\Column(name: 'name', type: 'string', length: 30)] #[Groups(['default'])] public $name; - #[ORM\ManyToOne(targetEntity: 'MaxDepthEagerDummy', cascade: ['persist'])] + #[ORM\ManyToOne(targetEntity: MaxDepthEagerDummy::class, cascade: ['persist'])] #[Groups(['default'])] #[MaxDepth(1)] public $child; diff --git a/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php b/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php index a53282c9343..aaa2eea17e5 100644 --- a/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NetworkPathDummy.php @@ -28,7 +28,7 @@ class NetworkPathDummy #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private $id; - #[ORM\ManyToOne(targetEntity: 'NetworkPathRelationDummy', inversedBy: 'networkPathDummies')] + #[ORM\ManyToOne(targetEntity: NetworkPathRelationDummy::class, inversedBy: 'networkPathDummies')] public $networkPathRelationDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php b/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php index aaef9ffd342..8906b1aed48 100644 --- a/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php +++ b/tests/Fixtures/TestBundle/Entity/NetworkPathRelationDummy.php @@ -26,7 +26,7 @@ class NetworkPathRelationDummy #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private $id; - #[ORM\OneToMany(targetEntity: 'NetworkPathDummy', mappedBy: 'networkPathRelationDummy')] + #[ORM\OneToMany(targetEntity: NetworkPathDummy::class, mappedBy: 'networkPathRelationDummy')] public $networkPathDummies; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/Order.php b/tests/Fixtures/TestBundle/Entity/Order.php index ef60d9fc4a8..35dd6185ccf 100644 --- a/tests/Fixtures/TestBundle/Entity/Order.php +++ b/tests/Fixtures/TestBundle/Entity/Order.php @@ -28,11 +28,11 @@ class Order #[ORM\GeneratedValue(strategy: 'AUTO')] #[Groups(['order_read'])] private ?int $id = null; - #[ORM\ManyToOne(targetEntity: 'Customer')] + #[ORM\ManyToOne(targetEntity: Customer::class)] #[ORM\JoinColumn(nullable: false)] #[Groups(['order_read'])] public $customer; - #[ORM\ManyToOne(targetEntity: 'Customer')] + #[ORM\ManyToOne(targetEntity: Customer::class)] #[ORM\JoinColumn(nullable: false)] #[Assert\NotNull] #[Groups(['order_read'])] diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php index 221e39fc8af..bd567060d8e 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php @@ -32,7 +32,7 @@ class PatchDummyRelation #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[ORM\ManyToOne(targetEntity: RelatedDummy::class)] #[Groups(['chicago'])] protected $related; diff --git a/tests/Fixtures/TestBundle/Entity/Person.php b/tests/Fixtures/TestBundle/Entity/Person.php index f53b1b484a6..509ef615998 100644 --- a/tests/Fixtures/TestBundle/Entity/Person.php +++ b/tests/Fixtures/TestBundle/Entity/Person.php @@ -38,10 +38,10 @@ class Person /** * @var Collection */ - #[ORM\OneToMany(targetEntity: 'PersonToPet', mappedBy: 'person')] + #[ORM\OneToMany(targetEntity: PersonToPet::class, mappedBy: 'person')] #[Groups(['people.pets'])] public $pets; - #[ORM\OneToMany(targetEntity: 'Greeting', mappedBy: 'sender')] + #[ORM\OneToMany(targetEntity: Greeting::class, mappedBy: 'sender')] public $sentGreetings; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/PersonToPet.php b/tests/Fixtures/TestBundle/Entity/PersonToPet.php index 8e098f5f91d..30b1f7c9aaf 100644 --- a/tests/Fixtures/TestBundle/Entity/PersonToPet.php +++ b/tests/Fixtures/TestBundle/Entity/PersonToPet.php @@ -28,7 +28,7 @@ class PersonToPet * @var Pet */ #[ORM\Id] - #[ORM\ManyToOne(targetEntity: 'Pet')] + #[ORM\ManyToOne(targetEntity: Pet::class)] #[ORM\JoinColumn(referencedColumnName: 'id')] #[Groups(['people.pets'])] public $pet; @@ -36,7 +36,7 @@ class PersonToPet * @var Person */ #[ORM\Id] - #[ORM\ManyToOne(targetEntity: 'Person')] + #[ORM\ManyToOne(targetEntity: Person::class)] #[ORM\JoinColumn(referencedColumnName: 'id')] public $person; } diff --git a/tests/Fixtures/TestBundle/Entity/Pet.php b/tests/Fixtures/TestBundle/Entity/Pet.php index 27ed27166c2..a3d1a2b7ee7 100644 --- a/tests/Fixtures/TestBundle/Entity/Pet.php +++ b/tests/Fixtures/TestBundle/Entity/Pet.php @@ -38,7 +38,7 @@ class Pet /** * @var Collection */ - #[ORM\OneToMany(targetEntity: 'PersonToPet', mappedBy: 'pet')] + #[ORM\OneToMany(targetEntity: PersonToPet::class, mappedBy: 'pet')] public $people; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/Question.php b/tests/Fixtures/TestBundle/Entity/Question.php index 09949775e3b..aa9ac63613d 100644 --- a/tests/Fixtures/TestBundle/Entity/Question.php +++ b/tests/Fixtures/TestBundle/Entity/Question.php @@ -31,7 +31,7 @@ class Question private $id; #[ORM\Column(nullable: true)] private $content; - #[ORM\OneToOne(targetEntity: 'Answer', inversedBy: 'question')] + #[ORM\OneToOne(targetEntity: Answer::class, inversedBy: 'question')] #[ORM\JoinColumn(name: 'answer_id', referencedColumnName: 'id', unique: true)] private $answer; diff --git a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php index 5cbbf05a777..255a1036a46 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php @@ -68,11 +68,11 @@ class RelatedDummy extends ParentDummy #[Groups(['friends'])] public $dummyDate; - #[ORM\ManyToOne(targetEntity: 'ThirdLevel', cascade: ['persist'])] + #[ORM\ManyToOne(targetEntity: ThirdLevel::class, cascade: ['persist'])] #[Groups(['barcelona', 'chicago', 'friends'])] public $thirdLevel; - #[ORM\OneToMany(targetEntity: 'RelatedToDummyFriend', cascade: ['persist'], mappedBy: 'relatedDummy')] + #[ORM\OneToMany(targetEntity: RelatedToDummyFriend::class, cascade: ['persist'], mappedBy: 'relatedDummy')] #[Groups(['fakemanytomany', 'friends'])] public $relatedToDummyFriend; diff --git a/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php index 56216cdd0a1..c60553ffe9c 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedNormalizedDummy.php @@ -50,7 +50,7 @@ class RelatedNormalizedDummy /** * @var Collection Several Normalized dummies */ - #[ORM\ManyToMany(targetEntity: 'CustomNormalizedDummy')] + #[ORM\ManyToMany(targetEntity: CustomNormalizedDummy::class)] #[Groups(['related_output', 'related_input'])] public $customNormalizedDummy; diff --git a/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php index f13139a6150..5a36dff0968 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedOwnedDummy.php @@ -38,7 +38,7 @@ class RelatedOwnedDummy /** * @var \Dummy */ - #[ORM\OneToOne(targetEntity: 'Dummy', cascade: ['persist'], inversedBy: 'relatedOwnedDummy')] + #[ORM\OneToOne(targetEntity: Dummy::class, cascade: ['persist'], inversedBy: 'relatedOwnedDummy')] #[ORM\JoinColumn(nullable: false)] public $owningDummy; diff --git a/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php index b11b684a2f0..6e5fcfb21dc 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedOwningDummy.php @@ -38,7 +38,7 @@ class RelatedOwningDummy /** * @var \Dummy|null */ - #[ORM\OneToOne(targetEntity: 'Dummy', cascade: ['persist'], mappedBy: 'relatedOwningDummy')] + #[ORM\OneToOne(targetEntity: Dummy::class, cascade: ['persist'], mappedBy: 'relatedOwningDummy')] public $ownedDummy; public function getId() diff --git a/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php b/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php index 108c343108a..55695630618 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedToDummyFriend.php @@ -48,13 +48,13 @@ class RelatedToDummyFriend #[Groups(['fakemanytomany', 'friends'])] private ?string $description = null; #[ORM\Id] - #[ORM\ManyToOne(targetEntity: 'DummyFriend')] + #[ORM\ManyToOne(targetEntity: DummyFriend::class)] #[ORM\JoinColumn(name: 'dummyfriend_id', referencedColumnName: 'id', nullable: false)] #[Groups(['fakemanytomany', 'friends'])] #[Assert\NotNull] private $dummyFriend; #[ORM\Id] - #[ORM\ManyToOne(targetEntity: 'RelatedDummy', inversedBy: 'relatedToDummyFriend')] + #[ORM\ManyToOne(targetEntity: RelatedDummy::class, inversedBy: 'relatedToDummyFriend')] #[ORM\JoinColumn(name: 'relateddummy_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] #[Assert\NotNull] private $relatedDummy; diff --git a/tests/Fixtures/TestBundle/Entity/Relation1.php b/tests/Fixtures/TestBundle/Entity/Relation1.php index 501347320b5..2c420ddeeff 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation1.php +++ b/tests/Fixtures/TestBundle/Entity/Relation1.php @@ -27,6 +27,6 @@ class Relation1 #[ORM\Id] #[ORM\GeneratedValue] public $id; - #[ORM\ManyToOne(targetEntity: 'Relation2', inversedBy: 'relation1s')] + #[ORM\ManyToOne(targetEntity: Relation2::class, inversedBy: 'relation1s')] public $relation2; } diff --git a/tests/Fixtures/TestBundle/Entity/Relation2.php b/tests/Fixtures/TestBundle/Entity/Relation2.php index 61597d71a30..9e7d3888cc8 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation2.php +++ b/tests/Fixtures/TestBundle/Entity/Relation2.php @@ -28,7 +28,7 @@ class Relation2 #[ORM\Id] #[ORM\GeneratedValue] public $id; - #[ORM\OneToMany(targetEntity: 'Relation1', mappedBy: 'relation2')] + #[ORM\OneToMany(targetEntity: Relation1::class, mappedBy: 'relation2')] public $relation1s; public function __construct() diff --git a/tests/Fixtures/TestBundle/Entity/Relation3.php b/tests/Fixtures/TestBundle/Entity/Relation3.php index dd7acd4e412..6eaac03d891 100644 --- a/tests/Fixtures/TestBundle/Entity/Relation3.php +++ b/tests/Fixtures/TestBundle/Entity/Relation3.php @@ -29,8 +29,8 @@ class Relation3 /** * @var Collection */ - #[ORM\ManyToMany(targetEntity: 'Relation2', orphanRemoval: true)] - private readonly \Doctrine\Common\Collections\Collection $relation2s; + #[ORM\ManyToMany(targetEntity: Relation2::class, orphanRemoval: true)] + private \Doctrine\Common\Collections\Collection $relation2s; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php index 8eb6cc79e06..3b61cdf9683 100644 --- a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php @@ -41,10 +41,10 @@ class RelationEmbedder #[ORM\Column] #[Groups(['barcelona', 'chicago'])] public $krondstadt = 'Krondstadt'; - #[ORM\ManyToOne(targetEntity: 'RelatedDummy', cascade: ['persist'])] + #[ORM\ManyToOne(targetEntity: RelatedDummy::class, cascade: ['persist'])] #[Groups(['chicago', 'barcelona'])] public $anotherRelated; - #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[ORM\ManyToOne(targetEntity: RelatedDummy::class)] #[Groups(['barcelona', 'chicago'])] protected $related; diff --git a/tests/Fixtures/TestBundle/Entity/SecuredDummy.php b/tests/Fixtures/TestBundle/Entity/SecuredDummy.php index c82f789baaa..bf9efdbd804 100644 --- a/tests/Fixtures/TestBundle/Entity/SecuredDummy.php +++ b/tests/Fixtures/TestBundle/Entity/SecuredDummy.php @@ -81,7 +81,7 @@ class SecuredDummy * @var Collection Several dummies */ #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] - #[ORM\ManyToMany(targetEntity: 'RelatedDummy')] + #[ORM\ManyToMany(targetEntity: RelatedDummy::class)] #[ORM\JoinTable(name: 'secured_dummy_related_dummy')] public $relatedDummies; @@ -91,7 +91,7 @@ class SecuredDummy * @var RelatedDummy|null */ #[ApiProperty(security: "is_granted('ROLE_ADMIN')")] - #[ORM\ManyToOne(targetEntity: 'RelatedDummy')] + #[ORM\ManyToOne(targetEntity: RelatedDummy::class)] #[ORM\JoinColumn(name: 'related_dummy_id')] protected $relatedDummy; @@ -101,7 +101,7 @@ class SecuredDummy * @var Collection Several dummies */ #[ApiProperty(security: "is_granted('ROLE_USER')")] - #[ORM\ManyToMany(targetEntity: 'RelatedSecuredDummy')] + #[ORM\ManyToMany(targetEntity: RelatedSecuredDummy::class)] #[ORM\JoinTable(name: 'secured_dummy_related_secured_dummy')] public $relatedSecuredDummies; @@ -111,7 +111,7 @@ class SecuredDummy * @var RelatedSecuredDummy|null */ #[ApiProperty(security: "is_granted('ROLE_USER')")] - #[ORM\ManyToOne(targetEntity: 'RelatedSecuredDummy')] + #[ORM\ManyToOne(targetEntity: RelatedSecuredDummy::class)] #[ORM\JoinColumn(name: 'related_secured_dummy_id')] protected $relatedSecuredDummy; @@ -120,7 +120,7 @@ class SecuredDummy * * @var Collection Several dummies */ - #[ORM\ManyToMany(targetEntity: 'RelatedSecuredDummy')] + #[ORM\ManyToMany(targetEntity: RelatedSecuredDummy::class)] #[ORM\JoinTable(name: 'secured_dummy_public_related_secured_dummy')] public $publicRelatedSecuredDummies; @@ -129,7 +129,7 @@ class SecuredDummy * * @var RelatedSecuredDummy|null */ - #[ORM\ManyToOne(targetEntity: 'RelatedSecuredDummy')] + #[ORM\ManyToOne(targetEntity: RelatedSecuredDummy::class)] #[ORM\JoinColumn(name: 'public_related_secured_dummy_id')] protected $publicRelatedSecuredDummy; diff --git a/tests/Fixtures/TestBundle/Entity/Site.php b/tests/Fixtures/TestBundle/Entity/Site.php index 1dcfdd5d35f..eccd33bffe5 100644 --- a/tests/Fixtures/TestBundle/Entity/Site.php +++ b/tests/Fixtures/TestBundle/Entity/Site.php @@ -28,7 +28,7 @@ class Site private $title; #[ORM\Column] private $description; - #[ORM\OneToOne(targetEntity: 'AbstractUser', cascade: ['persist', 'remove'])] + #[ORM\OneToOne(targetEntity: AbstractUser::class, cascade: ['persist', 'remove'])] #[ORM\JoinColumn(nullable: false)] private $owner; diff --git a/tests/Fixtures/TestBundle/Entity/ThirdLevel.php b/tests/Fixtures/TestBundle/Entity/ThirdLevel.php index 67502e04e43..41b00a8a9b9 100644 --- a/tests/Fixtures/TestBundle/Entity/ThirdLevel.php +++ b/tests/Fixtures/TestBundle/Entity/ThirdLevel.php @@ -45,7 +45,7 @@ class ThirdLevel private int $level = 3; #[ORM\Column(type: 'boolean')] private bool $test = true; - #[ORM\ManyToOne(targetEntity: 'FourthLevel', cascade: ['persist'])] + #[ORM\ManyToOne(targetEntity: FourthLevel::class, cascade: ['persist'])] #[Groups(['barcelona', 'chicago', 'friends'])] public $fourthLevel; #[ORM\ManyToOne(targetEntity: FourthLevel::class, cascade: ['persist'])] diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php index 228618067b5..25fe7667332 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php @@ -26,7 +26,7 @@ class VoDummyCar extends VoDummyVehicle /** * @var VoDummyInspection[]|Collection */ - #[ORM\OneToMany(targetEntity: 'VoDummyInspection', mappedBy: 'car', cascade: ['persist'])] + #[ORM\OneToMany(targetEntity: VoDummyInspection::class, mappedBy: 'car', cascade: ['persist'])] #[Groups(['car_read', 'car_write'])] private readonly array|\Doctrine\Common\Collections\Collection $inspections; diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php index 21aac8dc940..7d88ae92d5b 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php @@ -27,7 +27,7 @@ class VoDummyInspection #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private \DateTime $performed; - public function __construct(#[ORM\Column(type: 'boolean')] #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private readonly bool $accepted, #[ORM\ManyToOne(targetEntity: 'VoDummyCar', inversedBy: 'inspections')] #[Groups(['inspection_read', 'inspection_write'])] private readonly ?VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') + public function __construct(#[ORM\Column(type: 'boolean')] #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private readonly bool $accepted, #[ORM\ManyToOne(targetEntity: VoDummyCar::class, inversedBy: 'inspections')] #[Groups(['inspection_read', 'inspection_write'])] private readonly ?VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') { $this->performed = $performed ?: new DateTime(); } diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php b/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php index 0ae2c6a2125..805a3a9f6ba 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyVehicle.php @@ -25,13 +25,13 @@ abstract class VoDummyVehicle /** * @var VoDummyDriver[]|Collection */ - #[ORM\ManyToMany(targetEntity: 'VoDummyDriver', cascade: ['persist'])] + #[ORM\ManyToMany(targetEntity: VoDummyDriver::class, cascade: ['persist'])] #[Groups(['car_read', 'car_write'])] - private readonly array|\Doctrine\Common\Collections\Collection $drivers; + private \Doctrine\Common\Collections\Collection $drivers; public function __construct( #[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $make, - #[ORM\ManyToOne(targetEntity: 'VoDummyInsuranceCompany', cascade: ['persist'])] #[Groups(['car_read', 'car_write'])] private readonly ?VoDummyInsuranceCompany $insuranceCompany, + #[ORM\ManyToOne(targetEntity: VoDummyInsuranceCompany::class, cascade: ['persist'])] #[Groups(['car_read', 'car_write'])] private readonly ?VoDummyInsuranceCompany $insuranceCompany, array $drivers ) { $this->drivers = new ArrayCollection($drivers); diff --git a/tests/Fixtures/TestBundle/State/DummyDtoCustomProcessor.php b/tests/Fixtures/TestBundle/State/DummyDtoCustomProcessor.php new file mode 100644 index 00000000000..06b09f4a305 --- /dev/null +++ b/tests/Fixtures/TestBundle/State/DummyDtoCustomProcessor.php @@ -0,0 +1,27 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProcessorInterface; + +class DummyDtoCustomProcessor implements ProcessorInterface +{ + /** + * {@inheritDoc} + */ + public function process($data, Operation $operation, array $uriVariables = [], array $context = []) + { + } +} From c52e1b61c7128119f0ebaa2faf5eccdb6b6a05ac Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 22 Jun 2022 14:14:59 +0200 Subject: [PATCH 37/56] doctrine + input/output --- features/hal/input_output.feature | 16 --- features/jsonapi/input_output.feature | 9 +- features/jsonld/context.feature | 2 +- features/jsonld/input_output.feature | 79 +++-------- src/Api/CompositeIdentifierParser.php | 1 - src/Api/IdentifiersExtractor.php | 1 - .../Action/DocumentationAction.php | 2 - src/Hal/Serializer/CollectionNormalizer.php | 2 +- src/JsonLd/ContextBuilder.php | 96 ++------------ src/JsonLd/Serializer/ItemNormalizer.php | 17 +-- src/JsonLd/Serializer/ObjectNormalizer.php | 2 +- src/Serializer/AbstractItemNormalizer.php | 30 +---- src/State/CallableProcessor.php | 2 +- src/State/CallableProvider.php | 2 +- .../Compiler/AttributeFilterPass.php | 1 - .../Test/Constraint/ArraySubsetTrait.php | 2 +- src/Symfony/EventListener/ReadListener.php | 2 +- .../Action/DocumentationActionTest.php | 3 - .../DummyDtoOutputFallbackToSameClass.php | 49 ------- .../Document/DummyDtoOutputSameClass.php | 48 ------- .../TestBundle/Dto/CustomInputDto.php | 11 +- .../TestBundle/Entity/CircularReference.php | 4 +- tests/Fixtures/TestBundle/Entity/Dummy.php | 8 +- .../TestBundle/Entity/DummyDtoCustom.php | 16 ++- .../TestBundle/Entity/DummyDtoInputOutput.php | 4 +- .../TestBundle/Entity/DummyDtoNoInput.php | 13 +- .../DummyDtoOutputFallbackToSameClass.php | 51 ------- .../Entity/DummyDtoOutputSameClass.php | 50 ------- .../TestBundle/Entity/DummyProduct.php | 2 +- .../TestBundle/Entity/InitializeInput.php | 3 +- .../TestBundle/Entity/MaxDepthDummy.php | 2 +- .../TestBundle/Entity/MaxDepthEagerDummy.php | 2 +- tests/Fixtures/TestBundle/Entity/User.php | 18 ++- .../State/CustomInputDtoProcessor.php | 45 +++++++ .../State/CustomOutputDtoProvider.php | 53 ++++++++ .../State/DummyDtoInputOutputProcessor.php | 40 ++++++ .../State/DummyDtoInputOutputProvider.php | 32 +++++ .../State/DummyDtoNoInputsProcessor.php | 39 ++++++ .../State/InitializeInputProcessor.php | 27 ++++ .../State/RecoverPasswordProcessor.php | 36 +++++ tests/Fixtures/app/config/config_common.yml | 124 +++++++++++------- tests/Fixtures/app/config/config_doctrine.yml | 104 +++++++++++++++ 42 files changed, 563 insertions(+), 487 deletions(-) delete mode 100644 tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php delete mode 100644 tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php delete mode 100644 tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php delete mode 100644 tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php create mode 100644 tests/Fixtures/TestBundle/State/CustomInputDtoProcessor.php create mode 100644 tests/Fixtures/TestBundle/State/CustomOutputDtoProvider.php create mode 100644 tests/Fixtures/TestBundle/State/DummyDtoInputOutputProcessor.php create mode 100644 tests/Fixtures/TestBundle/State/DummyDtoInputOutputProvider.php create mode 100644 tests/Fixtures/TestBundle/State/DummyDtoNoInputsProcessor.php create mode 100644 tests/Fixtures/TestBundle/State/InitializeInputProcessor.php create mode 100644 tests/Fixtures/TestBundle/State/RecoverPasswordProcessor.php create mode 100644 tests/Fixtures/app/config/config_doctrine.yml diff --git a/features/hal/input_output.feature b/features/hal/input_output.feature index 531c349c280..c7acbe989f0 100644 --- a/features/hal/input_output.feature +++ b/features/hal/input_output.feature @@ -2,7 +2,6 @@ Feature: HAL DTO input and output In order to use a hypermedia API As a client software developer I need to be able to use DTOs on my resources as Input or Output objects. - TODO: in 3.0 we should change the generated IRIs, /dummy_dto_custom_output/1 should retrieve /dummy_dto_custom_output/1 not /dumy_dto_customs/1 for the collection we can search for an Operation with the same Output class as the given one for the collection Background: @@ -18,11 +17,6 @@ Feature: HAL DTO input and output And the JSON should be a superset of: """ { - "_links": { - "self": { - "href": "/dummy_dto_customs/1" - } - }, "foo": "test", "bar": 1 } @@ -41,20 +35,10 @@ Feature: HAL DTO input and output "_embedded": { "item": [ { - "_links": { - "self": { - "href": "/dummy_dto_customs/1" - } - }, "foo": "test", "bar": 1 }, { - "_links": { - "self": { - "href": "/dummy_dto_customs/2" - } - }, "foo": "test", "bar": 2 } diff --git a/features/jsonapi/input_output.feature b/features/jsonapi/input_output.feature index 71fc0d377da..1fb6771081d 100644 --- a/features/jsonapi/input_output.feature +++ b/features/jsonapi/input_output.feature @@ -19,8 +19,7 @@ Feature: JSON API DTO input and output """ { "data": { - "id": "/dummy_dto_customs/1", - "type": "DummyDtoCustom", + "type": "CustomOutputDto", "attributes": { "foo": "test", "bar": 1 @@ -42,16 +41,14 @@ Feature: JSON API DTO input and output { "data": [ { - "id": "/dummy_dto_customs/1", - "type": "DummyDtoCustom", + "type": "CustomOutputDto", "attributes": { "foo": "test", "bar": 1 } }, { - "id": "/dummy_dto_customs/2", - "type": "DummyDtoCustom", + "type": "CustomOutputDto", "attributes": { "foo": "test", "bar": 2 diff --git a/features/jsonld/context.feature b/features/jsonld/context.feature index 45f324a742f..2c7b71e6ac5 100644 --- a/features/jsonld/context.feature +++ b/features/jsonld/context.feature @@ -79,7 +79,7 @@ Feature: JSON-LD contexts generation "@vocab": "http://example.com/docs.jsonld#", "hydra": "http://www.w3.org/ns/hydra/core#", "person": { - "@id": "http://example.com/id", + "@id": "https://example.com/id", "@type": "@id", "foo": "bar" } diff --git a/features/jsonld/input_output.feature b/features/jsonld/input_output.feature index ad7ee0344e8..609c4907819 100644 --- a/features/jsonld/input_output.feature +++ b/features/jsonld/input_output.feature @@ -38,7 +38,7 @@ Feature: JSON-LD DTO input and output Then the response status code should be 200 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: + And the JSON should be a superset of: """ { "@context": { @@ -47,8 +47,7 @@ Feature: JSON-LD DTO input and output "foo": "CustomOutputDto/foo", "bar": "CustomOutputDto/bar" }, - "@type": "DummyDtoCustom", - "@id": "/dummy_dto_customs/1", + "@type": "CustomOutputDto", "foo": "test", "bar": 1 } @@ -61,22 +60,20 @@ Feature: JSON-LD DTO input and output Then the response status code should be 200 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: + And the JSON should be a superset of: """ { "@context": "/contexts/DummyDtoCustom", - "@id": "/dummy_dto_customs", + "@id": "/dummy_dto_custom_output", "@type": "hydra:Collection", "hydra:member": [ { - "@type": "DummyDtoCustom", - "@id": "/dummy_dto_customs/1", + "@type": "CustomOutputDto", "foo": "test", "bar": 1 }, { - "@type": "DummyDtoCustom", - "@id": "/dummy_dto_customs/2", + "@type": "CustomOutputDto", "foo": "test", "bar": 2 } @@ -85,44 +82,6 @@ Feature: JSON-LD DTO input and output } """ - @createSchema - Scenario: Get an item with same class as custom output - Given there is a DummyDtoOutputSameClass - When I send a "GET" request to "/dummy_dto_output_same_classes/1" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/DummyDtoOutputSameClass", - "@id": "/dummy_dto_output_same_classes/1", - "@type": "DummyDtoOutputSameClass", - "lorem": "test", - "ipsum": "modified", - "id": 1 - } - """ - - @createSchema - Scenario: Get an item with a data transformer that will return the original class as a fallback - Given there is a DummyDtoOutputFallbackToSameClass - When I send a "GET" request to "/dummy_dto_output_fallback_to_same_classes/1" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/DummyDtoOutputFallbackToSameClass", - "@id": "/dummy_dto_output_fallback_to_same_classes/1", - "@type": "DummyDtoOutputFallbackToSameClass", - "lorem": "test", - "ipsum": "modified", - "id": 1 - } - """ - @createSchema Scenario: Create a DummyDtoCustom object without output When I send a "POST" request to "/dummy_dto_custom_post_without_output" with body: @@ -144,8 +103,9 @@ Feature: JSON-LD DTO input and output "bar": 1 } """ + Then print last JSON response Then the response status code should be 201 - And the JSON should be equal to: + And the JSON should be a superset of: """ { "@context": { @@ -156,8 +116,7 @@ Feature: JSON-LD DTO input and output "bat": "OutputDto/bat", "relatedDummies": "OutputDto/relatedDummies" }, - "@type": "DummyDtoInputOutput", - "@id": "/dummy_dto_input_outputs/1", + "@type": "OutputDto", "id": 1, "baz": 1, "bat": "test", @@ -174,7 +133,7 @@ Feature: JSON-LD DTO input and output } """ Then the response status code should be 200 - And the JSON should be equal to: + And the JSON should be a superset of: """ { "@context": { @@ -185,8 +144,7 @@ Feature: JSON-LD DTO input and output "bat": "OutputDto/bat", "relatedDummies": "OutputDto/relatedDummies" }, - "@type": "DummyDtoInputOutput", - "@id": "/dummy_dto_input_outputs/1", + "@type": "OutputDto", "id": 1, "baz": 2, "bat": "test", @@ -215,7 +173,7 @@ Feature: JSON-LD DTO input and output } """ Then the response status code should be 200 - And the JSON should be equal to: + And the JSON should be a superset of: """ { "@context": { @@ -223,8 +181,7 @@ Feature: JSON-LD DTO input and output "hydra": "http://www.w3.org/ns/hydra/core#", "dummy": "RecoverPasswordOutput/dummy" }, - "@type": "User", - "@id": "/users/1", + "@type": "RecoverPasswordOutput", "dummy": "/dummies/1" } """ @@ -235,7 +192,7 @@ Feature: JSON-LD DTO input and output Then the response status code should be 201 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: + And the JSON should be a superset of: """ { "@context": { @@ -246,8 +203,7 @@ Feature: JSON-LD DTO input and output "bat": "OutputDto/bat", "relatedDummies": "OutputDto/relatedDummies" }, - "@type": "DummyDtoNoInput", - "@id": "/dummy_dto_no_inputs/1", + "@type": "OutputDto", "id": 1, "baz": 1, "bat": "test", @@ -260,7 +216,7 @@ Feature: JSON-LD DTO input and output Then the response status code should be 200 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: + And the JSON should be a superset of: """ { "@context": { @@ -271,8 +227,7 @@ Feature: JSON-LD DTO input and output "bat": "OutputDto/bat", "relatedDummies": "OutputDto/relatedDummies" }, - "@type": "DummyDtoNoInput", - "@id": "/dummy_dto_no_inputs/1", + "@type": "OutputDto", "id": 1, "baz": 1, "bat": "testtest", diff --git a/src/Api/CompositeIdentifierParser.php b/src/Api/CompositeIdentifierParser.php index 953ef5e1b69..aed4bc8c094 100644 --- a/src/Api/CompositeIdentifierParser.php +++ b/src/Api/CompositeIdentifierParser.php @@ -61,4 +61,3 @@ public static function stringify(array $identifiers): string return implode(';', $composite); } } - diff --git a/src/Api/IdentifiersExtractor.php b/src/Api/IdentifiersExtractor.php index 7b1bef680b4..88c2055ce90 100644 --- a/src/Api/IdentifiersExtractor.php +++ b/src/Api/IdentifiersExtractor.php @@ -13,7 +13,6 @@ namespace ApiPlatform\Api; -use ApiPlatform\Api\CompositeIdentifierParser; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation; use ApiPlatform\Metadata\HttpOperation; diff --git a/src/Documentation/Action/DocumentationAction.php b/src/Documentation/Action/DocumentationAction.php index 2a777e3de29..2b78e9ff9a5 100644 --- a/src/Documentation/Action/DocumentationAction.php +++ b/src/Documentation/Action/DocumentationAction.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Documentation\Action; -use ApiPlatform\Core\Api\FormatsProviderInterface; -use ApiPlatform\Core\OpenApi\Factory\OpenApiFactoryInterface as LegacyOpenApiFactoryInterface; use ApiPlatform\Documentation\Documentation; use ApiPlatform\Documentation\DocumentationInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; diff --git a/src/Hal/Serializer/CollectionNormalizer.php b/src/Hal/Serializer/CollectionNormalizer.php index f2081c0d746..27f20e1a704 100644 --- a/src/Hal/Serializer/CollectionNormalizer.php +++ b/src/Hal/Serializer/CollectionNormalizer.php @@ -92,7 +92,7 @@ protected function getItemsData($object, string $format = null, array $context = throw new UnexpectedValueException('Expected item to be an array'); } $data['_embedded']['item'][] = $item; - $data['_links']['item'][] = $item['_links']['self']; + $data['_links']['item'][] = $item['_links']['self'] ?? null; } return $data; diff --git a/src/JsonLd/ContextBuilder.php b/src/JsonLd/ContextBuilder.php index 3b14141db8d..cf0a52857eb 100644 --- a/src/JsonLd/ContextBuilder.php +++ b/src/JsonLd/ContextBuilder.php @@ -14,11 +14,7 @@ namespace ApiPlatform\JsonLd; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface as LegacyPropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface as LegacyPropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; -use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; @@ -29,7 +25,6 @@ /** * {@inheritdoc} - * TODO: 3.0 simplify or remove the class. * * @author Kévin Dunglas */ @@ -40,24 +35,11 @@ final class ContextBuilder implements AnonymousContextBuilderInterface public const FORMAT = 'jsonld'; private $resourceNameCollectionFactory; - /** - * @param ResourceMetadataFactoryInterface|ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory - */ - private $resourceMetadataFactory; - /** - * @var LegacyPropertyNameCollectionFactoryInterface|PropertyNameCollectionFactoryInterface - */ - private $propertyNameCollectionFactory; - /** - * @var LegacyPropertyMetadataFactoryInterface|PropertyMetadataFactoryInterface - */ - private $propertyMetadataFactory; - private $urlGenerator; - - /** - * @var NameConverterInterface|null - */ - private $nameConverter; + private ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory; + private PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory; + private PropertyMetadataFactoryInterface $propertyMetadataFactory; + private UrlGeneratorInterface $urlGenerator; + private ?NameConverterInterface $nameConverter = null; public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, UrlGeneratorInterface $urlGenerator, NameConverterInterface $nameConverter = null) { @@ -67,10 +49,6 @@ public function __construct(ResourceNameCollectionFactoryInterface $resourceName $this->propertyMetadataFactory = $propertyMetadataFactory; $this->urlGenerator = $urlGenerator; $this->nameConverter = $nameConverter; - - if ($resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use "%s" instead of "%s".', ResourceMetadataCollectionFactoryInterface::class, ResourceMetadataFactoryInterface::class)); - } } /** @@ -92,13 +70,7 @@ public function getEntrypointContext(int $referenceType = UrlGeneratorInterface: $context = $this->getBaseContext($referenceType); foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) { - // TODO: remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $shortName = $this->resourceMetadataFactory->create($resourceClass)->getShortName(); - } else { - $shortName = $this->resourceMetadataFactory->create($resourceClass)[0]->getShortName(); - } - + $shortName = $this->resourceMetadataFactory->create($resourceClass)[0]->getShortName(); $resourceName = lcfirst($shortName); $context[$resourceName] = [ @@ -115,23 +87,6 @@ public function getEntrypointContext(int $referenceType = UrlGeneratorInterface: */ public function getResourceContext(string $resourceClass, int $referenceType = UrlGeneratorInterface::ABS_PATH): array { - // TODO: Remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (null === $shortName = $resourceMetadata->getShortName()) { - return []; - } - - if ($resourceMetadata->getAttribute('normalization_context')['iri_only'] ?? false) { - $context = $this->getBaseContext($referenceType); - $context['hydra:member']['@type'] = '@id'; - - return $context; - } - - return $this->getResourceContextWithShortname($resourceClass, $referenceType, $shortName); - } - $operation = $this->resourceMetadataFactory->create($resourceClass)->getOperation(); if (null === $shortName = $operation->getShortName()) { return []; @@ -152,16 +107,6 @@ public function getResourceContext(string $resourceClass, int $referenceType = U */ public function getResourceContextUri(string $resourceClass, int $referenceType = null): string { - // TODO: remove in 3.0 - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); - if (null === $referenceType) { - $referenceType = $resourceMetadata->getAttribute('url_generation_strategy'); - } - - return $this->urlGenerator->generate('api_jsonld_context', ['shortName' => $resourceMetadata->getShortName()], $referenceType); - } - $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass)[0]; if (null === $referenceType) { $referenceType = $resourceMetadata->getUrlGenerationStrategy(); @@ -176,7 +121,8 @@ public function getResourceContextUri(string $resourceClass, int $referenceType public function getAnonymousResourceContext($object, array $context = [], int $referenceType = UrlGeneratorInterface::ABS_PATH): array { $outputClass = $this->getObjectClass($object); - $shortName = (new \ReflectionClass($outputClass))->getShortName(); + $operation = $context['operation'] ?? new Get(shortName: (new \ReflectionClass($outputClass))->getShortName()); + $shortName = $operation->getShortName(); $jsonLdContext = [ '@context' => $this->getResourceContextWithShortname( @@ -197,11 +143,7 @@ public function getAnonymousResourceContext($object, array $context = [], int $r // here the object can be different from the resource given by the $context['api_resource'] value if (isset($context['api_resource'])) { - if ($this->resourceMetadataFactory instanceof ResourceMetadataFactoryInterface) { - $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))->getShortName(); - } else { - $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))[0]->getShortName(); - } + $jsonLdContext['@type'] = $this->resourceMetadataFactory->create($this->getObjectClass($context['api_resource']))[0]->getShortName(); } return $jsonLdContext; @@ -210,14 +152,9 @@ public function getAnonymousResourceContext($object, array $context = [], int $r private function getResourceContextWithShortname(string $resourceClass, int $referenceType, string $shortName, ?HttpOperation $operation = null): array { $context = $this->getBaseContext($referenceType); - if ($this->propertyMetadataFactory instanceof LegacyPropertyMetadataFactoryInterface) { - $propertyContext = []; - } else { - $propertyContext = $operation ? ['normalization_groups' => $operation->getNormalizationContext()['groups'] ?? null, 'denormalization_groups' => $operation->getDenormalizationContext()['groups'] ?? null] : ['normalization_groups' => [], 'denormalization_groups' => []]; - } + $propertyContext = $operation ? ['normalization_groups' => $operation->getNormalizationContext()['groups'] ?? null, 'denormalization_groups' => $operation->getDenormalizationContext()['groups'] ?? null] : ['normalization_groups' => [], 'denormalization_groups' => []]; foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - /** @var PropertyMetadata|ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName, $propertyContext); if ($propertyMetadata->isIdentifier() && true !== $propertyMetadata->isWritable()) { @@ -225,15 +162,10 @@ private function getResourceContextWithShortname(string $resourceClass, int $ref } $convertedName = $this->nameConverter ? $this->nameConverter->normalize($propertyName, $resourceClass, self::FORMAT) : $propertyName; - if ($propertyMetadata instanceof PropertyMetadata) { - $jsonldContext = ($propertyMetadata->getAttributes() ?? [])['jsonld_context'] ?? []; - $id = $propertyMetadata->getIri(); - } else { - $jsonldContext = $propertyMetadata->getJsonldContext() ?? []; + $jsonldContext = $propertyMetadata->getJsonldContext() ?? []; - if ($id = $propertyMetadata->getIris()) { - $id = 1 === \count($id) ? $id[0] : $id; - } + if ($id = $propertyMetadata->getIris()) { + $id = 1 === \count($id) ? $id[0] : $id; } if (!$id) { diff --git a/src/JsonLd/Serializer/ItemNormalizer.php b/src/JsonLd/Serializer/ItemNormalizer.php index 9ef170b36df..a46a48b1d60 100644 --- a/src/JsonLd/Serializer/ItemNormalizer.php +++ b/src/JsonLd/Serializer/ItemNormalizer.php @@ -71,21 +71,17 @@ public function supportsNormalization($data, $format = null): bool public function normalize($object, $format = null, array $context = []) { $objectClass = $this->getObjectClass($object); - $outputClass = $this->getOutputClass($objectClass, $context); - if (null !== $outputClass && !isset($context[self::IS_TRANSFORMED_TO_SAME_CLASS])) { - return parent::normalize($object, $format, $context); - } - // TODO: we should not remove the resource_class in the normalizeRawCollection as we would find out anyway that it's not the same as the requested one - $previousResourceClass = $context['resource_class'] ?? null; $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); - $context = $this->initContext($resourceClass, $context); - $metadata = $this->addJsonLdContext($this->contextBuilder, $resourceClass, $context); - if (isset($context['operation']) && $previousResourceClass !== $resourceClass) { - unset($context['operation'], $context['operation_name']); + if (isset($context['operation']) && $resourceClass !== $context['operation']->getClass()) { + unset($context['operation']); } + $operation = $context['operation'] = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); + $context = $this->initContext($resourceClass, $context); + $metadata = $this->addJsonLdContext($this->contextBuilder, $resourceClass, $context); + $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); $context['iri'] = $iri; $metadata['@id'] = $iri; @@ -96,7 +92,6 @@ public function normalize($object, $format = null, array $context = []) return $data; } - $operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); $types = $operation instanceof HttpOperation ? $operation->getTypes() : null; if (null === $types) { $types = [$operation->getShortName()]; diff --git a/src/JsonLd/Serializer/ObjectNormalizer.php b/src/JsonLd/Serializer/ObjectNormalizer.php index c3e0df18d28..303c36230ad 100644 --- a/src/JsonLd/Serializer/ObjectNormalizer.php +++ b/src/JsonLd/Serializer/ObjectNormalizer.php @@ -80,7 +80,7 @@ public function normalize($object, $format = null, array $context = []) */ $context['api_empty_resource_as_iri'] = true; - $data = $this->decorated->normalize($object, $format, $context); + $data = $this->decorated->normalize($object, $format, $context + ['api_sub_level' => true]); if (!\is_array($data) || !$data) { return $data; } diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 30e811a7ebe..920c2c75f03 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -56,8 +56,6 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer use ContextTrait; use InputOutputMetadataTrait; - public const IS_TRANSFORMED_TO_SAME_CLASS = 'is_transformed_to_same_class'; - protected $propertyNameCollectionFactory; protected $propertyMetadataFactory; protected $iriConverter; @@ -119,25 +117,6 @@ public function hasCacheableSupportsMethod(): bool */ public function normalize($object, $format = null, array $context = []) { - if (!($isTransformed = isset($context[self::IS_TRANSFORMED_TO_SAME_CLASS])) && $outputClass = $this->getOutputClass($this->getObjectClass($object), $context)) { - if (!$this->serializer instanceof NormalizerInterface) { - throw new LogicException('Cannot normalize the output because the injected serializer is not a normalizer'); - } - - if ($object !== $transformed = $this->transformOutput($object, $context, $outputClass)) { - $context['api_normalize'] = true; - $context['api_resource'] = $object; - unset($context['output'], $context['resource_class']); - } else { - $context[self::IS_TRANSFORMED_TO_SAME_CLASS] = true; - } - - return $this->serializer->normalize($transformed, $format, $context); - } - if ($isTransformed) { - unset($context[self::IS_TRANSFORMED_TO_SAME_CLASS]); - } - $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); $context = $this->initContext($resourceClass, $context); @@ -202,7 +181,7 @@ public function denormalize($data, $class, $format = null, array $context = []) $context['resource_class'] = $resourceClass; if ( - $inputClass = $this->getInputClass($resourceClass, $context) + ($inputClass = $this->getInputClass($resourceClass, $context)) && ($context['operation'] ?? $context['operation_type'] ?? false) // Are we in a Request context? ) { @@ -221,7 +200,12 @@ public function denormalize($data, $class, $format = null, array $context = []) } $previousObject = null !== $objectToPopulate ? clone $objectToPopulate : null; - $object = parent::denormalize($data, $resourceClass, $format, $context); + + try { + $object = parent::denormalize($data, $resourceClass, $format, $context); + } catch (NotNormalizableValueException $e) { + throw new UnexpectedValueException('The input data is misformatted.', $e->getCode(), $e); + } if (!$this->resourceClassResolver->isResourceClass($context['resource_class'])) { return $object; diff --git a/src/State/CallableProcessor.php b/src/State/CallableProcessor.php index 3a950f8fedf..5fcc820b7e7 100644 --- a/src/State/CallableProcessor.php +++ b/src/State/CallableProcessor.php @@ -13,7 +13,7 @@ namespace ApiPlatform\State; -use ApiPlatform\Core\Exception\RuntimeException; +use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\Operation; use Psr\Container\ContainerInterface; diff --git a/src/State/CallableProvider.php b/src/State/CallableProvider.php index 96318ef865e..77bc7ca42c1 100644 --- a/src/State/CallableProvider.php +++ b/src/State/CallableProvider.php @@ -13,7 +13,7 @@ namespace ApiPlatform\State; -use ApiPlatform\Core\Exception\RuntimeException; +use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\Operation; use Psr\Container\ContainerInterface; diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPass.php index 276c5276b5d..7668f7da83e 100644 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPass.php +++ b/src/Symfony/Bundle/DependencyInjection/Compiler/AttributeFilterPass.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler; use ApiPlatform\Metadata\ApiFilter; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ConvertedBoolean; use ApiPlatform\Util\AttributeFilterExtractorTrait; use ApiPlatform\Util\ReflectionClassRecursiveIterator; use Symfony\Component\DependencyInjection\ChildDefinition; diff --git a/src/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php b/src/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php index 08c38b2a81f..4f371f3a1b4 100644 --- a/src/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php +++ b/src/Symfony/Bundle/Test/Constraint/ArraySubsetTrait.php @@ -13,7 +13,7 @@ namespace ApiPlatform\Symfony\Bundle\Test\Constraint; -use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\ComparisonFailure; /** * Constraint that asserts that the array it is evaluated for has a specified subset. diff --git a/src/Symfony/EventListener/ReadListener.php b/src/Symfony/EventListener/ReadListener.php index 607e445a472..fd13172e4ae 100644 --- a/src/Symfony/EventListener/ReadListener.php +++ b/src/Symfony/EventListener/ReadListener.php @@ -65,7 +65,7 @@ public function onKernelRequest(RequestEvent $event): void return; } - if (!$operation || !($operation->canRead() ?? true) || !$attributes['receive'] || (!$operation->getUriVariables() && !$request->isMethodSafe()) || ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) || ($operation->getExtraProperties()['is_legacy_subresource'] ?? false)) { + if (!$operation || !($operation->canRead() ?? true) || !$attributes['receive'] || (!$operation->getUriVariables() && !$request->isMethodSafe())) { return; } diff --git a/tests/Documentation/Action/DocumentationActionTest.php b/tests/Documentation/Action/DocumentationActionTest.php index 7c128e953d9..e84e32070e1 100644 --- a/tests/Documentation/Action/DocumentationActionTest.php +++ b/tests/Documentation/Action/DocumentationActionTest.php @@ -14,9 +14,6 @@ namespace ApiPlatform\Tests\Documentation\Action; use ApiPlatform\Documentation\Action\DocumentationAction; -use ApiPlatform\Documentation\Documentation; -use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; -use ApiPlatform\Metadata\Resource\ResourceNameCollection; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Model\Info; use ApiPlatform\OpenApi\Model\Paths; diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php deleted file mode 100644 index d5b7828b25e..00000000000 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputFallbackToSameClass.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\Document; - -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDtoDummy; -use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; - -/** - * Dummy InputOutput. - * - * @author Daniel West - */ -#[ApiResource(output: OutputDtoDummy::class)] -#[ODM\Document] -class DummyDtoOutputFallbackToSameClass -{ - /** - * @var int The id - */ - #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] - private ?int $id = null; - /** - * @var string - */ - #[ODM\Field] - public $lorem; - /** - * @var string - */ - #[ODM\Field] - public $ipsum; - - public function getId() - { - return $this->id; - } -} diff --git a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php deleted file mode 100644 index 4ffceb19d42..00000000000 --- a/tests/Fixtures/TestBundle/Document/DummyDtoOutputSameClass.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\Document; - -use ApiPlatform\Metadata\ApiResource; -use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; - -/** - * Dummy InputOutput. - * - * @author Daniel West - */ -#[ApiResource(output: DummyDtoOutputSameClass::class)] -#[ODM\Document] -class DummyDtoOutputSameClass -{ - /** - * @var int The id - */ - #[ODM\Id(strategy: 'INCREMENT', type: 'int', nullable: true)] - private ?int $id = null; - /** - * @var string - */ - #[ODM\Field] - public $lorem; - /** - * @var string - */ - #[ODM\Field] - public $ipsum; - - public function getId() - { - return $this->id; - } -} diff --git a/tests/Fixtures/TestBundle/Dto/CustomInputDto.php b/tests/Fixtures/TestBundle/Dto/CustomInputDto.php index 10516973376..dd751bf6d58 100644 --- a/tests/Fixtures/TestBundle/Dto/CustomInputDto.php +++ b/tests/Fixtures/TestBundle/Dto/CustomInputDto.php @@ -15,13 +15,6 @@ class CustomInputDto { - /** - * @var string - */ - public $foo; - - /** - * @var int - */ - public $bar; + public string $foo; + public int $bar; } diff --git a/tests/Fixtures/TestBundle/Entity/CircularReference.php b/tests/Fixtures/TestBundle/Entity/CircularReference.php index 7f8ee99ea55..33845117461 100644 --- a/tests/Fixtures/TestBundle/Entity/CircularReference.php +++ b/tests/Fixtures/TestBundle/Entity/CircularReference.php @@ -31,10 +31,10 @@ class CircularReference #[ORM\Id] #[ORM\GeneratedValue(strategy: 'AUTO')] public $id; - #[ORM\ManyToOne(targetEntity: CircularReference::class, inversedBy: 'children')] + #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[Groups(['circular'])] public $parent; - #[ORM\OneToMany(targetEntity: CircularReference::class, mappedBy: 'parent')] + #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')] #[Groups(['circular'])] public $children; diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index 68f17887305..38015744630 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -43,7 +43,7 @@ class Dummy /** * @var string The dummy name */ - #[ApiProperty(types: ['http://schema.org/name'])] + #[ApiProperty(iris: ['http://schema.org/name'])] #[ORM\Column] #[Assert\NotBlank] private ?string $name = null; @@ -51,7 +51,7 @@ class Dummy /** * @var string|null The dummy name alias */ - #[ApiProperty(types: ['http://schema.org/alternateName'])] + #[ApiProperty(iris: ['https://schema.org/alternateName'])] #[ORM\Column(nullable: true)] private $alias; @@ -63,7 +63,7 @@ class Dummy /** * @var string|null A short description of the item */ - #[ApiProperty(types: ['http://schema.org/description'])] + #[ApiProperty(iris: ['https://schema.org/description'])] #[ORM\Column(nullable: true)] public $description; @@ -82,7 +82,7 @@ class Dummy /** * @var \DateTime|null A dummy date */ - #[ApiProperty(types: ['http://schema.org/DateTime'])] + #[ApiProperty(iris: ['http://schema.org/DateTime'])] #[ORM\Column(type: 'datetime', nullable: true)] public $dummyDate; diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php index abd19524d29..a59c0f90716 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoCustom.php @@ -21,6 +21,8 @@ use ApiPlatform\Metadata\Put; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomInputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomOutputDto; +use ApiPlatform\Tests\Fixtures\TestBundle\State\CustomInputDtoProcessor; +use ApiPlatform\Tests\Fixtures\TestBundle\State\CustomOutputDtoProvider; use Doctrine\ORM\Mapping as ORM; /** @@ -29,13 +31,13 @@ #[ApiResource( operations: [ new Get(), - new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}'), - new Put(), - new Delete(), - new Post(input: CustomInputDto::class), - new GetCollection(), - new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output'), - new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output') + new Put(), + new Delete(), + new Post(input: CustomInputDto::class, processor: CustomInputDtoProcessor::class), + new GetCollection(), + new GetCollection(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output', provider: CustomOutputDtoProvider::class), + new Get(output: CustomOutputDto::class, uriTemplate: 'dummy_dto_custom_output/{id}', provider: CustomOutputDtoProvider::class), + new Post(output: false, uriTemplate: 'dummy_dto_custom_post_without_output'), ] )] #[ORM\Entity] diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php index 926e94eeced..34a7a744256 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoInputOutput.php @@ -16,6 +16,8 @@ use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoInputOutputProcessor; +use ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoInputOutputProvider; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -25,7 +27,7 @@ * * @author Kévin Dunglas */ -#[ApiResource(input: InputDto::class, output: OutputDto::class)] +#[ApiResource(input: InputDto::class, output: OutputDto::class, processor: DummyDtoInputOutputProcessor::class, provider: DummyDtoInputOutputProvider::class)] #[ORM\Entity] class DummyDtoInputOutput { diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php index 126627ce62f..6cbcd80e121 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php @@ -21,6 +21,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\CreateItemAction; use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\DoubleBatAction; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoNoInputsProcessor; use Doctrine\ORM\Mapping as ORM; /** @@ -28,7 +29,17 @@ * * @author Vincent Chalamon */ -#[ApiResource(operations: [new Get(), new Delete(), new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200), new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class), new GetCollection()], input: false, output: OutputDto::class)] +#[ApiResource( + operations: [ + new Get(), + new Delete(), + new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200, processor: DummyDtoNoInputsProcessor::class), + new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class, processor: DummyDtoNoInputsProcessor::class), + new GetCollection(), + ], + input: false, + output: OutputDto::class +)] #[ORM\Entity] class DummyDtoNoInput { diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php deleted file mode 100644 index e1d647f57b8..00000000000 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputFallbackToSameClass.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\Entity; - -use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDtoDummy; -use Doctrine\ORM\Mapping as ORM; - -/** - * Dummy InputOutput. - * - * @author Daniel West - */ -#[ApiResource(output: OutputDtoDummy::class)] -#[ORM\Entity] -class DummyDtoOutputFallbackToSameClass -{ - /** - * @var int The id - */ - #[ORM\Column(type: 'integer')] - #[ORM\Id] - #[ORM\GeneratedValue(strategy: 'AUTO')] - private ?int $id = null; - /** - * @var string - */ - #[ORM\Column] - public $lorem; - /** - * @var string - */ - #[ORM\Column] - public $ipsum; - - public function getId() - { - return $this->id; - } -} diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php b/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php deleted file mode 100644 index 277bdc9ba58..00000000000 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoOutputSameClass.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * 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\Tests\Fixtures\TestBundle\Entity; - -use ApiPlatform\Metadata\ApiResource; -use Doctrine\ORM\Mapping as ORM; - -/** - * Dummy InputOutput. - * - * @author Daniel West - */ -#[ApiResource(output: DummyDtoOutputSameClass::class)] -#[ORM\Entity] -class DummyDtoOutputSameClass -{ - /** - * @var int The id - */ - #[ORM\Column(type: 'integer')] - #[ORM\Id] - #[ORM\GeneratedValue(strategy: 'AUTO')] - private ?int $id = null; - /** - * @var string - */ - #[ORM\Column] - public $lorem; - /** - * @var string - */ - #[ORM\Column] - public $ipsum; - - public function getId() - { - return $this->id; - } -} diff --git a/tests/Fixtures/TestBundle/Entity/DummyProduct.php b/tests/Fixtures/TestBundle/Entity/DummyProduct.php index f3184faea3a..1311529452d 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyProduct.php +++ b/tests/Fixtures/TestBundle/Entity/DummyProduct.php @@ -52,7 +52,7 @@ class DummyProduct /** * @var \Collection */ - #[ORM\OneToMany(targetEntity: DummyProduct::class, mappedBy: 'parent')] + #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent')] private Collection $relatedProducts; #[ORM\ManyToOne(targetEntity: 'DummyProduct', inversedBy: 'relatedProducts')] private $parent; diff --git a/tests/Fixtures/TestBundle/Entity/InitializeInput.php b/tests/Fixtures/TestBundle/Entity/InitializeInput.php index 6e571a53a50..6f944d837b6 100644 --- a/tests/Fixtures/TestBundle/Entity/InitializeInput.php +++ b/tests/Fixtures/TestBundle/Entity/InitializeInput.php @@ -15,9 +15,10 @@ use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InitializeInputDto; +use ApiPlatform\Tests\Fixtures\TestBundle\State\InitializeInputProcessor; use Doctrine\ORM\Mapping as ORM; -#[ApiResource(input: InitializeInputDto::class)] +#[ApiResource(input: InitializeInputDto::class, processor: InitializeInputProcessor::class)] #[ORM\Entity] class InitializeInput { diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php index 758710f9ac1..e7de9409e7c 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthDummy.php @@ -37,7 +37,7 @@ class MaxDepthDummy public $name; #[ApiProperty(fetchEager: false)] - #[ORM\ManyToOne(targetEntity: MaxDepthDummy::class, cascade: ['persist'])] + #[ORM\ManyToOne(targetEntity: self::class, cascade: ['persist'])] #[Groups(['default'])] #[MaxDepth(1)] public $child; diff --git a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php index cf1e6d95233..791757f4b6c 100644 --- a/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php +++ b/tests/Fixtures/TestBundle/Entity/MaxDepthEagerDummy.php @@ -36,7 +36,7 @@ class MaxDepthEagerDummy #[ORM\Column(name: 'name', type: 'string', length: 30)] #[Groups(['default'])] public $name; - #[ORM\ManyToOne(targetEntity: MaxDepthEagerDummy::class, cascade: ['persist'])] + #[ORM\ManyToOne(targetEntity: self::class, cascade: ['persist'])] #[Groups(['default'])] #[MaxDepth(1)] public $child; diff --git a/tests/Fixtures/TestBundle/Entity/User.php b/tests/Fixtures/TestBundle/Entity/User.php index b9c6f8d6a47..bee85637c49 100644 --- a/tests/Fixtures/TestBundle/Entity/User.php +++ b/tests/Fixtures/TestBundle/Entity/User.php @@ -24,6 +24,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordOutput; use ApiPlatform\Tests\Fixtures\TestBundle\Security\AbstractSecurityUser; +use ApiPlatform\Tests\Fixtures\TestBundle\State\RecoverPasswordProcessor; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; @@ -33,7 +34,22 @@ * @author Théo FIDRY * @author Kévin Dunglas */ -#[ApiResource(operations: [new Get(), new Put(), new Delete(), new Put(input: RecoverPasswordInput::class, output: RecoverPasswordOutput::class, uriTemplate: 'users/recover/{id}'), new Post(), new GetCollection(), new Post(uriTemplate: '/users/password_reset_request', messenger: 'input', input: PasswordResetRequest::class, output: PasswordResetRequestResult::class, normalizationContext: ['groups' => ['user_password_reset_request']], denormalizationContext: ['groups' => ['user_password_reset_request']])], normalizationContext: ['groups' => ['user', 'user-read']], denormalizationContext: ['groups' => ['user', 'user-write']])] +#[ApiResource(operations: [ + new Get(), + new Put(), + new Delete(), + new Put(input: RecoverPasswordInput::class, output: RecoverPasswordOutput::class, uriTemplate: 'users/recover/{id}', processor: RecoverPasswordProcessor::class), + new Post(), + new GetCollection(), + new Post( + uriTemplate: '/users/password_reset_request', + messenger: 'input', + input: PasswordResetRequest::class, + output: PasswordResetRequestResult::class, + normalizationContext: ['groups' => ['user_password_reset_request']], + denormalizationContext: ['groups' => ['user_password_reset_request']] + ), +], normalizationContext: ['groups' => ['user', 'user-read']], denormalizationContext: ['groups' => ['user', 'user-write']])] #[ORM\Entity] #[ORM\Table(name: 'user_test')] class User extends AbstractSecurityUser diff --git a/tests/Fixtures/TestBundle/State/CustomInputDtoProcessor.php b/tests/Fixtures/TestBundle/State/CustomInputDtoProcessor.php new file mode 100644 index 00000000000..37aa5598bcd --- /dev/null +++ b/tests/Fixtures/TestBundle/State/CustomInputDtoProcessor.php @@ -0,0 +1,45 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\Operation; +use ApiPlatform\Serializer\AbstractItemNormalizer; +use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomInputDto; + +final class CustomInputDtoProcessor implements ProcessorInterface +{ + public function __construct(private ProcessorInterface $decorated) + { + } + + /** + * {@inheritDoc} + */ + public function process($data, Operation $operation, array $uriVariables = [], array $context = []) + { + if (!$data instanceof CustomInputDto) { + throw new \InvalidArgumentException(); + } + + /** + * @var \ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoCustom + */ + $resourceObject = $context[AbstractItemNormalizer::OBJECT_TO_POPULATE] ?? new $context['resource_class'](); + $resourceObject->lorem = $data->foo; + $resourceObject->ipsum = (string) $data->bar; + + return $this->decorated->process($resourceObject, $operation, $uriVariables, $context); + } +} diff --git a/tests/Fixtures/TestBundle/State/CustomOutputDtoProvider.php b/tests/Fixtures/TestBundle/State/CustomOutputDtoProvider.php new file mode 100644 index 00000000000..f804fb006ca --- /dev/null +++ b/tests/Fixtures/TestBundle/State/CustomOutputDtoProvider.php @@ -0,0 +1,53 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\CollectionOperationInterface; +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProviderInterface; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\CustomOutputDto; + +final class CustomOutputDtoProvider implements ProviderInterface +{ + public function __construct(private ProviderInterface $itemProvider, private ProviderInterface $collectionProvider) + { + } + + /** + * {@inheritDoc} + */ + public function provide(Operation $operation, array $uriVariables = [], array $context = []) + { + if ($operation instanceof CollectionOperationInterface) { + $object = $this->collectionProvider->provide($operation, $uriVariables, $context); + + foreach ($object as &$value) { + $value = $this->toOutput($value); + } + + return $object; + } + + return $this->toOutput($this->itemProvider->provide($operation, $uriVariables, $context)); + } + + private function toOutput($object): CustomOutputDto + { + $output = new CustomOutputDto(); + $output->foo = $object->lorem; + $output->bar = (int) $object->ipsum; + + return $output; + } +} diff --git a/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProcessor.php b/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProcessor.php new file mode 100644 index 00000000000..d6571884f3e --- /dev/null +++ b/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProcessor.php @@ -0,0 +1,40 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; + +final class DummyDtoInputOutputProcessor implements ProcessorInterface +{ + /** + * {@inheritDoc} + * + * @param InputDto $data + */ + public function process($data, Operation $operation, array $uriVariables = [], array $context = []) + { + $outputDto = $context['previous_data'] ?? new OutputDto(); + if (!$outputDto->id) { + $outputDto->id = 1; + } + + $outputDto->baz = $data->bar; + $outputDto->bat = $data->foo; + + return $outputDto; + } +} diff --git a/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProvider.php b/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProvider.php new file mode 100644 index 00000000000..74ee62cfaab --- /dev/null +++ b/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProvider.php @@ -0,0 +1,32 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProviderInterface; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; + +final class DummyDtoInputOutputProvider implements ProviderInterface +{ + /** + * {@inheritDoc} + */ + public function provide(Operation $operation, array $uriVariables = [], array $context = []) + { + $outputDto = new OutputDto(); + $outputDto->id = $uriVariables['id']; + + return $outputDto; + } +} diff --git a/tests/Fixtures/TestBundle/State/DummyDtoNoInputsProcessor.php b/tests/Fixtures/TestBundle/State/DummyDtoNoInputsProcessor.php new file mode 100644 index 00000000000..88e8304a0aa --- /dev/null +++ b/tests/Fixtures/TestBundle/State/DummyDtoNoInputsProcessor.php @@ -0,0 +1,39 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto as OutputDtoDocument; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoNoInput; + +class DummyDtoNoInputsProcessor implements ProcessorInterface +{ + public function __construct(private ProcessorInterface $decorated) + { + } + + public function process($data, Operation $operation, array $uriVariables = [], array $context = []) + { + $object = $this->decorated->process($data, $operation, $uriVariables, $context); + + $output = $object instanceof DummyDtoNoInput ? new OutputDto() : new OutputDtoDocument(); + $output->id = $object->getId(); + $output->bat = (string) $object->lorem; + $output->baz = (float) $object->ipsum; + + return $output; + } +} diff --git a/tests/Fixtures/TestBundle/State/InitializeInputProcessor.php b/tests/Fixtures/TestBundle/State/InitializeInputProcessor.php new file mode 100644 index 00000000000..6bd345e1d70 --- /dev/null +++ b/tests/Fixtures/TestBundle/State/InitializeInputProcessor.php @@ -0,0 +1,27 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\Operation; + +class InitializeInputProcessor +{ + public static function process($data, Operation $operation, array $uriVariables = [], array $context = []) + { + $resourceObject = $context['previous_data']; + $resourceObject->name = $data->name; + + return $resourceObject; + } +} diff --git a/tests/Fixtures/TestBundle/State/RecoverPasswordProcessor.php b/tests/Fixtures/TestBundle/State/RecoverPasswordProcessor.php new file mode 100644 index 00000000000..07a366c05d1 --- /dev/null +++ b/tests/Fixtures/TestBundle/State/RecoverPasswordProcessor.php @@ -0,0 +1,36 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RecoverPasswordOutput; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; + +class RecoverPasswordProcessor implements ProcessorInterface +{ + public function process($data, Operation $operation, array $uriVariables = [], array $context = []) + { + // Because we're in a PUT operation, we will use the retrieved object... + $resourceObject = $context['previous_data'] ?? new $context['resource_class'](); + // ...where we remove the credentials + $resourceObject->eraseCredentials(); + + $output = new RecoverPasswordOutput(); + $output->dummy = new Dummy(); + $output->dummy->setId(1); + + return $output; + } +} diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index d7339ea7b37..9c930df6d76 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -294,59 +294,93 @@ services: tags: ['messenger.message_handler'] mercure.hub.default.publisher: '@mercure.hub.default.message_handler' - app.data_transformer.custom_input_dto: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\CustomInputDtoDataTransformer' - public: false - tags: - - { name: 'api_platform.data_transformer' } - - app.data_transformer.custom_output_dto: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\CustomOutputDtoDataTransformer' - public: false + ApiPlatform\Tests\Fixtures\TestBundle\State\CustomInputDtoProcessor: + arguments: + $decorated: '@ApiPlatform\Doctrine\Common\State\PersistProcessor' tags: - - { name: 'api_platform.data_transformer' } + - name: 'api_platform.state_processor' - app.data_transformer.custom_output_dto_fallback_same_class: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\OutputDtoSameClassTransformer' - public: false + ApiPlatform\Tests\Fixtures\TestBundle\State\CustomOutputDtoProvider: + arguments: + $itemProvider: '@ApiPlatform\Doctrine\Orm\State\ItemProvider' + $collectionProvider: '@ApiPlatform\Doctrine\Orm\State\CollectionProvider' tags: - - { name: 'api_platform.data_transformer' } + - name: 'api_platform.state_provider' - app.data_transformer.input_dto: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\InputDtoDataTransformer' - public: false + ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoInputOutputProcessor: tags: - - { name: 'api_platform.data_transformer' } + - name: 'api_platform.state_processor' - app.data_transformer.output_dto: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\OutputDtoDataTransformer' - public: false + ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoInputOutputProvider: tags: - - { name: 'api_platform.data_transformer' } + - name: 'api_platform.state_provider' - app.data_transformer.dummy_dto_no_input_to_output_dto: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\DummyDtoNoInputToOutputDtoDataTransformer' - public: false + ApiPlatform\Tests\Fixtures\TestBundle\State\RecoverPasswordProcessor: tags: - - { name: 'api_platform.data_transformer' } + - name: 'api_platform.state_processor' - app.data_transformer.recover_password_input: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RecoverPasswordInputDataTransformer' - public: false + ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoNoInputsProcessor: + arguments: + $decorated: '@ApiPlatform\Doctrine\Common\State\PersistProcessor' tags: - - { name: 'api_platform.data_transformer' } + - name: 'api_platform.state_processor' - app.data_transformer.recover_password_output: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RecoverPasswordOutputDataTransformer' - public: false + ApiPlatform\Tests\Fixtures\TestBundle\State\InitializeInputProcessor: tags: - - { name: 'api_platform.data_transformer' } - - app.data_transformer.initialize_input: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\InitializeInputDataTransformer' - public: false - tags: - - { name: 'api_platform.data_transformer' } + - name: 'api_platform.state_processor' + # app.data_transformer.custom_input_dto: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\CustomInputDtoDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } + # + # app.data_transformer.custom_output_dto: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\CustomOutputDtoDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } + # + # app.data_transformer.custom_output_dto_fallback_same_class: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\OutputDtoSameClassTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } + # + # app.data_transformer.input_dto: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\InputDtoDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } + # + # app.data_transformer.output_dto: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\OutputDtoDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } + # + # app.data_transformer.dummy_dto_no_input_to_output_dto: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\DummyDtoNoInputToOutputDtoDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } + # + # app.data_transformer.recover_password_input: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RecoverPasswordInputDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } + # + # app.data_transformer.recover_password_output: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RecoverPasswordOutputDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } + # + # app.data_transformer.initialize_input: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\InitializeInputDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } app.messenger_handler.messenger_with_response: class: 'ApiPlatform\Tests\Fixtures\TestBundle\MessengerHandler\MessengerWithResponseHandler' @@ -414,11 +448,11 @@ services: arguments: ['@app.graphql.type_converter.inner'] public: false - app.data_transformer.rpc_output: - class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RPCOutputDataTransformer' - public: false - tags: - - { name: 'api_platform.data_transformer' } + # app.data_transformer.rpc_output: + # class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataTransformer\RPCOutputDataTransformer' + # public: false + # tags: + # - { name: 'api_platform.data_transformer' } app.security.authentication_entrypoint: class: 'ApiPlatform\Tests\Fixtures\TestBundle\Security\AuthenticationEntryPoint' diff --git a/tests/Fixtures/app/config/config_doctrine.yml b/tests/Fixtures/app/config/config_doctrine.yml new file mode 100644 index 00000000000..892e56d3b9c --- /dev/null +++ b/tests/Fixtures/app/config/config_doctrine.yml @@ -0,0 +1,104 @@ +services: + ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\EntityManager: + decorates: 'doctrine.orm.default_entity_manager' + arguments: + $wrapped: '@ApiPlatform\Tests\Fixtures\TestBundle\Doctrine\Orm\EntityManager.inner' + $repositoryFactory: '@doctrine.orm.container_repository_factory' + + app.my_dummy_resource.search_filter: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial', 'alias': 'start', 'description': 'word_start', 'relatedDummy.name': 'exact', 'relatedDummies': 'exact', 'dummy': 'ipartial', 'relatedDummies.name': 'start', 'embeddedDummy.dummyName': 'partial', 'relatedDummy.thirdLevel.level': 'exact', 'relatedDummy.thirdLevel.fourthLevel.level': 'exact', 'relatedDummy.thirdLevel.badFourthLevel.level': 'exact', 'relatedDummy.thirdLevel.fourthLevel.badThirdLevel.level': 'exact', 'nameConverted': 'partial' } ] + tags: [ { name: 'api_platform.filter', id: 'my_dummy.search' } ] + + # Tests if the id default to the service name, do not add id attributes here + app.my_dummy_resource.order_filter: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: [ { 'id': ~, 'name': 'desc', 'description': ~, 'relatedDummy.name': ~, 'embeddedDummy.dummyName': 'desc', 'relatedDummy.symfony': ~, 'dummyDate': ~} ] + tags: [ { name: 'api_platform.filter', id: 'my_dummy.order' } ] + + app.my_dummy_resource.date_filter: + parent: 'api_platform.doctrine.orm.date_filter' + arguments: [ { 'dummyDate': ~, 'relatedDummy.dummyDate': ~, 'embeddedDummy.dummyDate': ~ } ] + tags: [ { name: 'api_platform.filter', id: 'my_dummy.date' } ] + + app.my_dummy_date_resource.date_filter: + parent: 'api_platform.doctrine.orm.date_filter' + arguments: [ { 'dummyDate': ~ } ] + tags: [ { name: 'api_platform.filter', id: 'my_dummy_date.date' } ] + + my_dummy_immutable_date.date: + parent: 'api_platform.doctrine.orm.date_filter' + arguments: [ { 'dummyDate': ~ } ] + tags: [ { name: 'api_platform.filter' } ] + + app.my_dummy_resource.range_filter: + parent: 'api_platform.doctrine.orm.range_filter' + arguments: [ { 'dummyFloat': ~, 'dummyPrice': ~ } ] + tags: [ { name: 'api_platform.filter', id: 'my_dummy.range' } ] + + app.my_dummy_resource.boolean_filter: + parent: 'api_platform.doctrine.orm.boolean_filter' + arguments: [ { 'dummyBoolean': ~, 'embeddedDummy.dummyBoolean': ~, 'relatedDummy.embeddedDummy.dummyBoolean': ~ } ] + tags: [ { name: 'api_platform.filter', id: 'my_dummy.boolean' } ] + + app.my_dummy_resource.numeric_filter: + parent: 'api_platform.doctrine.orm.numeric_filter' + arguments: [ { 'dummyFloat': ~, 'dummyPrice': ~ } ] + tags: [ { name: 'api_platform.filter', id: 'my_dummy.numeric' } ] + + app.my_dummy_resource.exists_filter: + parent: 'api_platform.doctrine.orm.exists_filter' + arguments: [ { 'alias': ~, 'description': ~, 'relatedDummy.name': ~, 'dummyBoolean': ~, 'relatedDummy': ~, 'relatedDummies': ~ } ] + tags: [ { name: 'api_platform.filter', id: 'my_dummy.exists' } ] + + app.related_dummy_resource.search_filter: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'relatedToDummyFriend.dummyFriend': 'exact', 'name': 'partial', 'age': 'exact' } ] + tags: [ { name: 'api_platform.filter', id: 'related_dummy.friends' } ] + + app.related_dummy_resource.complex_sub_query_filter: + class: ApiPlatform\Tests\Fixtures\TestBundle\Filter\LegacyComplexSubQueryFilter + arguments: ['@doctrine'] + tags: [ { name: 'api_platform.filter', id: 'related_dummy.complex_sub_query' } ] + + app.related_dummy_to_friend_resource.search_filter: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'name': 'ipartial', 'description': 'ipartial' } ] + tags: [ { name: 'api_platform.filter', id: 'related_to_dummy_friend.name' } ] + + ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\ProductItemDataProvider: + public: false + arguments: + $managerRegistry: '@doctrine' + tags: + - name: 'api_platform.item_data_provider' + + ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider: + class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\ProductProvider' + public: false + arguments: + $managerRegistry: '@doctrine' + tags: + - name: 'api_platform.state_provider' + + ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\TaxonItemDataProvider: + public: false + arguments: + $managerRegistry: '@doctrine' + tags: + - name: 'api_platform.item_data_provider' + + ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider: + class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\TaxonItemProvider' + public: false + arguments: + $managerRegistry: '@doctrine' + tags: + - name: 'api_platform.state_provider' + + app.dummy_dto_no_input.data_provider: + class: 'ApiPlatform\Tests\Fixtures\TestBundle\DataProvider\DummyDtoNoInputCollectionDataProvider' + public: false + arguments: ['@doctrine'] + tags: + - { name: 'api_platform.collection_data_provider' } From a33d2670d9571b4d89caf9444cd12d3fa26a3791 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 22 Jun 2022 09:28:14 +0200 Subject: [PATCH 38/56] fix(cache): call iriConverter only for resources --- .../EventListener/PurgeHttpCacheListener.php | 8 +++- .../PurgeHttpCacheListenerTest.php | 45 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/Doctrine/EventListener/PurgeHttpCacheListener.php b/src/Doctrine/EventListener/PurgeHttpCacheListener.php index efb7e7967d3..7145fe3e7a1 100644 --- a/src/Doctrine/EventListener/PurgeHttpCacheListener.php +++ b/src/Doctrine/EventListener/PurgeHttpCacheListener.php @@ -22,6 +22,7 @@ use ApiPlatform\Exception\RuntimeException; use ApiPlatform\HttpCache\PurgerInterface; use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Util\ClassInfoTrait; use Doctrine\Common\Util\ClassUtils; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Event\OnFlushEventArgs; @@ -39,6 +40,8 @@ */ final class PurgeHttpCacheListener { + use ClassInfoTrait; + private $purger; private $iriConverter; private $resourceClassResolver; @@ -159,8 +162,11 @@ private function addTagsFor($value): void private function addTagForItem($value): void { + if (!$this->resourceClassResolver->isResourceClass($this->getObjectClass($value))) { + return; + } + try { - // TODO: test if this is a resource class $iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($value) : $this->iriConverter->getIriFromResource($value); $this->tags[$iri] = $iri; } catch (RuntimeException|InvalidArgumentException $e) { diff --git a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php index e7b5d230dd4..a90d31303b8 100644 --- a/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php +++ b/tests/Doctrine/EventListener/PurgeHttpCacheListenerTest.php @@ -21,6 +21,8 @@ use ApiPlatform\Exception\ItemNotFoundException; use ApiPlatform\HttpCache\PurgerInterface; use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Tests\Fixtures\NotAResource; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ContainNonResource; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyNoGetOperation; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy; @@ -73,6 +75,7 @@ public function testOnFlush() $iriConverterProphecy->getIriFromResource(Argument::any())->willThrow(new ItemNotFoundException()); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(true)->shouldBeCalled(); $resourceClassResolverProphecy->getResourceClass(Argument::type(Dummy::class))->willReturn(Dummy::class)->shouldBeCalled(); $resourceClassResolverProphecy->getResourceClass(Argument::type(DummyNoGetOperation::class))->willReturn(DummyNoGetOperation::class)->shouldBeCalled(); @@ -124,6 +127,7 @@ public function testPreUpdate() $iriConverterProphecy->getIriFromResource($newRelatedDummy)->willReturn('/related_dummies/new')->shouldBeCalled(); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(true)->shouldBeCalled(); $resourceClassResolverProphecy->getResourceClass(Argument::type(Dummy::class))->willReturn(Dummy::class)->shouldBeCalled(); $emProphecy = $this->prophesize(EntityManagerInterface::class); @@ -167,4 +171,45 @@ public function testNothingToPurge() $listener->preUpdate($eventArgs); $listener->postFlush(); } + + public function testNotAResourceClass() + { + $containNonResource = new ContainNonResource(); + $nonResource = new NotAResource('foo', 'bar'); + + $purgerProphecy = $this->prophesize(PurgerInterface::class); + $purgerProphecy->purge([])->shouldNotBeCalled(); + + $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); + $iriConverterProphecy->getIriFromResource(ContainNonResource::class, UrlGeneratorInterface::ABS_PATH, Argument::any())->willReturn('/dummies/1'); + $iriConverterProphecy->getIriFromResource($nonResource)->shouldNotBeCalled(); + + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->getResourceClass(Argument::type(ContainNonResource::class))->willReturn(ContainNonResource::class)->shouldBeCalled(); + $resourceClassResolverProphecy->isResourceClass(NotAResource::class)->willReturn(false)->shouldBeCalled(); + + $emProphecy = $this->prophesize(EntityManagerInterface::class); + + $uowProphecy = $this->prophesize(UnitOfWork::class); + $uowProphecy->getScheduledEntityInsertions()->willReturn([$containNonResource])->shouldBeCalled(); + $uowProphecy->getScheduledEntityUpdates()->willReturn([])->shouldBeCalled(); + $uowProphecy->getScheduledEntityDeletions()->willReturn([])->shouldBeCalled(); + + $emProphecy = $this->prophesize(EntityManagerInterface::class); + $emProphecy->getUnitOfWork()->willReturn($uowProphecy->reveal())->shouldBeCalled(); + + $dummyClassMetadata = new ClassMetadata(ContainNonResource::class); + $dummyClassMetadata->associationMappings = [ + 'notAResource' => [], + ]; + $emProphecy->getClassMetadata(ContainNonResource::class)->willReturn($dummyClassMetadata); + $eventArgs = new OnFlushEventArgs($emProphecy->reveal()); + + $propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class); + $propertyAccessorProphecy->isReadable(Argument::type(ContainNonResource::class), 'notAResource')->willReturn(true); + $propertyAccessorProphecy->getValue(Argument::type(ContainNonResource::class), 'notAResource')->shouldBeCalled()->willReturn($nonResource); + + $listener = new PurgeHttpCacheListener($purgerProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceClassResolverProphecy->reveal(), $propertyAccessorProphecy->reveal()); + $listener->onFlush($eventArgs); + } } From 1fa28c203ab861ae9b96e4fa842e1e0d54d430e2 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 22 Jun 2022 09:30:49 +0200 Subject: [PATCH 39/56] fix(jsonapi): use skolem iris --- src/JsonApi/Serializer/ObjectNormalizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JsonApi/Serializer/ObjectNormalizer.php b/src/JsonApi/Serializer/ObjectNormalizer.php index ea930fc11fc..64bced3587b 100644 --- a/src/JsonApi/Serializer/ObjectNormalizer.php +++ b/src/JsonApi/Serializer/ObjectNormalizer.php @@ -84,7 +84,7 @@ public function normalize($object, $format = null, array $context = []) ]; } else { $resourceData = [ - 'id' => \function_exists('spl_object_id') ? spl_object_id($object) : spl_object_hash($object), + 'id' => '/.well-known/genid/'.(bin2hex(random_bytes(10))), 'type' => (new \ReflectionClass($this->getObjectClass($object)))->getShortName(), ]; } From 91ab904bcce282655edb2139239bdd5bbed99649 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 22 Jun 2022 09:33:38 +0200 Subject: [PATCH 40/56] fix(symfony): catch identifiers exceptions in iri converter --- src/Symfony/Routing/IriConverter.php | 2 +- tests/Symfony/Routing/IriConverterTest.php | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Routing/IriConverter.php b/src/Symfony/Routing/IriConverter.php index 1bc3b6abb02..93dbcd7bd7a 100644 --- a/src/Symfony/Routing/IriConverter.php +++ b/src/Symfony/Routing/IriConverter.php @@ -156,7 +156,7 @@ public function getIriFromResource($item, int $referenceType = UrlGeneratorInter if (\is_object($item)) { try { $identifiers = $this->identifiersExtractor->getIdentifiersFromItem($item, $operation); - } catch (RuntimeException $e) { + } catch (InvalidArgumentException|RuntimeException $e) { // We can try using context uri variables if any if (!$identifiers) { throw new InvalidArgumentException(sprintf('Unable to generate an IRI for the item of type "%s"', $resourceClass), $e->getCode(), $e); diff --git a/tests/Symfony/Routing/IriConverterTest.php b/tests/Symfony/Routing/IriConverterTest.php index 79049d83a30..d8c7df74e11 100644 --- a/tests/Symfony/Routing/IriConverterTest.php +++ b/tests/Symfony/Routing/IriConverterTest.php @@ -16,7 +16,8 @@ use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Core\Api\IriConverterInterface; +use ApiPlatform\Api\IriConverterInterface; +use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; @@ -124,6 +125,25 @@ public function testGetIriFromItemWithNoOperations() $iriConverter->getIriFromResource($item); } + public function testGetIriFromItemWithBadIdentifiers() + { + $this->expectExceptionMessage(sprintf('Unable to generate an IRI for the item of type "%s"', Dummy::class)); + + $item = new Dummy(); + $item->setId(1); + + $resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataCollectionFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new ResourceMetadataCollection(Dummy::class, [ + (new ApiResource())->withOperations(new Operations()), + ])); + + $identifiersExtractorProphecy = $this->prophesize(IdentifiersExtractorInterface::class); + $identifiersExtractorProphecy->getIdentifiersFromItem($item, Argument::type(HttpOperation::class))->willThrow(InvalidArgumentException::class); + + $iriConverter = $this->getIriConverter(null, null, $identifiersExtractorProphecy, $resourceMetadataCollectionFactoryProphecy); + $iriConverter->getIriFromResource($item); + } + public function testGetCollectionIri() { $operationName = 'operation_name'; From ec4c8482aaa5eef232886c1fc6d94e6829b24111 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 22 Jun 2022 09:42:36 +0200 Subject: [PATCH 41/56] fix(metadata): merge defaults arrays --- ...butesResourceMetadataCollectionFactory.php | 12 +++++++++++- .../Entity/AttributeDefaultOperations.php | 2 +- ...sResourceMetadataCollectionFactoryTest.php | 19 ++++++++++++++----- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php index 1fbf30f0672..783e7a37311 100644 --- a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php @@ -245,7 +245,17 @@ private function addGlobalDefaults($operation) if (!isset($extraProperties[$key])) { $extraProperties[$key] = $value; } - } elseif (null === $operation->{$getter}()) { + } else { + $currentValue = $operation->{$getter}(); + + if (\is_array($currentValue) && $currentValue) { + $operation = $operation->{'with'.$upperKey}(array_merge($value, $currentValue)); + } + + if (null !== $currentValue) { + continue; + } + $operation = $operation->{'with'.$upperKey}($value); } } diff --git a/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php b/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php index ef54ab11855..20e3f8eadf7 100644 --- a/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php +++ b/tests/Fixtures/TestBundle/Entity/AttributeDefaultOperations.php @@ -16,7 +16,7 @@ use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; -#[ApiResource(paginationItemsPerPage: 10, graphQlOperations: [])] +#[ApiResource(paginationItemsPerPage: 10, graphQlOperations: [], cacheHeaders: ['shared_max_age' => 60])] final class AttributeDefaultOperations { public function __construct(#[ApiProperty(identifier: true)] private readonly int $identifier, private readonly string $name) diff --git a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php index 1a5ab585e94..1a8901f5707 100644 --- a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php @@ -138,9 +138,17 @@ class: AttributeResources::class, public function testCreateWithDefaults(): void { - $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory(null, null, ['cache_headers' => ['max_age' => 60], 'non_existing_attribute' => 'foo']); - - $operation = new HttpOperation(shortName: 'AttributeDefaultOperations', class: AttributeDefaultOperations::class, cacheHeaders: ['max_age' => 60], paginationItemsPerPage: 10, extraProperties: ['non_existing_attribute' => 'foo']); + $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory(null, null, [ + 'cache_headers' => [ + 'max_age' => 60, + 'shared_max_age' => 120, + 'public' => true, + ], + 'non_existing_attribute' => 'foo', + ]); + + // Check the AttributeDefaultOperations it specifies a shared_max_age that should not be overridden + $operation = new HttpOperation(shortName: 'AttributeDefaultOperations', class: AttributeDefaultOperations::class, cacheHeaders: ['max_age' => 60, 'shared_max_age' => 60, 'public' => true], paginationItemsPerPage: 10, extraProperties: ['non_existing_attribute' => 'foo']); $this->assertEquals(new ResourceMetadataCollection(AttributeDefaultOperations::class, [ new ApiResource( @@ -155,7 +163,7 @@ class: AttributeDefaultOperations::class, '_api_AttributeDefaultOperations_patch' => (new Patch())->withOperation($operation), '_api_AttributeDefaultOperations_delete' => (new Delete())->withOperation($operation), ], - cacheHeaders: ['max_age' => 60], + cacheHeaders: ['max_age' => 60, 'shared_max_age' => 60, 'public' => true], paginationItemsPerPage: 10, extraProperties: ['non_existing_attribute' => 'foo'] ), @@ -170,7 +178,7 @@ public function testCreateShouldNotOverrideWithDefault(): void ] ); - $operation = new HttpOperation(shortName: 'AttributeDefaultOperations', class: AttributeDefaultOperations::class, paginationItemsPerPage: 10); + $operation = new HttpOperation(shortName: 'AttributeDefaultOperations', class: AttributeDefaultOperations::class, paginationItemsPerPage: 10, cacheHeaders: ['shared_max_age' => 60]); $this->assertEquals(new ResourceMetadataCollection(AttributeDefaultOperations::class, [ new ApiResource( shortName: 'AttributeDefaultOperations', @@ -183,6 +191,7 @@ class: AttributeDefaultOperations::class, '_api_AttributeDefaultOperations_patch' => (new Patch())->withOperation($operation), '_api_AttributeDefaultOperations_delete' => (new Delete())->withOperation($operation), ], + cacheHeaders: ['shared_max_age' => 60], graphQlOperations: [], paginationItemsPerPage: 10 ), From 7dcf80d656c305b9d610a6d10c03bc75d5028afa Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 22 Jun 2022 09:54:44 +0200 Subject: [PATCH 42/56] fix(test): use an operation within schema assertions --- .../Bundle/Test/ApiTestAssertionsTrait.php | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php b/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php index 60080f41703..5fadbe45982 100644 --- a/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php +++ b/src/Symfony/Bundle/Test/ApiTestAssertionsTrait.php @@ -17,6 +17,7 @@ use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Symfony\Bundle\Test\Constraint\ArraySubset; use ApiPlatform\Symfony\Bundle\Test\Constraint\MatchesJsonSchema; use PHPUnit\Framework\ExpectationFailedException; @@ -113,14 +114,30 @@ public static function assertMatchesJsonSchema($jsonSchema, ?int $checkMode = nu public static function assertMatchesResourceCollectionJsonSchema(string $resourceClass, ?string $operationName = null, string $format = 'jsonld'): void { - $schema = self::getSchemaFactory()->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, new GetCollection(name: $operationName), null); + $schemaFactory = self::getSchemaFactory(); + + if ($resourceMetadataFactoryCollection = self::getResourceMetadataCollectionFactory()) { + $operation = $resourceMetadataFactoryCollection->create($resourceClass)->getOperation($operationName, true); + } else { + $operation = $operationName ? (new GetCollection())->withName($operationName) : new GetCollection(); + } + + $schema = $schemaFactory->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, $operation, null); static::assertMatchesJsonSchema($schema->getArrayCopy()); } public static function assertMatchesResourceItemJsonSchema(string $resourceClass, ?string $operationName = null, string $format = 'jsonld'): void { - $schema = self::getSchemaFactory()->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, new Get(name: $operationName), null); + $schemaFactory = self::getSchemaFactory(); + + if ($resourceMetadataFactoryCollection = self::getResourceMetadataCollectionFactory()) { + $operation = $resourceMetadataFactoryCollection->create($resourceClass)->getOperation($operationName); + } else { + $operation = $operationName ? (new Get())->withName($operationName) : new Get(); + } + + $schema = $schemaFactory->buildSchema($resourceClass, $format, Schema::TYPE_OUTPUT, $operation, null); static::assertMatchesJsonSchema($schema->getArrayCopy()); } @@ -149,15 +166,12 @@ private static function getHttpResponse(): ResponseInterface return $response; } - /** - * @return SchemaFactoryInterface|LegacySchemaFactoryInterface - */ - private static function getSchemaFactory() + private static function getSchemaFactory(): SchemaFactoryInterface { $container = method_exists(static::class, 'getContainer') ? static::getContainer() : static::$container; // @phpstan-ignore-line try { - /** @var SchemaFactoryInterface|LegacySchemaFactoryInterface $schemaFactory */ + /** @var SchemaFactoryInterface $schemaFactory */ $schemaFactory = $container->get('api_platform.json_schema.schema_factory'); } catch (ServiceNotFoundException $e) { throw new \LogicException('You cannot use the resource JSON Schema assertions if the "api_platform.swagger.versions" config is null or empty.'); @@ -165,4 +179,17 @@ private static function getSchemaFactory() return $schemaFactory; } + + private static function getResourceMetadataCollectionFactory(): ?ResourceMetadataCollectionFactoryInterface + { + $container = method_exists(static::class, 'getContainer') ? static::getContainer() : static::$container; // @phpstan-ignore-line + + try { + $resourceMetadataFactoryCollection = $container->get('api_platform.metadata.resource.metadata_collection_factory'); + } catch (ServiceNotFoundException $e) { + return null; + } + + return $resourceMetadataFactoryCollection; + } } From 88419daa985587ac17ddafa3b51a05080cc58fb2 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 22 Jun 2022 15:37:58 +0200 Subject: [PATCH 43/56] tests patch, rpc fix wrong iris --- features/main/default_order.feature | 4 +-- features/main/operation.feature | 4 +-- features/main/operation_resource.feature | 1 + features/main/overridden_operation.feature | 2 +- src/Serializer/AbstractItemNormalizer.php | 8 ++---- .../TestBundle/Document/PatchDummy.php | 2 +- .../Document/PatchDummyRelation.php | 2 +- .../TestBundle/Entity/OperationResource.php | 17 ++++++++++-- .../Fixtures/TestBundle/Entity/PatchDummy.php | 2 +- .../TestBundle/Entity/PatchDummyRelation.php | 2 +- tests/Fixtures/TestBundle/Entity/RPC.php | 3 ++- .../TestBundle/Entity/RelationEmbedder.php | 4 +-- .../Fixtures/TestBundle/Entity/VoDummyCar.php | 2 +- .../TestBundle/State/RPCProcessor.php | 26 +++++++++++++++++++ tests/Fixtures/app/config/config_common.yml | 6 +++++ tests/Symfony/Routing/IriConverterTest.php | 2 +- 16 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 tests/Fixtures/TestBundle/State/RPCProcessor.php diff --git a/features/main/default_order.feature b/features/main/default_order.feature index 1bc97ab37c1..91211014315 100644 --- a/features/main/default_order.feature +++ b/features/main/default_order.feature @@ -127,7 +127,7 @@ Feature: Default order """ { "@context": "/contexts/Foo", - "@id": "/foos", + "@id": "/custom_collection_asc_foos", "@type": "hydra:Collection", "hydra:member": [ { @@ -183,7 +183,7 @@ Feature: Default order """ { "@context": "/contexts/Foo", - "@id": "/foos", + "@id": "/custom_collection_desc_foos", "@type": "hydra:Collection", "hydra:member": [ { diff --git a/features/main/operation.feature b/features/main/operation.feature index 24dda9b8746..8786f6b04ef 100644 --- a/features/main/operation.feature +++ b/features/main/operation.feature @@ -47,7 +47,7 @@ Feature: Operation support """ { "@context": "/contexts/EmbeddedDummy", - "@id": "/embedded_dummies/1", + "@id": "/embedded_dummies_groups/1", "@type": "EmbeddedDummy", "name": "Dummy #1", "embeddedDummy": { @@ -76,7 +76,7 @@ Feature: Operation support """ { "@context": "/contexts/Book", - "@id": "/books/1", + "@id": "/books/by_isbn/9780451524935", "@type": "Book", "name": "1984", "isbn": "9780451524935", diff --git a/features/main/operation_resource.feature b/features/main/operation_resource.feature index 42794174264..a30054294fb 100644 --- a/features/main/operation_resource.feature +++ b/features/main/operation_resource.feature @@ -28,6 +28,7 @@ Feature: Resource operations """ {"name": "Patched"} """ + Then print last JSON response Then the response status code should be 200 And the response should be in JSON And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" diff --git a/features/main/overridden_operation.feature b/features/main/overridden_operation.feature index 4d57a700a03..d07181de8bd 100644 --- a/features/main/overridden_operation.feature +++ b/features/main/overridden_operation.feature @@ -153,4 +153,4 @@ Feature: Create-Retrieve-Update-Delete with a Overridden Operation context """ Then the response status code should be 200 And the JSON node "success" should be equal to "YES" - And the JSON node "@type" should be equal to "RPC" + And the JSON node "@type" should be equal to "RPCOutput" diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 920c2c75f03..a510c00e2e5 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -638,12 +638,8 @@ protected function getAttributeValue($object, $attribute, $format = null, array $childContext = $this->createChildContext($context, $attribute, $format); unset($childContext['iri'], $childContext['uri_variables']); - if ($propertyMetadata instanceof PropertyMetadata) { - $childContext['output']['iri'] = $propertyMetadata->getIri(); - } else { - if (null !== ($propertyIris = $propertyMetadata->getIris())) { - $childContext['output']['iri'] = 1 === \count($propertyIris) ? $propertyIris[0] : $propertyIris; - } + if (null !== ($propertyIris = $propertyMetadata->getIris())) { + $childContext['output']['iri'] = 1 === \count($propertyIris) ? $propertyIris[0] : $propertyIris; } return $this->serializer->normalize($attributeValue, $format, $childContext); diff --git a/tests/Fixtures/TestBundle/Document/PatchDummy.php b/tests/Fixtures/TestBundle/Document/PatchDummy.php index b86e852b60f..0165652ee32 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummy.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummy.php @@ -23,7 +23,7 @@ /** * @author Kévin Dunglas */ -#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()])] +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi'], normalizationContext: ['skip_null_values' => true]), new Post(), new GetCollection()])] #[ODM\Document] class PatchDummy { diff --git a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php index ae5a9b477b1..68b7020b23a 100644 --- a/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Document/PatchDummyRelation.php @@ -24,7 +24,7 @@ /** * @author Kévin Dunglas */ -#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi'], normalizationContext: ['skip_null_values' => true, 'groups' => ['chicago']]), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] #[ODM\Document] class PatchDummyRelation { diff --git a/tests/Fixtures/TestBundle/Entity/OperationResource.php b/tests/Fixtures/TestBundle/Entity/OperationResource.php index 955a72d204f..1e023516b05 100644 --- a/tests/Fixtures/TestBundle/Entity/OperationResource.php +++ b/tests/Fixtures/TestBundle/Entity/OperationResource.php @@ -23,17 +23,30 @@ use ApiPlatform\Tests\Fixtures\TestBundle\State\OperationResourceProcessor; use Doctrine\ORM\Mapping as ORM; +#[ORM\Entity] #[ApiResource(normalizationContext: ['skip_null_values' => true], processor: OperationResourceProcessor::class)] #[Get] #[Patch(inputFormats: ['json' => ['application/merge-patch+json']])] #[Post] #[Put] #[Delete] -#[ORM\Entity] class OperationResource { - public function __construct(#[ApiProperty(identifier: true)] #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private readonly int $identifier, public string $name) + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] + #[ApiProperty(identifier: true)] + private $identifier; + + /** + * @var string + */ + public $name; + + public function __construct(int $identifier, string $name) { + $this->identifier = $identifier; + $this->name = $name; } public function getIdentifier() diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummy.php b/tests/Fixtures/TestBundle/Entity/PatchDummy.php index aaa4bb7c718..5b660be9463 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummy.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummy.php @@ -23,7 +23,7 @@ /** * @author Kévin Dunglas */ -#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()])] +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi'], normalizationContext: ['skip_null_values' => true]), new Post(), new GetCollection()])] #[ORM\Entity] class PatchDummy { diff --git a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php index bd567060d8e..bbad3440044 100644 --- a/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php +++ b/tests/Fixtures/TestBundle/Entity/PatchDummyRelation.php @@ -24,7 +24,7 @@ /** * @author Kévin Dunglas */ -#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi']), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] +#[ApiResource(operations: [new Get(), new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'jsonapi'], normalizationContext: ['skip_null_values' => true, 'groups' => ['chicago']]), new Post(), new GetCollection()], normalizationContext: ['groups' => ['chicago']], denormalizationContext: ['groups' => ['chicago']])] #[ORM\Entity] class PatchDummyRelation { diff --git a/tests/Fixtures/TestBundle/Entity/RPC.php b/tests/Fixtures/TestBundle/Entity/RPC.php index 2f3fac9d713..14f7186c0bd 100644 --- a/tests/Fixtures/TestBundle/Entity/RPC.php +++ b/tests/Fixtures/TestBundle/Entity/RPC.php @@ -16,11 +16,12 @@ use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Post; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RPCOutput; +use ApiPlatform\Tests\Fixtures\TestBundle\State\RPCProcessor; /** * RPC-like resource. */ -#[ApiResource(operations: [new Post(status: 202, messenger: true, uriTemplate: 'rpc', output: false), new Post(status: 200, uriTemplate: 'rpc_output', output: RPCOutput::class)])] +#[ApiResource(operations: [new Post(status: 202, messenger: true, uriTemplate: 'rpc', output: false), new Post(status: 200, uriTemplate: 'rpc_output', output: RPCOutput::class, processor: RPCProcessor::class)])] class RPC { /** diff --git a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php index 3b61cdf9683..4803986e597 100644 --- a/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php +++ b/tests/Fixtures/TestBundle/Entity/RelationEmbedder.php @@ -43,10 +43,10 @@ class RelationEmbedder public $krondstadt = 'Krondstadt'; #[ORM\ManyToOne(targetEntity: RelatedDummy::class, cascade: ['persist'])] #[Groups(['chicago', 'barcelona'])] - public $anotherRelated; + public ?RelatedDummy $anotherRelated; #[ORM\ManyToOne(targetEntity: RelatedDummy::class)] #[Groups(['barcelona', 'chicago'])] - protected $related; + protected ?RelatedDummy $related; public function getRelated() { diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php index 25fe7667332..200377453c9 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyCar.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyCar.php @@ -28,7 +28,7 @@ class VoDummyCar extends VoDummyVehicle */ #[ORM\OneToMany(targetEntity: VoDummyInspection::class, mappedBy: 'car', cascade: ['persist'])] #[Groups(['car_read', 'car_write'])] - private readonly array|\Doctrine\Common\Collections\Collection $inspections; + private array|Collection $inspections; public function __construct(string $make, VoDummyInsuranceCompany $insuranceCompany, array $drivers, #[ORM\Column(type: 'integer')] #[Groups(['car_read', 'car_write'])] private readonly int $mileage, #[ORM\Column] #[Groups(['car_read', 'car_write'])] private readonly string $bodyType = 'coupe') { diff --git a/tests/Fixtures/TestBundle/State/RPCProcessor.php b/tests/Fixtures/TestBundle/State/RPCProcessor.php new file mode 100644 index 00000000000..deea611b091 --- /dev/null +++ b/tests/Fixtures/TestBundle/State/RPCProcessor.php @@ -0,0 +1,26 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\RPCOutput; + +final class RPCProcessor implements ProcessorInterface +{ + public function process($data, Operation $operation, array $uriVariables = [], array $context = []) + { + return new RPCOutput(); + } +} diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index 9c930df6d76..b0313ae6fea 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -116,6 +116,12 @@ services: tags: - { name: 'api_platform.state_processor' } + ApiPlatform\Tests\Fixtures\TestBundle\State\RPCProcessor: + class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\RPCProcessor' + public: false + tags: + - { name: 'api_platform.state_processor' } + ApiPlatform\Tests\Fixtures\TestBundle\State\ContainNonResourceProvider: class: 'ApiPlatform\Tests\Fixtures\TestBundle\State\ContainNonResourceProvider' diff --git a/tests/Symfony/Routing/IriConverterTest.php b/tests/Symfony/Routing/IriConverterTest.php index d8c7df74e11..540171c8ac0 100644 --- a/tests/Symfony/Routing/IriConverterTest.php +++ b/tests/Symfony/Routing/IriConverterTest.php @@ -14,9 +14,9 @@ namespace ApiPlatform\Tests\Symfony\Routing; use ApiPlatform\Api\IdentifiersExtractorInterface; +use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; -use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\RuntimeException; use ApiPlatform\Metadata\ApiResource; From e7f3fde72a7a2a478fa4ab7a99c5874a85f25362 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Sat, 21 May 2022 14:32:26 +0200 Subject: [PATCH 44/56] fix: clear missing metadata pools (#4770) --- .../Bundle/DependencyInjection/ApiPlatformExtension.php | 8 ++++++++ src/Symfony/Bundle/Resources/config/symfony/events.xml | 2 -- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 3a5be8d9e23..4295ace6ca1 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -34,6 +34,7 @@ use ApiPlatform\State\ProviderInterface; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; use phpDocumentor\Reflection\DocBlockFactoryInterface; use Ramsey\Uuid\Uuid; use Symfony\Component\Config\FileLocator; @@ -479,6 +480,13 @@ private function registerCacheConfiguration(ContainerBuilder $container): void if (!$container->hasParameter('kernel.debug') || !$container->getParameter('kernel.debug')) { $container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer'); } + + $container->register('api_platform.cache.metadata.property', ArrayAdapter::class); + $container->register('api_platform.cache.metadata.resource', ArrayAdapter::class); + $container->register('api_platform.cache.metadata.resource_collection', ArrayAdapter::class); + $container->register('api_platform.cache.route_name_resolver', ArrayAdapter::class); + $container->register('api_platform.cache.identifiers_extractor', ArrayAdapter::class); + $container->register('api_platform.elasticsearch.cache.metadata.document', ArrayAdapter::class); } private function registerDoctrineOrmConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void diff --git a/src/Symfony/Bundle/Resources/config/symfony/events.xml b/src/Symfony/Bundle/Resources/config/symfony/events.xml index c136206d5ed..71e30db5292 100644 --- a/src/Symfony/Bundle/Resources/config/symfony/events.xml +++ b/src/Symfony/Bundle/Resources/config/symfony/events.xml @@ -79,9 +79,7 @@ api_platform.cache.metadata.property - api_platform.cache.metadata.property.legacy api_platform.cache.metadata.resource - api_platform.cache.metadata.resource.legacy api_platform.cache.metadata.resource_collection api_platform.cache.route_name_resolver api_platform.cache.identifiers_extractor From a9f2ae0bbbb7a21691edd716ebdf217b35e8a6f0 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 23 Jun 2022 19:33:10 +0200 Subject: [PATCH 45/56] fix subresource iris --- features/main/subresource.feature | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/features/main/subresource.feature b/features/main/subresource.feature index ae4969a5abf..2fd278ea02e 100644 --- a/features/main/subresource.feature +++ b/features/main/subresource.feature @@ -13,7 +13,7 @@ Feature: Subresource support """ { "@context": "/contexts/Answer", - "@id": "/answers/1", + "@id": "/questions/1/answer", "@type": "Answer", "id": 1, "content": "42", @@ -234,7 +234,7 @@ Feature: Subresource support """ { "@context": "/contexts/RelatedDummy", - "@id": "/related_dummies/2", + "@id": "/dummies/1/related_dummies/2", "@type": "https://schema.org/Product", "id": 2, "name": null, @@ -274,7 +274,7 @@ Feature: Subresource support """ { "@context": "/contexts/ThirdLevel", - "@id": "/third_levels/1", + "@id": "/dummies/1/related_dummies/1/third_level", "@type": "ThirdLevel", "fourthLevel": "/fourth_levels/1", "badFourthLevel": null, @@ -293,7 +293,7 @@ Feature: Subresource support """ { "@context": "/contexts/FourthLevel", - "@id": "/fourth_levels/1", + "@id": "/dummies/1/related_dummies/1/third_level/fourth_level", "@type": "FourthLevel", "badThirdLevel": [], "id": 1, @@ -411,7 +411,7 @@ Feature: Subresource support """ { "@context": "/contexts/Dummy", - "@id": "/dummies/1", + "@id": "/related_owned_dummies/1/owning_dummy", "@type": "Dummy", "description": null, "dummy": null, @@ -444,7 +444,7 @@ Feature: Subresource support """ { "@context": "/contexts/Dummy", - "@id": "/dummies/1", + "@id": "/related_owning_dummies/1/owned_dummy", "@type": "Dummy", "description": null, "dummy": null, From 811f4bed964703ea45a4f0c51646652f1697011b Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 23 Jun 2022 20:14:10 +0200 Subject: [PATCH 46/56] fixtures upgrade php8 fixes --- .../Orm/DummyValidationController.php | 4 +- .../Document/DummyCustomMutation.php | 83 +++++++++-------- .../TestBundle/Document/DummyCustomQuery.php | 84 +++++++---------- tests/Fixtures/TestBundle/Entity/Answer.php | 4 +- .../TestBundle/Entity/DummyAggregateOffer.php | 5 +- .../TestBundle/Entity/DummyCustomMutation.php | 90 +++++++++---------- .../TestBundle/Entity/DummyCustomQuery.php | 81 +++++++---------- .../TestBundle/Entity/DummyDtoNoInput.php | 7 +- .../TestBundle/Entity/DummyValidation.php | 12 +-- .../TestBundle/Entity/RamseyUuidDummy.php | 2 +- .../State/DummyDtoNoInputsProvider.php | 58 ++++++++++++ 11 files changed, 226 insertions(+), 204 deletions(-) create mode 100644 tests/Fixtures/TestBundle/State/DummyDtoNoInputsProvider.php diff --git a/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php b/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php index 2b6d837d995..1c652b87e9f 100644 --- a/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php +++ b/tests/Fixtures/TestBundle/Controller/Orm/DummyValidationController.php @@ -21,7 +21,7 @@ class DummyValidationController /** * @param mixed $data */ - #[Route(methods: ['POST'], name: 'post_validation_groups', path: '/dummy_validation/validation_groups', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_groups'])] + #[Route(methods: ['POST'], name: 'post_validation_groups', path: '/dummy_validation/validation_groups', defaults: ['_api_resource_class' => DummyValidation::class, '_api_operation_name' => 'post_validation_groups'])] public function postValidationGroups($data) { return $data; @@ -30,7 +30,7 @@ public function postValidationGroups($data) /** * @param mixed $data */ - #[Route(methods: ['POST'], name: 'post_validation_sequence', path: '/dummy_validation/validation_sequence', defaults: ['_api_resource_class' => DummyValidation::class, '_api_collection_operation_name' => 'post_validation_sequence'])] + #[Route(methods: ['POST'], name: 'post_validation_sequence', path: '/dummy_validation/validation_sequence', defaults: ['_api_resource_class' => DummyValidation::class, '_api_operation_name' => 'post_validation_sequence'])] public function postValidationSequence($data) { return $data; diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php index 36621125f89..c2aa97c42d5 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomMutation.php @@ -20,71 +20,68 @@ /** * Dummy with a custom GraphQL mutation resolver. * - * @ODM\Document - * @ApiResource(graphql={ - * "sum"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNotPersisted"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNoWriteCustomResult"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "write"=false - * }, - * "sumOnlyPersist"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist_document", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "read"=false, - * "deserialize"=false, - * "validate"=false, - * "serialize"=false - * }, - * "testCustomArguments"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "args"={"operandC"={"type"="Int!"}} - * } - * }) - * * @author Raoul Clais */ +#[ODM\Document] +#[ApiResource(graphQlOperations: [ + new Mutation( + name: 'sum', + resolver: 'app.graphql.mutation_resolver.dummy_custom', + normalizationContext: ['groups' => ['result']], + denormalizationContext: ['groups' => ['sum']] + ), + new Mutation( + name: 'sumNotPersisted', + resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', + normalizationContext: ['groups' => ['result']], + denormalizationContext: ['groups' => ['sum']] + ), + new Mutation(name: 'sumNoWriteCustomResult', + resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', + normalizationContext: ['groups' => ['result']], + denormalizationContext: ['groups' => ['sum']], + write: false + ), + new Mutation(name: 'sumOnlyPersist', + resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist_document', + normalizationContext: ['groups' => ['result']], + denormalizationContext: ['groups' => ['sum']], + read: false, + deserialize: false, + validate: false, + serialize: false + ), + new Mutation(name: 'testCustomArguments', + resolver: 'app.graphql.mutation_resolver.dummy_custom', + args: ['operandC' => ['type' => 'Int!']] + ), +])] class DummyCustomMutation { /** * @var int|null - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] private $id; /** * @var int|null - * - * @ODM\Field(type="int") */ + #[ODM\Field(type: 'int')] private $operandA; /** * @var int|null - * - * @Groups({"sum"}) - * @ODM\Field(type="int", nullable=true) */ + #[Groups(['sum'])] + #[ODM\Field(type: 'int', nullable: true)] private $operandB; /** * @var int|null - * - * @Groups({"result"}) - * @ODM\Field(type="int", nullable=true) */ + #[Groups(['result'])] + #[ODM\Field(type: 'int', nullable: true)] private $result; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php index c8e0ba438f5..dff1603822c 100644 --- a/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Document/DummyCustomQuery.php @@ -13,64 +13,46 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -/** - * Dummy with custom GraphQL query resolvers. - * - * @author Lukas Lücke - * - * @ApiResource(graphql={ - * "testItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item" - * }, - * "testNotRetrievedItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item_document", - * "args"={} - * }, - * "testNoReadAndSerializeItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document", - * "read"=false, - * "serialize"=false - * }, - * "testItemCustomArguments"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item", - * "args"={ - * "id"={"type"="ID"}, - * "customArgumentNullableBool"={"type"="Boolean"}, - * "customArgumentBool"={"type"="Boolean!"}, - * "customArgumentInt"={"type"="Int!"}, - * "customArgumentString"={"type"="String!"}, - * "customArgumentFloat"={"type"="Float!"}, - * "customArgumentIntArray"={"type"="[Int!]!"}, - * "customArgumentCustomType"={"type"="DateTime!"} - * } - * }, - * "testCollection"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection" - * }, - * "testCollectionNoReadAndSerialize"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testCollectionCustomArguments"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection", - * "args"={ - * "customArgumentString"={"type"="String!"} - * } - * } - * }) - * @ODM\Document - */ + /** + * Dummy with custom GraphQL query resolvers. + * + * @author Lukas Lücke + */ + #[ODM\Document] + #[ApiResource(graphQlOperations: [ + new Query(resolver: 'app.graphql.query_resolver.dummy_custom_item', name: 'testItem'), + new Query(args: [], resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item_document', name: 'testNotRetrievedItem'), + new Query(resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document', read: false, serialize: false, name: 'testNoReadAndSerializeItem'), + new Query( + resolver: 'app.graphql.query_resolver.dummy_custom_item', + args: [ + 'id' => ['type' => 'ID'], + 'customArgumentNullableBool' => ['type' => 'Boolean'], + 'customArgumentBool' => ['type' => 'Boolean!'], + 'customArgumentInt' => ['type' => 'Int!'], + 'customArgumentString' => ['type' => 'String!'], + 'customArgumentFloat' => ['type' => 'Float!'], + 'customArgumentIntArray' => ['type' => '[Int!]!'], + 'customArgumentCustomType' => ['type' => 'DateTime!'], + ], name: 'testItemCustomArguments'), + new QueryCollection(resolver: 'app.graphql.query_resolver.dummy_custom_collection', name: 'testCollection'), + new QueryCollection(resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false, name: 'testCollectionNoReadAndSerialize'), + new Query( + name: 'testCollectionCustomArguments', + resolver: 'app.graphql.query_resolver.dummy_custom_collection', + args: ['customArgumentString' => ['type' => 'String!']]), + ])] class DummyCustomQuery { /** * @var int - * - * @ODM\Id(strategy="INCREMENT", type="int") */ + #[ODM\Id(strategy: 'INCREMENT', type: 'int')] public $id; /** diff --git a/tests/Fixtures/TestBundle/Entity/Answer.php b/tests/Fixtures/TestBundle/Entity/Answer.php index bbc89f5abb0..141311889b4 100644 --- a/tests/Fixtures/TestBundle/Entity/Answer.php +++ b/tests/Fixtures/TestBundle/Entity/Answer.php @@ -46,11 +46,11 @@ class Answer #[Serializer\Groups(['foobar'])] private $question; /** - * @var \Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: Question::class, mappedBy: 'answer')] #[Serializer\Groups(['foobar'])] - private readonly \Collection $relatedQuestions; + private Collection $relatedQuestions; public function __construct() { diff --git a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php index 6097e450a49..c03364b9f09 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php +++ b/tests/Fixtures/TestBundle/Entity/DummyAggregateOffer.php @@ -17,6 +17,7 @@ use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Link; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; /** @@ -40,10 +41,10 @@ class DummyAggregateOffer #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; /** - * @var \Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: DummyOffer::class, mappedBy: 'aggregate', cascade: ['persist'])] - private \Collection $offers; + private Collection $offers; /** * @var DummyProduct|null The dummy product */ diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php index d14ccdb0f86..03b3dbefb10 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php @@ -13,80 +13,78 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Mutation; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * Dummy with a custom GraphQL mutation resolver. * - * @ORM\Entity - * @ApiResource(graphql={ - * "sum"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNotPersisted"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}} - * }, - * "sumNoWriteCustomResult"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "write"=false - * }, - * "sumOnlyPersist"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist", - * "normalization_context"={"groups"={"result"}}, - * "denormalization_context"={"groups"={"sum"}}, - * "read"=false, - * "deserialize"=false, - * "validate"=false, - * "serialize"=false - * }, - * "testCustomArguments"={ - * "mutation"="app.graphql.mutation_resolver.dummy_custom", - * "args"={"operandC"={"type"="Int!"}} - * } - * }) - * * @author Raoul Clais */ +#[ORM\Entity] +#[ApiResource(graphQlOperations: [ + new Mutation( + name: 'sum', + resolver: 'app.graphql.mutation_resolver.dummy_custom', + normalizationContext: ['groups' => ['result']], + denormalizationContext: ['groups' => ['sum']] + ), + new Mutation( + name: 'sumNotPersisted', + resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', + normalizationContext: ['groups' => ['result']], + denormalizationContext: ['groups' => ['sum']] + ), + new Mutation(name: 'sumNoWriteCustomResult', + resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', + normalizationContext: ['groups' => ['result']], + denormalizationContext: ['groups' => ['sum']], + write: false + ), + new Mutation(name: 'sumOnlyPersist', + resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist', + normalizationContext: ['groups' => ['result']], + denormalizationContext: ['groups' => ['sum']], + read: false, + deserialize: false, + validate: false, + serialize: false + ), + new Mutation(name: 'testCustomArguments', + resolver: 'app.graphql.mutation_resolver.dummy_custom', + args: ['operandC' => ['type' => 'Int!']] + ), +])] class DummyCustomMutation { /** * @var int|null - * - * @ORM\Column(type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** * @var int|null - * - * @ORM\Column(type="integer", nullable=true) */ + #[ORM\Column(type: 'integer', nullable: true)] private $operandA; /** * @var int|null - * - * @Groups({"sum"}) - * @ORM\Column(type="integer", nullable=true) */ + #[Groups(['sum'])] + #[ORM\Column(type: 'integer', nullable: true)] private $operandB; /** * @var int|null - * - * @Groups({"result"}) - * @ORM\Column(type="integer", nullable=true) */ + #[Groups(['result'])] + #[ORM\Column(type: 'integer', nullable: true)] private $result; public function getId(): ?int diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php index 56240c35a35..b570184ac76 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php @@ -13,66 +13,47 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; -use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use Doctrine\ORM\Mapping as ORM; /** * Dummy with custom GraphQL query resolvers. - * - * @author Lukas Lücke - * - * @ApiResource(graphql={ - * "testItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item" - * }, - * "testNotRetrievedItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item", - * "args"={} - * }, - * "testNoReadAndSerializeItem"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testItemCustomArguments"={ - * "item_query"="app.graphql.query_resolver.dummy_custom_item", - * "args"={ - * "id"={"type"="ID"}, - * "customArgumentNullableBool"={"type"="Boolean"}, - * "customArgumentBool"={"type"="Boolean!"}, - * "customArgumentInt"={"type"="Int!"}, - * "customArgumentString"={"type"="String!"}, - * "customArgumentFloat"={"type"="Float!"}, - * "customArgumentIntArray"={"type"="[Int!]!"}, - * "customArgumentCustomType"={"type"="DateTime!"} - * } - * }, - * "testCollection"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection" - * }, - * "testCollectionNoReadAndSerialize"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize", - * "read"=false, - * "serialize"=false - * }, - * "testCollectionCustomArguments"={ - * "collection_query"="app.graphql.query_resolver.dummy_custom_collection", - * "args"={ - * "customArgumentString"={"type"="String!"} - * } - * } - * }) - * @ORM\Entity */ +#[ORM\Entity] +#[ApiResource(graphQlOperations: [ + new Query(resolver: 'app.graphql.query_resolver.dummy_custom_item', name: 'testItem'), + new Query(args: [], resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item', name: 'testNotRetrievedItem'), + new Query(resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize', read: false, serialize: false, name: 'testNoReadAndSerializeItem'), + new Query( + resolver: 'app.graphql.query_resolver.dummy_custom_item', + args: [ + 'id' => ['type' => 'ID'], + 'customArgumentNullableBool' => ['type' => 'Boolean'], + 'customArgumentBool' => ['type' => 'Boolean!'], + 'customArgumentInt' => ['type' => 'Int!'], + 'customArgumentString' => ['type' => 'String!'], + 'customArgumentFloat' => ['type' => 'Float!'], + 'customArgumentIntArray' => ['type' => '[Int!]!'], + 'customArgumentCustomType' => ['type' => 'DateTime!'], + ], name: 'testItemCustomArguments'), + new QueryCollection(resolver: 'app.graphql.query_resolver.dummy_custom_collection', name: 'testCollection'), + new QueryCollection(resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false, name: 'testCollectionNoReadAndSerialize'), + new Query( + name: 'testCollectionCustomArguments', + resolver: 'app.graphql.query_resolver.dummy_custom_collection', + args: ['customArgumentString' => ['type' => 'String!']] + ), +])] class DummyCustomQuery { /** * @var int - * - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] public $id; /** diff --git a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php index 6cbcd80e121..f88d4e6ac0a 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php +++ b/tests/Fixtures/TestBundle/Entity/DummyDtoNoInput.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; +use ApiPlatform\Doctrine\Orm\State\ItemProvider; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; @@ -22,6 +23,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Controller\DummyDtoNoInput\DoubleBatAction; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; use ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoNoInputsProcessor; +use ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoNoInputsProvider; use Doctrine\ORM\Mapping as ORM; /** @@ -33,12 +35,13 @@ operations: [ new Get(), new Delete(), - new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200, processor: DummyDtoNoInputsProcessor::class), + new Post(uriTemplate: '/dummy_dto_no_inputs/{id}/double_bat', controller: DoubleBatAction::class, status: 200, processor: DummyDtoNoInputsProcessor::class, output: DummyDtoNoInput::class, provider: ItemProvider::class), new Post(uriTemplate: '/dummy_dto_no_inputs', controller: CreateItemAction::class, processor: DummyDtoNoInputsProcessor::class), new GetCollection(), ], input: false, - output: OutputDto::class + output: OutputDto::class, + provider: DummyDtoNoInputsProvider::class )] #[ORM\Entity] class DummyDtoNoInput diff --git a/tests/Fixtures/TestBundle/Entity/DummyValidation.php b/tests/Fixtures/TestBundle/Entity/DummyValidation.php index 45e192a7247..d61771ef8c6 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyValidation.php +++ b/tests/Fixtures/TestBundle/Entity/DummyValidation.php @@ -14,16 +14,18 @@ namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Delete; -use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; -use ApiPlatform\Metadata\Put; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; -#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(), new Post(uriTemplate: 'dummy_validation.{_format}'), new GetCollection(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]), new GetCollection(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator'])])] +#[ApiResource(operations: [ + new GetCollection(), + new Post(uriTemplate: 'dummy_validation.{_format}'), + new Post(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]), + new Post(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator']), +] +)] #[ORM\Entity] class DummyValidation { diff --git a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php index b42c9236a82..01802333724 100644 --- a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php @@ -24,7 +24,7 @@ class RamseyUuidDummy { #[ORM\Id] #[ORM\Column(type: 'uuid', unique: true)] - private readonly \Ramsey\Uuid\UuidInterface $id; + private \Ramsey\Uuid\UuidInterface $id; #[ORM\Column(type: 'uuid', nullable: true)] private ?\Ramsey\Uuid\UuidInterface $other = null; diff --git a/tests/Fixtures/TestBundle/State/DummyDtoNoInputsProvider.php b/tests/Fixtures/TestBundle/State/DummyDtoNoInputsProvider.php new file mode 100644 index 00000000000..4cb15cb03ff --- /dev/null +++ b/tests/Fixtures/TestBundle/State/DummyDtoNoInputsProvider.php @@ -0,0 +1,58 @@ + + * + * 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\Tests\Fixtures\TestBundle\State; + +use ApiPlatform\Metadata\CollectionOperationInterface; +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProviderInterface; +use ApiPlatform\Tests\Fixtures\TestBundle\Document\DummyDtoNoInput as DummyDtoNoInputDocument; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\Document\OutputDto as OutputDtoDocument; +use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoNoInput; + +final class DummyDtoNoInputsProvider implements ProviderInterface +{ + public function __construct(private ProviderInterface $itemProvider, private ProviderInterface $collectionProvider) + { + } + + /** + * {@inheritDoc} + */ + public function provide(Operation $operation, array $uriVariables = [], array $context = []) + { + if ($operation instanceof CollectionOperationInterface) { + $object = $this->collectionProvider->provide($operation, $uriVariables, $context); + foreach ($object as &$v) { + $v = $this->toOutput($v); + } + + return $object; + } + + $object = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $this->toOutput($object); + } + + private function toOutput(DummyDtoNoInput|DummyDtoNoInputDocument $object): OutputDto|OutputDtoDocument + { + $output = $object instanceof DummyDtoNoInput ? new OutputDto() : new OutputDtoDocument(); + $output->id = $object->getId(); + $output->bat = (string) $object->lorem; + $output->baz = (float) $object->ipsum; + + return $output; + } +} From 1783c22f2ee8da2290dd5682719196ffc92cf19b Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 23 Jun 2022 20:14:45 +0200 Subject: [PATCH 47/56] REVIEW THIS ! --- src/GraphQl/Serializer/ItemNormalizer.php | 8 +- src/Hal/Serializer/ItemNormalizer.php | 6 +- src/Hydra/Serializer/CollectionNormalizer.php | 2 +- src/JsonApi/Serializer/ItemNormalizer.php | 8 +- src/JsonLd/Serializer/ItemNormalizer.php | 57 ++++-- src/JsonLd/Serializer/JsonLdContextTrait.php | 4 +- src/JsonLd/Serializer/ObjectNormalizer.php | 2 +- src/Serializer/AbstractItemNormalizer.php | 179 ++++++++++-------- src/Serializer/InputOutputMetadataTrait.php | 24 +-- 9 files changed, 150 insertions(+), 140 deletions(-) diff --git a/src/GraphQl/Serializer/ItemNormalizer.php b/src/GraphQl/Serializer/ItemNormalizer.php index 5bf8a4b167a..2e488b9e66f 100644 --- a/src/GraphQl/Serializer/ItemNormalizer.php +++ b/src/GraphQl/Serializer/ItemNormalizer.php @@ -58,9 +58,9 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName /** * {@inheritdoc} */ - public function supportsNormalization($data, $format = null): bool + public function supportsNormalization($data, $format = null, array $context = []): bool { - return self::FORMAT === $format && parent::supportsNormalization($data, $format); + return self::FORMAT === $format && parent::supportsNormalization($data, $format, $context); } /** @@ -105,9 +105,9 @@ protected function normalizeCollectionOfRelations(ApiProperty $propertyMetadata, /** * {@inheritdoc} */ - public function supportsDenormalization($data, $type, $format = null): bool + public function supportsDenormalization($data, string $type, $format = null, array $context = []): bool { - return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format); + return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format, $context); } /** diff --git a/src/Hal/Serializer/ItemNormalizer.php b/src/Hal/Serializer/ItemNormalizer.php index 444dbe26e54..55b7899f8b5 100644 --- a/src/Hal/Serializer/ItemNormalizer.php +++ b/src/Hal/Serializer/ItemNormalizer.php @@ -41,9 +41,9 @@ final class ItemNormalizer extends AbstractItemNormalizer /** * {@inheritdoc} */ - public function supportsNormalization($data, $format = null): bool + public function supportsNormalization($data, $format = null, array $context = []): bool { - return self::FORMAT === $format && parent::supportsNormalization($data, $format); + return self::FORMAT === $format && parent::supportsNormalization($data, $format, $context); } /** @@ -89,7 +89,7 @@ public function normalize($object, $format = null, array $context = []) /** * {@inheritdoc} */ - public function supportsDenormalization($data, $type, $format = null): bool + public function supportsDenormalization($data, string $type, $format = null, array $context = []): bool { // prevent the use of lower priority normalizers (e.g. serializer.normalizer.object) for this format return self::FORMAT === $format; diff --git a/src/Hydra/Serializer/CollectionNormalizer.php b/src/Hydra/Serializer/CollectionNormalizer.php index fa13ab4d532..7738aa886da 100644 --- a/src/Hydra/Serializer/CollectionNormalizer.php +++ b/src/Hydra/Serializer/CollectionNormalizer.php @@ -59,7 +59,7 @@ public function __construct(ContextBuilderInterface $contextBuilder, ResourceCla /** * {@inheritdoc} */ - public function supportsNormalization($data, $format = null): bool + public function supportsNormalization($data, $format = null, array $context = []): bool { return self::FORMAT === $format && is_iterable($data); } diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index 028b79b5023..22b3b581c5d 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -60,9 +60,9 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName /** * {@inheritdoc} */ - public function supportsNormalization($data, $format = null): bool + public function supportsNormalization($data, $format = null, array $context = []): bool { - return self::FORMAT === $format && parent::supportsNormalization($data, $format); + return self::FORMAT === $format && parent::supportsNormalization($data, $format, $context); } /** @@ -126,9 +126,9 @@ public function normalize($object, $format = null, array $context = []) /** * {@inheritdoc} */ - public function supportsDenormalization($data, $type, $format = null): bool + public function supportsDenormalization($data, string $type, $format = null, array $context = []): bool { - return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format); + return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format, $context); } /** diff --git a/src/JsonLd/Serializer/ItemNormalizer.php b/src/JsonLd/Serializer/ItemNormalizer.php index a46a48b1d60..98d27036995 100644 --- a/src/JsonLd/Serializer/ItemNormalizer.php +++ b/src/JsonLd/Serializer/ItemNormalizer.php @@ -16,6 +16,7 @@ use ApiPlatform\Api\IriConverterInterface; use ApiPlatform\Api\ResourceClassResolverInterface; use ApiPlatform\Api\UrlGeneratorInterface; +use ApiPlatform\JsonLd\AnonymousContextBuilderInterface; use ApiPlatform\JsonLd\ContextBuilderInterface; use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; @@ -46,9 +47,9 @@ final class ItemNormalizer extends AbstractItemNormalizer private $contextBuilder; - public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ContextBuilderInterface $contextBuilder, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) + public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, ContextBuilderInterface $contextBuilder, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceAccessCheckerInterface $resourceAccessChecker = null) { - parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $defaultContext, $resourceMetadataFactory, $resourceAccessChecker); + parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $defaultContext, $resourceMetadataCollectionFactory, $resourceAccessChecker); $this->contextBuilder = $contextBuilder; } @@ -56,9 +57,9 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource /** * {@inheritdoc} */ - public function supportsNormalization($data, $format = null): bool + public function supportsNormalization($data, $format = null, array $context = []): bool { - return self::FORMAT === $format && parent::supportsNormalization($data, $format); + return self::FORMAT === $format && parent::supportsNormalization($data, $format, $context); } /** @@ -70,21 +71,34 @@ public function supportsNormalization($data, $format = null): bool */ public function normalize($object, $format = null, array $context = []) { - $objectClass = $this->getObjectClass($object); + $resourceClass = $this->getObjectClass($object); + $outputClass = $this->getOutputClass($resourceClass, $context); + if (null !== $outputClass) { + return parent::normalize($object, $format, $context); + } - $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); + // TODO: we should not remove the resource_class in the normalizeRawCollection as we would find out anyway that it's not the same as the requested one + $previousResourceClass = $context['resource_class'] ?? null; - if (isset($context['operation']) && $resourceClass !== $context['operation']->getClass()) { - unset($context['operation']); + if ($isResourceClass = $this->resourceClassResolver->isResourceClass($resourceClass)) { + $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); + $context = $this->initContext($resourceClass, $context); + $metadata = $this->addJsonLdContext($this->contextBuilder, $resourceClass, $context); + } elseif ($this->contextBuilder instanceof AnonymousContextBuilderInterface) { + // We should improve what's behind the context creation, its probably more complicated then it should + $metadata = $this->createJsonLdContext($this->contextBuilder, $object, $context); } - $operation = $context['operation'] = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); - $context = $this->initContext($resourceClass, $context); - $metadata = $this->addJsonLdContext($this->contextBuilder, $resourceClass, $context); + // maybe not needed anymore + if (isset($context['operation']) && $previousResourceClass !== $resourceClass) { + unset($context['operation'], $context['operation_name']); + } + + if ($iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context)) { + $context['iri'] = $iri; + $metadata['@id'] = $iri; + } - $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_PATH, $context['operation'] ?? null, $context); - $context['iri'] = $iri; - $metadata['@id'] = $iri; $context['api_normalize'] = true; $data = parent::normalize($object, $format, $context); @@ -92,11 +106,14 @@ public function normalize($object, $format = null, array $context = []) return $data; } - $types = $operation instanceof HttpOperation ? $operation->getTypes() : null; - if (null === $types) { - $types = [$operation->getShortName()]; + if (!isset($metadata['@type']) && $isResourceClass) { + $operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); + $types = $operation instanceof HttpOperation ? $operation->getTypes() : null; + if (null === $types) { + $types = [$operation->getShortName()]; + } + $metadata['@type'] = 1 === \count($types) ? $types[0] : $types; } - $metadata['@type'] = 1 === \count($types) ? $types[0] : $types; return $metadata + $data; } @@ -104,9 +121,9 @@ public function normalize($object, $format = null, array $context = []) /** * {@inheritdoc} */ - public function supportsDenormalization($data, $type, $format = null): bool + public function supportsDenormalization($data, string $type, $format = null, array $context = []): bool { - return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format); + return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format, $context); } /** diff --git a/src/JsonLd/Serializer/JsonLdContextTrait.php b/src/JsonLd/Serializer/JsonLdContextTrait.php index fcbe98206c2..d8603e03d6e 100644 --- a/src/JsonLd/Serializer/JsonLdContextTrait.php +++ b/src/JsonLd/Serializer/JsonLdContextTrait.php @@ -51,11 +51,11 @@ private function createJsonLdContext(AnonymousContextBuilderInterface $contextBu { // We're in a collection, don't add the @context part if (isset($context['jsonld_has_context'])) { - return $contextBuilder->getAnonymousResourceContext($object, ($context['output'] ?? []) + ['api_resource' => $context['api_resource'] ?? null, 'has_context' => true]); + return $contextBuilder->getAnonymousResourceContext($object, ['api_resource' => $context['api_resource'] ?? null, 'has_context' => true]); } $context['jsonld_has_context'] = true; - return $contextBuilder->getAnonymousResourceContext($object, ($context['output'] ?? []) + ['api_resource' => $context['api_resource'] ?? null]); + return $contextBuilder->getAnonymousResourceContext($object, ['api_resource' => $context['api_resource'] ?? null]); } } diff --git a/src/JsonLd/Serializer/ObjectNormalizer.php b/src/JsonLd/Serializer/ObjectNormalizer.php index 303c36230ad..c3e0df18d28 100644 --- a/src/JsonLd/Serializer/ObjectNormalizer.php +++ b/src/JsonLd/Serializer/ObjectNormalizer.php @@ -80,7 +80,7 @@ public function normalize($object, $format = null, array $context = []) */ $context['api_empty_resource_as_iri'] = true; - $data = $this->decorated->normalize($object, $format, $context + ['api_sub_level' => true]); + $data = $this->decorated->normalize($object, $format, $context); if (!\is_array($data) || !$data) { return $data; } diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index a510c00e2e5..1fd0b5e3729 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -19,8 +19,6 @@ use ApiPlatform\Exception\InvalidArgumentException; use ApiPlatform\Exception\InvalidValueException; use ApiPlatform\Exception\ItemNotFoundException; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; @@ -39,9 +37,9 @@ use Symfony\Component\Serializer\Exception\RuntimeException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; +use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -50,18 +48,20 @@ * * @author Kévin Dunglas */ -abstract class AbstractItemNormalizer extends AbstractObjectNormalizer +abstract class AbstractItemNormalizer extends AbstractObjectNormalizer implements ContextAwareDenormalizerInterface { use ClassInfoTrait; use ContextTrait; use InputOutputMetadataTrait; - protected $propertyNameCollectionFactory; - protected $propertyMetadataFactory; - protected $iriConverter; - protected $resourceClassResolver; - protected $resourceAccessChecker; - protected $propertyAccessor; + public const IS_TRANSFORMED_TO_SAME_CLASS = 'is_transformed_to_same_class'; + + protected PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory; + protected PropertyMetadataFactoryInterface $propertyMetadataFactory; + protected IriConverterInterface $iriConverter; + protected ResourceClassResolverInterface $resourceClassResolver; + protected ResourceAccessCheckerInterface $resourceAccessChecker; + protected PropertyAccessorInterface $propertyAccessor; protected $localCache = []; public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, ResourceClassResolverInterface $resourceClassResolver, PropertyAccessorInterface $propertyAccessor = null, NameConverterInterface $nameConverter = null, ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ResourceAccessCheckerInterface $resourceAccessChecker = null) @@ -71,9 +71,6 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName return $this->iriConverter->getIriFromResource($object); }; } - if (!interface_exists(AdvancedNameConverterInterface::class) && method_exists($this, 'setCircularReferenceHandler')) { - $this->setCircularReferenceHandler($defaultContext['circular_reference_handler']); - } parent::__construct($classMetadataFactory, $nameConverter, null, null, \Closure::fromCallable([$this, 'getObjectClass']), $defaultContext); @@ -88,15 +85,17 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName /** * {@inheritdoc} - * - * @return bool */ - public function supportsNormalization($data, $format = null) + public function supportsNormalization($data, $format = null, array $context = []): bool { if (!\is_object($data) || is_iterable($data)) { return false; } + if (($context['output']['class'] ?? null) === $this->getObjectClass($data)) { + return true; + } + return $this->resourceClassResolver->isResourceClass($this->getObjectClass($data)); } @@ -117,17 +116,29 @@ public function hasCacheableSupportsMethod(): bool */ public function normalize($object, $format = null, array $context = []) { - $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); - $context = $this->initContext($resourceClass, $context); + $class = $this->getObjectClass($object); + if ($outputClass = $this->getOutputClass($class, $context)) { + if (!$this->serializer instanceof DenormalizerInterface) { + throw new LogicException('Cannot normalize the output because the injected serializer is not a normalizer'); + } - if (isset($context['iri'])) { - $iri = $context['iri']; - } else { - $iri = $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_URL, $context['operation'] ?? null, $context); + unset($context['output']); + unset($context['operation']); + unset($context['operation_name']); + $context['resource_class'] = $outputClass; + $context['api_sub_level'] = true; + $context[self::ALLOW_EXTRA_ATTRIBUTES] = false; + + return $this->serializer->normalize($object, $format, $context); + } + + if ($this->resourceClassResolver->isResourceClass($class)) { + $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); + $context = $this->initContext($resourceClass, $context); } - $context['iri'] = $iri; $context['api_normalize'] = true; + $iri = $context['iri'] = $context['iri'] ?? $this->iriConverter->getIriFromResource($object, UrlGeneratorInterface::ABS_URL, $context['operation'] ?? null, $context); /* * When true, converts the normalized data array of a resource into an @@ -156,11 +167,13 @@ public function normalize($object, $format = null, array $context = []) /** * {@inheritdoc} - * - * @return bool */ - public function supportsDenormalization($data, $type, $format = null) + public function supportsDenormalization($data, string $type, $format = null, array $context = []): bool { + if (($context['input']['class'] ?? null) === $type) { + return true; + } + return $this->localCache[$type] ?? $this->localCache[$type] = $this->resourceClassResolver->isResourceClass($type); } @@ -171,24 +184,44 @@ public function supportsDenormalization($data, $type, $format = null) */ public function denormalize($data, $class, $format = null, array $context = []) { - if (null === $objectToPopulate = $this->extractObjectToPopulate($class, $context, static::OBJECT_TO_POPULATE)) { + $resourceClass = $class; + + if ($inputClass = $this->getInputClass($class, $context)) { + if (!$this->serializer instanceof DenormalizerInterface) { + throw new LogicException('Cannot normalize the output because the injected serializer is not a normalizer'); + } + + // $class = $inputClass; + unset($context['input']); + unset($context['operation']); + unset($context['operation_name']); + $context['resource_class'] = $inputClass; + + try { + return $this->serializer->denormalize($data, $inputClass, $format, $context); + } catch (NotNormalizableValueException $e) { + throw new UnexpectedValueException('The input data is misformatted.', $e->getCode(), $e); + } + } + + if (null === $objectToPopulate = $this->extractObjectToPopulate($resourceClass, $context, static::OBJECT_TO_POPULATE)) { $normalizedData = \is_scalar($data) ? [$data] : $this->prepareForDenormalization($data); $class = $this->getClassDiscriminatorResolvedClass($normalizedData, $class); } - $resourceClass = $this->resourceClassResolver->getResourceClass($objectToPopulate, $class); $context['api_denormalize'] = true; - $context['resource_class'] = $resourceClass; - if ( - ($inputClass = $this->getInputClass($resourceClass, $context)) - && - ($context['operation'] ?? $context['operation_type'] ?? false) // Are we in a Request context? - ) { - $resourceClass = $inputClass; - $context['resource_class'] = $inputClass; + if ($this->resourceClassResolver->isResourceClass($class)) { + $resourceClass = $this->resourceClassResolver->getResourceClass($objectToPopulate, $class); + $context['resource_class'] = $resourceClass; } + // Are we in a Request context? + // if ($context['operation'] ?? $context['operation_type'] ?? false) { + // $resourceClass = $inputClass; + // $context['resource_class'] = $inputClass; + // } + if (\is_string($data)) { try { return $this->iriConverter->getResourceFromIri($data, $context + ['fetch_data' => true]); @@ -199,18 +232,17 @@ public function denormalize($data, $class, $format = null, array $context = []) } } - $previousObject = null !== $objectToPopulate ? clone $objectToPopulate : null; - - try { - $object = parent::denormalize($data, $resourceClass, $format, $context); - } catch (NotNormalizableValueException $e) { - throw new UnexpectedValueException('The input data is misformatted.', $e->getCode(), $e); + if (!\is_array($data)) { + throw new UnexpectedValueException(sprintf('Expected IRI or document for resource "%s", "%s" given.', $resourceClass, \gettype($data))); } - if (!$this->resourceClassResolver->isResourceClass($context['resource_class'])) { + $object = parent::denormalize($data, $class, $format, $context); + + if (!$this->resourceClassResolver->isResourceClass($class)) { return $object; } + $previousObject = isset($objectToPopulate) ? clone $objectToPopulate : null; // Revert attributes that aren't allowed to be changed after a post-denormalize check foreach (array_keys($data) as $attribute) { if (!$this->canAccessAttributePostDenormalize($object, $previousObject, $attribute, $context)) { @@ -386,9 +418,9 @@ protected function canAccessAttribute($object, string $attribute, array $context } $options = $this->getFactoryOptions($context); - /** @var ApiProperty */ + /** @var PropertyMetadata|ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $options); - $security = $propertyMetadata->getSecurity(); + $security = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('security') : $propertyMetadata->getSecurity(); if ($this->resourceAccessChecker && $security) { return $this->resourceAccessChecker->isGranted($context['resource_class'], $security, [ 'object' => $object, @@ -407,9 +439,9 @@ protected function canAccessAttribute($object, string $attribute, array $context protected function canAccessAttributePostDenormalize($object, $previousObject, string $attribute, array $context = []): bool { $options = $this->getFactoryOptions($context); - /** @var ApiProperty */ + /** @var PropertyMetadata|ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $options); - $security = $propertyMetadata->getSecurityPostDenormalize(); + $security = $propertyMetadata instanceof PropertyMetadata ? $propertyMetadata->getAttribute('security_post_denormalize') : $propertyMetadata->getSecurityPostDenormalize(); if ($this->resourceAccessChecker && $security) { return $this->resourceAccessChecker->isGranted($context['resource_class'], $security, [ 'object' => $object, @@ -452,11 +484,12 @@ protected function validateType(string $attribute, Type $type, $value, string $f /** * Denormalizes a collection of objects. * - * @param mixed $value + * @param ApiProperty|PropertyMetadata $propertyMetadata + * @param mixed $value * * @throws InvalidArgumentException */ - protected function denormalizeCollection(string $attribute, ApiProperty $propertyMetadata, Type $type, string $className, $value, ?string $format, array $context): array + protected function denormalizeCollection(string $attribute, $propertyMetadata, Type $type, string $className, $value, ?string $format, array $context): array { if (!\is_array($value)) { throw new InvalidArgumentException(sprintf('The type of the "%s" attribute must be "array", "%s" given.', $attribute, \gettype($value))); @@ -538,17 +571,11 @@ protected function getFactoryOptions(array $context): array $options['serializer_groups'] = (array) $context[self::GROUPS]; } - if (null !== $this->resourceMetadataCollectionFactory) { - try { - $operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($context['resource_class'])->getOperation($context['operation_name'] ?? null); - $options['normalization_groups'] = $operation->getNormalizationContext()['groups'] ?? null; - $options['denormalization_groups'] = $operation->getDenormalizationContext()['groups'] ?? null; - } catch (OperationNotFoundException|ResourceClassNotFoundException) { - } - } - - if (isset($context['operation_name'])) { - $options['operation_name'] = $context['operation_name']; + if ($this->resourceClassResolver->isResourceClass($context['resource_class'])) { + $operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($context['resource_class'])->getOperation($context['operation_name'] ?? null); + $options['normalization_groups'] = $operation->getNormalizationContext()['groups'] ?? null; + $options['denormalization_groups'] = $operation->getDenormalizationContext()['groups'] ?? null; + $options['operation_name'] = $operation->getName(); } return $options; @@ -565,7 +592,6 @@ protected function getFactoryOptions(array $context): array protected function getAttributeValue($object, $attribute, $format = null, array $context = []) { $context['api_attribute'] = $attribute; - /** @var ApiProperty */ $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context)); try { @@ -594,12 +620,9 @@ protected function getAttributeValue($object, $attribute, $format = null, array $resourceClass = $this->resourceClassResolver->getResourceClass($attributeValue, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; - if (null !== $this->resourceMetadataCollectionFactory) { - try { - $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); - } catch (OperationNotFoundException|ResourceClassNotFoundException) { - } - } + // if ($this->resourceMetadataCollectionFactory instanceof ResourceMetadataCollectionFactoryInterface) { + $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); + // } unset($childContext['iri'], $childContext['uri_variables']); return $this->normalizeCollectionOfRelations($propertyMetadata, $attributeValue, $resourceClass, $format, $childContext); @@ -617,12 +640,9 @@ protected function getAttributeValue($object, $attribute, $format = null, array $resourceClass = $this->resourceClassResolver->getResourceClass($attributeValue, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; - if (null !== $this->resourceMetadataCollectionFactory) { - try { - $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); - } catch (OperationNotFoundException|ResourceClassNotFoundException) { - } - } + // if ($this->resourceMetadataCollectionFactory instanceof ResourceMetadataCollectionFactoryInterface) { + $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); + // } unset($childContext['iri'], $childContext['uri_variables']); return $this->normalizeRelation($propertyMetadata, $attributeValue, $resourceClass, $format, $childContext); @@ -707,10 +727,6 @@ protected function normalizeRelation(ApiProperty $propertyMetadata, ?object $rel private function createAttributeValue($attribute, $value, $format = null, array $context = []) { - if (!$this->resourceClassResolver->isResourceClass($context['resource_class'])) { - return $value; - } - $propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context)); $type = $propertyMetadata->getBuiltinTypes()[0] ?? null; @@ -751,12 +767,9 @@ private function createAttributeValue($attribute, $value, $format = null, array $resourceClass = $this->resourceClassResolver->getResourceClass(null, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; - if (null !== $this->resourceMetadataCollectionFactory) { - try { - $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); - } catch (OperationNotFoundException|ResourceClassNotFoundException) { - } - } + // if ($this->resourceMetadataCollectionFactory instanceof ResourceMetadataCollectionFactoryInterface) { + $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); + // } return $this->denormalizeRelation($attribute, $propertyMetadata, $resourceClass, $value, $format, $childContext); } diff --git a/src/Serializer/InputOutputMetadataTrait.php b/src/Serializer/InputOutputMetadataTrait.php index 1f4b45787cf..c17c0e32015 100644 --- a/src/Serializer/InputOutputMetadataTrait.php +++ b/src/Serializer/InputOutputMetadataTrait.php @@ -13,8 +13,6 @@ namespace ApiPlatform\Serializer; -use ApiPlatform\Exception\OperationNotFoundException; -use ApiPlatform\Exception\ResourceClassNotFoundException; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; trait InputOutputMetadataTrait @@ -34,16 +32,7 @@ protected function getInputClass(string $class, array $context = []): ?string return $context['input']['class']; } - $operation = $context['operation'] ?? null; - if (!$operation) { - try { - $operation = $this->resourceMetadataCollectionFactory->create($class)->getOperation($context['operation_name'] ?? null); - } catch (OperationNotFoundException|ResourceClassNotFoundException $e) { - return null; - } - } - - return $operation ? $operation->getInput()['class'] ?? null : null; + return null; } protected function getOutputClass(string $class, array $context = []): ?string @@ -56,15 +45,6 @@ protected function getOutputClass(string $class, array $context = []): ?string return $context['output']['class']; } - $operation = $context['operation'] ?? null; - if (null === $operation) { - try { - $operation = $this->resourceMetadataCollectionFactory->create($class)->getOperation($context['operation_name'] ?? null); - } catch (OperationNotFoundException|ResourceClassNotFoundException $e) { - return null; - } - } - - return $operation ? $operation->getOutput()['class'] ?? null : null; + return null; } } From cf8b8db7b8c389968f5a00c721cff78944b9de38 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 23 Jun 2022 20:16:48 +0200 Subject: [PATCH 48/56] fix openapi tests --- features/openapi/docs.feature | 97 ------------------- src/OpenApi/Factory/OpenApiFactory.php | 7 +- .../ApiPlatformExtension.php | 5 +- .../EventListener/SwaggerUiListener.php | 2 +- .../Resources/views/SwaggerUi/index.html.twig | 3 +- .../Bundle/SwaggerUi/SwaggerUiAction.php | 5 +- .../EventListener/SwaggerUiListenerTest.php | 4 +- 7 files changed, 11 insertions(+), 112 deletions(-) diff --git a/features/openapi/docs.feature b/features/openapi/docs.feature index 624e18632d7..2d80d34dfa4 100644 --- a/features/openapi/docs.feature +++ b/features/openapi/docs.feature @@ -219,103 +219,6 @@ Feature: Documentation support } """ - @createSchema - Scenario: Retrieve the Swagger documentation - Given I send a "GET" request to "/docs.json?spec_version=2" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/json; charset=utf-8" - # Context - And the JSON node "swagger" should be equal to "2.0" - # Root properties - And the JSON node "info.title" should be equal to "My Dummy API" - And the JSON node "info.description" should contain "This is a test API." - And the JSON node "info.description" should contain "Made with love" - # Supported classes - And the Swagger class "AbstractDummy" exists - And the Swagger class "CircularReference" exists - And the Swagger class "CircularReference-circular" exists - And the Swagger class "CompositeItem" exists - And the Swagger class "CompositeLabel" exists - And the Swagger class "ConcreteDummy" exists - And the Swagger class "CustomIdentifierDummy" exists - And the Swagger class "CustomNormalizedDummy-input" exists - And the Swagger class "CustomNormalizedDummy-output" exists - And the Swagger class "CustomWritableIdentifierDummy" exists - And the Swagger class "Dummy" exists - And the Swagger class "DummyBoolean" exists - And the Swagger class "RelatedDummy" exists - And the Swagger class "DummyTableInheritance" exists - And the Swagger class "DummyTableInheritanceChild" exists - And the Swagger class "OverriddenOperationDummy-overridden_operation_dummy_get" exists - And the Swagger class "OverriddenOperationDummy-overridden_operation_dummy_put" exists - And the Swagger class "OverriddenOperationDummy-overridden_operation_dummy_read" exists - And the Swagger class "OverriddenOperationDummy-overridden_operation_dummy_write" exists - And the Swagger class "RelatedDummy" exists - And the Swagger class "NoCollectionDummy" exists - And the Swagger class "RelatedToDummyFriend" exists - And the Swagger class "RelatedToDummyFriend-fakemanytomany" exists - And the Swagger class "DummyFriend" exists - And the Swagger class "RelationEmbedder-barcelona" exists - And the Swagger class "RelationEmbedder-chicago" exists - And the Swagger class "User-user_user-read" exists - And the Swagger class "User-user_user-write" exists - And the Swagger class "UuidIdentifierDummy" exists - And the Swagger class "ThirdLevel" exists - And the Swagger class "ParentDummy" doesn't exist - And the Swagger class "UnknownDummy" doesn't exist - And the Swagger path "/relation_embedders/{id}/custom" exists - And the Swagger path "/override/swagger" exists - And the Swagger path "/api/custom-call/{id}" exists - And the JSON node "paths./api/custom-call/{id}.get" should exist - And the JSON node "paths./api/custom-call/{id}.put" should exist - # Properties - And the "id" property exists for the Swagger class "Dummy" - And the "name" property is required for the Swagger class "Dummy" - # Enable these tests when SF 4.4 / PHP 7.1 support is dropped - #And the "isDummyBoolean" property exists for the Swagger class "DummyBoolean" - #And the "isDummyBoolean" property is not read only for the Swagger class "DummyBoolean" - # Filters - And the JSON node "paths./dummies.get.parameters[0].name" should be equal to "dummyBoolean" - And the JSON node "paths./dummies.get.parameters[0].in" should be equal to "query" - And the JSON node "paths./dummies.get.parameters[0].required" should be false - - # Subcollection - check filter on subResource - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[0].name" should be equal to "id" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[0].in" should be equal to "path" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[0].required" should be true - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[1].name" should be equal to "name" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[1].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[1].required" should be false - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[2].name" should be equal to "description" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[2].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[2].required" should be false - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[3].name" should be equal to "page" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[3].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[3].required" should be false - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[4].name" should be equal to "itemsPerPage" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[4].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[4].required" should be false - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[5].name" should be equal to "pagination" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[5].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[5].required" should be false - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters" should have 6 elements - - # Deprecations - And the JSON node "paths./dummies.get.deprecated" should not exist - And the JSON node "paths./deprecated_resources.get.deprecated" should be true - And the JSON node "paths./deprecated_resources.post.deprecated" should be true - And the JSON node "paths./deprecated_resources/{id}.get.deprecated" should be true - And the JSON node "paths./deprecated_resources/{id}.delete.deprecated" should be true - And the JSON node "paths./deprecated_resources/{id}.put.deprecated" should be true - And the JSON node "paths./deprecated_resources/{id}.patch.deprecated" should be true - Scenario: OpenAPI UI is enabled for docs endpoint Given I add "Accept" header equal to "text/html" And I send a "GET" request to "/docs?spec_version=3" diff --git a/src/OpenApi/Factory/OpenApiFactory.php b/src/OpenApi/Factory/OpenApiFactory.php index 3d41b3acde8..11432a45c95 100644 --- a/src/OpenApi/Factory/OpenApiFactory.php +++ b/src/OpenApi/Factory/OpenApiFactory.php @@ -30,6 +30,7 @@ use ApiPlatform\OpenApi\Model\ExternalDocumentation; use ApiPlatform\OpenApi\OpenApi; use ApiPlatform\OpenApi\Options; +use ApiPlatform\OpenApi\Serializer\NormalizeOperationNameTrait; use ApiPlatform\State\Pagination\PaginationOptions; use Psr\Container\ContainerInterface; use Symfony\Component\PropertyInfo\Type; @@ -41,6 +42,7 @@ final class OpenApiFactory implements OpenApiFactoryInterface { use FilterLocatorTrait; + use NormalizeOperationNameTrait; public const BASE_URL = 'base_url'; public const OPENAPI_DEFINITION_NAME = 'openapi_definition_name'; @@ -555,9 +557,4 @@ private function hasParameter(Model\Parameter $parameter, array $parameters): bo return false; } - - private function normalizeOperationName(string $operationName): string - { - return preg_replace('/^_/', '', str_replace(['/', '.{_format}', '{', '}'], ['', '', '_', ''], $operationName)); - } } diff --git a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php index 4295ace6ca1..31787b5ebce 100644 --- a/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php +++ b/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php @@ -34,9 +34,9 @@ use ApiPlatform\State\ProviderInterface; use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface; use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; use phpDocumentor\Reflection\DocBlockFactoryInterface; use Ramsey\Uuid\Uuid; +use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -360,9 +360,6 @@ private function registerOAuthConfiguration(ContainerBuilder $container, array $ $container->setParameter('api_platform.oauth.scopes', $config['oauth']['scopes']); $container->setParameter('api_platform.oauth.pkce', $config['oauth']['pkce']); - if ($container->hasDefinition('api_platform.swagger.action.ui')) { - $container->getDefinition('api_platform.swagger.action.ui')->setArgument(27, $config['oauth']['pkce']); - } if ($container->hasDefinition('api_platform.swagger_ui.action')) { $container->getDefinition('api_platform.swagger_ui.action')->setArgument(10, $config['oauth']['pkce']); } diff --git a/src/Symfony/Bundle/EventListener/SwaggerUiListener.php b/src/Symfony/Bundle/EventListener/SwaggerUiListener.php index 65d58468fb9..a7c9cf85b37 100644 --- a/src/Symfony/Bundle/EventListener/SwaggerUiListener.php +++ b/src/Symfony/Bundle/EventListener/SwaggerUiListener.php @@ -30,6 +30,6 @@ public function onKernelRequest(RequestEvent $event): void return; } - $request->attributes->set('_controller', 'api_platform.swagger.action.ui'); + $request->attributes->set('_controller', 'api_platform.swagger_ui.action'); } } diff --git a/src/Symfony/Bundle/Resources/views/SwaggerUi/index.html.twig b/src/Symfony/Bundle/Resources/views/SwaggerUi/index.html.twig index c846f64526e..a27ec7dba40 100644 --- a/src/Symfony/Bundle/Resources/views/SwaggerUi/index.html.twig +++ b/src/Symfony/Bundle/Resources/views/SwaggerUi/index.html.twig @@ -73,8 +73,7 @@ {% set active_ui = app.request.get('ui', 'swagger_ui') %} {% if swaggerUiEnabled and active_ui != 'swagger_ui' %}Swagger UI{% endif %} {% if reDocEnabled and active_ui != 're_doc' %}ReDoc{% endif %} - {# FIXME: Typo in graphql => graphQl in SwaggerUiAction #} - {% if not graphqlEnabled %}GraphiQL{% endif %} + {% if not graphQlEnabled %}GraphiQL{% endif %} {% if graphiQlEnabled %}GraphiQL{% endif %} {% if graphQlPlaygroundEnabled %}GraphQL Playground{% endif %} diff --git a/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php b/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php index 4bd2c3d2cf9..b3e4d30780b 100644 --- a/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php +++ b/src/Symfony/Bundle/SwaggerUi/SwaggerUiAction.php @@ -17,6 +17,7 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; use ApiPlatform\OpenApi\Options; +use ApiPlatform\OpenApi\Serializer\NormalizeOperationNameTrait; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; @@ -30,6 +31,8 @@ */ final class SwaggerUiAction { + use NormalizeOperationNameTrait; + private $twig; private $urlGenerator; private $normalizer; @@ -102,7 +105,7 @@ public function __invoke(Request $request) $metadata = $this->resourceMetadataFactory->create($resourceClass)->getOperation($request->attributes->get('_api_operation_name')); $swaggerData['shortName'] = $metadata->getShortName(); - $swaggerData['operationId'] = $metadata->getName(); + $swaggerData['operationId'] = $this->normalizeOperationName($metadata->getName()); [$swaggerData['path'], $swaggerData['method']] = $this->getPathAndMethod($swaggerData); } diff --git a/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php b/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php index 8ab04043adb..c15f7234c17 100644 --- a/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php +++ b/tests/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php @@ -52,8 +52,8 @@ public function getParameters() $jsonRequest->setRequestFormat('json'); return [ - [$respondRequest, 'api_platform.swagger.action.ui'], - [$resourceClassRequest, 'api_platform.swagger.action.ui'], + [$respondRequest, 'api_platform.swagger_ui.action'], + [$resourceClassRequest, 'api_platform.swagger_ui.action'], [new Request(), null], [$jsonRequest, null], ]; From 3a07977a91ed01647bc6ca4958e31cc5804ec571 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 23 Jun 2022 20:17:04 +0200 Subject: [PATCH 49/56] config but review commented --- tests/Fixtures/app/config/config_common.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index b0313ae6fea..b83ec58b655 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -321,6 +321,13 @@ services: tags: - name: 'api_platform.state_provider' + ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoNoInputsProvider: + arguments: + $itemProvider: '@ApiPlatform\Doctrine\Orm\State\ItemProvider' + $collectionProvider: '@ApiPlatform\Doctrine\Orm\State\CollectionProvider' + tags: + - name: 'api_platform.state_provider' + ApiPlatform\Tests\Fixtures\TestBundle\State\RecoverPasswordProcessor: tags: - name: 'api_platform.state_processor' From 75855b2c2a09284a8eda0d79f6c40e3935e11605 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 23 Jun 2022 20:19:37 +0200 Subject: [PATCH 50/56] forgot name openapi --- .../NormalizeOperationNameTrait.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/OpenApi/Serializer/NormalizeOperationNameTrait.php diff --git a/src/OpenApi/Serializer/NormalizeOperationNameTrait.php b/src/OpenApi/Serializer/NormalizeOperationNameTrait.php new file mode 100644 index 00000000000..53bb0b22a10 --- /dev/null +++ b/src/OpenApi/Serializer/NormalizeOperationNameTrait.php @@ -0,0 +1,28 @@ + + * + * 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\OpenApi\Serializer; + +/** + * Transforms the operation name to a readable operation id. + * + * @author soyuka + */ +trait NormalizeOperationNameTrait +{ + private function normalizeOperationName(string $operationName): string + { + // .{_format} is related to the symfony router + return preg_replace('/^_/', '', str_replace(['/', '.{_format}', '{', '}'], ['', '', '_', ''], $operationName)); + } +} From 7b474d48714dbdb98c408748d6f8c270a893471f Mon Sep 17 00:00:00 2001 From: Saif Eddin Gmati <29315886+azjezz@users.noreply.github.com> Date: Sat, 25 Jun 2022 12:11:43 +0100 Subject: [PATCH 51/56] chore: remove deprecated mercure publisher compiler pass (#46) --- src/Symfony/Bundle/ApiPlatformBundle.php | 2 - .../DeprecateMercurePublisherPass.php | 41 -------------- .../Symfony/Bundle/ApiPlatformBundleTest.php | 2 - .../DeprecateMercurePublisherPassTest.php | 53 ------------------- 4 files changed, 98 deletions(-) delete mode 100644 src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php delete mode 100644 tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php diff --git a/src/Symfony/Bundle/ApiPlatformBundle.php b/src/Symfony/Bundle/ApiPlatformBundle.php index a87bb2f993a..de96d544946 100644 --- a/src/Symfony/Bundle/ApiPlatformBundle.php +++ b/src/Symfony/Bundle/ApiPlatformBundle.php @@ -16,7 +16,6 @@ use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AttributeFilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass; -use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass; @@ -50,7 +49,6 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new GraphQlTypePass()); $container->addCompilerPass(new GraphQlQueryResolverPass()); $container->addCompilerPass(new GraphQlMutationResolverPass()); - $container->addCompilerPass(new DeprecateMercurePublisherPass()); $container->addCompilerPass(new MetadataAwareNameConverterPass()); $container->addCompilerPass(new TestClientPass()); $container->addCompilerPass(new AuthenticatorManagerPass()); diff --git a/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php b/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php deleted file mode 100644 index afa28c12a42..00000000000 --- a/src/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPass.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * 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\Symfony\Bundle\DependencyInjection\Compiler; - -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Handles Mercure Publisher depreciation. - * - * @internal calls `setDeprecated` method with valid arguments - * depending which version of symfony/dependency-injection is used - */ -final class DeprecateMercurePublisherPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - $container - ->setAlias('api_platform.doctrine.listener.mercure.publish', 'api_platform.doctrine.orm.listener.mercure.publish') - ->setDeprecated(...$this->buildDeprecationArgs('2.6', 'Using "%alias_id%" service is deprecated since API Platform 2.6. Use "api_platform.doctrine.orm.listener.mercure.publish" instead.')); - } - - private function buildDeprecationArgs(string $version, string $message): array - { - return method_exists(BaseNode::class, 'getDeprecation') - ? ['api-platform/core', $version, $message] - : [$message]; - } -} diff --git a/tests/Symfony/Bundle/ApiPlatformBundleTest.php b/tests/Symfony/Bundle/ApiPlatformBundleTest.php index 14fcf41188f..57ba390da36 100644 --- a/tests/Symfony/Bundle/ApiPlatformBundleTest.php +++ b/tests/Symfony/Bundle/ApiPlatformBundleTest.php @@ -16,7 +16,6 @@ use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\AuthenticatorManagerPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DataProviderPass; -use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\ElasticsearchClientPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\FilterPass; use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\GraphQlMutationResolverPass; @@ -45,7 +44,6 @@ public function testBuild() $containerProphecy->addCompilerPass(Argument::type(GraphQlTypePass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(GraphQlQueryResolverPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(GraphQlMutationResolverPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); - $containerProphecy->addCompilerPass(Argument::type(DeprecateMercurePublisherPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(MetadataAwareNameConverterPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(TestClientPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); $containerProphecy->addCompilerPass(Argument::type(AuthenticatorManagerPass::class))->willReturn($containerProphecy->reveal())->shouldBeCalled(); diff --git a/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php b/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php deleted file mode 100644 index 91dee4d93d9..00000000000 --- a/tests/Symfony/Bundle/DependencyInjection/Compiler/DeprecateMercurePublisherPassTest.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * 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\Tests\Symfony\Bundle\DependencyInjection\Compiler; - -use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\DeprecateMercurePublisherPass; -use ApiPlatform\Tests\ProphecyTrait; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -final class DeprecateMercurePublisherPassTest extends TestCase -{ - use ProphecyTrait; - - public function testProcess() - { - $deprecateMercurePublisherPass = new DeprecateMercurePublisherPass(); - - $this->assertInstanceOf(CompilerPassInterface::class, $deprecateMercurePublisherPass); - - $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); - $aliasProphecy = $this->prophesize(Alias::class); - - $containerBuilderProphecy - ->setAlias('api_platform.doctrine.listener.mercure.publish', 'api_platform.doctrine.orm.listener.mercure.publish') - ->willReturn($aliasProphecy->reveal()) - ->shouldBeCalled(); - - $setDeprecatedArgs = method_exists(BaseNode::class, 'getDeprecation') - ? ['api-platform/core', '2.6', 'Using "%alias_id%" service is deprecated since API Platform 2.6. Use "api_platform.doctrine.orm.listener.mercure.publish" instead.'] - : ['Using "%alias_id%" service is deprecated since API Platform 2.6. Use "api_platform.doctrine.orm.listener.mercure.publish" instead.']; - - $aliasProphecy - ->setDeprecated(...$setDeprecatedArgs) - ->willReturn($aliasProphecy->reveal()) - ->shouldBeCalled(); - - $deprecateMercurePublisherPass->process($containerBuilderProphecy->reveal()); - } -} From a18ef04cc5c3d8b19ed0737cdfb9406c47689343 Mon Sep 17 00:00:00 2001 From: soyuka Date: Fri, 24 Jun 2022 12:56:58 +0200 Subject: [PATCH 52/56] fix(openapi): aws api gateway for openapi 3.0 --- features/openapi/docs.feature | 18 ++- features/swagger/docs.feature | 137 ------------------ .../Serializer/ApiGatewayNormalizer.php | 14 +- .../TestBundle/Entity/RamseyUuidDummy.php | 3 + 4 files changed, 24 insertions(+), 148 deletions(-) delete mode 100644 features/swagger/docs.feature diff --git a/features/openapi/docs.feature b/features/openapi/docs.feature index 2d80d34dfa4..3e9fda188bc 100644 --- a/features/openapi/docs.feature +++ b/features/openapi/docs.feature @@ -5,7 +5,7 @@ Feature: Documentation support @createSchema Scenario: Retrieve the OpenAPI documentation - Given I send a "GET" request to "/docs.json?spec_version=3" + Given I send a "GET" request to "/docs.json" Then the response status code should be 200 And the response should be in JSON And the header "Content-Type" should be equal to "application/json; charset=utf-8" @@ -221,13 +221,13 @@ Feature: Documentation support Scenario: OpenAPI UI is enabled for docs endpoint Given I add "Accept" header equal to "text/html" - And I send a "GET" request to "/docs?spec_version=3" + And I send a "GET" request to "/docs" Then the response status code should be 200 And I should see text matching "My Dummy API" And I should see text matching "openapi" Scenario: OpenAPI extension properties is enabled in JSON docs - Given I send a "GET" request to "/docs.json?spec_version=3" + Given I send a "GET" request to "/docs.json" Then the response status code should be 200 And the response should be in JSON And the header "Content-Type" should be equal to "application/json; charset=utf-8" @@ -235,6 +235,16 @@ Feature: Documentation support Scenario: OpenAPI UI is enabled for an arbitrary endpoint Given I add "Accept" header equal to "text/html" - And I send a "GET" request to "/dummies?spec_version=3" + And I send a "GET" request to "/dummies" Then the response status code should be 200 And I should see text matching "openapi" + + Scenario: Retrieve the OpenAPI documentation with API Gateway compatibility + Given I send a "GET" request to "/docs.json?api_gateway=true" + Then the response status code should be 200 + And the response should be in JSON + And the header "Content-Type" should be equal to "application/json; charset=utf-8" + And the JSON node "basePath" should be equal to "/" + And the JSON node "components.schemas.RamseyUuidDummy.properties.id.description" should be equal to "The dummy id." + And the JSON node "components.schemas.RelatedDummy-barcelona" should not exist + And the JSON node "components.schemas.RelatedDummybarcelona" should exist diff --git a/features/swagger/docs.feature b/features/swagger/docs.feature deleted file mode 100644 index 9b14c8353c6..00000000000 --- a/features/swagger/docs.feature +++ /dev/null @@ -1,137 +0,0 @@ -Feature: Documentation support - In order to build an auto-discoverable API - As a client software developer - I need to know Swagger specifications of objects I send and receive - - @createSchema - Scenario: Retrieve the Swagger/OpenAPI documentation - Given I send a "GET" request to "/docs.json" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/json; charset=utf-8" - # OverrideDocumentationNormalizer - And the JSON node "definitions.RamseyUuidDummy.properties.id.description" should be equal to "The dummy id" - And the JSON node "definitions.RelatedDummy-barcelona" should exist - And the JSON node "definitions.RelatedDummybarcelona" should not exist - # Context - And the JSON node "swagger" should be equal to "2.0" - # Root properties - And the JSON node "info.title" should be equal to "My Dummy API" - And the JSON node "info.description" should contain "This is a test API." - And the JSON node "info.description" should contain "Made with love" - # Supported classes - And the Swagger class "AbstractDummy" exists - And the Swagger class "CircularReference" exists - And the Swagger class "CircularReference-circular" exists - And the Swagger class "CompositeItem" exists - And the Swagger class "CompositeLabel" exists - And the Swagger class "ConcreteDummy" exists - And the Swagger class "CustomIdentifierDummy" exists - And the Swagger class "CustomNormalizedDummy-input" exists - And the Swagger class "CustomNormalizedDummy-output" exists - And the Swagger class "CustomWritableIdentifierDummy" exists - And the Swagger class "Dummy" exists - And the Swagger class "RelatedDummy" exists - And the Swagger class "DummyTableInheritance" exists - And the Swagger class "DummyTableInheritanceChild" exists - And the Swagger class "OverriddenOperationDummy-overridden_operation_dummy_get" exists - And the Swagger class "OverriddenOperationDummy-overridden_operation_dummy_put" exists - And the Swagger class "OverriddenOperationDummy-overridden_operation_dummy_read" exists - And the Swagger class "OverriddenOperationDummy-overridden_operation_dummy_write" exists - And the Swagger class "RelatedDummy" exists - And the Swagger class "NoCollectionDummy" exists - And the Swagger class "RelatedToDummyFriend" exists - And the Swagger class "RelatedToDummyFriend-fakemanytomany" exists - And the Swagger class "DummyFriend" exists - And the Swagger class "RelationEmbedder-barcelona" exists - And the Swagger class "RelationEmbedder-chicago" exists - And the Swagger class "User-user_user-read" exists - And the Swagger class "User-user_user-write" exists - And the Swagger class "UuidIdentifierDummy" exists - And the Swagger class "ThirdLevel" exists - And the Swagger class "ParentDummy" doesn't exist - And the Swagger class "UnknownDummy" doesn't exist - And the Swagger path "/relation_embedders/{id}/custom" exists - And the Swagger path "/override/swagger" exists - And the Swagger path "/api/custom-call/{id}" exists - And the JSON node "paths./api/custom-call/{id}.get" should exist - And the JSON node "paths./api/custom-call/{id}.put" should exist - # Properties - And the "id" property exists for the Swagger class "Dummy" - And the "name" property is required for the Swagger class "Dummy" - # Filters - And the JSON node "paths./dummies.get.parameters[0].name" should be equal to "dummyBoolean" - And the JSON node "paths./dummies.get.parameters[0].in" should be equal to "query" - And the JSON node "paths./dummies.get.parameters[0].required" should be false - And the JSON node "paths./dummies.get.parameters[0].type" should be equal to "boolean" - - # Subcollection - check filter on subResource - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[0].name" should be equal to "id" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[0].in" should be equal to "path" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[0].required" should be true - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[0].type" should be equal to "string" - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[1].name" should be equal to "name" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[1].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[1].required" should be false - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[1].type" should be equal to "string" - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[2].name" should be equal to "description" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[2].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[2].required" should be false - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[2].type" should be equal to "string" - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[3].name" should be equal to "page" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[3].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[3].required" should be false - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[3].type" should be equal to "integer" - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[4].name" should be equal to "itemsPerPage" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[4].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[4].required" should be false - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[4].type" should be equal to "integer" - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[5].name" should be equal to "pagination" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[5].in" should be equal to "query" - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[5].required" should be false - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters[5].type" should be equal to "boolean" - - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters" should have 6 elements - - # Subcollection - check schema - And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.responses.200.schema.items.$ref" should be equal to "#/definitions/RelatedToDummyFriend-fakemanytomany" - - # Deprecations - And the JSON node "paths./dummies.get.deprecated" should not exist - And the JSON node "paths./deprecated_resources.get.deprecated" should be true - And the JSON node "paths./deprecated_resources.post.deprecated" should be true - And the JSON node "paths./deprecated_resources/{id}.get.deprecated" should be true - And the JSON node "paths./deprecated_resources/{id}.delete.deprecated" should be true - And the JSON node "paths./deprecated_resources/{id}.put.deprecated" should be true - And the JSON node "paths./deprecated_resources/{id}.patch.deprecated" should be true - - Scenario: Swagger UI is enabled for docs endpoint - Given I add "Accept" header equal to "text/html" - And I send a "GET" request to "/docs" - Then the response status code should be 200 - And I should see text matching "My Dummy API" - And I should see text matching "swagger" - And I should see text matching "2.0" - - Scenario: Swagger UI is enabled for an arbitrary endpoint - Given I add "Accept" header equal to "text/html" - And I send a "GET" request to "/dummies" - Then the response status code should be 200 - And I should see text matching "My Dummy API" - And I should see text matching "swagger" - And I should see text matching "2.0" - - Scenario: Retrieve the Swagger/OpenAPI documentation with API Gateway compatibility - Given I send a "GET" request to "/docs.json?api_gateway=true" - Then the response status code should be 200 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/json; charset=utf-8" - And the JSON node "basePath" should be equal to "/" - And the JSON node "definitions.RamseyUuidDummy.properties.id.description" should be equal to "The dummy id" - And the JSON node "definitions.RelatedDummy-barcelona" should not exist - And the JSON node "definitions.RelatedDummybarcelona" should exist diff --git a/src/OpenApi/Serializer/ApiGatewayNormalizer.php b/src/OpenApi/Serializer/ApiGatewayNormalizer.php index c904208a51f..7923bc68673 100644 --- a/src/OpenApi/Serializer/ApiGatewayNormalizer.php +++ b/src/OpenApi/Serializer/ApiGatewayNormalizer.php @@ -89,28 +89,28 @@ public function normalize($object, $format = null, array $context = []) } } - foreach ($data['definitions'] as $definition => $options) { + foreach ($data['components']['schemas'] as $definition => $options) { if (!isset($options['properties'])) { continue; } foreach ($options['properties'] as $property => $propertyOptions) { if (isset($propertyOptions['readOnly'])) { - unset($data['definitions'][$definition]['properties'][$property]['readOnly']); + unset($data['components']['schemas'][$definition]['properties'][$property]['readOnly']); } if (isset($propertyOptions['$ref']) && $this->isLocalRef($propertyOptions['$ref'])) { - $data['definitions'][$definition]['properties'][$property]['$ref'] = $this->normalizeRef($propertyOptions['$ref']); + $data['components']['schemas'][$definition]['properties'][$property]['$ref'] = $this->normalizeRef($propertyOptions['$ref']); } if (isset($propertyOptions['items']['$ref']) && $this->isLocalRef($propertyOptions['items']['$ref'])) { - $data['definitions'][$definition]['properties'][$property]['items']['$ref'] = $this->normalizeRef($propertyOptions['items']['$ref']); + $data['components']['schemas'][$definition]['properties'][$property]['items']['$ref'] = $this->normalizeRef($propertyOptions['items']['$ref']); } } } // $data['definitions'] is an instance of \ArrayObject - foreach (array_keys($data['definitions']->getArrayCopy()) as $definition) { + foreach (array_keys($data['components']['schemas']) as $definition) { if (!preg_match('/^[0-9A-Za-z]+$/', (string) $definition)) { - $data['definitions'][preg_replace('/[^0-9A-Za-z]/', '', (string) $definition)] = $data['definitions'][$definition]; - unset($data['definitions'][$definition]); + $data['components']['schemas'][preg_replace('/[^0-9A-Za-z]/', '', (string) $definition)] = $data['components']['schemas'][$definition]; + unset($data['components']['schemas'][$definition]); } } diff --git a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php index 01802333724..eb9837a9858 100644 --- a/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RamseyUuidDummy.php @@ -24,6 +24,9 @@ class RamseyUuidDummy { #[ORM\Id] #[ORM\Column(type: 'uuid', unique: true)] + /** + * The dummy id. + */ private \Ramsey\Uuid\UuidInterface $id; #[ORM\Column(type: 'uuid', nullable: true)] private ?\Ramsey\Uuid\UuidInterface $other = null; From f3388ea127bda2496df430238d3581bf300b7e1d Mon Sep 17 00:00:00 2001 From: soyuka Date: Sat, 25 Jun 2022 19:29:35 +0200 Subject: [PATCH 53/56] fix serializer + gql --- src/Api/IdentifiersExtractor.php | 5 +++ .../Resolver/Factory/ItemResolverFactory.php | 1 + .../Resolver/Stage/DeserializeStage.php | 2 +- src/GraphQl/Resolver/Stage/ReadStage.php | 2 +- src/GraphQl/Resolver/Stage/SerializeStage.php | 2 +- src/GraphQl/Resolver/Stage/WriteStage.php | 2 +- src/GraphQl/Serializer/ItemNormalizer.php | 20 +++++++---- src/GraphQl/Serializer/ObjectNormalizer.php | 6 +--- .../Serializer/SerializerContextBuilder.php | 28 ++++----------- .../SerializerContextBuilderInterface.php | 4 ++- src/GraphQl/Type/SchemaBuilder.php | 12 ------- src/Hal/Serializer/ItemNormalizer.php | 8 +++-- src/JsonApi/Serializer/ItemNormalizer.php | 17 +++++++--- src/JsonLd/ContextBuilder.php | 2 -- src/JsonLd/Serializer/ItemNormalizer.php | 4 +-- .../SerializerPropertyMetadataFactory.php | 4 +++ src/Serializer/AbstractItemNormalizer.php | 17 ++++------ src/Symfony/Routing/IriConverter.php | 34 +++++++++---------- .../TestBundle/Entity/DummyCustomQuery.php | 2 +- .../TestBundle/Entity/VoDummyInspection.php | 16 ++++++++- .../State/DummyDtoInputOutputProcessor.php | 29 +++++++++++++--- .../State/DummyDtoInputOutputProvider.php | 11 +++++- tests/Fixtures/app/config/config_common.yml | 4 +++ 23 files changed, 136 insertions(+), 96 deletions(-) diff --git a/src/Api/IdentifiersExtractor.php b/src/Api/IdentifiersExtractor.php index 88c2055ce90..532d5572197 100644 --- a/src/Api/IdentifiersExtractor.php +++ b/src/Api/IdentifiersExtractor.php @@ -55,6 +55,11 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource public function getIdentifiersFromItem($item, Operation $operation = null, array $context = []): array { $identifiers = []; + + if (!$this->isResourceClass($this->getObjectClass($item))) { + return ['id' => $this->propertyAccessor->getValue($item, 'id')]; + } + $resourceClass = $this->getResourceClass($item, true); $operation = $operation ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation(null, false, true); diff --git a/src/GraphQl/Resolver/Factory/ItemResolverFactory.php b/src/GraphQl/Resolver/Factory/ItemResolverFactory.php index 5e43e6b6aa1..3ac8b912734 100644 --- a/src/GraphQl/Resolver/Factory/ItemResolverFactory.php +++ b/src/GraphQl/Resolver/Factory/ItemResolverFactory.php @@ -71,6 +71,7 @@ public function __invoke(?string $resourceClass = null, ?string $rootClass = nul throw new \LogicException('Item from read stage should be a nullable object.'); } + $resourceClass = $operation->getOutput()['class'] ?? $resourceClass; // The item retrieved can be of another type when using an identifier (see Relay Nodes at query.feature:23) $resourceClass = $this->getResourceClass($item, $resourceClass); $queryResolverId = $operation->getResolver(); diff --git a/src/GraphQl/Resolver/Stage/DeserializeStage.php b/src/GraphQl/Resolver/Stage/DeserializeStage.php index d1262199c76..c7f2ceb37f2 100644 --- a/src/GraphQl/Resolver/Stage/DeserializeStage.php +++ b/src/GraphQl/Resolver/Stage/DeserializeStage.php @@ -44,7 +44,7 @@ public function __invoke($objectToPopulate, string $resourceClass, Operation $op return $objectToPopulate; } - $denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation->getName(), $context, false); + $denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation, $context, false); if (null !== $objectToPopulate) { $denormalizationContext[AbstractNormalizer::OBJECT_TO_POPULATE] = $objectToPopulate; } diff --git a/src/GraphQl/Resolver/Stage/ReadStage.php b/src/GraphQl/Resolver/Stage/ReadStage.php index d0a180fcc5a..089f43c08ec 100644 --- a/src/GraphQl/Resolver/Stage/ReadStage.php +++ b/src/GraphQl/Resolver/Stage/ReadStage.php @@ -59,7 +59,7 @@ public function __invoke(?string $resourceClass, ?string $rootClass, Operation $ } $args = $context['args']; - $normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation->getName(), $context, true); + $normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation, $context, true); if (!$context['is_collection']) { $identifier = $this->getIdentifierFromContext($context); diff --git a/src/GraphQl/Resolver/Stage/SerializeStage.php b/src/GraphQl/Resolver/Stage/SerializeStage.php index cbe326b1205..01e4b6246cd 100644 --- a/src/GraphQl/Resolver/Stage/SerializeStage.php +++ b/src/GraphQl/Resolver/Stage/SerializeStage.php @@ -76,7 +76,7 @@ public function __invoke($itemOrCollection, string $resourceClass, Operation $op return null; } - $normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, true); + $normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation, $context, true); $data = null; if (!$isCollection) { diff --git a/src/GraphQl/Resolver/Stage/WriteStage.php b/src/GraphQl/Resolver/Stage/WriteStage.php index b0a466488bd..01d790abf65 100644 --- a/src/GraphQl/Resolver/Stage/WriteStage.php +++ b/src/GraphQl/Resolver/Stage/WriteStage.php @@ -42,7 +42,7 @@ public function __invoke($data, string $resourceClass, Operation $operation, arr return $data; } - $denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation->getName(), $context, false); + $denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation, $context, false); return $this->processor->process($data, $operation, [], ['operation' => $operation] + $denormalizationContext); } diff --git a/src/GraphQl/Serializer/ItemNormalizer.php b/src/GraphQl/Serializer/ItemNormalizer.php index 2e488b9e66f..c8b83a8f489 100644 --- a/src/GraphQl/Serializer/ItemNormalizer.php +++ b/src/GraphQl/Serializer/ItemNormalizer.php @@ -72,22 +72,28 @@ public function supportsNormalization($data, $format = null, array $context = [] */ public function normalize($object, $format = null, array $context = []) { - if (isset($context['operation_name'])) { - unset($context['operation_name']); - } + $resourceClass = $this->getObjectClass($object); + + if ($outputClass = $this->getOutputClass($resourceClass, $context)) { + $context['graphql_identifiers'] = [ + self::ITEM_RESOURCE_CLASS_KEY => $context['operation']->getClass(), + self::ITEM_IDENTIFIERS_KEY => $this->identifiersExtractor->getIdentifiersFromItem($object, $context['operation'] ?? null), + ]; - if (null !== $this->getOutputClass($this->getObjectClass($object), $context)) { return parent::normalize($object, $format, $context); } + unset($context['operation_name'], $context['operation']); $data = parent::normalize($object, $format, $context); if (!\is_array($data)) { throw new UnexpectedValueException('Expected data to be an array.'); } - if (!($context['no_resolver_data'] ?? false)) { - $data[self::ITEM_RESOURCE_CLASS_KEY] = $this->getObjectClass($object); - $data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($object); + if (isset($context['graphql_identifiers'])) { + $data = $data + $context['graphql_identifiers']; + } elseif (!($context['no_resolver_data'] ?? false)) { + $data[self::ITEM_RESOURCE_CLASS_KEY] = $resourceClass; + $data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($object, $context['operation'] ?? null); } return $data; diff --git a/src/GraphQl/Serializer/ObjectNormalizer.php b/src/GraphQl/Serializer/ObjectNormalizer.php index 68d23ef8f8b..88bb0761df1 100644 --- a/src/GraphQl/Serializer/ObjectNormalizer.php +++ b/src/GraphQl/Serializer/ObjectNormalizer.php @@ -15,7 +15,6 @@ use ApiPlatform\Api\IdentifiersExtractorInterface; use ApiPlatform\Api\IriConverterInterface; -use ApiPlatform\Core\Api\IriConverterInterface as LegacyIriConverterInterface; use ApiPlatform\Util\ClassInfoTrait; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; @@ -37,13 +36,10 @@ final class ObjectNormalizer implements NormalizerInterface, CacheableSupportsMe private $iriConverter; private $identifiersExtractor; - public function __construct(NormalizerInterface $decorated, $iriConverter, IdentifiersExtractorInterface $identifiersExtractor) + public function __construct(NormalizerInterface $decorated, IriConverterInterface $iriConverter, IdentifiersExtractorInterface $identifiersExtractor) { $this->decorated = $decorated; $this->iriConverter = $iriConverter; - if ($iriConverter instanceof LegacyIriConverterInterface) { - trigger_deprecation('api-platform/core', '2.7', sprintf('Use an implementation of "%s" instead of "%s".', IriConverterInterface::class, LegacyIriConverterInterface::class)); - } $this->identifiersExtractor = $identifiersExtractor; } diff --git a/src/GraphQl/Serializer/SerializerContextBuilder.php b/src/GraphQl/Serializer/SerializerContextBuilder.php index 5c4899cdbef..cfc8b473a1f 100644 --- a/src/GraphQl/Serializer/SerializerContextBuilder.php +++ b/src/GraphQl/Serializer/SerializerContextBuilder.php @@ -13,7 +13,6 @@ namespace ApiPlatform\GraphQl\Serializer; -use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use GraphQL\Type\Definition\ResolveInfo; @@ -36,33 +35,18 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource $this->nameConverter = $nameConverter; } - public function create(?string $resourceClass, string $operationName, array $resolverContext, bool $normalization): array + public function create(?string $resourceClass, Operation $operation, array $resolverContext, bool $normalization): array { - $context = ['resource_class' => $resourceClass, 'operation_name' => $operationName, 'graphql_operation_name' => $operationName]; - $operation = null; - - if ($resourceClass) { - $resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass); - try { - $operation = $resourceMetadata->getOperation($operationName); - } catch (OperationNotFoundException $e) { - // It's possible that the serialization context may not be tight to an existing operation - try { - $context['operation_name'] = $resourceMetadata->getOperation()->getName(); - } catch (OperationNotFoundException $e) { - } - } - } + $context = ['resource_class' => $resourceClass, 'operation_name' => $operation->getName(), 'graphql_operation_name' => $operation->getName()]; if (isset($resolverContext['fields'])) { $context['no_resolver_data'] = true; } - if ($operation) { - $context['input'] = $operation->getInput(); - $context['output'] = $operation->getOutput(); - $context = $normalization ? array_merge($operation->getNormalizationContext() ?? [], $context) : array_merge($operation->getDenormalizationContext() ?? [], $context); - } + $context['operation'] = $operation; + $context['input'] = $operation->getInput(); + $context['output'] = $operation->getOutput(); + $context = $normalization ? array_merge($operation->getNormalizationContext() ?? [], $context) : array_merge($operation->getDenormalizationContext() ?? [], $context); if ($normalization) { $context['attributes'] = $this->fieldsToAttributes($resourceClass, $operation instanceof Operation ? $operation : null, $resolverContext, $context); diff --git a/src/GraphQl/Serializer/SerializerContextBuilderInterface.php b/src/GraphQl/Serializer/SerializerContextBuilderInterface.php index 545c996cca7..1ec210b1aa9 100644 --- a/src/GraphQl/Serializer/SerializerContextBuilderInterface.php +++ b/src/GraphQl/Serializer/SerializerContextBuilderInterface.php @@ -13,6 +13,8 @@ namespace ApiPlatform\GraphQl\Serializer; +use ApiPlatform\Metadata\GraphQl\Operation; + /** * Builds the context used by the Symfony Serializer. * @@ -20,5 +22,5 @@ */ interface SerializerContextBuilderInterface { - public function create(string $resourceClass, string $operationName, array $resolverContext, bool $normalization): array; + public function create(string $resourceClass, Operation $operation, array $resolverContext, bool $normalization): array; } diff --git a/src/GraphQl/Type/SchemaBuilder.php b/src/GraphQl/Type/SchemaBuilder.php index 11041e9b241..7f237e16c24 100644 --- a/src/GraphQl/Type/SchemaBuilder.php +++ b/src/GraphQl/Type/SchemaBuilder.php @@ -63,18 +63,6 @@ public function getSchema(): Schema foreach ($resourceMetadata->getGraphQlOperations() ?? [] as $operationName => $operation) { $configuration = null !== $operation->getArgs() ? ['args' => $operation->getArgs()] : []; - // TODO: 3.0 remove these - if ('item_query' === $operationName) { - $queryFields += $this->fieldsBuilder->getItemQueryFields($resourceClass, $operation, $configuration); - continue; - } - - if ('collection_query' === $operationName) { - $queryFields += $this->fieldsBuilder->getCollectionQueryFields($resourceClass, $operation, $configuration); - - continue; - } - if ($operation instanceof Query && $operation instanceof CollectionOperationInterface) { $queryFields += $this->fieldsBuilder->getCollectionQueryFields($resourceClass, $operation, $configuration); diff --git a/src/Hal/Serializer/ItemNormalizer.php b/src/Hal/Serializer/ItemNormalizer.php index 55b7899f8b5..76bd14c4359 100644 --- a/src/Hal/Serializer/ItemNormalizer.php +++ b/src/Hal/Serializer/ItemNormalizer.php @@ -53,7 +53,8 @@ public function supportsNormalization($data, $format = null, array $context = [] */ public function normalize($object, $format = null, array $context = []) { - if (null !== $this->getOutputClass($this->getObjectClass($object), $context)) { + $resourceClass = $this->getObjectClass($object); + if ($this->getOutputClass($resourceClass, $context)) { return parent::normalize($object, $format, $context); } @@ -61,7 +62,10 @@ public function normalize($object, $format = null, array $context = []) $context['cache_key'] = $this->getCacheKey($format, $context); } - $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); + if ($this->resourceClassResolver->isResourceClass($resourceClass)) { + $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); + } + $context = $this->initContext($resourceClass, $context); $iri = $this->iriConverter->getIriFromResource($object); $context['iri'] = $iri; diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index 22b3b581c5d..c0c2dc177bb 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -72,7 +72,8 @@ public function supportsNormalization($data, $format = null, array $context = [] */ public function normalize($object, $format = null, array $context = []) { - if (null !== $this->getOutputClass($this->getObjectClass($object), $context)) { + $resourceClass = $this->getObjectClass($object); + if ($this->getOutputClass($resourceClass, $context)) { return parent::normalize($object, $format, $context); } @@ -80,7 +81,10 @@ public function normalize($object, $format = null, array $context = []) $context['cache_key'] = $this->getCacheKey($format, $context); } - $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); + if ($isResourceClass = $this->resourceClassResolver->isResourceClass($resourceClass)) { + $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); + } + $context = $this->initContext($resourceClass, $context); $iri = $this->iriConverter->getIriFromResource($object); $context['iri'] = $iri; @@ -455,10 +459,15 @@ private function getIncludedNestedResources(string $relationshipName, array $con }, $filtered); } + // TODO: this code is similar to the one used in JsonLd private function getResourceShortName(string $resourceClass): string { - $resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass); + if ($this->resourceClassResolver->isResourceClass($resourceClass)) { + $resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass); + + return $resourceMetadata->getOperation()->getShortName(); + } - return $resourceMetadata->getOperation()->getShortName(); + return (new \ReflectionClass($resourceClass))->getShortName(); } } diff --git a/src/JsonLd/ContextBuilder.php b/src/JsonLd/ContextBuilder.php index cf0a52857eb..2569967c807 100644 --- a/src/JsonLd/ContextBuilder.php +++ b/src/JsonLd/ContextBuilder.php @@ -191,5 +191,3 @@ private function getResourceContextWithShortname(string $resourceClass, int $ref return $context; } } - -class_alias(ContextBuilder::class, \ApiPlatform\Core\JsonLd\ContextBuilder::class); diff --git a/src/JsonLd/Serializer/ItemNormalizer.php b/src/JsonLd/Serializer/ItemNormalizer.php index 98d27036995..0f43bbdfb9f 100644 --- a/src/JsonLd/Serializer/ItemNormalizer.php +++ b/src/JsonLd/Serializer/ItemNormalizer.php @@ -72,8 +72,8 @@ public function supportsNormalization($data, $format = null, array $context = [] public function normalize($object, $format = null, array $context = []) { $resourceClass = $this->getObjectClass($object); - $outputClass = $this->getOutputClass($resourceClass, $context); - if (null !== $outputClass) { + + if ($outputClass = $this->getOutputClass($resourceClass, $context)) { return parent::normalize($object, $format, $context); } diff --git a/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php b/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php index e43e513f76c..57c7cbaa797 100644 --- a/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php +++ b/src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php @@ -65,6 +65,10 @@ public function create(string $resourceClass, string $property, array $options = $propertyMetadata = $this->transformReadWrite($propertyMetadata, $resourceClass, $property, $normalizationGroups, $denormalizationGroups); + if (!$this->isResourceClass($resourceClass) && ($builtinType = $propertyMetadata->getBuiltinTypes()[0] ?? null) && $builtinType->isCollection()) { + return $propertyMetadata->withReadableLink(true)->withWritableLink(true); + } + return $this->transformLinkStatus($propertyMetadata, $normalizationGroups, $denormalizationGroups); } diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index 1fd0b5e3729..49d5474c978 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -116,8 +116,8 @@ public function hasCacheableSupportsMethod(): bool */ public function normalize($object, $format = null, array $context = []) { - $class = $this->getObjectClass($object); - if ($outputClass = $this->getOutputClass($class, $context)) { + $resourceClass = $this->getObjectClass($object); + if ($outputClass = $this->getOutputClass($resourceClass, $context)) { if (!$this->serializer instanceof DenormalizerInterface) { throw new LogicException('Cannot normalize the output because the injected serializer is not a normalizer'); } @@ -132,8 +132,7 @@ public function normalize($object, $format = null, array $context = []) return $this->serializer->normalize($object, $format, $context); } - if ($this->resourceClassResolver->isResourceClass($class)) { - $resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null); + if ($this->resourceClassResolver->isResourceClass($resourceClass)) { $context = $this->initContext($resourceClass, $context); } @@ -158,6 +157,7 @@ public function normalize($object, $format = null, array $context = []) } $data = parent::normalize($object, $format, $context); + if ($emptyResourceAsIri && \is_array($data) && 0 === \count($data)) { return $iri; } @@ -571,8 +571,9 @@ protected function getFactoryOptions(array $context): array $options['serializer_groups'] = (array) $context[self::GROUPS]; } - if ($this->resourceClassResolver->isResourceClass($context['resource_class'])) { - $operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($context['resource_class'])->getOperation($context['operation_name'] ?? null); + if (isset($context['resource_class']) && $this->resourceClassResolver->isResourceClass($context['resource_class'])) { + $resourceClass = $this->resourceClassResolver->getResourceClass($context['resource_class'], $context['resource_class']); + $operation = $context['operation'] ?? $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation($context['operation_name'] ?? null); $options['normalization_groups'] = $operation->getNormalizationContext()['groups'] ?? null; $options['denormalization_groups'] = $operation->getDenormalizationContext()['groups'] ?? null; $options['operation_name'] = $operation->getName(); @@ -620,9 +621,7 @@ protected function getAttributeValue($object, $attribute, $format = null, array $resourceClass = $this->resourceClassResolver->getResourceClass($attributeValue, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; - // if ($this->resourceMetadataCollectionFactory instanceof ResourceMetadataCollectionFactoryInterface) { $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); - // } unset($childContext['iri'], $childContext['uri_variables']); return $this->normalizeCollectionOfRelations($propertyMetadata, $attributeValue, $resourceClass, $format, $childContext); @@ -640,9 +639,7 @@ protected function getAttributeValue($object, $attribute, $format = null, array $resourceClass = $this->resourceClassResolver->getResourceClass($attributeValue, $className); $childContext = $this->createChildContext($context, $attribute, $format); $childContext['resource_class'] = $resourceClass; - // if ($this->resourceMetadataCollectionFactory instanceof ResourceMetadataCollectionFactoryInterface) { $childContext['operation'] = $this->resourceMetadataCollectionFactory->create($resourceClass)->getOperation(); - // } unset($childContext['iri'], $childContext['uri_variables']); return $this->normalizeRelation($propertyMetadata, $attributeValue, $resourceClass, $format, $childContext); diff --git a/src/Symfony/Routing/IriConverter.php b/src/Symfony/Routing/IriConverter.php index 93dbcd7bd7a..cd849e2f780 100644 --- a/src/Symfony/Routing/IriConverter.php +++ b/src/Symfony/Routing/IriConverter.php @@ -32,6 +32,7 @@ use ApiPlatform\State\ProviderInterface; use ApiPlatform\State\UriVariablesResolverTrait; use ApiPlatform\Util\AttributesExtractor; +use ApiPlatform\Util\ClassInfoTrait; use ApiPlatform\Util\ResourceClassInfoTrait; use Symfony\Component\Routing\Exception\ExceptionInterface as RoutingExceptionInterface; use Symfony\Component\Routing\RouterInterface; @@ -45,6 +46,7 @@ */ final class IriConverter implements IriConverterInterface { + use ClassInfoTrait; use ResourceClassInfoTrait; use UriVariablesResolverTrait; @@ -113,10 +115,15 @@ public function getResourceFromIri(string $iri, array $context = [], ?Operation */ public function getIriFromResource($item, int $referenceType = UrlGeneratorInterface::ABS_PATH, Operation $operation = null, array $context = []): ?string { - try { - $resourceClass = \is_string($item) ? $item : $this->getResourceClass($item, true); - } catch (InvalidArgumentException $e) { - return null; + $resourceClass = \is_string($item) ? $item : $this->getObjectClass($item); + + if (!$this->resourceClassResolver->isResourceClass($resourceClass)) { + return $this->generateSkolemIri($context); + } + + // This is only for when a class (that is not a resource) extends another one that is a resource, we should remove this behavior + if (!\is_string($item)) { + $resourceClass = $this->getResourceClass($item, true); } if (!$operation) { @@ -128,17 +135,10 @@ public function getIriFromResource($item, int $referenceType = UrlGeneratorInter unset($context['uri_variables']); } - // Legacy subresources had bad IRIs but we don't want to break these, remove this in 3.0 - $isLegacySubresource = ($operation->getExtraProperties()['is_legacy_subresource'] ?? false) && !$operation instanceof CollectionOperationInterface; - // Custom resources should have the same IRI as requested, it was not the case pre 2.7 - $isLegacyCustomResource = ($operation->getExtraProperties()['is_legacy_resource_metadata'] ?? false) && ($operation->getExtraProperties()['user_defined_uri_template'] ?? false); - // In symfony the operation name is the route name, try to find one if none provided if ( !$operation->getName() || ($operation instanceof HttpOperation && HttpOperation::METHOD_POST === $operation->getMethod()) - || $isLegacySubresource - || $isLegacyCustomResource ) { $forceCollection = $operation instanceof CollectionOperationInterface; try { @@ -149,10 +149,6 @@ public function getIriFromResource($item, int $referenceType = UrlGeneratorInter $identifiers = $context['uri_variables'] ?? []; - if ($isLegacySubresource || $isLegacyCustomResource) { - $identifiers = []; - } - if (\is_object($item)) { try { $identifiers = $this->identifiersExtractor->getIdentifiersFromItem($item, $operation); @@ -164,9 +160,8 @@ public function getIriFromResource($item, int $referenceType = UrlGeneratorInter } } - // TODO: call the Skolem IRI generator if (!$operation->getName()) { - return null; + return $this->generateSkolemIri($context); } try { @@ -175,4 +170,9 @@ public function getIriFromResource($item, int $referenceType = UrlGeneratorInter throw new InvalidArgumentException(sprintf('Unable to generate an IRI for the item of type "%s"', $resourceClass), $e->getCode(), $e); } } + + private function generateSkolemIri(array $context = []) + { + return $context['iri'] ?? '/.well-known/genid/'.(bin2hex(random_bytes(10))); + } } diff --git a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php index b570184ac76..989c2712ef4 100644 --- a/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php +++ b/tests/Fixtures/TestBundle/Entity/DummyCustomQuery.php @@ -40,7 +40,7 @@ ], name: 'testItemCustomArguments'), new QueryCollection(resolver: 'app.graphql.query_resolver.dummy_custom_collection', name: 'testCollection'), new QueryCollection(resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false, name: 'testCollectionNoReadAndSerialize'), - new Query( + new QueryCollection( name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']] diff --git a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php index 7d88ae92d5b..b20e7ffdd93 100644 --- a/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php +++ b/tests/Fixtures/TestBundle/Entity/VoDummyInspection.php @@ -23,13 +23,27 @@ class VoDummyInspection { use VoDummyIdAwareTrait; + + #[ORM\Column(type: 'boolean')] + #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] + private bool $accepted; + + #[ORM\ManyToOne(targetEntity: VoDummyCar::class, inversedBy: 'inspections')] + #[Groups(['inspection_read', 'inspection_write'])] + private ?VoDummyCar $car; + #[ORM\Column(type: 'datetime')] #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private \DateTime $performed; - public function __construct(#[ORM\Column(type: 'boolean')] #[Groups(['car_read', 'car_write', 'inspection_read', 'inspection_write'])] private readonly bool $accepted, #[ORM\ManyToOne(targetEntity: VoDummyCar::class, inversedBy: 'inspections')] #[Groups(['inspection_read', 'inspection_write'])] private readonly ?VoDummyCar $car, DateTime $performed = null, private readonly string $attributeWithoutConstructorEquivalent = '') + private $attributeWithoutConstructorEquivalent; + + public function __construct(bool $accepted, VoDummyCar $car, DateTime $performed = null, string $parameterWhichIsNotClassAttribute = '') { + $this->accepted = $accepted; + $this->car = $car; $this->performed = $performed ?: new DateTime(); + $this->attributeWithoutConstructorEquivalent = $parameterWhichIsNotClassAttribute; } public function isAccepted() diff --git a/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProcessor.php b/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProcessor.php index d6571884f3e..6af9918e23f 100644 --- a/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProcessor.php +++ b/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProcessor.php @@ -17,9 +17,15 @@ use ApiPlatform\State\ProcessorInterface; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\InputDto; use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyDtoInputOutput; +use Doctrine\Persistence\ManagerRegistry; final class DummyDtoInputOutputProcessor implements ProcessorInterface { + public function __construct(private ManagerRegistry $registry) + { + } + /** * {@inheritDoc} * @@ -27,13 +33,26 @@ final class DummyDtoInputOutputProcessor implements ProcessorInterface */ public function process($data, Operation $operation, array $uriVariables = [], array $context = []) { - $outputDto = $context['previous_data'] ?? new OutputDto(); - if (!$outputDto->id) { - $outputDto->id = 1; + // TODO: mongodb + $entity = new DummyDtoInputOutput(); + $manager = $this->registry->getManagerForClass(DummyDtoInputOutput::class); + + if (isset($context['previous_data'])) { + $entity = $manager->getReference(DummyDtoInputOutput::class, $context['previous_data']->id); } - $outputDto->baz = $data->bar; - $outputDto->bat = $data->foo; + $entity->str = $data->foo; + $entity->num = $data->bar; + $entity->relatedDummies = $data->relatedDummies; + + $manager->persist($entity); + $manager->flush(); + + $outputDto = new OutputDto(); + $outputDto->id = $entity->id; + $outputDto->baz = $entity->num; + $outputDto->bat = $entity->str; + $outputDto->relatedDummies = $data->relatedDummies ?? []; return $outputDto; } diff --git a/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProvider.php b/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProvider.php index 74ee62cfaab..a052eaeb719 100644 --- a/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProvider.php +++ b/tests/Fixtures/TestBundle/State/DummyDtoInputOutputProvider.php @@ -19,13 +19,22 @@ final class DummyDtoInputOutputProvider implements ProviderInterface { + public function __construct(private ProviderInterface $decorated) + { + } + /** * {@inheritDoc} */ public function provide(Operation $operation, array $uriVariables = [], array $context = []) { + $data = $this->decorated->provide($operation, $uriVariables, $context); + $outputDto = new OutputDto(); - $outputDto->id = $uriVariables['id']; + $outputDto->id = $data->id; + $outputDto->baz = $data->num; + $outputDto->bat = $data->str; + $outputDto->relatedDummies = $data->relatedDummies; return $outputDto; } diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index b83ec58b655..1408ea61855 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -314,10 +314,14 @@ services: - name: 'api_platform.state_provider' ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoInputOutputProcessor: + arguments: + $registry: '@doctrine' tags: - name: 'api_platform.state_processor' ApiPlatform\Tests\Fixtures\TestBundle\State\DummyDtoInputOutputProvider: + arguments: + $decorated: '@ApiPlatform\Doctrine\Orm\State\ItemProvider' tags: - name: 'api_platform.state_provider' From ca6353c50bd3ad5bda3ce0e892af52ea54734b6b Mon Sep 17 00:00:00 2001 From: soyuka Date: Sat, 25 Jun 2022 19:30:00 +0200 Subject: [PATCH 54/56] ask alan --- features/graphql/input_output.feature | 6 ++---- features/graphql/introspection.feature | 2 +- features/graphql/mutation.feature | 2 +- features/jsonld/input_output.feature | 1 - tests/Fixtures/TestBundle/Entity/RelatedDummy.php | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/features/graphql/input_output.feature b/features/graphql/input_output.feature index 6dad98666d4..08bbb4c167b 100644 --- a/features/graphql/input_output.feature +++ b/features/graphql/input_output.feature @@ -27,14 +27,12 @@ Feature: GraphQL DTO input and output "bat": "OutputDto/bat", "relatedDummies": "OutputDto/relatedDummies" }, - "@type": "DummyDtoInputOutput", - "@id": "/dummy_dto_input_outputs/1", + "@type": "OutputDto", "id": 1, "baz": 1, "bat": "test", "relatedDummies": [ { - "@context": "/contexts/RelatedDummy", "@id": "/related_dummies/1", "@type": "https://schema.org/Product", "name": "RelatedDummy with friends", @@ -150,7 +148,7 @@ Feature: GraphQL DTO input and output { "errors": [ { - "message": "Cannot query field \"id\" on type \"DummyDtoNoOutput\".", + "message": "Cannot query field \"id\" on type \"createDummyDtoNoOutputPayloadData\".", "extensions": { "category": "graphql" }, diff --git a/features/graphql/introspection.feature b/features/graphql/introspection.feature index e60211419c6..22934bbbb31 100644 --- a/features/graphql/introspection.feature +++ b/features/graphql/introspection.feature @@ -565,4 +565,4 @@ Feature: GraphQL introspection support And the header "Content-Type" should be equal to "application/json" And the JSON node "errors[0].debugMessage" should be equal to 'Type with id "VoDummyInspectionCursorConnection" is not present in the types container' And the JSON node "data.typeNotAvailable" should be null - And the JSON node "data.typeOwner.fields[3].type.name" should be equal to "VoDummyInspectionCursorConnection" + And the JSON node "data.typeOwner.fields[1].type.name" should be equal to "VoDummyInspectionCursorConnection" diff --git a/features/graphql/mutation.feature b/features/graphql/mutation.feature index 01b38f97e17..48c6a7781fe 100644 --- a/features/graphql/mutation.feature +++ b/features/graphql/mutation.feature @@ -400,7 +400,7 @@ Feature: GraphQL mutation support And the header "Content-Type" should be equal to "application/json" And the JSON node "data.createFoo.foo.id" should be equal to "/foos/1" And the JSON node "data.createFoo.foo._id" should be equal to 1 - And the JSON node "data.createFoo.foo.__typename" should be equal to "Foo" + And the JSON node "data.createFoo.foo.__typename" should be equal to "createFooPayloadData" And the JSON node "data.createFoo.foo.name" should be equal to "A new one" And the JSON node "data.createFoo.foo.bar" should be equal to "new" And the JSON node "data.createFoo.clientMutationId" should be equal to "myId" diff --git a/features/jsonld/input_output.feature b/features/jsonld/input_output.feature index 609c4907819..eb5b65514c0 100644 --- a/features/jsonld/input_output.feature +++ b/features/jsonld/input_output.feature @@ -103,7 +103,6 @@ Feature: JSON-LD DTO input and output "bar": 1 } """ - Then print last JSON response Then the response status code should be 201 And the JSON should be a superset of: """ diff --git a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php index 255a1036a46..e66816e08fb 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php @@ -53,7 +53,7 @@ class RelatedDummy extends ParentDummy * @var string|null A name */ #[ORM\Column(nullable: true)] - #[Groups(['friends'])] + #[Groups(['friends', 'chicago'])] public $name; #[ORM\Column] From f37afb0c3a3442d7301c349eab4865855e6cbbd8 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Mon, 27 Jun 2022 12:27:13 +0200 Subject: [PATCH 55/56] fix(graphql): wrapped type should always take the query normalization context --- features/graphql/input_output.feature | 2 +- features/graphql/mutation.feature | 2 +- src/GraphQl/Type/TypeBuilder.php | 20 +++++++++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/features/graphql/input_output.feature b/features/graphql/input_output.feature index 08bbb4c167b..1a5bcb166b5 100644 --- a/features/graphql/input_output.feature +++ b/features/graphql/input_output.feature @@ -148,7 +148,7 @@ Feature: GraphQL DTO input and output { "errors": [ { - "message": "Cannot query field \"id\" on type \"createDummyDtoNoOutputPayloadData\".", + "message": "Cannot query field \"id\" on type \"DummyDtoNoOutput\".", "extensions": { "category": "graphql" }, diff --git a/features/graphql/mutation.feature b/features/graphql/mutation.feature index 48c6a7781fe..01b38f97e17 100644 --- a/features/graphql/mutation.feature +++ b/features/graphql/mutation.feature @@ -400,7 +400,7 @@ Feature: GraphQL mutation support And the header "Content-Type" should be equal to "application/json" And the JSON node "data.createFoo.foo.id" should be equal to "/foos/1" And the JSON node "data.createFoo.foo._id" should be equal to 1 - And the JSON node "data.createFoo.foo.__typename" should be equal to "createFooPayloadData" + And the JSON node "data.createFoo.foo.__typename" should be equal to "Foo" And the JSON node "data.createFoo.foo.name" should be equal to "A new one" And the JSON node "data.createFoo.foo.bar" should be equal to "new" And the JSON node "data.createFoo.clientMutationId" should be equal to "myId" diff --git a/src/GraphQl/Type/TypeBuilder.php b/src/GraphQl/Type/TypeBuilder.php index af6774f7b5b..9378b922c86 100644 --- a/src/GraphQl/Type/TypeBuilder.php +++ b/src/GraphQl/Type/TypeBuilder.php @@ -115,11 +115,7 @@ public function getResourceObjectType(?string $resourceClass, ResourceMetadataCo 'resolveField' => $this->defaultFieldResolver, 'fields' => function () use ($resourceClass, $operation, $operationName, $resourceMetadataCollection, $input, $wrapData, $depth, $ioMetadata) { if ($wrapData) { - try { - $queryNormalizationContext = $operation instanceof Query ? ($resourceMetadataCollection->getOperation($operationName)->getNormalizationContext() ?? []) : []; - } catch (OperationNotFoundException $e) { - $queryNormalizationContext = []; - } + $queryNormalizationContext = $this->getQueryOperation($resourceMetadataCollection)?->getNormalizationContext() ?? []; try { $mutationNormalizationContext = $operation instanceof Mutation || $operation instanceof Subscription ? ($resourceMetadataCollection->getOperation($operationName)->getNormalizationContext() ?? []) : []; @@ -310,4 +306,18 @@ private function getPageBasedPaginationFields(GraphQLType $resourceType): array 'paginationInfo' => GraphQLType::nonNull($paginationInfoObjectType), ]; } + + private function getQueryOperation(ResourceMetadataCollection $resourceMetadataCollection): ?Operation + { + foreach ($resourceMetadataCollection as $resourceMetadata) { + foreach ($resourceMetadata->getGraphQlOperations() as $operation) { + // Filter the custom queries. + if ($operation instanceof Query && !$operation->getResolver()) { + return $operation; + } + } + } + + return null; + } } From b164f711f9c0e407888ff09f91adae0f9ccf9170 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Mon, 27 Jun 2022 14:59:01 +0200 Subject: [PATCH 56/56] test: remove group from RelatedDummy --- tests/Fixtures/TestBundle/Entity/RelatedDummy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php index e66816e08fb..255a1036a46 100644 --- a/tests/Fixtures/TestBundle/Entity/RelatedDummy.php +++ b/tests/Fixtures/TestBundle/Entity/RelatedDummy.php @@ -53,7 +53,7 @@ class RelatedDummy extends ParentDummy * @var string|null A name */ #[ORM\Column(nullable: true)] - #[Groups(['friends', 'chicago'])] + #[Groups(['friends'])] public $name; #[ORM\Column]