Completed
Push — master ( 7b9f4b...1cd743 )
by Andreas
13s queued 10s
created

ODM/MongoDB/Utility/LifecycleEventManager.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
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 1651
    public function __construct(DocumentManager $dm, UnitOfWork $uow, EventManager $evm)
34
    {
35 1651
        $this->dm  = $dm;
36 1651
        $this->evm = $evm;
37 1651
        $this->uow = $uow;
38 1651
    }
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 593
    public function postPersist(ClassMetadata $class, object $document) : void
66
    {
67 593
        $class->invokeLifecycleCallbacks(Events::postPersist, $document, [new LifecycleEventArgs($document, $this->dm)]);
68 593
        $this->evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($document, $this->dm));
69 593
        $this->cascadePostPersist($class, $document);
70 593
    }
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 229
    public function postUpdate(ClassMetadata $class, object $document) : void
86
    {
87 229
        $class->invokeLifecycleCallbacks(Events::postUpdate, $document, [new LifecycleEventArgs($document, $this->dm)]);
88 229
        $this->evm->dispatchEvent(Events::postUpdate, new LifecycleEventArgs($document, $this->dm));
89 229
        $this->cascadePostUpdate($class, $document);
90 229
    }
91
92
    /**
93
     * Invokes prePersist callbacks and events for given document.
94
     */
95 641
    public function prePersist(ClassMetadata $class, object $document) : void
96
    {
97 641
        $class->invokeLifecycleCallbacks(Events::prePersist, $document, [new LifecycleEventArgs($document, $this->dm)]);
98 641
        $this->evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($document, $this->dm));
99 641
    }
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 236
    public function preUpdate(ClassMetadata $class, object $document) : void
114
    {
115 236
        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 236
        $this->evm->dispatchEvent(Events::preUpdate, new PreUpdateEventArgs($document, $this->dm, $this->uow->getDocumentChangeSet($document)));
120 236
        $this->cascadePreUpdate($class, $document);
121 236
    }
122
123
    /**
124
     * Cascades the preUpdate event to embedded documents.
125
     */
126 236
    private function cascadePreUpdate(ClassMetadata $class, object $document) : void
127
    {
128 236
        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 79
                    continue;
138
                }
139 52
                $this->preUpdate($this->dm->getClassMetadata(get_class($entry)), $entry);
0 ignored issues
show
$this->dm->getClassMetadata(\get_class($entry)) of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ODM\Mong...\Mapping\ClassMetadata>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
140
            }
141
        }
142 236
    }
143
144
    /**
145
     * Cascades the postUpdate and postPersist events to embedded documents.
146
     */
147 229
    private function cascadePostUpdate(ClassMetadata $class, object $document) : void
148
    {
149 229
        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 54
                    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);
0 ignored issues
show
$entryClass of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ODM\Mong...\Mapping\ClassMetadata>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
166
            }
167
        }
168 229
    }
169
170
    /**
171
     * Cascades the postPersist events to embedded documents.
172
     */
173 593
    private function cascadePostPersist(ClassMetadata $class, object $document) : void
174
    {
175 593
        foreach ($class->getEmbeddedFieldsMappings() as $mapping) {
176 363
            $value = $class->reflFields[$mapping['fieldName']]->getValue($document);
177 363
            if ($value === null) {
178 229
                continue;
179
            }
180 331
            $values = $mapping['type'] === ClassMetadata::ONE ? [$value] : $value;
181 331
            foreach ($values as $embeddedDocument) {
182 168
                $this->postPersist($this->dm->getClassMetadata(get_class($embeddedDocument)), $embeddedDocument);
0 ignored issues
show
$this->dm->getClassMetad...ass($embeddedDocument)) of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ODM\Mong...\Mapping\ClassMetadata>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
183
            }
184
        }
185 593
    }
186
}
187