Completed
Push — master ( 95608f...d78a07 )
by Andreas
14s queued 10s
created

LifecycleEventManager::cascadePreUpdate()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 7

Importance

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