QueryBuilderTest::testQueryBuilderUsesTraits()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Janisbiz\LightOrm\Tests\Unit\Dms\MySQL\QueryBuilder;
4
5
use Janisbiz\LightOrm\Dms\MySQL\Enum\CommandEnum;
6
use Janisbiz\LightOrm\Dms\MySQL\Enum\KeywordEnum;
7
use Janisbiz\LightOrm\Dms\MySQL\QueryBuilder\QueryBuilder;
8
use Janisbiz\LightOrm\Dms\MySQL\QueryBuilder\QueryBuilderInterface;
9
use Janisbiz\LightOrm\Dms\MySQL\QueryBuilder\Traits;
10
use Janisbiz\LightOrm\Dms\MySQL\Repository\AbstractRepository;
11
use Janisbiz\LightOrm\Entity\EntityInterface;
12
use Janisbiz\LightOrm\QueryBuilder\QueryBuilderException;
13
use Janisbiz\LightOrm\Repository\AbstractRepository as BaseAbstractRepository;
14
use Janisbiz\LightOrm\Tests\Unit\Dms\MySQL\QueryBuilder\Traits\AbstractTraitTestCase;
15
use Janisbiz\LightOrm\Tests\Unit\Dms\MySQL\QueryBuilder\Traits\UnionTraitTest;
16
use Janisbiz\LightOrm\Tests\Unit\ReflectionTrait;
17
18
class QueryBuilderTest extends AbstractTraitTestCase
19
{
20
    use ReflectionTrait;
21
    use QueryBuilderTrait;
22
23
    const COMMAND_INVALID = 'INVALID';
24
25
    /**
26
     * @var \ReflectionMethod[]
27
     */
28
    private $abstractRepositoryPublicMethods = [];
29
30
    /**
31
     * @var AbstractRepository|\PHPUnit_Framework_MockObject_MockObject
32
     */
33
    private $abstractRepository;
34
35
    /**
36
     * @var QueryBuilder
37
     */
38
    private $queryBuilder;
39
40
    /**
41
     *
42
     * @throws \Exception
43
     */
44
    public function setUp()
45
    {
46
        if (empty($this->abstractRepositoryPublicMethods = $this->extractAbstractRepositoryPublicMethods())) {
47
            throw new \Exception('There are no AbstractRepository public methods methods!');
48
        }
49
50
        $this->abstractRepository = $this->getMockForAbstractClass(
51
            AbstractRepository::class,
52
            [],
53
            '',
54
            true,
55
            true,
56
            true,
57
            $this->abstractRepositoryPublicMethods
58
        );
59
60
        $this->queryBuilder = $this->createQueryBuilder($this->abstractRepository);
61
    }
62
63
    public function testQueryBuilderUsesTraits()
64
    {
65
        $this->assertObjectUsesTrait(Traits::class, $this->queryBuilder);
66
    }
67
68
    /**
69
     * @dataProvider crudData
70
     *
71
     * @param string $method
72
     * @param bool $toString
73
     */
74
    public function testCrud(string $method, bool $toString)
75
    {
76
        $this->abstractRepository->expects($this->once())->method($method)->with($this->queryBuilder, $toString);
77
        $this->queryBuilder->$method($toString);
78
    }
79
80
    /**
81
     *
82
     * @return array
83
     */
84
    public function crudData()
85
    {
86
        return \array_reduce(
87
            [
88
                \array_map(
89
                    function ($publicMethod) {
90
                        return [
91
                            $publicMethod,
92
                            false
93
                        ];
94
                    },
95
                    $this->extractAbstractRepositoryPublicMethods()
96
                ),
97
                \array_map(
98
                    function ($publicMethod) {
99
                        return [
100
                            $publicMethod,
101
                            true
102
                        ];
103
                    },
104
                    $this->extractAbstractRepositoryPublicMethods()
105
                ),
106
            ],
107
            'array_merge',
108
            []
109
        );
110
    }
111
112
    /**
113
     * @dataProvider buildQueryData
114
     *
115
     * @param string $command
116
     * @param array $methods
117
     * @param array $expected
118
     * @param array $expectedToString
119
     */
120
    public function testBuildQuery(string $command, array $methods, array $expected, array $expectedToString)
121
    {
122
        $this->addQueryPartsToQueryBuilder($command, $methods);
123
124
        $this->assertEquals(\implode(' ', $expected), $this->queryBuilder->buildQuery());
125
        $this->assertEquals(\implode(' ', $expectedToString), $this->queryBuilder->toString());
126
    }
127
128
    /**
129
     *
130
     * @return array
131
     */
132
    public function buildQueryData()
133
    {
134
        /** phpcs:disable */
135
        return [
136
            [
137
                CommandEnum::INSERT_INTO,
138
                [
139
                    'table' => 'table1',
140
                    'value' => [
141
                        'table1.column1',
142
                        'table1Column1Value',
143
                    ],
144
                    'onDuplicateKeyUpdate' => [
145
                        'table1.column1',
146
                        'table1Column1Value2',
147
                    ],
148
                ],
149
                [
150
                    'INSERT INTO',
151
                    'table1',
152
                    '(table1.column1) VALUES (:Table1_Column1_Value)',
153
                    'ON DUPLICATE KEY UPDATE table1.column1 = :Table1_Column1_OnDuplicateKeyUpdate',
154
                ],
155
                [
156
                    'INSERT INTO',
157
                    'table1',
158
                    '(table1.column1) VALUES (\'table1Column1Value\')',
159
                    'ON DUPLICATE KEY UPDATE table1.column1 = \'table1Column1Value2\'',
160
                ],
161
            ],
162
            [
163
                CommandEnum::SELECT,
164
                [
165
                    'column' => '*',
166
                    'table' => 'table1',
167
                    'innerJoin' => [
168
                        'table2',
169
                        'table2.id = table1.table2_id AND table2.column1 = :bindValue2',
170
                        [
171
                            'bindValue2' => 2,
172
                        ],
173
                    ],
174
                    'leftJoin' => [
175
                        'table3',
176
                        'table3.id = table1.table3_id AND table3.column1 = :bindValue3',
177
                        [
178
                            'bindValue3' => 3,
179
                        ],
180
                    ],
181
                    'rightJoin' => [
182
                        'table4',
183
                        'table4.id = table1.table4_id AND table4.column1 = :bindValue4',
184
                        [
185
                            'bindValue4' => 4,
186
                        ],
187
                    ],
188
                    'crossJoin' => [
189
                        'table5',
190
                        'table5.id = table1.table5_id AND table5.column1 = :bindValue5',
191
                        [
192
                            'bindValue5' => 5,
193
                        ],
194
                    ],
195
                    'fullOuterJoin' => [
196
                        'table6',
197
                        'table6.id = table1.table6_id AND table6.column1 = :bindValue6',
198
                        [
199
                            'bindValue6' => 6,
200
                        ],
201
                    ],
202
                    'innerJoinAs' => [
203
                        'table7',
204
                        'table7_alias',
205
                        'table7.id = table1.table7_id AND table7.column1 = :bindValue7',
206
                        [
207
                            'bindValue7' => 7,
208
                        ],
209
                    ],
210
                    'leftJoinAs' => [
211
                        'table8',
212
                        'table8_alias',
213
                        'table8.id = table1.table8_id AND table8.column1 = :bindValue8',
214
                        [
215
                            'bindValue8' => 8,
216
                        ],
217
                    ],
218
                    'rightJoinAs' => [
219
                        'table9',
220
                        'table9_alias',
221
                        'table9.id = table1.table9_id AND table9.column1 = :bindValue9',
222
                        [
223
                            'bindValue9' => 9,
224
                        ],
225
                    ],
226
                    'crossJoinAs' => [
227
                        'table10',
228
                        'table10_alias',
229
                        'table10.id = table1.table10_id AND table10.column1 = :bindValue10',
230
                        [
231
                            'bindValue10' => 10,
232
                        ],
233
                    ],
234
                    'fullOuterJoinAs' => [
235
                        'table11',
236
                        'table11_alias',
237
                        'table11.id = table1.table11_id AND table11.column1 = :bindValue11',
238
                        [
239
                            'bindValue11' => 11,
240
                        ],
241
                    ],
242
                    'where' => [
243
                        'table1.column1 = :table1Column1BindValue',
244
                        [
245
                            'table1Column1BindValue' => 'table1Column1BindValue'
246
                        ]
247
                    ],
248
                    'whereIn' => [
249
                        'table1.column2',
250
                        [
251
                            'table1Column2BindValue1',
252
                            'table1Column2BindValue2',
253
                        ]
254
                    ],
255
                    'whereNotIn' => [
256
                        'table1.column3',
257
                        [
258
                            'table1Column3BindValue1',
259
                            'table1Column3BindValue2',
260
                        ]
261
                    ],
262
                    'groupBy' => 'table1.column1',
263
                    'having' => [
264
                        'table1.column1 = table2.column2 AND table1.column2 = :havingTable1Column2',
265
                        [
266
                            'havingTable1Column2' => 1.2,
267
                        ]
268
                    ],
269
                    'orderBy' => [
270
                        'table1.column1',
271
                        KeywordEnum::DESC,
272
                    ],
273
                    'limit' => 1,
274
                    'offset' => 2,
275
                ],
276
                [
277
                    'SELECT',
278
                    '*',
279
                    'FROM table1',
280
                    'INNER JOIN table2 ON (table2.id = table1.table2_id AND table2.column1 = :bindValue2)',
281
                    'LEFT JOIN table3 ON (table3.id = table1.table3_id AND table3.column1 = :bindValue3)',
282
                    'RIGHT JOIN table4 ON (table4.id = table1.table4_id AND table4.column1 = :bindValue4)',
283
                    'CROSS JOIN table5 ON (table5.id = table1.table5_id AND table5.column1 = :bindValue5)',
284
                    'FULL OUTER JOIN table6 ON (table6.id = table1.table6_id AND table6.column1 = :bindValue6)',
285
                    'INNER JOIN table7 AS table7_alias ON (table7.id = table1.table7_id AND table7.column1 = :bindValue7)',
286
                    'LEFT JOIN table8 AS table8_alias ON (table8.id = table1.table8_id AND table8.column1 = :bindValue8)',
287
                    'RIGHT JOIN table9 AS table9_alias ON (table9.id = table1.table9_id AND table9.column1 = :bindValue9)',
288
                    'CROSS JOIN table10 AS table10_alias ON (table10.id = table1.table10_id AND table10.column1 = :bindValue10)',
289
                    'FULL OUTER JOIN table11 AS table11_alias ON (table11.id = table1.table11_id AND table11.column1 = :bindValue11)',
290
                    'WHERE table1.column1 = :table1Column1BindValue',
291
                    'AND table1.column2 IN (:0_table1column2_In, :1_table1column2_In)',
292
                    'AND table1.column3 NOT IN (:0_table1column3_NotIn, :1_table1column3_NotIn)',
293
                    'GROUP BY table1.column1',
294
                    'HAVING table1.column1 = table2.column2 AND table1.column2 = :havingTable1Column2',
295
                    'ORDER BY table1.column1 DESC',
296
                    'LIMIT 1 OFFSET 2',
297
                ],
298
                [
299
                    'SELECT',
300
                    '*',
301
                    'FROM table1',
302
                    'INNER JOIN table2 ON (table2.id = table1.table2_id AND table2.column1 = 2)',
303
                    'LEFT JOIN table3 ON (table3.id = table1.table3_id AND table3.column1 = 3)',
304
                    'RIGHT JOIN table4 ON (table4.id = table1.table4_id AND table4.column1 = 4)',
305
                    'CROSS JOIN table5 ON (table5.id = table1.table5_id AND table5.column1 = 5)',
306
                    'FULL OUTER JOIN table6 ON (table6.id = table1.table6_id AND table6.column1 = 6)',
307
                    'INNER JOIN table7 AS table7_alias ON (table7.id = table1.table7_id AND table7.column1 = 7)',
308
                    'LEFT JOIN table8 AS table8_alias ON (table8.id = table1.table8_id AND table8.column1 = 8)',
309
                    'RIGHT JOIN table9 AS table9_alias ON (table9.id = table1.table9_id AND table9.column1 = 9)',
310
                    'CROSS JOIN table10 AS table10_alias ON (table10.id = table1.table10_id AND table10.column1 = 10)',
311
                    'FULL OUTER JOIN table11 AS table11_alias ON (table11.id = table1.table11_id AND table11.column1 = 11)',
312
                    'WHERE table1.column1 = \'table1Column1BindValue\'',
313
                    'AND table1.column2 IN (\'table1Column2BindValue1\', \'table1Column2BindValue2\')',
314
                    'AND table1.column3 NOT IN (\'table1Column3BindValue1\', \'table1Column3BindValue2\')',
315
                    'GROUP BY table1.column1',
316
                    'HAVING table1.column1 = table2.column2 AND table1.column2 = 1.2',
317
                    'ORDER BY table1.column1 DESC',
318
                    'LIMIT 1 OFFSET 2',
319
                ],
320
            ],
321
            [
322
                CommandEnum::SELECT,
323
                [
324
                    'unionAll' => function () {
325
                        $queryBuilder = $this->createMock(QueryBuilderInterface::class);
326
                        $queryBuilder
327
                            ->method('commandData')
0 ignored issues
show
Bug introduced by
The method method() does not exist on PHPUnit\Framework\MockObject\MockObject. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

327
                            ->/** @scrutinizer ignore-call */ 
328
                              method('commandData')

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
328
                            ->willReturn(UnionTraitTest::QUERY_BUILDER_COMMAND)
329
                        ;
330
                        $queryBuilder
331
                            ->method('bindData')
332
                            ->willReturn(UnionTraitTest::QUERY_BUILDER_BIND_DATA)
333
                        ;
334
                        $queryBuilder
335
                            ->method('buildQuery')
336
                            ->willReturn(UnionTraitTest::QUERY_BUILDER_QUERY)
337
                        ;
338
339
                        return $queryBuilder;
340
                    },
341
                    'orderBy' => [
342
                        'col1',
343
                        KeywordEnum::DESC,
344
                    ],
345
                    'limit' => 1,
346
                    'offset' => 2,
347
                ],
348
                [
349
                    '(SELECT col1, col2, col3 FROM table1 WHERE table1.col1 = :col1 AND table1.col2 IS NOT NULL)',
350
                    'UNION ALL',
351
                    '(SELECT col1, col2, col3 FROM table1 WHERE table1.col1 = :col1 AND table1.col2 IS NOT NULL)',
352
                    'UNION ALL',
353
                    '(SELECT col1, col2, col3 FROM table1 WHERE table1.col1 = :col1 AND table1.col2 IS NOT NULL)',
354
                    'ORDER BY col1 DESC',
355
                    'LIMIT 1 OFFSET 2',
356
                ],
357
                [
358
                    '(SELECT col1, col2, col3 FROM table1 WHERE table1.col1 = \'val1\' AND table1.col2 IS NOT NULL)',
359
                    'UNION ALL',
360
                    '(SELECT col1, col2, col3 FROM table1 WHERE table1.col1 = \'val1\' AND table1.col2 IS NOT NULL)',
361
                    'UNION ALL',
362
                    '(SELECT col1, col2, col3 FROM table1 WHERE table1.col1 = \'val1\' AND table1.col2 IS NOT NULL)',
363
                    'ORDER BY col1 DESC',
364
                    'LIMIT 1 OFFSET 2',
365
                ],
366
            ],
367
            [
368
                CommandEnum::UPDATE,
369
                [
370
                    'table' => 'table1',
371
                    'set' => [
372
                        'table1.column1',
373
                        'table1Column1Value',
374
                    ],
375
                    'innerJoin' => [
376
                        'table2',
377
                        'table2.id = table1.table2_id AND table2.column1 = :bindValue2',
378
                        [
379
                            'bindValue2' => 2,
380
                        ],
381
                    ],
382
                    'leftJoin' => [
383
                        'table3',
384
                        'table3.id = table1.table3_id AND table3.column1 = :bindValue3',
385
                        [
386
                            'bindValue3' => 3,
387
                        ],
388
                    ],
389
                    'rightJoin' => [
390
                        'table4',
391
                        'table4.id = table1.table4_id AND table4.column1 = :bindValue4',
392
                        [
393
                            'bindValue4' => 4,
394
                        ],
395
                    ],
396
                    'crossJoin' => [
397
                        'table5',
398
                        'table5.id = table1.table5_id AND table5.column1 = :bindValue5',
399
                        [
400
                            'bindValue5' => 5,
401
                        ],
402
                    ],
403
                    'fullOuterJoin' => [
404
                        'table6',
405
                        'table6.id = table1.table6_id AND table6.column1 = :bindValue6',
406
                        [
407
                            'bindValue6' => 6,
408
                        ],
409
                    ],
410
                    'innerJoinAs' => [
411
                        'table7',
412
                        'table7_alias',
413
                        'table7.id = table1.table7_id AND table7.column1 = :bindValue7',
414
                        [
415
                            'bindValue7' => 7,
416
                        ],
417
                    ],
418
                    'leftJoinAs' => [
419
                        'table8',
420
                        'table8_alias',
421
                        'table8.id = table1.table8_id AND table8.column1 = :bindValue8',
422
                        [
423
                            'bindValue8' => 8,
424
                        ],
425
                    ],
426
                    'rightJoinAs' => [
427
                        'table9',
428
                        'table9_alias',
429
                        'table9.id = table1.table9_id AND table9.column1 = :bindValue9',
430
                        [
431
                            'bindValue9' => 9,
432
                        ],
433
                    ],
434
                    'crossJoinAs' => [
435
                        'table10',
436
                        'table10_alias',
437
                        'table10.id = table1.table10_id AND table10.column1 = :bindValue10',
438
                        [
439
                            'bindValue10' => 10,
440
                        ],
441
                    ],
442
                    'fullOuterJoinAs' => [
443
                        'table11',
444
                        'table11_alias',
445
                        'table11.id = table1.table11_id AND table11.column1 = :bindValue11',
446
                        [
447
                            'bindValue11' => 11,
448
                        ],
449
                    ],
450
                    'where' => [
451
                        'table1.column1 = :table1Column1BindValue',
452
                        [
453
                            'table1Column1BindValue' => 'table1Column1BindValue'
454
                        ]
455
                    ],
456
                    'whereIn' => [
457
                        'table1.column2',
458
                        [
459
                            'table1Column2BindValue1',
460
                            'table1Column2BindValue2',
461
                        ]
462
                    ],
463
                    'whereNotIn' => [
464
                        'table1.column3',
465
                        [
466
                            'table1Column3BindValue1',
467
                            'table1Column3BindValue2',
468
                        ]
469
                    ],
470
                    'limit' => 1,
471
                    'offset' => 2,
472
                ],
473
                [
474
                    'UPDATE',
475
                    'table1',
476
                    'INNER JOIN table2 ON (table2.id = table1.table2_id AND table2.column1 = :bindValue2)',
477
                    'LEFT JOIN table3 ON (table3.id = table1.table3_id AND table3.column1 = :bindValue3)',
478
                    'RIGHT JOIN table4 ON (table4.id = table1.table4_id AND table4.column1 = :bindValue4)',
479
                    'CROSS JOIN table5 ON (table5.id = table1.table5_id AND table5.column1 = :bindValue5)',
480
                    'FULL OUTER JOIN table6 ON (table6.id = table1.table6_id AND table6.column1 = :bindValue6)',
481
                    'INNER JOIN table7 AS table7_alias ON (table7.id = table1.table7_id AND table7.column1 = :bindValue7)',
482
                    'LEFT JOIN table8 AS table8_alias ON (table8.id = table1.table8_id AND table8.column1 = :bindValue8)',
483
                    'RIGHT JOIN table9 AS table9_alias ON (table9.id = table1.table9_id AND table9.column1 = :bindValue9)',
484
                    'CROSS JOIN table10 AS table10_alias ON (table10.id = table1.table10_id AND table10.column1 = :bindValue10)',
485
                    'FULL OUTER JOIN table11 AS table11_alias ON (table11.id = table1.table11_id AND table11.column1 = :bindValue11)',
486
                    'SET table1.column1 = :Table1_Column1_Update',
487
                    'WHERE table1.column1 = :table1Column1BindValue',
488
                    'AND table1.column2 IN (:0_table1column2_In, :1_table1column2_In)',
489
                    'AND table1.column3 NOT IN (:0_table1column3_NotIn, :1_table1column3_NotIn)',
490
                    'LIMIT 1 OFFSET 2'
491
                ],
492
                [
493
                    'UPDATE',
494
                    'table1',
495
                    'INNER JOIN table2 ON (table2.id = table1.table2_id AND table2.column1 = 2)',
496
                    'LEFT JOIN table3 ON (table3.id = table1.table3_id AND table3.column1 = 3)',
497
                    'RIGHT JOIN table4 ON (table4.id = table1.table4_id AND table4.column1 = 4)',
498
                    'CROSS JOIN table5 ON (table5.id = table1.table5_id AND table5.column1 = 5)',
499
                    'FULL OUTER JOIN table6 ON (table6.id = table1.table6_id AND table6.column1 = 6)',
500
                    'INNER JOIN table7 AS table7_alias ON (table7.id = table1.table7_id AND table7.column1 = 7)',
501
                    'LEFT JOIN table8 AS table8_alias ON (table8.id = table1.table8_id AND table8.column1 = 8)',
502
                    'RIGHT JOIN table9 AS table9_alias ON (table9.id = table1.table9_id AND table9.column1 = 9)',
503
                    'CROSS JOIN table10 AS table10_alias ON (table10.id = table1.table10_id AND table10.column1 = 10)',
504
                    'FULL OUTER JOIN table11 AS table11_alias ON (table11.id = table1.table11_id AND table11.column1 = 11)',
505
                    'SET table1.column1 = \'table1Column1Value\'',
506
                    'WHERE table1.column1 = \'table1Column1BindValue\'',
507
                    'AND table1.column2 IN (\'table1Column2BindValue1\', \'table1Column2BindValue2\')',
508
                    'AND table1.column3 NOT IN (\'table1Column3BindValue1\', \'table1Column3BindValue2\')',
509
                    'LIMIT 1 OFFSET 2',
510
                ],
511
            ],
512
            [
513
                CommandEnum::DELETE,
514
                [
515
                    'table' => 'table1',
516
                    'innerJoin' => [
517
                        'table2',
518
                        'table2.id = table1.table2_id AND table2.column1 = :bindValue2',
519
                        [
520
                            'bindValue2' => 2,
521
                        ],
522
                    ],
523
                    'leftJoin' => [
524
                        'table3',
525
                        'table3.id = table1.table3_id AND table3.column1 = :bindValue3',
526
                        [
527
                            'bindValue3' => 3,
528
                        ],
529
                    ],
530
                    'rightJoin' => [
531
                        'table4',
532
                        'table4.id = table1.table4_id AND table4.column1 = :bindValue4',
533
                        [
534
                            'bindValue4' => 4,
535
                        ],
536
                    ],
537
                    'crossJoin' => [
538
                        'table5',
539
                        'table5.id = table1.table5_id AND table5.column1 = :bindValue5',
540
                        [
541
                            'bindValue5' => 5,
542
                        ],
543
                    ],
544
                    'fullOuterJoin' => [
545
                        'table6',
546
                        'table6.id = table1.table6_id AND table6.column1 = :bindValue6',
547
                        [
548
                            'bindValue6' => 6,
549
                        ],
550
                    ],
551
                    'innerJoinAs' => [
552
                        'table7',
553
                        'table7_alias',
554
                        'table7.id = table1.table7_id AND table7.column1 = :bindValue7',
555
                        [
556
                            'bindValue7' => 7,
557
                        ],
558
                    ],
559
                    'leftJoinAs' => [
560
                        'table8',
561
                        'table8_alias',
562
                        'table8.id = table1.table8_id AND table8.column1 = :bindValue8',
563
                        [
564
                            'bindValue8' => 8,
565
                        ],
566
                    ],
567
                    'rightJoinAs' => [
568
                        'table9',
569
                        'table9_alias',
570
                        'table9.id = table1.table9_id AND table9.column1 = :bindValue9',
571
                        [
572
                            'bindValue9' => 9,
573
                        ],
574
                    ],
575
                    'crossJoinAs' => [
576
                        'table10',
577
                        'table10_alias',
578
                        'table10.id = table1.table10_id AND table10.column1 = :bindValue10',
579
                        [
580
                            'bindValue10' => 10,
581
                        ],
582
                    ],
583
                    'fullOuterJoinAs' => [
584
                        'table11',
585
                        'table11_alias',
586
                        'table11.id = table1.table11_id AND table11.column1 = :bindValue11',
587
                        [
588
                            'bindValue11' => 11,
589
                        ],
590
                    ],
591
                    'where' => [
592
                        'table1.column1 = :table1Column1BindValue',
593
                        [
594
                            'table1Column1BindValue' => 'table1Column1BindValue'
595
                        ]
596
                    ],
597
                    'whereIn' => [
598
                        'table1.column2',
599
                        [
600
                            'table1Column2BindValue1',
601
                            'table1Column2BindValue2',
602
                        ]
603
                    ],
604
                    'whereNotIn' => [
605
                        'table1.column3',
606
                        [
607
                            'table1Column3BindValue1',
608
                            'table1Column3BindValue2',
609
                        ]
610
                    ],
611
                    'limit' => 1,
612
                    'offset' => 2,
613
                ],
614
                [
615
                    'DELETE',
616
                    'table1 FROM table1',
617
                    'INNER JOIN table2 ON (table2.id = table1.table2_id AND table2.column1 = :bindValue2)',
618
                    'LEFT JOIN table3 ON (table3.id = table1.table3_id AND table3.column1 = :bindValue3)',
619
                    'RIGHT JOIN table4 ON (table4.id = table1.table4_id AND table4.column1 = :bindValue4)',
620
                    'CROSS JOIN table5 ON (table5.id = table1.table5_id AND table5.column1 = :bindValue5)',
621
                    'FULL OUTER JOIN table6 ON (table6.id = table1.table6_id AND table6.column1 = :bindValue6)',
622
                    'INNER JOIN table7 AS table7_alias ON (table7.id = table1.table7_id AND table7.column1 = :bindValue7)',
623
                    'LEFT JOIN table8 AS table8_alias ON (table8.id = table1.table8_id AND table8.column1 = :bindValue8)',
624
                    'RIGHT JOIN table9 AS table9_alias ON (table9.id = table1.table9_id AND table9.column1 = :bindValue9)',
625
                    'CROSS JOIN table10 AS table10_alias ON (table10.id = table1.table10_id AND table10.column1 = :bindValue10)',
626
                    'FULL OUTER JOIN table11 AS table11_alias ON (table11.id = table1.table11_id AND table11.column1 = :bindValue11)',
627
                    'WHERE table1.column1 = :table1Column1BindValue',
628
                    'AND table1.column2 IN (:0_table1column2_In, :1_table1column2_In)',
629
                    'AND table1.column3 NOT IN (:0_table1column3_NotIn, :1_table1column3_NotIn)',
630
                    'LIMIT 1 OFFSET 2',
631
                ],
632
                [
633
                    'DELETE',
634
                    'table1 FROM table1',
635
                    'INNER JOIN table2 ON (table2.id = table1.table2_id AND table2.column1 = 2)',
636
                    'LEFT JOIN table3 ON (table3.id = table1.table3_id AND table3.column1 = 3)',
637
                    'RIGHT JOIN table4 ON (table4.id = table1.table4_id AND table4.column1 = 4)',
638
                    'CROSS JOIN table5 ON (table5.id = table1.table5_id AND table5.column1 = 5)',
639
                    'FULL OUTER JOIN table6 ON (table6.id = table1.table6_id AND table6.column1 = 6)',
640
                    'INNER JOIN table7 AS table7_alias ON (table7.id = table1.table7_id AND table7.column1 = 7)',
641
                    'LEFT JOIN table8 AS table8_alias ON (table8.id = table1.table8_id AND table8.column1 = 8)',
642
                    'RIGHT JOIN table9 AS table9_alias ON (table9.id = table1.table9_id AND table9.column1 = 9)',
643
                    'CROSS JOIN table10 AS table10_alias ON (table10.id = table1.table10_id AND table10.column1 = 10)',
644
                    'FULL OUTER JOIN table11 AS table11_alias ON (table11.id = table1.table11_id AND table11.column1 = 11)',
645
                    'WHERE table1.column1 = \'table1Column1BindValue\'',
646
                    'AND table1.column2 IN (\'table1Column2BindValue1\', \'table1Column2BindValue2\')',
647
                    'AND table1.column3 NOT IN (\'table1Column3BindValue1\', \'table1Column3BindValue2\')',
648
                    'LIMIT 1 OFFSET 2',
649
                ],
650
            ],
651
        ];
652
        /** phpcs:enable */
653
    }
654
655
    /**
656
     * @dataProvider buildQueryWithMissingQueryPartsProvideData
657
     *
658
     * @param string $command
659
     * @param string[] $methods
660
     * @param string $expectedException
661
     * @param string $expectedExceptionMessage
662
     */
663
    public function testBuildQueryWithMissingQueryPartsProvided(
664
        string $command,
665
        array $methods,
666
        string $expectedException,
667
        string $expectedExceptionMessage
668
    ) {
669
        $this->addQueryPartsToQueryBuilder($command, $methods);
670
671
        $this->expectException($expectedException);
672
        $this->expectExceptionMessage($expectedExceptionMessage);
673
674
        $this->queryBuilder->buildQuery();
675
    }
676
677
    /**
678
     * @return array
679
     */
680
    public function buildQueryWithMissingQueryPartsProvideData()
681
    {
682
        return [
683
            [
684
                '',
685
                [],
686
                QueryBuilderException::class,
687
                'Could not build query, as there is no command provided!',
688
            ],
689
            [
690
                CommandEnum::UPDATE,
691
                [],
692
                QueryBuilderException::class,
693
                'Cannot perform UPDATE action without SET condition!',
694
            ],
695
            [
696
                CommandEnum::UPDATE,
697
                [
698
                    'set' => [
699
                        'table1.column1',
700
                        'table1Column1Value',
701
                    ],
702
                ],
703
                QueryBuilderException::class,
704
                'Cannot perform UPDATE action without WHERE condition!',
705
            ],
706
            [
707
                CommandEnum::UPDATE_IGNORE,
708
                [],
709
                QueryBuilderException::class,
710
                'Cannot perform UPDATE action without SET condition!',
711
            ],
712
            [
713
                CommandEnum::UPDATE_IGNORE,
714
                [
715
                    'set' => [
716
                        'table1.column1',
717
                        'table1Column1Value',
718
                    ],
719
                ],
720
                QueryBuilderException::class,
721
                'Cannot perform UPDATE action without WHERE condition!',
722
            ],
723
            [
724
                CommandEnum::DELETE,
725
                [],
726
                QueryBuilderException::class,
727
                'Cannot perform DELETE action without WHERE condition!',
728
            ],
729
            [
730
                CommandEnum::DELETE,
731
                [],
732
                QueryBuilderException::class,
733
                'Cannot perform DELETE action without WHERE condition!',
734
            ],
735
            [
736
                static::COMMAND_INVALID,
737
                [],
738
                QueryBuilderException::class,
739
                \sprintf('Could not build query, as there is no valid(%s) command provided!', static::COMMAND_INVALID),
740
            ],
741
        ];
742
    }
743
744
    public function testGetEntity()
745
    {
746
        /** @var EntityInterface $entity */
747
        $entity = $this->createMock(EntityInterface::class);
748
749
        $queryBuilder = $this->createQueryBuilder($this->abstractRepository, $entity);
750
751
        $this->assertTrue($queryBuilder->getEntity() instanceof EntityInterface);
752
    }
753
754
    /**
755
     * @param string $command
756
     * @param string[] $methods
757
     *
758
     * @return $this
759
     */
760
    private function addQueryPartsToQueryBuilder(string $command, array $methods)
761
    {
762
        $this->queryBuilder->command($command);
763
764
        foreach ($methods as $method => $value) {
765
            switch ($method) {
766
                case 'column':
767
                case 'table':
768
                case 'groupBy':
769
                case 'limit':
770
                case 'offset':
771
                    $this->queryBuilder->$method($value);
772
773
                    break;
774
775
                case 'innerJoin':
776
                case 'leftJoin':
777
                case 'rightJoin':
778
                case 'crossJoin':
779
                case 'fullOuterJoin':
780
                    $this->queryBuilder->$method($value[0], $value[1], !empty($value[2]) ? $value[2] : []);
781
782
                    break;
783
784
                case 'innerJoinAs':
785
                case 'leftJoinAs':
786
                case 'rightJoinAs':
787
                case 'crossJoinAs':
788
                case 'fullOuterJoinAs':
789
                    $this->queryBuilder->$method($value[0], $value[1], $value[2], !empty($value[3]) ? $value[3] : []);
790
791
                    break;
792
793
                case 'where':
794
                case 'whereIn':
795
                case 'whereNotIn':
796
                case 'having':
797
                case 'value':
798
                case 'onDuplicateKeyUpdate':
799
                case 'set':
800
                case 'orderBy':
801
                    $this->queryBuilder->$method($value[0], $value[1]);
802
803
                    break;
804
805
                case 'unionAll':
806
                    $queryBuilder = $value();
807
808
                    $unionAllQueries = [
809
                        $queryBuilder,
810
                        $queryBuilder,
811
                        $queryBuilder,
812
                    ];
813
814
                    foreach ($unionAllQueries as $unionAllQuery) {
815
                        $this->queryBuilder->unionAll($unionAllQuery);
816
                    }
817
818
                    break;
819
            }
820
        }
821
822
        return $this;
823
    }
824
825
    /**
826
     * @return array
827
     */
828
    private function extractAbstractRepositoryPublicMethods()
829
    {
830
        $abstractRepositoryReflection = new \ReflectionClass(AbstractRepository::class);
831
832
        return \array_filter(\array_diff(
833
            \array_map(
834
                function (\ReflectionMethod $abstractRepositoryMethod) {
835
                    if (2 === $abstractRepositoryMethod->getNumberOfParameters()
836
                        && 'queryBuilder' === $abstractRepositoryMethod->getParameters()[0]->getName()
837
                        && 'toString' === $abstractRepositoryMethod->getParameters()[1]->getName()
838
                    ) {
839
                        return $abstractRepositoryMethod->getName();
840
                    }
841
842
                    return null;
843
                },
844
                $abstractRepositoryReflection->getMethods(\ReflectionMethod::IS_PROTECTED)
845
            ),
846
            \array_reduce(
847
                \array_map(
848
                    function (array $publicMethods) {
849
                        return \array_map(
850
                            function (\ReflectionMethod $publicMethod) {
851
                                return $publicMethod->getName();
852
                            },
853
                            $publicMethods
854
                        );
855
                    },
856
                    [
857
                        (new \ReflectionClass(BaseAbstractRepository::class))
858
                            ->getMethods(\ReflectionMethod::IS_PROTECTED | \ReflectionMethod::IS_ABSTRACT),
859
                    ]
860
                ),
861
                'array_merge',
862
                []
863
            )
864
        ));
865
    }
866
}
867