Completed
Pull Request — master (#1254)
by Rafał
03:45
created

AbstractProvider::getSlice()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2.1481

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 8
cts 12
cp 0.6667
rs 9.4285
cc 2
eloc 13
nc 2
nop 4
crap 2.1481
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
        $nbObjects = $this->countObjects($queryBuilder);
95 9
        $offset = $options['offset'];
96
97 9
        $objects = [];
98 9
        for (; $offset < $nbObjects; $offset += $options['batch_size']) {
99 9
            $sliceSize = $options['batch_size'];
100
            try {
101 9
                $objects = $this->getSlice($queryBuilder, $options['batch_size'], $offset, $objects);
102 9
                $sliceSize = count($objects);
103 9
                $objects = $this->filterObjects($options, $objects);
104
105 9
                if (!empty($objects)) {
106 8
                    $this->objectPersister->insertMany($objects);
107
                }
108 1
            } catch (BulkResponseException $e) {
109 1
                if (!$options['ignore_errors']) {
110 1
                    throw $e;
111
                }
112
113
                if (null !== $loggerClosure) {
114
                    $loggerClosure(
115
                        $options['batch_size'],
116
                        $nbObjects,
117
                        sprintf('<error>%s</error>', $e->getMessage())
118
                    );
119
                }
120
            }
121
122 8
            if ($options['clear_object_manager']) {
123 7
                $manager->clear();
124
            }
125
126 8
            usleep($options['sleep']);
127
128 8
            if (null !== $loggerClosure) {
129 1
                $loggerClosure($sliceSize, $nbObjects);
130
            }
131
        }
132 8
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137 9 View Code Duplication
    protected function configureOptions()
138
    {
139 9
        parent::configureOptions();
140
141 9
        $this->resolver->setDefaults([
142 9
            'clear_object_manager' => true,
143
            'debug_logging' => false,
144
            'ignore_errors' => false,
145
            'offset' => 0,
146
            'query_builder_method' => 'createQueryBuilder',
147
            'sleep' => 0,
148
        ]);
149 9
    }
150
151
    /**
152
     * If this Provider has a SliceFetcher defined, we use it instead of falling back to
153
     * the fetchSlice methods defined in the ORM/MongoDB subclasses.
154
     *
155
     * @param $queryBuilder
156
     * @param int   $limit
157
     * @param int   $offset
158
     * @param array $lastSlice
159
     *
160
     * @return array
161
     */
162 9
    private function getSlice($queryBuilder, $limit, $offset, $lastSlice)
163
    {
164 9
        if (!$this->sliceFetcher) {
165 2
            return $this->fetchSlice($queryBuilder, $limit, $offset);
166
        }
167
168 7
        $manager = $this->managerRegistry->getManagerForClass($this->objectClass);
169
        $identifierFieldNames = $manager
170 7
            ->getClassMetadata($this->objectClass)
171 7
            ->getIdentifierFieldNames();
172
173 7
        return $this->sliceFetcher->fetch(
174
            $queryBuilder,
175
            $limit,
176
            $offset,
177
            $lastSlice,
178 7
            $identifierFieldNames
179
        );
180
    }
181
}
182