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

AbstractListenerBase::doPostFlush()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
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 14
    public function __construct(
73
        ObjectPersisterInterface $objectPersister,
74
        IndexableInterface $indexable,
75
        array $config = array(),
76
        LoggerInterface $logger = null
77
    ) {
78 14
        $this->config = array_merge(array(
79 14
            'identifier' => 'id',
80
        ), $config);
81 14
        $this->indexable = $indexable;
82 14
        $this->objectPersister = $objectPersister;
83 14
        $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
84
85 14
        if ($logger && $this->objectPersister instanceof ObjectPersister) {
86
            $this->objectPersister->setLogger($logger);
87
        }
88 14
    }
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 6
    private function persistScheduled()
95
    {
96 6
        if (count($this->scheduledForInsertion)) {
97 1
            $this->objectPersister->insertMany($this->scheduledForInsertion);
98 1
            $this->scheduledForInsertion = array();
99
        }
100 6
        if (count($this->scheduledForUpdate)) {
101 1
            $this->objectPersister->replaceMany($this->scheduledForUpdate);
102 1
            $this->scheduledForUpdate = array();
103
        }
104 6
        if (count($this->scheduledForDeletion)) {
105 3
            $this->objectPersister->deleteManyByIdentifiers($this->scheduledForDeletion);
106 3
            $this->scheduledForDeletion = array();
107
        }
108 6
    }
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 6
    protected function doPostFlush()
115
    {
116 6
        $this->persistScheduled();
117 6
    }
118
119
    /**
120
     * Record the specified identifier to delete. Do not need to entire object.
121
     *
122
     * @param object $object
123
     */
124 3
    private function scheduleForDeletion($object)
125
    {
126 3
        if ($identifierValue = $this->propertyAccessor->getValue($object, $this->config['identifier'])) {
127 3
            $this->scheduledForDeletion[] = $identifierValue;
128
        }
129 3
    }
130
131
    /**
132
     * Checks if the object is indexable or not.
133
     *
134
     * @param object $object
135
     *
136
     * @return bool
137
     */
138 4
    private function isObjectIndexable($object)
139
    {
140 4
        return $this->indexable->isObjectIndexable(
141 4
            $this->config['indexName'],
142 4
            $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 2
    protected function doPostPersist($entity)
153
    {
154 2
        if ($this->objectPersister->handlesObject($entity) && $this->isObjectIndexable($entity)) {
155 1
            $this->scheduledForInsertion[] = $entity;
156
        }
157 2
    }
158
    
159
    /**
160
     * Looks for objects being updated that should be indexed or removed from the index.
161
     *
162
     * @param object $entity
163
     */
164 2
    protected function doPostUpdate($entity)
165
    {
166 2
        if ($this->objectPersister->handlesObject($entity)) {
167 2
            if ($this->isObjectIndexable($entity)) {
168 1
                $this->scheduledForUpdate[] = $entity;
169
            } else {
170
                // Delete if no longer indexable
171 1
                $this->scheduleForDeletion($entity);
172
            }
173
        }
174 2
    }
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 2
    protected function doPreRemove($entity)
183
    {
184 2
        if ($this->objectPersister->handlesObject($entity)) {
185 2
            $this->scheduleForDeletion($entity);
186
        }
187 2
    }
188
}
189