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

PersistenceBuilder::prepareUpsertData()   D

Complexity

Conditions 28
Paths 52

Size

Total Lines 71

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 30.8522

Importance

Changes 0
Metric Value
dl 0
loc 71
ccs 33
cts 39
cp 0.8462
rs 4.1666
c 0
b 0
f 0
cc 28
nc 52
nop 1
crap 30.8522

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ODM\MongoDB\Persisters;
6
7
use Doctrine\ODM\MongoDB\DocumentManager;
8
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
9
use Doctrine\ODM\MongoDB\Mapping\MappingException;
10
use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface;
11
use Doctrine\ODM\MongoDB\Types\Type;
12
use Doctrine\ODM\MongoDB\UnitOfWork;
13
use Doctrine\ODM\MongoDB\Utility\CollectionHelper;
14
use InvalidArgumentException;
15
use UnexpectedValueException;
16
use function array_search;
17
use function array_values;
18
use function get_class;
19
20
/**
21
 * PersistenceBuilder builds the queries used by the persisters to update and insert
22
 * documents when a DocumentManager is flushed. It uses the changeset information in the
23
 * UnitOfWork to build queries using atomic operators like $set, $unset, etc.
24
 */
25
class PersistenceBuilder
26
{
27
    /**
28
     * The DocumentManager instance.
29
     *
30
     * @var DocumentManager
31
     */
32
    private $dm;
33
34
    /**
35
     * The UnitOfWork instance.
36
     *
37
     * @var UnitOfWork
38
     */
39
    private $uow;
40
41
    /**
42
     * Initializes a new PersistenceBuilder instance.
43
     */
44 1130
    public function __construct(DocumentManager $dm, UnitOfWork $uow)
45
    {
46 1130
        $this->dm  = $dm;
47 1130
        $this->uow = $uow;
48 1130
    }
49
50
    /**
51
     * Prepares the array that is ready to be inserted to mongodb for a given object document.
52
     *
53
     * @param object $document
54
     *
55
     * @return array $insertData
56
     */
57 523
    public function prepareInsertData($document)
58
    {
59 523
        $class     = $this->dm->getClassMetadata(get_class($document));
60 523
        $changeset = $this->uow->getDocumentChangeSet($document);
61
62 523
        $insertData = [];
63 523
        foreach ($class->fieldMappings as $mapping) {
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
64 523
            $new = $changeset[$mapping['fieldName']][1] ?? null;
65
66 523
            if ($new === null && $mapping['nullable']) {
67 160
                $insertData[$mapping['name']] = null;
68
            }
69
70
            /* Nothing more to do for null values, since we're either storing
71
             * them (if nullable was true) or not.
72
             */
73 523
            if ($new === null) {
74 366
                continue;
75
            }
76
77
            // @Field, @String, @Date, etc.
78 521
            if (! isset($mapping['association'])) {
79 521
                $insertData[$mapping['name']] = Type::getType($mapping['type'])->convertToDatabaseValue($new);
80
81
            // @ReferenceOne
82 416
            } elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE) {
83 99
                $insertData[$mapping['name']] = $this->prepareReferencedDocumentValue($mapping, $new);
84
85
            // @EmbedOne
86 392
            } elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::EMBED_ONE) {
87 60
                $insertData[$mapping['name']] = $this->prepareEmbeddedDocumentValue($mapping, $new);
88
89
            // @ReferenceMany, @EmbedMany
90
            // We're excluding collections using addToSet since there is a risk
91
            // of duplicated entries stored in the collection
92 374
            } elseif ($mapping['type'] === ClassMetadata::MANY && ! $mapping['isInverseSide']
93 374
                    && $mapping['strategy'] !== ClassMetadata::STORAGE_STRATEGY_ADD_TO_SET && ! $new->isEmpty()) {
94 216
                $insertData[$mapping['name']] = $this->prepareAssociatedCollectionValue($new, true);
95
            }
96
        }
97
98
        // add discriminator if the class has one
99 512
        if (isset($class->discriminatorField)) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorField on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
100 26
            if ($class->discriminatorValue === null) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
101 5
                if (! empty($class->discriminatorMap)) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorMap on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
102 4
                    throw MappingException::unlistedClassInDiscriminatorMap($class->name);
0 ignored issues
show
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
103
                }
104 1
                $class->discriminatorValue = $class->name;
0 ignored issues
show
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
105
            }
106 25
            $insertData[$class->discriminatorField] = $class->discriminatorValue;
0 ignored issues
show
Bug introduced by
Accessing discriminatorField on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
107
        }
108
109 512
        return $insertData;
110
    }
111
112
    /**
113
     * Prepares the update query to update a given document object in mongodb.
114
     *
115
     * @param object $document
116
     *
117
     * @return array $updateData
118
     */
119 228
    public function prepareUpdateData($document)
120
    {
121 228
        $class     = $this->dm->getClassMetadata(get_class($document));
122 228
        $changeset = $this->uow->getDocumentChangeSet($document);
123
124 228
        $updateData = [];
125 228
        foreach ($changeset as $fieldName => $change) {
126 227
            $mapping = $class->fieldMappings[$fieldName];
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
127
128
            // skip non embedded document identifiers
129 227
            if (! $class->isEmbeddedDocument && ! empty($mapping['id'])) {
0 ignored issues
show
Bug introduced by
Accessing isEmbeddedDocument on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
130 2
                continue;
131
            }
132
133 226
            [$old, $new] = $change;
0 ignored issues
show
Bug introduced by
The variable $old does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $new does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
134
135
            // Scalar fields
136 226
            if (! isset($mapping['association'])) {
137 115
                if ($new === null && $mapping['nullable'] !== true) {
138 1
                    $updateData['$unset'][$mapping['name']] = true;
139
                } else {
140 115
                    if ($new !== null && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadata::STORAGE_STRATEGY_INCREMENT) {
141 4
                        $operator = '$inc';
142 4
                        $value    = Type::getType($mapping['type'])->convertToDatabaseValue($new - $old);
143
                    } else {
144 112
                        $operator = '$set';
145 112
                        $value    = $new === null ? null : Type::getType($mapping['type'])->convertToDatabaseValue($new);
146
                    }
147
148 115
                    $updateData[$operator][$mapping['name']] = $value;
149
                }
150
151
            // @EmbedOne
152 153
            } elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::EMBED_ONE) {
153
                // If we have a new embedded document then lets set the whole thing
154 29
                if ($new && $this->uow->isScheduledForInsert($new)) {
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object<Doctrine\ODM\MongoDB\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
155 10
                    $updateData['$set'][$mapping['name']] = $this->prepareEmbeddedDocumentValue($mapping, $new);
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
156
157
                // If we don't have a new value then lets unset the embedded document
158 22
                } elseif (! $new) {
159 3
                    $updateData['$unset'][$mapping['name']] = true;
160
161
                // Update existing embedded document
162
                } else {
163 19
                    $update = $this->prepareUpdateData($new);
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
164 29
                    foreach ($update as $cmd => $values) {
165 15
                        foreach ($values as $key => $value) {
166 15
                            $updateData[$cmd][$mapping['name'] . '.' . $key] = $value;
167
                        }
168
                    }
169
                }
170
171
            // @ReferenceMany, @EmbedMany
172 136
            } elseif (isset($mapping['association']) && $mapping['type'] === 'many' && $new) {
173 126
                if (CollectionHelper::isAtomic($mapping['strategy']) && $this->uow->isCollectionScheduledForUpdate($new)) {
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object<Doctrine\ODM\Mong...entCollectionInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
174 20
                    $updateData['$set'][$mapping['name']] = $this->prepareAssociatedCollectionValue($new, true);
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object<Doctrine\ODM\Mong...entCollectionInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
175 108
                } elseif (CollectionHelper::isAtomic($mapping['strategy']) && $this->uow->isCollectionScheduledForDeletion($new)) {
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object<Doctrine\ODM\Mong...entCollectionInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176 2
                    $updateData['$unset'][$mapping['name']] = true;
177 2
                    $this->uow->unscheduleCollectionDeletion($new);
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object<Doctrine\ODM\Mong...entCollectionInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
178 106
                } elseif (CollectionHelper::isAtomic($mapping['strategy']) && $this->uow->isCollectionScheduledForDeletion($old)) {
179 2
                    $updateData['$unset'][$mapping['name']] = true;
180 2
                    $this->uow->unscheduleCollectionDeletion($old);
181 104
                } elseif ($mapping['association'] === ClassMetadata::EMBED_MANY) {
182 126
                    foreach ($new as $key => $embeddedDoc) {
0 ignored issues
show
Bug introduced by
The expression $new of type integer|double is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
183 58
                        if ($this->uow->isScheduledForInsert($embeddedDoc)) {
184 42
                            continue;
185
                        }
186
187 45
                        $update = $this->prepareUpdateData($embeddedDoc);
188 45
                        foreach ($update as $cmd => $values) {
189 14
                            foreach ($values as $name => $value) {
190 14
                                $updateData[$cmd][$mapping['name'] . '.' . $key . '.' . $name] = $value;
191
                            }
192
                        }
193
                    }
194
                }
195
196
            // @ReferenceOne
197 16
            } elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE) {
198 12
                if (isset($new) || $mapping['nullable'] === true) {
199 12
                    $updateData['$set'][$mapping['name']] = $new === null ? null : $this->prepareReferencedDocumentValue($mapping, $new);
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
200
                } else {
201 2
                    $updateData['$unset'][$mapping['name']] = true;
202
                }
203
            }
204
        }
205
        // collections that aren't dirty but could be subject to update are
206
        // excluded from change set, let's go through them now
207 228
        foreach ($this->uow->getScheduledCollections($document) as $coll) {
208 105
            $mapping = $coll->getMapping();
209 105
            if (CollectionHelper::isAtomic($mapping['strategy']) && $this->uow->isCollectionScheduledForUpdate($coll)) {
210 3
                $updateData['$set'][$mapping['name']] = $this->prepareAssociatedCollectionValue($coll, true);
211 102
            } elseif (CollectionHelper::isAtomic($mapping['strategy']) && $this->uow->isCollectionScheduledForDeletion($coll)) {
212 1
                $updateData['$unset'][$mapping['name']] = true;
213 1
                $this->uow->unscheduleCollectionDeletion($coll);
214
            }
215
            // @ReferenceMany is handled by CollectionPersister
216
        }
217 228
        return $updateData;
218
    }
219
220
    /**
221
     * Prepares the update query to upsert a given document object in mongodb.
222
     *
223
     * @param object $document
224
     *
225
     * @return array $updateData
226
     */
227 86
    public function prepareUpsertData($document)
228
    {
229 86
        $class     = $this->dm->getClassMetadata(get_class($document));
230 86
        $changeset = $this->uow->getDocumentChangeSet($document);
231
232 86
        $updateData = [];
233 86
        foreach ($changeset as $fieldName => $change) {
234 86
            $mapping = $class->fieldMappings[$fieldName];
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
235
236 86
            [$old, $new] = $change;
0 ignored issues
show
Bug introduced by
The variable $old does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $new does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
237
238
            // Scalar fields
239 86
            if (! isset($mapping['association'])) {
240 86
                if ($new !== null) {
241 86
                    if (empty($mapping['id']) && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadata::STORAGE_STRATEGY_INCREMENT) {
242 3
                        $operator = '$inc';
243 3
                        $value    = Type::getType($mapping['type'])->convertToDatabaseValue($new - $old);
244
                    } else {
245 86
                        $operator = '$set';
246 86
                        $value    = Type::getType($mapping['type'])->convertToDatabaseValue($new);
247
                    }
248
249 86
                    $updateData[$operator][$mapping['name']] = $value;
250 11
                } elseif ($mapping['nullable'] === true) {
251 86
                    $updateData['$setOnInsert'][$mapping['name']] = null;
252
                }
253
254
            // @EmbedOne
255 27
            } elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::EMBED_ONE) {
256
                // If we don't have a new value then do nothing on upsert
257
                // If we have a new embedded document then lets set the whole thing
258 8
                if ($new && $this->uow->isScheduledForInsert($new)) {
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object<Doctrine\ODM\MongoDB\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
259 5
                    $updateData['$set'][$mapping['name']] = $this->prepareEmbeddedDocumentValue($mapping, $new);
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
260 3
                } elseif ($new) {
261
                    // Update existing embedded document
262
                    $update = $this->prepareUpsertData($new);
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
263 8
                    foreach ($update as $cmd => $values) {
264
                        foreach ($values as $key => $value) {
265
                            $updateData[$cmd][$mapping['name'] . '.' . $key] = $value;
266
                        }
267
                    }
268
                }
269
270
            // @ReferenceOne
271 24
            } elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE) {
272 13
                if (isset($new) || $mapping['nullable'] === true) {
273 13
                    $updateData['$set'][$mapping['name']] = $new === null ? null : $this->prepareReferencedDocumentValue($mapping, $new);
0 ignored issues
show
Documentation introduced by
$new is of type integer|double, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
274
                }
275
276
            // @ReferenceMany, @EmbedMany
277 15
            } elseif ($mapping['type'] === ClassMetadata::MANY && ! $mapping['isInverseSide']
278 15
                    && $new instanceof PersistentCollectionInterface && $new->isDirty()
279 15
                    && CollectionHelper::isAtomic($mapping['strategy'])) {
280 1
                $updateData['$set'][$mapping['name']] = $this->prepareAssociatedCollectionValue($new, true);
281
            }
282
            // @EmbedMany and @ReferenceMany are handled by CollectionPersister
283
        }
284
285
        // add discriminator if the class has one
286 86
        if (isset($class->discriminatorField)) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorField on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
287 5
            if ($class->discriminatorValue === null) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
288
                if (! empty($class->discriminatorMap)) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorMap on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
289
                    throw MappingException::unlistedClassInDiscriminatorMap($class->name);
0 ignored issues
show
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
290
                }
291
                $class->discriminatorValue = $class->name;
0 ignored issues
show
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
292
            }
293 5
            $updateData['$set'][$class->discriminatorField] = $class->discriminatorValue;
0 ignored issues
show
Bug introduced by
Accessing discriminatorField on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
294
        }
295
296 86
        return $updateData;
297
    }
298
299
    /**
300
     * Returns the reference representation to be stored in MongoDB.
301
     *
302
     * If the document does not have an identifier and the mapping calls for a
303
     * simple reference, null may be returned.
304
     *
305
     * @param array  $referenceMapping
306
     * @param object $document
307
     *
308
     * @return array|null
309
     */
310 212
    public function prepareReferencedDocumentValue(array $referenceMapping, $document)
311
    {
312 212
        return $this->dm->createReference($document, $referenceMapping);
313
    }
314
315
    /**
316
     * Returns the embedded document to be stored in MongoDB.
317
     *
318
     * The return value will usually be an associative array with string keys
319
     * corresponding to field names on the embedded document. An object may be
320
     * returned if the document is empty, to ensure that a BSON object will be
321
     * stored in lieu of an array.
322
     *
323
     * If $includeNestedCollections is true, nested collections will be included
324
     * in this prepared value and the option will cascade to all embedded
325
     * associations. If any nested PersistentCollections (embed or reference)
326
     * within this value were previously scheduled for deletion or update, they
327
     * will also be unscheduled.
328
     *
329
     * @param array  $embeddedMapping
330
     * @param object $embeddedDocument
331
     * @param bool   $includeNestedCollections
332
     *
333
     * @return array|object
334
     *
335
     * @throws UnexpectedValueException If an unsupported associating mapping is found.
336
     */
337 186
    public function prepareEmbeddedDocumentValue(array $embeddedMapping, $embeddedDocument, $includeNestedCollections = false)
338
    {
339 186
        $embeddedDocumentValue = [];
340 186
        $class                 = $this->dm->getClassMetadata(get_class($embeddedDocument));
341
342 186
        foreach ($class->fieldMappings as $mapping) {
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
343
            // Skip notSaved fields
344 184
            if (! empty($mapping['notSaved'])) {
345 1
                continue;
346
            }
347
348
            // Inline ClassMetadata::getFieldValue()
349 184
            $rawValue = $class->reflFields[$mapping['fieldName']]->getValue($embeddedDocument);
0 ignored issues
show
Bug introduced by
Accessing reflFields on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
350
351 184
            $value = null;
352
353 184
            if ($rawValue !== null) {
354 181
                switch ($mapping['association'] ?? null) {
355
                    // @Field, @String, @Date, etc.
356
                    case null:
357 175
                        $value = Type::getType($mapping['type'])->convertToDatabaseValue($rawValue);
358 175
                        break;
359
360 72
                    case ClassMetadata::EMBED_ONE:
361 69
                    case ClassMetadata::REFERENCE_ONE:
362
                        // Nested collections should only be included for embedded relationships
363 21
                        $value = $this->prepareAssociatedDocumentValue($mapping, $rawValue, $includeNestedCollections && isset($mapping['embedded']));
364 21
                        break;
365
366 53
                    case ClassMetadata::EMBED_MANY:
367 4
                    case ClassMetadata::REFERENCE_MANY:
368
                        // Skip PersistentCollections already scheduled for deletion
369 53
                        if (! $includeNestedCollections && $rawValue instanceof PersistentCollectionInterface
370 53
                            && $this->uow->isCollectionScheduledForDeletion($rawValue)) {
371
                            break;
372
                        }
373
374 53
                        $value = $this->prepareAssociatedCollectionValue($rawValue, $includeNestedCollections);
375 53
                        break;
376
377
                    default:
378
                        throw new UnexpectedValueException('Unsupported mapping association: ' . $mapping['association']);
379
                }
380
            }
381
382
            // Omit non-nullable fields that would have a null value
383 184
            if ($value === null && $mapping['nullable'] === false) {
384 63
                continue;
385
            }
386
387 181
            $embeddedDocumentValue[$mapping['name']] = $value;
388
        }
389
390
        /* Add a discriminator value if the embedded document is not mapped
391
         * explicitly to a targetDocument class.
392
         */
393 186
        if (! isset($embeddedMapping['targetDocument'])) {
394 16
            $discriminatorField = $embeddedMapping['discriminatorField'];
395 16
            if (! empty($embeddedMapping['discriminatorMap'])) {
396 5
                $discriminatorValue = array_search($class->name, $embeddedMapping['discriminatorMap']);
0 ignored issues
show
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
397
398 5
                if ($discriminatorValue === false) {
399 5
                    throw MappingException::unlistedClassInDiscriminatorMap($class->name);
0 ignored issues
show
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
400
                }
401
            } else {
402 11
                $discriminatorValue = $class->name;
0 ignored issues
show
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
403
            }
404
405 15
            $embeddedDocumentValue[$discriminatorField] = $discriminatorValue;
406
        }
407
408
        /* If the class has a discriminator (field and value), use it. A child
409
         * class that is not defined in the discriminator map may only have a
410
         * discriminator field and no value, so default to the full class name.
411
         */
412 185
        if (isset($class->discriminatorField)) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorField on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
413 8
            if ($class->discriminatorValue === null) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
414 4
                if (! empty($class->discriminatorMap)) {
0 ignored issues
show
Bug introduced by
Accessing discriminatorMap on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
415 4
                    throw MappingException::unlistedClassInDiscriminatorMap($class->name);
0 ignored issues
show
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
416
                }
417
                $class->discriminatorValue = $class->name;
0 ignored issues
show
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
418
            }
419 6
            $embeddedDocumentValue[$class->discriminatorField] =  $class->discriminatorValue;
0 ignored issues
show
Bug introduced by
Accessing discriminatorField on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing discriminatorValue on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
420
        }
421
422
        // Ensure empty embedded documents are stored as BSON objects
423 183
        if (empty($embeddedDocumentValue)) {
424 6
            return (object) $embeddedDocumentValue;
425
        }
426
427
        /* @todo Consider always casting the return value to an object, or
428
         * building $embeddedDocumentValue as an object instead of an array, to
429
         * handle the edge case where all database field names are sequential,
430
         * numeric keys.
431
         */
432 179
        return $embeddedDocumentValue;
433
    }
434
435
    /**
436
     * Returns the embedded document or reference representation to be stored.
437
     *
438
     * @param array  $mapping
439
     * @param object $document
440
     * @param bool   $includeNestedCollections
441
     *
442
     * @return array|object|null
443
     *
444
     * @throws InvalidArgumentException If the mapping is neither embedded nor reference.
445
     */
446 21
    public function prepareAssociatedDocumentValue(array $mapping, $document, $includeNestedCollections = false)
447
    {
448 21
        if (isset($mapping['embedded'])) {
449 8
            return $this->prepareEmbeddedDocumentValue($mapping, $document, $includeNestedCollections);
450
        }
451
452 17
        if (isset($mapping['reference'])) {
453 17
            return $this->prepareReferencedDocumentValue($mapping, $document);
454
        }
455
456
        throw new InvalidArgumentException('Mapping is neither embedded nor reference.');
457
    }
458
459
    /**
460
     * Returns the collection representation to be stored and unschedules it afterwards.
461
     *
462
     * @param bool $includeNestedCollections
463
     *
464
     * @return array
465
     */
466 232
    public function prepareAssociatedCollectionValue(PersistentCollectionInterface $coll, $includeNestedCollections = false)
467
    {
468 232
        $mapping  = $coll->getMapping();
469 232
        $pb       = $this;
470 232
        $callback = isset($mapping['embedded'])
471
            ? static function ($v) use ($pb, $mapping, $includeNestedCollections) {
472 125
                return $pb->prepareEmbeddedDocumentValue($mapping, $v, $includeNestedCollections);
473 129
            }
474
            : static function ($v) use ($pb, $mapping) {
475 117
                return $pb->prepareReferencedDocumentValue($mapping, $v);
476 232
            };
477
478 232
        $setData = $coll->map($callback)->toArray();
479 227
        if (CollectionHelper::isList($mapping['strategy'])) {
480 206
            $setData = array_values($setData);
481
        }
482
483 227
        $this->uow->unscheduleCollectionDeletion($coll);
484 227
        $this->uow->unscheduleCollectionUpdate($coll);
485
486 227
        return $setData;
487
    }
488
}
489