Completed
Pull Request — master (#1073)
by Vincent
04:40 queued 45s
created

Pager::countSinglePrimaryKey()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
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(): int
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): array
60
    {
61
        return $this->getQuery()->execute([], $hydrationMode);
62
    }
63
64
    public function init(): void
65
    {
66
        $this->resetIterator();
67
68
        $this->setNbResults($this->computeNbResult());
69
70
        $this->getQuery()->setFirstResult(null);
71
        $this->getQuery()->setMaxResults(null);
72
73
        if (\count($this->getParameters()) > 0) {
74
            $this->getQuery()->setParameters($this->getParameters());
75
        }
76
77
        if (0 === $this->getPage() || 0 === $this->getMaxPerPage() || 0 === $this->getNbResults()) {
78
            $this->setLastPage(0);
79
        } else {
80
            $offset = ($this->getPage() - 1) * $this->getMaxPerPage();
81
82
            $this->setLastPage((int) ceil($this->getNbResults() / $this->getMaxPerPage()));
83
84
            $this->getQuery()->setFirstResult($offset);
85
            $this->getQuery()->setMaxResults($this->getMaxPerPage());
86
        }
87
    }
88
89
    private function countCompositePrimaryKey(ProxyQueryInterface $countQuery): void
90
    {
91
        $rootAliases = current($countQuery->getRootAliases());
92
        $countQuery->setParameter('concat_separator', self::CONCAT_SEPARATOR);
93
94
        $columns = $rootAliases.'.'.implode(', :concat_separator, '.$rootAliases.'.', $this->getCountColumn());
95
96
        $countQuery->select(sprintf(
97
            'count(%s concat(%s)) as cnt',
98
            $countQuery instanceof ProxyQuery && !$countQuery->isDistinct() ? null : 'DISTINCT',
99
            $columns
100
        ));
101
    }
102
103
    private function countSinglePrimaryKey(ProxyQueryInterface $countQuery): void
104
    {
105
        $countQuery->select(sprintf(
106
            'count(%s %s.%s) as cnt',
107
            $countQuery instanceof ProxyQuery && !$countQuery->isDistinct() ? null : 'DISTINCT',
108
            current($countQuery->getRootAliases()),
109
            current($this->getCountColumn())
110
        ));
111
    }
112
}
113