Skip to content

Commit

Permalink
feat: add a second hook for resource to entity or document transforma…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
mrossard committed Jan 20, 2025
1 parent 3b26b70 commit 9f4cb1a
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 84 deletions.
43 changes: 0 additions & 43 deletions src/Doctrine/Common/State/ModelTransformerLocatorTrait.php

This file was deleted.

26 changes: 21 additions & 5 deletions src/Doctrine/Common/State/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +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 $transformModel = null,
protected mixed $toResourceTransformer = null,
protected mixed $fromResourceTransformer = null,
) {
}

Expand All @@ -39,15 +42,28 @@ public function withHandleLinks(mixed $handleLinks): self
return $self;
}

public function getTransformModel(): mixed
public function getToResourceTransformer(): mixed
{
return $this->transformModel;
return $this->toResourceTransformer;
}

public function withTransformModel(mixed $transformModel): self
public function withToResourceTransformer(mixed $toResourceTransformer): self
{
$self = clone $this;
$self->transformModel = $transformModel;
$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;
}
Expand Down
1 change: 1 addition & 0 deletions src/Doctrine/Common/State/PersistProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ final class PersistProcessor implements ProcessorInterface
{
use ClassInfoTrait;
use LinksHandlerTrait;
use ResourceTransformerLocatorTrait;

public function __construct(private readonly ManagerRegistry $managerRegistry)
{
Expand Down
61 changes: 61 additions & 0 deletions src/Doctrine/Common/State/ResourceTransformerLocatorTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For 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;
}
}
8 changes: 4 additions & 4 deletions src/Doctrine/Odm/State/CollectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace ApiPlatform\Doctrine\Odm\State;

use ApiPlatform\Doctrine\Common\State\LinksHandlerLocatorTrait;
use ApiPlatform\Doctrine\Common\State\ModelTransformerLocatorTrait;
use ApiPlatform\Doctrine\Common\State\ResourceTransformerLocatorTrait;
use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface;
use ApiPlatform\Doctrine\Odm\Extension\AggregationResultCollectionExtensionInterface;
use ApiPlatform\Metadata\Exception\RuntimeException;
Expand All @@ -33,7 +33,7 @@ final class CollectionProvider implements ProviderInterface
{
use LinksHandlerLocatorTrait;
use LinksHandlerTrait;
use ModelTransformerLocatorTrait;
use ResourceTransformerLocatorTrait;

/**
* @param AggregationCollectionExtensionInterface[] $collectionExtensions
Expand All @@ -42,7 +42,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource
{
$this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
$this->handleLinksLocator = $handleLinksLocator;
$this->transformEntityLocator = $handleLinksLocator;
$this->resourceTransformerLocator = $handleLinksLocator;
$this->managerRegistry = $managerRegistry;
}

Expand Down Expand Up @@ -83,7 +83,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c

$result = $result ?? $aggregationBuilder->hydrate($documentClass)->execute($executeOptions);

return match ($transformer = $this->getEntityTransformer($operation)) {
return match ($transformer = $this->getToResourceTransformer($operation)) {
null => $result,
default => array_map($transformer, iterator_to_array($result)),
};
Expand Down
8 changes: 4 additions & 4 deletions src/Doctrine/Odm/State/ItemProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace ApiPlatform\Doctrine\Odm\State;

use ApiPlatform\Doctrine\Common\State\LinksHandlerLocatorTrait;
use ApiPlatform\Doctrine\Common\State\ModelTransformerLocatorTrait;
use ApiPlatform\Doctrine\Common\State\ResourceTransformerLocatorTrait;
use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface;
use ApiPlatform\Doctrine\Odm\Extension\AggregationResultItemExtensionInterface;
use ApiPlatform\Metadata\Exception\RuntimeException;
Expand All @@ -36,7 +36,7 @@ final class ItemProvider implements ProviderInterface
{
use LinksHandlerLocatorTrait;
use LinksHandlerTrait;
use ModelTransformerLocatorTrait;
use ResourceTransformerLocatorTrait;

/**
* @param AggregationItemExtensionInterface[] $itemExtensions
Expand All @@ -45,7 +45,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource
{
$this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
$this->handleLinksLocator = $handleLinksLocator;
$this->transformEntityLocator = $handleLinksLocator;
$this->resourceTransformerLocator = $handleLinksLocator;
$this->managerRegistry = $managerRegistry;
}

Expand Down Expand Up @@ -90,7 +90,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c

$result = $result ?? ($aggregationBuilder->hydrate($documentClass)->execute($executeOptions)->current() ?: null);

return match ($transformer = $this->getEntityTransformer($operation)) {
return match ($transformer = $this->getToResourceTransformer($operation)) {
null => $result,
default => (null !== $result) ? $transformer($result) : null,
};
Expand Down
12 changes: 6 additions & 6 deletions src/Doctrine/Odm/State/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ 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 $transformDocument 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 $transformDocument = null,
mixed $handleLinks = null,
mixed $transformFromDocument = null,
) {
parent::__construct(handleLinks: $handleLinks, transformModel: $transformDocument);
parent::__construct(handleLinks: $handleLinks, toResourceTransformer: $transformFromDocument);
}

public function getDocumentClass(): ?string
Expand All @@ -47,13 +47,13 @@ public function withDocumentClass(?string $documentClass): self

public function getTransformDocument(): mixed
{
return $this->getTransformModel();
return $this->getToResourceTransformer();
}

public function withTransformDocument(mixed $transformDocument): self
{
$self = clone $this;
$self->transformModel = $transformDocument;
$self->toResourceTransformer = $transformDocument;

return $self;
}
Expand Down
8 changes: 4 additions & 4 deletions src/Doctrine/Orm/State/CollectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace ApiPlatform\Doctrine\Orm\State;

use ApiPlatform\Doctrine\Common\State\LinksHandlerLocatorTrait;
use ApiPlatform\Doctrine\Common\State\ModelTransformerLocatorTrait;
use ApiPlatform\Doctrine\Common\State\ResourceTransformerLocatorTrait;
use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator;
Expand All @@ -36,7 +36,7 @@ final class CollectionProvider implements ProviderInterface
{
use LinksHandlerLocatorTrait;
use LinksHandlerTrait;
use ModelTransformerLocatorTrait;
use ResourceTransformerLocatorTrait;

/**
* @param QueryCollectionExtensionInterface[] $collectionExtensions
Expand All @@ -45,7 +45,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource
{
$this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
$this->handleLinksLocator = $handleLinksLocator;
$this->transformEntityLocator = $handleLinksLocator;
$this->resourceTransformerLocator = $handleLinksLocator;
$this->managerRegistry = $managerRegistry;
}

Expand Down Expand Up @@ -84,7 +84,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c

$result = $result ?? $queryBuilder->getQuery()->getResult();

return match ($transformer = $this->getEntityTransformer($operation)) {
return match ($transformer = $this->getToResourceTransformer($operation)) {
null => $result,
default => array_map($transformer, iterator_to_array($result)),
};
Expand Down
8 changes: 4 additions & 4 deletions src/Doctrine/Orm/State/ItemProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace ApiPlatform\Doctrine\Orm\State;

use ApiPlatform\Doctrine\Common\State\LinksHandlerLocatorTrait;
use ApiPlatform\Doctrine\Common\State\ModelTransformerLocatorTrait;
use ApiPlatform\Doctrine\Common\State\ResourceTransformerLocatorTrait;
use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface;
use ApiPlatform\Doctrine\Orm\Extension\QueryResultItemExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator;
Expand All @@ -36,7 +36,7 @@ final class ItemProvider implements ProviderInterface
{
use LinksHandlerLocatorTrait;
use LinksHandlerTrait;
use ModelTransformerLocatorTrait;
use ResourceTransformerLocatorTrait;

/**
* @param QueryItemExtensionInterface[] $itemExtensions
Expand All @@ -45,7 +45,7 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource
{
$this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
$this->handleLinksLocator = $handleLinksLocator;
$this->transformEntityLocator = $handleLinksLocator;
$this->resourceTransformerLocator = $handleLinksLocator;
$this->managerRegistry = $managerRegistry;
}

Expand Down Expand Up @@ -90,7 +90,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c

$result = $result ?? $queryBuilder->getQuery()->getOneOrNullResult();

return match ($transformer = $this->getEntityTransformer($operation)) {
return match ($transformer = $this->getToResourceTransformer($operation)) {
null => $result,
default => $transformer($result),
};
Expand Down
31 changes: 23 additions & 8 deletions src/Doctrine/Orm/State/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ 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 $transformEntity 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 $transformEntity = null,
mixed $handleLinks = null,
mixed $transformFromEntity = null,
mixed $transformToEntity = null,
) {
parent::__construct(handleLinks: $handleLinks, transformModel: $transformEntity);
parent::__construct(handleLinks: $handleLinks, toResourceTransformer: $transformFromEntity, fromResourceTransformer: $transformToEntity);
}

public function getEntityClass(): ?string
Expand All @@ -45,16 +46,30 @@ public function withEntityClass(?string $entityClass): self
return $self;
}

public function getTransformDocument(): mixed
public function getTransformFromEntity(): mixed
{
return $this->getTransformModel();
return $this->getToResourceTransformer();
}

public function withTransformDocument(mixed $transformEntity): self
public function withTransformFromEntity(mixed $transformFromEntity): self
{
$self = clone $this;
$self->transformModel = $transformEntity;
$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;
}

}
Loading

0 comments on commit 9f4cb1a

Please sign in to comment.