Completed
Push — master ( 957ab4...453ef8 )
by Andreas
12:42
created

LifecycleEventManager::cascadePreUpdate()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
ccs 13
cts 13
cp 1
rs 8.2222
cc 7
eloc 10
nc 4
nop 2
crap 7
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ODM\MongoDB\Utility;
21
22
use Doctrine\Common\EventManager;
23
use Doctrine\ODM\MongoDB\DocumentManager;
24
use Doctrine\ODM\MongoDB\Event\DocumentNotFoundEventArgs;
25
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
26
use Doctrine\ODM\MongoDB\Event\PreUpdateEventArgs;
27
use Doctrine\ODM\MongoDB\Events;
28
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
29
use Doctrine\ODM\MongoDB\UnitOfWork;
30
31
/**
32
 * @internal
33
 * @since 1.1
34
 */
35
class LifecycleEventManager
36
{
37
    /**
38
     * @var DocumentManager
39
     */
40
    private $dm;
41
    
42
    /**
43
     * @var EventManager
44
     */
45
    private $evm;
46
47
    /**
48
     * @var UnitOfWork
49
     */
50
    private $uow;
51
52
    /**
53
     * @param DocumentManager $dm
54
     * @param UnitOfWork $uow
55
     * @param EventManager $evm
56
     */
57 940
    public function __construct(DocumentManager $dm, UnitOfWork $uow, EventManager $evm)
58
    {
59 940
        $this->dm = $dm;
60 940
        $this->evm = $evm;
61 940
        $this->uow = $uow;
62 940
    }
63
64
    /**
65
     * @param object $proxy
66
     * @param mixed $id
67
     * @return bool Returns whether the exceptionDisabled flag was set
68
     */
69 9
    public function documentNotFound($proxy, $id)
70
    {
71 9
        $eventArgs = new DocumentNotFoundEventArgs($proxy, $this->dm, $id);
72 9
        $this->evm->dispatchEvent(Events::documentNotFound, $eventArgs);
73
74 9
        return $eventArgs->isExceptionDisabled();
75
    }
76
77
    /**
78
     * Invokes postPersist callbacks and events for given document cascading them to embedded documents as well.
79
     *
80
     * @param ClassMetadata $class
81
     * @param object $document
82
     */
83 555
    public function postPersist(ClassMetadata $class, $document)
84
    {
85 555
        $class->invokeLifecycleCallbacks(Events::postPersist, $document, array(new LifecycleEventArgs($document, $this->dm)));
86 555
        $this->evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($document, $this->dm));
87 555
        $this->cascadePostPersist($class, $document);
88 555
    }
89
90
    /**
91
     * Invokes postRemove callbacks and events for given document.
92
     *
93
     * @param ClassMetadata $class
94
     * @param object $document
95
     */
96 62
    public function postRemove(ClassMetadata $class, $document)
97
    {
98 62
        $class->invokeLifecycleCallbacks(Events::postRemove, $document, array(new LifecycleEventArgs($document, $this->dm)));
99 62
        $this->evm->dispatchEvent(Events::postRemove, new LifecycleEventArgs($document, $this->dm));
100 62
    }
101
102
    /**
103
     * Invokes postUpdate callbacks and events for given document. The same will be done for embedded documents owned
104
     * by given document unless they were new in which case postPersist callbacks and events will be dispatched.
105
     *
106
     * @param ClassMetadata $class
107
     * @param object $document
108
     */
109 216
    public function postUpdate(ClassMetadata $class, $document)
110
    {
111 216
        $class->invokeLifecycleCallbacks(Events::postUpdate, $document, array(new LifecycleEventArgs($document, $this->dm)));
112 216
        $this->evm->dispatchEvent(Events::postUpdate, new LifecycleEventArgs($document, $this->dm));
113 216
        $this->cascadePostUpdate($class, $document);
114 216
    }
115
116
    /**
117
     * Invokes prePersist callbacks and events for given document.
118
     *
119
     * @param ClassMetadata $class
120
     * @param object $document
121
     */
122 585
    public function prePersist(ClassMetadata $class, $document)
123
    {
124 585
        $class->invokeLifecycleCallbacks(Events::prePersist, $document, array(new LifecycleEventArgs($document, $this->dm)));
125 585
        $this->evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($document, $this->dm));
126 585
    }
127
128
    /**
129
     * Invokes prePersist callbacks and events for given document.
130
     *
131
     * @param ClassMetadata $class
132
     * @param object $document
133
     */
134 68
    public function preRemove(ClassMetadata $class, $document)
135
    {
136 68
        $class->invokeLifecycleCallbacks(Events::preRemove, $document, array(new LifecycleEventArgs($document, $this->dm)));
137 68
        $this->evm->dispatchEvent(Events::preRemove, new LifecycleEventArgs($document, $this->dm));
138 68
    }
139
140
    /**
141
     * Invokes preUpdate callbacks and events for given document cascading them to embedded documents as well.
142
     *
143
     * @param ClassMetadata $class
144
     * @param object $document
145
     */
146 220
    public function preUpdate(ClassMetadata $class, $document)
147
    {
148 220
        if ( ! empty($class->lifecycleCallbacks[Events::preUpdate])) {
149 12
            $class->invokeLifecycleCallbacks(Events::preUpdate, $document, array(
150 12
                new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document))
151 12
            ));
152 12
            $this->uow->recomputeSingleDocumentChangeSet($class, $document);
153 12
        }
154 220
        $this->evm->dispatchEvent(Events::preUpdate, new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document)));
155 220
        $this->cascadePreUpdate($class, $document);
156 220
    }
157
158
    /**
159
     * Cascades the preUpdate event to embedded documents.
160
     *
161
     * @param ClassMetadata $class
162
     * @param object $document
163
     */
164 220
    private function cascadePreUpdate(ClassMetadata $class, $document)
165
    {
166 220
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
167 135
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
168 135
            if ($value === null) {
169 49
                continue;
170
            }
171 133
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
172
173 133
            foreach ($values as $entry) {
174 86
                if ($this->uow->isScheduledForInsert($entry) || empty($this->uow->getDocumentChangeSet($entry))) {
175 70
                    continue;
176
                }
177 50
                $this->preUpdate($this->dm->getClassMetadata(get_class($entry)), $entry);
178 133
            }
179 220
        }
180 220
    }
181
182
    /**
183
     * Cascades the postUpdate and postPersist events to embedded documents.
184
     *
185
     * @param ClassMetadata $class
186
     * @param object $document
187
     */
188 216
    private function cascadePostUpdate(ClassMetadata $class, $document)
189
    {
190 216
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
191 131
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
192 131
            if ($value === null) {
193 52
                continue;
194
            }
195 129
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
196
197 129
            foreach ($values as $entry) {
198 86
                if (empty($this->uow->getDocumentChangeSet($entry)) && ! $this->uow->hasScheduledCollections($entry)) {
199 47
                    continue;
200
                }
201 72
                $entryClass = $this->dm->getClassMetadata(get_class($entry));
202 72
                $event = $this->uow->isScheduledForInsert($entry) ? Events::postPersist : Events::postUpdate;
203 72
                $entryClass->invokeLifecycleCallbacks($event, $entry, array(new LifecycleEventArgs($entry, $this->dm)));
204 72
                $this->evm->dispatchEvent($event, new LifecycleEventArgs($entry, $this->dm));
205
206 72
                $this->cascadePostUpdate($entryClass, $entry);
207 129
            }
208 216
        }
209 216
    }
210
211
    /**
212
     * Cascades the postPersist events to embedded documents.
213
     *
214
     * @param ClassMetadata $class
215
     * @param object $document
216
     */
217 555
    private function cascadePostPersist(ClassMetadata $class, $document)
218
    {
219 555
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
220 338
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
221 338
            if ($value === null) {
222 216
                continue;
223
            }
224 319
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
225 319
            foreach ($values as $embeddedDocument) {
226 160
                $this->postPersist($this->dm->getClassMetadata(get_class($embeddedDocument)), $embeddedDocument);
227 319
            }
228 555
        }
229 555
    }
230
}
231