Completed
Pull Request — master (#1240)
by Maksim
03:38
created

Provider::fetchSlice()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 30
ccs 0
cts 16
cp 0
rs 8.5806
cc 4
eloc 17
nc 3
nop 3
crap 20
1
<?php
2
3
/*
4
 * This file is part of the FOSElasticaBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
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
namespace FOS\ElasticaBundle\Doctrine\ORM;
13
14
use Doctrine\ORM\QueryBuilder;
15
use FOS\ElasticaBundle\Doctrine\AbstractProvider;
16
use FOS\ElasticaBundle\Exception\InvalidArgumentTypeException;
17
use FOS\ElasticaBundle\Provider\ProviderV2Interface;
18
use Pagerfanta\Adapter\CallbackAdapter;
19
use Pagerfanta\Pagerfanta;
20
21
class Provider extends AbstractProvider implements ProviderV2Interface
22
{
23
    const ENTITY_ALIAS = 'a';
24
25
    /**
26
     * Disables logging and returns the logger that was previously set.
27
     *
28
     * @return mixed
29
     */
30
    protected function disableLogging()
31
    {
32
        $configuration = $this->managerRegistry
33
            ->getManagerForClass($this->objectClass)
34
            ->getConnection()
35
            ->getConfiguration();
36
37
        $logger = $configuration->getSQLLogger();
38
        $configuration->setSQLLogger(null);
39
40
        return $logger;
41
    }
42
43
    /**
44
     * Reenables the logger with the previously returned logger from disableLogging();.
45
     *
46
     * @param mixed $logger
47
     *
48
     * @return mixed
49
     */
50
    protected function enableLogging($logger)
51
    {
52
        $configuration = $this->managerRegistry
53
            ->getManagerForClass($this->objectClass)
54
            ->getConnection()
55
            ->getConfiguration();
56
57
        $configuration->setSQLLogger($logger);
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    protected function countObjects($queryBuilder)
64
    {
65
        if (!$queryBuilder instanceof QueryBuilder) {
66
            throw new InvalidArgumentTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
0 ignored issues
show
Documentation introduced by
$queryBuilder is of type object, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
67
        }
68
69
        /* Clone the query builder before altering its field selection and DQL,
70
         * lest we leave the query builder in a bad state for fetchSlice().
71
         */
72
        $qb = clone $queryBuilder;
73
        $rootAliases = $queryBuilder->getRootAliases();
74
75
        return $qb
76
            ->select($qb->expr()->count($rootAliases[0]))
77
            // Remove ordering for efficiency; it doesn't affect the count
78
            ->resetDQLPart('orderBy')
79
            ->getQuery()
80
            ->getSingleScalarResult();
81
    }
82
83
    /**
84
     * This method should remain in sync with SliceFetcher::fetch until it is deprecated and removed.
85
     *
86
     * {@inheritdoc}
87
     */
88
    protected function fetchSlice($queryBuilder, $limit, $offset)
89
    {
90
        if (!$queryBuilder instanceof QueryBuilder) {
91
            throw new InvalidArgumentTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
0 ignored issues
show
Documentation introduced by
$queryBuilder is of type object, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
92
        }
93
94
        /*
95
         * An orderBy DQL  part is required to avoid fetching the same row twice.
96
         * @see http://stackoverflow.com/questions/6314879/does-limit-offset-length-require-order-by-for-pagination
97
         * @see http://www.postgresql.org/docs/current/static/queries-limit.html
98
         * @see http://www.sqlite.org/lang_select.html#orderby
99
         */
100
        $orderBy = $queryBuilder->getDQLPart('orderBy');
101
        if (empty($orderBy)) {
102
            $rootAliases = $queryBuilder->getRootAliases();
103
            $identifierFieldNames = $this->managerRegistry
104
                ->getManagerForClass($this->objectClass)
105
                ->getClassMetadata($this->objectClass)
106
                ->getIdentifierFieldNames();
107
            foreach ($identifierFieldNames as $fieldName) {
108
                $queryBuilder->addOrderBy($rootAliases[0].'.'.$fieldName);
109
            }
110
        }
111
112
        return $queryBuilder
113
            ->setFirstResult($offset)
114
            ->setMaxResults($limit)
115
            ->getQuery()
116
            ->getResult();
117
    }
118
119
    /**
120
     * {@inheritdoc}
121
     */
122
    protected function createQueryBuilder($method, array $arguments = [])
123
    {
124
        $repository = $this->managerRegistry
125
            ->getManagerForClass($this->objectClass)
126
            ->getRepository($this->objectClass);
127
        // ORM query builders require an alias argument
128
        $arguments = [static::ENTITY_ALIAS] + $arguments;
129
130
        return call_user_func_array([$repository, $method], $arguments);
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136
    public function provide(array $options = array())
137
    {
138
        $provider = $this;
139
        $queryBuilder = $this->createQueryBuilder($options['query_builder_method']);
140
        $manager = $this->managerRegistry->getManagerForClass($this->objectClass);
141
142
        return new Pagerfanta(new CallbackAdapter(
143
            function() use ($provider, $queryBuilder, $options) {
144
                return $provider->countObjects($queryBuilder);
145
            },
146
            function($offset, $length) use ($provider, $queryBuilder, $manager, $options) {
147
                if ($options['clear_object_manager']) {
148
                    $manager->clear();
149
                }
150
151
                return $provider->fetchSlice($queryBuilder, $length, $offset);
152
            }
153
        ));
154
    }
155
}
156