1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Doctrine\ODM\MongoDB\Utility; |
6
|
|
|
|
7
|
|
|
use Doctrine\Common\EventManager; |
8
|
|
|
use Doctrine\ODM\MongoDB\DocumentManager; |
9
|
|
|
use Doctrine\ODM\MongoDB\Event\DocumentNotFoundEventArgs; |
10
|
|
|
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs; |
11
|
|
|
use Doctrine\ODM\MongoDB\Event\PostCollectionLoadEventArgs; |
12
|
|
|
use Doctrine\ODM\MongoDB\Event\PreUpdateEventArgs; |
13
|
|
|
use Doctrine\ODM\MongoDB\Events; |
14
|
|
|
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; |
15
|
|
|
use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface; |
16
|
|
|
use Doctrine\ODM\MongoDB\UnitOfWork; |
17
|
|
|
use const E_USER_DEPRECATED; |
18
|
|
|
use function get_class; |
19
|
|
|
use function sprintf; |
20
|
|
|
use function trigger_error; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @internal |
24
|
|
|
* |
25
|
|
|
* @final |
26
|
|
|
*/ |
27
|
|
|
class LifecycleEventManager |
28
|
|
|
{ |
29
|
|
|
/** @var DocumentManager */ |
30
|
|
|
private $dm; |
31
|
|
|
|
32
|
|
|
/** @var EventManager */ |
33
|
|
|
private $evm; |
34
|
|
|
|
35
|
|
|
/** @var UnitOfWork */ |
36
|
|
|
private $uow; |
37
|
|
|
|
38
|
1656 |
View Code Duplication |
public function __construct(DocumentManager $dm, UnitOfWork $uow, EventManager $evm) |
|
|
|
|
39
|
|
|
{ |
40
|
1656 |
|
if (self::class !== static::class) { |
41
|
|
|
@trigger_error(sprintf('The class "%s" extends "%s" which will be final in MongoDB ODM 2.0.', static::class, self::class), E_USER_DEPRECATED); |
|
|
|
|
42
|
|
|
} |
43
|
1656 |
|
$this->dm = $dm; |
44
|
1656 |
|
$this->evm = $evm; |
45
|
1656 |
|
$this->uow = $uow; |
46
|
1656 |
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @param mixed $id |
50
|
|
|
* |
51
|
|
|
* @return bool Returns whether the exceptionDisabled flag was set |
52
|
|
|
*/ |
53
|
9 |
|
public function documentNotFound(object $proxy, $id) : bool |
54
|
|
|
{ |
55
|
9 |
|
$eventArgs = new DocumentNotFoundEventArgs($proxy, $this->dm, $id); |
56
|
9 |
|
$this->evm->dispatchEvent(Events::documentNotFound, $eventArgs); |
57
|
|
|
|
58
|
9 |
|
return $eventArgs->isExceptionDisabled(); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Dispatches postCollectionLoad event. |
63
|
|
|
*/ |
64
|
178 |
|
public function postCollectionLoad(PersistentCollectionInterface $coll) : void |
65
|
|
|
{ |
66
|
178 |
|
$eventArgs = new PostCollectionLoadEventArgs($coll, $this->dm); |
67
|
178 |
|
$this->evm->dispatchEvent(Events::postCollectionLoad, $eventArgs); |
68
|
178 |
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Invokes postPersist callbacks and events for given document cascading them to embedded documents as well. |
72
|
|
|
*/ |
73
|
596 |
|
public function postPersist(ClassMetadata $class, object $document) : void |
74
|
|
|
{ |
75
|
596 |
|
$class->invokeLifecycleCallbacks(Events::postPersist, $document, [new LifecycleEventArgs($document, $this->dm)]); |
76
|
596 |
|
$this->evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($document, $this->dm)); |
77
|
596 |
|
$this->cascadePostPersist($class, $document); |
78
|
596 |
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Invokes postRemove callbacks and events for given document. |
82
|
|
|
*/ |
83
|
77 |
|
public function postRemove(ClassMetadata $class, object $document) : void |
84
|
|
|
{ |
85
|
77 |
|
$class->invokeLifecycleCallbacks(Events::postRemove, $document, [new LifecycleEventArgs($document, $this->dm)]); |
86
|
77 |
|
$this->evm->dispatchEvent(Events::postRemove, new LifecycleEventArgs($document, $this->dm)); |
87
|
77 |
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Invokes postUpdate callbacks and events for given document. The same will be done for embedded documents owned |
91
|
|
|
* by given document unless they were new in which case postPersist callbacks and events will be dispatched. |
92
|
|
|
*/ |
93
|
229 |
|
public function postUpdate(ClassMetadata $class, object $document) : void |
94
|
|
|
{ |
95
|
229 |
|
$class->invokeLifecycleCallbacks(Events::postUpdate, $document, [new LifecycleEventArgs($document, $this->dm)]); |
96
|
229 |
|
$this->evm->dispatchEvent(Events::postUpdate, new LifecycleEventArgs($document, $this->dm)); |
97
|
229 |
|
$this->cascadePostUpdate($class, $document); |
98
|
229 |
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Invokes prePersist callbacks and events for given document. |
102
|
|
|
*/ |
103
|
644 |
|
public function prePersist(ClassMetadata $class, object $document) : void |
104
|
|
|
{ |
105
|
644 |
|
$class->invokeLifecycleCallbacks(Events::prePersist, $document, [new LifecycleEventArgs($document, $this->dm)]); |
106
|
644 |
|
$this->evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($document, $this->dm)); |
107
|
644 |
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Invokes prePersist callbacks and events for given document. |
111
|
|
|
*/ |
112
|
83 |
|
public function preRemove(ClassMetadata $class, object $document) : void |
113
|
|
|
{ |
114
|
83 |
|
$class->invokeLifecycleCallbacks(Events::preRemove, $document, [new LifecycleEventArgs($document, $this->dm)]); |
115
|
83 |
|
$this->evm->dispatchEvent(Events::preRemove, new LifecycleEventArgs($document, $this->dm)); |
116
|
83 |
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Invokes preUpdate callbacks and events for given document cascading them to embedded documents as well. |
120
|
|
|
*/ |
121
|
236 |
|
public function preUpdate(ClassMetadata $class, object $document) : void |
122
|
|
|
{ |
123
|
236 |
|
if (! empty($class->lifecycleCallbacks[Events::preUpdate])) { |
124
|
12 |
|
$class->invokeLifecycleCallbacks(Events::preUpdate, $document, [new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document))]); |
125
|
12 |
|
$this->uow->recomputeSingleDocumentChangeSet($class, $document); |
126
|
|
|
} |
127
|
236 |
|
$this->evm->dispatchEvent(Events::preUpdate, new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document))); |
128
|
236 |
|
$this->cascadePreUpdate($class, $document); |
129
|
236 |
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Cascades the preUpdate event to embedded documents. |
133
|
|
|
*/ |
134
|
236 |
|
private function cascadePreUpdate(ClassMetadata $class, object $document) : void |
135
|
|
|
{ |
136
|
236 |
|
foreach ($class->getEmbeddedFieldsMappings() as $mapping) { |
137
|
150 |
|
$value = $class->reflFields[$mapping['fieldName']]->getValue($document); |
138
|
150 |
|
if ($value === null) { |
139
|
55 |
|
continue; |
140
|
|
|
} |
141
|
142 |
|
$values = $mapping['type'] === ClassMetadata::ONE ? [$value] : $value; |
142
|
|
|
|
143
|
142 |
|
foreach ($values as $entry) { |
144
|
96 |
|
if ($this->uow->isScheduledForInsert($entry) || empty($this->uow->getDocumentChangeSet($entry))) { |
145
|
80 |
|
continue; |
146
|
|
|
} |
147
|
52 |
|
$this->preUpdate($this->dm->getClassMetadata(get_class($entry)), $entry); |
148
|
|
|
} |
149
|
|
|
} |
150
|
236 |
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Cascades the postUpdate and postPersist events to embedded documents. |
154
|
|
|
*/ |
155
|
229 |
|
private function cascadePostUpdate(ClassMetadata $class, object $document) : void |
156
|
|
|
{ |
157
|
229 |
|
foreach ($class->getEmbeddedFieldsMappings() as $mapping) { |
158
|
146 |
|
$value = $class->reflFields[$mapping['fieldName']]->getValue($document); |
159
|
146 |
|
if ($value === null) { |
160
|
58 |
|
continue; |
161
|
|
|
} |
162
|
138 |
|
$values = $mapping['type'] === ClassMetadata::ONE ? [$value] : $value; |
163
|
|
|
|
164
|
138 |
|
foreach ($values as $entry) { |
165
|
96 |
|
if (empty($this->uow->getDocumentChangeSet($entry)) && ! $this->uow->hasScheduledCollections($entry)) { |
166
|
55 |
|
continue; |
167
|
|
|
} |
168
|
82 |
|
$entryClass = $this->dm->getClassMetadata(get_class($entry)); |
169
|
82 |
|
$event = $this->uow->isScheduledForInsert($entry) ? Events::postPersist : Events::postUpdate; |
170
|
82 |
|
$entryClass->invokeLifecycleCallbacks($event, $entry, [new LifecycleEventArgs($entry, $this->dm)]); |
171
|
82 |
|
$this->evm->dispatchEvent($event, new LifecycleEventArgs($entry, $this->dm)); |
172
|
|
|
|
173
|
82 |
|
$this->cascadePostUpdate($entryClass, $entry); |
174
|
|
|
} |
175
|
|
|
} |
176
|
229 |
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Cascades the postPersist events to embedded documents. |
180
|
|
|
*/ |
181
|
596 |
|
private function cascadePostPersist(ClassMetadata $class, object $document) : void |
182
|
|
|
{ |
183
|
596 |
|
foreach ($class->getEmbeddedFieldsMappings() as $mapping) { |
184
|
365 |
|
$value = $class->reflFields[$mapping['fieldName']]->getValue($document); |
185
|
365 |
|
if ($value === null) { |
186
|
231 |
|
continue; |
187
|
|
|
} |
188
|
333 |
|
$values = $mapping['type'] === ClassMetadata::ONE ? [$value] : $value; |
189
|
333 |
|
foreach ($values as $embeddedDocument) { |
190
|
168 |
|
$this->postPersist($this->dm->getClassMetadata(get_class($embeddedDocument)), $embeddedDocument); |
191
|
|
|
} |
192
|
|
|
} |
193
|
596 |
|
} |
194
|
|
|
} |
195
|
|
|
|
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.