Completed
Pull Request — master (#992)
by David
05:34
created

AbstractProvider   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 6

Test Coverage

Coverage 9.3%

Importance

Changes 7
Bugs 4 Features 0
Metric Value
wmc 12
c 7
b 4
f 0
lcom 2
cbo 6
dl 0
loc 161
ccs 4
cts 43
cp 0.093
rs 10

7 Methods

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