Completed
Push — master ( 785c50...2c0a7f )
by Maciej
16s
created

Builder   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 459
Duplicated Lines 0.65 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 93.29%

Importance

Changes 0
Metric Value
wmc 52
lcom 1
cbo 9
dl 3
loc 459
ccs 139
cts 149
cp 0.9329
rs 7.9487
c 0
b 0
f 0

24 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A requireIndexes() 0 5 1
A field() 0 7 1
B prime() 0 19 6
A eagerCursor() 0 8 3
A hydrate() 0 5 1
A refresh() 0 5 1
A find() 0 7 1
A findAndUpdate() 0 7 1
A returnNew() 0 7 1
A findAndRemove() 0 7 1
A readOnly() 0 5 1
A update() 0 7 1
A updateOne() 0 7 1
A updateMany() 0 7 1
A insert() 0 7 1
A remove() 0 7 1
A references() 0 5 1
A includesReferenceTo() 0 5 1
A group() 0 8 1
C getQuery() 0 58 15
A expr() 0 7 1
B setDocumentName() 3 26 5
A getDiscriminatorValues() 0 15 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Builder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Builder, and based on these observations, apply Extract Interface, too.

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\Query;
21
22
use Doctrine\ODM\MongoDB\DocumentManager;
23
use Doctrine\ODM\MongoDB\Hydrator;
24
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo;
25
26
/**
27
 * Query builder for ODM.
28
 *
29
 * @since       1.0
30
 */
31
class Builder extends \Doctrine\MongoDB\Query\Builder
32
{
33
    /**
34
     * The DocumentManager instance for this query
35
     *
36
     * @var DocumentManager
37
     */
38
    private $dm;
39
40
    /**
41
     * The ClassMetadata instance.
42
     *
43
     * @var \Doctrine\ODM\MongoDB\Mapping\ClassMetadata
44
     */
45
    private $class;
46
47
    /**
48
     * The current field we are operating on.
49
     *
50
     * @todo Change this to private once ODM requires doctrine/mongodb 1.1+
51
     * @var string
52
     */
53
    protected $currentField;
54
55
    /**
56
     * Whether or not to hydrate the data to documents.
57
     *
58
     * @var boolean
59
     */
60
    private $hydrate = true;
61
62
    /**
63
     * Whether or not to refresh the data for documents that are already in the identity map.
64
     *
65
     * @var boolean
66
     */
67
    private $refresh = false;
68
69
    /**
70
     * Array of primer Closure instances.
71
     *
72
     * @var array
73
     */
74
    private $primers = array();
75
76
    /**
77
     * Whether or not to require indexes.
78
     *
79
     * @var bool
80
     */
81
    private $requireIndexes;
82
83
    /**
84
     * Whether or not to register documents in UnitOfWork.
85
     *
86
     * @var bool
87
     */
88
    private $readOnly;
89
90
    /**
91
     * Construct a Builder
92
     *
93
     * @param DocumentManager $dm
94
     * @param string[]|string|null $documentName (optional) an array of document names, the document name, or none
95
     */
96 232
    public function __construct(DocumentManager $dm, $documentName = null)
97
    {
98 232
        $this->dm = $dm;
99 232
        $this->expr = new Expr($dm);
100 232
        if ($documentName !== null) {
101 224
            $this->setDocumentName($documentName);
102
        }
103 231
    }
104
105
    /**
106
     * Set whether or not to require indexes.
107
     *
108
     * @param bool $requireIndexes
109
     * @return $this
110
     *
111
     * @deprecated method was deprecated in 1.2 and will be removed in 2.0
112
     */
113 2
    public function requireIndexes($requireIndexes = true)
114
    {
115 2
        $this->requireIndexes = $requireIndexes;
116 2
        return $this;
117
    }
118
119
    /**
120
     * Set the current field to operate on.
121
     *
122
     * @param string $field
123
     * @return $this
124
     */
125 155
    public function field($field)
126
    {
127 155
        $this->currentField = $field;
128 155
        parent::field($field);
129
130 155
        return $this;
131
    }
132
133
    /**
134
     * Use a primer to eagerly load all references in the current field.
135
     *
136
     * If $primer is true or a callable is provided, referenced documents for
137
     * this field will loaded into UnitOfWork immediately after the query is
138
     * executed. This will avoid multiple queries due to lazy initialization of
139
     * Proxy objects.
140
     *
141
     * If $primer is false, no priming will take place. That is also the default
142
     * behavior.
143
     *
144
     * If a custom callable is used, its signature should conform to the default
145
     * Closure defined in {@link ReferencePrimer::__construct()}.
146
     *
147
     * @param boolean|callable $primer
148
     * @return $this
149
     * @throws \InvalidArgumentException If $primer is not boolean or callable
150
     */
151 27
    public function prime($primer = true)
152
    {
153 27
        if ( ! is_bool($primer) && ! is_callable($primer)) {
154 1
            throw new \InvalidArgumentException('$primer is not a boolean or callable');
155
        }
156
157 26
        if ($primer === false) {
158 1
            unset($this->primers[$this->currentField]);
159
160 1
            return $this;
161
        }
162
163 26
        if (array_key_exists('eagerCursor', $this->query) && !$this->query['eagerCursor']) {
164 1
            throw new \BadMethodCallException("Can't call prime() when setting eagerCursor to false");
165
        }
166
167 25
        $this->primers[$this->currentField] = $primer;
168 25
        return $this;
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174 6
    public function eagerCursor($bool = true)
175
    {
176 6
        if ( ! $bool && ! empty($this->primers)) {
177 1
            throw new \BadMethodCallException("Can't set eagerCursor to false when using reference primers");
178
        }
179
180 5
        return parent::eagerCursor($bool);
181
    }
182
183
184
    /**
185
     * @param bool $bool
186
     * @return $this
187
     */
188 16
    public function hydrate($bool = true)
189
    {
190 16
        $this->hydrate = $bool;
191 16
        return $this;
192
    }
193
194
    /**
195
     * @param bool $bool
196
     * @return $this
197
     */
198 2
    public function readOnly($bool = true)
199
    {
200 2
        $this->readOnly = $bool;
201 2
        return $this;
202
    }
203
204
    /**
205
     * @param bool $bool
206
     * @return $this
207
     */
208 5
    public function refresh($bool = true)
209
    {
210 5
        $this->refresh = $bool;
211 5
        return $this;
212
    }
213
214
    /**
215
     * Change the query type to find and optionally set and change the class being queried.
216
     *
217
     * @param string $documentName
218
     * @return $this
219
     */
220 12
    public function find($documentName = null)
221
    {
222 12
        $this->setDocumentName($documentName);
223 12
        parent::find();
224
225 12
        return $this;
226
    }
227
228
    /**
229
     * @param string $documentName
230
     * @return $this
231
     */
232 13
    public function findAndUpdate($documentName = null)
233
    {
234 13
        $this->setDocumentName($documentName);
235 13
        parent::findAndUpdate();
236
237 13
        return $this;
238
    }
239
240
    /**
241
     * @param bool $bool
242
     * @return $this
243
     */
244 4
    public function returnNew($bool = true)
245
    {
246 4
        $this->refresh(true);
247 4
        parent::returnNew($bool);
248
249 4
        return $this;
250
    }
251
252
    /**
253
     * @param string $documentName
254
     * @return $this
255
     */
256 1
    public function findAndRemove($documentName = null)
257
    {
258 1
        $this->setDocumentName($documentName);
259 1
        parent::findAndRemove();
260
261 1
        return $this;
262
    }
263
264
    /**
265
     * @param string $documentName
266
     * @return $this
267
     *
268
     * @deprecated Deprecated in version 1.2 - use updateOne or updateMany instead
269
     */
270 12
    public function update($documentName = null)
271
    {
272 12
        $this->setDocumentName($documentName);
273 12
        parent::update();
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\MongoDB\Query\Builder::update() has been deprecated with message: Deprecated in version 1.4 - use updateOne or updateMany instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
274
275 12
        return $this;
276
    }
277
278
    /**
279
     * @param string $documentName
280
     * @return $this
281
     */
282
    public function updateOne($documentName = null)
283
    {
284
        $this->setDocumentName($documentName);
285
        parent::updateOne();
286
287
        return $this;
288
    }
289
290
    /**
291
     * @param string $documentName
292
     * @return $this
293
     */
294
    public function updateMany($documentName = null)
295
    {
296
        $this->setDocumentName($documentName);
297
        parent::updateMany();
298
299
        return $this;
300
    }
301
302
    /**
303
     * @param string $documentName
304
     * @return $this
305
     */
306 1
    public function insert($documentName = null)
307
    {
308 1
        $this->setDocumentName($documentName);
309 1
        parent::insert();
310
311 1
        return $this;
312
    }
313
314
    /**
315
     * @param string $documentName
316
     * @return $this
317
     */
318 1
    public function remove($documentName = null)
319
    {
320 1
        $this->setDocumentName($documentName);
321 1
        parent::remove();
322
323 1
        return $this;
324
    }
325
326
    /**
327
     * @param object $document
328
     * @return $this
329
     */
330 11
    public function references($document)
331
    {
332 11
        $this->expr->references($document);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Doctrine\MongoDB\Query\Expr as the method references() does only exist in the following sub-classes of Doctrine\MongoDB\Query\Expr: Doctrine\ODM\MongoDB\Query\Expr. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
333 9
        return $this;
334
    }
335
336
    /**
337
     * @param object $document
338
     * @return $this
339
     */
340 7
    public function includesReferenceTo($document)
341
    {
342 7
        $this->expr->includesReferenceTo($document);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Doctrine\MongoDB\Query\Expr as the method includesReferenceTo() does only exist in the following sub-classes of Doctrine\MongoDB\Query\Expr: Doctrine\ODM\MongoDB\Query\Expr. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
343 5
        return $this;
344
    }
345
346
    /**
347
     * @inheritdoc
348
     * @deprecated Deprecated in version 1.2 - use Aggregation Builder's group stage instead.
349
     */
350 1
    public function group($keys, array $initial, $reduce = null, array $options = [])
351
    {
352 1
        @trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
353 1
            sprintf('%s was deprecated in version 1.2 - use Aggregation Builder\'s group stage instead.', __METHOD__),
354 1
            E_USER_DEPRECATED
355
        );
356 1
        return parent::group($keys, $initial, $reduce, $options);
357
    }
358
359
    /**
360
     * Gets the Query executable.
361
     *
362
     * @param array $options
363
     * @return Query $query
364
     */
365 201
    public function getQuery(array $options = array())
366
    {
367 201
        if ($this->query['type'] === Query::TYPE_MAP_REDUCE) {
368 3
            $this->hydrate = false;
369
        }
370
371 201
        $documentPersister = $this->dm->getUnitOfWork()->getDocumentPersister($this->class->name);
372
373 201
        $query = $this->query;
374
375 201
        $query['query'] = $this->expr->getQuery();
376 201
        $query['query'] = $documentPersister->addDiscriminatorToPreparedQuery($query['query']);
0 ignored issues
show
Documentation introduced by
$query['query'] is of type string, but the function expects a array.

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...
377 201
        $query['query'] = $documentPersister->addFilterToPreparedQuery($query['query']);
378
379 201
        $query['newObj'] = $this->expr->getNewObj();
380
381 201
        if (isset($query['distinct'])) {
382 2
            $query['distinct'] = $documentPersister->prepareFieldName($query['distinct']);
0 ignored issues
show
Bug introduced by
It seems like $query['distinct'] can also be of type array; however, Doctrine\ODM\MongoDB\Per...ter::prepareFieldName() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
383
        }
384
385 201
        if ($this->class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION && ! empty($query['upsert']) &&
386 3
            (empty($query['query'][$this->class->discriminatorField]) || is_array($query['query'][$this->class->discriminatorField]))) {
387 1
            throw new \InvalidArgumentException('Upsert query that is to be performed on discriminated document does not have single ' .
388 1
                'discriminator. Either not use base class or set \'' . $this->class->discriminatorField . '\' field manually.');
389
        }
390
391 200
        if ( ! empty($query['select'])) {
392 14
            $query['select'] = $documentPersister->prepareSortOrProjection($query['select']);
393 14
            if ($this->hydrate && $this->class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION
394 2
                && ! isset($query['select'][$this->class->discriminatorField])) {
395
                $includeMode = 0 < count(array_filter($query['select'], function($mode) { return $mode == 1; }));
396 2
                if ($includeMode && ! isset($query['select'][$this->class->discriminatorField])) {
397 1
                    $query['select'][$this->class->discriminatorField] = 1;
398
                }
399
            }
400
        }
401
402 200
        if (isset($query['sort'])) {
403 28
            $query['sort'] = $documentPersister->prepareSortOrProjection($query['sort']);
404
        }
405
406 200
        if ($this->class->slaveOkay) {
407 1
            $query['slaveOkay'] = $this->class->slaveOkay;
408
        }
409
410 200
        return new Query(
411 200
            $this->dm,
412 200
            $this->class,
413 200
            $this->collection,
414
            $query,
415
            $options,
416 200
            $this->hydrate,
417 200
            $this->refresh,
418 200
            $this->primers,
419 200
            $this->requireIndexes,
420 200
            $this->readOnly
421
        );
422
    }
423
424
    /**
425
     * Create a new Expr instance that can be used as an expression with the Builder
426
     *
427
     * @return Expr $expr
428
     */
429 25
    public function expr()
430
    {
431 25
        $expr = new Expr($this->dm);
432 25
        $expr->setClassMetadata($this->class);
433
434 25
        return $expr;
435
    }
436
437
    /**
438
     * @param string[]|string $documentName an array of document names or just one.
439
     */
440 231
    private function setDocumentName($documentName)
441
    {
442 231
        if (is_array($documentName)) {
443 2
            $documentNames = $documentName;
444 2
            $documentName = $documentNames[0];
445
446 2
            $metadata = $this->dm->getClassMetadata($documentName);
447 2
            $discriminatorField = $metadata->discriminatorField;
448 2
            $discriminatorValues = $this->getDiscriminatorValues($documentNames);
449
450
            // If a defaultDiscriminatorValue is set and it is among the discriminators being queries, add NULL to the list
451 1 View Code Duplication
            if ($metadata->defaultDiscriminatorValue && array_search($metadata->defaultDiscriminatorValue, $discriminatorValues) !== false) {
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...
452 1
                $discriminatorValues[] = null;
453
            }
454
455 1
            $this->field($discriminatorField)->in($discriminatorValues);
456
        }
457
458 230
        if ($documentName !== null) {
459 230
            $this->collection = $this->dm->getDocumentCollection($documentName);
460 230
            $this->class = $this->dm->getClassMetadata($documentName);
461
462
            // Expr also needs to know
463 230
            $this->expr->setClassMetadata($this->class);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Doctrine\MongoDB\Query\Expr as the method setClassMetadata() does only exist in the following sub-classes of Doctrine\MongoDB\Query\Expr: Doctrine\ODM\MongoDB\Query\Expr. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
464
        }
465 230
    }
466
467
    /**
468
     * Get Discriminator Values
469
     *
470
     * @param \Iterator|array $classNames
471
     * @return array an array of discriminatorValues (mixed type)
472
     * @throws \InvalidArgumentException if the number of found collections > 1
473
     */
474 2
    private function getDiscriminatorValues($classNames)
475
    {
476 2
        $discriminatorValues = array();
477 2
        $collections = array();
478 2
        foreach ($classNames as $className) {
479 2
            $class = $this->dm->getClassMetadata($className);
480 2
            $discriminatorValues[] = $class->discriminatorValue;
481 2
            $key = $this->dm->getDocumentDatabase($className)->getName() . '.' . $class->getCollection();
482 2
            $collections[$key] = $key;
483
        }
484 2
        if (count($collections) > 1) {
485 1
            throw new \InvalidArgumentException('Documents involved are not all mapped to the same database collection.');
486
        }
487 1
        return $discriminatorValues;
488
    }
489
}
490