GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 619fa8...db31ee )
by Anderson
02:20
created

ElasticUnitOfWork::getCommitOrder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace DoctrineElastic;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Doctrine\ORM\Event\OnClearEventArgs;
7
use Doctrine\ORM\Event\PreFlushEventArgs;
8
use Doctrine\ORM\Events;
9
use Doctrine\ORM\ORMInvalidArgumentException;
10
use DoctrineElastic\Hydrate\SimpleEntityHydrator;
11
use DoctrineElastic\Persister\ElasticEntityPersister;
12
use Elasticsearch\Client;
13
use InvalidArgumentException;
14
15
/**
16
 * Here is a Elastic adaptation for UoW of Doctrine.
17
 * There is many simplifications, just like entity states, persist, remove, delete, commit actions,
18
 * and much more.
19
 *
20
 * @author Ands
21
 */
22
class ElasticUnitOfWork {
23
24
    /**
25
     * Entity has been persisted and now is managed by EntityManager
26
     */
27
    const STATE_MANAGED = 1;
28
29
    /**
30
     * Entity has been instantiated, and is not managed by EntityManager (yet)
31
     */
32
    const STATE_NEW = 2;
33
34
    /**
35
     * Entity has value(s) for identity field(s) and exists in elastic, therefore,
36
     * is not managed by EntityManager (yet)
37
     */
38
    const STATE_DETACHED = 3;
39
40
    /**
41
     * Entity was deleted by remove method, and will be removed on commit
42
     */
43
    const STATE_DELETED = 4;
44
45
    /* @var ElasticEntityManager $em */
46
    private $em;
47
48
    /* @var EntityManagerInterface $em */
49
    private $elastic;
50
51
    /** @var string[] */
52
    private $entitiesCommitOrder = [];
53
54
    protected $entityDeletions;
55
    protected $entityInsertions;
56
    protected $entityUpdates;
57
58
    private $hydrator;
59
60
    public function __construct(EntityManagerInterface $em, Client $elastic) {
61
        $this->em = $em;
0 ignored issues
show
Documentation Bug introduced by
$em is of type object<Doctrine\ORM\EntityManagerInterface>, but the property $em was declared to be of type object<DoctrineElastic\ElasticEntityManager>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
62
        $this->elastic = $elastic;
0 ignored issues
show
Documentation Bug introduced by
It seems like $elastic of type object<Elasticsearch\Client> is incompatible with the declared type object<Doctrine\ORM\EntityManagerInterface> of property $elastic.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
63
        $this->hydrator = new SimpleEntityHydrator();
64
    }
65
66
    /**
67
     * @param string $entityName
68
     * @return ElasticEntityPersister
69
     */
70
    public function getEntityPersister($entityName) {
71
        return new ElasticEntityPersister($this->em, $entityName);
72
    }
73
74
    /**
75
     * @param object $entity
76
     */
77
    public function persist($entity) {
78
        $oid = spl_object_hash($entity);
79
80
        switch ($this->getEntityState($entity)) {
81
            default:
82
                if (isset($this->entityInsertions[$oid])) {
83
                    unset($this->entityInsertions[$oid]);
84
                }
85
                if (isset($this->entityUpdates[$oid])) {
86
                    unset($this->entityUpdates[$oid]);
87
                }
88
89
                $this->scheduleForInsert($entity);
90
                break;
91
            case self::STATE_DETACHED:
92
                $this->scheduleForUpdate($entity);
93
                break;
94
        }
95
96
        $this->entitiesCommitOrder[] = get_class($entity);
97
    }
98
99
    /**
100
     * @param object $entity
101
     * @return int
102
     */
103
    public function getEntityState($entity) {
104
        if ($this->isEntityScheduled($entity)) {
105
            if ($this->isScheduledForDelete($entity)) {
106
                return self::STATE_DELETED;
107
            } else {
108
                return self::STATE_MANAGED;
109
            }
110
        }
111
112
        $persister = $this->getEntityPersister(get_class($entity));
113
114
        if (method_exists($entity, 'get_id')) {
115
            $_id = $entity->get_id();
116
        } else {
117
            $_id = $entity->_id;
118
        }
119
120
        if (boolval($_id)) {
121
            $element = $persister->loadById(['_id' => $_id]);
122
123
            if ($element) {
124
                return self::STATE_DETACHED;
125
            }
126
        }
127
128
        return self::STATE_NEW;
129
    }
130
131
    /**
132
     * @param object $entity
133
     */
134
    public function scheduleForInsert($entity) {
135
        if ($this->isScheduledForUpdate($entity)) {
136
            throw new InvalidArgumentException('Dirty entity can not be scheduled for insertion.');
137
        }
138
139
        if ($this->isScheduledForDelete($entity)) {
140
            throw ORMInvalidArgumentException::scheduleInsertForRemovedEntity($entity);
141
        }
142
143
        if ($this->isScheduledForInsert($entity)) {
144
            throw ORMInvalidArgumentException::scheduleInsertTwice($entity);
145
        }
146
147
        $this->entityInsertions[spl_object_hash($entity)] = $entity;
148
    }
149
150
    public function isScheduledForInsert($entity) {
151
        return isset($this->entityInsertions[spl_object_hash($entity)]);
152
    }
153
154
    public function isScheduledForUpdate($entity) {
155
        return isset($this->entityUpdates[spl_object_hash($entity)]);
156
    }
157
158
    public function isScheduledForDelete($entity) {
159
        return isset($this->entityDeletions[spl_object_hash($entity)]);
160
    }
161
162
    public function isEntityScheduled($entity) {
163
        $oid = spl_object_hash($entity);
164
165
        return isset($this->entityInsertions[$oid])
166
        || isset($this->entityUpdates[$oid])
167
        || isset($this->entityDeletions[$oid]);
168
    }
169
170
    public function scheduleForUpdate($entity) {
171
        $oid = spl_object_hash($entity);
172
173
        if (isset($this->entityDeletions[$oid])) {
174
            throw ORMInvalidArgumentException::entityIsRemoved($entity, "schedule for update");
175
        }
176
177
        if (!isset($this->entityUpdates[$oid]) && !isset($this->entityInsertions[$oid])) {
178
            $this->entityUpdates[$oid] = $entity;
179
        }
180
    }
181
182
    public function scheduleForDelete($entity) {
183
        $oid = spl_object_hash($entity);
184
185
        if (isset($this->entityInsertions[$oid])) {
186
            unset($this->entityInsertions[$oid]);
187
        }
188
189
        if (isset($this->entityUpdates[$oid])) {
190
            unset($this->entityUpdates[$oid]);
191
        }
192
193
        if (!isset($this->entityDeletions[$oid])) {
194
            $this->entityDeletions[$oid] = $entity;
195
        }
196
    }
197
198
    /**
199
     * @param null|object|array $entity
200
     * @return void
201
     * @throws \Exception
202
     */
203
    public function commit($entity = null) {
204
        if ($this->em->getEventManager()->hasListeners(Events::preFlush)) {
205
            $this->em->getEventManager()->dispatchEvent(Events::preFlush, new PreFlushEventArgs($this->em));
206
        }
207
208
        $this->dispatchOnFlushEvent();
209
        $commitOrder = $this->getEntitiesCommitOrder();
210
211
//        $conn = $this->em->getConnection();
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
212
//        $conn->beginTransaction();
213
214
        try {
215
            if ($this->entityInsertions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->entityInsertions of type array<string,object> is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
216
                foreach ($commitOrder as $className) {
217
                    $this->executeInserts($className);
218
                }
219
            }
220
221
            if ($this->entityUpdates) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->entityUpdates of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
222
                foreach ($commitOrder as $className) {
223
                    $this->executeUpdates($className);
224
                }
225
            }
226
227
            if ($this->entityDeletions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->entityDeletions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
228
                for ($count = count($commitOrder), $i = $count - 1; $i >= 0 && $this->entityDeletions; --$i) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->entityDeletions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
229
                    $this->executeDeletions($commitOrder[$i]);
230
                }
231
            }
232
233
//            $conn->commit();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
234
        } catch (\Exception $e) {
235
            $this->afterTransactionRolledBack();
236
            throw $e;
237
        }
238
239
        $this->afterTransactionComplete();
240
        $this->dispatchPostFlushEvent();
241
        $this->clear($entity);
242
    }
243
244
    public function executeInserts($className) {
245
        $persister = $this->getEntityPersister($className);
246
247
        foreach ($this->entityInsertions as $oid => $entity) {
248
            if (get_class($entity) !== $className) {
249
                continue;
250
            }
251
252
            $persister->addInsert($entity);
253
            unset($this->entityInsertions[$oid]);
254
        }
255
256
        $persister->executeInserts();
257
    }
258
259 View Code Duplication
    public function executeUpdates($className) {
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...
260
        $persister = $this->getEntityPersister($className);
261
262
        foreach ($this->entityUpdates as $oid => $entity) {
263
            if (get_class($entity) !== $className) {
264
                continue;
265
            }
266
267
            $persister->update($entity);
268
            unset($this->entityUpdates[$oid]);
269
        }
270
    }
271
272 View Code Duplication
    public function executeDeletions($className) {
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...
273
        $persister = $this->getEntityPersister($className);
274
275
        foreach ($this->entityDeletions as $oid => $entity) {
276
            if (get_class($entity) !== $className) {
277
                continue;
278
            }
279
280
            $persister->delete($entity);
281
            unset($this->entityDeletions[$oid]);
282
        }
283
    }
284
285
    protected function dispatchOnFlushEvent() {
286
287
    }
288
289
    protected function dispatchPostFlushEvent() {
290
291
    }
292
293
    public function clear($entity = null) {
294
        if ($entity === null) {
295
            $this->entityInsertions =
296
            $this->entityUpdates =
297
            $this->entityDeletions =
298
            $this->entitiesCommitOrder = [];
299
        } else {
300
            $this->clearEntityInsertions($entity);
301
            $this->clearEntityUpdate($entity);
302
            $this->clearEntityDeletions($entity);
303
        }
304
305
        if ($this->em->getEventManager()->hasListeners(Events::onClear)) {
306
            $this->em->getEventManager()->dispatchEvent(
307
                Events::onClear, new OnClearEventArgs($this->em, get_class($entity))
308
            );
309
        }
310
    }
311
312 View Code Duplication
    private function clearEntityInsertions($entity = null) {
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...
313
        if ($entity === null) {
314
            $this->entityInsertions = [];
315
        } else {
316
            $oid = spl_object_hash($entity);
317
            if (isset($this->entityInsertions[$oid])) {
318
                unset($this->entityInsertions[$oid]);
319
            }
320
        }
321
322
    }
323
324 View Code Duplication
    private function clearEntityUpdate($entity = null) {
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...
325
        if ($entity === null) {
326
            $this->entityUpdates = [];
327
        } else {
328
            $oid = spl_object_hash($entity);
329
            if (isset($this->entityUpdates[$oid])) {
330
                unset($this->entityUpdates[$oid]);
331
            }
332
        }
333
334
    }
335
336
    public function delete($entity) {
337
        if(!is_object($entity)){
338
            throw new InvalidArgumentException('Trying to schedule a non object to delete');
339
        }
340
341
        $this->scheduleForDelete($entity);
342
        $this->entitiesCommitOrder[] = get_class($entity);
343
    }
344
345 View Code Duplication
    private function clearEntityDeletions($entity = null) {
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...
346
        if ($entity === null) {
347
            $this->entityDeletions = [];
348
        } else {
349
            $oid = spl_object_hash($entity);
350
            if (isset($this->entityDeletions[$oid])) {
351
                unset($this->entityDeletions[$oid]);
352
            }
353
        }
354
355
    }
356
357
    /**
358
     * @return string[]
359
     */
360
    public function getEntitiesCommitOrder() {
361
        return $this->entitiesCommitOrder;
362
    }
363
364
    protected function afterTransactionRolledBack() {
365
366
    }
367
368
    protected function afterTransactionComplete() {
369
370
    }
371
372
    public function createEntity() {
373
374
    }
375
}