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

Builder::bitsAnySet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1
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\ClassMetadataInfo;
24
use GeoJson\Geometry\Geometry;
25
use GeoJson\Geometry\Point;
26
use MongoDB\Collection;
27
use MongoDB\Driver\ReadPreference;
28
29
/**
30
 * Query builder for ODM.
31
 *
32
 * @since       1.0
33
 */
34
class Builder
35
{
36
    /**
37
     * The DocumentManager instance for this query
38
     *
39
     * @var DocumentManager
40
     */
41
    private $dm;
42
43
    /**
44
     * The ClassMetadata instance.
45
     *
46
     * @var \Doctrine\ODM\MongoDB\Mapping\ClassMetadata
47
     */
48
    private $class;
49
50
    /**
51
     * The current field we are operating on.
52
     *
53
     * @todo Change this to private once ODM requires doctrine/mongodb 1.1+
54
     * @var string
55
     */
56
    protected $currentField;
57
58
    /**
59
     * Whether or not to hydrate the data to documents.
60
     *
61
     * @var boolean
62
     */
63
    private $hydrate = true;
64
65
    /**
66
     * Whether or not to refresh the data for documents that are already in the identity map.
67
     *
68
     * @var boolean
69
     */
70
    private $refresh = false;
71
72
    /**
73
     * Array of primer Closure instances.
74
     *
75
     * @var array
76
     */
77
    private $primers = array();
78
79
    /**
80
     * Whether or not to register documents in UnitOfWork.
81
     *
82
     * @var bool
83
     */
84
    private $readOnly;
85
86
    /**
87
     * The Collection instance.
88
     *
89
     * @var Collection
90
     */
91
    private $collection;
92
93
    /**
94
     * Array containing the query data.
95
     *
96
     * @var array
97
     */
98
    private $query = ['type' => Query::TYPE_FIND];
99
100
    /**
101
     * The Expr instance used for building this query.
102
     *
103
     * This object includes the query criteria and the "new object" used for
104
     * insert and update queries.
105
     *
106
     * @var Expr $expr
107
     */
108
    private $expr;
109
110
    /**
111
     * Construct a Builder
112
     *
113
     * @param DocumentManager $dm
114
     * @param string[]|string|null $documentName (optional) an array of document names, the document name, or none
115
     */
116 291
    public function __construct(DocumentManager $dm, $documentName = null)
117
    {
118 291
        $this->dm = $dm;
119 291
        $this->expr = new Expr($dm);
120 291
        if ($documentName !== null) {
121 283
            $this->setDocumentName($documentName);
122
        }
123 290
    }
124
125 1
    public function __clone()
126
    {
127 1
        $this->expr = clone $this->expr;
128 1
    }
129
130
    /**
131
     * Add one or more $and clauses to the current query.
132
     *
133
     * You can create a new expression using the {@link Builder::expr()} method.
134
     *
135
     * @see Expr::addAnd()
136
     * @see http://docs.mongodb.org/manual/reference/operator/and/
137
     * @param array|Expr $expression
138
     * @return $this
139
     */
140 4
    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...
141
    {
142 4
        $this->expr->addAnd(...func_get_args());
143 4
        return $this;
144
    }
145
146
    /**
147
     * Append multiple values to the current array field only if they do not
148
     * already exist in the array.
149
     *
150
     * If the field does not exist, it will be set to an array containing the
151
     * unique values in the argument. If the field is not an array, the query
152
     * will yield an error.
153
     *
154
     * @deprecated 1.1 Use {@link Builder::addToSet()} with {@link Expr::each()}; Will be removed in 2.0
155
     * @see Expr::addManyToSet()
156
     * @see http://docs.mongodb.org/manual/reference/operator/addToSet/
157
     * @see http://docs.mongodb.org/manual/reference/operator/each/
158
     * @param array $values
159
     * @return $this
160
     */
161 1
    public function addManyToSet(array $values)
162
    {
163 1
        $this->expr->addManyToSet($values);
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\ODM\MongoDB\Query\Expr::addManyToSet() has been deprecated with message: 1.1 Use {@link Expr::addToSet()} with {@link Expr::each()}; 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...
164 1
        return $this;
165
    }
166
167
    /**
168
     * Add one or more $nor clauses to the current query.
169
     *
170
     * You can create a new expression using the {@link Builder::expr()} method.
171
     *
172
     * @see Expr::addNor()
173
     * @see http://docs.mongodb.org/manual/reference/operator/nor/
174
     * @param array|Expr $expression
175
     * @return $this
176
     */
177 3
    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...
178
    {
179 3
        $this->expr->addNor(...func_get_args());
180 3
        return $this;
181
    }
182
183
    /**
184
     * Add one or more $or clauses to the current query.
185
     *
186
     * You can create a new expression using the {@link Builder::expr()} method.
187
     *
188
     * @see Expr::addOr()
189
     * @see http://docs.mongodb.org/manual/reference/operator/or/
190
     * @param array|Expr $expression
191
     * @return $this
192
     */
193 6
    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...
194
    {
195 6
        $this->expr->addOr(...func_get_args());
196 6
        return $this;
197
    }
198
199
    /**
200
     * Append one or more values to the current array field only if they do not
201
     * already exist in the array.
202
     *
203
     * If the field does not exist, it will be set to an array containing the
204
     * unique value(s) in the argument. If the field is not an array, the query
205
     * will yield an error.
206
     *
207
     * Multiple values may be specified by provided an Expr object and using
208
     * {@link Expr::each()}.
209
     *
210
     * @see Expr::addToSet()
211
     * @see http://docs.mongodb.org/manual/reference/operator/addToSet/
212
     * @see http://docs.mongodb.org/manual/reference/operator/each/
213
     * @param mixed|Expr $valueOrExpression
214
     * @return $this
215
     */
216 5
    public function addToSet($valueOrExpression)
217
    {
218 5
        $this->expr->addToSet($valueOrExpression);
219 5
        return $this;
220
    }
221
222
    /**
223
     * Specify $all criteria for the current field.
224
     *
225
     * @see Expr::all()
226
     * @see http://docs.mongodb.org/manual/reference/operator/all/
227
     * @param array $values
228
     * @return $this
229
     */
230 3
    public function all(array $values)
231
    {
232 3
        $this->expr->all($values);
233 3
        return $this;
234
    }
235
236
    /**
237
     * Apply a bitwise and operation on the current field.
238
     *
239
     * @see Expr::bitAnd()
240
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
241
     * @param int $value
242
     * @return $this
243
     */
244 1
    public function bitAnd($value)
245
    {
246 1
        $this->expr->bitAnd($value);
247 1
        return $this;
248
    }
249
250
    /**
251
     * Apply a bitwise or operation on the current field.
252
     *
253
     * @see Expr::bitOr()
254
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
255
     * @param int $value
256
     * @return $this
257
     */
258 1
    public function bitOr($value)
259
    {
260 1
        $this->expr->bitOr($value);
261 1
        return $this;
262
    }
263
264
    /**
265
     * Matches documents where all of the bit positions given by the query are
266
     * clear.
267
     *
268
     * @see Expr::bitsAllClear()
269
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAllClear/
270
     * @param int|array|\MongoBinData $value
271
     * @return $this
272
     */
273 1
    public function bitsAllClear($value)
274
    {
275 1
        $this->expr->bitsAllClear($value);
276 1
        return $this;
277
    }
278
279
    /**
280
     * Matches documents where all of the bit positions given by the query are
281
     * set.
282
     *
283
     * @see Expr::bitsAllSet()
284
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAllSet/
285
     * @param int|array|\MongoBinData $value
286
     * @return $this
287
     */
288 1
    public function bitsAllSet($value)
289
    {
290 1
        $this->expr->bitsAllSet($value);
291 1
        return $this;
292
    }
293
294
    /**
295
     * Matches documents where any of the bit positions given by the query are
296
     * clear.
297
     *
298
     * @see Expr::bitsAnyClear()
299
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAnyClear/
300
     * @param int|array|\MongoBinData $value
301
     * @return $this
302
     */
303 1
    public function bitsAnyClear($value)
304
    {
305 1
        $this->expr->bitsAnyClear($value);
306 1
        return $this;
307
    }
308
309
    /**
310
     * Matches documents where any of the bit positions given by the query are
311
     * set.
312
     *
313
     * @see Expr::bitsAnySet()
314
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAnySet/
315
     * @param int|array|\MongoBinData $value
316
     * @return $this
317
     */
318 1
    public function bitsAnySet($value)
319
    {
320 1
        $this->expr->bitsAnySet($value);
321 1
        return $this;
322
    }
323
324
    /**
325
     * Apply a bitwise xor operation on the current field.
326
     *
327
     * @see Expr::bitXor()
328
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
329
     * @param int $value
330
     * @return $this
331
     */
332 1
    public function bitXor($value)
333
    {
334 1
        $this->expr->bitXor($value);
335 1
        return $this;
336
    }
337
338
    /**
339
     * A boolean flag to enable or disable case sensitive search for $text
340
     * criteria.
341
     *
342
     * This method must be called after text().
343
     *
344
     * @see Expr::caseSensitive()
345
     * @see http://docs.mongodb.org/manual/reference/operator/text/
346
     * @param bool $caseSensitive
347
     * @return $this
348
     * @throws \BadMethodCallException if the query does not already have $text criteria
349
     *
350
     * @since 1.3
351
     */
352 1
    public function caseSensitive($caseSensitive)
353
    {
354 1
        $this->expr->caseSensitive($caseSensitive);
355 1
        return $this;
356
    }
357
358
    /**
359
     * Associates a comment to any expression taking a query predicate.
360
     *
361
     * @see Expr::comment()
362
     * @see http://docs.mongodb.org/manual/reference/operator/query/comment/
363
     * @param string $comment
364
     * @return $this
365
     */
366 1
    public function comment($comment)
367
    {
368 1
        $this->expr->comment($comment);
369 1
        return $this;
370
    }
371
372
    /**
373
     * Change the query type to count.
374
     *
375
     * @return $this
376
     */
377
    public function count()
378
    {
379
        $this->query['type'] = Query::TYPE_COUNT;
380
        return $this;
381
    }
382
383
    /**
384
     * Sets the value of the current field to the current date, either as a date or a timestamp.
385
     *
386
     * @see Expr::currentDate()
387
     * @see http://docs.mongodb.org/manual/reference/operator/currentDate/
388
     * @param string $type
389
     * @return $this
390
     */
391 3
    public function currentDate($type = 'date')
392
    {
393 3
        $this->expr->currentDate($type);
394 2
        return $this;
395
    }
396
397
    /**
398
     * Return an array of information about the Builder state for debugging.
399
     *
400
     * The $name parameter may be used to return a specific key from the
401
     * internal $query array property. If omitted, the entire array will be
402
     * returned.
403
     *
404
     * @param string $name
405
     * @return mixed
406
     */
407 28
    public function debug($name = null)
408
    {
409 28
        return $name !== null ? $this->query[$name] : $this->query;
410
    }
411
412
    /**
413
     * A boolean flag to enable or disable diacritic sensitive search for $text
414
     * criteria.
415
     *
416
     * This method must be called after text().
417
     *
418
     * @see Builder::diacriticSensitive()
419
     * @see http://docs.mongodb.org/manual/reference/operator/text/
420
     * @param bool $diacriticSensitive
421
     * @return $this
422
     * @throws \BadMethodCallException if the query does not already have $text criteria
423
     *
424
     * @since 1.3
425
     */
426 1
    public function diacriticSensitive($diacriticSensitive)
427
    {
428 1
        $this->expr->diacriticSensitive($diacriticSensitive);
429 1
        return $this;
430
    }
431
432
    /**
433
     * Change the query type to a distinct command.
434
     *
435
     * @see http://docs.mongodb.org/manual/reference/command/distinct/
436
     * @param string $field
437
     * @return $this
438
     */
439 2
    public function distinct($field)
440
    {
441 2
        $this->query['type'] = Query::TYPE_DISTINCT;
442 2
        $this->query['distinct'] = $field;
443 2
        return $this;
444
    }
445
446
    /**
447
     * Set whether the query should return its result as an EagerCursor.
448
     *
449
     * @param boolean $bool
450
     * @return $this
451
     */
452 5
    public function eagerCursor($bool = true)
453
    {
454 5
        if ( ! $bool && ! empty($this->primers)) {
455 1
            throw new \BadMethodCallException("Can't set eagerCursor to false when using reference primers");
456
        }
457
458 4
        $this->query['eagerCursor'] = (boolean) $bool;
459 4
        return $this;
460
    }
461
462
    /**
463
     * Specify $elemMatch criteria for the current field.
464
     *
465
     * You can create a new expression using the {@link Builder::expr()} method.
466
     *
467
     * @see Expr::elemMatch()
468
     * @see http://docs.mongodb.org/manual/reference/operator/elemMatch/
469
     * @param array|Expr $expression
470
     * @return $this
471
     */
472 6
    public function elemMatch($expression)
473
    {
474 6
        $this->expr->elemMatch($expression);
475 6
        return $this;
476
    }
477
478
    /**
479
     * Specify an equality match for the current field.
480
     *
481
     * @see Expr::equals()
482
     * @param mixed $value
483
     * @return $this
484
     */
485 75
    public function equals($value)
486
    {
487 75
        $this->expr->equals($value);
488 75
        return $this;
489
    }
490
491
    /**
492
     * Set one or more fields to be excluded from the query projection.
493
     *
494
     * If fields have been selected for inclusion, only the "_id" field may be
495
     * excluded.
496
     *
497
     * @param array|string $fieldName,...
0 ignored issues
show
Documentation introduced by
There is no parameter named $fieldName,.... Did you maybe mean $fieldName?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

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

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

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

Loading history...
498
     * @return $this
499
     */
500 6 View Code Duplication
    public function exclude($fieldName = 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...
501
    {
502 6
        if ( ! isset($this->query['select'])) {
503 6
            $this->query['select'] = [];
504
        }
505
506 6
        $fieldNames = is_array($fieldName) ? $fieldName : func_get_args();
507
508 6
        foreach ($fieldNames as $fieldName) {
509 4
            $this->query['select'][$fieldName] = 0;
510
        }
511
512 6
        return $this;
513
    }
514
515
    /**
516
     * Specify $exists criteria for the current field.
517
     *
518
     * @see Expr::exists()
519
     * @see http://docs.mongodb.org/manual/reference/operator/exists/
520
     * @param boolean $bool
521
     * @return $this
522
     */
523 5
    public function exists($bool)
524
    {
525 5
        $this->expr->exists((boolean) $bool);
526 5
        return $this;
527
    }
528
529
    /**
530
     * Create a new Expr instance that can be used as an expression with the Builder
531
     *
532
     * @return Expr $expr
533
     */
534 26
    public function expr()
535
    {
536 26
        $expr = new Expr($this->dm);
537 26
        $expr->setClassMetadata($this->class);
538
539 26
        return $expr;
540
    }
541
542
    /**
543
     * Set the current field to operate on.
544
     *
545
     * @param string $field
546
     * @return $this
547
     */
548 144
    public function field($field)
549
    {
550 144
        $this->currentField = $field;
551 144
        $this->expr->field((string) $field);
552
553 144
        return $this;
554
    }
555
556
    /**
557
     * Set the "finalize" option for a mapReduce or group command.
558
     *
559
     * @param string|\MongoCode $finalize
560
     * @return $this
561
     * @throws \BadMethodCallException if the query is not a mapReduce or group command
562
     */
563 2 View Code Duplication
    public function finalize($finalize)
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...
564
    {
565 2
        switch ($this->query['type']) {
566 2
            case Query::TYPE_MAP_REDUCE:
567 1
                $this->query['mapReduce']['options']['finalize'] = $finalize;
568 1
                break;
569
570 1
            case Query::TYPE_GROUP:
571
                $this->query['group']['options']['finalize'] = $finalize;
572
                break;
573
574
            default:
575 1
                throw new \BadMethodCallException('mapReduce(), map() or group() must be called before finalize()');
576
        }
577
578 1
        return $this;
579
    }
580
581
    /**
582
     * Change the query type to find and optionally set and change the class being queried.
583
     *
584
     * @param string $documentName
585
     * @return $this
586
     */
587 12
    public function find($documentName = null)
588
    {
589 12
        $this->setDocumentName($documentName);
590 12
        $this->query['type'] = Query::TYPE_FIND;
591
592 12
        return $this;
593
    }
594
595
    /**
596
     * @param string $documentName
597
     * @return $this
598
     */
599 1
    public function findAndRemove($documentName = null)
600
    {
601 1
        $this->setDocumentName($documentName);
602 1
        $this->query['type'] = Query::TYPE_FIND_AND_REMOVE;
603
604 1
        return $this;
605
    }
606
607
    /**
608
     * @param string $documentName
609
     * @return $this
610
     */
611 13
    public function findAndUpdate($documentName = null)
612
    {
613 13
        $this->setDocumentName($documentName);
614 13
        $this->query['type'] = Query::TYPE_FIND_AND_UPDATE;
615
616 13
        return $this;
617
    }
618
619
    /**
620
     * Add $geoIntersects criteria with a GeoJSON geometry to the query.
621
     *
622
     * The geometry parameter GeoJSON object or an array corresponding to the
623
     * geometry's JSON representation.
624
     *
625
     * @see Expr::geoIntersects()
626
     * @see http://docs.mongodb.org/manual/reference/operator/geoIntersects/
627
     * @param array|Geometry $geometry
628
     * @return $this
629
     */
630 1
    public function geoIntersects($geometry)
631
    {
632 1
        $this->expr->geoIntersects($geometry);
633 1
        return $this;
634
    }
635
636
    /**
637
     * Add $geoWithin criteria with a GeoJSON geometry to the query.
638
     *
639
     * The geometry parameter GeoJSON object or an array corresponding to the
640
     * geometry's JSON representation.
641
     *
642
     * @see Expr::geoWithin()
643
     * @see http://docs.mongodb.org/manual/reference/operator/geoWithin/
644
     * @param array|Geometry $geometry
645
     * @return $this
646
     */
647 1
    public function geoWithin($geometry)
648
    {
649 1
        $this->expr->geoWithin($geometry);
650 1
        return $this;
651
    }
652
653
    /**
654
     * Add $geoWithin criteria with a $box shape to the query.
655
     *
656
     * A rectangular polygon will be constructed from a pair of coordinates
657
     * corresponding to the bottom left and top right corners.
658
     *
659
     * Note: the $box operator only supports legacy coordinate pairs and 2d
660
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
661
     *
662
     * @see Expr::geoWithinBox()
663
     * @see http://docs.mongodb.org/manual/reference/operator/box/
664
     * @param float $x1
665
     * @param float $y1
666
     * @param float $x2
667
     * @param float $y2
668
     * @return $this
669
     */
670 1
    public function geoWithinBox($x1, $y1, $x2, $y2)
671
    {
672 1
        $this->expr->geoWithinBox($x1, $y1, $x2, $y2);
673 1
        return $this;
674
    }
675
676
    /**
677
     * Add $geoWithin criteria with a $center shape to the query.
678
     *
679
     * Note: the $center operator only supports legacy coordinate pairs and 2d
680
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
681
     *
682
     * @see Expr::geoWithinCenter()
683
     * @see http://docs.mongodb.org/manual/reference/operator/center/
684
     * @param float $x
685
     * @param float $y
686
     * @param float $radius
687
     * @return $this
688
     */
689 1
    public function geoWithinCenter($x, $y, $radius)
690
    {
691 1
        $this->expr->geoWithinCenter($x, $y, $radius);
692 1
        return $this;
693
    }
694
695
    /**
696
     * Add $geoWithin criteria with a $centerSphere shape to the query.
697
     *
698
     * Note: the $centerSphere operator supports both 2d and 2dsphere indexes.
699
     *
700
     * @see Expr::geoWithinCenterSphere()
701
     * @see http://docs.mongodb.org/manual/reference/operator/centerSphere/
702
     * @param float $x
703
     * @param float $y
704
     * @param float $radius
705
     * @return $this
706
     */
707 1
    public function geoWithinCenterSphere($x, $y, $radius)
708
    {
709 1
        $this->expr->geoWithinCenterSphere($x, $y, $radius);
710 1
        return $this;
711
    }
712
713
    /**
714
     * Add $geoWithin criteria with a $polygon shape to the query.
715
     *
716
     * Point coordinates are in x, y order (easting, northing for projected
717
     * coordinates, longitude, latitude for geographic coordinates).
718
     *
719
     * The last point coordinate is implicitly connected with the first.
720
     *
721
     * Note: the $polygon operator only supports legacy coordinate pairs and 2d
722
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
723
     *
724
     * @see Expr::geoWithinPolygon()
725
     * @see http://docs.mongodb.org/manual/reference/operator/polygon/
726
     * @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...
727
     * @return $this
728
     */
729 1
    public function geoWithinPolygon(/* array($x1, $y1), ... */)
730
    {
731 1
        $this->expr->geoWithinPolygon(...func_get_args());
732 1
        return $this;
733
    }
734
735
    /**
736
     * Return the expression's "new object".
737
     *
738
     * @see Expr::getNewObj()
739
     * @return array
740
     */
741 13
    public function getNewObj()
742
    {
743 13
        return $this->expr->getNewObj();
744
    }
745
746
    /**
747
     * Gets the Query executable.
748
     *
749
     * @param array $options
750
     * @return Query $query
751
     */
752 150
    public function getQuery(array $options = array())
753
    {
754 150
        if ($this->query['type'] === Query::TYPE_MAP_REDUCE) {
755
            $this->hydrate = false;
756
        }
757
758 150
        $documentPersister = $this->dm->getUnitOfWork()->getDocumentPersister($this->class->name);
759
760 150
        $query = $this->query;
761
762 150
        $query['query'] = $this->expr->getQuery();
763 150
        $query['query'] = $documentPersister->addDiscriminatorToPreparedQuery($query['query']);
764 150
        $query['query'] = $documentPersister->addFilterToPreparedQuery($query['query']);
765
766 150
        $query['newObj'] = $this->expr->getNewObj();
767
768 150
        if (isset($query['distinct'])) {
769 2
            $query['distinct'] = $documentPersister->prepareFieldName($query['distinct']);
0 ignored issues
show
Documentation introduced by
$query['distinct'] is of type array, but the function expects a string.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
770
        }
771
772 150
        if ($this->class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION && ! empty($query['upsert']) &&
773 150
            (empty($query['query'][$this->class->discriminatorField]) || is_array($query['query'][$this->class->discriminatorField]))) {
774 1
            throw new \InvalidArgumentException('Upsert query that is to be performed on discriminated document does not have single ' .
775 1
                'discriminator. Either not use base class or set \'' . $this->class->discriminatorField . '\' field manually.');
776
        }
777
778 149
        if ( ! empty($query['select'])) {
779 14
            $query['select'] = $documentPersister->prepareProjection($query['select']);
780 14
            if ($this->hydrate && $this->class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION
781 14
                && ! isset($query['select'][$this->class->discriminatorField])) {
782
                $includeMode = 0 < count(array_filter($query['select'], function($mode) { return $mode == 1; }));
783 2
                if ($includeMode && ! isset($query['select'][$this->class->discriminatorField])) {
784 1
                    $query['select'][$this->class->discriminatorField] = 1;
785
                }
786
            }
787
        }
788
789 149
        if (isset($query['sort'])) {
790 23
            $query['sort'] = $documentPersister->prepareSort($query['sort']);
791
        }
792
793 149
        if ($this->class->slaveOkay) {
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\ODM\MongoDB\Map...etadataInfo::$slaveOkay has been deprecated with message: in version 1.2 and will be removed in 2.0.

This property 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 property will be removed from the class and what other property to use instead.

Loading history...
794
            $query['slaveOkay'] = $this->class->slaveOkay;
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\ODM\MongoDB\Map...etadataInfo::$slaveOkay has been deprecated with message: in version 1.2 and will be removed in 2.0.

This property 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 property will be removed from the class and what other property to use instead.

Loading history...
795
        }
796
797 149
        if ($this->class->readPreference && ! array_key_exists('readPreference', $query)) {
798 1
            $query['readPreference'] = new ReadPreference($this->class->readPreference, $this->class->readPreferenceTags);
799
        }
800
801 149
        return new Query(
802 149
            $this->dm,
803 149
            $this->class,
804 149
            $this->collection,
805 149
            $query,
806 149
            $options,
807 149
            $this->hydrate,
808 149
            $this->refresh,
809 149
            $this->primers,
810 149
            $this->readOnly
811
        );
812
    }
813
814
    /**
815
     * Return the expression's query criteria.
816
     *
817
     * @see Expr::getQuery()
818
     * @return array
819
     */
820 33
    public function getQueryArray()
821
    {
822 33
        return $this->expr->getQuery();
823
    }
824
825
    /**
826
     * Get the type of this query.
827
     *
828
     * @return integer $type
829
     */
830 2
    public function getType()
831
    {
832 2
        return $this->query['type'];
833
    }
834
835
    /**
836
     * Specify $gt criteria for the current field.
837
     *
838
     * @see Expr::gt()
839
     * @see http://docs.mongodb.org/manual/reference/operator/gt/
840
     * @param mixed $value
841
     * @return $this
842
     */
843 2
    public function gt($value)
844
    {
845 2
        $this->expr->gt($value);
846 2
        return $this;
847
    }
848
849
    /**
850
     * Specify $gte criteria for the current field.
851
     *
852
     * @see Expr::gte()
853
     * @see http://docs.mongodb.org/manual/reference/operator/gte/
854
     * @param mixed $value
855
     * @return $this
856
     */
857 2
    public function gte($value)
858
    {
859 2
        $this->expr->gte($value);
860 2
        return $this;
861
    }
862
863
    /**
864
     * Set the index hint for the query.
865
     *
866
     * @param array|string $index
867
     * @return $this
868
     */
869
    public function hint($index)
870
    {
871
        $this->query['hint'] = $index;
872
        return $this;
873
    }
874
875
    /**
876
     * @param bool $bool
877
     * @return $this
878
     */
879 17
    public function hydrate($bool = true)
880
    {
881 17
        $this->hydrate = $bool;
882 17
        return $this;
883
    }
884
885
    /**
886
     * Set the immortal cursor flag.
887
     *
888
     * @param boolean $bool
889
     * @return $this
890
     */
891
    public function immortal($bool = true)
892
    {
893
        $this->query['immortal'] = (boolean) $bool;
894
        return $this;
895
    }
896
897
    /**
898
     * Specify $in criteria for the current field.
899
     *
900
     * @see Expr::in()
901
     * @see http://docs.mongodb.org/manual/reference/operator/in/
902
     * @param array $values
903
     * @return $this
904
     */
905 24
    public function in(array $values)
906
    {
907 24
        $this->expr->in($values);
908 24
        return $this;
909
    }
910
911
    /**
912
     * Increment the current field.
913
     *
914
     * If the field does not exist, it will be set to this value.
915
     *
916
     * @see Expr::inc()
917
     * @see http://docs.mongodb.org/manual/reference/operator/inc/
918
     * @param float|integer $value
919
     * @return $this
920
     */
921 6
    public function inc($value)
922
    {
923 6
        $this->expr->inc($value);
924 6
        return $this;
925
    }
926
927
    /**
928
     * @param object $document
929
     * @return $this
930
     */
931 6
    public function includesReferenceTo($document)
932
    {
933 6
        $this->expr->includesReferenceTo($document);
934 4
        return $this;
935
    }
936
937
    /**
938
     * @param string $documentName
939
     * @return $this
940
     */
941 1
    public function insert($documentName = null)
942
    {
943 1
        $this->setDocumentName($documentName);
944 1
        $this->query['type'] = Query::TYPE_INSERT;
945
946 1
        return $this;
947
    }
948
949
    /**
950
     * Set the $language option for $text criteria.
951
     *
952
     * This method must be called after text().
953
     *
954
     * @see Expr::language()
955
     * @see http://docs.mongodb.org/manual/reference/operator/text/
956
     * @param string $language
957
     * @return $this
958
     */
959 1
    public function language($language)
960
    {
961 1
        $this->expr->language($language);
962 1
        return $this;
963
    }
964
965
    /**
966
     * Set the limit for the query.
967
     *
968
     * This is only relevant for find queries and geoNear and mapReduce
969
     * commands.
970
     *
971
     * @see Query::prepareCursor()
972
     * @param integer $limit
973
     * @return $this
974
     */
975 2
    public function limit($limit)
976
    {
977 2
        $this->query['limit'] = (integer) $limit;
978 2
        return $this;
979
    }
980
981
    /**
982
     * Specify $lt criteria for the current field.
983
     *
984
     * @see Expr::lte()
985
     * @see http://docs.mongodb.org/manual/reference/operator/lte/
986
     * @param mixed $value
987
     * @return $this
988
     */
989
    public function lt($value)
990
    {
991
        $this->expr->lt($value);
992
        return $this;
993
    }
994
995
    /**
996
     * Specify $lte criteria for the current field.
997
     *
998
     * @see Expr::lte()
999
     * @see http://docs.mongodb.org/manual/reference/operator/lte/
1000
     * @param mixed $value
1001
     * @return $this
1002
     */
1003
    public function lte($value)
1004
    {
1005
        $this->expr->lte($value);
1006
        return $this;
1007
    }
1008
1009
    /**
1010
     * Change the query type to a mapReduce command.
1011
     *
1012
     * The "reduce" option is not specified when calling this method; it must
1013
     * be set with the {@link Builder::reduce()} method.
1014
     *
1015
     * The "out" option defaults to inline, like {@link Builder::mapReduce()}.
1016
     *
1017
     * @see http://docs.mongodb.org/manual/reference/command/mapReduce/
1018
     * @param string|\MongoCode $map
1019
     * @return $this
1020
     */
1021 1
    public function map($map)
1022
    {
1023 1
        $this->query['type'] = Query::TYPE_MAP_REDUCE;
1024 1
        $this->query['mapReduce'] = [
1025 1
            'map' => $map,
1026
            'reduce' => null,
1027
            'out' => ['inline' => true],
1028
            'options' => [],
1029
        ];
1030 1
        return $this;
1031
    }
1032
1033
    /**
1034
     * Change the query type to a mapReduce command.
1035
     *
1036
     * @see http://docs.mongodb.org/manual/reference/command/mapReduce/
1037
     * @param string|\MongoCode $map
1038
     * @param string|\MongoCode $reduce
1039
     * @param array|string $out
1040
     * @param array $options
1041
     * @return $this
1042
     */
1043 1
    public function mapReduce($map, $reduce, $out = ['inline' => true], array $options = [])
1044
    {
1045 1
        $this->query['type'] = Query::TYPE_MAP_REDUCE;
1046 1
        $this->query['mapReduce'] = [
1047 1
            'map' => $map,
1048 1
            'reduce' => $reduce,
1049 1
            'out' => $out,
1050 1
            'options' => $options
1051
        ];
1052 1
        return $this;
1053
    }
1054
1055
    /**
1056
     * Set additional options for a mapReduce command.
1057
     *
1058
     * @param array $options
1059
     * @return $this
1060
     * @throws \BadMethodCallException if the query is not a mapReduce command
1061
     */
1062 1 View Code Duplication
    public function mapReduceOptions(array $options)
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...
1063
    {
1064 1
        if ($this->query['type'] !== Query::TYPE_MAP_REDUCE) {
1065 1
            throw new \BadMethodCallException('This method requires a mapReduce command (call map() or mapReduce() first)');
1066
        }
1067
1068
        $this->query['mapReduce']['options'] = $options;
1069
        return $this;
1070
    }
1071
1072
    /**
1073
     * Updates the value of the field to a specified value if the specified value is greater than the current value of the field.
1074
     *
1075
     * @see Expr::max()
1076
     * @see http://docs.mongodb.org/manual/reference/operator/update/max/
1077
     * @param mixed $value
1078
     * @return $this
1079
     */
1080 1
    public function max($value)
1081
    {
1082 1
        $this->expr->max($value);
1083 1
        return $this;
1084
    }
1085
1086
    /**
1087
     * Specifies a cumulative time limit in milliseconds for processing operations on a cursor.
1088
     *
1089
     * @param int $ms
1090
     * @return $this
1091
     */
1092
    public function maxTimeMS($ms)
1093
    {
1094
        $this->query['maxTimeMS'] = $ms;
1095
        return $this;
1096
    }
1097
1098
    /**
1099
     * Updates the value of the field to a specified value if the specified value is less than the current value of the field.
1100
     *
1101
     * @see Expr::min()
1102
     * @see http://docs.mongodb.org/manual/reference/operator/update/min/
1103
     * @param mixed $value
1104
     * @return $this
1105
     */
1106 1
    public function min($value)
1107
    {
1108 1
        $this->expr->min($value);
1109 1
        return $this;
1110
    }
1111
1112
    /**
1113
     * Specify $mod criteria for the current field.
1114
     *
1115
     * @see Expr::mod()
1116
     * @see http://docs.mongodb.org/manual/reference/operator/mod/
1117
     * @param float|integer $divisor
1118
     * @param float|integer $remainder
1119
     * @return $this
1120
     */
1121 1
    public function mod($divisor, $remainder = 0)
1122
    {
1123 1
        $this->expr->mod($divisor, $remainder);
1124 1
        return $this;
1125
    }
1126
1127
    /**
1128
     * Multiply the current field.
1129
     *
1130
     * If the field does not exist, it will be set to 0.
1131
     *
1132
     * @see Expr::mul()
1133
     * @see http://docs.mongodb.org/manual/reference/operator/mul/
1134
     * @param float|integer $value
1135
     * @return $this
1136
     */
1137 1
    public function mul($value)
1138
    {
1139 1
        $this->expr->mul($value);
1140 1
        return $this;
1141
    }
1142
1143
    /**
1144
     * Set the "multiple" option for an update query.
1145
     *
1146
     * @param boolean $bool
1147
     * @return $this
1148
     *
1149
     * @deprecated Deprecated in version 1.4 - use updateOne or updateMany instead
1150
     */
1151
    public function multiple($bool = true)
1152
    {
1153
        $this->query['multiple'] = (boolean) $bool;
1154
        return $this;
1155
    }
1156
1157
    /**
1158
     * Add $near criteria to the query.
1159
     *
1160
     * A GeoJSON point may be provided as the first and only argument for
1161
     * 2dsphere queries. This single parameter may be a GeoJSON point object or
1162
     * an array corresponding to the point's JSON representation.
1163
     *
1164
     * @see Expr::near()
1165
     * @see http://docs.mongodb.org/manual/reference/operator/near/
1166
     * @param float|array|Point $x
1167
     * @param float $y
1168
     * @return $this
1169
     */
1170 1
    public function near($x, $y = null)
1171
    {
1172 1
        $this->expr->near($x, $y);
1173 1
        return $this;
1174
    }
1175
1176
    /**
1177
     * Add $nearSphere criteria to the query.
1178
     *
1179
     * A GeoJSON point may be provided as the first and only argument for
1180
     * 2dsphere queries. This single parameter may be a GeoJSON point object or
1181
     * an array corresponding to the point's JSON representation.
1182
     *
1183
     * @see Expr::nearSphere()
1184
     * @see http://docs.mongodb.org/manual/reference/operator/nearSphere/
1185
     * @param float|array|Point $x
1186
     * @param float $y
1187
     * @return $this
1188
     */
1189 1
    public function nearSphere($x, $y = null)
1190
    {
1191 1
        $this->expr->nearSphere($x, $y);
1192 1
        return $this;
1193
    }
1194
1195
    /**
1196
     * Negates an expression for the current field.
1197
     *
1198
     * You can create a new expression using the {@link Builder::expr()} method.
1199
     *
1200
     * @see Expr::not()
1201
     * @see http://docs.mongodb.org/manual/reference/operator/not/
1202
     * @param array|Expr $expression
1203
     * @return $this
1204
     */
1205 3
    public function not($expression)
1206
    {
1207 3
        $this->expr->not($expression);
1208 3
        return $this;
1209
    }
1210
1211
    /**
1212
     * Specify $ne criteria for the current field.
1213
     *
1214
     * @see Expr::notEqual()
1215
     * @see http://docs.mongodb.org/manual/reference/operator/ne/
1216
     * @param mixed $value
1217
     * @return $this
1218
     */
1219 4
    public function notEqual($value)
1220
    {
1221 4
        $this->expr->notEqual($value);
1222 4
        return $this;
1223
    }
1224
1225
    /**
1226
     * Specify $nin criteria for the current field.
1227
     *
1228
     * @see Expr::notIn()
1229
     * @see http://docs.mongodb.org/manual/reference/operator/nin/
1230
     * @param array $values
1231
     * @return $this
1232
     */
1233 4
    public function notIn(array $values)
1234
    {
1235 4
        $this->expr->notIn($values);
1236 4
        return $this;
1237
    }
1238
1239
    /**
1240
     * Set the "out" option for a mapReduce command.
1241
     *
1242
     * @param array|string $out
1243
     * @return $this
1244
     * @throws \BadMethodCallException if the query is not a mapReduce command
1245
     */
1246 1 View Code Duplication
    public function out($out)
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...
1247
    {
1248 1
        if ($this->query['type'] !== Query::TYPE_MAP_REDUCE) {
1249 1
            throw new \BadMethodCallException('This method requires a mapReduce command (call map() or mapReduce() first)');
1250
        }
1251
1252
        $this->query['mapReduce']['out'] = $out;
1253
        return $this;
1254
    }
1255
1256
    /**
1257
     * Remove the first element from the current array field.
1258
     *
1259
     * @see Expr::popFirst()
1260
     * @see http://docs.mongodb.org/manual/reference/operator/pop/
1261
     * @return $this
1262
     */
1263 2
    public function popFirst()
1264
    {
1265 2
        $this->expr->popFirst();
1266 2
        return $this;
1267
    }
1268
1269
    /**
1270
     * Remove the last element from the current array field.
1271
     *
1272
     * @see Expr::popLast()
1273
     * @see http://docs.mongodb.org/manual/reference/operator/pop/
1274
     * @return $this
1275
     */
1276 1
    public function popLast()
1277
    {
1278 1
        $this->expr->popLast();
1279 1
        return $this;
1280
    }
1281
1282
    /**
1283
     * Use a primer to eagerly load all references in the current field.
1284
     *
1285
     * If $primer is true or a callable is provided, referenced documents for
1286
     * this field will loaded into UnitOfWork immediately after the query is
1287
     * executed. This will avoid multiple queries due to lazy initialization of
1288
     * Proxy objects.
1289
     *
1290
     * If $primer is false, no priming will take place. That is also the default
1291
     * behavior.
1292
     *
1293
     * If a custom callable is used, its signature should conform to the default
1294
     * Closure defined in {@link ReferencePrimer::__construct()}.
1295
     *
1296
     * @param boolean|callable $primer
1297
     * @return $this
1298
     * @throws \InvalidArgumentException If $primer is not boolean or callable
1299
     */
1300 25
    public function prime($primer = true)
1301
    {
1302 25
        if ( ! is_bool($primer) && ! is_callable($primer)) {
1303 1
            throw new \InvalidArgumentException('$primer is not a boolean or callable');
1304
        }
1305
1306 24
        if ($primer === false) {
1307
            unset($this->primers[$this->currentField]);
1308
1309
            return $this;
1310
        }
1311
1312 24
        if (array_key_exists('eagerCursor', $this->query) && !$this->query['eagerCursor']) {
1313 1
            throw new \BadMethodCallException("Can't call prime() when setting eagerCursor to false");
1314
        }
1315
1316 23
        $this->primers[$this->currentField] = $primer;
1317 23
        return $this;
1318
    }
1319
1320
    /**
1321
     * Remove all elements matching the given value or expression from the
1322
     * current array field.
1323
     *
1324
     * @see Expr::pull()
1325
     * @see http://docs.mongodb.org/manual/reference/operator/pull/
1326
     * @param mixed|Expr $valueOrExpression
1327
     * @return $this
1328
     */
1329 1
    public function pull($valueOrExpression)
1330
    {
1331 1
        $this->expr->pull($valueOrExpression);
1332 1
        return $this;
1333
    }
1334
1335
    /**
1336
     * Remove all elements matching any of the given values from the current
1337
     * array field.
1338
     *
1339
     * @see Expr::pullAll()
1340
     * @see http://docs.mongodb.org/manual/reference/operator/pullAll/
1341
     * @param array $values
1342
     * @return $this
1343
     */
1344 1
    public function pullAll(array $values)
1345
    {
1346 1
        $this->expr->pullAll($values);
1347 1
        return $this;
1348
    }
1349
1350
    /**
1351
     * Append one or more values to the current array field.
1352
     *
1353
     * If the field does not exist, it will be set to an array containing the
1354
     * value(s) in the argument. If the field is not an array, the query
1355
     * will yield an error.
1356
     *
1357
     * Multiple values may be specified by providing an Expr object and using
1358
     * {@link Expr::each()}. {@link Expr::slice()} and {@link Expr::sort()} may
1359
     * also be used to limit and order array elements, respectively.
1360
     *
1361
     * @see Expr::push()
1362
     * @see http://docs.mongodb.org/manual/reference/operator/push/
1363
     * @see http://docs.mongodb.org/manual/reference/operator/each/
1364
     * @see http://docs.mongodb.org/manual/reference/operator/slice/
1365
     * @see http://docs.mongodb.org/manual/reference/operator/sort/
1366
     * @param mixed|Expr $valueOrExpression
1367
     * @return $this
1368
     */
1369 6
    public function push($valueOrExpression)
1370
    {
1371 6
        $this->expr->push($valueOrExpression);
1372 6
        return $this;
1373
    }
1374
1375
    /**
1376
     * Append multiple values to the current array field.
1377
     *
1378
     * If the field does not exist, it will be set to an array containing the
1379
     * values in the argument. If the field is not an array, the query will
1380
     * yield an error.
1381
     *
1382
     * This operator is deprecated in MongoDB 2.4. {@link Builder::push()} and
1383
     * {@link Expr::each()} should be used in its place.
1384
     *
1385
     * @see Expr::pushAll()
1386
     * @see http://docs.mongodb.org/manual/reference/operator/pushAll/
1387
     * @param array $values
1388
     * @return $this
1389
     */
1390 1
    public function pushAll(array $values)
1391
    {
1392 1
        $this->expr->pushAll($values);
1393 1
        return $this;
1394
    }
1395
1396
    /**
1397
     * Specify $gte and $lt criteria for the current field.
1398
     *
1399
     * This method is shorthand for specifying $gte criteria on the lower bound
1400
     * and $lt criteria on the upper bound. The upper bound is not inclusive.
1401
     *
1402
     * @see Expr::range()
1403
     * @param mixed $start
1404
     * @param mixed $end
1405
     * @return $this
1406
     */
1407 3
    public function range($start, $end)
1408
    {
1409 3
        $this->expr->range($start, $end);
1410 3
        return $this;
1411
    }
1412
1413
    /**
1414
     * @param bool $bool
1415
     * @return $this
1416
     */
1417 2
    public function readOnly($bool = true)
1418
    {
1419 2
        $this->readOnly = $bool;
1420 2
        return $this;
1421
    }
1422
1423
    /**
1424
     * Set the "reduce" option for a mapReduce or group command.
1425
     *
1426
     * @param string|\MongoCode $reduce
1427
     * @return $this
1428
     * @throws \BadMethodCallException if the query is not a mapReduce or group command
1429
     */
1430 2 View Code Duplication
    public function reduce($reduce)
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...
1431
    {
1432 2
        switch ($this->query['type']) {
1433 2
            case Query::TYPE_MAP_REDUCE:
1434 1
                $this->query['mapReduce']['reduce'] = $reduce;
1435 1
                break;
1436
1437 1
            case Query::TYPE_GROUP:
1438
                $this->query['group']['reduce'] = $reduce;
1439
                break;
1440
1441
            default:
1442 1
                throw new \BadMethodCallException('mapReduce(), map() or group() must be called before reduce()');
1443
        }
1444
1445 1
        return $this;
1446
    }
1447
1448
    /**
1449
     * @param object $document
1450
     * @return $this
1451
     */
1452 10
    public function references($document)
1453
    {
1454 10
        $this->expr->references($document);
1455 8
        return $this;
1456
    }
1457
1458
    /**
1459
     * @param bool $bool
1460
     * @return $this
1461
     */
1462 5
    public function refresh($bool = true)
1463
    {
1464 5
        $this->refresh = $bool;
1465 5
        return $this;
1466
    }
1467
1468
    /**
1469
     * @param string $documentName
1470
     * @return $this
1471
     */
1472 1
    public function remove($documentName = null)
1473
    {
1474 1
        $this->setDocumentName($documentName);
1475 1
        $this->query['type'] = Query::TYPE_REMOVE;
1476
1477 1
        return $this;
1478
    }
1479
1480
    /**
1481
     * Rename the current field.
1482
     *
1483
     * @see Expr::rename()
1484
     * @see http://docs.mongodb.org/manual/reference/operator/rename/
1485
     * @param string $name
1486
     * @return $this
1487
     */
1488
    public function rename($name)
1489
    {
1490
        $this->expr->rename($name);
1491
        return $this;
1492
    }
1493
1494
    /**
1495
     * @param bool $bool
1496
     * @return $this
1497
     */
1498 4
    public function returnNew($bool = true)
1499
    {
1500 4
        $this->refresh(true);
1501 4
        $this->query['new'] = (boolean) $bool;
1502
1503 4
        return $this;
1504
    }
1505
1506
    /**
1507
     * Set one or more fields to be included in the query projection.
1508
     *
1509
     * @param array|string $fieldName,...
0 ignored issues
show
Documentation introduced by
There is no parameter named $fieldName,.... Did you maybe mean $fieldName?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

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

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

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

Loading history...
1510
     * @return $this
1511
     */
1512 19 View Code Duplication
    public function select($fieldName = 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...
1513
    {
1514 19
        if ( ! isset($this->query['select'])) {
1515 18
            $this->query['select'] = [];
1516
        }
1517
1518 19
        $fieldNames = is_array($fieldName) ? $fieldName : func_get_args();
1519
1520 19
        foreach ($fieldNames as $fieldName) {
1521 16
            $this->query['select'][$fieldName] = 1;
1522
        }
1523
1524 19
        return $this;
1525
    }
1526
1527
    /**
1528
     * Select only matching embedded documents in an array field for the query
1529
     * projection.
1530
     *
1531
     * @see http://docs.mongodb.org/manual/reference/projection/elemMatch/
1532
     * @param string $fieldName
1533
     * @param array|Expr $expression
1534
     * @return $this
1535
     */
1536 2
    public function selectElemMatch($fieldName, $expression)
1537
    {
1538 2
        if ($expression instanceof Expr) {
1539 1
            $expression = $expression->getQuery();
1540
        }
1541 2
        $this->query['select'][$fieldName] = ['$elemMatch' => $expression];
1542 2
        return $this;
1543
    }
1544
1545
    /**
1546
     * Select a metadata field for the query projection.
1547
     *
1548
     * @see http://docs.mongodb.org/master/reference/operator/projection/meta/
1549
     * @param string $fieldName
1550
     * @param string $metaDataKeyword
1551
     * @return $this
1552
     */
1553 2
    public function selectMeta($fieldName, $metaDataKeyword)
1554
    {
1555 2
        $this->query['select'][$fieldName] = ['$meta' => $metaDataKeyword];
1556 2
        return $this;
1557
    }
1558
1559
    /**
1560
     * Select a slice of an array field for the query projection.
1561
     *
1562
     * The $countOrSkip parameter has two very different meanings, depending on
1563
     * whether or not $limit is provided. See the MongoDB documentation for more
1564
     * information.
1565
     *
1566
     * @see http://docs.mongodb.org/manual/reference/projection/slice/
1567
     * @param string $fieldName
1568
     * @param integer $countOrSkip Count parameter, or skip if limit is specified
1569
     * @param integer $limit       Limit parameter used in conjunction with skip
1570
     * @return $this
1571
     */
1572 3
    public function selectSlice($fieldName, $countOrSkip, $limit = null)
1573
    {
1574 3
        $slice = $countOrSkip;
1575 3
        if ($limit !== null) {
1576 2
            $slice = [$slice, $limit];
1577
        }
1578 3
        $this->query['select'][$fieldName] = ['$slice' => $slice];
1579 3
        return $this;
1580
    }
1581
1582
    /**
1583
     * Set the current field to a value.
1584
     *
1585
     * This is only relevant for insert, update, or findAndUpdate queries. For
1586
     * update and findAndUpdate queries, the $atomic parameter will determine
1587
     * whether or not a $set operator is used.
1588
     *
1589
     * @see Expr::set()
1590
     * @see http://docs.mongodb.org/manual/reference/operator/set/
1591
     * @param mixed $value
1592
     * @param boolean $atomic
1593
     * @return $this
1594
     */
1595 16
    public function set($value, $atomic = true)
1596
    {
1597 16
        $this->expr->set($value, $atomic && $this->query['type'] !== Query::TYPE_INSERT);
1598 16
        return $this;
1599
    }
1600
1601
    /**
1602
     * Set the expression's "new object".
1603
     *
1604
     * @see Expr::setNewObj()
1605
     * @param array $newObj
1606
     * @return $this
1607
     */
1608
    public function setNewObj(array $newObj)
1609
    {
1610
        $this->expr->setNewObj($newObj);
1611
        return $this;
1612
    }
1613
1614
    /**
1615
     * Set the current field to the value if the document is inserted in an
1616
     * upsert operation.
1617
     *
1618
     * If an update operation with upsert: true results in an insert of a
1619
     * document, then $setOnInsert assigns the specified values to the fields in
1620
     * the document. If the update operation does not result in an insert,
1621
     * $setOnInsert does nothing.
1622
     *
1623
     * @see Expr::setOnInsert()
1624
     * @see https://docs.mongodb.org/manual/reference/operator/update/setOnInsert/
1625
     * @param mixed $value
1626
     * @return $this
1627
     */
1628 2
    public function setOnInsert($value)
1629
    {
1630 2
        $this->expr->setOnInsert($value);
1631 2
        return $this;
1632
    }
1633
1634
    /**
1635
     * Set the read preference for the query.
1636
     *
1637
     * This is only relevant for read-only queries and commands.
1638
     *
1639
     * @see http://docs.mongodb.org/manual/core/read-preference/
1640
     * @param ReadPreference $readPreference
1641
     * @return $this
1642
     */
1643 6
    public function setReadPreference(ReadPreference $readPreference)
1644
    {
1645 6
        $this->query['readPreference'] = $readPreference;
1646 6
        return $this;
1647
    }
1648
1649
    /**
1650
     * Set the expression's query criteria.
1651
     *
1652
     * @see Expr::setQuery()
1653
     * @param array $query
1654
     * @return $this
1655
     */
1656 18
    public function setQueryArray(array $query)
1657
    {
1658 18
        $this->expr->setQuery($query);
1659 18
        return $this;
1660
    }
1661
1662
    /**
1663
     * Specify $size criteria for the current field.
1664
     *
1665
     * @see Expr::size()
1666
     * @see http://docs.mongodb.org/manual/reference/operator/size/
1667
     * @param integer $size
1668
     * @return $this
1669
     */
1670 1
    public function size($size)
1671
    {
1672 1
        $this->expr->size((integer) $size);
1673 1
        return $this;
1674
    }
1675
1676
    /**
1677
     * Set the skip for the query cursor.
1678
     *
1679
     * This is only relevant for find queries, or mapReduce queries that store
1680
     * results in an output collecton and return a cursor.
1681
     *
1682
     * @see Query::prepareCursor()
1683
     * @param integer $skip
1684
     * @return $this
1685
     */
1686
    public function skip($skip)
1687
    {
1688
        $this->query['skip'] = (integer) $skip;
1689
        return $this;
1690
    }
1691
1692
    /**
1693
     * Set the snapshot cursor flag.
1694
     *
1695
     * @param boolean $bool
1696
     * @return $this
1697
     */
1698
    public function snapshot($bool = true)
1699
    {
1700
        $this->query['snapshot'] = (boolean) $bool;
1701
        return $this;
1702
    }
1703
1704
    /**
1705
     * Set one or more field/order pairs on which to sort the query.
1706
     *
1707
     * If sorting by multiple fields, the first argument should be an array of
1708
     * field name (key) and order (value) pairs.
1709
     *
1710
     * @param array|string $fieldName Field name or array of field/order pairs
1711
     * @param int|string $order       Field order (if one field is specified)
1712
     * @return $this
1713
     */
1714 31
    public function sort($fieldName, $order = 1)
1715
    {
1716 31
        if ( ! isset($this->query['sort'])) {
1717 31
            $this->query['sort'] = [];
1718
        }
1719
1720 31
        $fields = is_array($fieldName) ? $fieldName : [$fieldName => $order];
1721
1722 31
        foreach ($fields as $fieldName => $order) {
1723 14
            if (is_string($order)) {
1724 9
                $order = strtolower($order) === 'asc' ? 1 : -1;
1725
            }
1726 14
            $this->query['sort'][$fieldName] = (integer) $order;
1727
        }
1728
1729 31
        return $this;
1730
    }
1731
1732
    /**
1733
     * Specify a projected metadata field on which to sort the query.
1734
     *
1735
     * Sort order is not configurable for metadata fields. Sorting by a metadata
1736
     * field requires the same field and $meta expression to exist in the
1737
     * projection document. This method will call {@link Builder::selectMeta()}
1738
     * if the field is not already set in the projection.
1739
     *
1740
     * @see http://docs.mongodb.org/master/reference/operator/projection/meta/#sort
1741
     * @param string $fieldName       Field name of the projected metadata
1742
     * @param string $metaDataKeyword
1743
     * @return $this
1744
     */
1745 2
    public function sortMeta($fieldName, $metaDataKeyword)
1746
    {
1747
        /* It's possible that the field is already projected without the $meta
1748
         * operator. We'll assume that the user knows what they're doing in that
1749
         * case and will not attempt to override the projection.
1750
         */
1751 2
        if ( ! isset($this->query['select'][$fieldName])) {
1752 1
            $this->selectMeta($fieldName, $metaDataKeyword);
1753
        }
1754
1755 2
        $this->query['sort'][$fieldName] = ['$meta' => $metaDataKeyword];
1756
1757 2
        return $this;
1758
    }
1759
1760
    /**
1761
     * Specify $text criteria for the current field.
1762
     *
1763
     * The $language option may be set with {@link Builder::language()}.
1764
     *
1765
     * @see Expr::text()
1766
     * @see http://docs.mongodb.org/master/reference/operator/query/text/
1767
     * @param string $search
1768
     * @return $this
1769
     */
1770 1
    public function text($search)
1771
    {
1772 1
        $this->expr->text($search);
1773 1
        return $this;
1774
    }
1775
1776
    /**
1777
     * Specify $type criteria for the current field.
1778
     *
1779
     * @see Expr::type()
1780
     * @see http://docs.mongodb.org/manual/reference/operator/type/
1781
     * @param integer $type
1782
     * @return $this
1783
     */
1784 2
    public function type($type)
1785
    {
1786 2
        $this->expr->type($type);
1787 2
        return $this;
1788
    }
1789
1790
    /**
1791
     * Unset the current field.
1792
     *
1793
     * The field will be removed from the document (not set to null).
1794
     *
1795
     * @see Expr::unsetField()
1796
     * @see http://docs.mongodb.org/manual/reference/operator/unset/
1797
     * @return $this
1798
     */
1799 4
    public function unsetField()
1800
    {
1801 4
        $this->expr->unsetField();
1802 4
        return $this;
1803
    }
1804
1805
    /**
1806
     * @param string $documentName
1807
     * @return $this
1808
     */
1809 21 View Code Duplication
    public function updateOne($documentName = 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...
1810
    {
1811 21
        $this->setDocumentName($documentName);
1812 21
        $this->query['type'] = Query::TYPE_UPDATE;
1813 21
        $this->query['multiple'] = false;
1814
1815 21
        return $this;
1816
    }
1817
1818
    /**
1819
     * @param string $documentName
1820
     * @return $this
1821
     */
1822 3 View Code Duplication
    public function updateMany($documentName = 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...
1823
    {
1824 3
        $this->setDocumentName($documentName);
1825 3
        $this->query['type'] = Query::TYPE_UPDATE;
1826 3
        $this->query['multiple'] = true;
1827
1828 3
        return $this;
1829
    }
1830
1831
    /**
1832
     * Set the "upsert" option for an update or findAndUpdate query.
1833
     *
1834
     * @param boolean $bool
1835
     * @return $this
1836
     */
1837 7
    public function upsert($bool = true)
1838
    {
1839 7
        $this->query['upsert'] = (boolean) $bool;
1840 7
        return $this;
1841
    }
1842
1843
    /**
1844
     * Specify a JavaScript expression to use for matching documents.
1845
     *
1846
     * @see Expr::where()
1847
     * @see http://docs.mongodb.org/manual/reference/operator/where/
1848
     * @param string|\MongoCode $javascript
1849
     * @return $this
1850
     */
1851 3
    public function where($javascript)
1852
    {
1853 3
        $this->expr->where($javascript);
1854 3
        return $this;
1855
    }
1856
1857
    /**
1858
     * Add $within criteria with a $box shape to the query.
1859
     *
1860
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1861
     * @see Builder::geoWithinBox()
1862
     * @see Expr::withinBox()
1863
     * @see http://docs.mongodb.org/manual/reference/operator/box/
1864
     * @param float $x1
1865
     * @param float $y1
1866
     * @param float $x2
1867
     * @param float $y2
1868
     * @return $this
1869
     */
1870 1
    public function withinBox($x1, $y1, $x2, $y2)
1871
    {
1872 1
        $this->expr->withinBox($x1, $y1, $x2, $y2);
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\ODM\MongoDB\Query\Expr::withinBox() has been deprecated with message: 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin

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...
1873 1
        return $this;
1874
    }
1875
1876
    /**
1877
     * Add $within criteria with a $center shape to the query.
1878
     *
1879
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1880
     * @see Builder::geoWithinCenter()
1881
     * @see Expr::withinCenter()
1882
     * @see http://docs.mongodb.org/manual/reference/operator/center/
1883
     * @param float $x
1884
     * @param float $y
1885
     * @param float $radius
1886
     * @return $this
1887
     */
1888 1
    public function withinCenter($x, $y, $radius)
1889
    {
1890 1
        $this->expr->withinCenter($x, $y, $radius);
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\ODM\MongoDB\Query\Expr::withinCenter() has been deprecated with message: 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin

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...
1891 1
        return $this;
1892
    }
1893
1894
    /**
1895
     * Add $within criteria with a $centerSphere shape to the query.
1896
     *
1897
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1898
     * @see Builder::geoWithinCenterSphere()
1899
     * @see Expr::withinCenterSphere()
1900
     * @see http://docs.mongodb.org/manual/reference/operator/centerSphere/
1901
     * @param float $x
1902
     * @param float $y
1903
     * @param float $radius
1904
     * @return $this
1905
     */
1906 1
    public function withinCenterSphere($x, $y, $radius)
1907
    {
1908 1
        $this->expr->withinCenterSphere($x, $y, $radius);
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\ODM\MongoDB\Que...r::withinCenterSphere() has been deprecated with message: 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin

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...
1909 1
        return $this;
1910
    }
1911
1912
    /**
1913
     * Add $within criteria with a $polygon shape to the query.
1914
     *
1915
     * Point coordinates are in x, y order (easting, northing for projected
1916
     * coordinates, longitude, latitude for geographic coordinates).
1917
     *
1918
     * The last point coordinate is implicitly connected with the first.
1919
     *
1920
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1921
     * @see Builder::geoWithinPolygon()
1922
     * @see Expr::withinPolygon()
1923
     * @see http://docs.mongodb.org/manual/reference/operator/polygon/
1924
     * @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...
1925
     * @return $this
1926
     */
1927 1
    public function withinPolygon(/* array($x1, $y1), array($x2, $y2), ... */)
1928
    {
1929 1
        $this->expr->withinPolygon(...func_get_args());
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\ODM\MongoDB\Query\Expr::withinPolygon() has been deprecated with message: 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin

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...
1930 1
        return $this;
1931
    }
1932
1933
    /**
1934
     * Get Discriminator Values
1935
     *
1936
     * @param \Traversable $classNames
1937
     * @return array an array of discriminatorValues (mixed type)
1938
     * @throws \InvalidArgumentException if the number of found collections > 1
1939
     */
1940 2
    private function getDiscriminatorValues($classNames)
1941
    {
1942 2
        $discriminatorValues = array();
1943 2
        $collections = array();
1944 2
        foreach ($classNames as $className) {
1945 2
            $class = $this->dm->getClassMetadata($className);
1946 2
            $discriminatorValues[] = $class->discriminatorValue;
1947 2
            $key = $this->dm->getDocumentDatabase($className)->getDatabaseName() . '.' . $class->getCollection();
1948 2
            $collections[$key] = $key;
1949
        }
1950 2
        if (count($collections) > 1) {
1951 1
            throw new \InvalidArgumentException('Documents involved are not all mapped to the same database collection.');
1952
        }
1953 1
        return $discriminatorValues;
1954
    }
1955
1956
    /**
1957
     * @param string[]|string $documentName an array of document names or just one.
1958
     */
1959 290
    private function setDocumentName($documentName)
1960
    {
1961 290
        if (is_array($documentName)) {
1962 2
            $documentNames = $documentName;
1963 2
            $documentName = $documentNames[0];
1964
1965 2
            $metadata = $this->dm->getClassMetadata($documentName);
1966 2
            $discriminatorField = $metadata->discriminatorField;
1967 2
            $discriminatorValues = $this->getDiscriminatorValues($documentNames);
0 ignored issues
show
Documentation introduced by
$documentNames is of type array, but the function expects a object<Traversable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1968
1969
            // If a defaultDiscriminatorValue is set and it is among the discriminators being queries, add NULL to the list
1970 1 View Code Duplication
            if ($metadata->defaultDiscriminatorValue && array_search($metadata->defaultDiscriminatorValue, $discriminatorValues) !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1971 1
                $discriminatorValues[] = null;
1972
            }
1973
1974 1
            $this->field($discriminatorField)->in($discriminatorValues);
1975
        }
1976
1977 289
        if ($documentName !== null) {
1978 289
            $this->collection = $this->dm->getDocumentCollection($documentName);
1979 289
            $this->class = $this->dm->getClassMetadata($documentName);
1980
1981
            // Expr also needs to know
1982 289
            $this->expr->setClassMetadata($this->class);
1983
        }
1984 289
    }
1985
}
1986