1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Dsantang\DomainEventsDoctrine\Outbox; |
6
|
|
|
|
7
|
|
|
use Doctrine\ORM\EntityManagerInterface; |
8
|
|
|
use Doctrine\ORM\Event\OnFlushEventArgs; |
9
|
|
|
use Doctrine\ORM\UnitOfWork; |
10
|
|
|
use Dsantang\DomainEvents\Counter; |
11
|
|
|
use Dsantang\DomainEvents\DomainEvent; |
12
|
|
|
use Dsantang\DomainEvents\EventAware; |
13
|
|
|
use function array_filter; |
14
|
|
|
use function array_merge; |
15
|
|
|
use function ksort; |
16
|
|
|
|
17
|
|
|
abstract class EventsHandler |
18
|
|
|
{ |
19
|
|
|
/** @var OutboxMappedSuperclass */ |
20
|
|
|
protected $outboxMappedSuperclass; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @return DomainEvent[] |
24
|
|
|
*/ |
25
|
4 |
|
protected function getDomainEvents(OnFlushEventArgs $eventArgs) : array |
26
|
|
|
{ |
27
|
4 |
|
$unitOfWork = $eventArgs->getEntityManager() |
28
|
4 |
|
->getUnitOfWork(); |
29
|
|
|
|
30
|
4 |
|
$events = []; |
31
|
|
|
|
32
|
4 |
|
foreach (self::getEventAwareEntities($unitOfWork) as $entity) { |
33
|
3 |
|
$events += $entity->expelRecordedEvents(); |
34
|
|
|
} |
35
|
|
|
|
36
|
4 |
|
ksort($events); |
37
|
|
|
|
38
|
4 |
|
Counter::reset(); |
39
|
|
|
|
40
|
4 |
|
return $events; |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @return OutboxEntry[] |
45
|
|
|
* |
46
|
|
|
* @var DomainEvent[] $domainEvents |
47
|
|
|
*/ |
48
|
|
|
abstract protected function convert(DomainEvent ...$domainEvents) : array; |
49
|
|
|
|
50
|
2 |
|
public function onFlush(OnFlushEventArgs $eventArgs) : void |
51
|
|
|
{ |
52
|
2 |
|
$domainEvents = $this->getDomainEvents($eventArgs); |
53
|
|
|
|
54
|
2 |
|
$outboxEvents = $this->convert(...$domainEvents); |
55
|
|
|
|
56
|
2 |
|
if (! $outboxEvents) { |
|
|
|
|
57
|
1 |
|
return; |
58
|
|
|
} |
59
|
|
|
|
60
|
1 |
|
$this->persist($eventArgs->getEntityManager(), ...$outboxEvents); |
61
|
1 |
|
} |
62
|
|
|
|
63
|
2 |
|
protected function persist(EntityManagerInterface $entityManager, OutboxEntry ...$outboxEntries) : void |
64
|
|
|
{ |
65
|
2 |
|
foreach ($outboxEntries as $outboxEntry) { |
66
|
2 |
|
$entity = $this->outboxMappedSuperclass->fromOutboxEntry($outboxEntry); |
67
|
2 |
|
$entityManager->persist($entity); |
68
|
|
|
} |
69
|
|
|
|
70
|
2 |
|
$entityManager->getUnitOfWork()->computeChangeSets(); |
71
|
2 |
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @return EventAware[] |
75
|
|
|
*/ |
76
|
4 |
|
private static function getEventAwareEntities(UnitOfWork $unitOfWork) : array |
77
|
|
|
{ |
78
|
4 |
|
$entities = array_merge( |
79
|
4 |
|
$unitOfWork->getScheduledEntityInsertions(), |
80
|
4 |
|
$unitOfWork->getScheduledEntityUpdates(), |
81
|
4 |
|
$unitOfWork->getScheduledEntityDeletions() |
82
|
|
|
); |
83
|
|
|
|
84
|
|
|
return array_filter($entities, static function ($entity) { |
85
|
3 |
|
return $entity instanceof EventAware; |
86
|
4 |
|
}); |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
|
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.