diff --git a/features/doctrine/transform_model.feature b/features/doctrine/transform_model.feature new file mode 100644 index 00000000000..5ace2cf83d4 --- /dev/null +++ b/features/doctrine/transform_model.feature @@ -0,0 +1,37 @@ +Feature: Use an entity or document transformer to return the correct ressource + + @createSchema + @!mongodb + Scenario: Get collection from entities + Given there is a TransformedDummy for date '2025-01-01' + When I send a "GET" request to "/transformed_dummy_entity_ressources" + Then the response status code should be 200 + And the response should be in JSON + And the JSON node "hydra:totalItems" should be equal to 1 + + @!mongodb + Scenario: Get item from entity + Given there is a TransformedDummy for date '2025-01-01' + When I send a "GET" request to "/transformed_dummy_entity_ressources/1" + Then the response status code should be 200 + And the response should be in JSON + And the JSON node "year" should exist + And the JSON node year should be equal to "2025" + + @createSchema + @mongodb + Scenario: Get collection from documents + Given there is a TransformedDummy for date '2025-01-01' + When I send a "GET" request to "/transformed_dummy_document_ressources" + Then the response status code should be 200 + And the response should be in JSON + And the JSON node "hydra:totalItems" should be equal to 1 + + @mongodb + Scenario: Get item from document + Given there is a TransformedDummy for date '2025-01-01' + When I send a "GET" request to "/transformed_dummy_document_ressources/1" + Then the response status code should be 200 + And the response should be in JSON + And the JSON node "year" should exist + And the JSON node year should be equal to "2025" diff --git a/src/Doctrine/Common/State/Options.php b/src/Doctrine/Common/State/Options.php index df42fc6cb84..8dc88eca6a7 100644 --- a/src/Doctrine/Common/State/Options.php +++ b/src/Doctrine/Common/State/Options.php @@ -19,9 +19,13 @@ class Options implements OptionsInterface { /** * @param mixed $handleLinks experimental callable, typed mixed as we may want a service name in the future + * @param mixed $toResourceTransformer experimental callable, typed mixed as we may want a service name in the future + * @param mixed $fromResourceTransformer experimental callable, typed mixed as we may want a service name in the future */ public function __construct( protected mixed $handleLinks = null, + protected mixed $toResourceTransformer = null, + protected mixed $fromResourceTransformer = null, ) { } @@ -37,4 +41,30 @@ public function withHandleLinks(mixed $handleLinks): self return $self; } + + public function getToResourceTransformer(): mixed + { + return $this->toResourceTransformer; + } + + public function withToResourceTransformer(mixed $toResourceTransformer): self + { + $self = clone $this; + $self->toResourceTransformer = $toResourceTransformer; + + return $self; + } + + public function getFromResourceTransformer(): mixed + { + return $this->fromResourceTransformer; + } + + public function withFromResourceTransformer(mixed $fromResourceTransformer): self + { + $self = clone $this; + $self->fromResourceTransformer = $fromResourceTransformer; + + return $self; + } } diff --git a/src/Doctrine/Common/State/PersistProcessor.php b/src/Doctrine/Common/State/PersistProcessor.php index abc21bf9e15..c0d85a1b5d0 100644 --- a/src/Doctrine/Common/State/PersistProcessor.php +++ b/src/Doctrine/Common/State/PersistProcessor.php @@ -24,6 +24,7 @@ final class PersistProcessor implements ProcessorInterface { use ClassInfoTrait; use LinksHandlerTrait; + use ResourceTransformerLocatorTrait; public function __construct(private readonly ManagerRegistry $managerRegistry) { diff --git a/src/Doctrine/Common/State/ResourceTransformerLocatorTrait.php b/src/Doctrine/Common/State/ResourceTransformerLocatorTrait.php new file mode 100644 index 00000000000..7441021e351 --- /dev/null +++ b/src/Doctrine/Common/State/ResourceTransformerLocatorTrait.php @@ -0,0 +1,61 @@ + + * + * For 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\Common\State; + +use ApiPlatform\Metadata\Operation; +use Psr\Container\ContainerInterface; + +/** + * Maybe merge this and LinksHandlerLocatorTrait into a OptionsHooksLocatorTrait or something similar? + */ +trait ResourceTransformerLocatorTrait +{ + private ?ContainerInterface $resourceTransformerLocator; + + protected function getToResourceTransformer(Operation $operation): ?callable + { + if (!($options = $operation->getStateOptions()) || !$options instanceof Options) { + return null; + } + + $transformer = $options->getToResourceTransformer(); + if (\is_callable($transformer)) { + return $transformer; + } + + if ($this->resourceTransformerLocator && \is_string($transformer) && $this->resourceTransformerLocator->has($transformer)) { + return [$this->resourceTransformerLocator->get($transformer), 'toResource']; + } + + return null; + } + + protected function getFromResourceTransformer(Operation $operation): ?callable + { + if (!($options = $operation->getStateOptions()) || !$options instanceof Options) { + return null; + } + + $transformer = $options->getFromResourceTransformer(); + if (\is_callable($transformer)) { + return $transformer; + } + + if ($this->resourceTransformerLocator && \is_string($transformer) && $this->resourceTransformerLocator->has($transformer)) { + return [$this->resourceTransformerLocator->get($transformer), 'fromResource']; + } + + return null; + } +} diff --git a/src/Doctrine/Odm/State/CollectionProvider.php b/src/Doctrine/Odm/State/CollectionProvider.php index 3c5c923f893..0b27e6795ab 100644 --- a/src/Doctrine/Odm/State/CollectionProvider.php +++ b/src/Doctrine/Odm/State/CollectionProvider.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Odm\State; use ApiPlatform\Doctrine\Common\State\LinksHandlerLocatorTrait; +use ApiPlatform\Doctrine\Common\State\ResourceTransformerLocatorTrait; use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface; use ApiPlatform\Metadata\Exception\RuntimeException; @@ -32,6 +33,7 @@ final class CollectionProvider implements ProviderInterface { use LinksHandlerLocatorTrait; use LinksHandlerTrait; + use ResourceTransformerLocatorTrait; /** * @param AggregationCollectionExtensionInterface[] $collectionExtensions @@ -40,6 +42,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource { $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; $this->handleLinksLocator = $handleLinksLocator; + $this->resourceTransformerLocator = $handleLinksLocator; $this->managerRegistry = $managerRegistry; } @@ -70,13 +73,19 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $extension->applyToCollection($aggregationBuilder, $documentClass, $operation, $context); if ($extension instanceof AggregationResultCollectionExtensionInterface && $extension->supportsResult($documentClass, $operation, $context)) { - return $extension->getResult($aggregationBuilder, $documentClass, $operation, $context); + $result = $extension->getResult($aggregationBuilder, $documentClass, $operation, $context); + break; } } $attribute = $operation->getExtraProperties()['doctrine_mongodb'] ?? []; $executeOptions = $attribute['execute_options'] ?? []; - return $aggregationBuilder->hydrate($documentClass)->execute($executeOptions); + $result = $result ?? $aggregationBuilder->hydrate($documentClass)->execute($executeOptions); + + return match ($transformer = $this->getToResourceTransformer($operation)) { + null => $result, + default => array_map($transformer, iterator_to_array($result)), + }; } } diff --git a/src/Doctrine/Odm/State/ItemProvider.php b/src/Doctrine/Odm/State/ItemProvider.php index d367ea4fa02..5832e432362 100644 --- a/src/Doctrine/Odm/State/ItemProvider.php +++ b/src/Doctrine/Odm/State/ItemProvider.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Odm\State; use ApiPlatform\Doctrine\Common\State\LinksHandlerLocatorTrait; +use ApiPlatform\Doctrine\Common\State\ResourceTransformerLocatorTrait; use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface; use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface; use ApiPlatform\Metadata\Exception\RuntimeException; @@ -35,6 +36,7 @@ final class ItemProvider implements ProviderInterface { use LinksHandlerLocatorTrait; use LinksHandlerTrait; + use ResourceTransformerLocatorTrait; /** * @param AggregationItemExtensionInterface[] $itemExtensions @@ -43,6 +45,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource { $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; $this->handleLinksLocator = $handleLinksLocator; + $this->resourceTransformerLocator = $handleLinksLocator; $this->managerRegistry = $managerRegistry; } @@ -78,12 +81,18 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $extension->applyToItem($aggregationBuilder, $documentClass, $uriVariables, $operation, $context); if ($extension instanceof AggregationResultItemExtensionInterface && $extension->supportsResult($documentClass, $operation, $context)) { - return $extension->getResult($aggregationBuilder, $documentClass, $operation, $context); + $result = $extension->getResult($aggregationBuilder, $documentClass, $operation, $context); + break; } } $executeOptions = $operation->getExtraProperties()['doctrine_mongodb']['execute_options'] ?? []; - return $aggregationBuilder->hydrate($documentClass)->execute($executeOptions)->current() ?: null; + $result = $result ?? ($aggregationBuilder->hydrate($documentClass)->execute($executeOptions)->current() ?: null); + + return match ($transformer = $this->getToResourceTransformer($operation)) { + null => $result, + default => (null !== $result) ? $transformer($result) : null, + }; } } diff --git a/src/Doctrine/Odm/State/Options.php b/src/Doctrine/Odm/State/Options.php index 459d6bc49ec..301b635b1ed 100644 --- a/src/Doctrine/Odm/State/Options.php +++ b/src/Doctrine/Odm/State/Options.php @@ -19,15 +19,17 @@ class Options extends CommonOptions implements OptionsInterface { /** - * @param mixed $handleLinks experimental callable, typed mixed as we may want a service name in the future + * @param mixed $handleLinks experimental callable, typed mixed as we may want a service name in the future + * @param mixed $transformFromDocument experimental callable, typed mixed as we may want a service name in the future * * @see LinksHandlerInterface */ public function __construct( protected ?string $documentClass = null, - mixed $handleLinks = null, + mixed $handleLinks = null, + mixed $transformFromDocument = null, ) { - parent::__construct(handleLinks: $handleLinks); + parent::__construct(handleLinks: $handleLinks, toResourceTransformer: $transformFromDocument); } public function getDocumentClass(): ?string @@ -42,4 +44,17 @@ public function withDocumentClass(?string $documentClass): self return $self; } + + public function getTransformDocument(): mixed + { + return $this->getToResourceTransformer(); + } + + public function withTransformDocument(mixed $transformDocument): self + { + $self = clone $this; + $self->toResourceTransformer = $transformDocument; + + return $self; + } } diff --git a/src/Doctrine/Orm/State/CollectionProvider.php b/src/Doctrine/Orm/State/CollectionProvider.php index ab2cb5a0810..f8daee3f084 100644 --- a/src/Doctrine/Orm/State/CollectionProvider.php +++ b/src/Doctrine/Orm/State/CollectionProvider.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Orm\State; use ApiPlatform\Doctrine\Common\State\LinksHandlerLocatorTrait; +use ApiPlatform\Doctrine\Common\State\ResourceTransformerLocatorTrait; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; @@ -35,6 +36,7 @@ final class CollectionProvider implements ProviderInterface { use LinksHandlerLocatorTrait; use LinksHandlerTrait; + use ResourceTransformerLocatorTrait; /** * @param QueryCollectionExtensionInterface[] $collectionExtensions @@ -43,6 +45,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource { $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; $this->handleLinksLocator = $handleLinksLocator; + $this->resourceTransformerLocator = $handleLinksLocator; $this->managerRegistry = $managerRegistry; } @@ -74,10 +77,16 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $extension->applyToCollection($queryBuilder, $queryNameGenerator, $entityClass, $operation, $context); if ($extension instanceof QueryResultCollectionExtensionInterface && $extension->supportsResult($entityClass, $operation, $context)) { - return $extension->getResult($queryBuilder, $entityClass, $operation, $context); + $result = $extension->getResult($queryBuilder, $entityClass, $operation, $context); + break; } } - return $queryBuilder->getQuery()->getResult(); + $result = $result ?? $queryBuilder->getQuery()->getResult(); + + return match ($transformer = $this->getToResourceTransformer($operation)) { + null => $result, + default => array_map($transformer, iterator_to_array($result)), + }; } } diff --git a/src/Doctrine/Orm/State/ItemProvider.php b/src/Doctrine/Orm/State/ItemProvider.php index 0a7f4862c89..16e6a4888e4 100644 --- a/src/Doctrine/Orm/State/ItemProvider.php +++ b/src/Doctrine/Orm/State/ItemProvider.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Doctrine\Orm\State; use ApiPlatform\Doctrine\Common\State\LinksHandlerLocatorTrait; +use ApiPlatform\Doctrine\Common\State\ResourceTransformerLocatorTrait; use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator; @@ -35,6 +36,7 @@ final class ItemProvider implements ProviderInterface { use LinksHandlerLocatorTrait; use LinksHandlerTrait; + use ResourceTransformerLocatorTrait; /** * @param QueryItemExtensionInterface[] $itemExtensions @@ -43,6 +45,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource { $this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory; $this->handleLinksLocator = $handleLinksLocator; + $this->resourceTransformerLocator = $handleLinksLocator; $this->managerRegistry = $managerRegistry; } @@ -80,10 +83,16 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $extension->applyToItem($queryBuilder, $queryNameGenerator, $entityClass, $uriVariables, $operation, $context); if ($extension instanceof QueryResultItemExtensionInterface && $extension->supportsResult($entityClass, $operation, $context)) { - return $extension->getResult($queryBuilder, $entityClass, $operation, $context); + $result = $extension->getResult($queryBuilder, $entityClass, $operation, $context); + break; } } - return $queryBuilder->getQuery()->getOneOrNullResult(); + $result = $result ?? $queryBuilder->getQuery()->getOneOrNullResult(); + + return match ($transformer = $this->getToResourceTransformer($operation)) { + null => $result, + default => $transformer($result), + }; } } diff --git a/src/Doctrine/Orm/State/Options.php b/src/Doctrine/Orm/State/Options.php index 3a9a46c3825..777ef189f60 100644 --- a/src/Doctrine/Orm/State/Options.php +++ b/src/Doctrine/Orm/State/Options.php @@ -19,15 +19,18 @@ class Options extends CommonOptions implements OptionsInterface { /** - * @param string|callable $handleLinks experimental callable, typed mixed as we may want a service name in the future + * @param string|callable $handleLinks experimental callable, typed mixed as we may want a service name in the future + * @param string|callable $transformFromEntity experimental callable, typed mixed as we may want a service name in the future * * @see LinksHandlerInterface */ public function __construct( protected ?string $entityClass = null, - mixed $handleLinks = null, + mixed $handleLinks = null, + mixed $transformFromEntity = null, + mixed $transformToEntity = null, ) { - parent::__construct(handleLinks: $handleLinks); + parent::__construct(handleLinks: $handleLinks, toResourceTransformer: $transformFromEntity, fromResourceTransformer: $transformToEntity); } public function getEntityClass(): ?string @@ -42,4 +45,31 @@ public function withEntityClass(?string $entityClass): self return $self; } + + public function getTransformFromEntity(): mixed + { + return $this->getToResourceTransformer(); + } + + public function withTransformFromEntity(mixed $transformFromEntity): self + { + $self = clone $this; + $self->toResourceTransformer = $transformFromEntity; + + return $self; + } + + public function getTransformToEntity(): mixed + { + return $this->getFromResourceTransformer(); + } + + public function withTransformToEntity(mixed $transformToEntity): self + { + $self = clone $this; + $self->fromResourceTransformer = $transformToEntity; + + return $self; + } + } diff --git a/tests/Behat/DoctrineContext.php b/tests/Behat/DoctrineContext.php index 4639644beb4..e24de9be09d 100644 --- a/tests/Behat/DoctrineContext.php +++ b/tests/Behat/DoctrineContext.php @@ -97,6 +97,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Document\SoMany as SoManyDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Taxon as TaxonDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel as ThirdLevelDocument; +use ApiPlatform\Tests\Fixtures\TestBundle\Document\TransformedDummyDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\UrlEncodedId as UrlEncodedIdDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\User as UserDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\VideoGame as VideoGameDocument; @@ -199,6 +200,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SymfonyUuidDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Taxon; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\TransformedDummyEntity; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\TreeDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\UrlEncodedId; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\User; @@ -2325,6 +2327,15 @@ public function thereAreIssue6039Users(): void $this->manager->flush(); } + /** + * @Given there is a TransformedDummy for date :date + */ + public function thereIsATransformedDummyEntity(string $date): void + { + $this->manager->persist($this->buildTransformedDummy(new \DateTimeImmutable($date))); + $this->manager->flush(); + } + private function isOrm(): bool { return null !== $this->schemaTool; @@ -2704,4 +2715,9 @@ private function buildLinkHandledDummy(string $slug): LinkHandledDummy|LinkHandl { return $this->isOrm() ? new LinkHandledDummy($slug) : new LinkHandledDummyDocument($slug); } + + private function buildTransformedDummy(\DateTimeImmutable $dateTime): TransformedDummyEntity|TransformedDummyDocument + { + return $this->isOrm() ? new TransformedDummyEntity($dateTime) : new TransformedDummyDocument($dateTime); + } } diff --git a/tests/Fixtures/TestBundle/ApiResource/TransformedDummyDocumentRessource.php b/tests/Fixtures/TestBundle/ApiResource/TransformedDummyDocumentRessource.php new file mode 100644 index 00000000000..bc55d335b55 --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/TransformedDummyDocumentRessource.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\ApiResource; + +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Tests\Fixtures\TestBundle\Document\TransformedDummyDocument; + +#[ApiResource( + operations : [ + new GetCollection(uriTemplate: '/transformed_dummy_document_ressources'), + new Get(uriTemplate: '/transformed_dummy_document_ressources/{id}'), + ], + stateOptions: new \ApiPlatform\Doctrine\Odm\State\Options( + documentClass: TransformedDummyDocument::class, + transformFromDocument: [self::class, 'transformToResource'], + ) +)] +class TransformedDummyDocumentRessource +{ + public ?int $id = null; + + public ?int $year = null; + + public static function transformToResource(TransformedDummyDocument $model): self + { + $resource = new self(); + $resource->id = $model->getId(); + $resource->year = (int) $model->getDate()->format('Y'); + + return $resource; + } +} diff --git a/tests/Fixtures/TestBundle/ApiResource/TransformedDummyEntityRessource.php b/tests/Fixtures/TestBundle/ApiResource/TransformedDummyEntityRessource.php new file mode 100644 index 00000000000..c234439144a --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/TransformedDummyEntityRessource.php @@ -0,0 +1,46 @@ + + * + * For 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\ApiResource; + +use ApiPlatform\Doctrine\Orm\State\Options; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\TransformedDummyEntity; + +#[ApiResource( + operations : [ + new GetCollection(uriTemplate: '/transformed_dummy_entity_ressources'), + new Get(uriTemplate: '/transformed_dummy_entity_ressources/{id}'), + ], + stateOptions: new Options( + entityClass: TransformedDummyEntity::class, + transformFromEntity: [self::class, 'transformToResource'], + ) +)] +class TransformedDummyEntityRessource +{ + public ?int $id = null; + + public ?int $year = null; + + public static function transformToResource(TransformedDummyEntity $model): self + { + $resource = new self(); + $resource->id = $model->getId(); + $resource->year = (int) $model->getDate()->format('Y'); + + return $resource; + } +} diff --git a/tests/Fixtures/TestBundle/Document/TransformedDummyDocument.php b/tests/Fixtures/TestBundle/Document/TransformedDummyDocument.php new file mode 100644 index 00000000000..d3511295cae --- /dev/null +++ b/tests/Fixtures/TestBundle/Document/TransformedDummyDocument.php @@ -0,0 +1,46 @@ + + * + * For 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 Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; + +#[ ODM\Document] +class TransformedDummyDocument +{ + #[ODM\Id(type: 'int', strategy: 'INCREMENT')] + private ?int $id = null; + + #[ODM\Field(type: 'date_immutable')] + private \DateTimeInterface $date; + + public function __construct(?\DateTimeInterface $date = null) + { + $this->setDate($date ?? new \DateTimeImmutable()); + } + + public function getDate(): \DateTimeInterface + { + return $this->date; + } + + public function setDate(\DateTimeInterface $date): void + { + $this->date = $date; + } + + public function getId(): ?int + { + return $this->id; + } +} diff --git a/tests/Fixtures/TestBundle/Entity/TransformedDummyEntity.php b/tests/Fixtures/TestBundle/Entity/TransformedDummyEntity.php new file mode 100644 index 00000000000..9ffe6d5aff0 --- /dev/null +++ b/tests/Fixtures/TestBundle/Entity/TransformedDummyEntity.php @@ -0,0 +1,49 @@ + + * + * For 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 Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; + +#[ORM\Entity] +class TransformedDummyEntity +{ + #[ORM\Column(type: 'integer')] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'AUTO')] + private ?int $id = null; + + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] + private \DateTimeInterface $date; + + public function __construct(?\DateTimeInterface $date = null) + { + $this->setDate($date ?? new \DateTimeImmutable()); + } + + public function getDate(): \DateTimeInterface + { + return $this->date; + } + + public function setDate(\DateTimeInterface $date): void + { + $this->date = $date; + } + + public function getId(): ?int + { + return $this->id; + } +}