Completed
Push — master ( 11f27c...4713a5 )
by Andreas
08:33
created

Expr::wrapEqualityCriteria()   C

Complexity

Conditions 8
Paths 5

Size

Total Lines 26
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 10
cts 10
cp 1
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 10
nc 5
nop 0
crap 8
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\Mapping\ClassMetadata;
24
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo;
25
use Doctrine\ODM\MongoDB\Mapping\MappingException;
26
use GeoJson\Geometry\Geometry;
27
use GeoJson\Geometry\Point;
28
29
/**
30
 * Query expression builder for ODM.
31
 *
32
 * @since       1.0
33
 */
34
class Expr
35
{
36
    /**
37
     * The query criteria array.
38
     *
39
     * @var array
40
     */
41
    private $query = [];
42
43
    /**
44
     * The "new object" array containing either a full document or a number of
45
     * atomic update operators.
46
     *
47
     * @see docs.mongodb.org/manual/reference/method/db.collection.update/#update-parameter
48
     * @var array
49
     */
50
    private $newObj = [];
51
52
    /**
53
     * The current field we are operating on.
54
     *
55
     * @var string
56
     */
57
    private $currentField;
58
59
    /**
60
     * The DocumentManager instance for this query
61
     *
62
     * @var DocumentManager
63
     */
64
    private $dm;
65
66
    /**
67
     * The ClassMetadata instance for the document being queried
68
     *
69
     * @var ClassMetadata
70
     */
71
    private $class;
72
73
    /**
74
     * @param DocumentManager $dm
75
     */
76 404
    public function __construct(DocumentManager $dm)
77
    {
78 404
        $this->dm = $dm;
79 404
    }
80
81
    /**
82
     * Add one or more $and clauses to the current query.
83
     *
84
     * @see Builder::addAnd()
85
     * @see http://docs.mongodb.org/manual/reference/operator/and/
86
     * @param array|Expr $expression
87
     * @return $this
88
     */
89 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...
90
    {
91 3
        if (! isset($this->query['$and'])) {
92 3
            $this->query['$and'] = [];
93
        }
94
95 3
        $this->query['$and'] = array_merge(
96 3
            $this->query['$and'],
97 3
            array_map(
98 3
                function ($expression) {
99 3
                    return $expression instanceof Expr ? $expression->getQuery() : $expression;
100 3
                },
101 3
                func_get_args()
102
            )
103
        );
104
105 3
        return $this;
106
    }
107
108
    /**
109
     * Append multiple values to the current array field only if they do not
110
     * already exist in the array.
111
     *
112
     * If the field does not exist, it will be set to an array containing the
113
     * unique values in the argument. If the field is not an array, the query
114
     * will yield an error.
115
     *
116
     * @deprecated 1.1 Use {@link Expr::addToSet()} with {@link Expr::each()}; Will be removed in 2.0
117
     * @see Builder::addManyToSet()
118
     * @see http://docs.mongodb.org/manual/reference/operator/addToSet/
119
     * @see http://docs.mongodb.org/manual/reference/operator/each/
120
     * @param array $values
121
     * @return $this
122
     */
123 1
    public function addManyToSet(array $values)
124
    {
125 1
        $this->requiresCurrentField();
126 1
        $this->newObj['$addToSet'][$this->currentField] = ['$each' => $values];
127 1
        return $this;
128
    }
129
130
    /**
131
     * Add one or more $nor clauses to the current query.
132
     *
133
     * @see Builder::addNor()
134
     * @see http://docs.mongodb.org/manual/reference/operator/nor/
135
     * @param array|Expr $expression
136
     * @return $this
137
     */
138 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...
139
    {
140 1
        if (! isset($this->query['$nor'])) {
141 1
            $this->query['$nor'] = [];
142
        }
143
144 1
        $this->query['$nor'] = array_merge(
145 1
            $this->query['$nor'],
146
            array_map(function ($expression) { return $expression instanceof Expr ? $expression->getQuery() : $expression; }, func_get_args())
147
        );
148
149 1
        return $this;
150
    }
151
152
    /**
153
     * Add one or more $or clauses to the current query.
154
     *
155
     * @see Builder::addOr()
156
     * @see http://docs.mongodb.org/manual/reference/operator/or/
157
     * @param array|Expr $expression
158
     * @return $this
159
     */
160 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...
161
    {
162 5
        if (! isset($this->query['$or'])) {
163 5
            $this->query['$or'] = [];
164
        }
165
166 5
        $this->query['$or'] = array_merge(
167 5
            $this->query['$or'],
168
            array_map(function ($expression) { return $expression instanceof Expr ? $expression->getQuery() : $expression; }, func_get_args())
169
        );
170
171 5
        return $this;
172
    }
173
174
    /**
175
     * Append one or more values to the current array field only if they do not
176
     * already exist in the array.
177
     *
178
     * If the field does not exist, it will be set to an array containing the
179
     * unique value(s) in the argument. If the field is not an array, the query
180
     * will yield an error.
181
     *
182
     * Multiple values may be specified by provided an Expr object and using
183
     * {@link Expr::each()}.
184
     *
185
     * @see Builder::addToSet()
186
     * @see http://docs.mongodb.org/manual/reference/operator/addToSet/
187
     * @see http://docs.mongodb.org/manual/reference/operator/each/
188
     * @param mixed|Expr $valueOrExpression
189
     * @return $this
190
     */
191 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...
192
    {
193 5
        if ($valueOrExpression instanceof Expr) {
194 1
            $valueOrExpression = $valueOrExpression->getQuery();
195
        }
196
197 5
        $this->requiresCurrentField();
198 5
        $this->newObj['$addToSet'][$this->currentField] = $valueOrExpression;
199 5
        return $this;
200
    }
201
202
    /**
203
     * Specify $all criteria for the current field.
204
     *
205
     * @see Builder::all()
206
     * @see http://docs.mongodb.org/manual/reference/operator/all/
207
     * @param array $values
208
     * @return $this
209
     */
210 2
    public function all(array $values)
211
    {
212 2
        return $this->operator('$all', (array) $values);
213
    }
214
215
    /**
216
     * Apply a bitwise operation on the current field
217
     *
218
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
219
     * @param string $operator
220
     * @param int $value
221
     * @return $this
222
     */
223 3
    protected function bit($operator, $value)
224
    {
225 3
        $this->requiresCurrentField();
226 3
        $this->newObj['$bit'][$this->currentField][$operator] = $value;
227 3
        return $this;
228
    }
229
230
    /**
231
     * Apply a bitwise and operation on the current field.
232
     *
233
     * @see Builder::bitAnd()
234
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
235
     * @param int $value
236
     * @return $this
237
     */
238 1
    public function bitAnd($value)
239
    {
240 1
        return $this->bit('and', $value);
241
    }
242
243
    /**
244
     * Apply a bitwise or operation on the current field.
245
     *
246
     * @see Builder::bitOr()
247
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
248
     * @param int $value
249
     * @return $this
250
     */
251 1
    public function bitOr($value)
252
    {
253 1
        return $this->bit('or', $value);
254
    }
255
256
    /**
257
     * Matches documents where all of the bit positions given by the query are
258
     * clear.
259
     *
260
     * @see Builder::bitsAllClear()
261
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAllClear/
262
     * @param int|array|\MongoBinData $value
263
     * @return $this
264
     */
265
    public function bitsAllClear($value)
266
    {
267
        $this->requiresCurrentField();
268
        return $this->operator('$bitsAllClear', $value);
269
    }
270
271
    /**
272
     * Matches documents where all of the bit positions given by the query are
273
     * set.
274
     *
275
     * @see Builder::bitsAllSet()
276
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAllSet/
277
     * @param int|array|\MongoBinData $value
278
     * @return $this
279
     */
280
    public function bitsAllSet($value)
281
    {
282
        $this->requiresCurrentField();
283
        return $this->operator('$bitsAllSet', $value);
284
    }
285
286
    /**
287
     * Matches documents where any of the bit positions given by the query are
288
     * clear.
289
     *
290
     * @see Builder::bitsAnyClear()
291
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAnyClear/
292
     * @param int|array|\MongoBinData $value
293
     * @return $this
294
     */
295
    public function bitsAnyClear($value)
296
    {
297
        $this->requiresCurrentField();
298
        return $this->operator('$bitsAnyClear', $value);
299
    }
300
301
    /**
302
     * Matches documents where any of the bit positions given by the query are
303
     * set.
304
     *
305
     * @see Builder::bitsAnySet()
306
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAnySet/
307
     * @param int|array|\MongoBinData $value
308
     * @return $this
309
     */
310
    public function bitsAnySet($value)
311
    {
312
        $this->requiresCurrentField();
313
        return $this->operator('$bitsAnySet', $value);
314
    }
315
316
    /**
317
     * Apply a bitwise xor operation on the current field.
318
     *
319
     * @see Builder::bitXor()
320
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
321
     * @param int $value
322
     * @return $this
323
     */
324 1
    public function bitXor($value)
325
    {
326 1
        return $this->bit('xor', $value);
327
    }
328
329
    /**
330
     * A boolean flag to enable or disable case sensitive search for $text
331
     * criteria.
332
     *
333
     * This method must be called after text().
334
     *
335
     * @see Builder::caseSensitive()
336
     * @see http://docs.mongodb.org/manual/reference/operator/text/
337
     * @param bool $caseSensitive
338
     * @return $this
339
     * @throws \BadMethodCallException if the query does not already have $text criteria
340
     *
341
     * @since 1.3
342
     */
343 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...
344
    {
345 3
        if ( ! isset($this->query['$text'])) {
346 1
            throw new \BadMethodCallException('This method requires a $text operator (call text() first)');
347
        }
348
349
        // Remove caseSensitive option to keep support for older database versions
350 2
        if ($caseSensitive) {
351 2
            $this->query['$text']['$caseSensitive'] = true;
352 1
        } elseif (isset($this->query['$text']['$caseSensitive'])) {
353 1
            unset($this->query['$text']['$caseSensitive']);
354
        }
355
356 2
        return $this;
357
    }
358
359
    /**
360
     * Associates a comment to any expression taking a query predicate.
361
     *
362
     * @see Builder::comment()
363
     * @see http://docs.mongodb.org/manual/reference/operator/query/comment/
364
     * @param string $comment
365
     * @return $this
366
     */
367
    public function comment($comment)
368
    {
369
        $this->query['$comment'] = $comment;
370
        return $this;
371
    }
372
373
    /**
374
     * Sets the value of the current field to the current date, either as a date or a timestamp.
375
     *
376
     * @see Builder::currentDate()
377
     * @see http://docs.mongodb.org/manual/reference/operator/update/currentDate/
378
     * @param string $type
379
     * @return $this
380
     * @throws \InvalidArgumentException if an invalid type is given
381
     */
382 3
    public function currentDate($type = 'date')
383
    {
384 3
        if (! in_array($type, ['date', 'timestamp'])) {
385 1
            throw new \InvalidArgumentException('Type for currentDate operator must be date or timestamp.');
386
        }
387
388 2
        $this->requiresCurrentField();
389 2
        $this->newObj['$currentDate'][$this->currentField]['$type'] = $type;
390 2
        return $this;
391
    }
392
393
    /**
394
     * A boolean flag to enable or disable diacritic sensitive search for $text
395
     * criteria.
396
     *
397
     * This method must be called after text().
398
     *
399
     * @see Builder::diacriticSensitive()
400
     * @see http://docs.mongodb.org/manual/reference/operator/text/
401
     * @param bool $diacriticSensitive
402
     * @return $this
403
     * @throws \BadMethodCallException if the query does not already have $text criteria
404
     *
405
     * @since 1.3
406
     */
407 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...
408
    {
409 3
        if ( ! isset($this->query['$text'])) {
410 1
            throw new \BadMethodCallException('This method requires a $text operator (call text() first)');
411
        }
412
413
        // Remove diacriticSensitive option to keep support for older database versions
414 2
        if ($diacriticSensitive) {
415 2
            $this->query['$text']['$diacriticSensitive'] = true;
416 1
        } elseif (isset($this->query['$text']['$diacriticSensitive'])) {
417 1
            unset($this->query['$text']['$diacriticSensitive']);
418
        }
419
420 2
        return $this;
421
    }
422
423
    /**
424
     * Add $each criteria to the expression for a $push operation.
425
     *
426
     * @see Expr::push()
427
     * @see http://docs.mongodb.org/manual/reference/operator/each/
428
     * @param array $values
429
     * @return $this
430
     */
431 4
    public function each(array $values)
432
    {
433 4
        return $this->operator('$each', $values);
434
    }
435
436
    /**
437
     * Specify $elemMatch criteria for the current field.
438
     *
439
     * @see Builder::elemMatch()
440
     * @see http://docs.mongodb.org/manual/reference/operator/elemMatch/
441
     * @param array|Expr $expression
442
     * @return $this
443
     */
444 4
    public function elemMatch($expression)
445
    {
446 4
        return $this->operator('$elemMatch', $expression instanceof Expr ? $expression->getQuery() : $expression);
447
    }
448
449
    /**
450
     * Specify an equality match for the current field.
451
     *
452
     * @see Builder::equals()
453
     * @param mixed $value
454
     * @return $this
455
     */
456 100
    public function equals($value)
457
    {
458 100
        if ($this->currentField) {
459 99
            $this->query[$this->currentField] = $value;
460
        } else {
461 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...
462
        }
463 100
        return $this;
464
    }
465
466
    /**
467
     * Specify $exists criteria for the current field.
468
     *
469
     * @see Builder::exists()
470
     * @see http://docs.mongodb.org/manual/reference/operator/exists/
471
     * @param boolean $bool
472
     * @return $this
473
     */
474 5
    public function exists($bool)
475
    {
476 5
        return $this->operator('$exists', (boolean) $bool);
477
    }
478
479
    /**
480
     * Set the current field for building the expression.
481
     *
482
     * @see Builder::field()
483
     * @param string $field
484
     * @return $this
485
     */
486 192
    public function field($field)
487
    {
488 192
        $this->currentField = (string) $field;
489 192
        return $this;
490
    }
491
492
    /**
493
     * Add $geoIntersects criteria with a GeoJSON geometry to the expression.
494
     *
495
     * The geometry parameter GeoJSON object or an array corresponding to the
496
     * geometry's JSON representation.
497
     *
498
     * @see Builder::geoIntersects()
499
     * @see http://docs.mongodb.org/manual/reference/operator/geoIntersects/
500
     * @param array|Geometry $geometry
501
     * @return $this
502
     */
503 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...
504
    {
505 2
        if ($geometry instanceof Geometry) {
506 1
            $geometry = $geometry->jsonSerialize();
507
        }
508
509 2
        return $this->operator('$geoIntersects', ['$geometry' => $geometry]);
510
    }
511
512
    /**
513
     * Add $geoWithin criteria with a GeoJSON geometry to the expression.
514
     *
515
     * The geometry parameter GeoJSON object or an array corresponding to the
516
     * geometry's JSON representation.
517
     *
518
     * @see Builder::geoWithin()
519
     * @see http://docs.mongodb.org/manual/reference/operator/geoIntersects/
520
     * @param array|Geometry $geometry
521
     * @return $this
522
     */
523 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...
524
    {
525 2
        if ($geometry instanceof Geometry) {
526 1
            $geometry = $geometry->jsonSerialize();
527
        }
528
529 2
        return $this->operator('$geoWithin', ['$geometry' => $geometry]);
530
    }
531
532
    /**
533
     * Add $geoWithin criteria with a $box shape to the expression.
534
     *
535
     * A rectangular polygon will be constructed from a pair of coordinates
536
     * corresponding to the bottom left and top right corners.
537
     *
538
     * Note: the $box operator only supports legacy coordinate pairs and 2d
539
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
540
     *
541
     * @see Builder::geoWithinBox()
542
     * @see http://docs.mongodb.org/manual/reference/operator/box/
543
     * @param float $x1
544
     * @param float $y1
545
     * @param float $x2
546
     * @param float $y2
547
     * @return $this
548
     */
549 1
    public function geoWithinBox($x1, $y1, $x2, $y2)
550
    {
551 1
        $shape = ['$box' => [[$x1, $y1], [$x2, $y2]]];
552
553 1
        return $this->operator('$geoWithin', $shape);
554
    }
555
556
    /**
557
     * Add $geoWithin criteria with a $center shape to the expression.
558
     *
559
     * Note: the $center operator only supports legacy coordinate pairs and 2d
560
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
561
     *
562
     * @see Builider::geoWithinCenter()
563
     * @see http://docs.mongodb.org/manual/reference/operator/center/
564
     * @param float $x
565
     * @param float $y
566
     * @param float $radius
567
     * @return $this
568
     */
569 1
    public function geoWithinCenter($x, $y, $radius)
570
    {
571 1
        $shape = ['$center' => [[$x, $y], $radius]];
572
573 1
        return $this->operator('$geoWithin', $shape);
574
    }
575
576
    /**
577
     * Add $geoWithin criteria with a $centerSphere shape to the expression.
578
     *
579
     * Note: the $centerSphere operator supports both 2d and 2dsphere indexes.
580
     *
581
     * @see Builder::geoWithinCenterSphere()
582
     * @see http://docs.mongodb.org/manual/reference/operator/centerSphere/
583
     * @param float $x
584
     * @param float $y
585
     * @param float $radius
586
     * @return $this
587
     */
588 1
    public function geoWithinCenterSphere($x, $y, $radius)
589
    {
590 1
        $shape = ['$centerSphere' => [[$x, $y], $radius]];
591
592 1
        return $this->operator('$geoWithin', $shape);
593
    }
594
595
    /**
596
     * Add $geoWithin criteria with a $polygon shape to the expression.
597
     *
598
     * Point coordinates are in x, y order (easting, northing for projected
599
     * coordinates, longitude, latitude for geographic coordinates).
600
     *
601
     * The last point coordinate is implicitly connected with the first.
602
     *
603
     * Note: the $polygon operator only supports legacy coordinate pairs and 2d
604
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
605
     *
606
     * @see Builder::geoWithinPolygon()
607
     * @see http://docs.mongodb.org/manual/reference/operator/polygon/
608
     * @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...
609
     * @return $this
610
     * @throws \InvalidArgumentException if less than three points are given
611
     */
612 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...
613
    {
614 2
        if (func_num_args() < 3) {
615 1
            throw new \InvalidArgumentException('Polygon must be defined by three or more points.');
616
        }
617
618 1
        $shape = ['$polygon' => func_get_args()];
619
620 1
        return $this->operator('$geoWithin', $shape);
621
    }
622
623
    /**
624
     * Return the current field.
625
     *
626
     * @return string
627
     */
628 2
    public function getCurrentField()
629
    {
630 2
        return $this->currentField;
631
    }
632
633
    /**
634
     * Gets prepared newObj part of expression.
635
     *
636
     * @return array
637
     */
638 175
    public function getNewObj()
639
    {
640 175
        return $this->dm->getUnitOfWork()
641 175
            ->getDocumentPersister($this->class->name)
642 175
            ->prepareQueryOrNewObj($this->newObj, true);
643
    }
644
645
    /**
646
     * Gets prepared query part of expression.
647
     *
648
     * @return array
649
     */
650 254
    public function getQuery()
651
    {
652 254
        return $this->dm->getUnitOfWork()
653 254
            ->getDocumentPersister($this->class->name)
654 254
            ->prepareQueryOrNewObj($this->query);
655
    }
656
657
    /**
658
     * Specify $gt criteria for the current field.
659
     *
660
     * @see Builder::gt()
661
     * @see http://docs.mongodb.org/manual/reference/operator/gt/
662
     * @param mixed $value
663
     * @return $this
664
     */
665 2
    public function gt($value)
666
    {
667 2
        return $this->operator('$gt', $value);
668
    }
669
670
    /**
671
     * Specify $gte criteria for the current field.
672
     *
673
     * @see Builder::gte()
674
     * @see http://docs.mongodb.org/manual/reference/operator/gte/
675
     * @param mixed $value
676
     * @return $this
677
     */
678 2
    public function gte($value)
679
    {
680 2
        return $this->operator('$gte', $value);
681
    }
682
683
    /**
684
     * Specify $in criteria for the current field.
685
     *
686
     * @see Builder::in()
687
     * @see http://docs.mongodb.org/manual/reference/operator/in/
688
     * @param array $values
689
     * @return $this
690
     */
691 31
    public function in(array $values)
692
    {
693 31
        return $this->operator('$in', array_values($values));
694
    }
695
696
    /**
697
     * Increment the current field.
698
     *
699
     * If the field does not exist, it will be set to this value.
700
     *
701
     * @see Builder::inc()
702
     * @see http://docs.mongodb.org/manual/reference/operator/inc/
703
     * @param float|integer $value
704
     * @return $this
705
     */
706 5
    public function inc($value)
707
    {
708 5
        $this->requiresCurrentField();
709 5
        $this->newObj['$inc'][$this->currentField] = $value;
710 5
        return $this;
711
    }
712
713
    /**
714
     * Checks that the current field includes a reference to the supplied document.
715
     *
716
     * @param object $document
717
     * @return Expr
718
     */
719 6
    public function includesReferenceTo($document)
720
    {
721 6
        if ($this->currentField) {
722 6
            $mapping = $this->getReferenceMapping();
723 4
            $reference = $this->dm->createReference($document, $mapping);
724 4
            $storeAs = array_key_exists('storeAs', $mapping) ? $mapping['storeAs'] : null;
725
726 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...
727 4
                case ClassMetadataInfo::REFERENCE_STORE_AS_ID:
728 2
                    $this->query[$mapping['name']] = $reference;
729 2
                    return $this;
730
                    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...
731
732 3
                case ClassMetadataInfo::REFERENCE_STORE_AS_REF:
733
                    $keys = ['id' => true];
734
                    break;
735
736 3
                case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF:
737 1
                case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB:
738 3
                    $keys = ['$ref' => true, '$id' => true, '$db' => true];
739
740 3
                    if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF) {
741 2
                        unset($keys['$db']);
742
                    }
743
744 3
                    if (isset($mapping['targetDocument'])) {
745 1
                        unset($keys['$ref'], $keys['$db']);
746
                    }
747 3
                    break;
748
749
                default:
750
                    throw new \InvalidArgumentException("Reference type {$storeAs} is invalid.");
751
            }
752
753 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...
754 3
                $this->query[$mapping['name']]['$elemMatch'][$key] = $reference[$key];
755
            }
756 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...
757
            @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...
758
759
            $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...
760
        }
761
762 3
        return $this;
763
    }
764
765
    /**
766
     * Set the $language option for $text criteria.
767
     *
768
     * This method must be called after text().
769
     *
770
     * @see Builder::language()
771
     * @see http://docs.mongodb.org/manual/reference/operator/text/
772
     * @param string $language
773
     * @return $this
774
     * @throws \BadMethodCallException if the query does not already have $text criteria
775
     */
776 2
    public function language($language)
777
    {
778 2
        if ( ! isset($this->query['$text'])) {
779 1
            throw new \BadMethodCallException('This method requires a $text operator (call text() first)');
780
        }
781
782 1
        $this->query['$text']['$language'] = (string) $language;
783
784 1
        return $this;
785
    }
786
787
    /**
788
     * Specify $lt criteria for the current field.
789
     *
790
     * @see Builder::lte()
791
     * @see http://docs.mongodb.org/manual/reference/operator/lte/
792
     * @param mixed $value
793
     * @return $this
794
     */
795 4
    public function lt($value)
796
    {
797 4
        return $this->operator('$lt', $value);
798
    }
799
800
    /**
801
     * Specify $lte criteria for the current field.
802
     *
803
     * @see Builder::lte()
804
     * @see http://docs.mongodb.org/manual/reference/operator/lte/
805
     * @param mixed $value
806
     * @return $this
807
     */
808 2
    public function lte($value)
809
    {
810 2
        return $this->operator('$lte', $value);
811
    }
812
813
    /**
814
     * Updates the value of the field to a specified value if the specified value is greater than the current value of the field.
815
     *
816
     * @see Builder::max()
817
     * @see http://docs.mongodb.org/manual/reference/operator/update/max/
818
     * @param mixed $value
819
     * @return $this
820
     */
821
    public function max($value)
822
    {
823
        $this->requiresCurrentField();
824
        $this->newObj['$max'][$this->currentField] = $value;
825
        return $this;
826
    }
827
828
    /**
829
     * Updates the value of the field to a specified value if the specified value is less than the current value of the field.
830
     *
831
     * @see Builder::min()
832
     * @see http://docs.mongodb.org/manual/reference/operator/update/min/
833
     * @param mixed $value
834
     * @return $this
835
     */
836
    public function min($value)
837
    {
838
        $this->requiresCurrentField();
839
        $this->newObj['$min'][$this->currentField] = $value;
840
        return $this;
841
    }
842
843
    /**
844
     * Specify $mod criteria for the current field.
845
     *
846
     * @see Builder::mod()
847
     * @see http://docs.mongodb.org/manual/reference/operator/mod/
848
     * @param float|integer $divisor
849
     * @param float|integer $remainder
850
     * @return $this
851
     */
852
    public function mod($divisor, $remainder = 0)
853
    {
854
        return $this->operator('$mod', [$divisor, $remainder]);
855
    }
856
857
    /**
858
     * Multiply the current field.
859
     *
860
     * If the field does not exist, it will be set to 0.
861
     *
862
     * @see Builder::mul()
863
     * @see http://docs.mongodb.org/manual/reference/operator/mul/
864
     * @param float|integer $value
865
     * @return $this
866
     */
867
    public function mul($value)
868
    {
869
        $this->requiresCurrentField();
870
        $this->newObj['$mul'][$this->currentField] = $value;
871
        return $this;
872
    }
873
874
    /**
875
     * Add $near criteria to the expression.
876
     *
877
     * A GeoJSON point may be provided as the first and only argument for
878
     * 2dsphere queries. This single parameter may be a GeoJSON point object or
879
     * an array corresponding to the point's JSON representation.
880
     *
881
     * @see Builder::near()
882
     * @see http://docs.mongodb.org/manual/reference/operator/near/
883
     * @param float|array|Point $x
884
     * @param float $y
885
     * @return $this
886
     */
887 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...
888
    {
889 3
        if ($x instanceof Point) {
890 1
            $x = $x->jsonSerialize();
891
        }
892
893 3
        if (is_array($x)) {
894 2
            return $this->operator('$near', ['$geometry' => $x]);
895
        }
896
897 1
        return $this->operator('$near', [$x, $y]);
898
    }
899
900
    /**
901
     * Add $nearSphere criteria to the expression.
902
     *
903
     * A GeoJSON point may be provided as the first and only argument for
904
     * 2dsphere queries. This single parameter may be a GeoJSON point object or
905
     * an array corresponding to the point's JSON representation.
906
     *
907
     * @see Builder::nearSphere()
908
     * @see http://docs.mongodb.org/manual/reference/operator/nearSphere/
909
     * @param float|array|Point $x
910
     * @param float $y
911
     * @return $this
912
     */
913 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...
914
    {
915 3
        if ($x instanceof Point) {
916 1
            $x = $x->jsonSerialize();
917
        }
918
919 3
        if (is_array($x)) {
920 2
            return $this->operator('$nearSphere', ['$geometry' => $x]);
921
        }
922
923 1
        return $this->operator('$nearSphere', [$x, $y]);
924
    }
925
926
    /**
927
     * Negates an expression for the current field.
928
     *
929
     * @see Builder::not()
930
     * @see http://docs.mongodb.org/manual/reference/operator/not/
931
     * @param array|Expr $expression
932
     * @return $this
933
     */
934 2
    public function not($expression)
935
    {
936 2
        return $this->operator('$not', $expression instanceof Expr ? $expression->getQuery() : $expression);
937
    }
938
939
    /**
940
     * Specify $ne criteria for the current field.
941
     *
942
     * @see Builder::notEqual()
943
     * @see http://docs.mongodb.org/manual/reference/operator/ne/
944
     * @param mixed $value
945
     * @return $this
946
     */
947 6
    public function notEqual($value)
948
    {
949 6
        return $this->operator('$ne', $value);
950
    }
951
952
    /**
953
     * Specify $nin criteria for the current field.
954
     *
955
     * @see Builder::notIn()
956
     * @see http://docs.mongodb.org/manual/reference/operator/nin/
957
     * @param array $values
958
     * @return $this
959
     */
960 6
    public function notIn(array $values)
961
    {
962 6
        return $this->operator('$nin', array_values($values));
963
    }
964
965
    /**
966
     * Defines an operator and value on the expression.
967
     *
968
     * If there is a current field, the operator will be set on it; otherwise,
969
     * the operator is set at the top level of the query.
970
     *
971
     * @param string $operator
972
     * @param mixed $value
973
     * @return $this
974
     */
975 85
    public function operator($operator, $value)
976
    {
977 85
        $this->wrapEqualityCriteria();
978
979 85
        if ($this->currentField) {
980 56
            $this->query[$this->currentField][$operator] = $value;
981
        } else {
982 31
            $this->query[$operator] = $value;
983
        }
984 85
        return $this;
985
    }
986
987
    /**
988
     * Remove the first element from the current array field.
989
     *
990
     * @see Builder::popFirst()
991
     * @see http://docs.mongodb.org/manual/reference/operator/pop/
992
     * @return $this
993
     */
994 1
    public function popFirst()
995
    {
996 1
        $this->requiresCurrentField();
997 1
        $this->newObj['$pop'][$this->currentField] = 1;
998 1
        return $this;
999
    }
1000
1001
    /**
1002
     * Remove the last element from the current array field.
1003
     *
1004
     * @see Builder::popLast()
1005
     * @see http://docs.mongodb.org/manual/reference/operator/pop/
1006
     * @return $this
1007
     */
1008
    public function popLast()
1009
    {
1010
        $this->requiresCurrentField();
1011
        $this->newObj['$pop'][$this->currentField] = -1;
1012
        return $this;
1013
    }
1014
1015
    /**
1016
     * Add $position criteria to the expression for a $push operation.
1017
     *
1018
     * This is useful in conjunction with {@link Expr::each()} for a
1019
     * {@link Expr::push()} operation.
1020
     *
1021
     * @see http://docs.mongodb.org/manual/reference/operator/update/position/
1022
     * @param integer $position
1023
     * @return $this
1024
     */
1025 1
    public function position($position)
1026
    {
1027 1
        return $this->operator('$position', $position);
1028
    }
1029
1030
    /**
1031
     * Remove all elements matching the given value or expression from the
1032
     * current array field.
1033
     *
1034
     * @see Builder::pull()
1035
     * @see http://docs.mongodb.org/manual/reference/operator/pull/
1036
     * @param mixed|Expr $valueOrExpression
1037
     * @return $this
1038
     */
1039 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...
1040
    {
1041 2
        if ($valueOrExpression instanceof Expr) {
1042 1
            $valueOrExpression = $valueOrExpression->getQuery();
1043
        }
1044
1045 2
        $this->requiresCurrentField();
1046 2
        $this->newObj['$pull'][$this->currentField] = $valueOrExpression;
1047 2
        return $this;
1048
    }
1049
1050
    /**
1051
     * Remove all elements matching any of the given values from the current
1052
     * array field.
1053
     *
1054
     * @see Builder::pullAll()
1055
     * @see http://docs.mongodb.org/manual/reference/operator/pullAll/
1056
     * @param array $values
1057
     * @return $this
1058
     */
1059
    public function pullAll(array $values)
1060
    {
1061
        $this->requiresCurrentField();
1062
        $this->newObj['$pullAll'][$this->currentField] = $values;
1063
        return $this;
1064
    }
1065
1066
    /**
1067
     * Append one or more values to the current array field.
1068
     *
1069
     * If the field does not exist, it will be set to an array containing the
1070
     * value(s) in the argument. If the field is not an array, the query
1071
     * will yield an error.
1072
     *
1073
     * Multiple values may be specified by providing an Expr object and using
1074
     * {@link Expr::each()}. {@link Expr::slice()} and {@link Expr::sort()} may
1075
     * also be used to limit and order array elements, respectively.
1076
     *
1077
     * @see Builder::push()
1078
     * @see http://docs.mongodb.org/manual/reference/operator/push/
1079
     * @see http://docs.mongodb.org/manual/reference/operator/each/
1080
     * @see http://docs.mongodb.org/manual/reference/operator/slice/
1081
     * @see http://docs.mongodb.org/manual/reference/operator/sort/
1082
     * @param mixed|Expr $valueOrExpression
1083
     * @return $this
1084
     */
1085 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...
1086
    {
1087 8
        if ($valueOrExpression instanceof Expr) {
1088 3
            $valueOrExpression = array_merge(
1089 3
                ['$each' => []],
1090 3
                $valueOrExpression->getQuery()
1091
            );
1092
        }
1093
1094 8
        $this->requiresCurrentField();
1095 8
        $this->newObj['$push'][$this->currentField] = $valueOrExpression;
1096 8
        return $this;
1097
    }
1098
1099
    /**
1100
     * Append multiple values to the current array field.
1101
     *
1102
     * If the field does not exist, it will be set to an array containing the
1103
     * values in the argument. If the field is not an array, the query will
1104
     * yield an error.
1105
     *
1106
     * This operator is deprecated in MongoDB 2.4. {@link Expr::push()} and
1107
     * {@link Expr::each()} should be used in its place.
1108
     *
1109
     * @see Builder::pushAll()
1110
     * @see http://docs.mongodb.org/manual/reference/operator/pushAll/
1111
     * @param array $values
1112
     * @return $this
1113
     */
1114
    public function pushAll(array $values)
1115
    {
1116
        $this->requiresCurrentField();
1117
        $this->newObj['$pushAll'][$this->currentField] = $values;
1118
        return $this;
1119
    }
1120
1121
    /**
1122
     * Specify $gte and $lt criteria for the current field.
1123
     *
1124
     * This method is shorthand for specifying $gte criteria on the lower bound
1125
     * and $lt criteria on the upper bound. The upper bound is not inclusive.
1126
     *
1127
     * @see Builder::range()
1128
     * @param mixed $start
1129
     * @param mixed $end
1130
     * @return $this
1131
     */
1132 2
    public function range($start, $end)
1133
    {
1134 2
        return $this->operator('$gte', $start)->operator('$lt', $end);
1135
    }
1136
1137
    /**
1138
     * Checks that the value of the current field is a reference to the supplied document.
1139
     *
1140
     * @param object $document
1141
     * @return Expr
1142
     */
1143 13
    public function references($document)
1144
    {
1145 13
        if ($this->currentField) {
1146 13
            $mapping = $this->getReferenceMapping();
1147 11
            $reference = $this->dm->createReference($document, $mapping);
1148 11
            $storeAs = array_key_exists('storeAs', $mapping) ? $mapping['storeAs'] : null;
1149
1150 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...
1151 11
                case ClassMetadataInfo::REFERENCE_STORE_AS_ID:
1152 4
                    $this->query[$mapping['name']] = $reference;
1153 4
                    return $this;
1154
                    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...
1155
1156 8
                case ClassMetadataInfo::REFERENCE_STORE_AS_REF:
1157
                    $keys = ['id' => true];
1158
                    break;
1159
1160 8
                case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF:
1161 3
                case ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF_WITH_DB:
1162 8
                    $keys = ['$ref' => true, '$id' => true, '$db' => true];
1163
1164 8
                    if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF) {
1165 5
                        unset($keys['$db']);
1166
                    }
1167
1168 8
                    if (isset($mapping['targetDocument'])) {
1169 4
                        unset($keys['$ref'], $keys['$db']);
1170
                    }
1171 8
                    break;
1172
1173
                default:
1174
                    throw new \InvalidArgumentException("Reference type {$storeAs} is invalid.");
1175
            }
1176
1177 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...
1178 8
                $this->query[$mapping['name'] . '.' . $key] = $reference[$key];
1179
            }
1180 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...
1181
            @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...
1182
1183
            $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...
1184
        }
1185
1186 8
        return $this;
1187
    }
1188
1189
    /**
1190
     * Rename the current field.
1191
     *
1192
     * @see Builder::rename()
1193
     * @see http://docs.mongodb.org/manual/reference/operator/rename/
1194
     * @param string $name
1195
     * @return $this
1196
     */
1197
    public function rename($name)
1198
    {
1199
        $this->requiresCurrentField();
1200
        $this->newObj['$rename'][$this->currentField] = $name;
1201
        return $this;
1202
    }
1203
1204
    /**
1205
     * Set the current field to a value.
1206
     *
1207
     * This is only relevant for insert, update, or findAndUpdate queries. For
1208
     * update and findAndUpdate queries, the $atomic parameter will determine
1209
     * whether or not a $set operator is used.
1210
     *
1211
     * @see Builder::set()
1212
     * @see http://docs.mongodb.org/manual/reference/operator/set/
1213
     * @param mixed $value
1214
     * @param boolean $atomic
1215
     * @return $this
1216
     */
1217 19
    public function set($value, $atomic = true)
1218
    {
1219 19
        $this->requiresCurrentField();
1220
1221 19
        if ($atomic) {
1222 16
            $this->newObj['$set'][$this->currentField] = $value;
1223 16
            return $this;
1224
        }
1225
1226 3
        if (strpos($this->currentField, '.') === false) {
1227 2
            $this->newObj[$this->currentField] = $value;
1228 2
            return $this;
1229
        }
1230
1231 2
        $keys = explode('.', $this->currentField);
1232 2
        $current = &$this->newObj;
1233 2
        foreach ($keys as $key) {
1234 2
            $current = &$current[$key];
1235
        }
1236 2
        $current = $value;
1237
1238 2
        return $this;
1239
    }
1240
1241
    /**
1242
     * Sets ClassMetadata for document being queried.
1243
     *
1244
     * @param ClassMetadata $class
1245
     */
1246 402
    public function setClassMetadata(ClassMetadata $class)
1247
    {
1248 402
        $this->class = $class;
1249 402
    }
1250
1251
    /**
1252
     * Set the "new object".
1253
     *
1254
     * @see Builder::setNewObj()
1255
     * @param array $newObj
1256
     * @return $this
1257
     */
1258
    public function setNewObj(array $newObj)
1259
    {
1260
        $this->newObj = $newObj;
1261
        return $this;
1262
    }
1263
1264
    /**
1265
     * Set the current field to the value if the document is inserted in an
1266
     * upsert operation.
1267
     *
1268
     * If an update operation with upsert: true results in an insert of a
1269
     * document, then $setOnInsert assigns the specified values to the fields in
1270
     * the document. If the update operation does not result in an insert,
1271
     * $setOnInsert does nothing.
1272
     *
1273
     * @see Builder::setOnInsert()
1274
     * @see https://docs.mongodb.org/manual/reference/operator/update/setOnInsert/
1275
     * @param mixed $value
1276
     * @return $this
1277
     */
1278 1
    public function setOnInsert($value)
1279
    {
1280 1
        $this->requiresCurrentField();
1281 1
        $this->newObj['$setOnInsert'][$this->currentField] = $value;
1282
1283 1
        return $this;
1284
    }
1285
1286
    /**
1287
     * Set the query criteria.
1288
     *
1289
     * @see Builder::setQueryArray()
1290
     * @param array $query
1291
     * @return $this
1292
     */
1293 18
    public function setQuery(array $query)
1294
    {
1295 18
        $this->query = $query;
1296 18
        return $this;
1297
    }
1298
1299
    /**
1300
     * Specify $size criteria for the current field.
1301
     *
1302
     * @see Builder::size()
1303
     * @see http://docs.mongodb.org/manual/reference/operator/size/
1304
     * @param integer $size
1305
     * @return $this
1306
     */
1307
    public function size($size)
1308
    {
1309
        return $this->operator('$size', (integer) $size);
1310
    }
1311
1312
    /**
1313
     * Add $slice criteria to the expression for a $push operation.
1314
     *
1315
     * This is useful in conjunction with {@link Expr::each()} for a
1316
     * {@link Expr::push()} operation. {@link Builder::selectSlice()} should be
1317
     * used for specifying $slice for a query projection.
1318
     *
1319
     * @see http://docs.mongodb.org/manual/reference/operator/slice/
1320
     * @param integer $slice
1321
     * @return $this
1322
     */
1323 2
    public function slice($slice)
1324
    {
1325 2
        return $this->operator('$slice', $slice);
1326
    }
1327
1328
    /**
1329
     * Add $sort criteria to the expression for a $push operation.
1330
     *
1331
     * If sorting by multiple fields, the first argument should be an array of
1332
     * field name (key) and order (value) pairs.
1333
     *
1334
     * This is useful in conjunction with {@link Expr::each()} for a
1335
     * {@link Expr::push()} operation. {@link Builder::sort()} should be used to
1336
     * sort the results of a query.
1337
     *
1338
     * @see http://docs.mongodb.org/manual/reference/operator/sort/
1339
     * @param array|string $fieldName Field name or array of field/order pairs
1340
     * @param int|string $order       Field order (if one field is specified)
1341
     * @return $this
1342
     */
1343 2
    public function sort($fieldName, $order = null)
1344
    {
1345 2
        $fields = is_array($fieldName) ? $fieldName : [$fieldName => $order];
1346
1347 2
        return $this->operator('$sort', array_map([$this, 'normalizeSortOrder'], $fields));
1348
    }
1349
1350
    /**
1351
     * Specify $text criteria for the current query.
1352
     *
1353
     * The $language option may be set with {@link Expr::language()}.
1354
     *
1355
     * @see Builder::text()
1356
     * @see http://docs.mongodb.org/master/reference/operator/query/text/
1357
     * @param string $search
1358
     * @return $this
1359
     */
1360 6
    public function text($search)
1361
    {
1362 6
        $this->query['$text'] = ['$search' => (string) $search];
1363 6
        return $this;
1364
    }
1365
1366
    /**
1367
     * Specify $type criteria for the current field.
1368
     *
1369
     * @todo Remove support for string $type argument in 2.0
1370
     * @see Builder::type()
1371
     * @see http://docs.mongodb.org/manual/reference/operator/type/
1372
     * @param integer $type
1373
     * @return $this
1374
     */
1375 1
    public function type($type)
1376
    {
1377 1
        if (is_string($type)) {
1378
            $map = [
1379 1
                'double' => 1,
1380
                'string' => 2,
1381
                'object' => 3,
1382
                'array' => 4,
1383
                'binary' => 5,
1384
                'undefined' => 6,
1385
                'objectid' => 7,
1386
                'boolean' => 8,
1387
                'date' => 9,
1388
                'null' => 10,
1389
                'regex' => 11,
1390
                'jscode' => 13,
1391
                'symbol' => 14,
1392
                'jscodewithscope' => 15,
1393
                'integer32' => 16,
1394
                'timestamp' => 17,
1395
                'integer64' => 18,
1396
                'maxkey' => 127,
1397
                'minkey' => 255,
1398
            ];
1399
1400 1
            $type = isset($map[$type]) ? $map[$type] : $type;
1401
        }
1402
1403 1
        return $this->operator('$type', $type);
1404
    }
1405
1406
    /**
1407
     * Unset the current field.
1408
     *
1409
     * The field will be removed from the document (not set to null).
1410
     *
1411
     * @see Builder::unsetField()
1412
     * @see http://docs.mongodb.org/manual/reference/operator/unset/
1413
     * @return $this
1414
     */
1415 3
    public function unsetField()
1416
    {
1417 3
        $this->requiresCurrentField();
1418 3
        $this->newObj['$unset'][$this->currentField] = 1;
1419 3
        return $this;
1420
    }
1421
1422
    /**
1423
     * Specify a JavaScript expression to use for matching documents.
1424
     *
1425
     * @see Builder::where()
1426
     * @see http://docs.mongodb.org/manual/reference/operator/where/
1427
     * @param string|\MongoCode $javascript
1428
     * @return $this
1429
     */
1430 3
    public function where($javascript)
1431
    {
1432 3
        $this->query['$where'] = $javascript;
1433 3
        return $this;
1434
    }
1435
1436
    /**
1437
     * Add $within criteria with a $box shape to the expression.
1438
     *
1439
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1440
     * @see Expr::geoWithinBox()
1441
     * @see http://docs.mongodb.org/manual/reference/operator/box/
1442
     * @param float $x1
1443
     * @param float $y1
1444
     * @param float $x2
1445
     * @param float $y2
1446
     * @return $this
1447
     */
1448 1
    public function withinBox($x1, $y1, $x2, $y2)
1449
    {
1450 1
        $shape = ['$box' => [[$x1, $y1], [$x2, $y2]]];
1451
1452 1
        return $this->operator('$within', $shape);
1453
    }
1454
1455
    /**
1456
     * Add $within criteria with a $center shape to the expression.
1457
     *
1458
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1459
     * @see Expr::geoWithinCenter()
1460
     * @see http://docs.mongodb.org/manual/reference/operator/center/
1461
     * @param float $x
1462
     * @param float $y
1463
     * @param float $radius
1464
     * @return $this
1465
     */
1466 1
    public function withinCenter($x, $y, $radius)
1467
    {
1468 1
        $shape = ['$center' => [[$x, $y], $radius]];
1469
1470 1
        return $this->operator('$within', $shape);
1471
    }
1472
1473
    /**
1474
     * Add $within criteria with a $centerSphere shape to the expression.
1475
     *
1476
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1477
     * @see Expr::geoWithinCenterSphere()
1478
     * @see http://docs.mongodb.org/manual/reference/operator/centerSphere/
1479
     * @param float $x
1480
     * @param float $y
1481
     * @param float $radius
1482
     * @return $this
1483
     */
1484 1
    public function withinCenterSphere($x, $y, $radius)
1485
    {
1486 1
        $shape = ['$centerSphere' => [[$x, $y], $radius]];
1487
1488 1
        return $this->operator('$within', $shape);
1489
    }
1490
1491
    /**
1492
     * Add $within criteria with a $polygon shape to the expression.
1493
     *
1494
     * Point coordinates are in x, y order (easting, northing for projected
1495
     * coordinates, longitude, latitude for geographic coordinates).
1496
     *
1497
     * The last point coordinate is implicitly connected with the first.
1498
     *
1499
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1500
     * @see Expr::geoWithinPolygon()
1501
     * @see http://docs.mongodb.org/manual/reference/operator/polygon/
1502
     * @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...
1503
     * @return $this
1504
     * @throws \InvalidArgumentException if less than three points are given
1505
     */
1506 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...
1507
    {
1508 2
        if (func_num_args() < 3) {
1509 1
            throw new \InvalidArgumentException('Polygon must be defined by three or more points.');
1510
        }
1511
1512 1
        $shape = ['$polygon' => func_get_args()];
1513
1514 1
        return $this->operator('$within', $shape);
1515
    }
1516
1517
    /**
1518
     * Gets reference mapping for current field from current class or its descendants.
1519
     *
1520
     * @return array
1521
     * @throws MappingException
1522
     */
1523 19
    private function getReferenceMapping()
1524
    {
1525 19
        $mapping = null;
1526
        try {
1527 19
            $mapping = $this->class->getFieldMapping($this->currentField);
1528 6
        } catch (MappingException $e) {
1529 6
            if (empty($this->class->discriminatorMap)) {
1530
                throw $e;
1531
            }
1532 6
            $foundIn = null;
1533 6
            foreach ($this->class->discriminatorMap as $child) {
1534 6
                $childClass = $this->dm->getClassMetadata($child);
1535 6
                if ($childClass->hasAssociation($this->currentField)) {
1536 4
                    if ($mapping !== null && $mapping !== $childClass->getFieldMapping($this->currentField)) {
1537 2
                        throw MappingException::referenceFieldConflict($this->currentField, $foundIn->name, $childClass->name);
1538
                    }
1539 4
                    $mapping = $childClass->getFieldMapping($this->currentField);
1540 6
                    $foundIn = $childClass;
1541
                }
1542
            }
1543 4
            if ($mapping === null) {
1544 2
                throw MappingException::mappingNotFoundInClassNorDescendants($this->class->name, $this->currentField);
1545
            }
1546
        }
1547 15
        return $mapping;
1548
    }
1549
1550
    /**
1551
     * @param int|string $order
1552
     *
1553
     * @return int
1554
     */
1555 2
    private function normalizeSortOrder($order): int
1556
    {
1557 2
        if (is_string($order)) {
1558
            $order = strtolower($order) === 'asc' ? 1 : -1;
1559
        }
1560
1561 2
        return (int) $order;
1562
    }
1563
1564
    /**
1565
     * Ensure that a current field has been set.
1566
     *
1567
     * @throws \LogicException if a current field has not been set
1568
     */
1569 49
    private function requiresCurrentField()
1570
    {
1571 49
        if ( ! $this->currentField) {
1572
            throw new \LogicException('This method requires you set a current field using field().');
1573
        }
1574 49
    }
1575
1576
    /**
1577
     * Wraps equality criteria with an operator.
1578
     *
1579
     * If equality criteria was previously specified for a field, it cannot be
1580
     * merged with other operators without first being wrapped in an operator of
1581
     * its own. Ideally, we would wrap it with $eq, but that is only available
1582
     * in MongoDB 2.8. Using a single-element $in is backwards compatible.
1583
     *
1584
     * @see Expr::operator()
1585
     */
1586 85
    private function wrapEqualityCriteria()
1587
    {
1588
        /* If the current field has no criteria yet, do nothing. This ensures
1589
         * that we do not inadvertently inject {"$in": null} into the query.
1590
         */
1591 85
        if ($this->currentField && ! isset($this->query[$this->currentField]) && ! array_key_exists($this->currentField, $this->query)) {
1592 55
            return;
1593
        }
1594
1595 35
        if ($this->currentField) {
1596 5
            $query = &$this->query[$this->currentField];
1597
        } else {
1598 31
            $query = &$this->query;
1599
        }
1600
1601
        /* If the query is an empty array, we'll assume that the user has not
1602
         * specified criteria. Otherwise, check if the array includes a query
1603
         * operator (checking the first key is sufficient). If neither of these
1604
         * conditions are met, we'll wrap the query value with $in.
1605
         */
1606 35
        if (is_array($query) && (empty($query) || strpos(key($query), '$') === 0)) {
1607 35
            return;
1608
        }
1609
1610 2
        $query = ['$in' => [$query]];
1611 2
    }
1612
}
1613