Completed
Pull Request — master (#2)
by Kevin
01:41
created

ORMQueryResult::count()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 6
1
<?php
2
3
namespace Zenstruck\Porpaginas\Doctrine;
4
5
use Doctrine\ORM\Query;
6
use Doctrine\ORM\QueryBuilder;
7
use Doctrine\ORM\Tools\Pagination\Paginator;
8
use Zenstruck\Porpaginas\Callback\CallbackPage;
9
use Zenstruck\Porpaginas\Page;
10
use Zenstruck\Porpaginas\Result;
11
12
final class ORMQueryResult implements Result
13
{
14
    private $query;
15
    private $fetchCollection;
16
    private $useOutputWalkers;
17
    private $count;
18
19
    /**
20
     * @param Query|QueryBuilder $query
21
     * @param bool|null          $useOutputWalkers Set to false if query contains only columns
22
     */
23
    public function __construct($query, bool $fetchCollection = true, $useOutputWalkers = null)
24
    {
25
        if ($query instanceof QueryBuilder) {
26
            $query = $query->getQuery();
27
        }
28
29
        $this->query = $query;
30
        $this->fetchCollection = $fetchCollection;
31
        $this->useOutputWalkers = $useOutputWalkers;
32
    }
33
34
    public function take(int $offset, int $limit): Page
35
    {
36
        return new CallbackPage(
37
            function ($offset, $limit) {
38
                return \iterator_to_array($this->createPaginator($offset, $limit));
39
            },
40
            [$this, 'count'],
41
            $offset,
42
            $limit
43
        );
44
    }
45
46
    public function count(): int
47
    {
48
        if (null !== $this->count) {
49
            return $this->count;
50
        }
51
52
        return $this->count = \count($this->paginatorFor($this->query));
53
    }
54
55
    public function getIterator(): \Traversable
56
    {
57
        $logger = $this->query->getEntityManager()->getConfiguration()->getSQLLogger();
58
        $this->query->getEntityManager()->getConfiguration()->setSQLLogger(null);
59
60
        foreach ($this->query->iterate() as $key => $value) {
61
            yield $key => IterableQueryResultNormalizer::normalize($value);
62
63
            $this->query->getEntityManager()->clear();
64
        }
65
66
        $this->query->getEntityManager()->getConfiguration()->setSQLLogger($logger);
67
    }
68
69 6
    public function batchIterator(int $batchSize = 100): ORMCountableBatchProcessor
70
    {
71
        return new ORMCountableBatchProcessor(
72
            new class($this->query, $this) implements \IteratorAggregate, \Countable {
73
                private $query;
74
                private $result;
75
76
                public function __construct(Query $query, ORMQueryResult $result)
77
                {
78 6
                    $this->query = $query;
79 6
                    $this->result = $result;
80 6
                }
81
82
                public function getIterator(): \Traversable
83
                {
84 6
                    return $this->query->iterate();
85
                }
86
87
                public function count(): int
88
                {
89 6
                    return $this->result->count();
90
                }
91
            },
92 6
            $this->query->getEntityManager(),
93
            $batchSize
94
        );
95
    }
96
97 24
    private function createPaginator(int $offset, int $limit): Paginator
98
    {
99 24
        $query = clone $this->query;
100 24
        $query->setParameters($this->query->getParameters());
101
102 24
        foreach ($this->query->getHints() as $name => $value) {
103 8
            $query->setHint($name, $value);
104
        }
105
106 24
        $query->setFirstResult($offset)->setMaxResults($limit);
107
108 24
        return $this->paginatorFor($query);
109
    }
110
111 34
    private function paginatorFor(Query $query): Paginator
112
    {
113 34
        return (new Paginator($query, $this->fetchCollection))->setUseOutputWalkers($this->useOutputWalkers);
114
    }
115
}
116