Completed
Push — master ( f2e43e...df01cf )
by Maciej
14:18
created

Builder::lte()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 3
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Doctrine\ODM\MongoDB\Query;
4
5
use Doctrine\ODM\MongoDB\DocumentManager;
6
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo;
7
use GeoJson\Geometry\Geometry;
8
use GeoJson\Geometry\Point;
9
use MongoDB\Collection;
10
use MongoDB\Driver\ReadPreference;
11
12
/**
13
 * Query builder for ODM.
14
 *
15
 * @since       1.0
16
 */
17
class Builder
18
{
19
    /**
20
     * The DocumentManager instance for this query
21
     *
22
     * @var DocumentManager
23
     */
24
    private $dm;
25
26
    /**
27
     * The ClassMetadata instance.
28
     *
29
     * @var \Doctrine\ODM\MongoDB\Mapping\ClassMetadata
30
     */
31
    private $class;
32
33
    /**
34
     * The current field we are operating on.
35
     *
36
     * @todo Change this to private once ODM requires doctrine/mongodb 1.1+
37
     * @var string
38
     */
39
    protected $currentField;
40
41
    /**
42
     * Whether or not to hydrate the data to documents.
43
     *
44
     * @var boolean
45
     */
46
    private $hydrate = true;
47
48
    /**
49
     * Whether or not to refresh the data for documents that are already in the identity map.
50
     *
51
     * @var boolean
52
     */
53
    private $refresh = false;
54
55
    /**
56
     * Array of primer Closure instances.
57
     *
58
     * @var array
59
     */
60
    private $primers = array();
61
62
    /**
63
     * Whether or not to register documents in UnitOfWork.
64
     *
65
     * @var bool
66
     */
67
    private $readOnly;
68
69
    /**
70
     * The Collection instance.
71
     *
72
     * @var Collection
73
     */
74
    private $collection;
75
76
    /**
77
     * Array containing the query data.
78
     *
79
     * @var array
80
     */
81
    private $query = ['type' => Query::TYPE_FIND];
82
83
    /**
84
     * The Expr instance used for building this query.
85
     *
86
     * This object includes the query criteria and the "new object" used for
87
     * insert and update queries.
88
     *
89
     * @var Expr $expr
90
     */
91
    private $expr;
92
93
    /**
94
     * Construct a Builder
95
     *
96
     * @param DocumentManager $dm
97
     * @param string[]|string|null $documentName (optional) an array of document names, the document name, or none
98
     */
99 291
    public function __construct(DocumentManager $dm, $documentName = null)
100
    {
101 291
        $this->dm = $dm;
102 291
        $this->expr = new Expr($dm);
103 291
        if ($documentName !== null) {
104 283
            $this->setDocumentName($documentName);
105
        }
106 290
    }
107
108 1
    public function __clone()
109
    {
110 1
        $this->expr = clone $this->expr;
111 1
    }
112
113
    /**
114
     * Add one or more $and clauses to the current query.
115
     *
116
     * You can create a new expression using the {@link Builder::expr()} method.
117
     *
118
     * @see Expr::addAnd()
119
     * @see http://docs.mongodb.org/manual/reference/operator/and/
120
     * @param array|Expr $expression
121
     * @return $this
122
     */
123 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...
124
    {
125 4
        $this->expr->addAnd(...func_get_args());
126 4
        return $this;
127
    }
128
129
    /**
130
     * Append multiple values to the current array field only if they do not
131
     * already exist in the array.
132
     *
133
     * If the field does not exist, it will be set to an array containing the
134
     * unique values in the argument. If the field is not an array, the query
135
     * will yield an error.
136
     *
137
     * @deprecated 1.1 Use {@link Builder::addToSet()} with {@link Expr::each()}; Will be removed in 2.0
138
     * @see Expr::addManyToSet()
139
     * @see http://docs.mongodb.org/manual/reference/operator/addToSet/
140
     * @see http://docs.mongodb.org/manual/reference/operator/each/
141
     * @param array $values
142
     * @return $this
143
     */
144 1
    public function addManyToSet(array $values)
145
    {
146 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...
147 1
        return $this;
148
    }
149
150
    /**
151
     * Add one or more $nor clauses to the current query.
152
     *
153
     * You can create a new expression using the {@link Builder::expr()} method.
154
     *
155
     * @see Expr::addNor()
156
     * @see http://docs.mongodb.org/manual/reference/operator/nor/
157
     * @param array|Expr $expression
158
     * @return $this
159
     */
160 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...
161
    {
162 3
        $this->expr->addNor(...func_get_args());
163 3
        return $this;
164
    }
165
166
    /**
167
     * Add one or more $or clauses to the current query.
168
     *
169
     * You can create a new expression using the {@link Builder::expr()} method.
170
     *
171
     * @see Expr::addOr()
172
     * @see http://docs.mongodb.org/manual/reference/operator/or/
173
     * @param array|Expr $expression
174
     * @return $this
175
     */
176 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...
177
    {
178 6
        $this->expr->addOr(...func_get_args());
179 6
        return $this;
180
    }
181
182
    /**
183
     * Append one or more values to the current array field only if they do not
184
     * already exist in the array.
185
     *
186
     * If the field does not exist, it will be set to an array containing the
187
     * unique value(s) in the argument. If the field is not an array, the query
188
     * will yield an error.
189
     *
190
     * Multiple values may be specified by provided an Expr object and using
191
     * {@link Expr::each()}.
192
     *
193
     * @see Expr::addToSet()
194
     * @see http://docs.mongodb.org/manual/reference/operator/addToSet/
195
     * @see http://docs.mongodb.org/manual/reference/operator/each/
196
     * @param mixed|Expr $valueOrExpression
197
     * @return $this
198
     */
199 5
    public function addToSet($valueOrExpression)
200
    {
201 5
        $this->expr->addToSet($valueOrExpression);
202 5
        return $this;
203
    }
204
205
    /**
206
     * Specify $all criteria for the current field.
207
     *
208
     * @see Expr::all()
209
     * @see http://docs.mongodb.org/manual/reference/operator/all/
210
     * @param array $values
211
     * @return $this
212
     */
213 3
    public function all(array $values)
214
    {
215 3
        $this->expr->all($values);
216 3
        return $this;
217
    }
218
219
    /**
220
     * Apply a bitwise and operation on the current field.
221
     *
222
     * @see Expr::bitAnd()
223
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
224
     * @param int $value
225
     * @return $this
226
     */
227 1
    public function bitAnd($value)
228
    {
229 1
        $this->expr->bitAnd($value);
230 1
        return $this;
231
    }
232
233
    /**
234
     * Apply a bitwise or operation on the current field.
235
     *
236
     * @see Expr::bitOr()
237
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
238
     * @param int $value
239
     * @return $this
240
     */
241 1
    public function bitOr($value)
242
    {
243 1
        $this->expr->bitOr($value);
244 1
        return $this;
245
    }
246
247
    /**
248
     * Matches documents where all of the bit positions given by the query are
249
     * clear.
250
     *
251
     * @see Expr::bitsAllClear()
252
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAllClear/
253
     * @param int|array|\MongoBinData $value
254
     * @return $this
255
     */
256 1
    public function bitsAllClear($value)
257
    {
258 1
        $this->expr->bitsAllClear($value);
259 1
        return $this;
260
    }
261
262
    /**
263
     * Matches documents where all of the bit positions given by the query are
264
     * set.
265
     *
266
     * @see Expr::bitsAllSet()
267
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAllSet/
268
     * @param int|array|\MongoBinData $value
269
     * @return $this
270
     */
271 1
    public function bitsAllSet($value)
272
    {
273 1
        $this->expr->bitsAllSet($value);
274 1
        return $this;
275
    }
276
277
    /**
278
     * Matches documents where any of the bit positions given by the query are
279
     * clear.
280
     *
281
     * @see Expr::bitsAnyClear()
282
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAnyClear/
283
     * @param int|array|\MongoBinData $value
284
     * @return $this
285
     */
286 1
    public function bitsAnyClear($value)
287
    {
288 1
        $this->expr->bitsAnyClear($value);
289 1
        return $this;
290
    }
291
292
    /**
293
     * Matches documents where any of the bit positions given by the query are
294
     * set.
295
     *
296
     * @see Expr::bitsAnySet()
297
     * @see https://docs.mongodb.org/manual/reference/operator/query/bitsAnySet/
298
     * @param int|array|\MongoBinData $value
299
     * @return $this
300
     */
301 1
    public function bitsAnySet($value)
302
    {
303 1
        $this->expr->bitsAnySet($value);
304 1
        return $this;
305
    }
306
307
    /**
308
     * Apply a bitwise xor operation on the current field.
309
     *
310
     * @see Expr::bitXor()
311
     * @see http://docs.mongodb.org/manual/reference/operator/update/bit/
312
     * @param int $value
313
     * @return $this
314
     */
315 1
    public function bitXor($value)
316
    {
317 1
        $this->expr->bitXor($value);
318 1
        return $this;
319
    }
320
321
    /**
322
     * A boolean flag to enable or disable case sensitive search for $text
323
     * criteria.
324
     *
325
     * This method must be called after text().
326
     *
327
     * @see Expr::caseSensitive()
328
     * @see http://docs.mongodb.org/manual/reference/operator/text/
329
     * @param bool $caseSensitive
330
     * @return $this
331
     * @throws \BadMethodCallException if the query does not already have $text criteria
332
     *
333
     * @since 1.3
334
     */
335 1
    public function caseSensitive($caseSensitive)
336
    {
337 1
        $this->expr->caseSensitive($caseSensitive);
338 1
        return $this;
339
    }
340
341
    /**
342
     * Associates a comment to any expression taking a query predicate.
343
     *
344
     * @see Expr::comment()
345
     * @see http://docs.mongodb.org/manual/reference/operator/query/comment/
346
     * @param string $comment
347
     * @return $this
348
     */
349 1
    public function comment($comment)
350
    {
351 1
        $this->expr->comment($comment);
352 1
        return $this;
353
    }
354
355
    /**
356
     * Change the query type to count.
357
     *
358
     * @return $this
359
     */
360
    public function count()
361
    {
362
        $this->query['type'] = Query::TYPE_COUNT;
363
        return $this;
364
    }
365
366
    /**
367
     * Sets the value of the current field to the current date, either as a date or a timestamp.
368
     *
369
     * @see Expr::currentDate()
370
     * @see http://docs.mongodb.org/manual/reference/operator/currentDate/
371
     * @param string $type
372
     * @return $this
373
     */
374 3
    public function currentDate($type = 'date')
375
    {
376 3
        $this->expr->currentDate($type);
377 2
        return $this;
378
    }
379
380
    /**
381
     * Return an array of information about the Builder state for debugging.
382
     *
383
     * The $name parameter may be used to return a specific key from the
384
     * internal $query array property. If omitted, the entire array will be
385
     * returned.
386
     *
387
     * @param string $name
388
     * @return mixed
389
     */
390 28
    public function debug($name = null)
391
    {
392 28
        return $name !== null ? $this->query[$name] : $this->query;
393
    }
394
395
    /**
396
     * A boolean flag to enable or disable diacritic sensitive search for $text
397
     * criteria.
398
     *
399
     * This method must be called after text().
400
     *
401
     * @see Builder::diacriticSensitive()
402
     * @see http://docs.mongodb.org/manual/reference/operator/text/
403
     * @param bool $diacriticSensitive
404
     * @return $this
405
     * @throws \BadMethodCallException if the query does not already have $text criteria
406
     *
407
     * @since 1.3
408
     */
409 1
    public function diacriticSensitive($diacriticSensitive)
410
    {
411 1
        $this->expr->diacriticSensitive($diacriticSensitive);
412 1
        return $this;
413
    }
414
415
    /**
416
     * Change the query type to a distinct command.
417
     *
418
     * @see http://docs.mongodb.org/manual/reference/command/distinct/
419
     * @param string $field
420
     * @return $this
421
     */
422 2
    public function distinct($field)
423
    {
424 2
        $this->query['type'] = Query::TYPE_DISTINCT;
425 2
        $this->query['distinct'] = $field;
426 2
        return $this;
427
    }
428
429
    /**
430
     * Set whether the query should return its result as an EagerCursor.
431
     *
432
     * @param boolean $bool
433
     * @return $this
434
     */
435 5
    public function eagerCursor($bool = true)
436
    {
437 5
        if ( ! $bool && ! empty($this->primers)) {
438 1
            throw new \BadMethodCallException("Can't set eagerCursor to false when using reference primers");
439
        }
440
441 4
        $this->query['eagerCursor'] = (boolean) $bool;
442 4
        return $this;
443
    }
444
445
    /**
446
     * Specify $elemMatch criteria for the current field.
447
     *
448
     * You can create a new expression using the {@link Builder::expr()} method.
449
     *
450
     * @see Expr::elemMatch()
451
     * @see http://docs.mongodb.org/manual/reference/operator/elemMatch/
452
     * @param array|Expr $expression
453
     * @return $this
454
     */
455 6
    public function elemMatch($expression)
456
    {
457 6
        $this->expr->elemMatch($expression);
458 6
        return $this;
459
    }
460
461
    /**
462
     * Specify an equality match for the current field.
463
     *
464
     * @see Expr::equals()
465
     * @param mixed $value
466
     * @return $this
467
     */
468 75
    public function equals($value)
469
    {
470 75
        $this->expr->equals($value);
471 75
        return $this;
472
    }
473
474
    /**
475
     * Set one or more fields to be excluded from the query projection.
476
     *
477
     * If fields have been selected for inclusion, only the "_id" field may be
478
     * excluded.
479
     *
480
     * @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...
481
     * @return $this
482
     */
483 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...
484
    {
485 6
        if ( ! isset($this->query['select'])) {
486 6
            $this->query['select'] = [];
487
        }
488
489 6
        $fieldNames = is_array($fieldName) ? $fieldName : func_get_args();
490
491 6
        foreach ($fieldNames as $fieldName) {
492 4
            $this->query['select'][$fieldName] = 0;
493
        }
494
495 6
        return $this;
496
    }
497
498
    /**
499
     * Specify $exists criteria for the current field.
500
     *
501
     * @see Expr::exists()
502
     * @see http://docs.mongodb.org/manual/reference/operator/exists/
503
     * @param boolean $bool
504
     * @return $this
505
     */
506 5
    public function exists($bool)
507
    {
508 5
        $this->expr->exists((boolean) $bool);
509 5
        return $this;
510
    }
511
512
    /**
513
     * Create a new Expr instance that can be used as an expression with the Builder
514
     *
515
     * @return Expr $expr
516
     */
517 26
    public function expr()
518
    {
519 26
        $expr = new Expr($this->dm);
520 26
        $expr->setClassMetadata($this->class);
521
522 26
        return $expr;
523
    }
524
525
    /**
526
     * Set the current field to operate on.
527
     *
528
     * @param string $field
529
     * @return $this
530
     */
531 144
    public function field($field)
532
    {
533 144
        $this->currentField = $field;
534 144
        $this->expr->field((string) $field);
535
536 144
        return $this;
537
    }
538
539
    /**
540
     * Set the "finalize" option for a mapReduce or group command.
541
     *
542
     * @param string|\MongoCode $finalize
543
     * @return $this
544
     * @throws \BadMethodCallException if the query is not a mapReduce or group command
545
     */
546 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...
547
    {
548 2
        switch ($this->query['type']) {
549
            case Query::TYPE_MAP_REDUCE:
550 1
                $this->query['mapReduce']['options']['finalize'] = $finalize;
551 1
                break;
552
553
            case Query::TYPE_GROUP:
554
                $this->query['group']['options']['finalize'] = $finalize;
555
                break;
556
557
            default:
558 1
                throw new \BadMethodCallException('mapReduce(), map() or group() must be called before finalize()');
559
        }
560
561 1
        return $this;
562
    }
563
564
    /**
565
     * Change the query type to find and optionally set and change the class being queried.
566
     *
567
     * @param string $documentName
568
     * @return $this
569
     */
570 12
    public function find($documentName = null)
571
    {
572 12
        $this->setDocumentName($documentName);
573 12
        $this->query['type'] = Query::TYPE_FIND;
574
575 12
        return $this;
576
    }
577
578
    /**
579
     * @param string $documentName
580
     * @return $this
581
     */
582 1
    public function findAndRemove($documentName = null)
583
    {
584 1
        $this->setDocumentName($documentName);
585 1
        $this->query['type'] = Query::TYPE_FIND_AND_REMOVE;
586
587 1
        return $this;
588
    }
589
590
    /**
591
     * @param string $documentName
592
     * @return $this
593
     */
594 13
    public function findAndUpdate($documentName = null)
595
    {
596 13
        $this->setDocumentName($documentName);
597 13
        $this->query['type'] = Query::TYPE_FIND_AND_UPDATE;
598
599 13
        return $this;
600
    }
601
602
    /**
603
     * Add $geoIntersects criteria with a GeoJSON geometry to the query.
604
     *
605
     * The geometry parameter GeoJSON object or an array corresponding to the
606
     * geometry's JSON representation.
607
     *
608
     * @see Expr::geoIntersects()
609
     * @see http://docs.mongodb.org/manual/reference/operator/geoIntersects/
610
     * @param array|Geometry $geometry
611
     * @return $this
612
     */
613 1
    public function geoIntersects($geometry)
614
    {
615 1
        $this->expr->geoIntersects($geometry);
616 1
        return $this;
617
    }
618
619
    /**
620
     * Add $geoWithin 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::geoWithin()
626
     * @see http://docs.mongodb.org/manual/reference/operator/geoWithin/
627
     * @param array|Geometry $geometry
628
     * @return $this
629
     */
630 1
    public function geoWithin($geometry)
631
    {
632 1
        $this->expr->geoWithin($geometry);
633 1
        return $this;
634
    }
635
636
    /**
637
     * Add $geoWithin criteria with a $box shape to the query.
638
     *
639
     * A rectangular polygon will be constructed from a pair of coordinates
640
     * corresponding to the bottom left and top right corners.
641
     *
642
     * Note: the $box operator only supports legacy coordinate pairs and 2d
643
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
644
     *
645
     * @see Expr::geoWithinBox()
646
     * @see http://docs.mongodb.org/manual/reference/operator/box/
647
     * @param float $x1
648
     * @param float $y1
649
     * @param float $x2
650
     * @param float $y2
651
     * @return $this
652
     */
653 1
    public function geoWithinBox($x1, $y1, $x2, $y2)
654
    {
655 1
        $this->expr->geoWithinBox($x1, $y1, $x2, $y2);
656 1
        return $this;
657
    }
658
659
    /**
660
     * Add $geoWithin criteria with a $center shape to the query.
661
     *
662
     * Note: the $center operator only supports legacy coordinate pairs and 2d
663
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
664
     *
665
     * @see Expr::geoWithinCenter()
666
     * @see http://docs.mongodb.org/manual/reference/operator/center/
667
     * @param float $x
668
     * @param float $y
669
     * @param float $radius
670
     * @return $this
671
     */
672 1
    public function geoWithinCenter($x, $y, $radius)
673
    {
674 1
        $this->expr->geoWithinCenter($x, $y, $radius);
675 1
        return $this;
676
    }
677
678
    /**
679
     * Add $geoWithin criteria with a $centerSphere shape to the query.
680
     *
681
     * Note: the $centerSphere operator supports both 2d and 2dsphere indexes.
682
     *
683
     * @see Expr::geoWithinCenterSphere()
684
     * @see http://docs.mongodb.org/manual/reference/operator/centerSphere/
685
     * @param float $x
686
     * @param float $y
687
     * @param float $radius
688
     * @return $this
689
     */
690 1
    public function geoWithinCenterSphere($x, $y, $radius)
691
    {
692 1
        $this->expr->geoWithinCenterSphere($x, $y, $radius);
693 1
        return $this;
694
    }
695
696
    /**
697
     * Add $geoWithin criteria with a $polygon shape to the query.
698
     *
699
     * Point coordinates are in x, y order (easting, northing for projected
700
     * coordinates, longitude, latitude for geographic coordinates).
701
     *
702
     * The last point coordinate is implicitly connected with the first.
703
     *
704
     * Note: the $polygon operator only supports legacy coordinate pairs and 2d
705
     * indexes. This cannot be used with 2dsphere indexes and GeoJSON shapes.
706
     *
707
     * @see Expr::geoWithinPolygon()
708
     * @see http://docs.mongodb.org/manual/reference/operator/polygon/
709
     * @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...
710
     * @return $this
711
     */
712 1
    public function geoWithinPolygon(/* array($x1, $y1), ... */)
713
    {
714 1
        $this->expr->geoWithinPolygon(...func_get_args());
715 1
        return $this;
716
    }
717
718
    /**
719
     * Return the expression's "new object".
720
     *
721
     * @see Expr::getNewObj()
722
     * @return array
723
     */
724 13
    public function getNewObj()
725
    {
726 13
        return $this->expr->getNewObj();
727
    }
728
729
    /**
730
     * Gets the Query executable.
731
     *
732
     * @param array $options
733
     * @return Query $query
734
     */
735 150
    public function getQuery(array $options = array())
736
    {
737 150
        if ($this->query['type'] === Query::TYPE_MAP_REDUCE) {
738
            $this->hydrate = false;
739
        }
740
741 150
        $documentPersister = $this->dm->getUnitOfWork()->getDocumentPersister($this->class->name);
742
743 150
        $query = $this->query;
744
745 150
        $query['query'] = $this->expr->getQuery();
746 150
        $query['query'] = $documentPersister->addDiscriminatorToPreparedQuery($query['query']);
747 150
        $query['query'] = $documentPersister->addFilterToPreparedQuery($query['query']);
748
749 150
        $query['newObj'] = $this->expr->getNewObj();
750
751 150
        if (isset($query['distinct'])) {
752 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...
753
        }
754
755 150
        if ($this->class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION && ! empty($query['upsert']) &&
756 150
            (empty($query['query'][$this->class->discriminatorField]) || is_array($query['query'][$this->class->discriminatorField]))) {
757 1
            throw new \InvalidArgumentException('Upsert query that is to be performed on discriminated document does not have single ' .
758 1
                'discriminator. Either not use base class or set \'' . $this->class->discriminatorField . '\' field manually.');
759
        }
760
761 149
        if ( ! empty($query['select'])) {
762 14
            $query['select'] = $documentPersister->prepareProjection($query['select']);
763 14
            if ($this->hydrate && $this->class->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_COLLECTION
764 14
                && ! isset($query['select'][$this->class->discriminatorField])) {
765
                $includeMode = 0 < count(array_filter($query['select'], function($mode) { return $mode == 1; }));
766 2
                if ($includeMode && ! isset($query['select'][$this->class->discriminatorField])) {
767 1
                    $query['select'][$this->class->discriminatorField] = 1;
768
                }
769
            }
770
        }
771
772 149
        if (isset($query['sort'])) {
773 23
            $query['sort'] = $documentPersister->prepareSort($query['sort']);
774
        }
775
776 149
        if ($this->class->readPreference && ! array_key_exists('readPreference', $query)) {
777 1
            $query['readPreference'] = new ReadPreference($this->class->readPreference, $this->class->readPreferenceTags);
778
        }
779
780 149
        return new Query(
781 149
            $this->dm,
782 149
            $this->class,
783 149
            $this->collection,
784 149
            $query,
785 149
            $options,
786 149
            $this->hydrate,
787 149
            $this->refresh,
788 149
            $this->primers,
789 149
            $this->readOnly
790
        );
791
    }
792
793
    /**
794
     * Return the expression's query criteria.
795
     *
796
     * @see Expr::getQuery()
797
     * @return array
798
     */
799 33
    public function getQueryArray()
800
    {
801 33
        return $this->expr->getQuery();
802
    }
803
804
    /**
805
     * Get the type of this query.
806
     *
807
     * @return integer $type
808
     */
809 2
    public function getType()
810
    {
811 2
        return $this->query['type'];
812
    }
813
814
    /**
815
     * Specify $gt criteria for the current field.
816
     *
817
     * @see Expr::gt()
818
     * @see http://docs.mongodb.org/manual/reference/operator/gt/
819
     * @param mixed $value
820
     * @return $this
821
     */
822 2
    public function gt($value)
823
    {
824 2
        $this->expr->gt($value);
825 2
        return $this;
826
    }
827
828
    /**
829
     * Specify $gte criteria for the current field.
830
     *
831
     * @see Expr::gte()
832
     * @see http://docs.mongodb.org/manual/reference/operator/gte/
833
     * @param mixed $value
834
     * @return $this
835
     */
836 2
    public function gte($value)
837
    {
838 2
        $this->expr->gte($value);
839 2
        return $this;
840
    }
841
842
    /**
843
     * Set the index hint for the query.
844
     *
845
     * @param array|string $index
846
     * @return $this
847
     */
848
    public function hint($index)
849
    {
850
        $this->query['hint'] = $index;
851
        return $this;
852
    }
853
854
    /**
855
     * @param bool $bool
856
     * @return $this
857
     */
858 17
    public function hydrate($bool = true)
859
    {
860 17
        $this->hydrate = $bool;
861 17
        return $this;
862
    }
863
864
    /**
865
     * Set the immortal cursor flag.
866
     *
867
     * @param boolean $bool
868
     * @return $this
869
     */
870
    public function immortal($bool = true)
871
    {
872
        $this->query['immortal'] = (boolean) $bool;
873
        return $this;
874
    }
875
876
    /**
877
     * Specify $in criteria for the current field.
878
     *
879
     * @see Expr::in()
880
     * @see http://docs.mongodb.org/manual/reference/operator/in/
881
     * @param array $values
882
     * @return $this
883
     */
884 24
    public function in(array $values)
885
    {
886 24
        $this->expr->in($values);
887 24
        return $this;
888
    }
889
890
    /**
891
     * Increment the current field.
892
     *
893
     * If the field does not exist, it will be set to this value.
894
     *
895
     * @see Expr::inc()
896
     * @see http://docs.mongodb.org/manual/reference/operator/inc/
897
     * @param float|integer $value
898
     * @return $this
899
     */
900 6
    public function inc($value)
901
    {
902 6
        $this->expr->inc($value);
903 6
        return $this;
904
    }
905
906
    /**
907
     * @param object $document
908
     * @return $this
909
     */
910 6
    public function includesReferenceTo($document)
911
    {
912 6
        $this->expr->includesReferenceTo($document);
913 4
        return $this;
914
    }
915
916
    /**
917
     * @param string $documentName
918
     * @return $this
919
     */
920 1
    public function insert($documentName = null)
921
    {
922 1
        $this->setDocumentName($documentName);
923 1
        $this->query['type'] = Query::TYPE_INSERT;
924
925 1
        return $this;
926
    }
927
928
    /**
929
     * Set the $language option for $text criteria.
930
     *
931
     * This method must be called after text().
932
     *
933
     * @see Expr::language()
934
     * @see http://docs.mongodb.org/manual/reference/operator/text/
935
     * @param string $language
936
     * @return $this
937
     */
938 1
    public function language($language)
939
    {
940 1
        $this->expr->language($language);
941 1
        return $this;
942
    }
943
944
    /**
945
     * Set the limit for the query.
946
     *
947
     * This is only relevant for find queries and geoNear and mapReduce
948
     * commands.
949
     *
950
     * @see Query::prepareCursor()
951
     * @param integer $limit
952
     * @return $this
953
     */
954 2
    public function limit($limit)
955
    {
956 2
        $this->query['limit'] = (integer) $limit;
957 2
        return $this;
958
    }
959
960
    /**
961
     * Specify $lt criteria for the current field.
962
     *
963
     * @see Expr::lte()
964
     * @see http://docs.mongodb.org/manual/reference/operator/lte/
965
     * @param mixed $value
966
     * @return $this
967
     */
968
    public function lt($value)
969
    {
970
        $this->expr->lt($value);
971
        return $this;
972
    }
973
974
    /**
975
     * Specify $lte criteria for the current field.
976
     *
977
     * @see Expr::lte()
978
     * @see http://docs.mongodb.org/manual/reference/operator/lte/
979
     * @param mixed $value
980
     * @return $this
981
     */
982
    public function lte($value)
983
    {
984
        $this->expr->lte($value);
985
        return $this;
986
    }
987
988
    /**
989
     * Change the query type to a mapReduce command.
990
     *
991
     * The "reduce" option is not specified when calling this method; it must
992
     * be set with the {@link Builder::reduce()} method.
993
     *
994
     * The "out" option defaults to inline, like {@link Builder::mapReduce()}.
995
     *
996
     * @see http://docs.mongodb.org/manual/reference/command/mapReduce/
997
     * @param string|\MongoCode $map
998
     * @return $this
999
     */
1000 1
    public function map($map)
1001
    {
1002 1
        $this->query['type'] = Query::TYPE_MAP_REDUCE;
1003 1
        $this->query['mapReduce'] = [
1004 1
            'map' => $map,
1005
            'reduce' => null,
1006
            'out' => ['inline' => true],
1007
            'options' => [],
1008
        ];
1009 1
        return $this;
1010
    }
1011
1012
    /**
1013
     * Change the query type to a mapReduce command.
1014
     *
1015
     * @see http://docs.mongodb.org/manual/reference/command/mapReduce/
1016
     * @param string|\MongoCode $map
1017
     * @param string|\MongoCode $reduce
1018
     * @param array|string $out
1019
     * @param array $options
1020
     * @return $this
1021
     */
1022 1
    public function mapReduce($map, $reduce, $out = ['inline' => true], array $options = [])
1023
    {
1024 1
        $this->query['type'] = Query::TYPE_MAP_REDUCE;
1025 1
        $this->query['mapReduce'] = [
1026 1
            'map' => $map,
1027 1
            'reduce' => $reduce,
1028 1
            'out' => $out,
1029 1
            'options' => $options
1030
        ];
1031 1
        return $this;
1032
    }
1033
1034
    /**
1035
     * Set additional options for a mapReduce command.
1036
     *
1037
     * @param array $options
1038
     * @return $this
1039
     * @throws \BadMethodCallException if the query is not a mapReduce command
1040
     */
1041 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...
1042
    {
1043 1
        if ($this->query['type'] !== Query::TYPE_MAP_REDUCE) {
1044 1
            throw new \BadMethodCallException('This method requires a mapReduce command (call map() or mapReduce() first)');
1045
        }
1046
1047
        $this->query['mapReduce']['options'] = $options;
1048
        return $this;
1049
    }
1050
1051
    /**
1052
     * Updates the value of the field to a specified value if the specified value is greater than the current value of the field.
1053
     *
1054
     * @see Expr::max()
1055
     * @see http://docs.mongodb.org/manual/reference/operator/update/max/
1056
     * @param mixed $value
1057
     * @return $this
1058
     */
1059 1
    public function max($value)
1060
    {
1061 1
        $this->expr->max($value);
1062 1
        return $this;
1063
    }
1064
1065
    /**
1066
     * Specifies a cumulative time limit in milliseconds for processing operations on a cursor.
1067
     *
1068
     * @param int $ms
1069
     * @return $this
1070
     */
1071
    public function maxTimeMS($ms)
1072
    {
1073
        $this->query['maxTimeMS'] = $ms;
1074
        return $this;
1075
    }
1076
1077
    /**
1078
     * Updates the value of the field to a specified value if the specified value is less than the current value of the field.
1079
     *
1080
     * @see Expr::min()
1081
     * @see http://docs.mongodb.org/manual/reference/operator/update/min/
1082
     * @param mixed $value
1083
     * @return $this
1084
     */
1085 1
    public function min($value)
1086
    {
1087 1
        $this->expr->min($value);
1088 1
        return $this;
1089
    }
1090
1091
    /**
1092
     * Specify $mod criteria for the current field.
1093
     *
1094
     * @see Expr::mod()
1095
     * @see http://docs.mongodb.org/manual/reference/operator/mod/
1096
     * @param float|integer $divisor
1097
     * @param float|integer $remainder
1098
     * @return $this
1099
     */
1100 1
    public function mod($divisor, $remainder = 0)
1101
    {
1102 1
        $this->expr->mod($divisor, $remainder);
1103 1
        return $this;
1104
    }
1105
1106
    /**
1107
     * Multiply the current field.
1108
     *
1109
     * If the field does not exist, it will be set to 0.
1110
     *
1111
     * @see Expr::mul()
1112
     * @see http://docs.mongodb.org/manual/reference/operator/mul/
1113
     * @param float|integer $value
1114
     * @return $this
1115
     */
1116 1
    public function mul($value)
1117
    {
1118 1
        $this->expr->mul($value);
1119 1
        return $this;
1120
    }
1121
1122
    /**
1123
     * Set the "multiple" option for an update query.
1124
     *
1125
     * @param boolean $bool
1126
     * @return $this
1127
     *
1128
     * @deprecated Deprecated in version 1.4 - use updateOne or updateMany instead
1129
     */
1130
    public function multiple($bool = true)
1131
    {
1132
        $this->query['multiple'] = (boolean) $bool;
1133
        return $this;
1134
    }
1135
1136
    /**
1137
     * Add $near criteria to the query.
1138
     *
1139
     * A GeoJSON point may be provided as the first and only argument for
1140
     * 2dsphere queries. This single parameter may be a GeoJSON point object or
1141
     * an array corresponding to the point's JSON representation.
1142
     *
1143
     * @see Expr::near()
1144
     * @see http://docs.mongodb.org/manual/reference/operator/near/
1145
     * @param float|array|Point $x
1146
     * @param float $y
1147
     * @return $this
1148
     */
1149 1
    public function near($x, $y = null)
1150
    {
1151 1
        $this->expr->near($x, $y);
1152 1
        return $this;
1153
    }
1154
1155
    /**
1156
     * Add $nearSphere criteria to the query.
1157
     *
1158
     * A GeoJSON point may be provided as the first and only argument for
1159
     * 2dsphere queries. This single parameter may be a GeoJSON point object or
1160
     * an array corresponding to the point's JSON representation.
1161
     *
1162
     * @see Expr::nearSphere()
1163
     * @see http://docs.mongodb.org/manual/reference/operator/nearSphere/
1164
     * @param float|array|Point $x
1165
     * @param float $y
1166
     * @return $this
1167
     */
1168 1
    public function nearSphere($x, $y = null)
1169
    {
1170 1
        $this->expr->nearSphere($x, $y);
1171 1
        return $this;
1172
    }
1173
1174
    /**
1175
     * Negates an expression for the current field.
1176
     *
1177
     * You can create a new expression using the {@link Builder::expr()} method.
1178
     *
1179
     * @see Expr::not()
1180
     * @see http://docs.mongodb.org/manual/reference/operator/not/
1181
     * @param array|Expr $expression
1182
     * @return $this
1183
     */
1184 3
    public function not($expression)
1185
    {
1186 3
        $this->expr->not($expression);
1187 3
        return $this;
1188
    }
1189
1190
    /**
1191
     * Specify $ne criteria for the current field.
1192
     *
1193
     * @see Expr::notEqual()
1194
     * @see http://docs.mongodb.org/manual/reference/operator/ne/
1195
     * @param mixed $value
1196
     * @return $this
1197
     */
1198 4
    public function notEqual($value)
1199
    {
1200 4
        $this->expr->notEqual($value);
1201 4
        return $this;
1202
    }
1203
1204
    /**
1205
     * Specify $nin criteria for the current field.
1206
     *
1207
     * @see Expr::notIn()
1208
     * @see http://docs.mongodb.org/manual/reference/operator/nin/
1209
     * @param array $values
1210
     * @return $this
1211
     */
1212 4
    public function notIn(array $values)
1213
    {
1214 4
        $this->expr->notIn($values);
1215 4
        return $this;
1216
    }
1217
1218
    /**
1219
     * Set the "out" option for a mapReduce command.
1220
     *
1221
     * @param array|string $out
1222
     * @return $this
1223
     * @throws \BadMethodCallException if the query is not a mapReduce command
1224
     */
1225 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...
1226
    {
1227 1
        if ($this->query['type'] !== Query::TYPE_MAP_REDUCE) {
1228 1
            throw new \BadMethodCallException('This method requires a mapReduce command (call map() or mapReduce() first)');
1229
        }
1230
1231
        $this->query['mapReduce']['out'] = $out;
1232
        return $this;
1233
    }
1234
1235
    /**
1236
     * Remove the first element from the current array field.
1237
     *
1238
     * @see Expr::popFirst()
1239
     * @see http://docs.mongodb.org/manual/reference/operator/pop/
1240
     * @return $this
1241
     */
1242 2
    public function popFirst()
1243
    {
1244 2
        $this->expr->popFirst();
1245 2
        return $this;
1246
    }
1247
1248
    /**
1249
     * Remove the last element from the current array field.
1250
     *
1251
     * @see Expr::popLast()
1252
     * @see http://docs.mongodb.org/manual/reference/operator/pop/
1253
     * @return $this
1254
     */
1255 1
    public function popLast()
1256
    {
1257 1
        $this->expr->popLast();
1258 1
        return $this;
1259
    }
1260
1261
    /**
1262
     * Use a primer to eagerly load all references in the current field.
1263
     *
1264
     * If $primer is true or a callable is provided, referenced documents for
1265
     * this field will loaded into UnitOfWork immediately after the query is
1266
     * executed. This will avoid multiple queries due to lazy initialization of
1267
     * Proxy objects.
1268
     *
1269
     * If $primer is false, no priming will take place. That is also the default
1270
     * behavior.
1271
     *
1272
     * If a custom callable is used, its signature should conform to the default
1273
     * Closure defined in {@link ReferencePrimer::__construct()}.
1274
     *
1275
     * @param boolean|callable $primer
1276
     * @return $this
1277
     * @throws \InvalidArgumentException If $primer is not boolean or callable
1278
     */
1279 25
    public function prime($primer = true)
1280
    {
1281 25
        if ( ! is_bool($primer) && ! is_callable($primer)) {
1282 1
            throw new \InvalidArgumentException('$primer is not a boolean or callable');
1283
        }
1284
1285 24
        if ($primer === false) {
1286
            unset($this->primers[$this->currentField]);
1287
1288
            return $this;
1289
        }
1290
1291 24
        if (array_key_exists('eagerCursor', $this->query) && !$this->query['eagerCursor']) {
1292 1
            throw new \BadMethodCallException("Can't call prime() when setting eagerCursor to false");
1293
        }
1294
1295 23
        $this->primers[$this->currentField] = $primer;
1296 23
        return $this;
1297
    }
1298
1299
    /**
1300
     * Remove all elements matching the given value or expression from the
1301
     * current array field.
1302
     *
1303
     * @see Expr::pull()
1304
     * @see http://docs.mongodb.org/manual/reference/operator/pull/
1305
     * @param mixed|Expr $valueOrExpression
1306
     * @return $this
1307
     */
1308 1
    public function pull($valueOrExpression)
1309
    {
1310 1
        $this->expr->pull($valueOrExpression);
1311 1
        return $this;
1312
    }
1313
1314
    /**
1315
     * Remove all elements matching any of the given values from the current
1316
     * array field.
1317
     *
1318
     * @see Expr::pullAll()
1319
     * @see http://docs.mongodb.org/manual/reference/operator/pullAll/
1320
     * @param array $values
1321
     * @return $this
1322
     */
1323 1
    public function pullAll(array $values)
1324
    {
1325 1
        $this->expr->pullAll($values);
1326 1
        return $this;
1327
    }
1328
1329
    /**
1330
     * Append one or more values to the current array field.
1331
     *
1332
     * If the field does not exist, it will be set to an array containing the
1333
     * value(s) in the argument. If the field is not an array, the query
1334
     * will yield an error.
1335
     *
1336
     * Multiple values may be specified by providing an Expr object and using
1337
     * {@link Expr::each()}. {@link Expr::slice()} and {@link Expr::sort()} may
1338
     * also be used to limit and order array elements, respectively.
1339
     *
1340
     * @see Expr::push()
1341
     * @see http://docs.mongodb.org/manual/reference/operator/push/
1342
     * @see http://docs.mongodb.org/manual/reference/operator/each/
1343
     * @see http://docs.mongodb.org/manual/reference/operator/slice/
1344
     * @see http://docs.mongodb.org/manual/reference/operator/sort/
1345
     * @param mixed|Expr $valueOrExpression
1346
     * @return $this
1347
     */
1348 6
    public function push($valueOrExpression)
1349
    {
1350 6
        $this->expr->push($valueOrExpression);
1351 6
        return $this;
1352
    }
1353
1354
    /**
1355
     * Append multiple values to the current array field.
1356
     *
1357
     * If the field does not exist, it will be set to an array containing the
1358
     * values in the argument. If the field is not an array, the query will
1359
     * yield an error.
1360
     *
1361
     * This operator is deprecated in MongoDB 2.4. {@link Builder::push()} and
1362
     * {@link Expr::each()} should be used in its place.
1363
     *
1364
     * @see Expr::pushAll()
1365
     * @see http://docs.mongodb.org/manual/reference/operator/pushAll/
1366
     * @param array $values
1367
     * @return $this
1368
     */
1369 1
    public function pushAll(array $values)
1370
    {
1371 1
        $this->expr->pushAll($values);
1372 1
        return $this;
1373
    }
1374
1375
    /**
1376
     * Specify $gte and $lt criteria for the current field.
1377
     *
1378
     * This method is shorthand for specifying $gte criteria on the lower bound
1379
     * and $lt criteria on the upper bound. The upper bound is not inclusive.
1380
     *
1381
     * @see Expr::range()
1382
     * @param mixed $start
1383
     * @param mixed $end
1384
     * @return $this
1385
     */
1386 3
    public function range($start, $end)
1387
    {
1388 3
        $this->expr->range($start, $end);
1389 3
        return $this;
1390
    }
1391
1392
    /**
1393
     * @param bool $bool
1394
     * @return $this
1395
     */
1396 2
    public function readOnly($bool = true)
1397
    {
1398 2
        $this->readOnly = $bool;
1399 2
        return $this;
1400
    }
1401
1402
    /**
1403
     * Set the "reduce" option for a mapReduce or group command.
1404
     *
1405
     * @param string|\MongoCode $reduce
1406
     * @return $this
1407
     * @throws \BadMethodCallException if the query is not a mapReduce or group command
1408
     */
1409 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...
1410
    {
1411 2
        switch ($this->query['type']) {
1412
            case Query::TYPE_MAP_REDUCE:
1413 1
                $this->query['mapReduce']['reduce'] = $reduce;
1414 1
                break;
1415
1416
            case Query::TYPE_GROUP:
1417
                $this->query['group']['reduce'] = $reduce;
1418
                break;
1419
1420
            default:
1421 1
                throw new \BadMethodCallException('mapReduce(), map() or group() must be called before reduce()');
1422
        }
1423
1424 1
        return $this;
1425
    }
1426
1427
    /**
1428
     * @param object $document
1429
     * @return $this
1430
     */
1431 10
    public function references($document)
1432
    {
1433 10
        $this->expr->references($document);
1434 8
        return $this;
1435
    }
1436
1437
    /**
1438
     * @param bool $bool
1439
     * @return $this
1440
     */
1441 5
    public function refresh($bool = true)
1442
    {
1443 5
        $this->refresh = $bool;
1444 5
        return $this;
1445
    }
1446
1447
    /**
1448
     * @param string $documentName
1449
     * @return $this
1450
     */
1451 1
    public function remove($documentName = null)
1452
    {
1453 1
        $this->setDocumentName($documentName);
1454 1
        $this->query['type'] = Query::TYPE_REMOVE;
1455
1456 1
        return $this;
1457
    }
1458
1459
    /**
1460
     * Rename the current field.
1461
     *
1462
     * @see Expr::rename()
1463
     * @see http://docs.mongodb.org/manual/reference/operator/rename/
1464
     * @param string $name
1465
     * @return $this
1466
     */
1467
    public function rename($name)
1468
    {
1469
        $this->expr->rename($name);
1470
        return $this;
1471
    }
1472
1473
    /**
1474
     * @param bool $bool
1475
     * @return $this
1476
     */
1477 4
    public function returnNew($bool = true)
1478
    {
1479 4
        $this->refresh(true);
1480 4
        $this->query['new'] = (boolean) $bool;
1481
1482 4
        return $this;
1483
    }
1484
1485
    /**
1486
     * Set one or more fields to be included in the query projection.
1487
     *
1488
     * @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...
1489
     * @return $this
1490
     */
1491 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...
1492
    {
1493 19
        if ( ! isset($this->query['select'])) {
1494 18
            $this->query['select'] = [];
1495
        }
1496
1497 19
        $fieldNames = is_array($fieldName) ? $fieldName : func_get_args();
1498
1499 19
        foreach ($fieldNames as $fieldName) {
1500 16
            $this->query['select'][$fieldName] = 1;
1501
        }
1502
1503 19
        return $this;
1504
    }
1505
1506
    /**
1507
     * Select only matching embedded documents in an array field for the query
1508
     * projection.
1509
     *
1510
     * @see http://docs.mongodb.org/manual/reference/projection/elemMatch/
1511
     * @param string $fieldName
1512
     * @param array|Expr $expression
1513
     * @return $this
1514
     */
1515 2
    public function selectElemMatch($fieldName, $expression)
1516
    {
1517 2
        if ($expression instanceof Expr) {
1518 1
            $expression = $expression->getQuery();
1519
        }
1520 2
        $this->query['select'][$fieldName] = ['$elemMatch' => $expression];
1521 2
        return $this;
1522
    }
1523
1524
    /**
1525
     * Select a metadata field for the query projection.
1526
     *
1527
     * @see http://docs.mongodb.org/master/reference/operator/projection/meta/
1528
     * @param string $fieldName
1529
     * @param string $metaDataKeyword
1530
     * @return $this
1531
     */
1532 2
    public function selectMeta($fieldName, $metaDataKeyword)
1533
    {
1534 2
        $this->query['select'][$fieldName] = ['$meta' => $metaDataKeyword];
1535 2
        return $this;
1536
    }
1537
1538
    /**
1539
     * Select a slice of an array field for the query projection.
1540
     *
1541
     * The $countOrSkip parameter has two very different meanings, depending on
1542
     * whether or not $limit is provided. See the MongoDB documentation for more
1543
     * information.
1544
     *
1545
     * @see http://docs.mongodb.org/manual/reference/projection/slice/
1546
     * @param string $fieldName
1547
     * @param integer $countOrSkip Count parameter, or skip if limit is specified
1548
     * @param integer $limit       Limit parameter used in conjunction with skip
1549
     * @return $this
1550
     */
1551 3
    public function selectSlice($fieldName, $countOrSkip, $limit = null)
1552
    {
1553 3
        $slice = $countOrSkip;
1554 3
        if ($limit !== null) {
1555 2
            $slice = [$slice, $limit];
1556
        }
1557 3
        $this->query['select'][$fieldName] = ['$slice' => $slice];
1558 3
        return $this;
1559
    }
1560
1561
    /**
1562
     * Set the current field to a value.
1563
     *
1564
     * This is only relevant for insert, update, or findAndUpdate queries. For
1565
     * update and findAndUpdate queries, the $atomic parameter will determine
1566
     * whether or not a $set operator is used.
1567
     *
1568
     * @see Expr::set()
1569
     * @see http://docs.mongodb.org/manual/reference/operator/set/
1570
     * @param mixed $value
1571
     * @param boolean $atomic
1572
     * @return $this
1573
     */
1574 16
    public function set($value, $atomic = true)
1575
    {
1576 16
        $this->expr->set($value, $atomic && $this->query['type'] !== Query::TYPE_INSERT);
1577 16
        return $this;
1578
    }
1579
1580
    /**
1581
     * Set the expression's "new object".
1582
     *
1583
     * @see Expr::setNewObj()
1584
     * @param array $newObj
1585
     * @return $this
1586
     */
1587
    public function setNewObj(array $newObj)
1588
    {
1589
        $this->expr->setNewObj($newObj);
1590
        return $this;
1591
    }
1592
1593
    /**
1594
     * Set the current field to the value if the document is inserted in an
1595
     * upsert operation.
1596
     *
1597
     * If an update operation with upsert: true results in an insert of a
1598
     * document, then $setOnInsert assigns the specified values to the fields in
1599
     * the document. If the update operation does not result in an insert,
1600
     * $setOnInsert does nothing.
1601
     *
1602
     * @see Expr::setOnInsert()
1603
     * @see https://docs.mongodb.org/manual/reference/operator/update/setOnInsert/
1604
     * @param mixed $value
1605
     * @return $this
1606
     */
1607 2
    public function setOnInsert($value)
1608
    {
1609 2
        $this->expr->setOnInsert($value);
1610 2
        return $this;
1611
    }
1612
1613
    /**
1614
     * Set the read preference for the query.
1615
     *
1616
     * This is only relevant for read-only queries and commands.
1617
     *
1618
     * @see http://docs.mongodb.org/manual/core/read-preference/
1619
     * @param ReadPreference $readPreference
1620
     * @return $this
1621
     */
1622 6
    public function setReadPreference(ReadPreference $readPreference)
1623
    {
1624 6
        $this->query['readPreference'] = $readPreference;
1625 6
        return $this;
1626
    }
1627
1628
    /**
1629
     * Set the expression's query criteria.
1630
     *
1631
     * @see Expr::setQuery()
1632
     * @param array $query
1633
     * @return $this
1634
     */
1635 18
    public function setQueryArray(array $query)
1636
    {
1637 18
        $this->expr->setQuery($query);
1638 18
        return $this;
1639
    }
1640
1641
    /**
1642
     * Specify $size criteria for the current field.
1643
     *
1644
     * @see Expr::size()
1645
     * @see http://docs.mongodb.org/manual/reference/operator/size/
1646
     * @param integer $size
1647
     * @return $this
1648
     */
1649 1
    public function size($size)
1650
    {
1651 1
        $this->expr->size((integer) $size);
1652 1
        return $this;
1653
    }
1654
1655
    /**
1656
     * Set the skip for the query cursor.
1657
     *
1658
     * This is only relevant for find queries, or mapReduce queries that store
1659
     * results in an output collecton and return a cursor.
1660
     *
1661
     * @see Query::prepareCursor()
1662
     * @param integer $skip
1663
     * @return $this
1664
     */
1665
    public function skip($skip)
1666
    {
1667
        $this->query['skip'] = (integer) $skip;
1668
        return $this;
1669
    }
1670
1671
    /**
1672
     * Set the snapshot cursor flag.
1673
     *
1674
     * @param boolean $bool
1675
     * @return $this
1676
     */
1677
    public function snapshot($bool = true)
1678
    {
1679
        $this->query['snapshot'] = (boolean) $bool;
1680
        return $this;
1681
    }
1682
1683
    /**
1684
     * Set one or more field/order pairs on which to sort the query.
1685
     *
1686
     * If sorting by multiple fields, the first argument should be an array of
1687
     * field name (key) and order (value) pairs.
1688
     *
1689
     * @param array|string $fieldName Field name or array of field/order pairs
1690
     * @param int|string $order       Field order (if one field is specified)
1691
     * @return $this
1692
     */
1693 31
    public function sort($fieldName, $order = 1)
1694
    {
1695 31
        if ( ! isset($this->query['sort'])) {
1696 31
            $this->query['sort'] = [];
1697
        }
1698
1699 31
        $fields = is_array($fieldName) ? $fieldName : [$fieldName => $order];
1700
1701 31
        foreach ($fields as $fieldName => $order) {
1702 14
            if (is_string($order)) {
1703 9
                $order = strtolower($order) === 'asc' ? 1 : -1;
1704
            }
1705 14
            $this->query['sort'][$fieldName] = (integer) $order;
1706
        }
1707
1708 31
        return $this;
1709
    }
1710
1711
    /**
1712
     * Specify a projected metadata field on which to sort the query.
1713
     *
1714
     * Sort order is not configurable for metadata fields. Sorting by a metadata
1715
     * field requires the same field and $meta expression to exist in the
1716
     * projection document. This method will call {@link Builder::selectMeta()}
1717
     * if the field is not already set in the projection.
1718
     *
1719
     * @see http://docs.mongodb.org/master/reference/operator/projection/meta/#sort
1720
     * @param string $fieldName       Field name of the projected metadata
1721
     * @param string $metaDataKeyword
1722
     * @return $this
1723
     */
1724 2
    public function sortMeta($fieldName, $metaDataKeyword)
1725
    {
1726
        /* It's possible that the field is already projected without the $meta
1727
         * operator. We'll assume that the user knows what they're doing in that
1728
         * case and will not attempt to override the projection.
1729
         */
1730 2
        if ( ! isset($this->query['select'][$fieldName])) {
1731 1
            $this->selectMeta($fieldName, $metaDataKeyword);
1732
        }
1733
1734 2
        $this->query['sort'][$fieldName] = ['$meta' => $metaDataKeyword];
1735
1736 2
        return $this;
1737
    }
1738
1739
    /**
1740
     * Specify $text criteria for the current field.
1741
     *
1742
     * The $language option may be set with {@link Builder::language()}.
1743
     *
1744
     * @see Expr::text()
1745
     * @see http://docs.mongodb.org/master/reference/operator/query/text/
1746
     * @param string $search
1747
     * @return $this
1748
     */
1749 1
    public function text($search)
1750
    {
1751 1
        $this->expr->text($search);
1752 1
        return $this;
1753
    }
1754
1755
    /**
1756
     * Specify $type criteria for the current field.
1757
     *
1758
     * @see Expr::type()
1759
     * @see http://docs.mongodb.org/manual/reference/operator/type/
1760
     * @param integer $type
1761
     * @return $this
1762
     */
1763 2
    public function type($type)
1764
    {
1765 2
        $this->expr->type($type);
1766 2
        return $this;
1767
    }
1768
1769
    /**
1770
     * Unset the current field.
1771
     *
1772
     * The field will be removed from the document (not set to null).
1773
     *
1774
     * @see Expr::unsetField()
1775
     * @see http://docs.mongodb.org/manual/reference/operator/unset/
1776
     * @return $this
1777
     */
1778 4
    public function unsetField()
1779
    {
1780 4
        $this->expr->unsetField();
1781 4
        return $this;
1782
    }
1783
1784
    /**
1785
     * @param string $documentName
1786
     * @return $this
1787
     */
1788 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...
1789
    {
1790 21
        $this->setDocumentName($documentName);
1791 21
        $this->query['type'] = Query::TYPE_UPDATE;
1792 21
        $this->query['multiple'] = false;
1793
1794 21
        return $this;
1795
    }
1796
1797
    /**
1798
     * @param string $documentName
1799
     * @return $this
1800
     */
1801 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...
1802
    {
1803 3
        $this->setDocumentName($documentName);
1804 3
        $this->query['type'] = Query::TYPE_UPDATE;
1805 3
        $this->query['multiple'] = true;
1806
1807 3
        return $this;
1808
    }
1809
1810
    /**
1811
     * Set the "upsert" option for an update or findAndUpdate query.
1812
     *
1813
     * @param boolean $bool
1814
     * @return $this
1815
     */
1816 7
    public function upsert($bool = true)
1817
    {
1818 7
        $this->query['upsert'] = (boolean) $bool;
1819 7
        return $this;
1820
    }
1821
1822
    /**
1823
     * Specify a JavaScript expression to use for matching documents.
1824
     *
1825
     * @see Expr::where()
1826
     * @see http://docs.mongodb.org/manual/reference/operator/where/
1827
     * @param string|\MongoCode $javascript
1828
     * @return $this
1829
     */
1830 3
    public function where($javascript)
1831
    {
1832 3
        $this->expr->where($javascript);
1833 3
        return $this;
1834
    }
1835
1836
    /**
1837
     * Add $within criteria with a $box shape to the query.
1838
     *
1839
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1840
     * @see Builder::geoWithinBox()
1841
     * @see Expr::withinBox()
1842
     * @see http://docs.mongodb.org/manual/reference/operator/box/
1843
     * @param float $x1
1844
     * @param float $y1
1845
     * @param float $x2
1846
     * @param float $y2
1847
     * @return $this
1848
     */
1849 1
    public function withinBox($x1, $y1, $x2, $y2)
1850
    {
1851 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...
1852 1
        return $this;
1853
    }
1854
1855
    /**
1856
     * Add $within criteria with a $center shape to the query.
1857
     *
1858
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1859
     * @see Builder::geoWithinCenter()
1860
     * @see Expr::withinCenter()
1861
     * @see http://docs.mongodb.org/manual/reference/operator/center/
1862
     * @param float $x
1863
     * @param float $y
1864
     * @param float $radius
1865
     * @return $this
1866
     */
1867 1
    public function withinCenter($x, $y, $radius)
1868
    {
1869 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...
1870 1
        return $this;
1871
    }
1872
1873
    /**
1874
     * Add $within criteria with a $centerSphere shape to the query.
1875
     *
1876
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1877
     * @see Builder::geoWithinCenterSphere()
1878
     * @see Expr::withinCenterSphere()
1879
     * @see http://docs.mongodb.org/manual/reference/operator/centerSphere/
1880
     * @param float $x
1881
     * @param float $y
1882
     * @param float $radius
1883
     * @return $this
1884
     */
1885 1
    public function withinCenterSphere($x, $y, $radius)
1886
    {
1887 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...
1888 1
        return $this;
1889
    }
1890
1891
    /**
1892
     * Add $within criteria with a $polygon shape to the query.
1893
     *
1894
     * Point coordinates are in x, y order (easting, northing for projected
1895
     * coordinates, longitude, latitude for geographic coordinates).
1896
     *
1897
     * The last point coordinate is implicitly connected with the first.
1898
     *
1899
     * @deprecated 1.1 MongoDB 2.4 deprecated $within in favor of $geoWithin
1900
     * @see Builder::geoWithinPolygon()
1901
     * @see Expr::withinPolygon()
1902
     * @see http://docs.mongodb.org/manual/reference/operator/polygon/
1903
     * @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...
1904
     * @return $this
1905
     */
1906 1
    public function withinPolygon(/* array($x1, $y1), array($x2, $y2), ... */)
1907
    {
1908 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...
1909 1
        return $this;
1910
    }
1911
1912
    /**
1913
     * Get Discriminator Values
1914
     *
1915
     * @param \Traversable $classNames
1916
     * @return array an array of discriminatorValues (mixed type)
1917
     * @throws \InvalidArgumentException if the number of found collections > 1
1918
     */
1919 2
    private function getDiscriminatorValues($classNames)
1920
    {
1921 2
        $discriminatorValues = array();
1922 2
        $collections = array();
1923 2
        foreach ($classNames as $className) {
1924 2
            $class = $this->dm->getClassMetadata($className);
1925 2
            $discriminatorValues[] = $class->discriminatorValue;
1926 2
            $key = $this->dm->getDocumentDatabase($className)->getDatabaseName() . '.' . $class->getCollection();
1927 2
            $collections[$key] = $key;
1928
        }
1929 2
        if (count($collections) > 1) {
1930 1
            throw new \InvalidArgumentException('Documents involved are not all mapped to the same database collection.');
1931
        }
1932 1
        return $discriminatorValues;
1933
    }
1934
1935
    /**
1936
     * @param string[]|string $documentName an array of document names or just one.
1937
     */
1938 290
    private function setDocumentName($documentName)
1939
    {
1940 290
        if (is_array($documentName)) {
1941 2
            $documentNames = $documentName;
1942 2
            $documentName = $documentNames[0];
1943
1944 2
            $metadata = $this->dm->getClassMetadata($documentName);
1945 2
            $discriminatorField = $metadata->discriminatorField;
1946 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...
1947
1948
            // If a defaultDiscriminatorValue is set and it is among the discriminators being queries, add NULL to the list
1949 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...
1950 1
                $discriminatorValues[] = null;
1951
            }
1952
1953 1
            $this->field($discriminatorField)->in($discriminatorValues);
1954
        }
1955
1956 289
        if ($documentName !== null) {
1957 289
            $this->collection = $this->dm->getDocumentCollection($documentName);
1958 289
            $this->class = $this->dm->getClassMetadata($documentName);
1959
1960
            // Expr also needs to know
1961 289
            $this->expr->setClassMetadata($this->class);
1962
        }
1963 289
    }
1964
}
1965