Pager::countCompositePrimaryKey()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 3
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\DoctrineORMAdminBundle\Datagrid;
15
16
use Doctrine\ORM\Query;
17
use Sonata\AdminBundle\Datagrid\Pager as BasePager;
18
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
19
20
/**
21
 * Doctrine pager class.
22
 *
23
 * @author Jonathan H. Wage <[email protected]>
24
 */
25
class Pager extends BasePager
26
{
27
    /**
28
     * Use separator in CONCAT() function for correct determinate similar records.
29
     */
30
    public const CONCAT_SEPARATOR = '|';
31
32
    /**
33
     * NEXT_MAJOR: remove this property.
34
     *
35
     * @deprecated since sonata-project/doctrine-orm-admin-bundle 2.4 and will be removed in 4.0
36
     */
37
    protected $queryBuilder = null;
38
39
    public function computeNbResult()
40
    {
41
        $countQuery = clone $this->getQuery();
42
43
        if (\count($this->getParameters()) > 0) {
44
            $countQuery->setParameters($this->getParameters());
45
        }
46
47
        if (\count($this->getCountColumn()) > 1) {
48
            $this->countCompositePrimaryKey($countQuery);
49
        } else {
50
            $this->countSinglePrimaryKey($countQuery);
51
        }
52
53
        return array_sum(array_column(
54
            $countQuery->resetDQLPart('orderBy')->getQuery()->getResult(Query::HYDRATE_SCALAR),
55
            'cnt'
56
        ));
57
    }
58
59
    public function getResults($hydrationMode = Query::HYDRATE_OBJECT)
60
    {
61
        return $this->getQuery()->execute([], $hydrationMode);
62
    }
63
64
    public function getQuery()
65
    {
66
        return $this->query;
67
    }
68
69
    public function init(): void
70
    {
71
        $this->resetIterator();
72
73
        $this->setNbResults($this->computeNbResult());
74
75
        $this->getQuery()->setFirstResult(null);
76
        $this->getQuery()->setMaxResults(null);
77
78
        if (\count($this->getParameters()) > 0) {
79
            $this->getQuery()->setParameters($this->getParameters());
80
        }
81
82
        if (0 === $this->getPage() || 0 === $this->getMaxPerPage() || 0 === $this->getNbResults()) {
83
            $this->setLastPage(0);
84
        } else {
85
            $offset = ($this->getPage() - 1) * $this->getMaxPerPage();
86
87
            $this->setLastPage((int) ceil($this->getNbResults() / $this->getMaxPerPage()));
88
89
            $this->getQuery()->setFirstResult($offset);
90
            $this->getQuery()->setMaxResults($this->getMaxPerPage());
91
        }
92
    }
93
94
    private function countCompositePrimaryKey(ProxyQueryInterface $countQuery): void
95
    {
96
        $rootAliases = current($countQuery->getRootAliases());
97
        $countQuery->setParameter('concat_separator', self::CONCAT_SEPARATOR);
98
99
        $columns = $rootAliases.'.'.implode(', :concat_separator, '.$rootAliases.'.', $this->getCountColumn());
100
101
        $countQuery->select(sprintf(
102
            'count(%s concat(%s)) as cnt',
103
            $countQuery instanceof ProxyQuery && !$countQuery->isDistinct() ? null : 'DISTINCT',
104
            $columns
105
        ));
106
    }
107
108
    private function countSinglePrimaryKey(ProxyQueryInterface $countQuery): void
109
    {
110
        $countQuery->select(sprintf(
111
            'count(%s %s.%s) as cnt',
112
            $countQuery instanceof ProxyQuery && !$countQuery->isDistinct() ? null : 'DISTINCT',
113
            current($countQuery->getRootAliases()),
114
            current($this->getCountColumn())
115
        ));
116
    }
117
}
118