diff --git a/src/State/Pagination/MappedObjectPaginator.php b/src/State/Pagination/MappedObjectPaginator.php new file mode 100644 index 00000000000..6ac79c65269 --- /dev/null +++ b/src/State/Pagination/MappedObjectPaginator.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\State\Pagination; + +use Symfony\Component\ObjectMapper\ObjectMapperInterface; + +final class MappedObjectPaginator implements \IteratorAggregate, PaginatorInterface +{ + public function __construct( + private readonly iterable $entities, + private readonly ObjectMapperInterface $mapper, + private readonly string $resourceClass, + private readonly float $totalItems = 0.0, + private readonly float $currentPage = 1.0, + private readonly float $lastPage = 1.0, + private readonly float $itemsPerPage = 30.0, + ) { + } + + public function count(): int + { + return (int) $this->totalItems; + } + + public function getLastPage(): float + { + return $this->lastPage; + } + + public function getTotalItems(): float + { + return $this->totalItems; + } + + public function getCurrentPage(): float + { + return $this->currentPage; + } + + public function getItemsPerPage(): float + { + return $this->itemsPerPage; + } + + public function getIterator(): \Traversable + { + foreach ($this->entities as $entity) { + yield $this->mapper->map($entity, $this->resourceClass); + } + } +} diff --git a/src/State/Provider/ObjectMapperProvider.php b/src/State/Provider/ObjectMapperProvider.php index 59628724d58..bc210571468 100644 --- a/src/State/Provider/ObjectMapperProvider.php +++ b/src/State/Provider/ObjectMapperProvider.php @@ -15,7 +15,7 @@ use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Util\CloneTrait; -use ApiPlatform\State\Pagination\ArrayPaginator; +use ApiPlatform\State\Pagination\MappedObjectPaginator; use ApiPlatform\State\Pagination\PaginatorInterface; use ApiPlatform\State\ProviderInterface; use Symfony\Component\ObjectMapper\ObjectMapperInterface; @@ -52,7 +52,15 @@ public function provide(Operation $operation, array $uriVariables = [], array $c $request?->attributes->set('mapped_data', $data); if ($data instanceof PaginatorInterface) { - $data = new ArrayPaginator(array_map(fn ($v) => $this->objectMapper->map($v, $operation->getClass()), iterator_to_array($data)), 0, \count($data)); + $data = new MappedObjectPaginator( + iterator_to_array($data), + $this->objectMapper, + $operation->getClass(), + $data->getTotalItems(), + $data->getCurrentPage(), + $data->getLastPage(), + $data->getItemsPerPage(), + ); } elseif (\is_array($data)) { foreach ($data as &$v) { if (\is_object($v)) { diff --git a/tests/State/Provider/ObjectMapperProviderTest.php b/tests/State/Provider/ObjectMapperProviderTest.php index 8b5b3d456dd..201f10fc4c6 100644 --- a/tests/State/Provider/ObjectMapperProviderTest.php +++ b/tests/State/Provider/ObjectMapperProviderTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Metadata\Get; use ApiPlatform\State\Pagination\ArrayPaginator; +use ApiPlatform\State\Pagination\MappedObjectPaginator; use ApiPlatform\State\Provider\ObjectMapperProvider; use ApiPlatform\State\ProviderInterface; use PHPUnit\Framework\TestCase; @@ -160,7 +161,7 @@ public function testProvideMapsPaginator(): void $provider = new ObjectMapperProvider($objectMapper, $decorated); $result = $provider->provide($operation); - $this->assertInstanceOf(ArrayPaginator::class, $result); + $this->assertInstanceOf(MappedObjectPaginator::class, $result); $items = iterator_to_array($result); $this->assertCount(2, $items); $this->assertSame($targetResource1, $items[0]); @@ -192,7 +193,7 @@ public function testProvideMapsEmptyPaginator(): void $provider = new ObjectMapperProvider($objectMapper, $decorated); $result = $provider->provide($operation); - $this->assertInstanceOf(ArrayPaginator::class, $result); + $this->assertInstanceOf(MappedObjectPaginator::class, $result); $this->assertCount(0, iterator_to_array($result)); } }