Completed
Pull Request — master (#1331)
by Maciej
09:05
created

LifecycleEventManager::__construct()   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
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4286
c 1
b 0
f 0
cc 1
eloc 4
nc 1
nop 3
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\LifecycleEventArgs;
25
use Doctrine\ODM\MongoDB\Event\PreUpdateEventArgs;
26
use Doctrine\ODM\MongoDB\Events;
27
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
28
use Doctrine\ODM\MongoDB\UnitOfWork;
29
30
/**
31
 * @internal
32
 * @since 1.1
33
 */
34
class LifecycleEventManager
35
{
36
    /**
37
     * @var DocumentManager
38
     */
39
    private $dm;
40
    
41
    /**
42
     * @var EventManager
43
     */
44
    private $evm;
45
46
    /**
47
     * @var UnitOfWork
48
     */
49
    private $uow;
50
51
    /**
52
     * @param DocumentManager $dm
53
     * @param UnitOfWork $uow
54
     * @param EventManager $evm
55
     */
56 932
    public function __construct(DocumentManager $dm, UnitOfWork $uow, EventManager $evm)
57
    {
58 932
        $this->dm = $dm;
59 932
        $this->evm = $evm;
60 932
        $this->uow = $uow;
61 932
    }
62
63
    /**
64
     * Invokes postPersist callbacks and events for given document cascading them to embedded documents as well.
65
     *
66
     * @param ClassMetadata $class
67
     * @param object $document
68
     */
69 553
    public function postPersist(ClassMetadata $class, $document)
70
    {
71 553
        $class->invokeLifecycleCallbacks(Events::postPersist, $document, array(new LifecycleEventArgs($document, $this->dm)));
72 553
        $this->evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($document, $this->dm));
73 553
        $this->cascadePostPersist($class, $document);
74 553
    }
75
76
    /**
77
     * Invokes postRemove callbacks and events for given document.
78
     *
79
     * @param ClassMetadata $class
80
     * @param object $document
81
     */
82 61
    public function postRemove(ClassMetadata $class, $document)
83
    {
84 61
        $class->invokeLifecycleCallbacks(Events::postRemove, $document, array(new LifecycleEventArgs($document, $this->dm)));
85 61
        $this->evm->dispatchEvent(Events::postRemove, new LifecycleEventArgs($document, $this->dm));
86 61
    }
87
88
    /**
89
     * Invokes postUpdate callbacks and events for given document. The same will be done for embedded documents owned
90
     * by given document unless they were new in which case postPersist callbacks and events will be dispatched.
91
     *
92
     * @param ClassMetadata $class
93
     * @param object $document
94
     */
95 215
    public function postUpdate(ClassMetadata $class, $document)
96
    {
97 215
        $class->invokeLifecycleCallbacks(Events::postUpdate, $document, array(new LifecycleEventArgs($document, $this->dm)));
98 215
        $this->evm->dispatchEvent(Events::postUpdate, new LifecycleEventArgs($document, $this->dm));
99 215
        $this->cascadePostUpdate($class, $document);
100 215
    }
101
102
    /**
103
     * Invokes prePersist callbacks and events for given document.
104
     *
105
     * @param ClassMetadata $class
106
     * @param object $document
107
     */
108 577
    public function prePersist(ClassMetadata $class, $document)
109
    {
110 577
        $class->invokeLifecycleCallbacks(Events::prePersist, $document, array(new LifecycleEventArgs($document, $this->dm)));
111 577
        $this->evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($document, $this->dm));
112 577
    }
113
114
    /**
115
     * Invokes prePersist callbacks and events for given document.
116
     *
117
     * @param ClassMetadata $class
118
     * @param object $document
119
     */
120 67
    public function preRemove(ClassMetadata $class, $document)
121
    {
122 67
        $class->invokeLifecycleCallbacks(Events::preRemove, $document, array(new LifecycleEventArgs($document, $this->dm)));
123 67
        $this->evm->dispatchEvent(Events::preRemove, new LifecycleEventArgs($document, $this->dm));
124 67
    }
125
126
    /**
127
     * Invokes preUpdate callbacks and events for given document cascading them to embedded documents as well.
128
     *
129
     * @param ClassMetadata $class
130
     * @param object $document
131
     */
132 219
    public function preUpdate(ClassMetadata $class, $document)
133
    {
134 219
        $changeset =& $this->uow->getDocumentChangeSetByRef($document);
135 219 View Code Duplication
        if ( ! empty($class->lifecycleCallbacks[Events::preUpdate])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
136 12
            $class->invokeLifecycleCallbacks(Events::preUpdate, $document, array(
137 12
                new PreUpdateEventArgs($document, $this->dm, $changeset)
138 12
            ));
139 12
            $this->uow->recomputeSingleDocumentChangeSet($class, $document);
140 12
        }
141 219
        $this->evm->dispatchEvent(Events::preUpdate, new PreUpdateEventArgs($document, $this->dm, $changeset));
142 219
        $this->cascadePreUpdate($class, $document);
143 219
    }
144
145
    /**
146
     * Cascades the preUpdate event to embedded documents.
147
     *
148
     * @param ClassMetadata $class
149
     * @param object $document
150
     */
151 219
    private function cascadePreUpdate(ClassMetadata $class, $document)
152
    {
153 219
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
154 134
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
155 134
            if ($value === null) {
156 49
                continue;
157
            }
158 132
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
159
160 132
            foreach ($values as $entry) {
161 85
                if ($this->uow->isScheduledForInsert($entry) || empty($this->uow->getDocumentChangeSet($entry))) {
162 71
                    continue;
163
                }
164 45
                $this->preUpdate($this->dm->getClassMetadata(get_class($entry)), $entry);
165 132
            }
166 219
        }
167 219
    }
168
169
    /**
170
     * Cascades the postUpdate and postPersist events to embedded documents.
171
     *
172
     * @param ClassMetadata $class
173
     * @param object $document
174
     */
175 215
    private function cascadePostUpdate(ClassMetadata $class, $document)
176
    {
177 215
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
178 130
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
179 130
            if ($value === null) {
180 52
                continue;
181
            }
182 128
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
183
184 128
            foreach ($values as $entry) {
185 85
                if (empty($this->uow->getDocumentChangeSet($entry)) && ! $this->uow->hasScheduledCollections($entry)) {
186 48
                    continue;
187
                }
188 67
                $entryClass = $this->dm->getClassMetadata(get_class($entry));
189 67
                $event = $this->uow->isScheduledForInsert($entry) ? Events::postPersist : Events::postUpdate;
190 67
                $entryClass->invokeLifecycleCallbacks($event, $entry, array(new LifecycleEventArgs($entry, $this->dm)));
191 67
                $this->evm->dispatchEvent($event, new LifecycleEventArgs($entry, $this->dm));
192
193 67
                $this->cascadePostUpdate($entryClass, $entry);
194 128
            }
195 215
        }
196 215
    }
197
198
    /**
199
     * Cascades the postPersist events to embedded documents.
200
     *
201
     * @param ClassMetadata $class
202
     * @param object $document
203
     */
204 553
    private function cascadePostPersist(ClassMetadata $class, $document)
205
    {
206 553
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
207 336
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
208 336
            if ($value === null) {
209 215
                continue;
210
            }
211 317
            $values = $mapping['type'] === ClassMetadata::ONE ? array($value) : $value;
212 317
            foreach ($values as $embeddedDocument) {
213 159
                $this->postPersist($this->dm->getClassMetadata(get_class($embeddedDocument)), $embeddedDocument);
214 317
            }
215 553
        }
216 553
    }
217
}
218