Completed
Pull Request — master (#1269)
by Wesley
11:25
created

AbstractProvider::getSlice()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 7
cts 7
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 13
nc 2
nop 4
crap 2
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;
13
14
use Doctrine\Common\Persistence\ManagerRegistry;
15
use Elastica\Exception\Bulk\ResponseException as BulkResponseException;
16
use FOS\ElasticaBundle\Persister\ObjectPersisterInterface;
17
use FOS\ElasticaBundle\Provider\AbstractProvider as BaseAbstractProvider;
18
use FOS\ElasticaBundle\Provider\IndexableInterface;
19
20
abstract class AbstractProvider extends BaseAbstractProvider
21
{
22
    /**
23
     * @var SliceFetcherInterface
24
     */
25
    private $sliceFetcher;
26
27
    /**
28
     * @var ManagerRegistry
29
     */
30
    protected $managerRegistry;
31
32
    /**
33
     * Constructor.
34
     *
35
     * @param ObjectPersisterInterface $objectPersister
36
     * @param IndexableInterface       $indexable
37
     * @param string                   $objectClass
38
     * @param array                    $baseOptions
39
     * @param ManagerRegistry          $managerRegistry
40
     * @param SliceFetcherInterface    $sliceFetcher
41
     */
42 9
    public function __construct(
43
        ObjectPersisterInterface $objectPersister,
44
        IndexableInterface $indexable,
45
        $objectClass,
46
        array $baseOptions,
47
        ManagerRegistry $managerRegistry,
48
        SliceFetcherInterface $sliceFetcher = null
49
    ) {
50 9
        parent::__construct($objectPersister, $indexable, $objectClass, $baseOptions);
51
52 9
        $this->managerRegistry = $managerRegistry;
53 9
        $this->sliceFetcher = $sliceFetcher;
54 9
    }
55
56
    /**
57
     * Counts objects that would be indexed using the query builder.
58
     *
59
     * @param object $queryBuilder
60
     *
61
     * @return int
62
     */
63
    abstract protected function countObjects($queryBuilder);
64
65
    /**
66
     * Creates the query builder, which will be used to fetch objects to index.
67
     *
68
     * @param string $method
69
     * @param array  $arguments
70
     *
71
     * @return object
72
     */
73
    abstract protected function createQueryBuilder($method, array $arguments = []);
74
75
    /**
76
     * Fetches a slice of objects using the query builder.
77
     *
78
     * @param object $queryBuilder
79
     * @param int    $limit
80
     * @param int    $offset
81
     *
82
     * @return array
83
     */
84
    abstract protected function fetchSlice($queryBuilder, $limit, $offset);
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 9
    protected function doPopulate($options, \Closure $loggerClosure = null)
90
    {
91 9
        $manager = $this->managerRegistry->getManagerForClass($this->objectClass);
92
93 9
        $queryBuilder = $this->createQueryBuilder($options['query_builder_method']);
94 9
        $limit = $nbObjects = $this->countObjects($queryBuilder);
95 9
        if ($options['limit'] && ($nbObjects - $options['offset']) > $options['limit']) {
96
            $limit = $options['limit'] + $options['offset'];
97
        }
98 9
        $offset = $options['offset'];
99 9
        if ($options['limit'] && $options['limit'] < $options['batch_size']) {
100
            $options['batch_size'] = $options['limit'];
101
        }
102
103 9
        $objects = [];
104 9
        for (; $offset < $limit; $offset += $options['batch_size']) {
105 9
            $sliceSize = $options['batch_size'];
106
            try {
107 9
                $objects = $this->getSlice($queryBuilder, $options['batch_size'], $offset, $objects);
108 9
                $sliceSize = count($objects);
109 9
                $objects = $this->filterObjects($options, $objects);
110
111 9
                if (!empty($objects)) {
112 9
                    $this->objectPersister->insertMany($objects);
113
                }
114 1
            } catch (BulkResponseException $e) {
115 1
                if (!$options['ignore_errors']) {
116 1
                    throw $e;
117
                }
118
119
                if (null !== $loggerClosure) {
120
                    $loggerClosure(
121
                        $options['batch_size'],
122
                        $nbObjects,
123
                        sprintf('<error>%s</error>', $e->getMessage())
124
                    );
125
                }
126
            }
127
128 8
            if ($options['clear_object_manager']) {
129 7
                $manager->clear();
130
            }
131
132 8
            usleep($options['sleep']);
133
134 8
            if (null !== $loggerClosure) {
135 1
                $loggerClosure($sliceSize, $nbObjects);
136
            }
137
        }
138 8
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143 9 View Code Duplication
    protected function configureOptions()
144
    {
145 9
        parent::configureOptions();
146
147 9
        $this->resolver->setDefaults([
148 9
            'clear_object_manager' => true,
149
            'debug_logging' => false,
150
            'ignore_errors' => false,
151
            'offset' => 0,
152
            'query_builder_method' => 'createQueryBuilder',
153
            'sleep' => 0,
154
        ]);
155 9
    }
156
157
    /**
158
     * If this Provider has a SliceFetcher defined, we use it instead of falling back to
159
     * the fetchSlice methods defined in the ORM/MongoDB subclasses.
160
     *
161
     * @param $queryBuilder
162
     * @param int   $limit
163
     * @param int   $offset
164
     * @param array $lastSlice
165
     *
166
     * @return array
167
     */
168 9
    private function getSlice($queryBuilder, $limit, $offset, $lastSlice)
169
    {
170 9
        if (!$this->sliceFetcher) {
171 2
            return $this->fetchSlice($queryBuilder, $limit, $offset);
172
        }
173
174 7
        $manager = $this->managerRegistry->getManagerForClass($this->objectClass);
175
        $identifierFieldNames = $manager
176 7
            ->getClassMetadata($this->objectClass)
177 7
            ->getIdentifierFieldNames();
178
179 7
        return $this->sliceFetcher->fetch(
180
            $queryBuilder,
181
            $limit,
182
            $offset,
183
            $lastSlice,
184
            $identifierFieldNames
185
        );
186
    }
187
}
188