Completed
Push — master ( d25871...e6c4a4 )
by Karel
35:25 queued 31:40
created

AbstractProvider   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 162
Duplicated Lines 8.02 %

Coupling/Cohesion

Components 2
Dependencies 6

Test Coverage

Coverage 88.33%

Importance

Changes 0
Metric Value
wmc 12
lcom 2
cbo 6
dl 13
loc 162
ccs 53
cts 60
cp 0.8833
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
countObjects() 0 1 ?
fetchSlice() 0 1 ?
C doPopulate() 0 44 8
A configureOptions() 13 13 1
A getSlice() 0 19 2
createQueryBuilder() 0 1 ?

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 8
                    $this->objectPersister->insertMany($objects);
99 7
                }
100 9
            } 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 7
            }
117
118 8
            usleep($options['sleep']);
119
120 8
            if (null !== $loggerClosure) {
121 1
                $loggerClosure($sliceSize, $nbObjects);
122 1
            }
123 8
        }
124 8
    }
125
126
    /**
127
     * {@inheritDoc}
128
     */
129 9 View Code Duplication
    protected function configureOptions()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
130
    {
131 9
        parent::configureOptions();
132
133 9
        $this->resolver->setDefaults(array(
134 9
            'clear_object_manager' => true,
135 9
            'debug_logging'        => false,
136 9
            'ignore_errors'        => false,
137 9
            'offset'               => 0,
138 9
            'query_builder_method' => 'createQueryBuilder',
139
            'sleep'                => 0
140 9
        ));
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 7
            $queryBuilder,
167 7
            $limit,
168 7
            $offset,
169 7
            $lastSlice,
170
            $identifierFieldNames
171 7
        );
172
    }
173
}
174