Completed
Pull Request — master (#1125)
by
unknown
09:58
created

AbstractListenerBase::doPostFlush()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
namespace FOS\ElasticaBundle\Doctrine;
4
5
use FOS\ElasticaBundle\Persister\ObjectPersister;
6
use FOS\ElasticaBundle\Persister\ObjectPersisterInterface;
7
use FOS\ElasticaBundle\Provider\IndexableInterface;
8
use Psr\Log\LoggerInterface;
9
use Symfony\Component\PropertyAccess\PropertyAccess;
10
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
11
12
/**
13
 * Common base for Doctrine / Propel listener.
14
 */
15
abstract class AbstractListenerBase
16
{
17
    /**
18
     * Object persister.
19
     *
20
     * @var ObjectPersisterInterface
21
     */
22
    protected $objectPersister;
23
24
    /**
25
     * Configuration for the listener.
26
     *
27
     * @var array
28
     */
29
    private $config;
30
31
    /**
32
     * Objects scheduled for insertion.
33
     *
34
     * @var array
35
     */
36
    public $scheduledForInsertion = array();
37
38
    /**
39
     * Objects scheduled to be updated or removed.
40
     *
41
     * @var array
42
     */
43
    public $scheduledForUpdate = array();
44
45
    /**
46
     * IDs of objects scheduled for removal.
47
     *
48
     * @var array
49
     */
50
    public $scheduledForDeletion = array();
51
52
    /**
53
     * PropertyAccessor instance.
54
     *
55
     * @var PropertyAccessorInterface
56
     */
57
    protected $propertyAccessor;
58
59
    /**
60
     * @var IndexableInterface
61
     */
62
    private $indexable;
63
64
    /**
65
     * Constructor.
66
     *
67
     * @param ObjectPersisterInterface $objectPersister
68
     * @param IndexableInterface       $indexable
69
     * @param array                    $config
70
     * @param LoggerInterface          $logger
71
     */
72 8
    public function __construct(
73
        ObjectPersisterInterface $objectPersister,
74
        IndexableInterface $indexable,
75
        array $config = array(),
76
        LoggerInterface $logger = null
77
    ) {
78 8
        $this->config = array_merge(array(
79 8
            'identifier' => 'id',
80
        ), $config);
81 8
        $this->indexable = $indexable;
82 8
        $this->objectPersister = $objectPersister;
83 8
        $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
84
85 8
        if ($logger && $this->objectPersister instanceof ObjectPersister) {
86
            $this->objectPersister->setLogger($logger);
87
        }
88 8
    }
89
90
    /**
91
     * Persist scheduled objects to ElasticSearch
92
     * After persisting, clear the scheduled queue to prevent multiple data updates when using multiple flush calls.
93
     */
94
    private function persistScheduled()
95
    {
96
        if (count($this->scheduledForInsertion)) {
97
            $this->objectPersister->insertMany($this->scheduledForInsertion);
98
            $this->scheduledForInsertion = array();
99
        }
100
        if (count($this->scheduledForUpdate)) {
101
            $this->objectPersister->replaceMany($this->scheduledForUpdate);
102
            $this->scheduledForUpdate = array();
103
        }
104
        if (count($this->scheduledForDeletion)) {
105
            $this->objectPersister->deleteManyByIdentifiers($this->scheduledForDeletion);
106
            $this->scheduledForDeletion = array();
107
        }
108
    }
109
110
    /**
111
     * Iterating through scheduled actions *after* flushing ensures that the
112
     * ElasticSearch index will be affected only if the query is successful.
113
     */
114
    protected function doPostFlush()
115
    {
116
        $this->persistScheduled();
117
    }
118
119
    /**
120
     * Record the specified identifier to delete. Do not need to entire object.
121
     *
122
     * @param object $object
123
     */
124
    private function scheduleForDeletion($object)
125
    {
126
        if ($identifierValue = $this->propertyAccessor->getValue($object, $this->config['identifier'])) {
127
            $this->scheduledForDeletion[] = $identifierValue;
128
        }
129
    }
130
131
    /**
132
     * Checks if the object is indexable or not.
133
     *
134
     * @param object $object
135
     *
136
     * @return bool
137
     */
138
    private function isObjectIndexable($object)
139
    {
140
        return $this->indexable->isObjectIndexable(
141
            $this->config['indexName'],
142
            $this->config['typeName'],
143
            $object
144
        );
145
    }
146
    
147
    /**
148
     * Looks for new objects that should be indexed.
149
     *
150
     * @param object $entity
151
     */
152
    protected function doPostPersist($entity)
153
    {
154
        if ($this->objectPersister->handlesObject($entity) && $this->isObjectIndexable($entity)) {
155
            $this->scheduledForInsertion[] = $entity;
156
        }
157
    }
158
    
159
    /**
160
     * Looks for objects being updated that should be indexed or removed from the index.
161
     *
162
     * @param object $entity
163
     */
164
    protected function doPostUpdate($entity)
165
    {
166
        if ($this->objectPersister->handlesObject($entity)) {
167
            if ($this->isObjectIndexable($entity)) {
168
                $this->scheduledForUpdate[] = $entity;
169
            } else {
170
                // Delete if no longer indexable
171
                $this->scheduleForDeletion($entity);
172
            }
173
        }
174
    }
175
    
176
    /**
177
     * Delete objects preRemove instead of postRemove so that we have access to the id.  Because this is called
178
     * preRemove, first check that the entity is managed by persister.
179
     *
180
     * @param object $entity
181
     */
182
    protected function doPreRemove($entity)
183
    {
184
        if ($this->objectPersister->handlesObject($entity)) {
185
            $this->scheduleForDeletion($entity);
186
        }
187
    }
188
}
189