Completed
Push — master ( 8fc9bf...b852d4 )
by Andreas
17s queued 12s
created

LifecycleEventManager::preRemove()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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