Completed
Push — master ( b90edc...95608f )
by Andreas
14:15 queued 11s
created

LifecycleEventManager::cascadePostUpdate()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

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