Completed
Pull Request — master (#1007)
by Stepan
10:03
created

AbstractProvider::countObjects()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
dl 0
loc 1
c 1
b 1
f 0
ccs 0
cts 0
cp 0
nc 1
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 9
        $this->managerRegistry = $managerRegistry;
45 9
        $this->sliceFetcher = $sliceFetcher;
46 9
    }
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
     * @param array $arguments
62
     *
63
     * @return object
64
     */
65
    abstract protected function createQueryBuilder($method, array $arguments = array());
66
67
    /**
68
     * Fetches a slice of objects using the query builder.
69
     *
70
     * @param object  $queryBuilder
71
     * @param integer $limit
72
     * @param integer $offset
73
     *
74
     * @return array
75
     */
76
    abstract protected function fetchSlice($queryBuilder, $limit, $offset);
77
78
    /**
79
     * {@inheritDoc}
80
     */
81 9
    protected function doPopulate($options, \Closure $loggerClosure = null)
82
    {
83 9
        $manager = $this->managerRegistry->getManagerForClass($this->objectClass);
84
85 9
        $queryBuilder = $this->createQueryBuilder($options['query_builder_method']);
86 9
        $nbObjects = $this->countObjects($queryBuilder);
87 9
        $offset = $options['offset'];
88
89 9
        $objects = array();
90 9
        for (; $offset < $nbObjects; $offset += $options['batch_size']) {
91 9
            $sliceSize = $options['batch_size'];
92
            try {
93 9
                $objects = $this->getSlice($queryBuilder, $options['batch_size'], $offset, $objects);
94 9
                $sliceSize = count($objects);
95 9
                $objects = $this->filterObjects($options, $objects);
96
97 9
                if (!empty($objects)) {
98 9
                    $this->objectPersister->insertMany($objects);
99
                }
100 1
            } catch (BulkResponseException $e) {
101 1
                if (!$options['ignore_errors']) {
102 1
                    throw $e;
103
                }
104
105
                if (null !== $loggerClosure) {
106
                    $loggerClosure(
107
                        $options['batch_size'],
108
                        $nbObjects,
109
                        sprintf('<error>%s</error>', $e->getMessage())
110
                    );
111
                }
112
            }
113
114 8
            if ($options['clear_object_manager']) {
115 7
                $manager->clear();
116
            }
117
118 8
            usleep($options['sleep']);
119
120 8
            if (null !== $loggerClosure) {
121 1
                $loggerClosure($sliceSize, $nbObjects);
122
            }
123
        }
124 8
    }
125
126
    /**
127
     * {@inheritDoc}
128
     */
129 9
    protected function configureOptions()
130
    {
131 9
        parent::configureOptions();
132
133 9
        $this->resolver->setDefaults(array(
134 9
            'clear_object_manager' => true,
135
            'debug_logging'        => false,
136
            'ignore_errors'        => false,
137
            'offset'               => 0,
138
            'query_builder_method' => 'createQueryBuilder',
139
            'sleep'                => 0
140
        ));
141 9
    }
142
143
    /**
144
     * If this Provider has a SliceFetcher defined, we use it instead of falling back to
145
     * the fetchSlice methods defined in the ORM/MongoDB subclasses.
146
     *
147
     * @param $queryBuilder
148
     * @param int   $limit
149
     * @param int   $offset
150
     * @param array $lastSlice
151
     *
152
     * @return array
153
     */
154 9
    private function getSlice($queryBuilder, $limit, $offset, $lastSlice)
155
    {
156 9
        if (!$this->sliceFetcher) {
157 2
            return $this->fetchSlice($queryBuilder, $limit, $offset);
158
        }
159
160 7
        $manager = $this->managerRegistry->getManagerForClass($this->objectClass);
161
        $identifierFieldNames = $manager
162 7
            ->getClassMetadata($this->objectClass)
163 7
            ->getIdentifierFieldNames();
164
165 7
        return $this->sliceFetcher->fetch(
166
            $queryBuilder,
167
            $limit,
168
            $offset,
169
            $lastSlice,
170
            $identifierFieldNames
171
        );
172
    }
173
}
174