Completed
Pull Request — master (#1379)
by Maciej
18:11
created

LifecycleEventManager::postUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
crap 1
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\PostCollectionLoadEventArgs;
27
use Doctrine\ODM\MongoDB\Event\PreUpdateEventArgs;
28
use Doctrine\ODM\MongoDB\Events;
29
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
30
use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface;
31
use Doctrine\ODM\MongoDB\UnitOfWork;
32
33
/**
34
 * @internal
35
 * @since 1.1
36
 */
37
class LifecycleEventManager
38
{
39
    /**
40
     * @var DocumentManager
41
     */
42
    private $dm;
43
    
44
    /**
45
     * @var EventManager
46
     */
47
    private $evm;
48
49
    /**
50
     * @var UnitOfWork
51
     */
52
    private $uow;
53
54
    /**
55
     * @param DocumentManager $dm
56
     * @param UnitOfWork $uow
57
     * @param EventManager $evm
58
     */
59 958
    public function __construct(DocumentManager $dm, UnitOfWork $uow, EventManager $evm)
60
    {
61 958
        $this->dm = $dm;
62 958
        $this->evm = $evm;
63 958
        $this->uow = $uow;
64 958
    }
65
66
    /**
67
     * @param object $proxy
68
     * @param mixed $id
69
     * @return bool Returns whether the exceptionDisabled flag was set
70
     */
71 9
    public function documentNotFound($proxy, $id)
72
    {
73 9
        $eventArgs = new DocumentNotFoundEventArgs($proxy, $this->dm, $id);
74 9
        $this->evm->dispatchEvent(Events::documentNotFound, $eventArgs);
75
76 9
        return $eventArgs->isExceptionDisabled();
77
    }
78
79
    /**
80
     * Dispatches postCollectionLoad event.
81
     *
82
     * @param PersistentCollectionInterface $coll
83
     */
84 161
    public function postCollectionLoad(PersistentCollectionInterface $coll)
85
    {
86 161
        $eventArgs = new PostCollectionLoadEventArgs($coll, $this->dm);
87 161
        $this->evm->dispatchEvent(Events::postCollectionLoad, $eventArgs);
88 161
    }
89
90
    /**
91
     * Invokes postPersist callbacks and events for given document cascading them to embedded documents as well.
92
     *
93
     * @param ClassMetadata $class
94
     * @param object $document
95
     */
96 566
    public function postPersist(ClassMetadata $class, $document)
97
    {
98 566
        $class->invokeLifecycleCallbacks(Events::postPersist, $document, array(new LifecycleEventArgs($document, $this->dm)));
99 566
        $this->evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($document, $this->dm));
100 566
        $this->cascadePostPersist($class, $document);
101 566
    }
102
103
    /**
104
     * Invokes postRemove callbacks and events for given document.
105
     *
106
     * @param ClassMetadata $class
107
     * @param object $document
108
     */
109 62
    public function postRemove(ClassMetadata $class, $document)
110
    {
111 62
        $class->invokeLifecycleCallbacks(Events::postRemove, $document, array(new LifecycleEventArgs($document, $this->dm)));
112 62
        $this->evm->dispatchEvent(Events::postRemove, new LifecycleEventArgs($document, $this->dm));
113 62
    }
114
115
    /**
116
     * Invokes postUpdate callbacks and events for given document. The same will be done for embedded documents owned
117
     * by given document unless they were new in which case postPersist callbacks and events will be dispatched.
118
     *
119
     * @param ClassMetadata $class
120
     * @param object $document
121
     */
122 218
    public function postUpdate(ClassMetadata $class, $document)
123
    {
124 218
        $class->invokeLifecycleCallbacks(Events::postUpdate, $document, array(new LifecycleEventArgs($document, $this->dm)));
125 218
        $this->evm->dispatchEvent(Events::postUpdate, new LifecycleEventArgs($document, $this->dm));
126 218
        $this->cascadePostUpdate($class, $document);
127 218
    }
128
129
    /**
130
     * Invokes prePersist callbacks and events for given document.
131
     *
132
     * @param ClassMetadata $class
133
     * @param object $document
134
     */
135 596
    public function prePersist(ClassMetadata $class, $document)
136
    {
137 596
        $class->invokeLifecycleCallbacks(Events::prePersist, $document, array(new LifecycleEventArgs($document, $this->dm)));
138 596
        $this->evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($document, $this->dm));
139 596
    }
140
141
    /**
142
     * Invokes prePersist callbacks and events for given document.
143
     *
144
     * @param ClassMetadata $class
145
     * @param object $document
146
     */
147 68
    public function preRemove(ClassMetadata $class, $document)
148
    {
149 68
        $class->invokeLifecycleCallbacks(Events::preRemove, $document, array(new LifecycleEventArgs($document, $this->dm)));
150 68
        $this->evm->dispatchEvent(Events::preRemove, new LifecycleEventArgs($document, $this->dm));
151 68
    }
152
153
    /**
154
     * Invokes preUpdate callbacks and events for given document cascading them to embedded documents as well.
155
     *
156
     * @param ClassMetadata $class
157
     * @param object $document
158
     */
159 222
    public function preUpdate(ClassMetadata $class, $document)
160
    {
161 222
        if ( ! empty($class->lifecycleCallbacks[Events::preUpdate])) {
162 12
            $class->invokeLifecycleCallbacks(Events::preUpdate, $document, array(
163 12
                new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document))
164 12
            ));
165 12
            $this->uow->recomputeSingleDocumentChangeSet($class, $document);
166 12
        }
167 222
        $this->evm->dispatchEvent(Events::preUpdate, new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document)));
168 222
        $this->cascadePreUpdate($class, $document);
169 222
    }
170
171
    /**
172
     * Cascades the preUpdate event to embedded documents.
173
     *
174
     * @param ClassMetadata $class
175
     * @param object $document
176
     */
177 222
    private function cascadePreUpdate(ClassMetadata $class, $document)
178
    {
179 222
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
180 136
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
181 136
            if ($value === null) {
182 50
                continue;
183
            }
184 134
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
185
186 134
            foreach ($values as $entry) {
187 87
                if ($this->uow->isScheduledForInsert($entry) || empty($this->uow->getDocumentChangeSet($entry))) {
188 71
                    continue;
189
                }
190 50
                $this->preUpdate($this->dm->getClassMetadata(get_class($entry)), $entry);
191 134
            }
192 222
        }
193 222
    }
194
195
    /**
196
     * Cascades the postUpdate and postPersist events to embedded documents.
197
     *
198
     * @param ClassMetadata $class
199
     * @param object $document
200
     */
201 218
    private function cascadePostUpdate(ClassMetadata $class, $document)
202
    {
203 218
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
204 132
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
205 132
            if ($value === null) {
206 53
                continue;
207
            }
208 130
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
209
210 130
            foreach ($values as $entry) {
211 87
                if (empty($this->uow->getDocumentChangeSet($entry)) && ! $this->uow->hasScheduledCollections($entry)) {
212 47
                    continue;
213
                }
214 73
                $entryClass = $this->dm->getClassMetadata(get_class($entry));
215 73
                $event = $this->uow->isScheduledForInsert($entry) ? Events::postPersist : Events::postUpdate;
216 73
                $entryClass->invokeLifecycleCallbacks($event, $entry, array(new LifecycleEventArgs($entry, $this->dm)));
217 73
                $this->evm->dispatchEvent($event, new LifecycleEventArgs($entry, $this->dm));
218
219 73
                $this->cascadePostUpdate($entryClass, $entry);
220 130
            }
221 218
        }
222 218
    }
223
224
    /**
225
     * Cascades the postPersist events to embedded documents.
226
     *
227
     * @param ClassMetadata $class
228
     * @param object $document
229
     */
230 566
    private function cascadePostPersist(ClassMetadata $class, $document)
231
    {
232 566
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
233 348
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
234 348
            if ($value === null) {
235 223
                continue;
236
            }
237 328
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
238 328
            foreach ($values as $embeddedDocument) {
239 164
                $this->postPersist($this->dm->getClassMetadata(get_class($embeddedDocument)), $embeddedDocument);
240 328
            }
241 566
        }
242 566
    }
243
}
244