Completed
Push — 2.0 ( 14462a...d6e995 )
by Peter
06:29 queued 10s
created

Spec   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 676
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 57

Importance

Changes 0
Metric Value
wmc 59
lcom 0
cbo 57
dl 0
loc 676
rs 4.0039
c 0
b 0
f 0

59 Methods

Rating   Name   Duplication   Size   Complexity  
A join() 0 4 1
A leftJoin() 0 4 1
A innerJoin() 0 4 1
A indexBy() 0 4 1
A limit() 0 4 1
A offset() 0 4 1
A slice() 0 4 1
A orderBy() 0 4 1
A groupBy() 0 4 1
A not() 0 4 1
A add() 0 4 1
A sub() 0 4 1
A mul() 0 4 1
A div() 0 4 1
A field() 0 4 1
A value() 0 4 1
A values() 0 4 1
A likePattern() 0 4 1
A __callStatic() 0 4 1
A andX() 0 4 1
A orX() 0 4 1
A distinct() 0 4 1
A select() 0 4 1
A addSelect() 0 4 1
A selectNew() 0 4 1
A selectEntity() 0 4 1
A selectAs() 0 4 1
A selectHiddenAs() 0 4 1
A asArray() 0 4 1
A asSingleScalar() 0 4 1
A asScalar() 0 4 1
A cache() 0 4 1
A roundDateTimeParams() 0 4 1
A isNull() 0 4 1
A isNotNull() 0 4 1
A isEmpty() 0 4 1
A in() 0 4 1
A notIn() 0 4 1
A eq() 0 4 1
A neq() 0 4 1
A lt() 0 4 1
A lte() 0 4 1
A gt() 0 4 1
A gte() 0 4 1
A like() 0 4 1
A instanceOfX() 0 4 1
A memberOfX() 0 4 1
A countOf() 0 4 1
A having() 0 4 1
A COUNT() 0 4 1
A AVG() 0 4 1
A MIN() 0 4 1
A MAX() 0 4 1
A SUM() 0 4 1
A DATE_ADD() 0 4 1
A DATE_SUB() 0 4 1
A TRIM() 0 4 1
A fun() 0 4 1
A alias() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Spec often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Spec, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * This file is part of the Happyr Doctrine Specification package.
6
 *
7
 * (c) Tobias Nyholm <[email protected]>
8
 *     Kacper Gunia <[email protected]>
9
 *     Peter Gribanov <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Happyr\DoctrineSpecification;
16
17
use Happyr\DoctrineSpecification\Filter\Equals;
18
use Happyr\DoctrineSpecification\Filter\Filter;
19
use Happyr\DoctrineSpecification\Filter\GreaterOrEqualThan;
20
use Happyr\DoctrineSpecification\Filter\GreaterThan;
21
use Happyr\DoctrineSpecification\Filter\In;
22
use Happyr\DoctrineSpecification\Filter\InstanceOfX;
23
use Happyr\DoctrineSpecification\Filter\IsEmpty;
24
use Happyr\DoctrineSpecification\Filter\IsNotNull;
25
use Happyr\DoctrineSpecification\Filter\IsNull;
26
use Happyr\DoctrineSpecification\Filter\LessOrEqualThan;
27
use Happyr\DoctrineSpecification\Filter\LessThan;
28
use Happyr\DoctrineSpecification\Filter\Like;
29
use Happyr\DoctrineSpecification\Filter\MemberOfX;
30
use Happyr\DoctrineSpecification\Filter\NotEquals;
31
use Happyr\DoctrineSpecification\Logic\AndX;
32
use Happyr\DoctrineSpecification\Logic\Not;
33
use Happyr\DoctrineSpecification\Logic\OrX;
34
use Happyr\DoctrineSpecification\Operand\Addition;
35
use Happyr\DoctrineSpecification\Operand\Alias;
36
use Happyr\DoctrineSpecification\Operand\Division;
37
use Happyr\DoctrineSpecification\Operand\Field;
38
use Happyr\DoctrineSpecification\Operand\LikePattern;
39
use Happyr\DoctrineSpecification\Operand\Multiplication;
40
use Happyr\DoctrineSpecification\Operand\Operand;
41
use Happyr\DoctrineSpecification\Operand\PlatformFunction;
42
use Happyr\DoctrineSpecification\Operand\PlatformFunction\Avg;
43
use Happyr\DoctrineSpecification\Operand\PlatformFunction\Count;
44
use Happyr\DoctrineSpecification\Operand\PlatformFunction\DateAdd;
45
use Happyr\DoctrineSpecification\Operand\PlatformFunction\DateSub;
46
use Happyr\DoctrineSpecification\Operand\PlatformFunction\Max;
47
use Happyr\DoctrineSpecification\Operand\PlatformFunction\Min;
48
use Happyr\DoctrineSpecification\Operand\PlatformFunction\Sum;
49
use Happyr\DoctrineSpecification\Operand\PlatformFunction\Trim;
50
use Happyr\DoctrineSpecification\Operand\Subtraction;
51
use Happyr\DoctrineSpecification\Operand\Value;
52
use Happyr\DoctrineSpecification\Operand\Values;
53
use Happyr\DoctrineSpecification\Query\AddSelect;
54
use Happyr\DoctrineSpecification\Query\Distinct;
55
use Happyr\DoctrineSpecification\Query\GroupBy;
56
use Happyr\DoctrineSpecification\Query\Having;
57
use Happyr\DoctrineSpecification\Query\IndexBy;
58
use Happyr\DoctrineSpecification\Query\InnerJoin;
59
use Happyr\DoctrineSpecification\Query\Join;
60
use Happyr\DoctrineSpecification\Query\LeftJoin;
61
use Happyr\DoctrineSpecification\Query\Limit;
62
use Happyr\DoctrineSpecification\Query\Offset;
63
use Happyr\DoctrineSpecification\Query\OrderBy;
64
use Happyr\DoctrineSpecification\Query\QueryModifier;
65
use Happyr\DoctrineSpecification\Query\Select;
66
use Happyr\DoctrineSpecification\Query\Selection\SelectAs;
67
use Happyr\DoctrineSpecification\Query\Selection\SelectEntity;
68
use Happyr\DoctrineSpecification\Query\Selection\SelectHiddenAs;
69
use Happyr\DoctrineSpecification\Query\Selection\Selection;
70
use Happyr\DoctrineSpecification\Query\SelectNew;
71
use Happyr\DoctrineSpecification\Query\Slice;
72
use Happyr\DoctrineSpecification\Result\AsArray;
73
use Happyr\DoctrineSpecification\Result\AsScalar;
74
use Happyr\DoctrineSpecification\Result\AsSingleScalar;
75
use Happyr\DoctrineSpecification\Result\Cache;
76
use Happyr\DoctrineSpecification\Result\RoundDateTime;
77
use Happyr\DoctrineSpecification\Specification\CountOf;
78
79
/**
80
 * Factory class for the specifications.
81
 *
82
 * @method static PlatformFunction CONCAT($str1, ...$str2)
83
 * @method static PlatformFunction SUBSTRING($str, $start, $length = null) Return substring of given string.
84
 * @method static PlatformFunction LOWER($str) Returns the string lowercased.
85
 * @method static PlatformFunction UPPER($str) Return the upper-case of the given string.
86
 * @method static PlatformFunction IDENTITY($expression, $fieldMapping = null) Retrieve the foreign key column of association of the owning side
87
 * @method static PlatformFunction LENGTH($str) Returns the length of the given string
88
 * @method static PlatformFunction LOCATE($needle, $haystack, $offset = 0) Locate the first occurrence of the substring in the string.
89
 * @method static PlatformFunction ABS($expression)
90
 * @method static PlatformFunction SQRT($q) Return the square-root of q.
91
 * @method static PlatformFunction MOD($a, $b) Return a MOD b.
92
 * @method static PlatformFunction SIZE($collection) Return the number of elements in the specified collection
93
 * @method static PlatformFunction DATE_DIFF($date1, $date2) Calculate the difference in days between date1-date2.
94
 * @method static PlatformFunction BIT_AND($a, $b)
95
 * @method static PlatformFunction BIT_OR($a, $b)
96
 * @method static PlatformFunction CURRENT_DATE() Return the current date
97
 * @method static PlatformFunction CURRENT_TIME() Returns the current time
98
 * @method static PlatformFunction CURRENT_TIMESTAMP() Returns a timestamp of the current date and time.
99
 */
100
class Spec
101
{
102
    /**
103
     * @param string  $functionName
104
     * @param mixed[] $arguments
105
     *
106
     * @return PlatformFunction
107
     */
108
    public static function __callStatic(string $functionName, array $arguments = []): PlatformFunction
109
    {
110
        return self::fun($functionName, ...$arguments);
111
    }
112
113
    // Logic
114
115
    /**
116
     * @param Filter|QueryModifier ...$specs
117
     *
118
     * @return AndX
119
     */
120
    public static function andX(...$specs): AndX
121
    {
122
        return new AndX(...$specs);
123
    }
124
125
    /**
126
     * @param Filter|QueryModifier ...$specs
127
     *
128
     * @return OrX
129
     */
130
    public static function orX(...$specs): OrX
131
    {
132
        return new OrX(...$specs);
133
    }
134
135
    /**
136
     * @param Filter $spec
137
     *
138
     * @return Not
139
     */
140
    public static function not(Filter $spec): Not
141
    {
142
        return new Not($spec);
143
    }
144
145
    // Query modifier
146
147
    /**
148
     * @param string      $field
149
     * @param string      $newAlias
150
     * @param string|null $context
151
     *
152
     * @return Join
153
     */
154
    public static function join(string $field, string $newAlias, ?string $context = null): Join
155
    {
156
        return new Join($field, $newAlias, $context);
157
    }
158
159
    /**
160
     * @param string      $field
161
     * @param string      $newAlias
162
     * @param string|null $context
163
     *
164
     * @return LeftJoin
165
     */
166
    public static function leftJoin(string $field, string $newAlias, ?string $context = null): LeftJoin
167
    {
168
        return new LeftJoin($field, $newAlias, $context);
169
    }
170
171
    /**
172
     * @param string      $field
173
     * @param string      $newAlias
174
     * @param string|null $context
175
     *
176
     * @return InnerJoin
177
     */
178
    public static function innerJoin(string $field, string $newAlias, ?string $context = null): InnerJoin
179
    {
180
        return new InnerJoin($field, $newAlias, $context);
181
    }
182
183
    /**
184
     * @param Field|string $field
185
     * @param string|null  $context
186
     *
187
     * @return IndexBy
188
     */
189
    public static function indexBy($field, ?string $context = null): IndexBy
190
    {
191
        return new IndexBy($field, $context);
192
    }
193
194
    /**
195
     * @param int $count
196
     *
197
     * @return Limit
198
     */
199
    public static function limit(int $count): Limit
200
    {
201
        return new Limit($count);
202
    }
203
204
    /**
205
     * @param int $count
206
     *
207
     * @return Offset
208
     */
209
    public static function offset(int $count): Offset
210
    {
211
        return new Offset($count);
212
    }
213
214
    /**
215
     * @param int $sliceSize
216
     * @param int $sliceNumber
217
     *
218
     * @return Slice
219
     */
220
    public static function slice(int $sliceSize, int $sliceNumber = 0): Slice
221
    {
222
        return new Slice($sliceSize, $sliceNumber);
223
    }
224
225
    /**
226
     * @param Field|Alias|string $field
227
     * @param string             $order
228
     * @param string|null        $context
229
     *
230
     * @return OrderBy
231
     */
232
    public static function orderBy($field, string $order = 'ASC', ?string $context = null): OrderBy
233
    {
234
        return new OrderBy($field, $order, $context);
235
    }
236
237
    /**
238
     * @param Field|Alias|string $field
239
     * @param string|null        $context
240
     *
241
     * @return GroupBy
242
     */
243
    public static function groupBy($field, ?string $context = null): GroupBy
244
    {
245
        return new GroupBy($field, $context);
246
    }
247
248
    /**
249
     * @return Distinct
250
     */
251
    public static function distinct(): Distinct
252
    {
253
        return new Distinct();
254
    }
255
256
    // Selection
257
258
    /**
259
     * @param Selection|string ...$fields
260
     *
261
     * @return Select
262
     */
263
    public static function select(...$fields): Select
264
    {
265
        return new Select(...$fields);
266
    }
267
268
    /**
269
     * @param Selection|string ...$fields
270
     *
271
     * @return AddSelect
272
     */
273
    public static function addSelect(...$fields): AddSelect
274
    {
275
        return new AddSelect(...$fields);
276
    }
277
278
    /**
279
     * @param string        $class
280
     * @param Operand|mixed ...$arguments
281
     *
282
     * @phpstan-param class-string $class
283
     *
284
     * @return SelectNew
285
     */
286
    public static function selectNew(string $class, ...$arguments): SelectNew
287
    {
288
        return new SelectNew($class, ...$arguments);
289
    }
290
291
    /**
292
     * @param string $dqlAliasInContext
293
     *
294
     * @return SelectEntity
295
     */
296
    public static function selectEntity(string $dqlAliasInContext): SelectEntity
297
    {
298
        return new SelectEntity($dqlAliasInContext);
299
    }
300
301
    /**
302
     * @param Filter|Operand|string $expression
303
     * @param string                $newAlias
304
     *
305
     * @return SelectAs
306
     */
307
    public static function selectAs($expression, string $newAlias): SelectAs
308
    {
309
        return new SelectAs($expression, $newAlias);
310
    }
311
312
    /**
313
     * @param Filter|Operand|string $expression
314
     * @param string                $newAlias
315
     *
316
     * @return SelectHiddenAs
317
     */
318
    public static function selectHiddenAs($expression, string $newAlias): SelectHiddenAs
319
    {
320
        return new SelectHiddenAs($expression, $newAlias);
321
    }
322
323
    // Result modifier
324
325
    /**
326
     * @return AsArray
327
     */
328
    public static function asArray(): AsArray
329
    {
330
        return new AsArray();
331
    }
332
333
    /**
334
     * @return AsSingleScalar
335
     */
336
    public static function asSingleScalar(): AsSingleScalar
337
    {
338
        return new AsSingleScalar();
339
    }
340
341
    /**
342
     * @return AsScalar
343
     */
344
    public static function asScalar(): AsScalar
345
    {
346
        return new AsScalar();
347
    }
348
349
    /**
350
     * @param int $cacheLifetime How many seconds the cached entry is valid
351
     *
352
     * @return Cache
353
     */
354
    public static function cache(int $cacheLifetime): Cache
355
    {
356
        return new Cache($cacheLifetime);
357
    }
358
359
    /**
360
     * @param int $roundSeconds How may seconds to round time
361
     *
362
     * @return RoundDateTime
363
     */
364
    public static function roundDateTimeParams(int $roundSeconds): RoundDateTime
365
    {
366
        return new RoundDateTime($roundSeconds);
367
    }
368
369
    // Filters
370
371
    /**
372
     * @param Operand|string $field
373
     * @param string|null    $context
374
     *
375
     * @return IsNull
376
     */
377
    public static function isNull($field, ?string $context = null): IsNull
378
    {
379
        return new IsNull($field, $context);
380
    }
381
382
    /**
383
     * @param Operand|string $field
384
     * @param string|null    $context
385
     *
386
     * @return IsNotNull
387
     */
388
    public static function isNotNull($field, ?string $context = null): IsNotNull
389
    {
390
        return new IsNotNull($field, $context);
391
    }
392
393
    /**
394
     * @param Operand|string $field
395
     * @param string|null    $context
396
     *
397
     * @return IsEmpty
398
     */
399
    public static function isEmpty($field, ?string $context = null): IsEmpty
400
    {
401
        return new IsEmpty($field, $context);
402
    }
403
404
    /**
405
     * Make sure the $field has a value equals to $value.
406
     *
407
     * @param Operand|string $field
408
     * @param Operand|mixed  $value
409
     * @param string|null    $context
410
     *
411
     * @return In
412
     */
413
    public static function in($field, $value, ?string $context = null): In
414
    {
415
        return new In($field, $value, $context);
416
    }
417
418
    /**
419
     * @param Operand|string $field
420
     * @param Operand|mixed  $value
421
     * @param string|null    $context
422
     *
423
     * @return Not
424
     */
425
    public static function notIn($field, $value, ?string $context = null): Not
426
    {
427
        return new Not(new In($field, $value, $context));
428
    }
429
430
    /**
431
     * @param Operand|string $field
432
     * @param Operand|mixed  $value
433
     * @param string|null    $context
434
     *
435
     * @return Equals
436
     */
437
    public static function eq($field, $value, ?string $context = null): Equals
438
    {
439
        return new Equals($field, $value, $context);
440
    }
441
442
    /**
443
     * @param Operand|string $field
444
     * @param Operand|mixed  $value
445
     * @param string|null    $context
446
     *
447
     * @return NotEquals
448
     */
449
    public static function neq($field, $value, ?string $context = null): NotEquals
450
    {
451
        return new NotEquals($field, $value, $context);
452
    }
453
454
    /**
455
     * @param Operand|string $field
456
     * @param Operand|mixed  $value
457
     * @param string|null    $context
458
     *
459
     * @return LessThan
460
     */
461
    public static function lt($field, $value, ?string $context = null): LessThan
462
    {
463
        return new LessThan($field, $value, $context);
464
    }
465
466
    /**
467
     * @param Operand|string $field
468
     * @param Operand|mixed  $value
469
     * @param string|null    $context
470
     *
471
     * @return LessOrEqualThan
472
     */
473
    public static function lte($field, $value, ?string $context = null): LessOrEqualThan
474
    {
475
        return new LessOrEqualThan($field, $value, $context);
476
    }
477
478
    /**
479
     * @param Operand|string $field
480
     * @param Operand|mixed  $value
481
     * @param string|null    $context
482
     *
483
     * @return GreaterThan
484
     */
485
    public static function gt($field, $value, ?string $context = null): GreaterThan
486
    {
487
        return new GreaterThan($field, $value, $context);
488
    }
489
490
    /**
491
     * @param Operand|string $field
492
     * @param Operand|mixed  $value
493
     * @param string|null    $context
494
     *
495
     * @return GreaterOrEqualThan
496
     */
497
    public static function gte($field, $value, ?string $context = null): GreaterOrEqualThan
498
    {
499
        return new GreaterOrEqualThan($field, $value, $context);
500
    }
501
502
    /**
503
     * @param Operand|string     $field
504
     * @param LikePattern|string $value
505
     * @param string             $format
506
     * @param string|null        $context
507
     *
508
     * @return Like
509
     */
510
    public static function like($field, $value, string $format = Like::CONTAINS, ?string $context = null): Like
511
    {
512
        return new Like($field, $value, $format, $context);
513
    }
514
515
    /**
516
     * @param string      $value
517
     * @param string|null $context
518
     *
519
     * @return InstanceOfX
520
     */
521
    public static function instanceOfX($value, ?string $context = null): InstanceOfX
522
    {
523
        return new InstanceOfX($value, $context);
524
    }
525
526
    /**
527
     * @param Operand|mixed  $value
528
     * @param Operand|string $field
529
     * @param string|null    $context
530
     *
531
     * @return MemberOfX
532
     */
533
    public static function memberOfX($value, $field, ?string $context = null): MemberOfX
534
    {
535
        return new MemberOfX($value, $field, $context);
536
    }
537
538
    // Specifications
539
540
    /**
541
     * @param Filter|QueryModifier $spec
542
     *
543
     * @return CountOf
544
     */
545
    public static function countOf($spec): CountOf
546
    {
547
        return new CountOf($spec);
548
    }
549
550
    /**
551
     * @param Filter $spec
552
     *
553
     * @return Having
554
     */
555
    public static function having(Filter $spec): Having
556
    {
557
        return new Having($spec);
558
    }
559
560
    // Operands
561
562
    /**
563
     * @param string      $fieldName
564
     * @param string|null $context
565
     *
566
     * @return Field
567
     */
568
    public static function field(string $fieldName, ?string $context = null): Field
569
    {
570
        return new Field($fieldName, $context);
571
    }
572
573
    /**
574
     * @param mixed           $value
575
     * @param int|string|null $valueType
576
     *
577
     * @return Value
578
     */
579
    public static function value($value, $valueType = null): Value
580
    {
581
        return new Value($value, $valueType);
582
    }
583
584
    /**
585
     * @param mixed[]         $values
586
     * @param int|string|null $valueType
587
     *
588
     * @return Values
589
     */
590
    public static function values(array $values, $valueType = null): Values
591
    {
592
        return new Values($values, $valueType);
593
    }
594
595
    /**
596
     * @param string $value
597
     * @param string $format
598
     *
599
     * @return LikePattern
600
     */
601
    public static function likePattern(string $value, string $format = LikePattern::CONTAINS): LikePattern
602
    {
603
        return new LikePattern($value, $format);
604
    }
605
606
    // Arithmetic operands
607
608
    /**
609
     * @param Operand|string $field
610
     * @param Operand|mixed  $value
611
     *
612
     * @return Addition
613
     */
614
    public static function add($field, $value): Addition
615
    {
616
        return new Addition($field, $value);
617
    }
618
619
    /**
620
     * @param Operand|string $field
621
     * @param Operand|mixed  $value
622
     *
623
     * @return Subtraction
624
     */
625
    public static function sub($field, $value): Subtraction
626
    {
627
        return new Subtraction($field, $value);
628
    }
629
630
    /**
631
     * @param Operand|string $field
632
     * @param Operand|mixed  $value
633
     *
634
     * @return Multiplication
635
     */
636
    public static function mul($field, $value): Multiplication
637
    {
638
        return new Multiplication($field, $value);
639
    }
640
641
    /**
642
     * @param Operand|string $field
643
     * @param Operand|mixed  $value
644
     *
645
     * @return Division
646
     */
647
    public static function div($field, $value): Division
648
    {
649
        return new Division($field, $value);
650
    }
651
652
    // Platform functions
653
654
    /**
655
     * @param Operand|string $field
656
     * @param bool           $distinct
657
     *
658
     * @return Count
659
     */
660
    public static function COUNT($field, bool $distinct = false): Count
661
    {
662
        return new Count($field, $distinct);
663
    }
664
665
    /**
666
     * @param Operand|string $field
667
     * @param bool           $distinct
668
     *
669
     * @return Avg
670
     */
671
    public static function AVG($field, bool $distinct = false): Avg
672
    {
673
        return new Avg($field, $distinct);
674
    }
675
676
    /**
677
     * @param Operand|string $field
678
     * @param bool           $distinct
679
     *
680
     * @return Min
681
     */
682
    public static function MIN($field, bool $distinct = false): Min
683
    {
684
        return new Min($field, $distinct);
685
    }
686
687
    /**
688
     * @param Operand|string $field
689
     * @param bool           $distinct
690
     *
691
     * @return Max
692
     */
693
    public static function MAX($field, bool $distinct = false): Max
694
    {
695
        return new Max($field, $distinct);
696
    }
697
698
    /**
699
     * @param Operand|string $field
700
     * @param bool           $distinct
701
     *
702
     * @return Sum
703
     */
704
    public static function SUM($field, bool $distinct = false): Sum
705
    {
706
        return new Sum($field, $distinct);
707
    }
708
709
    /**
710
     * Add the number of days to a given date. (Supported units are YEAR, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND).
711
     *
712
     * @param \DateTimeInterface|string|Operand $date
713
     * @param int|Operand                       $value
714
     * @param string                            $unit
715
     *
716
     * @return DateAdd
717
     */
718
    public static function DATE_ADD($date, $value, string $unit): DateAdd
719
    {
720
        return new DateAdd($date, $value, $unit);
721
    }
722
723
    /**
724
     * Substract the number of days from a given date. (Supported units are YEAR, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND).
725
     *
726
     * @param \DateTimeInterface|string|Operand $date
727
     * @param int|Operand                       $value
728
     * @param string                            $unit
729
     *
730
     * @return DateSub
731
     */
732
    public static function DATE_SUB($date, $value, string $unit): DateSub
733
    {
734
        return new DateSub($date, $value, $unit);
735
    }
736
737
    /**
738
     * Trim the string by the given trim char, defaults to whitespaces.
739
     *
740
     * @param Operand|string $string
741
     * @param string         $mode
742
     * @param string         $characters
743
     */
744
    public static function TRIM($string, string $mode = Trim::BOTH, string $characters = ''): Trim
745
    {
746
        return new Trim($string, $mode, $characters);
747
    }
748
749
    /**
750
     * Call DQL function.
751
     *
752
     * Usage:
753
     *  Spec::fun('CURRENT_DATE')
754
     *  Spec::fun('DATE_DIFF', $date1, $date2)
755
     *
756
     * @param string $functionName
757
     * @param mixed  ...$arguments
758
     *
759
     * @return PlatformFunction
760
     */
761
    public static function fun(string $functionName, ...$arguments): PlatformFunction
762
    {
763
        return new PlatformFunction($functionName, ...$arguments);
764
    }
765
766
    /**
767
     * @param string $alias
768
     *
769
     * @return Alias
770
     */
771
    public static function alias(string $alias): Alias
772
    {
773
        return new Alias($alias);
774
    }
775
}
776