03c8e4aab8dd2434dc1175cabc1830e9f7c4b51a
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Database / Query / QueryBuilderTest.php
1 <?php
2 declare (strict_types = 1);
3 namespace TYPO3\CMS\Core\Tests\Unit\Database\Query;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use Prophecy\Argument;
19 use TYPO3\CMS\Core\Database\Connection;
20 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
21 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
22 use TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform;
23 use TYPO3\CMS\Core\Tests\UnitTestCase;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25
26 class QueryBuilderTest extends UnitTestCase
27 {
28 /**
29 * @var Connection|\Prophecy\Prophecy\ObjectProphecy
30 */
31 protected $connection;
32
33 /**
34 * @var \Doctrine\DBAL\Platforms\AbstractPlatform
35 */
36 protected $platform;
37
38 /**
39 * @var QueryBuilder
40 */
41 protected $subject;
42
43 /**
44 * @var \Doctrine\DBAL\Query\QueryBuilder|\Prophecy\Prophecy\ObjectProphecy
45 */
46 protected $concreteQueryBuilder;
47
48 /**
49 * Create a new database connection mock object for every test.
50 *
51 * @return void
52 */
53 protected function setUp()
54 {
55 parent::setUp();
56
57 $this->concreteQueryBuilder = $this->prophesize(\Doctrine\DBAL\Query\QueryBuilder::class);
58
59 $this->connection = $this->prophesize(Connection::class);
60 $this->connection->getDatabasePlatform()->willReturn(new MockPlatform());
61
62 $this->subject = GeneralUtility::makeInstance(
63 QueryBuilder::class,
64 $this->connection->reveal(),
65 null,
66 $this->concreteQueryBuilder->reveal()
67 );
68 }
69
70 /**
71 * @test
72 */
73 public function exprReturnsExpressionBuilderForConnection()
74 {
75 $this->connection->getExpressionBuilder()
76 ->shouldBeCalled()
77 ->willReturn(GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection->reveal()));
78
79 $this->subject->expr();
80 }
81
82 /**
83 * @test
84 */
85 public function getTypeDelegatesToConcreteQueryBuilder()
86 {
87 $this->concreteQueryBuilder->getType()
88 ->shouldBeCalled()
89 ->willReturn(\Doctrine\DBAL\Query\QueryBuilder::INSERT);
90
91 $this->subject->getType();
92 }
93
94 /**
95 * @test
96 */
97 public function getStateDelegatesToConcreteQueryBuilder()
98 {
99 $this->concreteQueryBuilder->getState()
100 ->shouldBeCalled()
101 ->willReturn(\Doctrine\DBAL\Query\QueryBuilder::STATE_CLEAN);
102
103 $this->subject->getState();
104 }
105
106 /**
107 * @test
108 */
109 public function getSQLDelegatesToConcreteQueryBuilder()
110 {
111 $this->concreteQueryBuilder->getSQL()
112 ->shouldBeCalled()
113 ->willReturn('UPDATE aTable SET pid = 7');
114 $this->concreteQueryBuilder->getType()
115 ->willReturn(2); // Update Type
116
117 $this->subject->getSQL();
118 }
119
120 /**
121 * @test
122 */
123 public function setParameterDelegatesToConcreteQueryBuilder()
124 {
125 $this->concreteQueryBuilder->setParameter(Argument::exact('aField'), Argument::exact(5), Argument::cetera())
126 ->shouldBeCalled()
127 ->willReturn($this->subject);
128
129 $this->subject->setParameter('aField', 5);
130 }
131
132 /**
133 * @test
134 */
135 public function setParametersDelegatesToConcreteQueryBuilder()
136 {
137 $this->concreteQueryBuilder->setParameters(Argument::exact(['aField' => 'aValue']), Argument::exact([]))
138 ->shouldBeCalled()
139 ->willReturn($this->subject);
140
141 $this->subject->setParameters(['aField' => 'aValue']);
142 }
143
144 /**
145 * @test
146 */
147 public function getParametersDelegatesToConcreteQueryBuilder()
148 {
149 $this->concreteQueryBuilder->getParameters()
150 ->shouldBeCalled()
151 ->willReturn(['aField' => 'aValue']);
152
153 $this->subject->getParameters();
154 }
155
156 /**
157 * @test
158 */
159 public function getParameterDelegatesToConcreteQueryBuilder()
160 {
161 $this->concreteQueryBuilder->getParameter(Argument::exact('aField'))
162 ->shouldBeCalled()
163 ->willReturn('aValue');
164
165 $this->subject->getParameter('aField');
166 }
167
168 /**
169 * @test
170 */
171 public function getParameterTypesDelegatesToConcreteQueryBuilder()
172 {
173 $this->concreteQueryBuilder->getParameterTypes()
174 ->shouldBeCalled()
175 ->willReturn([]);
176
177 $this->subject->getParameterTypes();
178 }
179
180 /**
181 * @test
182 */
183 public function getParameterTypeDelegatesToConcreteQueryBuilder()
184 {
185 $this->concreteQueryBuilder->getParameterType(Argument::exact('aField'))
186 ->shouldBeCalled()
187 ->willReturn(Connection::PARAM_STR);
188
189 $this->subject->getParameterType('aField');
190 }
191
192 /**
193 * @test
194 */
195 public function setFirstResultDelegatesToConcreteQueryBuilder()
196 {
197 $this->concreteQueryBuilder->setFirstResult(Argument::cetera())
198 ->shouldBeCalled()
199 ->willReturn($this->subject);
200
201 $this->subject->setFirstResult(1);
202 }
203
204 /**
205 * @test
206 */
207 public function getFirstResultDelegatesToConcreteQueryBuilder()
208 {
209 $this->concreteQueryBuilder->getFirstResult()
210 ->shouldBeCalled()
211 ->willReturn(1);
212
213 $this->subject->getFirstResult();
214 }
215
216 /**
217 * @test
218 */
219 public function setMaxResultsDelegatesToConcreteQueryBuilder()
220 {
221 $this->concreteQueryBuilder->setMaxResults(Argument::cetera())
222 ->shouldBeCalled()
223 ->willReturn($this->subject);
224
225 $this->subject->setMaxResults(1);
226 }
227
228 /**
229 * @test
230 */
231 public function getMaxResultsDelegatesToConcreteQueryBuilder()
232 {
233 $this->concreteQueryBuilder->getMaxResults()
234 ->shouldBeCalled()
235 ->willReturn(1);
236
237 $this->subject->getMaxResults();
238 }
239
240 /**
241 * @test
242 */
243 public function addDelegatesToConcreteQueryBuilder()
244 {
245 $this->concreteQueryBuilder->add(Argument::exact('select'), Argument::exact('aField'), Argument::cetera())
246 ->shouldBeCalled()
247 ->willReturn($this->subject);
248
249 $this->subject->add('select', 'aField');
250 }
251
252 /**
253 * @test
254 */
255 public function countBuildsExpressionAndCallsSelect()
256 {
257 $this->concreteQueryBuilder->select(Argument::exact('COUNT(*)'))
258 ->shouldBeCalled()
259 ->willReturn($this->subject);
260
261 $this->subject->count('*');
262 }
263
264 /**
265 * @test
266 */
267 public function selectQuotesIdentifiersAndDelegatesToConcreteQueryBuilder()
268 {
269 $this->connection->quoteIdentifier('aField')
270 ->shouldBeCalled()
271 ->willReturnArgument(0);
272 $this->connection->quoteIdentifier('anotherField')
273 ->shouldBeCalled()
274 ->willReturnArgument(0);
275 $this->concreteQueryBuilder->select(Argument::exact('aField'), Argument::exact('anotherField'))
276 ->shouldBeCalled()
277 ->willReturn($this->subject);
278
279 $this->subject->select('aField', 'anotherField');
280 }
281
282 public function quoteIdentifiersForSelectDataProvider()
283 {
284 return [
285 'fieldName' => [
286 'fieldName',
287 '"fieldName"',
288 ],
289 'tableName.fieldName' => [
290 'tableName.fieldName',
291 '"tableName"."fieldName"',
292 ],
293 'tableName.*' => [
294 'tableName.*',
295 '"tableName".*',
296 ],
297 '*' => [
298 '*',
299 '*',
300 ],
301 'fieldName AS anotherFieldName' => [
302 'fieldName AS anotherFieldName',
303 '"fieldName" AS "anotherFieldName"',
304 ],
305 'tableName.fieldName AS anotherFieldName' => [
306 'tableName.fieldName AS anotherFieldName',
307 '"tableName"."fieldName" AS "anotherFieldName"',
308 ],
309 'tableName.fieldName AS anotherTable.anotherFieldName' => [
310 'tableName.fieldName AS anotherTable.anotherFieldName',
311 '"tableName"."fieldName" AS "anotherTable"."anotherFieldName"',
312 ],
313 ];
314 }
315
316 /**
317 * @test
318 * @dataProvider quoteIdentifiersForSelectDataProvider
319 * @param string $identifier
320 * @param string $expectedResult
321 */
322 public function quoteIdentifiersForSelect($identifier, $expectedResult)
323 {
324 $this->connection->quoteIdentifier(Argument::cetera())->will(
325 function ($args) {
326 $platform = new MockPlatform();
327
328 return $platform->quoteIdentifier($args[0]);
329 }
330 );
331
332 $this->assertSame([$expectedResult], $this->subject->quoteIdentifiersForSelect([$identifier]));
333 }
334
335 /**
336 * @test
337 * @expectedException \InvalidArgumentException
338 */
339 public function quoteIdentifiersForSelectWithInvalidAlias()
340 {
341 $this->connection->quoteIdentifier(Argument::cetera())->will(
342 function ($args) {
343 $platform = new MockPlatform();
344
345 return $platform->quoteIdentifier($args[0]);
346 }
347 );
348 $this->subject->quoteIdentifiersForSelect(['aField AS anotherField,someField AS someThing']);
349 }
350
351 /**
352 * @test
353 */
354 public function selectDoesNotQuoteStarPlaceholder()
355 {
356 $this->connection->quoteIdentifier('aField')
357 ->shouldBeCalled()
358 ->willReturnArgument(0);
359 $this->connection->quoteIdentifier('*')
360 ->shouldNotBeCalled();
361 $this->concreteQueryBuilder->select(Argument::exact('aField'), Argument::exact('*'))
362 ->shouldBeCalled()
363 ->willReturn($this->subject);
364
365 $this->subject->select('aField', '*');
366 }
367
368 /**
369 * @test
370 */
371 public function addSelectQuotesIdentifiersAndDelegatesToConcreteQueryBuilder()
372 {
373 $this->connection->quoteIdentifier('aField')
374 ->shouldBeCalled()
375 ->willReturnArgument(0);
376 $this->connection->quoteIdentifier('anotherField')
377 ->shouldBeCalled()
378 ->willReturnArgument(0);
379 $this->concreteQueryBuilder->addSelect(Argument::exact('aField'), Argument::exact('anotherField'))
380 ->shouldBeCalled()
381 ->willReturn($this->subject);
382
383 $this->subject->addSelect('aField', 'anotherField');
384 }
385
386 /**
387 * @test
388 */
389 public function addSelectDoesNotQuoteStarPlaceholder()
390 {
391 $this->connection->quoteIdentifier('aField')
392 ->shouldBeCalled()
393 ->willReturnArgument(0);
394 $this->connection->quoteIdentifier('*')
395 ->shouldNotBeCalled();
396 $this->concreteQueryBuilder->addSelect(Argument::exact('aField'), Argument::exact('*'))
397 ->shouldBeCalled()
398 ->willReturn($this->subject);
399
400 $this->subject->addSelect('aField', '*');
401 }
402
403 /**
404 * @test
405 * @todo: Test with alias
406 */
407 public function deleteQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
408 {
409 $this->connection->quoteIdentifier('aTable')
410 ->shouldBeCalled()
411 ->willReturnArgument(0);
412 $this->concreteQueryBuilder->delete(Argument::exact('aTable'), Argument::cetera())
413 ->shouldBeCalled()
414 ->willReturn($this->subject);
415
416 $this->subject->delete('aTable');
417 }
418
419 /**
420 * @test
421 * @todo: Test with alias
422 */
423 public function updateQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
424 {
425 $this->connection->quoteIdentifier('aTable')
426 ->shouldBeCalled()
427 ->willReturnArgument(0);
428 $this->concreteQueryBuilder->update(Argument::exact('aTable'), Argument::cetera())
429 ->shouldBeCalled()
430 ->willReturn($this->subject);
431
432 $this->subject->update('aTable');
433 }
434
435 /**
436 * @test
437 */
438 public function insertQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
439 {
440 $this->connection->quoteIdentifier('aTable')
441 ->shouldBeCalled()
442 ->willReturnArgument(0);
443 $this->concreteQueryBuilder->insert(Argument::exact('aTable'))
444 ->shouldBeCalled()
445 ->willReturn($this->subject);
446
447 $this->subject->insert('aTable');
448 }
449
450 /**
451 * @test
452 * @todo: Test with alias
453 */
454 public function fromQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
455 {
456 $this->connection->quoteIdentifier('aTable')
457 ->shouldBeCalled()
458 ->willReturnArgument(0);
459 $this->concreteQueryBuilder->from(Argument::exact('aTable'), Argument::cetera())
460 ->shouldBeCalled()
461 ->willReturn($this->subject);
462
463 $this->subject->from('aTable');
464 }
465
466 /**
467 * @test
468 */
469 public function joinQuotesIdentifiersAndDelegatesToConcreteQueryBuilder()
470 {
471 $this->connection->quoteIdentifier('fromAlias')
472 ->shouldBeCalled()
473 ->willReturnArgument(0);
474 $this->connection->quoteIdentifier('join')
475 ->shouldBeCalled()
476 ->willReturnArgument(0);
477 $this->connection->quoteIdentifier('alias')
478 ->shouldBeCalled()
479 ->willReturnArgument(0);
480 $this->concreteQueryBuilder->innerJoin('fromAlias', 'join', 'alias', null)
481 ->shouldBeCalled()
482 ->willReturn($this->subject);
483
484 $this->subject->join('fromAlias', 'join', 'alias');
485 }
486
487 /**
488 * @test
489 */
490 public function innerJoinQuotesIdentifiersAndDelegatesToConcreteQueryBuilder()
491 {
492 $this->connection->quoteIdentifier('fromAlias')
493 ->shouldBeCalled()
494 ->willReturnArgument(0);
495 $this->connection->quoteIdentifier('join')
496 ->shouldBeCalled()
497 ->willReturnArgument(0);
498 $this->connection->quoteIdentifier('alias')
499 ->shouldBeCalled()
500 ->willReturnArgument(0);
501 $this->concreteQueryBuilder->innerJoin('fromAlias', 'join', 'alias', null)
502 ->shouldBeCalled()
503 ->willReturn($this->subject);
504
505 $this->subject->innerJoin('fromAlias', 'join', 'alias');
506 }
507
508 /**
509 * @test
510 */
511 public function leftJoinQuotesIdentifiersAndDelegatesToConcreteQueryBuilder()
512 {
513 $this->connection->quoteIdentifier('fromAlias')
514 ->shouldBeCalled()
515 ->willReturnArgument(0);
516 $this->connection->quoteIdentifier('join')
517 ->shouldBeCalled()
518 ->willReturnArgument(0);
519 $this->connection->quoteIdentifier('alias')
520 ->shouldBeCalled()
521 ->willReturnArgument(0);
522 $this->concreteQueryBuilder->leftJoin('fromAlias', 'join', 'alias', null)
523 ->shouldBeCalled()
524 ->willReturn($this->subject);
525
526 $this->subject->leftJoin('fromAlias', 'join', 'alias');
527 }
528
529 /**
530 * @test
531 */
532 public function rightJoinQuotesIdentifiersAndDelegatesToConcreteQueryBuilder()
533 {
534 $this->connection->quoteIdentifier('fromAlias')
535 ->shouldBeCalled()
536 ->willReturnArgument(0);
537 $this->connection->quoteIdentifier('join')
538 ->shouldBeCalled()
539 ->willReturnArgument(0);
540 $this->connection->quoteIdentifier('alias')
541 ->shouldBeCalled()
542 ->willReturnArgument(0);
543 $this->concreteQueryBuilder->rightJoin('fromAlias', 'join', 'alias', null)
544 ->shouldBeCalled()
545 ->willReturn($this->subject);
546
547 $this->subject->rightJoin('fromAlias', 'join', 'alias');
548 }
549
550 /**
551 * @test
552 */
553 public function setQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
554 {
555 $this->connection->quoteIdentifier('aField')
556 ->shouldBeCalled()
557 ->willReturnArgument(0);
558 $this->concreteQueryBuilder->createNamedParameter('aValue', Argument::cetera())
559 ->shouldBeCalled()
560 ->willReturn(':dcValue1');
561 $this->concreteQueryBuilder->set('aField', ':dcValue1')
562 ->shouldBeCalled()
563 ->willReturn($this->subject);
564
565 $this->subject->set('aField', 'aValue');
566 }
567
568 /**
569 * @test
570 */
571 public function setWithoutNamedParameterQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
572 {
573 $this->connection->quoteIdentifier('aField')
574 ->shouldBeCalled()
575 ->willReturnArgument(0);
576 $this->concreteQueryBuilder->createNamedParameter(Argument::cetera())->shouldNotBeCalled();
577 $this->concreteQueryBuilder->set('aField', 'aValue')
578 ->shouldBeCalled()
579 ->willReturn($this->subject);
580
581 $this->subject->set('aField', 'aValue', false);
582 }
583
584 /**
585 * @test
586 */
587 public function whereDelegatesToConcreteQueryBuilder()
588 {
589 $this->concreteQueryBuilder->where('uid=1', 'type=9')
590 ->shouldBeCalled()
591 ->willReturn($this->subject);
592
593 $this->subject->where('uid=1', 'type=9');
594 }
595
596 /**
597 * @test
598 */
599 public function andWhereDelegatesToConcreteQueryBuilder()
600 {
601 $this->concreteQueryBuilder->andWhere('uid=1', 'type=9')
602 ->shouldBeCalled()
603 ->willReturn($this->subject);
604
605 $this->subject->andWhere('uid=1', 'type=9');
606 }
607
608 /**
609 * @test
610 */
611 public function orWhereDelegatesToConcreteQueryBuilder()
612 {
613 $this->concreteQueryBuilder->orWhere('uid=1', 'type=9')
614 ->shouldBeCalled()
615 ->willReturn($this->subject);
616
617 $this->subject->orWhere('uid=1', 'type=9');
618 }
619
620 /**
621 * @test
622 */
623 public function groupByQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
624 {
625 $this->connection->quoteIdentifiers(['aField', 'anotherField'])
626 ->shouldBeCalled()
627 ->willReturnArgument(0);
628 $this->concreteQueryBuilder->groupBy('aField', 'anotherField')
629 ->shouldBeCalled()
630 ->willReturn($this->subject);
631
632 $this->subject->groupBy('aField', 'anotherField');
633 }
634
635 /**
636 * @test
637 */
638 public function addGroupByQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
639 {
640 $this->connection->quoteIdentifiers(['aField', 'anotherField'])
641 ->shouldBeCalled()
642 ->willReturnArgument(0);
643 $this->concreteQueryBuilder->addGroupBy('aField', 'anotherField')
644 ->shouldBeCalled()
645 ->willReturn($this->subject);
646
647 $this->subject->addGroupBy('aField', 'anotherField');
648 }
649
650 /**
651 * @test
652 */
653 public function setValueQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
654 {
655 $this->connection->quoteIdentifier('aField')
656 ->shouldBeCalled()
657 ->willReturnArgument(0);
658 $this->concreteQueryBuilder->createNamedParameter('aValue', Argument::cetera())
659 ->shouldBeCalled()
660 ->willReturn(':dcValue1');
661 $this->concreteQueryBuilder->setValue('aField', ':dcValue1')
662 ->shouldBeCalled()
663 ->willReturn($this->subject);
664
665 $this->subject->setValue('aField', 'aValue');
666 }
667
668 /**
669 * @test
670 */
671 public function setValueWithoudNamedParameterQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
672 {
673 $this->connection->quoteIdentifier('aField')
674 ->shouldBeCalled()
675 ->willReturnArgument(0);
676 $this->concreteQueryBuilder->setValue('aField', 'aValue')
677 ->shouldBeCalled()
678 ->willReturn($this->subject);
679
680 $this->subject->setValue('aField', 'aValue', false);
681 }
682
683 /**
684 * @test
685 */
686 public function valuesQuotesIdentifiersAndDelegatesToConcreteQueryBuilder()
687 {
688 $this->connection->quoteColumnValuePairs(['aField' => ':dcValue1', 'aValue' => ':dcValue2'])
689 ->shouldBeCalled()
690 ->willReturnArgument(0);
691 $this->concreteQueryBuilder->createNamedParameter(1, Argument::cetera())
692 ->shouldBeCalled()
693 ->willReturn(':dcValue1');
694 $this->concreteQueryBuilder->createNamedParameter(2, Argument::cetera())
695 ->shouldBeCalled()
696 ->willReturn(':dcValue2');
697 $this->concreteQueryBuilder->values(['aField' => ':dcValue1', 'aValue' => ':dcValue2'])
698 ->shouldBeCalled()
699 ->willReturn($this->subject);
700
701 $this->subject->values(['aField' => 1, 'aValue' => 2]);
702 }
703
704 /**
705 * @test
706 */
707 public function valuesWithoutNamedParametersQuotesIdentifiersAndDelegatesToConcreteQueryBuilder()
708 {
709 $this->connection->quoteColumnValuePairs(['aField' => 1, 'aValue' => 2])
710 ->shouldBeCalled()
711 ->willReturnArgument(0);
712 $this->concreteQueryBuilder->values(['aField' => 1, 'aValue' => 2])
713 ->shouldBeCalled()
714 ->willReturn($this->subject);
715
716 $this->subject->values(['aField' => 1, 'aValue' => 2], false);
717 }
718
719 /**
720 * @test
721 */
722 public function havingDelegatesToConcreteQueryBuilder()
723 {
724 $this->concreteQueryBuilder->having('uid=1', 'type=9')
725 ->shouldBeCalled()
726 ->willReturn($this->subject);
727
728 $this->subject->having('uid=1', 'type=9');
729 }
730
731 /**
732 * @test
733 */
734 public function andHavingDelegatesToConcreteQueryBuilder()
735 {
736 $this->concreteQueryBuilder->andHaving('uid=1', 'type=9')
737 ->shouldBeCalled()
738 ->willReturn($this->subject);
739
740 $this->subject->andHaving('uid=1', 'type=9');
741 }
742
743 /**
744 * @test
745 */
746 public function orHavingDelegatesToConcreteQueryBuilder()
747 {
748 $this->concreteQueryBuilder->orHaving('uid=1', 'type=9')
749 ->shouldBeCalled()
750 ->willReturn($this->subject);
751
752 $this->subject->orHaving('uid=1', 'type=9');
753 }
754
755 /**
756 * @test
757 */
758 public function orderByQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
759 {
760 $this->connection->quoteIdentifier('aField')
761 ->shouldBeCalled()
762 ->willReturnArgument(0);
763 $this->concreteQueryBuilder->orderBy('aField', null)
764 ->shouldBeCalled()
765 ->willReturn($this->subject);
766
767 $this->subject->orderBy('aField');
768 }
769
770 /**
771 * @test
772 */
773 public function addOrderByQuotesIdentifierAndDelegatesToConcreteQueryBuilder()
774 {
775 $this->connection->quoteIdentifier('aField')
776 ->shouldBeCalled()
777 ->willReturnArgument(0);
778 $this->concreteQueryBuilder->addOrderBy('aField', 'DESC')
779 ->shouldBeCalled()
780 ->willReturn($this->subject);
781
782 $this->subject->addOrderBy('aField', 'DESC');
783 }
784
785 /**
786 * @test
787 */
788 public function getQueryPartDelegatesToConcreteQueryBuilder()
789 {
790 $this->concreteQueryBuilder->getQueryPart('from')
791 ->shouldBeCalled()
792 ->willReturn('aTable');
793
794 $this->subject->getQueryPart('from');
795 }
796
797 /**
798 * @test
799 */
800 public function getQueryPartsDelegatesToConcreteQueryBuilder()
801 {
802 $this->concreteQueryBuilder->getQueryParts()
803 ->shouldBeCalled()
804 ->willReturn([]);
805
806 $this->subject->getQueryParts();
807 }
808
809 /**
810 * @test
811 */
812 public function resetQueryPartsDelegatesToConcreteQueryBuilder()
813 {
814 $this->concreteQueryBuilder->resetQueryParts(['select', 'from'])
815 ->shouldBeCalled()
816 ->willReturn($this->subject);
817
818 $this->subject->resetQueryParts(['select', 'from']);
819 }
820
821 /**
822 * @test
823 */
824 public function resetQueryPartDelegatesToConcreteQueryBuilder()
825 {
826 $this->concreteQueryBuilder->resetQueryPart('select')
827 ->shouldBeCalled()
828 ->willReturn($this->subject);
829
830 $this->subject->resetQueryPart('select');
831 }
832
833 /**
834 * @test
835 */
836 public function createNamedParameterDelegatesToConcreteQueryBuilder()
837 {
838 $this->concreteQueryBuilder->createNamedParameter(5, Argument::cetera())
839 ->shouldBeCalled()
840 ->willReturn(':dcValue1');
841
842 $this->subject->createNamedParameter(5);
843 }
844
845 /**
846 * @test
847 */
848 public function createPositionalParameterDelegatesToConcreteQueryBuilder()
849 {
850 $this->concreteQueryBuilder->createPositionalParameter(5, Argument::cetera())
851 ->shouldBeCalled()
852 ->willReturn('?');
853
854 $this->subject->createPositionalParameter(5);
855 }
856
857 /**
858 * @test
859 */
860 public function queryRestrictionsAreAddedForSelectOnExecute()
861 {
862 $GLOBALS['TCA']['pages']['ctrl'] = [
863 'tstamp' => 'tstamp',
864 'versioningWS' => true,
865 'delete' => 'deleted',
866 'crdate' => 'crdate',
867 'enablecolumns' => [
868 'disabled' => 'hidden',
869 ],
870 ];
871
872 $this->connection->quoteIdentifier(Argument::cetera())
873 ->willReturnArgument(0);
874 $this->connection->quoteIdentifiers(Argument::cetera())
875 ->willReturnArgument(0);
876
877 $connectionBuilder = GeneralUtility::makeInstance(
878 \Doctrine\DBAL\Query\QueryBuilder::class,
879 $this->connection->reveal()
880 );
881
882 $expressionBuilder = GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection->reveal());
883 $this->connection->getExpressionBuilder()
884 ->willReturn($expressionBuilder);
885
886 $subject = GeneralUtility::makeInstance(
887 QueryBuilder::class,
888 $this->connection->reveal(),
889 null,
890 $connectionBuilder
891 );
892
893 $subject->select('*')
894 ->from('pages')
895 ->where('uid=1');
896
897 $expectedSQL = 'SELECT * FROM pages WHERE (uid=1) AND ((pages.hidden = 0) AND (pages.deleted = 0))';
898 $this->connection->executeQuery($expectedSQL, Argument::cetera())
899 ->shouldBeCalled();
900
901 $subject->execute();
902 }
903
904 /**
905 * @test
906 */
907 public function queryRestrictionsAreAddedForCountOnExecute()
908 {
909 $GLOBALS['TCA']['pages']['ctrl'] = [
910 'tstamp' => 'tstamp',
911 'versioningWS' => true,
912 'delete' => 'deleted',
913 'crdate' => 'crdate',
914 'enablecolumns' => [
915 'disabled' => 'hidden',
916 ],
917 ];
918
919 $this->connection->quoteIdentifier(Argument::cetera())
920 ->willReturnArgument(0);
921 $this->connection->quoteIdentifiers(Argument::cetera())
922 ->willReturnArgument(0);
923
924 $connectionBuilder = GeneralUtility::makeInstance(
925 \Doctrine\DBAL\Query\QueryBuilder::class,
926 $this->connection->reveal()
927 );
928
929 $expressionBuilder = GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection->reveal());
930 $this->connection->getExpressionBuilder()
931 ->willReturn($expressionBuilder);
932
933 $subject = GeneralUtility::makeInstance(
934 QueryBuilder::class,
935 $this->connection->reveal(),
936 null,
937 $connectionBuilder
938 );
939
940 $subject->count('uid')
941 ->from('pages')
942 ->where('uid=1');
943
944 $expectedSQL = 'SELECT COUNT(uid) FROM pages WHERE (uid=1) AND ((pages.hidden = 0) AND (pages.deleted = 0))';
945 $this->connection->executeQuery($expectedSQL, Argument::cetera())
946 ->shouldBeCalled();
947
948 $subject->execute();
949 }
950
951 /**
952 * @test
953 */
954 public function queryRestrictionsAreReevaluatedOnSettingsChangeForGetSQL()
955 {
956 $GLOBALS['TCA']['pages']['ctrl'] = [
957 'tstamp' => 'tstamp',
958 'versioningWS' => true,
959 'delete' => 'deleted',
960 'crdate' => 'crdate',
961 'enablecolumns' => [
962 'disabled' => 'hidden',
963 ],
964 ];
965
966 $this->connection->quoteIdentifier(Argument::cetera())
967 ->willReturnArgument(0);
968 $this->connection->quoteIdentifiers(Argument::cetera())
969 ->willReturnArgument(0);
970 $this->connection->getExpressionBuilder()
971 ->willReturn(GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection->reveal()));
972
973 $concreteQueryBuilder = GeneralUtility::makeInstance(
974 \Doctrine\DBAL\Query\QueryBuilder::class,
975 $this->connection->reveal()
976 );
977
978 $subject = GeneralUtility::makeInstance(
979 QueryBuilder::class,
980 $this->connection->reveal(),
981 null,
982 $concreteQueryBuilder
983 );
984
985 $subject->select('*')
986 ->from('pages')
987 ->where('uid=1');
988
989 $expectedSQL = 'SELECT * FROM pages WHERE (uid=1) AND ((pages.hidden = 0) AND (pages.deleted = 0))';
990 $this->assertSame($expectedSQL, $subject->getSQL());
991
992 $subject->getQueryContext()
993 ->setIgnoreEnableFields(true)
994 ->setIgnoredEnableFields(['disabled']);
995
996 $expectedSQL = 'SELECT * FROM pages WHERE (uid=1) AND (pages.deleted = 0)';
997 $this->assertSame($expectedSQL, $subject->getSQL());
998 }
999
1000 /**
1001 * @test
1002 */
1003 public function queryRestrictionsAreReevaluatedOnSettingsChangeForExecute()
1004 {
1005 $GLOBALS['TCA']['pages']['ctrl'] = [
1006 'tstamp' => 'tstamp',
1007 'versioningWS' => true,
1008 'delete' => 'deleted',
1009 'crdate' => 'crdate',
1010 'enablecolumns' => [
1011 'disabled' => 'hidden',
1012 ],
1013 ];
1014
1015 $this->connection->quoteIdentifier(Argument::cetera())
1016 ->willReturnArgument(0);
1017 $this->connection->quoteIdentifiers(Argument::cetera())
1018 ->willReturnArgument(0);
1019 $this->connection->getExpressionBuilder()
1020 ->willReturn(GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection->reveal()));
1021
1022 $concreteQueryBuilder = GeneralUtility::makeInstance(
1023 \Doctrine\DBAL\Query\QueryBuilder::class,
1024 $this->connection->reveal()
1025 );
1026
1027 $subject = GeneralUtility::makeInstance(
1028 QueryBuilder::class,
1029 $this->connection->reveal(),
1030 null,
1031 $concreteQueryBuilder
1032 );
1033
1034 $subject->select('*')
1035 ->from('pages')
1036 ->where('uid=1');
1037
1038 $subject->getQueryContext()
1039 ->setIgnoreEnableFields(true)
1040 ->setIgnoredEnableFields(['disabled']);
1041
1042 $expectedSQL = 'SELECT * FROM pages WHERE (uid=1) AND (pages.deleted = 0)';
1043 $this->connection->executeQuery($expectedSQL, Argument::cetera())
1044 ->shouldBeCalled();
1045
1046 $subject->execute();
1047
1048 $subject->getQueryContext()
1049 ->setIgnoreEnableFields(false);
1050
1051 $expectedSQL = 'SELECT * FROM pages WHERE (uid=1) AND ((pages.hidden = 0) AND (pages.deleted = 0))';
1052 $this->connection->executeQuery($expectedSQL, Argument::cetera())
1053 ->shouldBeCalled();
1054
1055 $subject->execute();
1056 }
1057 }