Passed
Pull Request — master (#2144)
by Alan
03:39
created

PaginationExtension::getResult()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 4
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension;
15
16
use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator;
17
use ApiPlatform\Core\DataProvider\Pagination;
18
use ApiPlatform\Core\Exception\RuntimeException;
19
use Doctrine\Common\Persistence\ManagerRegistry;
20
use Doctrine\ODM\MongoDB\Aggregation\Builder;
21
use Doctrine\ODM\MongoDB\DocumentManager;
22
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
23
24
/**
25
 * Applies pagination on the Doctrine aggregation for resource collection when enabled.
26
 *
27
 * @experimental
28
 *
29
 * @author Kévin Dunglas <[email protected]>
30
 * @author Samuel ROZE <[email protected]>
31
 * @author Alan Poulain <[email protected]>
32
 */
33
final class PaginationExtension implements AggregationResultCollectionExtensionInterface
34
{
35
    private $managerRegistry;
36
    private $pagination;
37
38
    public function __construct(ManagerRegistry $managerRegistry, Pagination $pagination)
39
    {
40
        $this->managerRegistry = $managerRegistry;
41
        $this->pagination = $pagination;
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     *
47
     * @throws RuntimeException
48
     */
49
    public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array &$context = [])
50
    {
51
        if (!$this->pagination->isEnabled($resourceClass, $operationName, $context)) {
52
            return;
53
        }
54
55
        [, $offset, $limit] = $this->pagination->getPagination($resourceClass, $operationName, $context);
56
57
        $manager = $this->managerRegistry->getManagerForClass($resourceClass);
58
        if (!$manager instanceof DocumentManager) {
59
            throw new RuntimeException(sprintf('The manager for "%s" must be an instance of "%s".', $resourceClass, DocumentManager::class));
60
        }
61
62
        $repository = $manager->getRepository($resourceClass);
63
        if (!$repository instanceof DocumentRepository) {
64
            throw new RuntimeException(sprintf('The repository for "%s" must be an instance of "%s".', $resourceClass, DocumentRepository::class));
65
        }
66
67
        $aggregationBuilder
68
            ->facet()
69
            ->field('results')->pipeline(
70
                $repository->createAggregationBuilder()
71
                    ->skip($offset)
72
                    ->limit($limit)
73
            )
74
            ->field('count')->pipeline(
75
                $repository->createAggregationBuilder()
76
                    ->count('count')
77
            );
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function supportsResult(string $resourceClass, string $operationName = null, array $context = []): bool
84
    {
85
        return $this->pagination->isEnabled($resourceClass, $operationName, $context);
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     *
91
     * @throws RuntimeException
92
     */
93
    public function getResult(Builder $aggregationBuilder, string $resourceClass, string $operationName = null, array $context = [])
94
    {
95
        $manager = $this->managerRegistry->getManagerForClass($resourceClass);
96
        if (!$manager instanceof DocumentManager) {
97
            throw new RuntimeException(sprintf('The manager for "%s" must be an instance of "%s".', $resourceClass, DocumentManager::class));
98
        }
99
100
        return new Paginator($aggregationBuilder->execute(), $manager->getUnitOfWork(), $resourceClass, $aggregationBuilder->getPipeline());
101
    }
102
}
103