Skip to content

Commit 054b597

Browse files
committed
bug(pagination): implement MappedObjectPaginator for fixing pagination on mapped data
1 parent 8f4bc08 commit 054b597

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
/*
3+
* This file is part of the API Platform project.
4+
*
5+
* (c) Kévin Dunglas <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace ApiPlatform\State\Pagination;
14+
15+
use Symfony\Component\ObjectMapper\ObjectMapperInterface;
16+
17+
final class MappedObjectPaginator implements \IteratorAggregate, PaginatorInterface
18+
{
19+
public function __construct(
20+
private readonly iterable $entities,
21+
private readonly ObjectMapperInterface $mapper,
22+
private readonly string $resourceClass,
23+
private readonly float $totalItems = 0.0,
24+
private readonly float $currentPage = 1.0,
25+
private readonly float $lastPage = 1.0,
26+
private readonly float $itemsPerPage = 30.0,
27+
) {}
28+
29+
public function count(): int
30+
{
31+
return (int) $this->totalItems;
32+
}
33+
34+
public function getLastPage(): float
35+
{
36+
return $this->lastPage;
37+
}
38+
39+
public function getTotalItems(): float
40+
{
41+
return $this->totalItems;
42+
}
43+
44+
public function getCurrentPage(): float
45+
{
46+
return $this->currentPage;
47+
}
48+
49+
public function getItemsPerPage(): float
50+
{
51+
return $this->itemsPerPage;
52+
}
53+
54+
public function getIterator(): \Traversable
55+
{
56+
foreach ($this->entities as $entity) {
57+
yield $this->mapper->map($entity, $this->resourceClass);
58+
}
59+
}
60+
}

src/State/Provider/ObjectMapperProvider.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
use ApiPlatform\Metadata\Operation;
1717
use ApiPlatform\Metadata\Util\CloneTrait;
18-
use ApiPlatform\State\Pagination\ArrayPaginator;
18+
use ApiPlatform\State\Pagination\MappedObjectPaginator;
1919
use ApiPlatform\State\Pagination\PaginatorInterface;
2020
use ApiPlatform\State\ProviderInterface;
2121
use Symfony\Component\ObjectMapper\ObjectMapperInterface;
@@ -52,7 +52,15 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
5252
$request?->attributes->set('mapped_data', $data);
5353

5454
if ($data instanceof PaginatorInterface) {
55-
$data = new ArrayPaginator(array_map(fn ($v) => $this->objectMapper->map($v, $operation->getClass()), iterator_to_array($data)), 0, \count($data));
55+
$data = new MappedObjectPaginator(
56+
iterator_to_array($data),
57+
$this->objectMapper,
58+
$operation->getClass(),
59+
$data->getTotalItems(),
60+
$data->getCurrentPage(),
61+
$data->getLastPage(),
62+
$data->getItemsPerPage(),
63+
);
5664
} elseif (\is_array($data)) {
5765
foreach ($data as &$v) {
5866
if (\is_object($v)) {

0 commit comments

Comments
 (0)