Completed
Push — master ( a8fe50...bce26f )
by Maciej
13s
created

lib/Doctrine/ODM/MongoDB/Aggregation/Expr.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ODM\MongoDB\Aggregation;
6
7
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
8
use Doctrine\ODM\MongoDB\DocumentManager;
9
use Doctrine\ODM\MongoDB\Persisters\DocumentPersister;
10
use Doctrine\ODM\MongoDB\Types\Type;
11
use function array_map;
12
use function array_merge;
13
use function func_get_args;
14
use function is_array;
15
use function is_string;
16
use function substr;
17
18
/**
19
 * Fluent interface for building aggregation pipelines.
20
 */
21
class Expr
22
{
23
    /** @var DocumentManager */
24
    private $dm;
25
26
    /** @var ClassMetadata */
27
    private $class;
28
29
    /** @var array */
30
    private $expr = [];
31
32
    /**
33
     * The current field we are operating on.
34
     *
35
     * @var string
36
     */
37
    private $currentField;
38
39
    /** @var array */
40
    private $switchBranch;
41
42
    /**
43
     * @inheritDoc
44
     */
45 367
    public function __construct(DocumentManager $dm, ClassMetadata $class)
46
    {
47 367
        $this->dm = $dm;
48 367
        $this->class = $class;
49 367
    }
50
51
    /**
52
     * Returns the absolute value of a number.
53
     *
54
     * The <number> argument can be any valid expression as long as it resolves
55
     * to a number.
56
     *
57
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/abs/
58
     * @param mixed|self $number
59
     *
60
     */
61 3
    public function abs($number): self
62
    {
63 3
        return $this->operator('$abs', $number);
64
    }
65
66
    /**
67
     * Adds numbers together or adds numbers and a date. If one of the arguments
68
     * is a date, $add treats the other arguments as milliseconds to add to the
69
     * date.
70
     *
71
     * The arguments can be any valid expression as long as they resolve to
72
     * either all numbers or to numbers and a date.
73
     *
74
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/add/
75
     * @param mixed|self $expression1
76
     * @param mixed|self $expression2
77
     * @param mixed|self ...$expressions Additional expressions
78
     */
79 15
    public function add($expression1, $expression2, ...$expressions): self
80
    {
81 15
        return $this->operator('$add', func_get_args());
82
    }
83
84
    /**
85
     * Adds one or more $and clauses to the current expression.
86
     *
87
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/and/
88
     * @param array|self $expression
89
     * @param array|self ...$expressions
90
     */
91 1
    public function addAnd($expression, ...$expressions): self
92
    {
93 1
        if (! isset($this->expr['$and'])) {
94 1
            $this->expr['$and'] = [];
95
        }
96
97 1
        $this->expr['$and'] = array_merge($this->expr['$and'], array_map([$this, 'ensureArray'], func_get_args()));
98
99 1
        return $this;
100
    }
101
102
    /**
103
     * Adds one or more $or clause to the current expression.
104
     *
105
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/or/
106
     * @param array|self $expression
107
     * @param array|self ...$expressions
108
     */
109
    public function addOr($expression, ...$expressions): self
110
    {
111
        if (! isset($this->expr['$or'])) {
112
            $this->expr['$or'] = [];
113
        }
114
115
        $this->expr['$or'] = array_merge($this->expr['$or'], array_map([$this, 'ensureArray'], func_get_args()));
116
117
        return $this;
118
    }
119
120
    /**
121
     * Returns an array of all unique values that results from applying an
122
     * expression to each document in a group of documents that share the same
123
     * group by key. Order of the elements in the output array is unspecified.
124
     *
125
     * AddToSet is an accumulator operation only available in the group stage.
126
     *
127
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/addToSet/
128
     * @param mixed|self $expression
129
     */
130 2
    public function addToSet($expression): self
131
    {
132 2
        return $this->operator('$addToSet', $expression);
133
    }
134
135
    /**
136
     * Evaluates an array as a set and returns true if no element in the array
137
     * is false. Otherwise, returns false. An empty array returns true.
138
     *
139
     * The expression must resolve to an array.
140
     *
141
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/allElementsTrue/
142
     * @param mixed|self $expression
143
     */
144 3
    public function allElementsTrue($expression): self
145
    {
146 3
        return $this->operator('$allElementsTrue', $expression);
147
    }
148
149
    /**
150
     * Evaluates an array as a set and returns true if any of the elements are
151
     * true and false otherwise. An empty array returns false.
152
     *
153
     * The expression must resolve to an array.
154
     *
155
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/anyElementTrue/
156
     * @param array|self $expression
157
     */
158 3
    public function anyElementTrue($expression): self
159
    {
160 3
        return $this->operator('$anyElementTrue', $expression);
161
    }
162
163
    /**
164
     * Returns the element at the specified array index.
165
     *
166
     * The <array> expression can be any valid expression as long as it resolves
167
     * to an array.
168
     * The <idx> expression can be any valid expression as long as it resolves
169
     * to an integer.
170
     *
171
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/arrayElemAt/
172
     * @param mixed|self $array
173
     * @param mixed|self $index
174
     *
175
     */
176 3
    public function arrayElemAt($array, $index): self
177
    {
178 3
        return $this->operator('$arrayElemAt', [$array, $index]);
179
    }
180
181
    /**
182
     * Returns the average value of the numeric values that result from applying
183
     * a specified expression to each document in a group of documents that
184
     * share the same group by key. Ignores nun-numeric values.
185
     *
186
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/avg/
187
     * @param mixed|self $expression
188
     */
189 10
    public function avg($expression): self
190
    {
191 10
        return $this->operator('$avg', $expression);
192
    }
193
194
    /**
195
     * Adds a case statement for a branch of the $switch operator.
196
     *
197
     * Requires {@link switch()} to be called first. The argument can be any
198
     * valid expression that resolves to a boolean. If the result is not a
199
     * boolean, it is coerced to a boolean value.
200
     *
201
     * @param mixed|self $expression
202
     *
203
     */
204 6
    public function case($expression): self
205
    {
206 6
        $this->requiresSwitchStatement(static::class . '::case');
207
208 4
        $this->switchBranch = ['case' => $expression];
209
210 4
        return $this;
211
    }
212
213
    /**
214
     * Returns the smallest integer greater than or equal to the specified number.
215
     *
216
     * The <number> expression can be any valid expression as long as it
217
     * resolves to a number.
218
     *
219
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/ceil/
220
     * @param mixed|self $number
221
     *
222
     */
223 3
    public function ceil($number): self
224
    {
225 3
        return $this->operator('$ceil', $number);
226
    }
227
228
    /**
229
     * Compares two values and returns:
230
     * -1 if the first value is less than the second.
231
     * 1 if the first value is greater than the second.
232
     * 0 if the two values are equivalent.
233
     *
234
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/cmp/
235
     * @param mixed|self $expression1
236
     * @param mixed|self $expression2
237
     */
238 3
    public function cmp($expression1, $expression2): self
239
    {
240 3
        return $this->operator('$cmp', [$expression1, $expression2]);
241
    }
242
243
    /**
244
     * Concatenates strings and returns the concatenated string.
245
     *
246
     * The arguments can be any valid expression as long as they resolve to
247
     * strings. If the argument resolves to a value of null or refers to a field
248
     * that is missing, $concat returns null.
249
     *
250
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/concat/
251
     * @param mixed|self $expression1
252
     * @param mixed|self $expression2
253
     * @param mixed|self ...$expressions Additional expressions
254
     */
255 9
    public function concat($expression1, $expression2, ...$expressions): self
256
    {
257 9
        return $this->operator('$concat', func_get_args());
258
    }
259
260
    /**
261
     * Concatenates arrays to return the concatenated array.
262
     *
263
     * The <array> expressions can be any valid expression as long as they
264
     * resolve to an array.
265
     *
266
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/concatArrays/
267
     * @param mixed|self $array1
268
     * @param mixed|self $array2
269
     * @param mixed|self ...$arrays Additional expressions
270
     *
271
     */
272 6
    public function concatArrays($array1, $array2, ...$arrays): self
273
    {
274 6
        return $this->operator('$concatArrays', func_get_args());
275
    }
276
277
    /**
278
     * Evaluates a boolean expression to return one of the two specified return
279
     * expressions.
280
     *
281
     * The arguments can be any valid expression.
282
     *
283
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/cond/
284
     * @param mixed|self $if
285
     * @param mixed|self $then
286
     * @param mixed|self $else
287
     */
288 10
    public function cond($if, $then, $else): self
289
    {
290 10
        return $this->operator('$cond', ['if' => $if, 'then' => $then, 'else' => $else]);
291
    }
292
293
    /**
294
     * Converts an expression object into an array, recursing into nested items
295
     *
296
     * For expression objects, it calls getExpression on the expression object.
297
     * For arrays, it recursively calls itself for each array item. Other values
298
     * are returned directly.
299
     *
300
     * @param mixed|self $expression
301
     * @return string|array
302
     * @internal
303
     */
304 1
    public static function convertExpression($expression)
305
    {
306 1
        if (is_array($expression)) {
307
            return array_map(['static', 'convertExpression'], $expression);
308 1
        } elseif ($expression instanceof self) {
309 1
            return $expression->getExpression();
310
        }
311
312
        return $expression;
313
    }
314
315
    /**
316
     * Converts a date object to a string according to a user-specified format.
317
     *
318
     * The format string can be any string literal, containing 0 or more format
319
     * specifiers.
320
     * The date argument can be any expression as long as it resolves to a date.
321
     *
322
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/dateToString/
323
     * @param mixed|self $expression
324
     */
325 3
    public function dateToString(string $format, $expression): self
326
    {
327 3
        return $this->operator('$dateToString', ['format' => $format, 'date' => $expression]);
328
    }
329
330
    /**
331
     * Returns the day of the month for a date as a number between 1 and 31.
332
     *
333
     * The argument can be any expression as long as it resolves to a date.
334
     *
335
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/dayOfMonth/
336
     * @param mixed|self $expression
337
     */
338 7
    public function dayOfMonth($expression): self
339
    {
340 7
        return $this->operator('$dayOfMonth', $expression);
341
    }
342
343
    /**
344
     * Returns the day of the week for a date as a number between 1 (Sunday) and
345
     * 7 (Saturday).
346
     *
347
     * The argument can be any expression as long as it resolves to a date.
348
     *
349
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/dayOfWeek/
350
     * @param mixed|self $expression
351
     */
352 7
    public function dayOfWeek($expression): self
353
    {
354 7
        return $this->operator('$dayOfWeek', $expression);
355
    }
356
357
    /**
358
     * Returns the day of the year for a date as a number between 1 and 366.
359
     *
360
     * The argument can be any expression as long as it resolves to a date.
361
     *
362
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/dayOfYear/
363
     * @param mixed|self $expression
364
     */
365 3
    public function dayOfYear($expression): self
366
    {
367 3
        return $this->operator('$dayOfYear', $expression);
368
    }
369
370
    /**
371
     * Adds a default statement for the current $switch operator.
372
     *
373
     * Requires {@link switch()} to be called first. The argument can be any
374
     * valid expression.
375
     *
376
     * Note: if no default is specified and no branch evaluates to true, the
377
     * $switch operator throws an error.
378
     *
379
     * @param mixed|self $expression
380
     *
381
     */
382 4
    public function default($expression): self
383
    {
384 4
        $this->requiresSwitchStatement(static::class . '::default');
385
386 2
        if ($this->currentField) {
387
            $this->expr[$this->currentField]['$switch']['default'] = $this->ensureArray($expression);
388
        } else {
389 2
            $this->expr['$switch']['default'] = $this->ensureArray($expression);
390
        }
391
392 2
        return $this;
393
    }
394
395
    /**
396
     * Divides one number by another and returns the result. The first argument
397
     * is divided by the second argument.
398
     *
399
     * The arguments can be any valid expression as long as the resolve to numbers.
400
     *
401
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/divide/
402
     * @param mixed|self $expression1
403
     * @param mixed|self $expression2
404
     */
405 3
    public function divide($expression1, $expression2): self
406
    {
407 3
        return $this->operator('$divide', [$expression1, $expression2]);
408
    }
409
410
    /**
411
     * Compares two values and returns whether the are equivalent.
412
     *
413
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/eq/
414
     * @param mixed|self $expression1
415
     * @param mixed|self $expression2
416
     */
417 9
    public function eq($expression1, $expression2): self
418
    {
419 9
        return $this->operator('$eq', [$expression1, $expression2]);
420
    }
421
422
    /**
423
     * Raises Euler’s number to the specified exponent and returns the result.
424
     *
425
     * The <exponent> expression can be any valid expression as long as it
426
     * resolves to a number.
427
     *
428
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/exp/
429
     * @param mixed|self $exponent
430
     *
431
     */
432 3
    public function exp($exponent): self
433
    {
434 3
        return $this->operator('$exp', $exponent);
435
    }
436
437
    /**
438
     * Returns a new expression object
439
     */
440 4
    public function expr(): self
441
    {
442 4
        return new static($this->dm, $this->class);
443
    }
444
445
    /**
446
     * Allows any expression to be used as a field value.
447
     *
448
     * @see http://docs.mongodb.org/manual/meta/aggregation-quick-reference/#aggregation-expressions
449
     * @param mixed|self $value
450
     */
451 12
    public function expression($value): self
452
    {
453 12
        $this->requiresCurrentField(__METHOD__);
454 11
        $this->expr[$this->currentField] = $this->ensureArray($value);
455
456 11
        return $this;
457
    }
458
459
    /**
460
     * Set the current field for building the expression.
461
     */
462 139
    public function field(string $fieldName): self
463
    {
464 139
        $fieldName = $this->getDocumentPersister()->prepareFieldName($fieldName);
465 139
        $this->currentField = (string) $fieldName;
466
467 139
        return $this;
468
    }
469
470
    /**
471
     * Selects a subset of the array to return based on the specified condition.
472
     *
473
     * Returns an array with only those elements that match the condition. The
474
     * returned elements are in the original order.
475
     *
476
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/filter/
477
     * @param mixed|self $input
478
     * @param mixed|self $as
479
     * @param mixed|self $cond
480
     *
481
     */
482 3
    public function filter($input, $as, $cond): self
483
    {
484 3
        return $this->operator('$filter', ['input' => $input, 'as' => $as, 'cond' => $cond]);
485
    }
486
487
    /**
488
     * Returns the value that results from applying an expression to the first
489
     * document in a group of documents that share the same group by key. Only
490
     * meaningful when documents are in a defined order.
491
     *
492
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/first/
493
     * @param mixed|self $expression
494
     */
495 2
    public function first($expression): self
496
    {
497 2
        return $this->operator('$first', $expression);
498
    }
499
500
    /**
501
     * Returns the largest integer less than or equal to the specified number.
502
     *
503
     * The <number> expression can be any valid expression as long as it
504
     * resolves to a number.
505
     *
506
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/floor/
507
     * @param mixed|self $number
508
     *
509
     */
510 3
    public function floor($number): self
511
    {
512 3
        return $this->operator('$floor', $number);
513
    }
514
515 339
    public function getExpression(): array
516
    {
517 339
        return $this->expr;
518
    }
519
520
    /**
521
     * Compares two values and returns:
522
     * true when the first value is greater than the second value.
523
     * false when the first value is less than or equivalent to the second
524
     * value.
525
     *
526
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/gt/
527
     * @param mixed|self $expression1
528
     * @param mixed|self $expression2
529
     */
530 3
    public function gt($expression1, $expression2): self
531
    {
532 3
        return $this->operator('$gt', [$expression1, $expression2]);
533
    }
534
535
    /**
536
     * Compares two values and returns:
537
     * true when the first value is greater than or equivalent to the second
538
     * value.
539
     * false when the first value is less than the second value.
540
     *
541
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/gte/
542
     * @param mixed|self $expression1
543
     * @param mixed|self $expression2
544
     */
545 6
    public function gte($expression1, $expression2): self
546
    {
547 6
        return $this->operator('$gte', [$expression1, $expression2]);
548
    }
549
550
    /**
551
     * Returns the hour portion of a date as a number between 0 and 23.
552
     *
553
     * The argument can be any expression as long as it resolves to a date.
554
     *
555
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/hour/
556
     * @param mixed|self $expression
557
     */
558 3
    public function hour($expression): self
559
    {
560 3
        return $this->operator('$hour', $expression);
561
    }
562
563
    /**
564
     * Evaluates an expression and returns the value of the expression if the
565
     * expression evaluates to a non-null value. If the expression evaluates to
566
     * a null value, including instances of undefined values or missing fields,
567
     * returns the value of the replacement expression.
568
     *
569
     * The arguments can be any valid expression.
570
     *
571
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/ifNull/
572
     * @param mixed|self $expression
573
     * @param mixed|self $replacementExpression
574
     */
575 3
    public function ifNull($expression, $replacementExpression): self
576
    {
577 3
        return $this->operator('$ifNull', [$expression, $replacementExpression]);
578
    }
579
580
    /**
581
     * Returns a boolean indicating whether a specified value is in an array.
582
     *
583
     * Unlike the $in query operator, the aggregation $in operator does not
584
     * support matching by regular expressions.
585
     *
586
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/in/
587
     * @param mixed|self $expression
588
     * @param mixed|self $arrayExpression
589
     */
590 3
    public function in($expression, $arrayExpression): self
591
    {
592 3
        return $this->operator('$in', [$expression, $arrayExpression]);
593
    }
594
595
    /**
596
     * Searches an array for an occurrence of a specified value and returns the
597
     * array index (zero-based) of the first occurrence. If the value is not
598
     * found, returns -1.
599
     *
600
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/indexOfArray/
601
     * @param mixed|self $arrayExpression  Can be any valid expression as long as it resolves to an array.
602
     * @param mixed|self $searchExpression Can be any valid expression.
603
     * @param mixed|self $start            Optional. An integer, or a number that can be represented as integers (such as 2.0), that specifies the starting index position for the search. Can be any valid expression that resolves to a non-negative integral number.
604
     * @param mixed|self $end              An integer, or a number that can be represented as integers (such as 2.0), that specifies the ending index position for the search. Can be any valid expression that resolves to a non-negative integral number.
605
     */
606 12
    public function indexOfArray($arrayExpression, $searchExpression, $start = null, $end = null): self
607
    {
608 12
        $args = [$arrayExpression, $searchExpression];
609 12
        if ($start !== null) {
610 6
            $args[] = $start;
611
612 6
            if ($end !== null) {
613 3
                $args[] = $end;
614
            }
615
        }
616
617 12
        return $this->operator('$indexOfArray', $args);
618
    }
619
620
    /**
621
     * Searches a string for an occurrence of a substring and returns the UTF-8
622
     * byte index (zero-based) of the first occurrence. If the substring is not
623
     * found, returns -1.
624
     *
625
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/indexOfBytes/
626
     * @param mixed|self      $stringExpression    Can be any valid expression as long as it resolves to a string.
627
     * @param mixed|self      $substringExpression Can be any valid expression as long as it resolves to a string.
628
     * @param string|int|null $start               An integral number that specifies the starting index position for the search. Can be any valid expression that resolves to a non-negative integral number.
629
     * @param string|int|null $end                 An integral number that specifies the ending index position for the search. Can be any valid expression that resolves to a non-negative integral number.
630
     *
631
     */
632 12
    public function indexOfBytes($stringExpression, $substringExpression, $start = null, $end = null): self
633
    {
634 12
        $args = [$stringExpression, $substringExpression];
635 12
        if ($start !== null) {
636 6
            $args[] = $start;
637
638 6
            if ($end !== null) {
639 3
                $args[] = $end;
640
            }
641
        }
642
643 12
        return $this->operator('$indexOfBytes', $args);
644
    }
645
646
    /**
647
     * Searches a string for an occurrence of a substring and returns the UTF-8
648
     * code point index (zero-based) of the first occurrence. If the substring is
649
     * not found, returns -1.
650
     *
651
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/indexOfCP/
652
     * @param mixed|self      $stringExpression    Can be any valid expression as long as it resolves to a string.
653
     * @param mixed|self      $substringExpression Can be any valid expression as long as it resolves to a string.
654
     * @param string|int|null $start               An integral number that specifies the starting index position for the search. Can be any valid expression that resolves to a non-negative integral number.
655
     * @param string|int|null $end                 An integral number that specifies the ending index position for the search. Can be any valid expression that resolves to a non-negative integral number.
656
     *
657
     */
658 12
    public function indexOfCP($stringExpression, $substringExpression, $start = null, $end = null): self
659
    {
660 12
        $args = [$stringExpression, $substringExpression];
661 12
        if ($start !== null) {
662 6
            $args[] = $start;
663
664 6
            if ($end !== null) {
665 3
                $args[] = $end;
666
            }
667
        }
668
669 12
        return $this->operator('$indexOfCP', $args);
670
    }
671
672
    /**
673
     * Determines if the operand is an array. Returns a boolean.
674
     *
675
     * The <expression> can be any valid expression.
676
     *
677
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/isArray/
678
     * @param mixed|self $expression
679
     *
680
     */
681 3
    public function isArray($expression): self
682
    {
683 3
        return $this->operator('$isArray', $expression);
684
    }
685
686
    /**
687
     * Returns the weekday number in ISO 8601 format, ranging from 1 (for Monday)
688
     * to 7 (for Sunday).
689
     *
690
     * The argument can be any expression as long as it resolves to a date.
691
     *
692
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/isoDayOfWeek/
693
     * @param mixed|self $expression
694
     */
695 3
    public function isoDayOfWeek($expression): self
696
    {
697 3
        return $this->operator('$isoDayOfWeek', $expression);
698
    }
699
700
    /**
701
     * Returns the week number in ISO 8601 format, ranging from 1 to 53.
702
     *
703
     * Week numbers start at 1 with the week (Monday through Sunday) that
704
     * contains the year’s first Thursday.
705
     *
706
     * The argument can be any expression as long as it resolves to a date.
707
     *
708
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/isoWeek/
709
     * @param mixed|self $expression
710
     */
711 3
    public function isoWeek($expression): self
712
    {
713 3
        return $this->operator('$isoWeek', $expression);
714
    }
715
716
    /**
717
     * Returns the year number in ISO 8601 format.
718
     *
719
     * The year starts with the Monday of week 1 (ISO 8601) and ends with the
720
     * Sunday of the last week (ISO 8601).
721
     *
722
     * The argument can be any expression as long as it resolves to a date.
723
     *
724
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/isoWeek/
725
     * @param mixed|self $expression
726
     */
727 3
    public function isoWeekYear($expression): self
728
    {
729 3
        return $this->operator('$isoWeekYear', $expression);
730
    }
731
732
    /**
733
     * Returns the value that results from applying an expression to the last
734
     * document in a group of documents that share the same group by a field.
735
     * Only meaningful when documents are in a defined order.
736
     *
737
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/last/
738
     * @param mixed|self $expression
739
     */
740 2
    public function last($expression): self
741
    {
742 2
        return $this->operator('$last', $expression);
743
    }
744
745
    /**
746
     * Binds variables for use in the specified expression, and returns the
747
     * result of the expression.
748
     *
749
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/let/
750
     * @param mixed|self $vars Assignment block for the variables accessible in the in expression. To assign a variable, specify a string for the variable name and assign a valid expression for the value.
751
     * @param mixed|self $in   The expression to evaluate.
752
     */
753 3
    public function let($vars, $in): self
754
    {
755 3
        return $this->operator('$let', ['vars' => $vars, 'in' => $in]);
756
    }
757
758
    /**
759
     * Returns a value without parsing. Use for values that the aggregation
760
     * pipeline may interpret as an expression.
761
     *
762
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/literal/
763
     * @param mixed|self $value
764
     */
765 3
    public function literal($value): self
766
    {
767 3
        return $this->operator('$literal', $value);
768
    }
769
770
    /**
771
     * Calculates the natural logarithm ln (i.e loge) of a number and returns
772
     * the result as a double.
773
     *
774
     * The <number> expression can be any valid expression as long as it
775
     * resolves to a non-negative number.
776
     *
777
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/log/
778
     * @param mixed|self $number
779
     *
780
     */
781 3
    public function ln($number): self
782
    {
783 3
        return $this->operator('$ln', $number);
784
    }
785
786
    /**
787
     * Calculates the log of a number in the specified base and returns the
788
     * result as a double.
789
     *
790
     * The <number> expression can be any valid expression as long as it
791
     * resolves to a non-negative number.
792
     * The <base> expression can be any valid expression as long as it resolves
793
     * to a positive number greater than 1.
794
     *
795
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/log/
796
     * @param mixed|self $number
797
     * @param mixed|self $base
798
     *
799
     */
800 3
    public function log($number, $base): self
801
    {
802 3
        return $this->operator('$log', [$number, $base]);
803
    }
804
805
    /**
806
     * Calculates the log base 10 of a number and returns the result as a double.
807
     *
808
     * The <number> expression can be any valid expression as long as it
809
     * resolves to a non-negative number.
810
     *
811
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/log10/
812
     * @param mixed|self $number
813
     *
814
     */
815 3
    public function log10($number): self
816
    {
817 3
        return $this->operator('$log10', $number);
818
    }
819
820
    /**
821
     * Compares two values and returns:
822
     * true when the first value is less than the second value.
823
     * false when the first value is greater than or equivalent to the second
824
     * value.
825
     *
826
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/lt/
827
     * @param mixed|self $expression1
828
     * @param mixed|self $expression2
829
     */
830 4
    public function lt($expression1, $expression2): self
831
    {
832 4
        return $this->operator('$lt', [$expression1, $expression2]);
833
    }
834
835
    /**
836
     * Compares two values and returns:
837
     * true when the first value is less than or equivalent to the second value.
838
     * false when the first value is greater than the second value.
839
     *
840
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/lte/
841
     * @param mixed|self $expression1
842
     * @param mixed|self $expression2
843
     */
844 6
    public function lte($expression1, $expression2): self
845
    {
846 6
        return $this->operator('$lte', [$expression1, $expression2]);
847
    }
848
849
    /**
850
     * Applies an expression to each item in an array and returns an array with
851
     * the applied results.
852
     *
853
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/map/
854
     * @param mixed|self $input An expression that resolves to an array.
855
     * @param string     $as    The variable name for the items in the input array. The in expression accesses each item in the input array by this variable.
856
     * @param mixed|self $in    The expression to apply to each item in the input array. The expression accesses the item by its variable name.
857
     */
858 3
    public function map($input, $as, $in): self
859
    {
860 3
        return $this->operator('$map', ['input' => $input, 'as' => $as, 'in' => $in]);
861
    }
862
863
    /**
864
     * Returns the highest value that results from applying an expression to
865
     * each document in a group of documents that share the same group by key.
866
     *
867
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/max/
868
     * @param mixed|self $expression
869
     */
870 3
    public function max($expression): self
871
    {
872 3
        return $this->operator('$max', $expression);
873
    }
874
875
    /**
876
     * Returns the metadata associated with a document in a pipeline operations.
877
     *
878
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/meta/
879
     * @param mixed|self $metaDataKeyword
880
     */
881 3
    public function meta($metaDataKeyword): self
882
    {
883 3
        return $this->operator('$meta', $metaDataKeyword);
884
    }
885
886
    /**
887
     * Returns the millisecond portion of a date as an integer between 0 and 999.
888
     *
889
     * The argument can be any expression as long as it resolves to a date.
890
     *
891
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/millisecond/
892
     * @param mixed|self $expression
893
     */
894 3
    public function millisecond($expression): self
895
    {
896 3
        return $this->operator('$millisecond', $expression);
897
    }
898
899
    /**
900
     * Returns the lowest value that results from applying an expression to each
901
     * document in a group of documents that share the same group by key.
902
     *
903
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/min/
904
     * @param mixed|self $expression
905
     */
906 3
    public function min($expression): self
907
    {
908 3
        return $this->operator('$min', $expression);
909
    }
910
911
    /**
912
     * Returns the minute portion of a date as a number between 0 and 59.
913
     *
914
     * The argument can be any expression as long as it resolves to a date.
915
     *
916
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/minute/
917
     * @param mixed|self $expression
918
     */
919 3
    public function minute($expression): self
920
    {
921 3
        return $this->operator('$minute', $expression);
922
    }
923
924
    /**
925
     * Divides one number by another and returns the remainder. The first
926
     * argument is divided by the second argument.
927
     *
928
     * The arguments can be any valid expression as long as they resolve to numbers.
929
     *
930
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/mod/
931
     * @param mixed|self $expression1
932
     * @param mixed|self $expression2
933
     */
934 3
    public function mod($expression1, $expression2): self
935
    {
936 3
        return $this->operator('$mod', [$expression1, $expression2]);
937
    }
938
939
    /**
940
     * Returns the month of a date as a number between 1 and 12.
941
     *
942
     * The argument can be any expression as long as it resolves to a date.
943
     *
944
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/month/
945
     * @param mixed|self $expression
946
     */
947 3
    public function month($expression): self
948
    {
949 3
        return $this->operator('$month', $expression);
950
    }
951
952
    /**
953
     * Multiplies numbers together and returns the result.
954
     *
955
     * The arguments can be any valid expression as long as they resolve to numbers.
956
     *
957
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/multiply/
958
     * @param mixed|self $expression1
959
     * @param mixed|self $expression2
960
     * @param mixed|self ...$expressions Additional expressions
961
     */
962 13
    public function multiply($expression1, $expression2, ...$expressions): self
963
    {
964 13
        return $this->operator('$multiply', func_get_args());
965
    }
966
967
    /**
968
     * Compares two values and returns:
969
     * true when the values are not equivalent.
970
     * false when the values are equivalent.
971
     *
972
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/ne/
973
     * @param mixed|self $expression1
974
     * @param mixed|self $expression2
975
     */
976 4
    public function ne($expression1, $expression2): self
977
    {
978 4
        return $this->operator('$ne', [$expression1, $expression2]);
979
    }
980
981
    /**
982
     * Evaluates a boolean and returns the opposite boolean value.
983
     *
984
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/not/
985
     * @param mixed|self $expression
986
     */
987 3
    public function not($expression): self
988
    {
989 3
        return $this->operator('$not', $expression);
990
    }
991
992
    /**
993
     * Raises a number to the specified exponent and returns the result.
994
     *
995
     * The <number> expression can be any valid expression as long as it
996
     * resolves to a non-negative number.
997
     * The <exponent> expression can be any valid expression as long as it
998
     * resolves to a number.
999
     *
1000
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/pow/
1001
     * @param mixed|self $number
1002
     * @param mixed|self $exponent
1003
     *
1004
     */
1005 3
    public function pow($number, $exponent): self
1006
    {
1007 3
        return $this->operator('$pow', [$number, $exponent]);
1008
    }
1009
1010
    /**
1011
     * Returns an array of all values that result from applying an expression to
1012
     * each document in a group of documents that share the same group by key.
1013
     *
1014
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/push/
1015
     * @param mixed|self $expression
1016
     */
1017 2
    public function push($expression): self
1018
    {
1019 2
        return $this->operator('$push', $expression);
1020
    }
1021
1022
    /**
1023
     * Returns an array whose elements are a generated sequence of numbers.
1024
     *
1025
     * $range generates the sequence from the specified starting number by successively incrementing the starting number by the specified step value up to but not including the end point.
1026
     *
1027
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/range/
1028
     * @param mixed|self $start An integer that specifies the start of the sequence. Can be any valid expression that resolves to an integer.
1029
     * @param mixed|self $end   An integer that specifies the exclusive upper limit of the sequence. Can be any valid expression that resolves to an integer.
1030
     * @param mixed|self $step  Optional. An integer that specifies the increment value. Can be any valid expression that resolves to a non-zero integer. Defaults to 1.
1031
     */
1032 6
    public function range($start, $end, $step = 1): self
1033
    {
1034 6
        return $this->operator('$range', [$start, $end, $step]);
1035
    }
1036
1037
    /**
1038
     * Applies an expression to each element in an array and combines them into
1039
     * a single value.
1040
     *
1041
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/reduce/
1042
     * @param mixed|self $input        Can be any valid expression that resolves to an array.
1043
     * @param mixed|self $initialValue The initial cumulative value set before in is applied to the first element of the input array.
1044
     * @param mixed|self $in           A valid expression that $reduce applies to each element in the input array in left-to-right order. Wrap the input value with $reverseArray to yield the equivalent of applying the combining expression from right-to-left.
1045
     */
1046 3
    public function reduce($input, $initialValue, $in): self
1047
    {
1048 3
        return $this->operator('$reduce', ['input' => $input, 'initialValue' => $initialValue, 'in' => $in]);
1049
    }
1050
1051
    /**
1052
     * Accepts an array expression as an argument and returns an array with the
1053
     * elements in reverse order.
1054
     *
1055
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/reverseArray/
1056
     * @param mixed|self $expression
1057
     */
1058 3
    public function reverseArray($expression): self
1059
    {
1060 3
        return $this->operator('$reverseArray', $expression);
1061
    }
1062
1063
    /**
1064
     * Returns the second portion of a date as a number between 0 and 59, but
1065
     * can be 60 to account for leap seconds.
1066
     *
1067
     * The argument can be any expression as long as it resolves to a date.
1068
     *
1069
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/second/
1070
     * @param mixed|self $expression
1071
     */
1072 3
    public function second($expression): self
1073
    {
1074 3
        return $this->operator('$second', $expression);
1075
    }
1076
1077
    /**
1078
     * Takes two sets and returns an array containing the elements that only
1079
     * exist in the first set.
1080
     *
1081
     * The arguments can be any valid expression as long as they each resolve to an array.
1082
     *
1083
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/setDifference/
1084
     * @param mixed|self $expression1
1085
     * @param mixed|self $expression2
1086
     */
1087 3
    public function setDifference($expression1, $expression2): self
1088
    {
1089 3
        return $this->operator('$setDifference', [$expression1, $expression2]);
1090
    }
1091
1092
    /**
1093
     * Compares two or more arrays and returns true if they have the same
1094
     * distinct elements and false otherwise.
1095
     *
1096
     * The arguments can be any valid expression as long as they each resolve to an array.
1097
     *
1098
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/setEquals/
1099
     * @param mixed|self $expression1
1100
     * @param mixed|self $expression2
1101
     * @param mixed|self ...$expressions Additional sets
1102
     */
1103 6
    public function setEquals($expression1, $expression2, ...$expressions): self
1104
    {
1105 6
        return $this->operator('$setEquals', func_get_args());
1106
    }
1107
1108
    /**
1109
     * Takes two or more arrays and returns an array that contains the elements
1110
     * that appear in every input array.
1111
     *
1112
     * The arguments can be any valid expression as long as they each resolve to an array.
1113
     *
1114
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/setIntersection/
1115
     * @param mixed|self $expression1
1116
     * @param mixed|self $expression2
1117
     * @param mixed|self ...$expressions Additional sets
1118
     */
1119 6
    public function setIntersection($expression1, $expression2, ...$expressions): self
1120
    {
1121 6
        return $this->operator('$setIntersection', func_get_args());
1122
    }
1123
1124
    /**
1125
     * Takes two arrays and returns true when the first array is a subset of the
1126
     * second, including when the first array equals the second array, and false otherwise.
1127
     *
1128
     * The arguments can be any valid expression as long as they each resolve to an array.
1129
     *
1130
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/setIsSubset/
1131
     * @param mixed|self $expression1
1132
     * @param mixed|self $expression2
1133
     */
1134 3
    public function setIsSubset($expression1, $expression2): self
1135
    {
1136 3
        return $this->operator('$setIsSubset', [$expression1, $expression2]);
1137
    }
1138
1139
    /**
1140
     * Takes two or more arrays and returns an array containing the elements
1141
     * that appear in any input array.
1142
     *
1143
     * The arguments can be any valid expression as long as they each resolve to an array.
1144
     *
1145
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/setUnion/
1146
     * @param mixed|self $expression1
1147
     * @param mixed|self $expression2
1148
     * @param mixed|self ...$expressions Additional sets
1149
     */
1150 6
    public function setUnion($expression1, $expression2, ...$expressions): self
1151
    {
1152 6
        return $this->operator('$setUnion', func_get_args());
1153
    }
1154
1155
    /**
1156
     * Counts and returns the total the number of items in an array.
1157
     *
1158
     * The argument can be any expression as long as it resolves to an array.
1159
     *
1160
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/size/
1161
     * @param mixed|self $expression
1162
     */
1163 3
    public function size($expression): self
1164
    {
1165 3
        return $this->operator('$size', $expression);
1166
    }
1167
1168
    /**
1169
     * Returns a subset of an array.
1170
     *
1171
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/slice/
1172
     * @param mixed|self      $array
1173
     * @param mixed|self      $n
1174
     * @param mixed|self|null $position
1175
     *
1176
     */
1177 6
    public function slice($array, $n, $position = null): self
1178
    {
1179 6
        if ($position === null) {
1180 3
            return $this->operator('$slice', [$array, $n]);
1181
        }
1182
1183 3
        return $this->operator('$slice', [$array, $position, $n]);
1184
    }
1185
1186
    /**
1187
     * Divides a string into an array of substrings based on a delimiter.
1188
     *
1189
     * $split removes the delimiter and returns the resulting substrings as
1190
     * elements of an array. If the delimiter is not found in the string, $split
1191
     * returns the original string as the only element of an array.
1192
     *
1193
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/split/
1194
     * @param mixed|self $string    The string to be split. Can be any valid expression as long as it resolves to a string.
1195
     * @param mixed|self $delimiter The delimiter to use when splitting the string expression. Can be any valid expression as long as it resolves to a string.
1196
     *
1197
     */
1198 3
    public function split($string, $delimiter): self
1199
    {
1200 3
        return $this->operator('$split', [$string, $delimiter]);
1201
    }
1202
1203
    /**
1204
     * Calculates the square root of a positive number and returns the result as
1205
     * a double.
1206
     *
1207
     * The argument can be any valid expression as long as it resolves to a
1208
     * non-negative number.
1209
     *
1210
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/sqrt/
1211
     * @param mixed|self $expression
1212
     */
1213 3
    public function sqrt($expression): self
1214
    {
1215 3
        return $this->operator('$sqrt', $expression);
1216
    }
1217
1218
    /**
1219
     * Calculates the population standard deviation of the input values.
1220
     *
1221
     * The arguments can be any expression as long as it resolves to an array.
1222
     *
1223
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/stdDevPop/
1224
     * @param mixed|self $expression1
1225
     * @param mixed|self ...$expressions Additional samples
1226
     *
1227
     */
1228 5
    public function stdDevPop($expression1, ...$expressions): self
1229
    {
1230 5
        $expression = empty($expressions) ? $expression1 : func_get_args();
1231
1232 5
        return $this->operator('$stdDevPop', $expression);
1233
    }
1234
1235
    /**
1236
     * Calculates the sample standard deviation of the input values.
1237
     *
1238
     * The arguments can be any expression as long as it resolves to an array.
1239
     *
1240
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/stdDevSamp/
1241
     * @param mixed|self $expression1
1242
     * @param mixed|self ...$expressions Additional samples
1243
     *
1244
     */
1245 5
    public function stdDevSamp($expression1, ...$expressions): self
1246
    {
1247 5
        $expression = empty($expressions) ? $expression1 : func_get_args();
1248
1249 5
        return $this->operator('$stdDevSamp', $expression);
1250
    }
1251
1252
    /**
1253
     * Performs case-insensitive comparison of two strings. Returns
1254
     * 1 if first string is “greater than” the second string.
1255
     * 0 if the two strings are equal.
1256
     * -1 if the first string is “less than” the second string.
1257
     *
1258
     * The arguments can be any valid expression as long as they resolve to strings.
1259
     *
1260
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/strcasecmp/
1261
     * @param mixed|self $expression1
1262
     * @param mixed|self $expression2
1263
     */
1264 3
    public function strcasecmp($expression1, $expression2): self
1265
    {
1266 3
        return $this->operator('$strcasecmp', [$expression1, $expression2]);
1267
    }
1268
1269
    /**
1270
     * Returns the number of UTF-8 encoded bytes in the specified string.
1271
     *
1272
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/strLenBytes/
1273
     * @param mixed|self $string
1274
     *
1275
     */
1276 3
    public function strLenBytes($string): self
1277
    {
1278 3
        return $this->operator('$strLenBytes', $string);
1279
    }
1280
1281
    /**
1282
     * Returns the number of UTF-8 code points in the specified string.
1283
     *
1284
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/strLenCP/
1285
     * @param mixed|self $string
1286
     *
1287
     */
1288 3
    public function strLenCP($string): self
1289
    {
1290 3
        return $this->operator('$strLenCP', $string);
1291
    }
1292
1293
    /**
1294
     * Returns a substring of a string, starting at a specified index position
1295
     * and including the specified number of characters. The index is zero-based.
1296
     *
1297
     * The arguments can be any valid expression as long as long as the first argument resolves to a string, and the second and third arguments resolve to integers.
1298
     *
1299
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/substr/
1300
     * @param mixed|self $string
1301
     * @param mixed|self $start
1302
     * @param mixed|self $length
1303
     */
1304 3
    public function substr($string, $start, $length): self
1305
    {
1306 3
        return $this->operator('$substr', [$string, $start, $length]);
1307
    }
1308
1309
    /**
1310
     * Returns the substring of a string.
1311
     *
1312
     * The substring starts with the character at the specified UTF-8 byte index
1313
     * (zero-based) in the string and continues for the number of bytes
1314
     * specified.
1315
     *
1316
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/substrBytes/
1317
     * @param mixed|self $string The string from which the substring will be extracted. Can be any valid expression as long as it resolves to a string.
1318
     * @param mixed|self $start  Indicates the starting point of the substring. Can be any valid expression as long as it resolves to a non-negative integer or number that can be represented as an integer.
1319
     * @param mixed|self $count  Can be any valid expression as long as it resolves to a non-negative integer or number that can be represented as an integer.
1320
     *
1321
     */
1322 3
    public function substrBytes($string, $start, $count): self
1323
    {
1324 3
        return $this->operator('$substrBytes', [$string, $start, $count]);
1325
    }
1326
1327
    /**
1328
     * Returns the substring of a string.
1329
     *
1330
     * The substring starts with the character at the specified UTF-8 code point
1331
     * (CP) index (zero-based) in the string for the number of code points
1332
     * specified.
1333
     *
1334
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/substrBytes/
1335
     * @param mixed|self $string The string from which the substring will be extracted. Can be any valid expression as long as it resolves to a string.
1336
     * @param mixed|self $start  Indicates the starting point of the substring. Can be any valid expression as long as it resolves to a non-negative integer or number that can be represented as an integer.
1337
     * @param mixed|self $count  Can be any valid expression as long as it resolves to a non-negative integer or number that can be represented as an integer.
1338
     *
1339
     */
1340 3
    public function substrCP($string, $start, $count): self
1341
    {
1342 3
        return $this->operator('$substrCP', [$string, $start, $count]);
1343
    }
1344
1345
    /**
1346
     * Subtracts two numbers to return the difference. The second argument is
1347
     * subtracted from the first argument.
1348
     *
1349
     * The arguments can be any valid expression as long as they resolve to numbers and/or dates.
1350
     *
1351
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/subtract/
1352
     * @param mixed|self $expression1
1353
     * @param mixed|self $expression2
1354
     */
1355 3
    public function subtract($expression1, $expression2): self
1356
    {
1357 3
        return $this->operator('$subtract', [$expression1, $expression2]);
1358
    }
1359
1360
    /**
1361
     * Calculates and returns the sum of all the numeric values that result from
1362
     * applying a specified expression to each document in a group of documents
1363
     * that share the same group by key. Ignores nun-numeric values.
1364
     *
1365
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/sum/
1366
     * @param mixed|self $expression
1367
     */
1368 9
    public function sum($expression): self
1369
    {
1370 9
        return $this->operator('$sum', $expression);
1371
    }
1372
1373
    /**
1374
     * Converts a string to lowercase, returning the result.
1375
     *
1376
     * The argument can be any expression as long as it resolves to a string.
1377
     *
1378
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/toLower/
1379
     * @param mixed|self $expression
1380
     */
1381 3
    public function toLower($expression): self
1382
    {
1383 3
        return $this->operator('$toLower', $expression);
1384
    }
1385
1386
    /**
1387
     * Converts a string to uppercase, returning the result.
1388
     *
1389
     * The argument can be any expression as long as it resolves to a string.
1390
     *
1391
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/toUpper/
1392
     * @param mixed|self $expression
1393
     */
1394 3
    public function toUpper($expression): self
1395
    {
1396 3
        return $this->operator('$toUpper', $expression);
1397
    }
1398
1399
    /**
1400
     * Truncates a number to its integer.
1401
     *
1402
     * The <number> expression can be any valid expression as long as it
1403
     * resolves to a number.
1404
     *
1405
     * @see https://docs.mongodb.org/manual/reference/operator/aggregation/trunc/
1406
     * @param mixed|self $number
1407
     *
1408
     */
1409 3
    public function trunc($number): self
1410
    {
1411 3
        return $this->operator('$trunc', $number);
1412
    }
1413
1414
    /**
1415
     * Returns a string that specifies the BSON type of the argument.
1416
     *
1417
     * The argument can be any valid expression.
1418
     *
1419
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/type/
1420
     * @param mixed|self $expression
1421
     *
1422
     */
1423 3
    public function type($expression): self
1424
    {
1425 3
        return $this->operator('$type', $expression);
1426
    }
1427
1428
    /**
1429
     * Returns the week of the year for a date as a number between 0 and 53.
1430
     *
1431
     * The argument can be any expression as long as it resolves to a date.
1432
     *
1433
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/week/
1434
     * @param mixed|self $expression
1435
     */
1436 3
    public function week($expression): self
1437
    {
1438 3
        return $this->operator('$week', $expression);
1439
    }
1440
1441
    /**
1442
     * Returns the year portion of a date.
1443
     *
1444
     * The argument can be any expression as long as it resolves to a date.
1445
     *
1446
     * @see http://docs.mongodb.org/manual/reference/operator/aggregation/year/
1447
     * @param mixed|self $expression
1448
     */
1449 4
    public function year($expression): self
1450
    {
1451 4
        return $this->operator('$year', $expression);
1452
    }
1453
1454
    /**
1455
     * Transposes an array of input arrays so that the first element of the
1456
     * output array would be an array containing, the first element of the first
1457
     * input array, the first element of the second input array, etc.
1458
     *
1459
     * @see https://docs.mongodb.com/manual/reference/operator/aggregation/zip/
1460
     * @param mixed|self      $inputs           An array of expressions that resolve to arrays. The elements of these input arrays combine to form the arrays of the output array.
1461
     * @param bool|null       $useLongestLength A boolean which specifies whether the length of the longest array determines the number of arrays in the output array.
1462
     * @param mixed|self|null $defaults         An array of default element values to use if the input arrays have different lengths. You must specify useLongestLength: true along with this field, or else $zip will return an error.
1463
     */
1464 9
    public function zip($inputs, ?bool $useLongestLength = null, $defaults = null): self
1465
    {
1466 9
        $args = ['inputs' => $inputs];
1467 9
        if ($useLongestLength !== null) {
1468 6
            $args['useLongestLength'] = $useLongestLength;
1469
        }
1470 9
        if ($defaults !== null) {
1471 3
            $args['defaults'] = $defaults;
1472
        }
1473
1474 9
        return $this->operator('$zip', $args);
1475
    }
1476
1477
1478
    /**
1479
     * @param mixed|self $expression
1480
     * @return mixed
1481
     */
1482 343
    private function ensureArray($expression)
1483
    {
1484 343
        if (is_string($expression) && substr($expression, 0, 1) === '$') {
1485 341
            return '$' . $this->getDocumentPersister()->prepareFieldName(substr($expression, 1));
1486 217
        } elseif (is_array($expression)) {
1487 209
            return array_map([$this, 'ensureArray'], $expression);
1488 87
        } elseif ($expression instanceof self) {
1489 20
            return $expression->getExpression();
1490
        }
1491
1492
        // Convert PHP types to MongoDB types for everything else
1493 85
        return Type::convertPHPToDatabaseValue($expression);
1494
    }
1495
1496 343
    private function getDocumentPersister(): DocumentPersister
1497
    {
1498 343
        return $this->dm->getUnitOfWork()->getDocumentPersister($this->class->name);
0 ignored issues
show
Accessing name on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
1499
    }
1500
1501
    /**
1502
     * Defines an operator and value on the expression.
1503
     *
1504
     * If there is a current field, the operator will be set on it; otherwise,
1505
     * the operator is set at the top level of the query.
1506
     *
1507
     * @param array|self[]|self $expression
1508
     */
1509 341
    private function operator(string $operator, $expression): self
1510
    {
1511 341
        if ($this->currentField) {
1512 137
            $this->expr[$this->currentField][$operator] = $this->ensureArray($expression);
1513
        } else {
1514 212
            $this->expr[$operator] = $this->ensureArray($expression);
1515
        }
1516
1517 341
        return $this;
1518
    }
1519
1520
    /**
1521
     * Ensure that a current field has been set.
1522
     *
1523
     * @throws \LogicException If a current field has not been set.
1524
     */
1525 12
    private function requiresCurrentField(?string $method = null): void
1526
    {
1527 12
        if (! $this->currentField) {
1528 1
            throw new \LogicException(($method ?: 'This method') . ' requires you set a current field using field().');
1529
        }
1530 11
    }
1531
1532
    /**
1533
     * @throws \BadMethodCallException If there is no current switch operator.
1534
     */
1535 8
    private function requiresSwitchStatement(?string $method = null): void
1536
    {
1537 8
        $message = ($method ?: 'This method') . ' requires a valid switch statement (call switch() first).';
1538
1539 8
        if ($this->currentField) {
1540
            if (! isset($this->expr[$this->currentField]['$switch'])) {
1541
                throw new \BadMethodCallException($message);
1542
            }
1543 8
        } elseif (! isset($this->expr['$switch'])) {
1544 4
            throw new \BadMethodCallException($message);
1545
        }
1546 4
    }
1547
1548
    /**
1549
     * Evaluates a series of case expressions. When it finds an expression which
1550
     * evaluates to true, $switch executes a specified expression and breaks out
1551
     * of the control flow.
1552
     *
1553
     * To add statements, use the {@link case()}, {@link then()} and
1554
     * {@link default()} methods.
1555
     *
1556
     */
1557 4
    public function switch(): self
1558
    {
1559 4
        $this->operator('$switch', []);
1560
1561 4
        return $this;
1562
    }
1563
1564
    /**
1565
     * Adds a case statement for the current branch of the $switch operator.
1566
     *
1567
     * Requires {@link case()} to be called first. The argument can be any valid
1568
     * expression.
1569
     *
1570
     * @param mixed|self $expression
1571
     *
1572
     */
1573 6
    public function then($expression): self
1574
    {
1575 6
        if (! is_array($this->switchBranch)) {
1576 4
            throw new \BadMethodCallException(static::class . '::then requires a valid case statement (call case() first).');
1577
        }
1578
1579 4
        $this->switchBranch['then'] = $expression;
1580
1581 4
        if ($this->currentField) {
1582
            $this->expr[$this->currentField]['$switch']['branches'][] = $this->ensureArray($this->switchBranch);
1583
        } else {
1584 4
            $this->expr['$switch']['branches'][] = $this->ensureArray($this->switchBranch);
1585
        }
1586
1587 4
        $this->switchBranch = null;
1588
1589 4
        return $this;
1590
    }
1591
}
1592