Completed
Pull Request — master (#1714)
by
unknown
11:18
created

Expr::requiresCurrentField()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 4
cp 0.75
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 0
crap 2.0625
1
<?php
2
3
namespace Doctrine\ODM\MongoDB\Query;
4
5
use Doctrine\ODM\MongoDB\DocumentManager;
6
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
7
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo;
8
use Doctrine\ODM\MongoDB\Mapping\MappingException;
9
use GeoJson\Geometry\Geometry;
10
use GeoJson\Geometry\Point;
11
12
/**
13
 * Query expression builder for ODM.
14
 *
15
 * @since       1.0
16
 */
17
class Expr
18
{
19
    /**
20
     * The query criteria array.
21
     *
22
     * @var array
23
     */
24
    private $query = [];
25
26
    /**
27
     * The "new object" array containing either a full document or a number of
28
     * atomic update operators.
29
     *
30
     * @see docs.mongodb.org/manual/reference/method/db.collection.update/#update-parameter
31
     * @var array
32
     */
33
    private $newObj = [];
34
35
    /**
36
     * The current field we are operating on.
37
     *
38
     * @var string
39
     */
40
    private $currentField;
41
42
    /**
43
     * The DocumentManager instance for this query
44
     *
45
     * @var DocumentManager
46
     */
47
    private $dm;
48
49
    /**
50
     * The ClassMetadata instance for the document being queried
51
     *
52
     * @var ClassMetadata
53
     */
54
    private $class;
55
56
    /**
57
     * @param DocumentManager $dm
58
     */
59 404
    public function __construct(DocumentManager $dm)
60
    {
61 404
        $this->dm = $dm;
62 404
    }
63
64
    /**
65
     * Add one or more $and clauses to the current query.
66
     *
67
     * @see Builder::addAnd()
68
     * @see http://docs.mongodb.org/manual/reference/operator/and/
69
     * @param array|Expr $expression
70
     * @return $this
71
     */
72 3 View Code Duplication
    public function addAnd($expression /*, $expression2, ... */)
0 ignored issues
show
Unused Code introduced by
The parameter $expression is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in 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...
73
    {
74 3
        if (! isset($this->query['$and'])) {
75 3
            $this->query['$and'] = [];
76
        }
77
78 3
        $this->query['$and'] = array_merge(
79 3
            $this->query['$and'],
80 3
            array_map(
81 3
                function ($expression) {
82 3
                    return $expression instanceof Expr ? $expression->getQuery() : $expression;
83 3
                },
84 3
                func_get_args()
85
            )
86
        );
87
88 3
        return $this;
89
    }
90
91
    /**
92
     * Append multiple values to the current array field only if they do not
93
     * already exist in the array.
94
     *
95
     * If the field does not exist, it will be set to an array containing the
96
     * unique values in the argument. If the field is not an array, the query
97
     * will yield an error.
98
     *
99
     * @deprecated 1.1 Use {@link Expr::addToSet()} with {@link Expr::each()}; Will be removed in 2.0
100
     * @see Builder::addManyToSet()
101
     * @see http://docs.mongodb.org/manual/reference/operator/addToSet/
102
     * @see http://docs.mongodb.org/manual/reference/operator/each/
103
     * @param array $values
104
     * @return $this
105
     */
106 1
    public function addManyToSet(array $values)
107
    {
108 1
        $this->requiresCurrentField();
109 1
        $this->newObj['$addToSet'][$this->currentField] = ['$each' => $values];
110 1
        return $this;
111
    }
112
113
    /**
114
     * Add one or more $nor clauses to the current query.
115
     *
116
     * @see Builder::addNor()
117
     * @see http://docs.mongodb.org/manual/reference/operator/nor/
118
     * @param array|Expr $expression
119
     * @return $this
120
     */
121 1 View Code Duplication
    public function addNor($expression /* , $expression2, ... */)
0 ignored issues
show
Unused Code introduced by
The parameter $expression is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in 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...
122
    {
123 1
        if (! isset($this->query['$nor'])) {
124 1
            $this->query['$nor'] = [];
125
        }
126
127 1
        $this->query['$nor'] = array_merge(
128 1
            $this->query['$nor'],
129
            array_map(function ($expression) { return $expression instanceof Expr ? $expression->getQuery() : $expression; }, func_get_args())
130
        );
131
132 1
        return $this;
133
    }
134
135
    /**
136
     * Add one or more $or clauses to the current query.
137
     *
138
     * @see Builder::addOr()
139
     * @see http://docs.mongodb.org/manual/reference/operator/or/
140
     * @param array|Expr $expression
141
     * @return $this
142
     */
143 5 View Code Duplication
    public function addOr($expression /* , $expression2, ... */)
0 ignored issues
show
Unused Code introduced by
The parameter $expression is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in 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...
144
    {
145 5
        if (! isset($this->query['$or'])) {
146 5
            $this->query['$or'] = [];
147
        }
148
149 5
        $this->query['$or'] = array_merge(
150 5
            $this->query['$or'],
151
            array_map(function ($expression) { return $expression instanceof Expr ? $expression->getQuery() : $expression; }, func_get_args())
152
        );
153
154 5
        return $this;
155
    }
156
157
    /**
158
     * Append one or more values to the current array field only if they do not
159
     * already exist in the array.
160
     *
161
     * If the field does not exist, it will be set to an array containing the
162
     * unique value(s) in the argument. If the field is not an array, the query
163
     * will yield an error.
164
     *
165
     * Multiple values may be specified by provided an Expr object and using
166
     * {@link Expr::each()}.
167
     *
168
     * @see Builder::addToSet()
169
     * @see http://docs.mongodb.org/manual/reference/operator/addToSet/
170
     * @see http://docs.mongodb.org/manual/reference/operator/each/
171
     * @param mixed|Expr $valueOrExpression
172
     * @return $this
173
     */
174 5 View Code Duplication
    public function addToSet($valueOrExpression)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
175
    {
176 5
        if ($valueOrExpression instanceof Expr) {
177 1
            $valueOrExpression = $valueOrExpression->getQuery();
178
        }
179
180 5
        $this->requiresCurrentField();
181 5
        $this->newObj['$addToSet'][$this->currentField] = $valueOrExpression;
182 5
        return $this;
183
    }
184
185
    /**
186
     * Specify $all criteria for the current field.
187
     *
188
     * @see Builder::all()
189
     * @see http://docs.mongodb.org/manual/reference/operator/all/
190
     * @param array $values
191
     * @return $this
192
     */
193 2
    public function all(array $values)
194
    {
195 2
        return $this->operator('$all', (array) $values);
196
    }
197
198
    /**
199
     * Apply a bitwise operation on the current field
200
     *
201
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
202
     * @param string $operator
203
     * @param int $value
204
     * @return $this
205
     */
206 3
    protected function bit($operator, $value)
207
    {
208 3
        $this->requiresCurrentField();
209 3
        $this->newObj['$bit'][$this->currentField][$operator] = $value;
210 3
        return $this;
211
    }
212
213
    /**
214
     * Apply a bitwise and operation on the current field.
215
     *
216
     * @see Builder::bitAnd()
217
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
218
     * @param int $value
219
     * @return $this
220
     */
221 1
    public function bitAnd($value)
222
    {
223 1
        return $this->bit('and', $value);
224
    }
225
226
    /**
227
     * Apply a bitwise or operation on the current field.
228
     *
229
     * @see Builder::bitOr()
230
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
231
     * @param int $value
232
     * @return $this
233
     */
234 1
    public function bitOr($value)
235
    {
236 1
        return $this->bit('or', $value);
237
    }
238
239
    /**
240
     * Matches documents where all of the bit positions given by the query are
241
     * clear.
242
     *
243
     * @see Builder::bitsAllClear()
244
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAllClear/
245
     * @param int|array|\MongoDB\BSON\Binary $value
246
     * @return $this
247
     */
248
    public function bitsAllClear($value)
249
    {
250
        $this->requiresCurrentField();
251
        return $this->operator('$bitsAllClear', $value);
252
    }
253
254
    /**
255
     * Matches documents where all of the bit positions given by the query are
256
     * set.
257
     *
258
     * @see Builder::bitsAllSet()
259
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAllSet/
260
     * @param int|array|\MongoDB\BSON\Binary $value
261
     * @return $this
262
     */
263
    public function bitsAllSet($value)
264
    {
265
        $this->requiresCurrentField();
266
        return $this->operator('$bitsAllSet', $value);
267
    }
268
269
    /**
270
     * Matches documents where any of the bit positions given by the query are
271
     * clear.
272
     *
273
     * @see Builder::bitsAnyClear()
274
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAnyClear/
275
     * @param int|array|\MongoDB\BSON\Binary $value
276
     * @return $this
277
     */
278
    public function bitsAnyClear($value)
279
    {
280
        $this->requiresCurrentField();
281
        return $this->operator('$bitsAnyClear', $value);
282
    }
283
284
    /**
285
     * Matches documents where any of the bit positions given by the query are
286
     * set.
287
     *
288
     * @see Builder::bitsAnySet()
289
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAnySet/
290
     * @param int|array|\MongoDB\BSON\Binary $value
291
     * @return $this
292
     */
293
    public function bitsAnySet($value)
294
    {
295
        $this->requiresCurrentField();
296
        return $this->operator('$bitsAnySet', $value);
297
    }
298
299
    /**
300
     * Apply a bitwise xor operation on the current field.
301
     *
302
     * @see Builder::bitXor()
303
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
304
     * @param int $value
305
     * @return $this
306
     */
307 1
    public function bitXor($value)
308
    {
309 1
        return $this->bit('xor', $value);
310
    }
311
312
    /**
313
     * A boolean flag to enable or disable case sensitive search for $text
314
     * criteria.
315
     *
316
     * This method must be called after text().
317
     *
318
     * @see Builder::caseSensitive()
319
     * @see http://docs.mongodb.org/manual/reference/operator/text/
320
     * @param bool $caseSensitive
321
     * @return $this
322
     * @throws \BadMethodCallException if the query does not already have $text criteria
323
     *
324
     * @since 1.3
325
     */
326 3 View Code Duplication
    public function caseSensitive($caseSensitive)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
327
    {
328 3
        if ( ! isset($this->query['$text'])) {
329 1
            throw new \BadMethodCallException('This method requires a $text operator (call text() first)');
330
        }
331
332
        // Remove caseSensitive option to keep support for older database versions
333 2
        if ($caseSensitive) {
334 2
            $this->query['$text']['$caseSensitive'] = true;
335 1
        } elseif (isset($this->query['$text']['$caseSensitive'])) {
336 1
            unset($this->query['$text']['$caseSensitive']);
337
        }
338
339 2
        return $this;
340
    }
341
342
    /**
343
     * Associates a comment to any expression taking a query predicate.
344
     *
345
     * @see Builder::comment()
346
     * @see http://docs.mongodb.org/manual/reference/operator/query/comment/
347
     * @param string $comment
348
     * @return $this
349
     */
350
    public function comment($comment)
351
    {
352
        $this->query['$comment'] = $comment;
353
        return $this;
354
    }
355
356
    /**
357
     * Sets the value of the current field to the current date, either as a date or a timestamp.
358
     *
359
     * @see Builder::currentDate()
360
     * @see http://docs.mongodb.org/manual/reference/operator/update/currentDate/
361
     * @param string $type
362
     * @return $this
363
     * @throws \InvalidArgumentException if an invalid type is given
364
     */
365 3
    public function currentDate($type = 'date')
366
    {
367 3
        if (! in_array($type, ['date', 'timestamp'])) {
368 1
            throw new \InvalidArgumentException('Type for currentDate operator must be date or timestamp.');
369
        }
370
371 2
        $this->requiresCurrentField();
372 2
        $this->newObj['$currentDate'][$this->currentField]['$type'] = $type;
373 2
        return $this;
374
    }
375
376
    /**
377
     * A boolean flag to enable or disable diacritic sensitive search for $text
378
     * criteria.
379
     *
380
     * This method must be called after text().
381
     *
382
     * @see Builder::diacriticSensitive()
383
     * @see http://docs.mongodb.org/manual/reference/operator/text/
384
     * @param bool $diacriticSensitive
385
     * @return $this
386
     * @throws \BadMethodCallException if the query does not already have $text criteria
387
     *
388
     * @since 1.3
389
     */
390 3 View Code Duplication
    public function diacriticSensitive($diacriticSensitive)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
391
    {
392 3
        if ( ! isset($this->query['$text'])) {
393 1
            throw new \BadMethodCallException('This method requires a $text operator (call text() first)');
394
        }
395
396
        // Remove diacriticSensitive option to keep support for older database versions
397 2
        if ($diacriticSensitive) {
398 2
            $this->query['$text']['$diacriticSensitive'] = true;
399 1
        } elseif (isset($this->query['$text']['$diacriticSensitive'])) {
400 1
            unset($this->query['$text']['$diacriticSensitive']);
401
        }
402
403 2
        return $this;
404
    }
405
406
    /**
407
     * Add $each criteria to the expression for a $push operation.
408
     *
409
     * @see Expr::push()
410
     * @see http://docs.mongodb.org/manual/reference/operator/each/
411
     * @param array $values
412
     * @return $this
413
     */
414 4
    public function each(array $values)
415
    {
416 4
        return $this->operator('$each', $values);
417
    }
418
419
    /**
420
     * Specify $elemMatch criteria for the current field.
421
     *
422
     * @see Builder::elemMatch()
423
     * @see http://docs.mongodb.org/manual/reference/operator/elemMatch/
424
     * @param array|Expr $expression
425
     * @return $this
426
     */
427 4
    public function elemMatch($expression)
428
    {
429 4
        return $this->operator('$elemMatch', $expression instanceof Expr ? $expression->getQuery() : $expression);
430
    }
431
432
    /**
433
     * Specify an equality match for the current field.
434
     *
435
     * @see Builder::equals()
436
     * @param mixed $value
437
     * @return $this
438
     */
439 100
    public function equals($value)
440
    {
441 100
        if ($this->currentField) {
442 99
            $this->query[$this->currentField] = $value;
443
        } else {
444 1
            $this->query = $value;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value of type * is incompatible with the declared type array of property $query.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
445
        }
446 100
        return $this;
447
    }
448
449
    /**
450
     * Specify $exists criteria for the current field.
451
     *
452
     * @see Builder::exists()
453
     * @see http://docs.mongodb.org/manual/reference/operator/exists/
454
     * @param boolean $bool
455
     * @return $this
456
     */
457 5
    public function exists($bool)
458
    {
459 5
        return $this->operator('$exists', (boolean) $bool);
460
    }
461
462
    /**
463
     * Set the current field for building the expression.
464
     *
465
     * @see Builder::field()
466
     * @param string $field
467
     * @return $this
468
     */
469 192
    public function field($field)
470
    {
471 192
        $this->currentField = (string) $field;
472 192
        return $this;
473
    }
474
475
    /**
476
     * Add $geoIntersects criteria with a GeoJSON geometry to the expression.
477
     *
478
     * The geometry parameter GeoJSON object or an array corresponding to the
479
     * geometry's JSON representation.
480
     *
481
     * @see Builder::geoIntersects()
482
     * @see http://docs.mongodb.org/manual/reference/operator/geoIntersects/
483
     * @param array|Geometry $geometry
484
     * @return $this
485
     */
486 2 View Code Duplication
    public function geoIntersects($geometry)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
487
    {
488 2
        if ($geometry instanceof Geometry) {
0 ignored issues
show
Bug introduced by
The class GeoJson\Geometry\Geometry does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
489 1
            $geometry = $geometry->jsonSerialize();
490
        }
491
492 2
        return $this->operator('$geoIntersects', ['$geometry' => $geometry]);
493
    }
494
495
    /**
496
     * Add $geoWithin criteria with a GeoJSON geometry to the expression.
497
     *
498
     * The geometry parameter GeoJSON object or an array corresponding to the
499
     * geometry's JSON representation.
500
     *
501
     * @see Builder::geoWithin()
502
     * @see http://docs.mongodb.org/manual/reference/operator/geoIntersects/
503
     * @param array|Geometry $geometry
504
     * @return $this
505
     */
506 2 View Code Duplication
    public function geoWithin($geometry)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
507
    {
508 2
        if ($geometry instanceof Geometry) {
0 ignored issues
show
Bug introduced by
The class GeoJson\Geometry\Geometry does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
509 1
            $geometry = $geometry->jsonSerialize();
510
        }
511
512 2
        return $this->operator('$geoWithin', ['$geometry' => $geometry]);
513
    }
514
515
    /**
516
     * Add $geoWithin criteria with a $box shape to the expression.
517
     *
518
     * A rectangular polygon will be constructed from a pair of coordinates
519
     * corresponding to the bottom left and top right corners.
520
     *
521
     * Note: the $box operator only supports legacy coordinate pairs and 2d
522
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
523
     *
524
     * @see Builder::geoWithinBox()
525
     * @see http://docs.mongodb.org/manual/reference/operator/box/
526
     * @param float $x1
527
     * @param float $y1
528
     * @param float $x2
529
     * @param float $y2
530
     * @return $this
531
     */
532 1
    public function geoWithinBox($x1, $y1, $x2, $y2)
533
    {
534 1
        $shape = ['$box' => [[$x1, $y1], [$x2, $y2]]];
535
536 1
        return $this->operator('$geoWithin', $shape);
537
    }
538
539
    /**
540
     * Add $geoWithin criteria with a $center shape to the expression.
541
     *
542
     * Note: the $center operator only supports legacy coordinate pairs and 2d
543
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
544
     *
545
     * @see Builider::geoWithinCenter()
546
     * @see http://docs.mongodb.org/manual/reference/operator/center/
547
     * @param float $x
548
     * @param float $y
549
     * @param float $radius
550
     * @return $this
551
     */
552 1
    public function geoWithinCenter($x, $y, $radius)
553
    {
554 1
        $shape = ['$center' => [[$x, $y], $radius]];
555
556 1
        return $this->operator('$geoWithin', $shape);
557
    }
558
559
    /**
560
     * Add $geoWithin criteria with a $centerSphere shape to the expression.
561
     *
562
     * Note: the $centerSphere operator supports both 2d and 2dsphere indexes.
563
     *
564
     * @see Builder::geoWithinCenterSphere()
565
     * @see http://docs.mongodb.org/manual/reference/operator/centerSphere/
566
     * @param float $x
567
     * @param float $y
568
     * @param float $radius
569
     * @return $this
570
     */
571 1
    public function geoWithinCenterSphere($x, $y, $radius)
572
    {
573 1
        $shape = ['$centerSphere' => [[$x, $y], $radius]];
574
575 1
        return $this->operator('$geoWithin', $shape);
576
    }
577
578
    /**
579
     * Add $geoWithin criteria with a $polygon shape to the expression.
580
     *
581
     * Point coordinates are in x, y order (easting, northing for projected
582
     * coordinates, longitude, latitude for geographic coordinates).
583
     *
584
     * The last point coordinate is implicitly connected with the first.
585
     *
586
     * Note: the $polygon operator only supports legacy coordinate pairs and 2d
587
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
588
     *
589
     * @see Builder::geoWithinPolygon()
590
     * @see http://docs.mongodb.org/manual/reference/operator/polygon/
591
     * @param array $point,... Three or more point coordinate tuples
0 ignored issues
show
Bug introduced by
There is no parameter named $point,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
592
     * @return $this
593
     * @throws \InvalidArgumentException if less than three points are given
594
     */
595 2 View Code Duplication
    public function geoWithinPolygon(/* array($x1, $y1), ... */)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
596
    {
597 2
        if (func_num_args() < 3) {
598 1
            throw new \InvalidArgumentException('Polygon must be defined by three or more points.');
599
        }
600
601 1
        $shape = ['$polygon' => func_get_args()];
602
603 1
        return $this->operator('$geoWithin', $shape);
604
    }
605
606
    /**
607
     * Return the current field.
608
     *
609
     * @return string
610
     */
611 2
    public function getCurrentField()
612
    {
613 2
        return $this->currentField;
614
    }
615
616
    /**
617
     * Gets prepared newObj part of expression.
618
     *
619
     * @return array
620
     */
621 175
    public function getNewObj()
622
    {
623 175
        return $this->dm->getUnitOfWork()
624 175
            ->getDocumentPersister($this->class->name)
625 175
            ->prepareQueryOrNewObj($this->newObj, true);
626
    }
627
628
    /**
629
     * Gets prepared query part of expression.
630
     *
631
     * @return array
632
     */
633 254
    public function getQuery()
634
    {
635 254
        return $this->dm->getUnitOfWork()
636 254
            ->getDocumentPersister($this->class->name)
637 254
            ->prepareQueryOrNewObj($this->query);
638
    }
639
640
    /**
641
     * Specify $gt criteria for the current field.
642
     *
643
     * @see Builder::gt()
644
     * @see http://docs.mongodb.org/manual/reference/operator/gt/
645
     * @param mixed $value
646
     * @return $this
647
     */
648 2
    public function gt($value)
649
    {
650 2
        return $this->operator('$gt', $value);
651
    }
652
653
    /**
654
     * Specify $gte criteria for the current field.
655
     *
656
     * @see Builder::gte()
657
     * @see http://docs.mongodb.org/manual/reference/operator/gte/
658
     * @param mixed $value
659
     * @return $this
660
     */
661 2
    public function gte($value)
662
    {
663 2
        return $this->operator('$gte', $value);
664
    }
665
666
    /**
667
     * Specify $in criteria for the current field.
668
     *
669
     * @see Builder::in()
670
     * @see http://docs.mongodb.org/manual/reference/operator/in/
671
     * @param array $values
672
     * @return $this
673
     */
674 31
    public function in(array $values)
675
    {
676 31
        return $this->operator('$in', array_values($values));
677
    }
678
679
    /**
680
     * Increment the current field.
681
     *
682
     * If the field does not exist, it will be set to this value.
683
     *
684
     * @see Builder::inc()
685
     * @see http://docs.mongodb.org/manual/reference/operator/inc/
686
     * @param float|integer $value
687
     * @return $this
688
     */
689 5
    public function inc($value)
690
    {
691 5
        $this->requiresCurrentField();
692 5
        $this->newObj['$inc'][$this->currentField] = $value;
693 5
        return $this;
694
    }
695
696
    /**
697
     * Checks that the current field includes a reference to the supplied document.
698
     *
699
     * @param object $document
700
     * @return Expr
701
     */
702 6
    public function includesReferenceTo($document)
703
    {
704 6
        if ($this->currentField) {
705 6
            $mapping = $this->getReferenceMapping();
706 4
            $reference = $this->dm->createReference($document, $mapping);
707 4
            $storeAs = array_key_exists('storeAs', $mapping) ? $mapping['storeAs'] : null;
708 4
            $keys = [];
0 ignored issues
show
Unused Code introduced by
$keys is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
709
710 View Code Duplication
            switch ($storeAs) {
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...
711 4
                case ClassMetadataInfo::REFERENCE_STORE_AS_ID:
712 2
                    $this->query[$mapping['name']] = $reference;
713 2
                    return $this;
714
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
715
716 3
                case ClassMetadataInfo::REFERENCE_STORE_AS_REF:
717
                    $keys = ['id' => true];
718
                    break;
719
720 3
                case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF:
721 1
                case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB:
722 3
                    $keys = ['$ref' => true, '$id' => true, '$db' => true];
723
724 3
                    if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF) {
725 2
                        unset($keys['$db']);
726
                    }
727
728 3
                    if (isset($mapping['targetDocument'])) {
729 1
                        unset($keys['$ref'], $keys['$db']);
730
                    }
731 3
                    break;
732
733
                default:
734
                    throw new \InvalidArgumentException("Reference type {$storeAs} is invalid.");
735
            }
736
737 3 View Code Duplication
            foreach ($keys as $key => $value) {
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...
738 3
                $this->query[$mapping['name']]['$elemMatch'][$key] = $reference[$key];
739
            }
740 View Code Duplication
        } else {
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...
741
            @trigger_error('Calling ' . __METHOD__ . ' without a current field set will no longer be possible in ODM 2.0.', E_USER_DEPRECATED);
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...
742
743
            $this->query['$elemMatch'] = $this->dm->createDBRef($document);
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\ODM\MongoDB\Doc...tManager::createDBRef() has been deprecated with message: Deprecated in favor of createReference; will be removed in 2.0

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...
744
        }
745
746 3
        return $this;
747
    }
748
749
    /**
750
     * Set the $language option for $text criteria.
751
     *
752
     * This method must be called after text().
753
     *
754
     * @see Builder::language()
755
     * @see http://docs.mongodb.org/manual/reference/operator/text/
756
     * @param string $language
757
     * @return $this
758
     * @throws \BadMethodCallException if the query does not already have $text criteria
759
     */
760 2
    public function language($language)
761
    {
762 2
        if ( ! isset($this->query['$text'])) {
763 1
            throw new \BadMethodCallException('This method requires a $text operator (call text() first)');
764
        }
765
766 1
        $this->query['$text']['$language'] = (string) $language;
767
768 1
        return $this;
769
    }
770
771
    /**
772
     * Specify $lt criteria for the current field.
773
     *
774
     * @see Builder::lte()
775
     * @see http://docs.mongodb.org/manual/reference/operator/lte/
776
     * @param mixed $value
777
     * @return $this
778
     */
779 4
    public function lt($value)
780
    {
781 4
        return $this->operator('$lt', $value);
782
    }
783
784
    /**
785
     * Specify $lte criteria for the current field.
786
     *
787
     * @see Builder::lte()
788
     * @see http://docs.mongodb.org/manual/reference/operator/lte/
789
     * @param mixed $value
790
     * @return $this
791
     */
792 2
    public function lte($value)
793
    {
794 2
        return $this->operator('$lte', $value);
795
    }
796
797
    /**
798
     * Updates the value of the field to a specified value if the specified value is greater than the current value of the field.
799
     *
800
     * @see Builder::max()
801
     * @see http://docs.mongodb.org/manual/reference/operator/update/max/
802
     * @param mixed $value
803
     * @return $this
804
     */
805
    public function max($value)
806
    {
807
        $this->requiresCurrentField();
808
        $this->newObj['$max'][$this->currentField] = $value;
809
        return $this;
810
    }
811
812
    /**
813
     * Updates the value of the field to a specified value if the specified value is less than the current value of the field.
814
     *
815
     * @see Builder::min()
816
     * @see http://docs.mongodb.org/manual/reference/operator/update/min/
817
     * @param mixed $value
818
     * @return $this
819
     */
820
    public function min($value)
821
    {
822
        $this->requiresCurrentField();
823
        $this->newObj['$min'][$this->currentField] = $value;
824
        return $this;
825
    }
826
827
    /**
828
     * Specify $mod criteria for the current field.
829
     *
830
     * @see Builder::mod()
831
     * @see http://docs.mongodb.org/manual/reference/operator/mod/
832
     * @param float|integer $divisor
833
     * @param float|integer $remainder
834
     * @return $this
835
     */
836
    public function mod($divisor, $remainder = 0)
837
    {
838
        return $this->operator('$mod', [$divisor, $remainder]);
839
    }
840
841
    /**
842
     * Multiply the current field.
843
     *
844
     * If the field does not exist, it will be set to 0.
845
     *
846
     * @see Builder::mul()
847
     * @see http://docs.mongodb.org/manual/reference/operator/mul/
848
     * @param float|integer $value
849
     * @return $this
850
     */
851
    public function mul($value)
852
    {
853
        $this->requiresCurrentField();
854
        $this->newObj['$mul'][$this->currentField] = $value;
855
        return $this;
856
    }
857
858
    /**
859
     * Add $near criteria to the expression.
860
     *
861
     * A GeoJSON point may be provided as the first and only argument for
862
     * 2dsphere queries. This single parameter may be a GeoJSON point object or
863
     * an array corresponding to the point's JSON representation.
864
     *
865
     * @see Builder::near()
866
     * @see http://docs.mongodb.org/manual/reference/operator/near/
867
     * @param float|array|Point $x
868
     * @param float $y
869
     * @return $this
870
     */
871 3 View Code Duplication
    public function near($x, $y = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
872
    {
873 3
        if ($x instanceof Point) {
0 ignored issues
show
Bug introduced by
The class GeoJson\Geometry\Point does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
874 1
            $x = $x->jsonSerialize();
875
        }
876
877 3
        if (is_array($x)) {
878 2
            return $this->operator('$near', ['$geometry' => $x]);
879
        }
880
881 1
        return $this->operator('$near', [$x, $y]);
882
    }
883
884
    /**
885
     * Add $nearSphere criteria to the expression.
886
     *
887
     * A GeoJSON point may be provided as the first and only argument for
888
     * 2dsphere queries. This single parameter may be a GeoJSON point object or
889
     * an array corresponding to the point's JSON representation.
890
     *
891
     * @see Builder::nearSphere()
892
     * @see http://docs.mongodb.org/manual/reference/operator/nearSphere/
893
     * @param float|array|Point $x
894
     * @param float $y
895
     * @return $this
896
     */
897 3 View Code Duplication
    public function nearSphere($x, $y = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
898
    {
899 3
        if ($x instanceof Point) {
0 ignored issues
show
Bug introduced by
The class GeoJson\Geometry\Point does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
900 1
            $x = $x->jsonSerialize();
901
        }
902
903 3
        if (is_array($x)) {
904 2
            return $this->operator('$nearSphere', ['$geometry' => $x]);
905
        }
906
907 1
        return $this->operator('$nearSphere', [$x, $y]);
908
    }
909
910
    /**
911
     * Negates an expression for the current field.
912
     *
913
     * @see Builder::not()
914
     * @see http://docs.mongodb.org/manual/reference/operator/not/
915
     * @param array|Expr $expression
916
     * @return $this
917
     */
918 2
    public function not($expression)
919
    {
920 2
        return $this->operator('$not', $expression instanceof Expr ? $expression->getQuery() : $expression);
921
    }
922
923
    /**
924
     * Specify $ne criteria for the current field.
925
     *
926
     * @see Builder::notEqual()
927
     * @see http://docs.mongodb.org/manual/reference/operator/ne/
928
     * @param mixed $value
929
     * @return $this
930
     */
931 6
    public function notEqual($value)
932
    {
933 6
        return $this->operator('$ne', $value);
934
    }
935
936
    /**
937
     * Specify $nin criteria for the current field.
938
     *
939
     * @see Builder::notIn()
940
     * @see http://docs.mongodb.org/manual/reference/operator/nin/
941
     * @param array $values
942
     * @return $this
943
     */
944 6
    public function notIn(array $values)
945
    {
946 6
        return $this->operator('$nin', array_values($values));
947
    }
948
949
    /**
950
     * Defines an operator and value on the expression.
951
     *
952
     * If there is a current field, the operator will be set on it; otherwise,
953
     * the operator is set at the top level of the query.
954
     *
955
     * @param string $operator
956
     * @param mixed $value
957
     * @return $this
958
     */
959 85
    public function operator($operator, $value)
960
    {
961 85
        $this->wrapEqualityCriteria();
962
963 85
        if ($this->currentField) {
964 56
            $this->query[$this->currentField][$operator] = $value;
965
        } else {
966 31
            $this->query[$operator] = $value;
967
        }
968 85
        return $this;
969
    }
970
971
    /**
972
     * Remove the first element from the current array field.
973
     *
974
     * @see Builder::popFirst()
975
     * @see http://docs.mongodb.org/manual/reference/operator/pop/
976
     * @return $this
977
     */
978 1
    public function popFirst()
979
    {
980 1
        $this->requiresCurrentField();
981 1
        $this->newObj['$pop'][$this->currentField] = 1;
982 1
        return $this;
983
    }
984
985
    /**
986
     * Remove the last element from the current array field.
987
     *
988
     * @see Builder::popLast()
989
     * @see http://docs.mongodb.org/manual/reference/operator/pop/
990
     * @return $this
991
     */
992
    public function popLast()
993
    {
994
        $this->requiresCurrentField();
995
        $this->newObj['$pop'][$this->currentField] = -1;
996
        return $this;
997
    }
998
999
    /**
1000
     * Add $position criteria to the expression for a $push operation.
1001
     *
1002
     * This is useful in conjunction with {@link Expr::each()} for a
1003
     * {@link Expr::push()} operation.
1004
     *
1005
     * @see http://docs.mongodb.org/manual/reference/operator/update/position/
1006
     * @param integer $position
1007
     * @return $this
1008
     */
1009 1
    public function position($position)
1010
    {
1011 1
        return $this->operator('$position', $position);
1012
    }
1013
1014
    /**
1015
     * Remove all elements matching the given value or expression from the
1016
     * current array field.
1017
     *
1018
     * @see Builder::pull()
1019
     * @see http://docs.mongodb.org/manual/reference/operator/pull/
1020
     * @param mixed|Expr $valueOrExpression
1021
     * @return $this
1022
     */
1023 2 View Code Duplication
    public function pull($valueOrExpression)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1024
    {
1025 2
        if ($valueOrExpression instanceof Expr) {
1026 1
            $valueOrExpression = $valueOrExpression->getQuery();
1027
        }
1028
1029 2
        $this->requiresCurrentField();
1030 2
        $this->newObj['$pull'][$this->currentField] = $valueOrExpression;
1031 2
        return $this;
1032
    }
1033
1034
    /**
1035
     * Remove all elements matching any of the given values from the current
1036
     * array field.
1037
     *
1038
     * @see Builder::pullAll()
1039
     * @see http://docs.mongodb.org/manual/reference/operator/pullAll/
1040
     * @param array $values
1041
     * @return $this
1042
     */
1043
    public function pullAll(array $values)
1044
    {
1045
        $this->requiresCurrentField();
1046
        $this->newObj['$pullAll'][$this->currentField] = $values;
1047
        return $this;
1048
    }
1049
1050
    /**
1051
     * Append one or more values to the current array field.
1052
     *
1053
     * If the field does not exist, it will be set to an array containing the
1054
     * value(s) in the argument. If the field is not an array, the query
1055
     * will yield an error.
1056
     *
1057
     * Multiple values may be specified by providing an Expr object and using
1058
     * {@link Expr::each()}. {@link Expr::slice()} and {@link Expr::sort()} may
1059
     * also be used to limit and order array elements, respectively.
1060
     *
1061
     * @see Builder::push()
1062
     * @see http://docs.mongodb.org/manual/reference/operator/push/
1063
     * @see http://docs.mongodb.org/manual/reference/operator/each/
1064
     * @see http://docs.mongodb.org/manual/reference/operator/slice/
1065
     * @see http://docs.mongodb.org/manual/reference/operator/sort/
1066
     * @param mixed|Expr $valueOrExpression
1067
     * @return $this
1068
     */
1069 8 View Code Duplication
    public function push($valueOrExpression)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1070
    {
1071 8
        if ($valueOrExpression instanceof Expr) {
1072 3
            $valueOrExpression = array_merge(
1073 3
                ['$each' => []],
1074 3
                $valueOrExpression->getQuery()
1075
            );
1076
        }
1077
1078 8
        $this->requiresCurrentField();
1079 8
        $this->newObj['$push'][$this->currentField] = $valueOrExpression;
1080 8
        return $this;
1081
    }
1082
1083
    /**
1084
     * Append multiple values to the current array field.
1085
     *
1086
     * If the field does not exist, it will be set to an array containing the
1087
     * values in the argument. If the field is not an array, the query will
1088
     * yield an error.
1089
     *
1090
     * This operator is deprecated in MongoDB 2.4. {@link Expr::push()} and
1091
     * {@link Expr::each()} should be used in its place.
1092
     *
1093
     * @see Builder::pushAll()
1094
     * @see http://docs.mongodb.org/manual/reference/operator/pushAll/
1095
     * @param array $values
1096
     * @return $this
1097
     */
1098
    public function pushAll(array $values)
1099
    {
1100
        $this->requiresCurrentField();
1101
        $this->newObj['$pushAll'][$this->currentField] = $values;
1102
        return $this;
1103
    }
1104
1105
    /**
1106
     * Specify $gte and $lt criteria for the current field.
1107
     *
1108
     * This method is shorthand for specifying $gte criteria on the lower bound
1109
     * and $lt criteria on the upper bound. The upper bound is not inclusive.
1110
     *
1111
     * @see Builder::range()
1112
     * @param mixed $start
1113
     * @param mixed $end
1114
     * @return $this
1115
     */
1116 2
    public function range($start, $end)
1117
    {
1118 2
        return $this->operator('$gte', $start)->operator('$lt', $end);
1119
    }
1120
1121
    /**
1122
     * Checks that the value of the current field is a reference to the supplied document.
1123
     *
1124
     * @param object $document
1125
     * @return Expr
1126
     */
1127 13
    public function references($document)
1128
    {
1129 13
        if ($this->currentField) {
1130 13
            $mapping = $this->getReferenceMapping();
1131 11
            $reference = $this->dm->createReference($document, $mapping);
1132 11
            $storeAs = array_key_exists('storeAs', $mapping) ? $mapping['storeAs'] : null;
1133 11
            $keys = [];
0 ignored issues
show
Unused Code introduced by
$keys is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1134
1135 View Code Duplication
            switch ($storeAs) {
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...
1136 11
                case ClassMetadataInfo::REFERENCE_STORE_AS_ID:
1137 4
                    $this->query[$mapping['name']] = $reference;
1138 4
                    return $this;
1139
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1140
1141 8
                case ClassMetadataInfo::REFERENCE_STORE_AS_REF:
1142
                    $keys = ['id' => true];
1143
                    break;
1144
1145 8
                case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF:
1146 3
                case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB:
1147 8
                    $keys = ['$ref' => true, '$id' => true, '$db' => true];
1148
1149 8
                    if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF) {
1150 5
                        unset($keys['$db']);
1151
                    }
1152
1153 8
                    if (isset($mapping['targetDocument'])) {
1154 4
                        unset($keys['$ref'], $keys['$db']);
1155
                    }
1156 8
                    break;
1157
1158
                default:
1159
                    throw new \InvalidArgumentException("Reference type {$storeAs} is invalid.");
1160
            }
1161
1162 8 View Code Duplication
            foreach ($keys as $key => $value) {
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...
1163 8
                $this->query[$mapping['name'] . '.' . $key] = $reference[$key];
1164
            }
1165 View Code Duplication
        } else {
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...
1166
            @trigger_error('Calling ' . __METHOD__ . ' without a current field set will no longer be possible in ODM 2.0.', E_USER_DEPRECATED);
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...
1167
1168
            $this->query = $this->dm->createDBRef($document);
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\ODM\MongoDB\Doc...tManager::createDBRef() has been deprecated with message: Deprecated in favor of createReference; will be removed in 2.0

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...
1169
        }
1170
1171 8
        return $this;
1172
    }
1173
1174
    /**
1175
     * Rename the current field.
1176
     *
1177
     * @see Builder::rename()
1178
     * @see http://docs.mongodb.org/manual/reference/operator/rename/
1179
     * @param string $name
1180
     * @return $this
1181
     */
1182
    public function rename($name)
1183
    {
1184
        $this->requiresCurrentField();
1185
        $this->newObj['$rename'][$this->currentField] = $name;
1186
        return $this;
1187
    }
1188
1189
    /**
1190
     * Set the current field to a value.
1191
     *
1192
     * This is only relevant for insert, update, or findAndUpdate queries. For
1193
     * update and findAndUpdate queries, the $atomic parameter will determine
1194
     * whether or not a $set operator is used.
1195
     *
1196
     * @see Builder::set()
1197
     * @see http://docs.mongodb.org/manual/reference/operator/set/
1198
     * @param mixed $value
1199
     * @param boolean $atomic
1200
     * @return $this
1201
     */
1202 19
    public function set($value, $atomic = true)
1203
    {
1204 19
        $this->requiresCurrentField();
1205
1206 19
        if ($atomic) {
1207 16
            $this->newObj['$set'][$this->currentField] = $value;
1208 16
            return $this;
1209
        }
1210
1211 3
        if (strpos($this->currentField, '.') === false) {
1212 2
            $this->newObj[$this->currentField] = $value;
1213 2
            return $this;
1214
        }
1215
1216 2
        $keys = explode('.', $this->currentField);
1217 2
        $current = &$this->newObj;
1218 2
        foreach ($keys as $key) {
1219 2
            $current = &$current[$key];
1220
        }
1221 2
        $current = $value;
1222
1223 2
        return $this;
1224
    }
1225
1226
    /**
1227
     * Sets ClassMetadata for document being queried.
1228
     *
1229
     * @param ClassMetadata $class
1230
     */
1231 402
    public function setClassMetadata(ClassMetadata $class)
1232
    {
1233 402
        $this->class = $class;
1234 402
    }
1235
1236
    /**
1237
     * Set the "new object".
1238
     *
1239
     * @see Builder::setNewObj()
1240
     * @param array $newObj
1241
     * @return $this
1242
     */
1243
    public function setNewObj(array $newObj)
1244
    {
1245
        $this->newObj = $newObj;
1246
        return $this;
1247
    }
1248
1249
    /**
1250
     * Set the current field to the value if the document is inserted in an
1251
     * upsert operation.
1252
     *
1253
     * If an update operation with upsert: true results in an insert of a
1254
     * document, then $setOnInsert assigns the specified values to the fields in
1255
     * the document. If the update operation does not result in an insert,
1256
     * $setOnInsert does nothing.
1257
     *
1258
     * @see Builder::setOnInsert()
1259
     * @see https://docs.mongodb.org/manual/reference/operator/update/setOnInsert/
1260
     * @param mixed $value
1261
     * @return $this
1262
     */
1263 1
    public function setOnInsert($value)
1264
    {
1265 1
        $this->requiresCurrentField();
1266 1
        $this->newObj['$setOnInsert'][$this->currentField] = $value;
1267
1268 1
        return $this;
1269
    }
1270
1271
    /**
1272
     * Set the query criteria.
1273
     *
1274
     * @see Builder::setQueryArray()
1275
     * @param array $query
1276
     * @return $this
1277
     */
1278 18
    public function setQuery(array $query)
1279
    {
1280 18
        $this->query = $query;
1281 18
        return $this;
1282
    }
1283
1284
    /**
1285
     * Specify $size criteria for the current field.
1286
     *
1287
     * @see Builder::size()
1288
     * @see http://docs.mongodb.org/manual/reference/operator/size/
1289
     * @param integer $size
1290
     * @return $this
1291
     */
1292
    public function size($size)
1293
    {
1294
        return $this->operator('$size', (integer) $size);
1295
    }
1296
1297
    /**
1298
     * Add $slice criteria to the expression for a $push operation.
1299
     *
1300
     * This is useful in conjunction with {@link Expr::each()} for a
1301
     * {@link Expr::push()} operation. {@link Builder::selectSlice()} should be
1302
     * used for specifying $slice for a query projection.
1303
     *
1304
     * @see http://docs.mongodb.org/manual/reference/operator/slice/
1305
     * @param integer $slice
1306
     * @return $this
1307
     */
1308 2
    public function slice($slice)
1309
    {
1310 2
        return $this->operator('$slice', $slice);
1311
    }
1312
1313
    /**
1314
     * Add $sort criteria to the expression for a $push operation.
1315
     *
1316
     * If sorting by multiple fields, the first argument should be an array of
1317
     * field name (key) and order (value) pairs.
1318
     *
1319
     * This is useful in conjunction with {@link Expr::each()} for a
1320
     * {@link Expr::push()} operation. {@link Builder::sort()} should be used to
1321
     * sort the results of a query.
1322
     *
1323
     * @see http://docs.mongodb.org/manual/reference/operator/sort/
1324
     * @param array|string $fieldName Field name or array of field/order pairs
1325
     * @param int|string $order       Field order (if one field is specified)
1326
     * @return $this
1327
     */
1328 2
    public function sort($fieldName, $order = null)
1329
    {
1330 2
        $fields = is_array($fieldName) ? $fieldName : [$fieldName => $order];
1331
1332 2
        return $this->operator('$sort', array_map([$this, 'normalizeSortOrder'], $fields));
1333
    }
1334
1335
    /**
1336
     * Specify $text criteria for the current query.
1337
     *
1338
     * The $language option may be set with {@link Expr::language()}.
1339
     *
1340
     * @see Builder::text()
1341
     * @see http://docs.mongodb.org/master/reference/operator/query/text/
1342
     * @param string $search
1343
     * @return $this
1344
     */
1345 6
    public function text($search)
1346
    {
1347 6
        $this->query['$text'] = ['$search' => (string) $search];
1348 6
        return $this;
1349
    }
1350
1351
    /**
1352
     * Specify $type criteria for the current field.
1353
     *
1354
     * @todo Remove support for string $type argument in 2.0
1355
     * @see Builder::type()
1356
     * @see http://docs.mongodb.org/manual/reference/operator/type/
1357
     * @param integer $type
1358
     * @return $this
1359
     */
1360 1
    public function type($type)
1361
    {
1362 1
        if (is_string($type)) {
1363
            $map = [
1364 1
                'double' => 1,
1365
                'string' => 2,
1366
                'object' => 3,
1367
                'array' => 4,
1368
                'binary' => 5,
1369
                'undefined' => 6,
1370
                'objectid' => 7,
1371
                'boolean' => 8,
1372
                'date' => 9,
1373
                'null' => 10,
1374
                'regex' => 11,
1375
                'jscode' => 13,
1376
                'symbol' => 14,
1377
                'jscodewithscope' => 15,
1378
                'integer32' => 16,
1379
                'timestamp' => 17,
1380
                'integer64' => 18,
1381
                'maxkey' => 127,
1382
                'minkey' => 255,
1383
            ];
1384
1385 1
            $type = $map[$type] ?? $type;
1386
        }
1387
1388 1
        return $this->operator('$type', $type);
1389
    }
1390
1391
    /**
1392
     * Unset the current field.
1393
     *
1394
     * The field will be removed from the document (not set to null).
1395
     *
1396
     * @see Builder::unsetField()
1397
     * @see http://docs.mongodb.org/manual/reference/operator/unset/
1398
     * @return $this
1399
     */
1400 3
    public function unsetField()
1401
    {
1402 3
        $this->requiresCurrentField();
1403 3
        $this->newObj['$unset'][$this->currentField] = 1;
1404 3
        return $this;
1405
    }
1406
1407
    /**
1408
     * Specify a JavaScript expression to use for matching documents.
1409
     *
1410
     * @see Builder::where()
1411
     * @see http://docs.mongodb.org/manual/reference/operator/where/
1412
     * @param string|\MongoDB\BSON\JavaScript $javascript
1413
     * @return $this
1414
     */
1415 3
    public function where($javascript)
1416
    {
1417 3
        $this->query['$where'] = $javascript;
1418 3
        return $this;
1419
    }
1420
1421
    /**
1422
     * Add $within criteria with a $box shape to the expression.
1423
     *
1424
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1425
     * @see Expr::geoWithinBox()
1426
     * @see http://docs.mongodb.org/manual/reference/operator/box/
1427
     * @param float $x1
1428
     * @param float $y1
1429
     * @param float $x2
1430
     * @param float $y2
1431
     * @return $this
1432
     */
1433 1
    public function withinBox($x1, $y1, $x2, $y2)
1434
    {
1435 1
        $shape = ['$box' => [[$x1, $y1], [$x2, $y2]]];
1436
1437 1
        return $this->operator('$within', $shape);
1438
    }
1439
1440
    /**
1441
     * Add $within criteria with a $center shape to the expression.
1442
     *
1443
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1444
     * @see Expr::geoWithinCenter()
1445
     * @see http://docs.mongodb.org/manual/reference/operator/center/
1446
     * @param float $x
1447
     * @param float $y
1448
     * @param float $radius
1449
     * @return $this
1450
     */
1451 1
    public function withinCenter($x, $y, $radius)
1452
    {
1453 1
        $shape = ['$center' => [[$x, $y], $radius]];
1454
1455 1
        return $this->operator('$within', $shape);
1456
    }
1457
1458
    /**
1459
     * Add $within criteria with a $centerSphere shape to the expression.
1460
     *
1461
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1462
     * @see Expr::geoWithinCenterSphere()
1463
     * @see http://docs.mongodb.org/manual/reference/operator/centerSphere/
1464
     * @param float $x
1465
     * @param float $y
1466
     * @param float $radius
1467
     * @return $this
1468
     */
1469 1
    public function withinCenterSphere($x, $y, $radius)
1470
    {
1471 1
        $shape = ['$centerSphere' => [[$x, $y], $radius]];
1472
1473 1
        return $this->operator('$within', $shape);
1474
    }
1475
1476
    /**
1477
     * Add $within criteria with a $polygon shape to the expression.
1478
     *
1479
     * Point coordinates are in x, y order (easting, northing for projected
1480
     * coordinates, longitude, latitude for geographic coordinates).
1481
     *
1482
     * The last point coordinate is implicitly connected with the first.
1483
     *
1484
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1485
     * @see Expr::geoWithinPolygon()
1486
     * @see http://docs.mongodb.org/manual/reference/operator/polygon/
1487
     * @param array $point,... Three or more point coordinate tuples
0 ignored issues
show
Bug introduced by
There is no parameter named $point,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1488
     * @return $this
1489
     * @throws \InvalidArgumentException if less than three points are given
1490
     */
1491 2 View Code Duplication
    public function withinPolygon(/* array($x1, $y1), array($x2, $y2), ... */)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1492
    {
1493 2
        if (func_num_args() < 3) {
1494 1
            throw new \InvalidArgumentException('Polygon must be defined by three or more points.');
1495
        }
1496
1497 1
        $shape = ['$polygon' => func_get_args()];
1498
1499 1
        return $this->operator('$within', $shape);
1500
    }
1501
1502
    /**
1503
     * Gets reference mapping for current field from current class or its descendants.
1504
     *
1505
     * @return array
1506
     * @throws MappingException
1507
     */
1508 19
    private function getReferenceMapping()
1509
    {
1510 19
        $mapping = null;
1511
        try {
1512 19
            $mapping = $this->class->getFieldMapping($this->currentField);
1513 6
        } catch (MappingException $e) {
1514 6
            if (empty($this->class->discriminatorMap)) {
1515
                throw $e;
1516
            }
1517 6
            $foundIn = null;
1518 6
            foreach ($this->class->discriminatorMap as $child) {
1519 6
                $childClass = $this->dm->getClassMetadata($child);
1520 6
                if ($childClass->hasAssociation($this->currentField)) {
1521 4
                    if ($mapping !== null && $mapping !== $childClass->getFieldMapping($this->currentField)) {
1522 2
                        throw MappingException::referenceFieldConflict($this->currentField, $foundIn->name, $childClass->name);
1523
                    }
1524 4
                    $mapping = $childClass->getFieldMapping($this->currentField);
1525 6
                    $foundIn = $childClass;
1526
                }
1527
            }
1528 4
            if ($mapping === null) {
1529 2
                throw MappingException::mappingNotFoundInClassNorDescendants($this->class->name, $this->currentField);
1530
            }
1531
        }
1532 15
        return $mapping;
1533
    }
1534
1535
    /**
1536
     * @param int|string $order
1537
     *
1538
     * @return int
1539
     */
1540 2
    private function normalizeSortOrder($order): int
1541
    {
1542 2
        if (is_string($order)) {
1543
            $order = strtolower($order) === 'asc' ? 1 : -1;
1544
        }
1545
1546 2
        return (int) $order;
1547
    }
1548
1549
    /**
1550
     * Ensure that a current field has been set.
1551
     *
1552
     * @throws \LogicException if a current field has not been set
1553
     */
1554 49
    private function requiresCurrentField()
1555
    {
1556 49
        if ( ! $this->currentField) {
1557
            throw new \LogicException('This method requires you set a current field using field().');
1558
        }
1559 49
    }
1560
1561
    /**
1562
     * Wraps equality criteria with an operator.
1563
     *
1564
     * If equality criteria was previously specified for a field, it cannot be
1565
     * merged with other operators without first being wrapped in an operator of
1566
     * its own. Ideally, we would wrap it with $eq, but that is only available
1567
     * in MongoDB 2.8. Using a single-element $in is backwards compatible.
1568
     *
1569
     * @see Expr::operator()
1570
     */
1571 85
    private function wrapEqualityCriteria()
1572
    {
1573
        /* If the current field has no criteria yet, do nothing. This ensures
1574
         * that we do not inadvertently inject {"$in": null} into the query.
1575
         */
1576 85
        if ($this->currentField && ! isset($this->query[$this->currentField]) && ! array_key_exists($this->currentField, $this->query)) {
1577 55
            return;
1578
        }
1579
1580 35
        if ($this->currentField) {
1581 5
            $query = &$this->query[$this->currentField];
1582
        } else {
1583 31
            $query = &$this->query;
1584
        }
1585
1586
        /* If the query is an empty array, we'll assume that the user has not
1587
         * specified criteria. Otherwise, check if the array includes a query
1588
         * operator (checking the first key is sufficient). If neither of these
1589
         * conditions are met, we'll wrap the query value with $in.
1590
         */
1591 35
        if (is_array($query) && (empty($query) || strpos(key($query), '$') === 0)) {
1592 35
            return;
1593
        }
1594
1595 2
        $query = ['$in' => [$query]];
1596 2
    }
1597
}
1598