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

PaginationExtension   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 10
eloc 51
dl 0
loc 94
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A isPaginationEnabled() 0 10 2
A __construct() 0 12 1
A getResult() 0 3 1
A supportsResult() 0 10 2
A applyToCollection() 0 28 4
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
 * This file is part of the API Platform project.
15
 *
16
 * (c) Kévin Dunglas <[email protected]>
17
 *
18
 * For the full copyright and license information, please view the LICENSE
19
 * file that was distributed with this source code.
20
 */
21
22
namespace ApiPlatform\Core\Bridge\Doctrine\MongoDB\Extension;
23
24
use ApiPlatform\Core\Bridge\Doctrine\MongoDB\Paginator;
25
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
26
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
27
use Doctrine\Common\Persistence\ManagerRegistry;
28
use Doctrine\ODM\MongoDB\Aggregation\Builder;
29
use Symfony\Component\HttpFoundation\Request;
30
use Symfony\Component\HttpFoundation\RequestStack;
31
32
/**
33
 * Applies pagination on the Doctrine query for resource collection when enabled.
34
 *
35
 * @author Kévin Dunglas <[email protected]>
36
 * @author Samuel ROZE <[email protected]>
37
 * @author Alan Poulain <[email protected]>
38
 */
39
final class PaginationExtension implements QueryResultExtensionInterface
40
{
41
    private $managerRegistry;
42
    private $requestStack;
43
    private $resourceMetadataFactory;
44
    private $enabled;
45
    private $clientEnabled;
46
    private $clientItemsPerPage;
47
    private $itemsPerPage;
48
    private $pageParameterName;
49
    private $enabledParameterName;
50
    private $itemsPerPageParameterName;
51
52
    public function __construct(ManagerRegistry $managerRegistry, RequestStack $requestStack, ResourceMetadataFactoryInterface $resourceMetadataFactory, bool $enabled = true, bool $clientEnabled = false, bool $clientItemsPerPage = false, int $itemsPerPage = 30, string $pageParameterName = 'page', string $enabledParameterName = 'pagination', string $itemsPerPageParameterName = 'itemsPerPage')
53
    {
54
        $this->managerRegistry = $managerRegistry;
55
        $this->requestStack = $requestStack;
56
        $this->resourceMetadataFactory = $resourceMetadataFactory;
57
        $this->enabled = $enabled;
58
        $this->clientEnabled = $clientEnabled;
59
        $this->clientItemsPerPage = $clientItemsPerPage;
60
        $this->itemsPerPage = $itemsPerPage;
61
        $this->pageParameterName = $pageParameterName;
62
        $this->enabledParameterName = $enabledParameterName;
63
        $this->itemsPerPageParameterName = $itemsPerPageParameterName;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, string $operationName = null)
70
    {
71
        $request = $this->requestStack->getCurrentRequest();
72
        if (null === $request) {
73
            return;
74
        }
75
76
        $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
77
        if (!$this->isPaginationEnabled($request, $resourceMetadata, $operationName)) {
78
            return;
79
        }
80
81
        $itemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', $this->itemsPerPage, true);
82
        if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) {
83
            $itemsPerPage = (int) $request->query->get($this->itemsPerPageParameterName, $itemsPerPage);
84
        }
85
86
        $repository = $this->managerRegistry->getManagerForClass($resourceClass)->getRepository($resourceClass);
87
        $aggregationBuilder
88
            ->facet()
89
            ->field('results')->pipeline(
90
                $repository->createAggregationBuilder()
91
                    ->skip(($request->query->get($this->pageParameterName, 1) - 1) * $itemsPerPage)
92
                    ->limit($itemsPerPage)
93
            )
94
            ->field('count')->pipeline(
95
                $repository->createAggregationBuilder()
96
                    ->count('count')
97
            );
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    public function supportsResult(string $resourceClass, string $operationName = null): bool
104
    {
105
        $request = $this->requestStack->getCurrentRequest();
106
        if (null === $request) {
107
            return false;
108
        }
109
110
        $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
111
112
        return $this->isPaginationEnabled($request, $resourceMetadata, $operationName);
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function getResult(Builder $aggregationBuilder, string $resourceClass)
119
    {
120
        return new Paginator($aggregationBuilder->execute(), $this->managerRegistry->getManagerForClass($resourceClass)->getUnitOfWork(), $resourceClass);
0 ignored issues
show
Bug introduced by
The method getUnitOfWork() does not exist on Doctrine\Common\Persistence\ObjectManager. It seems like you code against a sub-type of said class. However, the method does not exist in Doctrine\Common\Persistence\ObjectManagerDecorator. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

120
        return new Paginator($aggregationBuilder->execute(), $this->managerRegistry->getManagerForClass($resourceClass)->/** @scrutinizer ignore-call */ getUnitOfWork(), $resourceClass);
Loading history...
121
    }
122
123
    private function isPaginationEnabled(Request $request, ResourceMetadata $resourceMetadata, string $operationName = null): bool
124
    {
125
        $enabled = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_enabled', $this->enabled, true);
126
        $clientEnabled = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_enabled', $this->clientEnabled, true);
127
128
        if ($clientEnabled) {
129
            $enabled = filter_var($request->query->get($this->enabledParameterName, $enabled), FILTER_VALIDATE_BOOLEAN);
130
        }
131
132
        return $enabled;
133
    }
134
}
135