Completed
Pull Request — master (#1379)
by Maciej
22:04
created

LifecycleEventManager::prePersist()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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