‪TYPO3CMS  10.4
TcaSelectItemsTest.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Doctrine\DBAL\DBALException;
19 use Doctrine\DBAL\Driver\Statement;
20 use Prophecy\Argument;
21 use Prophecy\Prophecy\ObjectProphecy;
47 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
48 
52 class ‪TcaSelectItemsTest extends UnitTestCase
53 {
57  protected function ‪setUp(): void
58  {
59  parent::setUp();
60  // Default LANG prophecy just returns incoming value as label if calling ->sL()
61  $languageServiceProphecy = $this->prophesize(LanguageService::class);
62  $languageServiceProphecy->loadSingleTableDescription(Argument::cetera())->willReturn(null);
63  $languageServiceProphecy->sL(Argument::cetera())->willReturnArgument(0);
64  ‪$GLOBALS['LANG'] = $languageServiceProphecy->reveal();
65 
66  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
67  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
68 
69  $cacheManagerProphecy = $this->prophesize(CacheManager::class);
70  $cacheProphecy = $this->prophesize(FrontendInterface::class);
71  $cacheManagerProphecy->getCache('runtime')->willReturn($cacheProphecy->reveal());
72  $cacheProphecy->get(Argument::cetera())->willReturn(false);
73  $cacheProphecy->set(Argument::cetera())->willReturn(false);
74  GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
75 
76  $iconRegistryProphecy = $this->prophesize(IconRegistry::class);
77  GeneralUtility::setSingletonInstance(IconRegistry::class, $iconRegistryProphecy->reveal());
78  $iconFactoryProphecy = $this->prophesize(IconFactory::class);
79  GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
80  }
81 
85  protected function ‪tearDown(): void
86  {
87  GeneralUtility::purgeInstances();
88  parent::tearDown();
89  }
90 
98  protected function ‪mockDatabaseConnection($tableName = 'fTable'): array
99  {
100  $connectionProphet = $this->prophesize(Connection::class);
101  $connectionProphet->quote(Argument::cetera())->will(function ($arguments) {
102  return "'" . $arguments[0] . "'";
103  });
104  $connectionProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
105  return '`' . $arguments[0] . '`';
106  });
107 
108  $restrictionProphet = $this->prophesize(DefaultRestrictionContainer::class);
109  $restrictionProphet->removeAll()->willReturn($restrictionProphet->reveal());
110  $restrictionProphet->add(Argument::cetera())->willReturn($restrictionProphet->reveal());
111 
112  $queryBuilderProphet = $this->prophesize(QueryBuilder::class);
113  $queryBuilderProphet->expr()->willReturn(
114  GeneralUtility::makeInstance(ExpressionBuilder::class, $connectionProphet->reveal())
115  );
116  $queryBuilderProphet->getRestrictions()->willReturn($restrictionProphet->reveal());
117  $queryBuilderProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
118  return '`' . $arguments[0] . '`';
119  });
120 
121  $connectionPoolProphet = $this->prophesize(ConnectionPool::class);
122  $connectionPoolProphet->getConnectionForTable($tableName)
123  ->willReturn($connectionProphet->reveal());
124  $connectionPoolProphet->getQueryBuilderForTable($tableName)
125  ->shouldBeCalled()
126  ->willReturn($queryBuilderProphet->reveal());
127 
128  return [$queryBuilderProphet, $connectionPoolProphet, $connectionProphet, $restrictionProphet];
129  }
130 
136  {
137  [$queryBuilderProphet, $connectionPoolProphet] = $this->‪mockDatabaseConnection('foreignTable');
138 
140  $statementProphet = $this->prophesize(Statement::class);
141  $statementProphet->fetch()->shouldBeCalled();
142 
143  $queryBuilderProphet->select('foreignTable.uid')
144  ->shouldBeCalled()
145  ->willReturn($queryBuilderProphet->reveal());
146  $queryBuilderProphet->from('foreignTable')
147  ->shouldBeCalled()
148  ->willReturn($queryBuilderProphet->reveal());
149  $queryBuilderProphet->from('pages')
150  ->shouldBeCalled()
151  ->willReturn($queryBuilderProphet->reveal());
152  $queryBuilderProphet->where('')
153  ->shouldBeCalled()
154  ->willReturn($queryBuilderProphet->reveal());
155  $queryBuilderProphet->andWhere(' 1=1')
156  ->shouldBeCalled()
157  ->willReturn($queryBuilderProphet->reveal());
158  $queryBuilderProphet->andWhere('`pages.uid` = `foreignTable.pid`')
159  ->shouldBeCalled()
160  ->willReturn($queryBuilderProphet->reveal());
161  $queryBuilderProphet->execute()
162  ->shouldBeCalled()
163  ->willReturn($statementProphet->reveal());
164 
165  // Two instances are needed due to the push/pop behavior of addInstance()
166  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
167  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
168  }
169 
173  public function ‪addDataKeepExistingItems(): void
174  {
175  $input = [
176  'tableName' => 'aTable',
177  'processedTca' => [
178  'columns' => [
179  'aField' => [
180  'config' => [
181  'type' => 'radio',
182  'items' => [
183  0 => [
184  'foo',
185  'bar',
186  ],
187  ],
188  ],
189  ],
190  'anotherField' => [
191  'config' => [
192  'type' => 'group',
193  'items' => [
194  0 => [
195  'foo',
196  'bar',
197  ],
198  ],
199  ],
200  ],
201  ],
202  ],
203  ];
204 
205  $expected = $input;
206  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
207  }
208 
213  {
214  $input = [
215  'tableName' => 'aTable',
216  'processedTca' => [
217  'columns' => [
218  'aField' => [
219  'config' => [
220  'type' => 'select',
221  'renderType' => 'selectSingle',
222  'items' => [
223  0 => 'foo',
224  ],
225  ],
226  ],
227  ],
228  ],
229  ];
230 
231  $this->expectException(\UnexpectedValueException::class);
232  $this->expectExceptionCode(1439288036);
233 
234  (new ‪TcaSelectItems())->addData($input);
235  }
236 
240  public function ‪addDataTranslatesItemLabels(): void
241  {
242  $input = [
243  'tableName' => 'aTable',
244  'databaseRow' => [
245  'aField' => 'aValue',
246  ],
247  'processedTca' => [
248  'columns' => [
249  'aField' => [
250  'config' => [
251  'type' => 'select',
252  'renderType' => 'selectSingle',
253  'items' => [
254  0 => [
255  0 => 'aLabel',
256  1 => 'aValue',
257  ],
258  ],
259  'maxitems' => 99999,
260  ],
261  ],
262  ],
263  ],
264  ];
265 
267  $languageService = $this->prophesize(LanguageService::class);
268  ‪$GLOBALS['LANG'] = $languageService->reveal();
269  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue')->willReturn('INVALID VALUE "%s"');
270 
271  $languageService->sL('aLabel')->shouldBeCalled()->willReturn('translated');
272 
273  $expected = $input;
274  $expected['processedTca']['columns']['aField']['config']['items'][0][0] = 'translated';
275  $expected['processedTca']['columns']['aField']['config']['items'][0][2] = null;
276  $expected['processedTca']['columns']['aField']['config']['items'][0][3] = null;
277  $expected['processedTca']['columns']['aField']['config']['items'][0][4] = null;
278 
279  $expected['databaseRow']['aField'] = ['aValue'];
280 
281  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
282  }
283 
288  {
289  $input = [
290  'tableName' => 'aTable',
291  'databaseRow' => [
292  'aField' => 'aValue',
293  ],
294  'processedTca' => [
295  'columns' => [
296  'aField' => [
297  'config' => [
298  'type' => 'select',
299  'renderType' => 'selectSingle',
300  'items' => [
301  [
302  'aLabel',
303  'aValue',
304  'an-icon-reference',
305  'non-existing-group',
306  null,
307  ],
308  [
309  'anotherLabel',
310  'anotherValue',
311  'an-icon-reference',
312  'example-group',
313  null,
314  ],
315  ],
316  'itemGroups' => [
317  'example-group' => 'My Example Group'
318  ],
319  'maxitems' => 99999,
320  ],
321  ],
322  ],
323  ],
324  ];
325 
326  $expected = $input;
327  $expected['databaseRow']['aField'] = ['aValue'];
328  $expected['processedTca']['columns']['aField']['config']['items'] = [
329  [
330  'My Example Group',
331  '--div--',
332  null,
333  'example-group',
334  null,
335  ],
336  [
337  'anotherLabel',
338  'anotherValue',
339  'an-icon-reference',
340  'example-group',
341  null,
342  ], [
343  'non-existing-group',
344  '--div--',
345  null,
346  'non-existing-group',
347  null,
348  ],
349  [
350  'aLabel',
351  'aValue',
352  'an-icon-reference',
353  'non-existing-group',
354  null,
355  ],
356  ];
357 
358  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
359  }
360 
364  public function ‪addDataKeepsIconFromItem(): void
365  {
366  $input = [
367  'tableName' => 'aTable',
368  'databaseRow' => [
369  'aField' => 'aValue',
370  ],
371  'processedTca' => [
372  'columns' => [
373  'aField' => [
374  'config' => [
375  'type' => 'select',
376  'renderType' => 'selectSingle',
377  'items' => [
378  0 => [
379  0 => 'aLabel',
380  1 => 'aValue',
381  2 => 'an-icon-reference',
382  3 => null,
383  4 => null,
384  ],
385  ],
386  'maxitems' => 99999,
387  ],
388  ],
389  ],
390  ],
391  ];
392 
393  $expected = $input;
394  $expected['databaseRow']['aField'] = ['aValue'];
395 
396  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
397  }
398 
403  {
404  $input = [
405  'tableName' => 'aTable',
406  'processedTca' => [
407  'columns' => [
408  'aField' => [
409  'config' => [
410  'type' => 'select',
411  'renderType' => 'selectSingle',
412  'special' => 'anUnknownValue',
413  ],
414  ],
415  ],
416  ],
417  ];
418 
419  $this->expectException(\UnexpectedValueException::class);
420  $this->expectExceptionCode(1439298496);
421 
422  (new ‪TcaSelectItems())->addData($input);
423  }
424 
429  {
430  $input = [
431  'databaseRow' => [
432  'aField' => '',
433  ],
434  'tableName' => 'aTable',
435  'processedTca' => [
436  'columns' => [
437  'aField' => [
438  'config' => [
439  'type' => 'select',
440  'renderType' => 'selectSingle',
441  'special' => 'tables',
442  'maxitems' => 99999,
443  ],
444  ],
445  ],
446  ],
447  ];
448  ‪$GLOBALS['TCA'] = [
449  'notInResult' => [
450  'ctrl' => [
451  'adminOnly' => true,
452  ],
453  ],
454  'aTable' => [
455  'ctrl' => [
456  'title' => 'aTitle',
457  ],
458  ],
459  ];
460  ‪$GLOBALS['TCA_DESCR']['aTable']['columns']['']['description'] = 'aDescription';
461 
463  $languageService = $this->prophesize(LanguageService::class);
464  ‪$GLOBALS['LANG'] = $languageService->reveal();
465  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue')->willReturn('INVALID VALUE "%s"');
466  $languageService->sL(Argument::containingString('INVALID VALUE'))->willReturnArgument(0);
467 
468  $languageService->sL('aDescription')->shouldBeCalled()->willReturnArgument(0);
469  $languageService->sL('aTitle')->shouldBeCalled()->willReturnArgument(0);
470  $languageService->loadSingleTableDescription('aTable')->shouldBeCalled();
471 
472  $expected = $input;
473  $expected['databaseRow']['aField'] = [];
474  $expected['processedTca']['columns']['aField']['config']['items'] = [
475  0 => [
476  0 => 'aTitle',
477  1 => 'aTable',
478  2 => null,
479  3 => null,
480  4 => 'aDescription',
481  ]
482  ];
483 
484  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
485  }
486 
491  {
492  $input = [
493  'databaseRow' => [
494  'aField' => 'aValue',
495  ],
496  'tableName' => 'aTable',
497  'processedTca' => [
498  'columns' => [
499  'aField' => [
500  'config' => [
501  'type' => 'select',
502  'renderType' => 'selectSingle',
503  'special' => 'pagetypes',
504  'items' => [],
505  'maxitems' => 99999,
506  ],
507  ],
508  ],
509  ],
510  ];
511  ‪$GLOBALS['TCA'] = [
512  'pages' => [
513  'columns' => [
514  'doktype' => [
515  'config' => [
516  'items' => [
517  0 => [
518  0 => 'aLabel',
519  1 => 'aValue',
520  ],
521  ],
522  ],
523  ],
524  ],
525  ],
526  ];
527 
529  $languageService = $this->prophesize(LanguageService::class);
530  ‪$GLOBALS['LANG'] = $languageService->reveal();
531  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue')->willReturn('INVALID VALUE "%s"');
532 
533  $languageService->sL('aLabel')->shouldBeCalled()->willReturnArgument(0);
534 
535  $expected = $input;
536  $expected['databaseRow']['aField'] = ['aValue'];
537  $expected['processedTca']['columns']['aField']['config']['items'] = [
538  0 => [
539  0 => 'aLabel',
540  1 => 'aValue',
541  2 => null,
542  3 => null,
543  4 => null,
544  ]
545  ];
546 
547  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
548  }
549 
554  {
555  return [
556  'Table with exclude and non exclude field returns exclude item' => [
557  [
558  // input tca
559  'fooTable' => [
560  'ctrl' => [
561  'title' => 'fooTableTitle',
562  ],
563  'columns' => [
564  'bar' => [
565  'label' => 'barColumnTitle',
566  'exclude' => 1
567  ],
568  'baz' => [
569  'label' => 'bazColumnTitle',
570  ],
571  ],
572  ],
573  ],
574  [
575  // expected items
576  0 => [
577  0 => 'fooTableTitle',
578  1 => '--div--',
579  2 => null,
580  3 => null,
581  4 => null,
582  ],
583  1 => [
584  0 => 'barColumnTitle (bar)',
585  1 => 'fooTable:bar',
586  2 => 'empty-empty',
587  3 => null,
588  4 => 'aDescription',
589  ],
590  ],
591  ],
592  'Root level table with ignored root level restriction returns exclude item' => [
593  [
594  // input tca
595  'fooTable' => [
596  'ctrl' => [
597  'title' => 'fooTableTitle',
598  'rootLevel' => 1,
599  'security' => [
600  'ignoreRootLevelRestriction' => true,
601  ],
602  ],
603  'columns' => [
604  'bar' => [
605  'label' => 'barColumnTitle',
606  'exclude' => true,
607  ],
608  ],
609  ],
610  ],
611  [
612  // expected items
613  0 => [
614  0 => 'fooTableTitle',
615  1 => '--div--',
616  2 => null,
617  3 => null,
618  4 => null,
619  ],
620  1 => [
621  0 => 'barColumnTitle (bar)',
622  1 => 'fooTable:bar',
623  2 => 'empty-empty',
624  3 => null,
625  4 => 'aDescription',
626  ],
627  ],
628  ],
629  'Root level table without ignored root level restriction returns no item' => [
630  [
631  // input tca
632  'fooTable' => [
633  'ctrl' => [
634  'title' => 'fooTableTitle',
635  'rootLevel' => 1,
636  ],
637  'columns' => [
638  'bar' => [
639  'label' => 'barColumnTitle',
640  'exclude' => true,
641  ],
642  ],
643  ],
644  ],
645  [
646  // no items
647  ],
648  ],
649  'Admin table returns no item' => [
650  [
651  // input tca
652  'fooTable' => [
653  'ctrl' => [
654  'title' => 'fooTableTitle',
655  'adminOnly' => true,
656  ],
657  'columns' => [
658  'bar' => [
659  'label' => 'barColumnTitle',
660  'exclude' => true,
661  ],
662  ],
663  ],
664  ],
665  [
666  // no items
667  ],
668  ],
669  ];
670  }
671 
676  public function ‪addDataAddsExcludeFieldsWithSpecialExclude(‪$tca, $expectedItems): void
677  {
678  $input = [
679  'tableName' => 'aTable',
680  'databaseRow' => [],
681  'processedTca' => [
682  'columns' => [
683  'aField' => [
684  'config' => [
685  'type' => 'select',
686  'renderType' => 'selectSingle',
687  'special' => 'exclude',
688  ],
689  ],
690  ],
691  ],
692  ];
693  ‪$GLOBALS['TCA'] = ‪$tca;
694  ‪$GLOBALS['TCA_DESCR']['fooTable']['columns']['bar']['description'] = 'aDescription';
695 
696  $result = (new ‪TcaSelectItems())->addData($input);
697 
698  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
699  }
700 
705  {
706  $input = [
707  'tableName' => 'aTable',
708  'databaseRow' => [],
709  'processedTca' => [
710  'columns' => [
711  'aField' => [
712  'config' => [
713  'type' => 'select',
714  'renderType' => 'selectSingle',
715  'special' => 'exclude',
716  ],
717  ],
718  ],
719  ],
720  ];
721 
722  ‪$GLOBALS['TCA'] = [
723  'fooTable' => [
724  'ctrl' => [
725  'title' => 'fooTableTitle',
726  ],
727  'columns' => [
728  'aFlexField' => [
729  'label' => 'aFlexFieldTitle',
730  'config' => [
731  'type' => 'flex',
732  'title' => 'title',
733  'ds' => [
734  'dummy' => '
735  <T3DataStructure>
736  <ROOT>
737  <type>array</type>
738  <el>
739  <input1>
740  <TCEforms>
741  <label>flexInputLabel</label>
742  <exclude>1</exclude>
743  <config>
744  <type>input</type>
745  <size>23</size>
746  </config>
747  </TCEforms>
748  </input1>
749  </el>
750  </ROOT>
751  </T3DataStructure>
752  ',
753  ],
754  ],
755  ],
756  ],
757  ],
758  ];
759 
760  $expectedItems = [
761  0 => [
762  0 => 'fooTableTitle aFlexFieldTitle dummy',
763  1 => '--div--',
764  2 => null,
765  3 => null,
766  4 => null,
767  ],
768  1 => [
769  0 => 'flexInputLabel (input1)',
770  1 => 'fooTable:aFlexField;dummy;sDEF;input1',
771  2 => 'empty-empty',
772  3 => null,
773  4 => null,
774  ],
775  ];
776 
777  $result = (new ‪TcaSelectItems())->addData($input);
778 
779  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
780  }
781 
786  {
787  $input = [
788  'tableName' => 'aTable',
789  'databaseRow' => [],
790  'processedTca' => [
791  'columns' => [
792  'aField' => [
793  'config' => [
794  'type' => 'select',
795  'renderType' => 'selectSingle',
796  'special' => 'explicitValues',
797  ],
798  ],
799  ],
800  ],
801  ];
802 
803  ‪$GLOBALS['TCA'] = [
804  'fooTable' => [
805  'ctrl' => [
806  'title' => 'fooTableTitle',
807  ],
808  'columns' => [
809  'aField' => [
810  'label' => 'aFieldTitle',
811  'config' => [
812  'type' => 'select',
813  'renderType' => 'selectSingle',
814  'authMode' => 'explicitAllow',
815  'items' => [
816  0 => [
817  'anItemTitle',
818  'anItemValue',
819  ],
820  ]
821  ],
822  ],
823  ],
824  ],
825  ];
826 
828  $languageService = $this->prophesize(LanguageService::class);
829  ‪$GLOBALS['LANG'] = $languageService->reveal();
830  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.allow')->shouldBeCalled()->willReturn('allowMe');
831  $languageService->sL(Argument::cetera())->willReturnArgument(0);
832 
833  $expectedItems = [
834  0 => [
835  0 => 'fooTableTitle: aFieldTitle',
836  1 => '--div--',
837  2 => null,
838  3 => null,
839  4 => null,
840  ],
841  1 => [
842  0 => '[allowMe] anItemTitle',
843  1 => 'fooTable:aField:anItemValue:ALLOW',
844  2 => 'status-status-permission-granted',
845  3 => null,
846  4 => null,
847  ],
848  ];
849 
850  $result = (new ‪TcaSelectItems())->addData($input);
851 
852  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
853  }
854 
859  {
860  $input = [
861  'tableName' => 'aTable',
862  'databaseRow' => [],
863  'processedTca' => [
864  'columns' => [
865  'aField' => [
866  'config' => [
867  'type' => 'select',
868  'renderType' => 'selectSingle',
869  'special' => 'explicitValues',
870  ],
871  ],
872  ],
873  ],
874  ];
875 
876  ‪$GLOBALS['TCA'] = [
877  'fooTable' => [
878  'ctrl' => [
879  'title' => 'fooTableTitle',
880  ],
881  'columns' => [
882  'aField' => [
883  'label' => 'aFieldTitle',
884  'config' => [
885  'type' => 'select',
886  'renderType' => 'selectSingle',
887  'authMode' => 'explicitDeny',
888  'items' => [
889  0 => [
890  'anItemTitle',
891  'anItemValue',
892  ],
893  ]
894  ],
895  ],
896  ],
897  ],
898  ];
899 
901  $languageService = $this->prophesize(LanguageService::class);
902  ‪$GLOBALS['LANG'] = $languageService->reveal();
903  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.deny')->shouldBeCalled()->willReturn('denyMe');
904  $languageService->sL(Argument::cetera())->willReturnArgument(0);
905 
906  $expectedItems = [
907  0 => [
908  0 => 'fooTableTitle: aFieldTitle',
909  1 => '--div--',
910  2 => null,
911  3 => null,
912  4 => null,
913  ],
914  1 => [
915  0 => '[denyMe] anItemTitle',
916  1 => 'fooTable:aField:anItemValue:DENY',
917  2 => 'status-status-permission-denied',
918  3 => null,
919  4 => null,
920  ],
921  ];
922 
923  $result = (new ‪TcaSelectItems())->addData($input);
924 
925  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
926  }
927 
932  {
933  $input = [
934  'tableName' => 'aTable',
935  'databaseRow' => [],
936  'processedTca' => [
937  'columns' => [
938  'aField' => [
939  'config' => [
940  'type' => 'select',
941  'renderType' => 'selectSingle',
942  'special' => 'explicitValues',
943  ],
944  ],
945  ],
946  ],
947  ];
948 
949  ‪$GLOBALS['TCA'] = [
950  'fooTable' => [
951  'ctrl' => [
952  'title' => 'fooTableTitle',
953  ],
954  'columns' => [
955  'aField' => [
956  'label' => 'aFieldTitle',
957  'config' => [
958  'type' => 'select',
959  'renderType' => 'selectSingle',
960  'authMode' => 'individual',
961  'items' => [
962  0 => [
963  'aItemTitle',
964  'aItemValue',
965  null,
966  null,
967  '',
968  'EXPL_ALLOW',
969  ],
970  // 1 is not selectable as allow and is always allowed
971  1 => [
972  'bItemTitle',
973  'bItemValue',
974  ],
975  2 => [
976  'cItemTitle',
977  'cItemValue',
978  null,
979  null,
980  '',
981  'EXPL_ALLOW',
982  ],
983  ]
984  ],
985  ],
986  ],
987  ],
988  ];
989 
991  $languageService = $this->prophesize(LanguageService::class);
992  ‪$GLOBALS['LANG'] = $languageService->reveal();
993  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.allow')->shouldBeCalled()->willReturn('allowMe');
994  $languageService->sL(Argument::cetera())->willReturnArgument(0);
995 
996  $expectedItems = [
997  0 => [
998  0 => 'fooTableTitle: aFieldTitle',
999  1 => '--div--',
1000  2 => null,
1001  3 => null,
1002  4 => null,
1003  ],
1004  1 => [
1005  0 => '[allowMe] aItemTitle',
1006  1 => 'fooTable:aField:aItemValue:ALLOW',
1007  2 => 'status-status-permission-granted',
1008  3 => null,
1009  4 => null,
1010  ],
1011  2 => [
1012  0 => '[allowMe] cItemTitle',
1013  1 => 'fooTable:aField:cItemValue:ALLOW',
1014  2 => 'status-status-permission-granted',
1015  3 => null,
1016  4 => null,
1017  ],
1018  ];
1019 
1020  $result = (new ‪TcaSelectItems())->addData($input);
1021 
1022  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
1023  }
1024 
1029  {
1030  $input = [
1031  'tableName' => 'aTable',
1032  'databaseRow' => [],
1033  'processedTca' => [
1034  'columns' => [
1035  'aField' => [
1036  'config' => [
1037  'type' => 'select',
1038  'renderType' => 'selectSingle',
1039  'special' => 'explicitValues',
1040  ],
1041  ],
1042  ],
1043  ],
1044  ];
1045 
1046  ‪$GLOBALS['TCA'] = [
1047  'fooTable' => [
1048  'ctrl' => [
1049  'title' => 'fooTableTitle',
1050  ],
1051  'columns' => [
1052  'aField' => [
1053  'label' => 'aFieldTitle',
1054  'config' => [
1055  'type' => 'select',
1056  'renderType' => 'selectSingle',
1057  'authMode' => 'individual',
1058  'items' => [
1059  0 => [
1060  'aItemTitle',
1061  'aItemValue',
1062  null,
1063  null,
1064  '',
1065  'EXPL_DENY',
1066  ],
1067  // 1 is not selectable as allow and is always allowed
1068  1 => [
1069  'bItemTitle',
1070  'bItemValue',
1071  ],
1072  2 => [
1073  'cItemTitle',
1074  'cItemValue',
1075  null,
1076  null,
1077  '',
1078  'EXPL_DENY',
1079  ],
1080  ]
1081  ],
1082  ],
1083  ],
1084  ],
1085  ];
1086 
1088  $languageService = $this->prophesize(LanguageService::class);
1089  ‪$GLOBALS['LANG'] = $languageService->reveal();
1090  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.deny')->shouldBeCalled()->willReturn('denyMe');
1091  $languageService->sL(Argument::cetera())->willReturnArgument(0);
1092 
1093  $expectedItems = [
1094  0 => [
1095  0 => 'fooTableTitle: aFieldTitle',
1096  1 => '--div--',
1097  2 => null,
1098  3 => null,
1099  4 => null,
1100  ],
1101  1 => [
1102  0 => '[denyMe] aItemTitle',
1103  1 => 'fooTable:aField:aItemValue:DENY',
1104  2 => 'status-status-permission-denied',
1105  3 => null,
1106  4 => null,
1107  ],
1108  2 => [
1109  0 => '[denyMe] cItemTitle',
1110  1 => 'fooTable:aField:cItemValue:DENY',
1111  2 => 'status-status-permission-denied',
1112  3 => null,
1113  4 => null,
1114  ],
1115  ];
1116 
1117  $result = (new ‪TcaSelectItems())->addData($input);
1118 
1119  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
1120  }
1121 
1126  {
1127  $input = [
1128  'tableName' => 'aTable',
1129  'databaseRow' => [],
1130  'processedTca' => [
1131  'columns' => [
1132  'aField' => [
1133  'config' => [
1134  'type' => 'select',
1135  'renderType' => 'selectSingle',
1136  'special' => 'languages',
1137  ],
1138  ],
1139  ],
1140  ],
1141  ];
1142 
1143  $siteFinder = $this->prophesize(SiteFinder::class);
1144  $siteFinder->getAllSites()->willReturn([
1145  new ‪Site('test', 13, [
1146  'base' => '/',
1147  'languages' => [
1148  [
1149  'title' => 'French',
1150  'languageId' => 13,
1151  'base' => '/fr/',
1152  'locale' => 'fr_FR',
1153  'flag' => 'aFlag.gif'
1154  ]
1155  ]
1156  ])
1157  ]);
1158  GeneralUtility::addInstance(SiteFinder::class, $siteFinder->reveal());
1159 
1160  $expectedItems = [
1161  0 => [
1162  0 => 'French [Site: test]',
1163  1 => 13,
1164  2 => 'flags-aFlag.gif',
1165  3 => null,
1166  4 => null,
1167  ],
1168  ];
1169 
1170  $result = (new ‪TcaSelectItems())->addData($input);
1171 
1172  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
1173  }
1174 
1179  {
1180  $input = [
1181  'tableName' => 'aTable',
1182  'databaseRow' => [],
1183  'processedTca' => [
1184  'columns' => [
1185  'aField' => [
1186  'config' => [
1187  'type' => 'select',
1188  'renderType' => 'selectSingle',
1189  'special' => 'custom',
1190  ],
1191  ],
1192  ],
1193  ],
1194  ];
1195 
1196  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['customPermOptions'] = [
1197  'aKey' => [
1198  'header' => 'aHeader',
1199  'items' => [
1200  'anItemKey' => [
1201  0 => 'anItemTitle',
1202  ],
1203  'anotherKey' => [
1204  0 => 'anotherTitle',
1205  1 => 'status-status-permission-denied',
1206  2 => 'aDescription',
1207  ],
1208  ],
1209  ]
1210  ];
1211 
1212  $expectedItems = [
1213  0 => [
1214  0 => 'aHeader',
1215  1 => '--div--',
1216  null,
1217  null,
1218  null,
1219  ],
1220  1 => [
1221  0 => 'anItemTitle',
1222  1 => 'aKey:anItemKey',
1223  2 => 'empty-empty',
1224  3 => null,
1225  4 => null,
1226  ],
1227  2 => [
1228  0 => 'anotherTitle',
1229  1 => 'aKey:anotherKey',
1230  2 => 'empty-empty',
1231  3 => null,
1232  4 => 'aDescription',
1233  ],
1234  ];
1235 
1236  $result = (new ‪TcaSelectItems())->addData($input);
1237 
1238  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
1239  }
1240 
1245  {
1246  $input = [
1247  'tableName' => 'aTable',
1248  'databaseRow' => [],
1249  'processedTca' => [
1250  'columns' => [
1251  'aField' => [
1252  'config' => [
1253  'type' => 'select',
1254  'renderType' => 'selectSingle',
1255  'special' => 'modListGroup',
1256  ],
1257  ],
1258  ],
1259  ],
1260  ];
1261 
1262  ‪$GLOBALS['TBE_MODULES'] = [];
1263 
1265  $moduleLoaderProphecy = $this->prophesize(ModuleLoader::class);
1266  GeneralUtility::addInstance(ModuleLoader::class, $moduleLoaderProphecy->reveal());
1267  $moduleLoaderProphecy->load([])->shouldBeCalled();
1268  $moduleLoaderProphecy->modListGroup = [
1269  'aModule',
1270  ];
1271  $moduleLoaderProphecy->modules = [
1272  'aModule' => [
1273  'iconIdentifier' => 'empty-empty'
1274  ]
1275  ];
1276  $moduleLoaderProphecy->getLabelsForModule('aModule')->shouldBeCalled()->willReturn([
1277  'shortdescription' => 'aModuleTabLabel',
1278  'description' => 'aModuleTabDescription',
1279  'title' => 'aModuleLabel'
1280  ]);
1281 
1282  $expectedItems = [
1283  0 => [
1284  0 => 'aModuleLabel',
1285  1 => 'aModule',
1286  2 => 'empty-empty',
1287  3 => null,
1288  4 => [
1289  'title' => 'aModuleTabLabel',
1290  'description' => 'aModuleTabDescription',
1291  ],
1292  ],
1293  ];
1294 
1295  $result = (new ‪TcaSelectItems())->addData($input);
1296 
1297  $result['processedTca']['columns']['aField']['config']['items'][0][2] = str_replace([CR, LF, "\t"], '', $result['processedTca']['columns']['aField']['config']['items'][0][2]);
1298  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
1299  }
1300 
1305  {
1306  $directory = ‪StringUtility::getUniqueId('test-') . '/';
1307  $input = [
1308  'tableName' => 'aTable',
1309  'databaseRow' => [],
1310  'processedTca' => [
1311  'columns' => [
1312  'aField' => [
1313  'config' => [
1314  'type' => 'select',
1315  'renderType' => 'selectSingle',
1316  // use absolute path here to avoid fallback to public path as prefix
1317  'fileFolder' => ‪Environment::getVarPath() . '/' . $directory,
1318  'fileFolder_extList' => 'gif',
1319  'fileFolder_recursions' => 1,
1320  ],
1321  ],
1322  ],
1323  ],
1324  ];
1325 
1326  mkdir(‪Environment::getVarPath() . '/' . $directory);
1327  $this->testFilesToDelete[] = ‪Environment::getVarPath() . '/' . $directory;
1328  touch(‪Environment::getVarPath() . '/' . $directory . 'anImage.gif');
1329  touch(‪Environment::getVarPath() . '/' . $directory . 'aFile.txt');
1330  mkdir(‪Environment::getVarPath() . '/' . $directory . '/subdir');
1331  touch(‪Environment::getVarPath() . '/' . $directory . '/subdir/anotherImage.gif');
1332 
1333  $expectedItems = [
1334  0 => [
1335  0 => 'anImage.gif',
1336  1 => 'anImage.gif',
1337  2 => ‪Environment::getVarPath() . '/' . $directory . 'anImage.gif',
1338  3 => null,
1339  4 => null,
1340  ],
1341  1 => [
1342  0 => 'subdir/anotherImage.gif',
1343  1 => 'subdir/anotherImage.gif',
1344  2 => ‪Environment::getVarPath() . '/' . $directory . 'subdir/anotherImage.gif',
1345  3 => null,
1346  4 => null,
1347  ],
1348  ];
1349 
1350  $result = (new ‪TcaSelectItems())->addData($input);
1351 
1352  self::assertSame($expectedItems, $result['processedTca']['columns']['aField']['config']['items']);
1353  }
1354 
1359  {
1360  $input = [
1361  'tableName' => 'aTable',
1362  'databaseRow' => [],
1363  'processedTca' => [
1364  'columns' => [
1365  'aField' => [
1366  'config' => [
1367  'type' => 'select',
1368  'renderType' => 'selectSingle',
1369  'fileFolder' => 'EXT:non_existing/Resources/Public/',
1370  ],
1371  ],
1372  ],
1373  ],
1374  ];
1375 
1376  $this->expectException(\RuntimeException::class);
1377  $this->expectExceptionCode(1479399227);
1378  (new ‪TcaSelectItems())->addData($input);
1379  }
1380 
1385  {
1386  $input = [
1387  'databaseRow' => [
1388  'aField' => '',
1389  ],
1390  'tableName' => 'aTable',
1391  'processedTca' => [
1392  'columns' => [
1393  'aField' => [
1394  'config' => [
1395  'type' => 'select',
1396  'renderType' => 'selectSingle',
1397  'items' => [
1398  0 => [
1399  0 => 'keepMe',
1400  1 => 'keep',
1401  null,
1402  null,
1403  null,
1404  ],
1405  ],
1406  'maxitems' => 99999,
1407  ],
1408  ],
1409  ]
1410  ],
1411  'pageTsConfig' => [
1412  'TCEFORM.' => [
1413  'aTable.' => [
1414  'aField.' => [
1415  'addItems.' => [
1416  '1' => 'addMe'
1417  ],
1418  ],
1419  ],
1420  ],
1421  ],
1422  ];
1423 
1424  $expected = $input;
1425  $expected['databaseRow']['aField'] = [];
1426  $expected['processedTca']['columns']['aField']['config']['items'][1] = [
1427  0 => 'addMe',
1428  1 => '1',
1429  null,
1430  null,
1431  null,
1432  ];
1433 
1434  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
1435  }
1436 
1441  {
1442  $input = [
1443  'databaseRow' => [
1444  'aField' => '',
1445  ],
1446  'tableName' => 'aTable',
1447  'processedTca' => [
1448  'columns' => [
1449  'aField' => [
1450  'config' => [
1451  'type' => 'select',
1452  'renderType' => 'selectSingle',
1453  'items' => [
1454  0 => [
1455  0 => 'keepMe',
1456  1 => 'keep',
1457  null,
1458  null,
1459  null,
1460  ],
1461  ],
1462  'maxitems' => 99999,
1463  ],
1464  ],
1465  ]
1466  ],
1467  'pageTsConfig' => [
1468  'TCEFORM.' => [
1469  'aTable.' => [
1470  'aField.' => [
1471  'addItems.' => [
1472  'keep' => 'addMe'
1473  ],
1474  ],
1475  ],
1476  ],
1477  ],
1478  ];
1479 
1480  $expected = $input;
1481  $expected['databaseRow']['aField'] = [];
1482  $expected['processedTca']['columns']['aField']['config']['items'][1] = [
1483  0 => 'addMe',
1484  1 => 'keep',
1485  null,
1486  null,
1487  null,
1488  ];
1489 
1490  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
1491  }
1492 
1497  {
1498  return [
1499  'replace REC_FIELD' => [
1500  'AND fTable.title=\'###REC_FIELD_rowField###\'',
1501  [
1502  ['fTable.title=\'rowFieldValue\''],
1503  [' 1=1'],
1504  ['`pages.uid` = `fTable.pid`']
1505  ],
1506  [],
1507  ],
1508  'replace REC_FIELD within FlexForm' => [
1509  'AND fTable.title=###REC_FIELD_rowFieldFlexForm###',
1510  [
1511  ['fTable.title=\'rowFieldFlexFormValue\''],
1512  [' 1=1'],
1513  ['`pages.uid` = `fTable.pid`']
1514  ],
1515  [
1516  'databaseRow' => [
1517  'rowFieldThree' => [
1518  0 => 'rowFieldThreeValue'
1519  ]
1520  ],
1521  'flexParentDatabaseRow' => [
1522  'rowFieldFlexForm' => [
1523  0 => 'rowFieldFlexFormValue'
1524  ]
1525  ],
1526  ],
1527  ],
1528  'replace REC_FIELD fullQuote' => [
1529  'AND fTable.title=###REC_FIELD_rowField###',
1530  [
1531  ['fTable.title=\'rowFieldValue\''],
1532  [' 1=1'],
1533  ['`pages.uid` = `fTable.pid`']
1534  ],
1535  [],
1536  ],
1537  'replace REC_FIELD fullQuoteWithArray' => [
1538  'AND fTable.title=###REC_FIELD_rowFieldThree###',
1539  [
1540  ['fTable.title=\'rowFieldThreeValue\''],
1541  [' 1=1'],
1542  ['`pages.uid` = `fTable.pid`']
1543  ],
1544  [
1545  'databaseRow' => [
1546  'rowFieldThree' => [
1547  0 => 'rowFieldThreeValue'
1548  ]
1549  ],
1550  ],
1551  ],
1552  'replace REC_FIELD multiple markers' => [
1553  'AND fTable.title=\'###REC_FIELD_rowField###\' AND fTable.pid=###REC_FIELD_rowFieldTwo###',
1554  [
1555  ['fTable.title=\'rowFieldValue\' AND fTable.pid=\'rowFieldTwoValue\''],
1556  [' 1=1'],
1557  ['`pages.uid` = `fTable.pid`']
1558  ],
1559  [],
1560  ],
1561  'replace CURRENT_PID' => [
1562  'AND fTable.uid=###CURRENT_PID###',
1563  [
1564  ['fTable.uid=43'],
1565  [' 1=1'],
1566  ['`pages.uid` = `fTable.pid`']
1567  ],
1568  [],
1569  ],
1570  'replace CURRENT_PID within FlexForm' => [
1571  'AND fTable.uid=###CURRENT_PID###',
1572  [
1573  ['fTable.uid=77'],
1574  [' 1=1'],
1575  ['`pages.uid` = `fTable.pid`']
1576  ],
1577  [
1578  'flexParentDatabaseRow' => [
1579  'pid' => '77',
1580  ],
1581  ],
1582  ],
1583  'replace CURRENT_PID integer cast' => [
1584  'AND fTable.uid=###CURRENT_PID###',
1585  [
1586  ['fTable.uid=431'],
1587  [' 1=1'],
1588  ['`pages.uid` = `fTable.pid`']
1589  ],
1590  [
1591  'effectivePid' => '431string',
1592  ],
1593  ],
1594  'replace THIS_UID' => [
1595  'AND fTable.uid=###THIS_UID###',
1596  [
1597  ['fTable.uid=42'],
1598  [' 1=1'],
1599  ['`pages.uid` = `fTable.pid`']
1600  ],
1601  [],
1602  ],
1603  'replace THIS_UID integer cast' => [
1604  'AND fTable.uid=###THIS_UID###',
1605  [
1606  ['fTable.uid=421'],
1607  [' 1=1'],
1608  ['`pages.uid` = `fTable.pid`']
1609  ],
1610  [
1611  'databaseRow' => [
1612  'uid' => '421string',
1613  ],
1614  ],
1615  ],
1616  'replace SITEROOT' => [
1617  'AND fTable.uid=###SITEROOT###',
1618  [
1619  ['fTable.uid=44'],
1620  [' 1=1'],
1621  ['`pages.uid` = `fTable.pid`']
1622  ],
1623  [],
1624  ],
1625  'replace SITEROOT integer cast' => [
1626  'AND fTable.uid=###SITEROOT###',
1627  [
1628  ['fTable.uid=441'],
1629  [' 1=1'],
1630  ['`pages.uid` = `fTable.pid`']
1631  ],
1632  [
1633  'rootline' => [
1634  1 => [
1635  'uid' => '441string',
1636  ],
1637  ],
1638  ],
1639  ],
1640  'replace PAGE_TSCONFIG_ID' => [
1641  'AND fTable.uid=###PAGE_TSCONFIG_ID###',
1642  [
1643  ['fTable.uid=45'],
1644  [' 1=1'],
1645  ['`pages.uid` = `fTable.pid`']
1646  ],
1647  [
1648  'pageTsConfig' => [
1649  'TCEFORM.' => [
1650  'aTable.' => [
1651  'aField.' => [
1652  'PAGE_TSCONFIG_ID' => '45',
1653  ],
1654  ],
1655  ],
1656  ],
1657  ],
1658  ],
1659  'replace PAGE_TSCONFIG_ID integer cast' => [
1660  'AND fTable.uid=###PAGE_TSCONFIG_ID###',
1661  [
1662  ['fTable.uid=451'],
1663  [' 1=1'],
1664  ['`pages.uid` = `fTable.pid`']
1665  ],
1666  [
1667  'pageTsConfig' => [
1668  'TCEFORM.' => [
1669  'aTable.' => [
1670  'aField.' => [
1671  'PAGE_TSCONFIG_ID' => '451string'
1672  ],
1673  ],
1674  ],
1675  ],
1676  ],
1677  ],
1678  'replace PAGE_TSCONFIG_STR' => [
1679  'AND fTable.uid=\'###PAGE_TSCONFIG_STR###\'',
1680  [
1681  ['fTable.uid=\'46\''],
1682  [' 1=1'],
1683  ['`pages.uid` = `fTable.pid`']
1684  ],
1685  [
1686  'pageTsConfig' => [
1687  'TCEFORM.' => [
1688  'aTable.' => [
1689  'aField.' => [
1690  'PAGE_TSCONFIG_STR' => '46',
1691  ],
1692  ],
1693  ],
1694  ],
1695  ],
1696  ],
1697  'replace PAGE_TSCONFIG_IDLIST' => [
1698  'AND fTable.uid IN (###PAGE_TSCONFIG_IDLIST###)',
1699  [
1700  ['fTable.uid IN (47,48)'],
1701  [' 1=1'],
1702  ['`pages.uid` = `fTable.pid`']
1703  ],
1704  [
1705  'pageTsConfig' => [
1706  'TCEFORM.' => [
1707  'aTable.' => [
1708  'aField.' => [
1709  'PAGE_TSCONFIG_IDLIST' => '47,48',
1710  ],
1711  ],
1712  ],
1713  ],
1714  ],
1715  ],
1716  'replace PAGE_TSCONFIG_IDLIST cleans list' => [
1717  'AND fTable.uid IN (###PAGE_TSCONFIG_IDLIST###)',
1718  [
1719  ['fTable.uid IN (471,481)'],
1720  [' 1=1'],
1721  ['`pages.uid` = `fTable.pid`']
1722  ],
1723  [
1724  'pageTsConfig' => [
1725  'TCEFORM.' => [
1726  'aTable.' => [
1727  'aField.' => [
1728  'PAGE_TSCONFIG_IDLIST' => 'a, 471, b, 481, c',
1729  ],
1730  ],
1731  ],
1732  ],
1733  ],
1734  ],
1735  ];
1736  }
1737 
1742  public function ‪addDataReplacesMarkersInForeignTableClause($foreignTableWhere, $expectedWhere, array $inputOverride): void
1743  {
1744  $input = [
1745  'tableName' => 'aTable',
1746  'effectivePid' => 43,
1747  'databaseRow' => [
1748  'uid' => 42,
1749  'rowField' => 'rowFieldValue',
1750  'rowFieldTwo' => 'rowFieldTwoValue',
1751  ],
1752  'processedTca' => [
1753  'columns' => [
1754  'aField' => [
1755  'config' => [
1756  'type' => 'select',
1757  'renderType' => 'selectSingle',
1758  'foreign_table' => 'fTable',
1759  'foreign_table_where' => $foreignTableWhere,
1760  ],
1761  ],
1762  ]
1763  ],
1764  'rootline' => [
1765  2 => [
1766  'uid' => 999,
1767  'is_siteroot' => 0,
1768  ],
1769  1 => [
1770  'uid' => 44,
1771  'is_siteroot' => 1,
1772  ],
1773  0 => [
1774  'uid' => 0,
1775  'is_siteroot' => null,
1776  ],
1777  ],
1778  'pageTsConfig' => [],
1779  ];
1780  ‪ArrayUtility::mergeRecursiveWithOverrule($input, $inputOverride);
1781 
1782  ‪$GLOBALS['TCA']['fTable'] = [];
1783 
1784  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
1785  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
1786  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
1787 
1788  [$queryBuilderProphet, $connectionPoolProphet] = $this->‪mockDatabaseConnection();
1789 
1791  $statementProphet = $this->prophesize(Statement::class);
1792 
1793  $queryBuilderProphet->select('fTable.uid')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1794  $queryBuilderProphet->from('fTable')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1795  $queryBuilderProphet->from('pages')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1796  $queryBuilderProphet->where(...array_shift($expectedWhere))->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1797  $queryBuilderProphet->execute()->shouldBeCalled()->willReturn($statementProphet->reveal());
1798 
1799  while ($constraint = array_shift($expectedWhere)) {
1800  $queryBuilderProphet->andWhere(...$constraint)
1801  ->shouldBeCalled()
1802  ->willReturn($queryBuilderProphet->reveal());
1803  }
1804 
1805  // Two instances are needed due to the push/pop behavior of addInstance()
1806  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
1807  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
1808 
1810  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
1811  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
1812  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
1813 
1814  (new ‪TcaSelectItems())->addData($input);
1815  }
1816 
1821  {
1822  $input = [
1823  'tableName' => 'aTable',
1824  'processedTca' => [
1825  'columns' => [
1826  'aField' => [
1827  'config' => [
1828  'type' => 'select',
1829  'renderType' => 'selectSingle',
1830  'foreign_table' => 'fTable',
1831  ],
1832  ],
1833  ]
1834  ],
1835  ];
1836 
1837  $this->expectException(\UnexpectedValueException::class);
1838  $this->expectExceptionCode(1439569743);
1839 
1840  (new ‪TcaSelectItems())->addData($input);
1841  }
1842 
1847  {
1848  $input = [
1849  'tableName' => 'aTable',
1850  'effectivePid' => 42,
1851  'databaseRow' => [
1852  'uid' => 23,
1853  ],
1854  'processedTca' => [
1855  'columns' => [
1856  'aField' => [
1857  'config' => [
1858  'type' => 'select',
1859  'renderType' => 'selectSingle',
1860  'foreign_table' => 'fTable',
1861  'foreign_table_where' => '
1862  AND ftable.uid=1
1863  GROUP BY groupField1, groupField2
1864  ORDER BY orderField
1865  LIMIT 1,2',
1866  ],
1867  ],
1868  ]
1869  ],
1870  'rootline' => [],
1871  ];
1872 
1873  ‪$GLOBALS['TCA']['fTable'] = [];
1874 
1875  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
1876  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
1877  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
1878 
1880  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
1881  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
1882  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
1883 
1884  [$queryBuilderProphet, $connectionPoolProphet] = $this->‪mockDatabaseConnection();
1885 
1887  $statementProphet = $this->prophesize(Statement::class);
1888 
1889  $queryBuilderProphet->select('fTable.uid')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1890  $queryBuilderProphet->from('fTable')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1891  $queryBuilderProphet->from('pages')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1892  $queryBuilderProphet->groupBy('groupField1', 'groupField2')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1893  $queryBuilderProphet->addOrderBy('orderField', null)->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1894  $queryBuilderProphet->setFirstResult(1)->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1895  $queryBuilderProphet->setMaxResults(2)->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1896  $queryBuilderProphet->where('ftable.uid=1')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1897  $queryBuilderProphet->andWhere(' 1=1')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1898  $queryBuilderProphet->andWhere('`pages.uid` = `fTable.pid`')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1899  $queryBuilderProphet->execute()->shouldBeCalled()->willReturn($statementProphet->reveal());
1900 
1901  // Two instances are needed due to the push/pop behavior of addInstance()
1902  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
1903  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
1904 
1905  (new ‪TcaSelectItems())->addData($input);
1906  }
1907 
1912  {
1913  $input = [
1914  'databaseRow' => [
1915  'uid' => 23,
1916  'aField' => '',
1917  ],
1918  'tableName' => 'aTable',
1919  'effectivePid' => 42,
1920  'processedTca' => [
1921  'columns' => [
1922  'aField' => [
1923  'config' => [
1924  'type' => 'select',
1925  'renderType' => 'selectSingle',
1926  'foreign_table' => 'fTable',
1927  'items' => [
1928  0 => [
1929  0 => 'itemLabel',
1930  1 => 'itemValue',
1931  2 => null,
1932  3 => null,
1933  4 => null,
1934  ],
1935  ],
1936  'maxitems' => 99999,
1937  ],
1938  ],
1939  ]
1940  ],
1941  'rootline' => [],
1942  ];
1943 
1944  ‪$GLOBALS['TCA']['fTable'] = [];
1945 
1947  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
1948  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
1949  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
1950 
1951  [$queryBuilderProphet, $connectionPoolProphet] = $this->‪mockDatabaseConnection();
1952 
1953  $queryBuilderProphet->select('fTable.uid')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1954  $queryBuilderProphet->from('fTable')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1955  $queryBuilderProphet->from('pages')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1956  $queryBuilderProphet->where('')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1957  $queryBuilderProphet->andWhere(' 1=1')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1958  $queryBuilderProphet->andWhere('`pages.uid` = `fTable.pid`')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1959 
1960  $prevException = new DBALException('Invalid table name', 1476045274);
1961  $exception = new DBALException('Driver error', 1476045971, $prevException);
1962 
1963  $queryBuilderProphet->execute()->shouldBeCalled()->willThrow($exception);
1964 
1965  // Two instances are needed due to the push/pop behavior of addInstance()
1966  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
1967  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
1968 
1970  $flashMessage = $this->prophesize(FlashMessage::class);
1971  GeneralUtility::addInstance(FlashMessage::class, $flashMessage->reveal());
1973  $flashMessageService = $this->prophesize(FlashMessageService::class);
1974  GeneralUtility::setSingletonInstance(FlashMessageService::class, $flashMessageService->reveal());
1976  $flashMessageQueue = $this->prophesize(FlashMessageQueue::class);
1977  $flashMessageService->getMessageQueueByIdentifier(Argument::cetera())->willReturn($flashMessageQueue->reveal());
1978 
1979  $flashMessageQueue->enqueue($flashMessage)->shouldBeCalled();
1980 
1981  $expected = $input;
1982  $expected['databaseRow']['aField'] = [];
1983 
1984  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
1985  }
1986 
1990  private function ‪mockForeignTableItemsQuery(): array
1991  {
1992  [$queryBuilderProphet, $connectionPoolProphet] = $this->‪mockDatabaseConnection();
1993 
1995  $statementProphet = $this->prophesize(Statement::class);
1996 
1997  $queryBuilderProphet->select('fTable.uid', 'fTable.labelField')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1998  $queryBuilderProphet->from('fTable')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
1999  $queryBuilderProphet->from('pages')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2000  $queryBuilderProphet->where('')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2001  $queryBuilderProphet->andWhere(' 1=1')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2002  $queryBuilderProphet->andWhere('`pages.uid` = `fTable.pid`')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2003  $queryBuilderProphet->execute()->shouldBeCalled()->willReturn($statementProphet->reveal());
2004 
2005  return [$connectionPoolProphet, $statementProphet];
2006  }
2007 
2012  {
2013  $input = [
2014  'databaseRow' => [
2015  'uid' => 5,
2016  'aField' => '',
2017  ],
2018  'tableName' => 'aTable',
2019  'effectivePid' => 42,
2020  'processedTca' => [
2021  'columns' => [
2022  'aField' => [
2023  'config' => [
2024  'type' => 'select',
2025  'renderType' => 'selectSingle',
2026  'foreign_table' => 'fTable',
2027  'foreign_table_prefix' => 'aPrefix',
2028  'items' => [],
2029  'maxitems' => 99999,
2030  ],
2031  ],
2032  ]
2033  ],
2034  'rootline' => [],
2035  ];
2036 
2037  ‪$GLOBALS['TCA']['fTable'] = [
2038  'ctrl' => [
2039  'label' => 'labelField',
2040  ],
2041  'columns' => [],
2042  ];
2043 
2044  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
2045  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
2046  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
2047 
2048  $iconFactoryProphecy = $this->prophesize(IconFactory::class);
2049  GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
2050 
2052  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
2053  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
2054  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
2055 
2056  [$connectionPoolProphet, $statementProphet] = $this->‪mockForeignTableItemsQuery();
2057 
2058  // Two instances are needed due to the push/pop behavior of addInstance()
2059  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
2060  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
2061 
2062  $counter = 0;
2063  $statementProphet->fetch()->shouldBeCalled()->will(function (‪$args) use (&$counter) {
2064  $counter++;
2065  if ($counter >= 3) {
2066  return false;
2067  }
2068  return [
2069  'uid' => $counter,
2070  'pid' => 23,
2071  'labelField' => 'aLabel',
2072  'aValue' => 'bar,',
2073  ];
2074  });
2075 
2076  $expected = $input;
2077  $expected['processedTca']['columns']['aField']['config']['items'] = [
2078  0 => [
2079  0 => 'aPrefix[LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title]',
2080  1 => 1,
2081  2 => null,
2082  3 => null,
2083  4 => null,
2084  ],
2085  1 => [
2086  0 => 'aPrefix[LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title]',
2087  1 => 2,
2088  2 => null,
2089  3 => null,
2090  4 => null,
2091  ],
2092  ];
2093 
2094  $expected['databaseRow']['aField'] = [];
2095 
2096  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2097  }
2098 
2103  {
2104  $input = [
2105  'databaseRow' => [
2106  'uid' => 5,
2107  'aField' => '',
2108  ],
2109  'tableName' => 'aTable',
2110  'effectivePid' => 42,
2111  'processedTca' => [
2112  'columns' => [
2113  'aField' => [
2114  'config' => [
2115  'type' => 'select',
2116  'renderType' => 'selectSingle',
2117  'foreign_table' => 'sys_file_storage',
2118  'foreign_table_prefix' => 'prefix for item labels',
2119  'items' => [],
2120  'maxitems' => 99999,
2121  ],
2122  ],
2123  ]
2124  ],
2125  'rootline' => [],
2126  ];
2127 
2128  ‪$GLOBALS['TCA']['sys_file_storage'] = [
2129  'ctrl' => [
2130  'label' => 'labelField',
2131  ],
2132  'columns' => [],
2133  ];
2134 
2135  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
2136  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
2137  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
2138 
2139  $iconFactoryProphecy = $this->prophesize(IconFactory::class);
2140  GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
2141 
2142  $resourceStorageProphecy = $this->prophesize(ResourceStorage::class);
2143  $resourceStorageProphecy->getUid()->willReturn(1);
2144 
2146  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
2147  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
2148  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
2149  $backendUserProphecy->getFileStorages()->shouldBeCalled()->willReturn(
2150  [$resourceStorageProphecy->reveal()]
2151  );
2152 
2153  [$queryBuilderProphet, $connectionPoolProphet] = $this->‪mockDatabaseConnection('sys_file_storage');
2154 
2156  $statementProphet = $this->prophesize(Statement::class);
2157 
2158  $queryBuilderProphet->select('sys_file_storage.uid', 'sys_file_storage.labelField')
2159  ->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2160  $queryBuilderProphet->from('sys_file_storage')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2161  $queryBuilderProphet->from('pages')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2162  $queryBuilderProphet->where('')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2163  $queryBuilderProphet->andWhere(' 1=1')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2164  $queryBuilderProphet->andWhere('`pages.uid` = `sys_file_storage.pid`')
2165  ->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2166  $queryBuilderProphet->execute()->shouldBeCalled()->willReturn($statementProphet->reveal());
2167 
2168  // Two instances are needed due to the push/pop behavior of addInstance()
2169  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
2170  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
2171 
2172  $counter = 0;
2173  $statementProphet->fetch()->shouldBeCalled()->will(function (‪$args) use (&$counter) {
2174  $counter++;
2175  if ($counter >= 3) {
2176  return false;
2177  }
2178  return [
2179  'uid' => $counter,
2180  'pid' => 0,
2181  'labelField' => 'storageFolderLabel'
2182  ];
2183  });
2184 
2185  $expected = $input;
2186  $expected['processedTca']['columns']['aField']['config']['items'] = [
2187  0 => [
2188  0 => 'prefix for item labels[LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title]',
2189  1 => 1,
2190  2 => null,
2191  3 => null,
2192  4 => null,
2193  ]
2194  ];
2195 
2196  $expected['databaseRow']['aField'] = [];
2197 
2198  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2199  }
2200 
2205  {
2206  $input = [
2207  'databaseRow' => [
2208  'uid' => 5,
2209  'aField' => '',
2210  ],
2211  'tableName' => 'aTable',
2212  'effectivePid' => 42,
2213  'processedTca' => [
2214  'columns' => [
2215  'aField' => [
2216  'config' => [
2217  'type' => 'select',
2218  'renderType' => 'selectSingle',
2219  'foreign_table' => 'fTable',
2220  'maxitems' => 99999,
2221  ],
2222  ],
2223  ]
2224  ],
2225  'rootline' => [],
2226  ];
2227 
2228  // Fake the foreign_table
2229  ‪$GLOBALS['TCA']['fTable'] = [
2230  'ctrl' => [
2231  'label' => 'icon',
2232  'selicon_field' => 'icon',
2233  ],
2234  'columns' =>[
2235  'icon' => [],
2236  ],
2237  ];
2238 
2239  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
2240  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
2241  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
2242 
2244  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
2245  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
2246  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
2247 
2248  [$queryBuilderProphet, $connectionPoolProphet] = $this->‪mockDatabaseConnection();
2249 
2251  $statementProphet = $this->prophesize(Statement::class);
2252 
2253  $queryBuilderProphet->select('fTable.uid', 'fTable.icon')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2254  $queryBuilderProphet->from('fTable')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2255  $queryBuilderProphet->from('pages')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2256  $queryBuilderProphet->where('')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2257  $queryBuilderProphet->andWhere(' 1=1')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2258  $queryBuilderProphet->andWhere('`pages.uid` = `fTable.pid`')->shouldBeCalled()->willReturn($queryBuilderProphet->reveal());
2259  $queryBuilderProphet->execute()->shouldBeCalled()->willReturn($statementProphet->reveal());
2260 
2261  // Two instances are needed due to the push/pop behavior of addInstance()
2262  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
2263  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
2264 
2265  // Query returns one row, then false on second call
2266  $foreignTableRowResultOne = [
2267  'uid' => 1,
2268  'pid' => 23,
2269  'icon' => 'foo.jpg',
2270  ];
2271  $statementProphet->fetch()->shouldBeCalled()->willReturn($foreignTableRowResultOne, false);
2272 
2273  $expected = $input;
2274  $expected['processedTca']['columns']['aField']['config']['items'] = [
2275  0 => [
2276  0 => 'foo.jpg',
2277  1 => 1,
2278  2 => null,
2279  3 => null,
2280  4 => null,
2281  ],
2282  ];
2283  $expected['databaseRow']['aField'] = [];
2284 
2285  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2286  }
2287 
2292  {
2293  $input = [
2294  'databaseRow' => [
2295  'aField' => '',
2296  ],
2297  'tableName' => 'aTable',
2298  'processedTca' => [
2299  'columns' => [
2300  'aField' => [
2301  'config' => [
2302  'type' => 'select',
2303  'renderType' => 'selectSingle',
2304  'items' => [
2305  0 => [
2306  0 => 'keepMe',
2307  1 => 'keep',
2308  null,
2309  null,
2310  null,
2311  ],
2312  1 => [
2313  0 => 'removeMe',
2314  1 => 'remove',
2315  ],
2316  2 => [
2317  0 => 'removeMe',
2318  1 => 0,
2319  ],
2320  ],
2321  'maxitems' => 99999,
2322  ],
2323  ],
2324  ]
2325  ],
2326  'pageTsConfig' => [
2327  'TCEFORM.' => [
2328  'aTable.' => [
2329  'aField.' => [
2330  'keepItems' => 'keep',
2331  ],
2332  ],
2333  ],
2334  ],
2335  ];
2336 
2337  $expected = $input;
2338  $expected['databaseRow']['aField'] = [];
2339  unset(
2340  $expected['processedTca']['columns']['aField']['config']['items'][1],
2341  $expected['processedTca']['columns']['aField']['config']['items'][2]
2342  );
2343 
2344  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2345  }
2346 
2351  {
2352  $input = [
2353  'databaseRow' => [
2354  'aField' => '',
2355  ],
2356  'tableName' => 'aTable',
2357  'processedTca' => [
2358  'columns' => [
2359  'aField' => [
2360  'config' => [
2361  'type' => 'select',
2362  'renderType' => 'selectSingle',
2363  'items' => [
2364  0 => [
2365  0 => 'keepMe',
2366  1 => 'keep',
2367  null,
2368  null,
2369  ],
2370  1 => [
2371  0 => 'removeMe',
2372  1 => 'remove',
2373  ],
2374  ],
2375  'maxitems' => 99999,
2376  ],
2377  ],
2378  ]
2379  ],
2380  'pageTsConfig' => [
2381  'TCEFORM.' => [
2382  'aTable.' => [
2383  'aField.' => [
2384  'keepItems' => '',
2385  ],
2386  ],
2387  ],
2388  ],
2389  ];
2390 
2391  $expected = $input;
2392  $expected['databaseRow']['aField'] = [];
2393  $expected['processedTca']['columns']['aField']['config']['items'] = [];
2394 
2395  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2396  }
2397 
2402  {
2403  $input = [
2404  'databaseRow' => [
2405  'aField' => '',
2406  ],
2407  'tableName' => 'aTable',
2408  'processedTca' => [
2409  'columns' => [
2410  'aField' => [
2411  'config' => [
2412  'type' => 'select',
2413  'renderType' => 'selectSingle',
2414  'items' => [
2415  0 => [
2416  0 => 'keepMe',
2417  1 => '1',
2418  null,
2419  null,
2420  ],
2421  1 => [
2422  0 => 'removeMe',
2423  1 => 'remove',
2424  ],
2425  ],
2426  'maxitems' => 99999,
2427  ],
2428  ],
2429  ]
2430  ],
2431  'pageTsConfig' => [
2432  'TCEFORM.' => [
2433  'aTable.' => [
2434  'aField.' => [
2435  'keepItems' => '1',
2436  'addItems.' => [
2437  '1' => 'addItem #1',
2438  '12' => 'addItem #12',
2439  ],
2440  ],
2441  ],
2442  ],
2443  ],
2444  ];
2445 
2446  $expected = $input;
2447  $expected['databaseRow']['aField'] = [];
2448  $expected['processedTca']['columns']['aField']['config']['items'] = [
2449  0 => [
2450  0 => 'keepMe',
2451  1 => '1',
2452  null,
2453  null,
2454  null,
2455  ],
2456  1 => [
2457  0 => 'addItem #1',
2458  1 => '1',
2459  null,
2460  null,
2461  null,
2462  ],
2463  2 => [
2464  0 => 'addItem #12',
2465  1 => '12',
2466  null,
2467  null,
2468  null,
2469  ],
2470  ];
2471 
2472  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2473  }
2474 
2479  {
2480  $input = [
2481  'databaseRow' => [
2482  'aField' => ''
2483  ],
2484  'tableName' => 'aTable',
2485  'processedTca' => [
2486  'columns' => [
2487  'aField' => [
2488  'config' => [
2489  'type' => 'select',
2490  'renderType' => 'selectSingle',
2491  'items' => [
2492  0 => [
2493  0 => 'keepMe',
2494  1 => 'keep',
2495  null,
2496  null,
2497  null,
2498  ],
2499  1 => [
2500  0 => 'removeMe',
2501  1 => 'remove',
2502  ],
2503  2 => [
2504  0 => 'keep me',
2505  1 => 0,
2506  null,
2507  null,
2508  null,
2509  ],
2510  ],
2511  'maxitems' => 99999,
2512  ],
2513  ],
2514  ]
2515  ],
2516  'pageTsConfig' => [
2517  'TCEFORM.' => [
2518  'aTable.' => [
2519  'aField.' => [
2520  'removeItems' => 'remove',
2521  ],
2522  ],
2523  ],
2524  ],
2525  ];
2526 
2527  $expected = $input;
2528  $expected['databaseRow']['aField'] = [];
2529  unset($expected['processedTca']['columns']['aField']['config']['items'][1]);
2530  $expected['processedTca']['columns']['aField']['config']['items'] = array_values($expected['processedTca']['columns']['aField']['config']['items']);
2531  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2532  }
2533 
2538  {
2539  $input = [
2540  'databaseRow' => [
2541  'aField' => ''
2542  ],
2543  'tableName' => 'aTable',
2544  'processedTca' => [
2545  'columns' => [
2546  'aField' => [
2547  'config' => [
2548  'type' => 'select',
2549  'renderType' => 'selectSingle',
2550  'items' => [
2551  0 => [
2552  0 => 'keepMe',
2553  1 => 'keep',
2554  null,
2555  null,
2556  null,
2557  ],
2558  1 => [
2559  0 => 'keepMe',
2560  1 => 'keepMe2',
2561  null,
2562  null,
2563  null,
2564  ],
2565  2 => [
2566  0 => 'remove me',
2567  1 => 0,
2568  ],
2569  ],
2570  'maxitems' => 99999,
2571  ],
2572  ],
2573  ]
2574  ],
2575  'pageTsConfig' => [
2576  'TCEFORM.' => [
2577  'aTable.' => [
2578  'aField.' => [
2579  'removeItems' => '0',
2580  ],
2581  ],
2582  ],
2583  ],
2584  ];
2585 
2586  $expected = $input;
2587  $expected['databaseRow']['aField'] = [];
2588  unset($expected['processedTca']['columns']['aField']['config']['items'][2]);
2589  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2590  }
2591 
2596  {
2597  $input = [
2598  'databaseRow' => [
2599  'aField' => ''
2600  ],
2601  'tableName' => 'aTable',
2602  'processedTca' => [
2603  'columns' => [
2604  'aField' => [
2605  'config' => [
2606  'type' => 'select',
2607  'renderType' => 'selectSingle',
2608  'items' => [
2609  0 => [
2610  0 => 'keepMe',
2611  1 => 'keep',
2612  null,
2613  null,
2614  null,
2615  ],
2616  1 => [
2617  0 => 'removeMe',
2618  1 => 'remove',
2619  ],
2620  ],
2621  'maxitems' => 99999,
2622  ],
2623  ],
2624  ]
2625  ],
2626  'pageTsConfig' => [
2627  'TCEFORM.' => [
2628  'aTable.' => [
2629  'aField.' => [
2630  'removeItems' => 'remove,add',
2631  'addItems.' => [
2632  'add' => 'addMe'
2633  ]
2634  ],
2635  ],
2636  ],
2637  ],
2638  ];
2639 
2640  $expected = $input;
2641  $expected['databaseRow']['aField'] = [];
2642  unset($expected['processedTca']['columns']['aField']['config']['items'][1]);
2643 
2644  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2645  }
2646 
2651  {
2652  $input = [
2653  'databaseRow' => [
2654  'aField' => 'aValue,remove'
2655  ],
2656  'tableName' => 'aTable',
2657  'processedTca' => [
2658  'ctrl' => [
2659  'languageField' => 'aField',
2660  ],
2661  'columns' => [
2662  'aField' => [
2663  'config' => [
2664  'type' => 'select',
2665  'renderType' => 'selectSingle',
2666  'items' => [
2667  0 => [
2668  0 => 'keepMe',
2669  1 => 'keep',
2670  null,
2671  null,
2672  null,
2673  ],
2674  1 => [
2675  0 => 'removeMe',
2676  1 => 'remove',
2677  ],
2678  ],
2679  'maxitems' => 99999,
2680  ],
2681  ],
2682  ]
2683  ],
2684  ];
2685 
2687  $languageService = $this->prophesize(LanguageService::class);
2688  ‪$GLOBALS['LANG'] = $languageService->reveal();
2689  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue')->willReturn('INVALID VALUE "%s"');
2690  $languageService->sL(Argument::cetera())->willReturnArgument(0);
2691 
2693  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
2694  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
2695  $backendUserProphecy->checkLanguageAccess('keep')->shouldBeCalled()->willReturn(true);
2696  $backendUserProphecy->checkLanguageAccess('remove')->shouldBeCalled()->willReturn(false);
2697 
2698  $expected = $input;
2699  $expected['databaseRow']['aField'] = [];
2700  $expected['processedTca']['columns']['aField']['config']['items'] = [
2701  [ '[ INVALID VALUE "aValue" ]', 'aValue', null, 'none', null ],
2702  [ 'keepMe', 'keep', null, null, null ],
2703  ];
2704 
2705  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2706  }
2707 
2712  {
2713  $input = [
2714  'databaseRow' => [
2715  'aField' => 'keep,remove'
2716  ],
2717  'tableName' => 'aTable',
2718  'processedTca' => [
2719  'columns' => [
2720  'aField' => [
2721  'config' => [
2722  'type' => 'select',
2723  'renderType' => 'selectSingle',
2724  'authMode' => 'explicitAllow',
2725  'items' => [
2726  0 => [
2727  0 => 'keepMe',
2728  1 => 'keep',
2729  null,
2730  null,
2731  null,
2732  ],
2733  1 => [
2734  0 => 'removeMe',
2735  1 => 'remove',
2736  ],
2737  ],
2738  'maxitems' => 99999,
2739  ],
2740  ],
2741  ]
2742  ],
2743  ];
2744 
2746  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
2747  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
2748  $backendUserProphecy->checkAuthMode('aTable', 'aField', 'keep', 'explicitAllow')->shouldBeCalled()->willReturn(true);
2749  $backendUserProphecy->checkAuthMode('aTable', 'aField', 'remove', 'explicitAllow')->shouldBeCalled()->willReturn(false);
2750 
2751  $expected = $input;
2752  $expected['databaseRow']['aField'] = ['keep'];
2753  unset($expected['processedTca']['columns']['aField']['config']['items'][1]);
2754 
2755  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2756  }
2757 
2762  {
2763  $input = [
2764  'databaseRow' => [
2765  'doktype' => 'keep'
2766  ],
2767  'tableName' => 'pages',
2768  'processedTca' => [
2769  'columns' => [
2770  'doktype' => [
2771  'config' => [
2772  'type' => 'select',
2773  'renderType' => 'selectSingle',
2774  'items' => [
2775  0 => [
2776  0 => 'keepMe',
2777  1 => 'keep',
2778  null,
2779  null,
2780  null,
2781  ],
2782  ],
2783  'maxitems' => 99999,
2784  ],
2785  ],
2786  ],
2787  ],
2788  ];
2789 
2791  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
2792  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
2793  $backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(true);
2794 
2795  $expected = $input;
2796  $expected['databaseRow']['doktype'] = ['keep'];
2797 
2798  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2799  }
2800 
2805  {
2806  $input = [
2807  'databaseRow' => [
2808  'doktype' => 'keep',
2809  ],
2810  'tableName' => 'pages',
2811  'processedTca' => [
2812  'columns' => [
2813  'doktype' => [
2814  'config' => [
2815  'type' => 'select',
2816  'renderType' => 'selectSingle',
2817  'items' => [
2818  0 => [
2819  0 => 'keepMe',
2820  1 => 'keep',
2821  null,
2822  null,
2823  null,
2824  ],
2825  1 => [
2826  0 => 'removeMe',
2827  1 => 'remove',
2828  ],
2829  ],
2830  'maxitems' => 99999,
2831  ],
2832  ],
2833  ],
2834  ],
2835  ];
2836 
2838  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
2839  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
2840  $backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(false);
2841  $backendUserProphecy->groupData = [
2842  'pagetypes_select' => 'foo,keep,anotherAllowedDoktype',
2843  ];
2844 
2845  $expected = $input;
2846  $expected['databaseRow']['doktype'] = ['keep'];
2847  unset($expected['processedTca']['columns']['doktype']['config']['items'][1]);
2848 
2849  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
2850  }
2851 
2855  public function ‪addDataCallsItemsProcFunc(): void
2856  {
2857  $input = [
2858  'tableName' => 'aTable',
2859  'inlineParentUid' => 1,
2860  'inlineParentTableName' => 'aTable',
2861  'inlineParentFieldName' => 'aField',
2862  'inlineParentConfig' => [],
2863  'inlineTopMostParentUid' => 1,
2864  'inlineTopMostParentTableName' => 'topMostTable',
2865  'inlineTopMostParentFieldName' => 'topMostField',
2866  'databaseRow' => [
2867  'aField' => 'aValue'
2868  ],
2869  'processedTca' => [
2870  'columns' => [
2871  'aField' => [
2872  'config' => [
2873  'type' => 'select',
2874  'renderType' => 'selectSingle',
2875  'items' => [],
2876  'itemsProcFunc' => function (array $parameters, $pObj) {
2877  $parameters['items'] = [
2878  0 => [
2879  0 => 'aLabel',
2880  1 => 'aValue',
2881  2 => null,
2882  3 => null,
2883  4 => null,
2884  ],
2885  ];
2886  },
2887  ],
2888  ],
2889  ],
2890  ],
2891  ];
2892 
2893  $expected = $input;
2894  $expected['databaseRow']['aField'] = ['aValue'];
2895  $expected['processedTca']['columns']['aField']['config'] = [
2896  'type' => 'select',
2897  'renderType' => 'selectSingle',
2898  'items' => [
2899  0 => [
2900  0 => 'aLabel',
2901  1 => 'aValue',
2902  2 => null,
2903  3 => null,
2904  4 => null,
2905  ],
2906  ],
2907  'maxitems' => 99999,
2908  ];
2909 
2910  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
2911  }
2912 
2917  {
2918  $input = [
2919  'databaseRow' => [
2920  'uid' => 5,
2921  'aField' => 2
2922  ],
2923  'tableName' => 'aTable',
2924  'effectivePid' => 42,
2925  'processedTca' => [
2926  'columns' => [
2927  'aField' => [
2928  'config' => [
2929  'type' => 'select',
2930  'renderType' => 'selectSingle',
2931  'foreign_table' => 'fTable',
2932  'maxitems' => 99999,
2933  ],
2934  ],
2935  ]
2936  ],
2937  'rootline' => [],
2938  ];
2939 
2940  ‪$GLOBALS['TCA']['fTable'] = [
2941  'ctrl' => [
2942  'label' => 'labelField',
2943  ],
2944  'columns' => [
2945  'labelField' => []
2946  ],
2947  ];
2948 
2949  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
2950  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
2951  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
2952 
2953  $iconFactoryProphecy = $this->prophesize(IconFactory::class);
2954  GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
2955 
2957  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
2958  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
2959  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
2960 
2961  [$connectionPoolProphet, $statementProphet] = $this->‪mockForeignTableItemsQuery();
2962 
2963  // Two instances are needed due to the push/pop behavior of addInstance()
2964  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
2965  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
2966 
2967  $counter = 0;
2968  $statementProphet->fetch()->shouldBeCalled()->will(function (‪$args) use (&$counter) {
2969  $counter++;
2970  if ($counter >= 3) {
2971  return false;
2972  }
2973  return [
2974  'uid' => $counter,
2975  'pid' => 23,
2976  'labelField' => 'aLabel_' . $counter,
2977  'aValue' => 'bar,',
2978  'dbfield' => 'some data'
2979  ];
2980  });
2981 
2982  $expected = $input;
2983  $expected['processedTca']['columns']['aField']['config']['items'] = [
2984  0 => [
2985  0 => 'aLabel_1',
2986  1 => 1,
2987  2 => null,
2988  3 => null,
2989  4 => null,
2990  ],
2991  1 => [
2992  0 => 'aLabel_2',
2993  1 => 2,
2994  2 => null,
2995  3 => null,
2996  4 => null,
2997  ],
2998  ];
2999 
3000  $expected['databaseRow']['aField'] = [
3001  0 => '2' // the selected value stored in db
3002  ];
3003 
3004  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3005  }
3006 
3016  {
3017  $input = [
3018  'databaseRow' => [
3019  'uid' => 5,
3020  'aField' => ''
3021  ],
3022  'tableName' => 'aTable',
3023  'inlineParentUid' => 1,
3024  'inlineParentTableName' => 'aTable',
3025  'inlineParentFieldName' => 'aField',
3026  'inlineParentConfig' => [],
3027  'inlineTopMostParentUid' => 1,
3028  'inlineTopMostParentTableName' => 'topMostTable',
3029  'inlineTopMostParentFieldName' => 'topMostField',
3030  'effectivePid' => 42,
3031  'processedTca' => [
3032  'columns' => [
3033  'aField' => [
3034  'config' => [
3035  'type' => 'select',
3036  'renderType' => 'selectSingle',
3037  'foreign_table' => 'fTable',
3038  'itemsProcFunc' => function (array $parameters, $pObj) {
3039  $filteredItems = [];
3040  // Iterate over given items to filter them
3041  foreach ($parameters['items'] as $item) {
3042  if ($item[1] === 2) { // uid === 2
3043  $filteredItems[] = [
3044  $item[0], // label
3045  $item[1], // uid
3046  null, // icon
3047  null, // groupID
3048  null // helpText
3049  ];
3050  }
3051  }
3052  $parameters['items'] = $filteredItems;
3053  },
3054  'maxitems' => 99999,
3055  ],
3056  ],
3057  ]
3058  ],
3059  'rootline' => [],
3060  ];
3061 
3062  ‪$GLOBALS['TCA']['fTable'] = [
3063  'ctrl' => [
3064  'label' => 'labelField',
3065  ],
3066  'columns' => [],
3067  ];
3068 
3069  // FileRepository to get the icon of the foreign table
3070  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
3071  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
3072  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
3073 
3074  $iconFactoryProphecy = $this->prophesize(IconFactory::class);
3075  GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
3076 
3078  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
3079  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
3080  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
3081 
3082  [$connectionPoolProphet, $statementProphet] = $this->‪mockForeignTableItemsQuery();
3083 
3084  // Two instances are needed due to the push/pop behavior of addInstance()
3085  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
3086  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
3087 
3088  $counter = 0;
3089 
3090  // simulates foreign_table containing two rows
3091  $statementProphet->fetch()->shouldBeCalled()->will(function (‪$args) use (&$counter) {
3092  $counter++;
3093  if ($counter >= 3) {
3094  return false;
3095  }
3096  return [
3097  'uid' => $counter,
3098  'pid' => 23,
3099  'labelField' => 'aLabel will be replaced since the label column is not configured',
3100  'aValue' => 'bar, irrelevant',
3101  'dbfield' => 'some random data, irrelevant'
3102  ];
3103  });
3104 
3105  $expected = $input;
3106  $expected['processedTca']['columns']['aField']['config'] = [
3107  'type' => 'select',
3108  'renderType' => 'selectSingle',
3109  'foreign_table' => 'fTable',
3110  'items' => [
3111  0 => [
3112  0 => '[LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title]',
3113  1 => 2,
3114  2 => null,
3115  3 => null,
3116  4 => null,
3117  ],
3118  ],
3119  'maxitems' => 99999
3120  ];
3121 
3122  $expected['databaseRow']['aField'] = [];
3123 
3124  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3125  }
3126 
3137  {
3138  $input = [
3139  'databaseRow' => [
3140  'uid' => 5,
3141  'aField' => ''
3142  ],
3143  'tableName' => 'aTable',
3144  'inlineParentUid' => 1,
3145  'inlineParentTableName' => 'aTable',
3146  'inlineParentFieldName' => 'aField',
3147  'inlineParentConfig' => [],
3148  'inlineTopMostParentUid' => 1,
3149  'inlineTopMostParentTableName' => 'topMostTable',
3150  'inlineTopMostParentFieldName' => 'topMostField',
3151  'effectivePid' => 42,
3152  'processedTca' => [
3153  'columns' => [
3154  'aField' => [
3155  'config' => [
3156  'type' => 'select',
3157  'renderType' => 'selectSingle',
3158  'foreign_table' => 'fTable',
3159  'itemsProcFunc' => function (array $parameters, $pObj) {
3160  $filteredItems = [];
3161  // Iterate over given items to filter them
3162  foreach ($parameters['items'] as $item) {
3163  if ($item[1] < 3) { // uid < 2
3164  $filteredItems[] = [
3165  $item[0], // label
3166  $item[1], // uid
3167  null, // icon
3168  null, // groupId
3169  null // helpText
3170  ];
3171  }
3172  }
3173  $parameters['items'] = $filteredItems;
3174  },
3175  'maxitems' => 99999,
3176  ],
3177  ],
3178  ]
3179  ],
3180  'pageTsConfig' => [
3181  'TCEFORM.' => [
3182  'aTable.' => [
3183  'aField.' => [
3184  'removeItems' => '2'
3185  ],
3186  ],
3187  ],
3188  ],
3189  'rootline' => [],
3190  ];
3191 
3192  ‪$GLOBALS['TCA']['fTable'] = [
3193  'ctrl' => [
3194  'label' => 'labelField',
3195  ],
3196  'columns' => [],
3197  ];
3198 
3199  // FileRepository to get the icon of the foreign table
3200  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
3201  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
3202  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
3203 
3204  $iconFactoryProphecy = $this->prophesize(IconFactory::class);
3205  GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
3206 
3208  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
3209  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
3210  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
3211 
3212  [$connectionPoolProphet, $statementProphet] = $this->‪mockForeignTableItemsQuery();
3213 
3214  // Two instances are needed due to the push/pop behavior of addInstance()
3215  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
3216  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
3217 
3218  $counter = 0;
3219 
3220  // simulates foreign_table containing two rows
3221  $statementProphet->fetch()->shouldBeCalled()->will(function (‪$args) use (&$counter) {
3222  $counter++;
3223  if ($counter >= 3) {
3224  return false;
3225  }
3226  return [
3227  'uid' => $counter,
3228  'pid' => 23,
3229  'labelField' => 'aLabel will be replaced since the label column is not configured',
3230  'randomDbField' => 'bar, irrelevant'
3231  ];
3232  });
3233 
3234  $expected = $input;
3235  $expected['processedTca']['columns']['aField']['config'] = [
3236  'type' => 'select',
3237  'renderType' => 'selectSingle',
3238  'foreign_table' => 'fTable',
3239  'items' => [
3240  0 => [
3241  0 => '[LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title]',
3242  1 => 1,
3243  2 => null,
3244  3 => null,
3245  4 => null,
3246  ]
3247  ],
3248  'maxitems' => 99999
3249  ];
3250 
3251  $expected['databaseRow']['aField'] = [];
3252 
3253  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3254  }
3255 
3266  {
3267  $input = [
3268  'databaseRow' => [
3269  'uid' => 5,
3270  'aField' => ''
3271  ],
3272  'tableName' => 'aTable',
3273  'inlineParentUid' => 1,
3274  'inlineParentTableName' => 'aTable',
3275  'inlineParentFieldName' => 'aField',
3276  'inlineParentConfig' => [],
3277  'inlineTopMostParentUid' => 1,
3278  'inlineTopMostParentTableName' => 'topMostTable',
3279  'inlineTopMostParentFieldName' => 'topMostField',
3280  'effectivePid' => 42,
3281  'processedTca' => [
3282  'columns' => [
3283  'aField' => [
3284  'config' => [
3285  'type' => 'select',
3286  'renderType' => 'selectSingle',
3287  'foreign_table' => 'fTable',
3288  'itemsProcFunc' => function (array $parameters, $pObj) {
3289  $filteredItems = [];
3290  // Iterate over given items to filter them
3291  foreach ($parameters['items'] as $item) {
3292  if ($item[1] === 2) { // uid must be 2
3293  $filteredItems[] = [
3294  $item[0], // label
3295  $item[1], // uid
3296  null, // icon
3297  null, // groupID
3298  null // helpText
3299  ];
3300  }
3301  }
3302  $parameters['items'] = $filteredItems;
3303  },
3304  'maxitems' => 99999,
3305  ],
3306  ],
3307  ]
3308  ],
3309  'pageTsConfig' => [
3310  'TCEFORM.' => [
3311  'aTable.' => [
3312  'aField.' => [
3313  'addItems.' => [
3314  '12' => 'Label of the added item'
3315  ]
3316  ],
3317  ],
3318  ],
3319  ],
3320  'rootline' => [],
3321  ];
3322 
3323  ‪$GLOBALS['TCA']['fTable'] = [
3324  'ctrl' => [
3325  'label' => 'labelField',
3326  ],
3327  'columns' => [],
3328  ];
3329 
3330  // FileRepository to get the icon of the foreign table
3331  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
3332  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
3333  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
3334 
3335  $iconFactoryProphecy = $this->prophesize(IconFactory::class);
3336  GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
3337 
3339  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
3340  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
3341  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
3342 
3343  [$connectionPoolProphet, $statementProphet] = $this->‪mockForeignTableItemsQuery();
3344 
3345  // Two instances are needed due to the push/pop behavior of addInstance()
3346  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
3347  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
3348 
3349  $counter = 0;
3350 
3351  // simulates foreign_table containing two rows
3352  $statementProphet->fetch()->shouldBeCalled()->will(function (‪$args) use (&$counter) {
3353  $counter++;
3354  if ($counter >= 3) {
3355  return false;
3356  }
3357  return [
3358  'uid' => $counter,
3359  'pid' => 23,
3360  'labelField' => 'aLabel will be replaced since the label column is not configured',
3361  'randomDbField' => 'bar, irrelevant'
3362  ];
3363  });
3364 
3365  $expected = $input;
3366  $expected['processedTca']['columns']['aField']['config'] = [
3367  'type' => 'select',
3368  'renderType' => 'selectSingle',
3369  'foreign_table' => 'fTable',
3370  'items' => [
3371  0 => [
3372  0 => '[LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title]',
3373  1 => 2,
3374  2 => null,
3375  3 => null,
3376  4 => null,
3377  ],
3378  1 => [
3379  0 => 'Label of the added item',
3380  1 => 12,
3381  2 => null,
3382  3 => null,
3383  4 => null,
3384  ],
3385  ],
3386  'maxitems' => 99999
3387  ];
3388 
3389  $expected['databaseRow']['aField'] = [];
3390 
3391  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3392  }
3393 
3398  {
3399  $input = [
3400  'tableName' => 'aTable',
3401  'inlineParentUid' => 1,
3402  'inlineParentTableName' => 'aTable',
3403  'inlineParentFieldName' => 'aField',
3404  'inlineParentConfig' => ['config' => 'someValue'],
3405  'inlineTopMostParentUid' => 1,
3406  'inlineTopMostParentTableName' => 'topMostTable',
3407  'inlineTopMostParentFieldName' => 'topMostField',
3408  'databaseRow' => [
3409  'aField' => 'aValue',
3410  ],
3411  'pageTsConfig' => [
3412  'TCEFORM.' => [
3413  'aTable.' => [
3414  'aField.' => [
3415  'itemsProcFunc.' => [
3416  'itemParamKey' => 'itemParamValue',
3417  ],
3418  ]
3419  ],
3420  ],
3421  ],
3422  'processedTca' => [
3423  'columns' => [
3424  'aField' => [
3425  'config' => [
3426  'type' => 'select',
3427  'renderType' => 'selectSingle',
3428  'aKey' => 'aValue',
3429  'items' => [
3430  0 => [
3431  0 => 'aLabel',
3432  1 => 'aValue',
3433  ],
3434  ],
3435  'itemsProcFunc' => function (array $parameters, $pObj) {
3436  if ($parameters['items'] !== [ 0 => [ 'aLabel', 'aValue'] ]
3437  || $parameters['config']['aKey'] !== 'aValue'
3438  || $parameters['TSconfig'] !== [ 'itemParamKey' => 'itemParamValue' ]
3439  || $parameters['table'] !== 'aTable'
3440  || $parameters['row'] !== [ 'aField' => 'aValue' ]
3441  || $parameters['field'] !== 'aField'
3442  || $parameters['inlineParentUid'] !== 1
3443  || $parameters['inlineParentTableName'] !== 'aTable'
3444  || $parameters['inlineParentFieldName'] !== 'aField'
3445  || $parameters['inlineParentConfig'] !== ['config' => 'someValue']
3446  || $parameters['inlineTopMostParentUid'] !== 1
3447  || $parameters['inlineTopMostParentTableName'] !== 'topMostTable'
3448  || $parameters['inlineTopMostParentFieldName'] !== 'topMostField'
3449  ) {
3450  throw new \UnexpectedValueException('broken', 1476109436);
3451  }
3452  },
3453  ],
3454  ],
3455  ],
3456  ],
3457  ];
3458 
3459  $languageService = $this->prophesize(LanguageService::class);
3460  ‪$GLOBALS['LANG'] = $languageService->reveal();
3461  $languageService->sL(Argument::cetera())->willReturnArgument(0);
3463  $flashMessage = $this->prophesize(FlashMessage::class);
3464  GeneralUtility::addInstance(FlashMessage::class, $flashMessage->reveal());
3466  $flashMessageService = $this->prophesize(FlashMessageService::class);
3467  GeneralUtility::setSingletonInstance(FlashMessageService::class, $flashMessageService->reveal());
3469  $flashMessageQueue = $this->prophesize(FlashMessageQueue::class);
3470  $flashMessageService->getMessageQueueByIdentifier(Argument::cetera())->willReturn($flashMessageQueue->reveal());
3471 
3472  // itemsProcFunc must NOT have raised an exception
3473  $flashMessageQueue->enqueue($flashMessage)->shouldNotBeCalled();
3474 
3475  (new ‪TcaSelectItems())->addData($input);
3476  }
3477 
3482  {
3483  $input = [
3484  'tableName' => 'aTable',
3485  'inlineParentUid' => 1,
3486  'inlineParentTableName' => 'aTable',
3487  'inlineParentFieldName' => 'aField',
3488  'inlineParentConfig' => [],
3489  'inlineTopMostParentUid' => 1,
3490  'inlineTopMostParentTableName' => 'topMostTable',
3491  'inlineTopMostParentFieldName' => 'topMostField',
3492  'databaseRow' => [
3493  'aField' => 'aValue',
3494  ],
3495  'pageTsConfig' => [
3496  'TCEFORM.' => [
3497  'aTable.' => [
3498  'aField.' => [
3499  'itemsProcFunc.' => [
3500  'itemParamKey' => 'itemParamValue',
3501  ],
3502  ]
3503  ],
3504  ],
3505  ],
3506  'processedTca' => [
3507  'columns' => [
3508  'aField' => [
3509  'config' => [
3510  'type' => 'select',
3511  'renderType' => 'selectSingle',
3512  'aKey' => 'aValue',
3513  'items' => [
3514  0 => [
3515  0 => 'aLabel',
3516  1 => 'aValue',
3517  ],
3518  ],
3519  'itemsProcFunc' => function (array $parameters, $pObj) {
3520  throw new \UnexpectedValueException('anException', 1476109437);
3521  },
3522  ],
3523  ],
3524  ],
3525  ],
3526  ];
3527 
3528  $languageService = $this->prophesize(LanguageService::class);
3529  ‪$GLOBALS['LANG'] = $languageService->reveal();
3531  $flashMessage = $this->prophesize(FlashMessage::class);
3532  GeneralUtility::addInstance(FlashMessage::class, $flashMessage->reveal());
3534  $flashMessageService = $this->prophesize(FlashMessageService::class);
3535  GeneralUtility::setSingletonInstance(FlashMessageService::class, $flashMessageService->reveal());
3537  $flashMessageQueue = $this->prophesize(FlashMessageQueue::class);
3538  $flashMessageService->getMessageQueueByIdentifier(Argument::cetera())->willReturn($flashMessageQueue->reveal());
3539 
3540  $flashMessageQueue->enqueue($flashMessage)->shouldBeCalled();
3541 
3542  (new ‪TcaSelectItems())->addData($input);
3543  }
3544 
3549  {
3550  $input = [
3551  'databaseRow' => [
3552  'aField' => 'aValue',
3553  ],
3554  'tableName' => 'aTable',
3555  'processedTca' => [
3556  'columns' => [
3557  'aField' => [
3558  'config' => [
3559  'type' => 'select',
3560  'renderType' => 'selectSingle',
3561  'items' => [
3562  0 => [
3563  0 => 'aLabel',
3564  1 => 'aValue',
3565  null,
3566  null,
3567  null
3568  ],
3569  ],
3570  'maxitems' => 99999,
3571  ],
3572  ],
3573  ],
3574  ],
3575  'pageTsConfig' => [
3576  'TCEFORM.' => [
3577  'aTable.' => [
3578  'aField.' => [
3579  'altLabels.' => [
3580  'aValue' => 'labelOverride',
3581  ],
3582  ]
3583  ],
3584  ],
3585  ],
3586  ];
3587 
3589  $languageService = $this->prophesize(LanguageService::class);
3590  ‪$GLOBALS['LANG'] = $languageService->reveal();
3591  $languageService->sL('aLabel')->willReturnArgument(0);
3592  $languageService->sL('labelOverride')->shouldBeCalled()->willReturnArgument(0);
3593  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue')->willReturn('INVALID VALUE "%s"');
3594 
3595  $expected = $input;
3596  $expected['databaseRow']['aField'] = ['aValue'];
3597  $expected['processedTca']['columns']['aField']['config']['items'][0][0] = 'labelOverride';
3598 
3599  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
3600  }
3601 
3605  public function ‪addDataAddsIconsFromPageTsConfig(): void
3606  {
3607  $input = [
3608  'databaseRow' => [
3609  'aField' => 'aValue',
3610  ],
3611  'tableName' => 'aTable',
3612  'processedTca' => [
3613  'columns' => [
3614  'aField' => [
3615  'config' => [
3616  'type' => 'select',
3617  'renderType' => 'selectSingle',
3618  'items' => [
3619  0 => [
3620  0 => 'aLabel',
3621  1 => 'aValue',
3622  2 => 'icon-identifier',
3623  null,
3624  null
3625  ],
3626  ],
3627  'maxitems' => 99999,
3628  ],
3629  ],
3630  ],
3631  ],
3632  'pageTsConfig' => [
3633  'TCEFORM.' => [
3634  'aTable.' => [
3635  'aField.' => [
3636  'altIcons.' => [
3637  'aValue' => 'icon-identifier-override',
3638  ],
3639  ]
3640  ],
3641  ],
3642  ],
3643  ];
3644 
3645  $languageService = $this->prophesize(LanguageService::class);
3646  ‪$GLOBALS['LANG'] = $languageService->reveal();
3647  $languageService->sL('aLabel')->willReturnArgument(0);
3648  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue')->willReturn('INVALID VALUE "%s"');
3649 
3650  $expected = $input;
3651  $expected['databaseRow']['aField'] = ['aValue'];
3652  $expected['processedTca']['columns']['aField']['config']['items'][0][2] = 'icon-identifier-override';
3653 
3654  self::assertSame($expected, (new ‪TcaSelectItems())->addData($input));
3655  }
3656 
3661  {
3662  ‪$GLOBALS['TCA']['foreignTable'] = [];
3663 
3664  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
3665  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
3666  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
3667 
3669  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
3670  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
3671  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
3672 
3674 
3675  $input = [
3676  'command' => 'edit',
3677  'tableName' => 'aTable',
3678  'effectivePid' => 23,
3679  'databaseRow' => [
3680  'uid' => 42,
3681  // Two connected rows
3682  'aField' => 2,
3683  ],
3684  'processedTca' => [
3685  'columns' => [
3686  'aField' => [
3687  'config' => [
3688  'type' => 'select',
3689  'renderType' => 'selectSingle',
3690  'maxitems' => 999,
3691  'foreign_table' => 'foreignTable',
3692  'MM' => 'aTable_foreignTable_mm',
3693  'items' => [],
3694  ],
3695  ],
3696  ],
3697  ],
3698  ];
3699  $fieldConfig = $input['processedTca']['columns']['aField']['config'];
3701  $relationHandlerProphecy = $this->prophesize(RelationHandler::class);
3702  GeneralUtility::addInstance(RelationHandler::class, $relationHandlerProphecy->reveal());
3703 
3704  $relationHandlerUids = [
3705  23,
3706  24
3707  ];
3708 
3709  $relationHandlerProphecy->start('', 'foreignTable', 'aTable_foreignTable_mm', 42, 'aTable', $fieldConfig)->shouldBeCalled();
3710  $relationHandlerProphecy->processDeletePlaceholder()->shouldBeCalled();
3711  $relationHandlerProphecy->getValueArray()->shouldBeCalled()->willReturn($relationHandlerUids);
3712 
3713  $expected = $input;
3714  $expected['databaseRow']['aField'] = $relationHandlerUids;
3715 
3716  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3717  }
3718 
3723  {
3724  ‪$GLOBALS['TCA']['foreignTable'] = [];
3725 
3726  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
3727  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
3728  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
3729 
3731  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
3732  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
3733  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
3734 
3736 
3737  $input = [
3738  'tableName' => 'aTable',
3739  'effectivePid' => 23,
3740  'databaseRow' => [
3741  'uid' => 42,
3742  // Two connected rows
3743  'aField' => '22,23,24,25',
3744  ],
3745  'processedTca' => [
3746  'columns' => [
3747  'aField' => [
3748  'config' => [
3749  'type' => 'select',
3750  'renderType' => 'selectSingle',
3751  'maxitems' => 999,
3752  'foreign_table' => 'foreignTable',
3753  'items' => [],
3754  ],
3755  ],
3756  ],
3757  ],
3758  ];
3759  $fieldConfig = $input['processedTca']['columns']['aField']['config'];
3761  $relationHandlerProphecy = $this->prophesize(RelationHandler::class);
3762  GeneralUtility::addInstance(RelationHandler::class, $relationHandlerProphecy->reveal());
3763 
3764  $relationHandlerUids = [
3765  23,
3766  24
3767  ];
3768 
3769  $relationHandlerProphecy->start('22,23,24,25', 'foreignTable', '', 42, 'aTable', $fieldConfig)->shouldBeCalled();
3770  $relationHandlerProphecy->processDeletePlaceholder()->shouldBeCalled();
3771  $relationHandlerProphecy->getValueArray()->shouldBeCalled()->willReturn($relationHandlerUids);
3772 
3773  $expected = $input;
3774  $expected['databaseRow']['aField'] = $relationHandlerUids;
3775 
3776  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3777  }
3778 
3783  {
3784  ‪$GLOBALS['TCA']['foreignTable'] = [];
3785 
3786  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
3787  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
3788  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
3789 
3791  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
3792  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
3793  $backendUserProphecy->getPagePermsClause(1)->shouldBeCalled()->willReturn(' 1=1');
3794 
3796 
3797  $relationHandlerProphecy = $this->prophesize(RelationHandler::class);
3798  GeneralUtility::addInstance(RelationHandler::class, $relationHandlerProphecy->reveal());
3799  $relationHandlerProphecy->start(Argument::cetera())->shouldBeCalled();
3800  $relationHandlerProphecy->processDeletePlaceholder()->shouldBeCalled();
3801  $relationHandlerProphecy->getValueArray(Argument::cetera())->shouldBeCalled()->willReturn([1]);
3802 
3803  $input = [
3804  'tableName' => 'aTable',
3805  'effectivePid' => 23,
3806  'databaseRow' => [
3807  'uid' => 5,
3808  'aField' => '1,2,bar,foo',
3809  ],
3810  'processedTca' => [
3811  'columns' => [
3812  'aField' => [
3813  'config' => [
3814  'type' => 'select',
3815  'renderType' => 'selectSingleBox',
3816  'foreign_table' => 'foreignTable',
3817  'maxitems' => 999,
3818  'items' => [
3819  ['foo', 'foo', null, null, null],
3820  ],
3821  ],
3822  ],
3823  ],
3824  ],
3825  ];
3826 
3827  $expected = $input;
3828  $expected['databaseRow']['aField'] = [1, 'foo'];
3829 
3830  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3831  }
3832 
3837  {
3838  $input = [
3839  'tableName' => 'aTable',
3840  'databaseRow' => [
3841  'aField' => 'foo,bar',
3842  ],
3843  'processedTca' => [
3844  'columns' => [
3845  'aField' => [
3846  'config' => [
3847  'type' => 'select',
3848  'renderType' => 'selectSingle',
3849  'maxitems' => 999,
3850  'items' => [
3851  ['foo', 'foo', null, null, null],
3852  ['bar', 'bar', null, null, null],
3853  ],
3854  ],
3855  ],
3856  ],
3857  ],
3858  ];
3859 
3860  $expected = $input;
3861  $expected['databaseRow']['aField'] = [
3862  'foo',
3863  'bar'
3864  ];
3865 
3866  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3867  }
3868 
3873  {
3874  $input = [
3875  'tableName' => 'aTable',
3876  'databaseRow' => [
3877  'aField' => '',
3878  ],
3879  'processedTca' => [
3880  'columns' => [
3881  'aField' => [
3882  'config' => [
3883  'type' => 'select',
3884  'renderType' => 'selectSingle',
3885  'maxitems' => 99999,
3886  'items' => [],
3887  ],
3888  ],
3889  ],
3890  ],
3891  ];
3892 
3893  $expected = $input;
3894  $expected['databaseRow']['aField'] = [];
3895 
3896  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3897  }
3898 
3903  {
3904  $input = [
3905  'tableName' => 'aTable',
3906  'databaseRow' => [
3907  'aField' => 'b,,c',
3908  ],
3909  'processedTca' => [
3910  'columns' => [
3911  'aField' => [
3912  'config' => [
3913  'type' => 'select',
3914  'renderType' => 'selectSingle',
3915  'maxitems' => 999,
3916  'items' => [
3917  ['a', '', null, null, null],
3918  ['b', 'b', null, null, null],
3919  ['c', 'c', null, null, null],
3920  ],
3921  ],
3922  ],
3923  ],
3924  ],
3925  ];
3926 
3927  $expected = $input;
3928  $expected['databaseRow']['aField'] = [
3929  'b',
3930  'c',
3931  ];
3932 
3933  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3934  }
3935 
3940  {
3941  $relationHandlerProphecy = $this->prophesize(RelationHandler::class);
3942  GeneralUtility::addInstance(RelationHandler::class, $relationHandlerProphecy->reveal());
3943  $relationHandlerProphecy->start(Argument::cetera())->shouldNotBeCalled();
3944  $relationHandlerProphecy->getValueArray(Argument::cetera())->shouldNotBeCalled();
3945 
3946  $input = [
3947  'tableName' => 'aTable',
3948  'databaseRow' => [
3949  'aField' => 'foo',
3950  ],
3951  'processedTca' => [
3952  'columns' => [
3953  'aField' => [
3954  'config' => [
3955  'type' => 'select',
3956  'renderType' => 'selectSingle',
3957  'maxitems' => 999,
3958  'items' => [
3959  ['foo', 'foo', null, null, null],
3960  ],
3961  ],
3962  ],
3963  ],
3964  ],
3965  ];
3966 
3967  $expected = $input;
3968  $expected['databaseRow']['aField'] = ['foo'];
3969 
3970  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
3971  }
3972 
3977  {
3978  $languageService = $this->prophesize(LanguageService::class);
3979  ‪$GLOBALS['LANG'] = $languageService->reveal();
3980  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noMatchingValue')->willReturn('INVALID VALUE "%s"');
3981  $languageService->sL(Argument::cetera())->willReturnArgument(0);
3982 
3983  $relationHandlerProphecy = $this->prophesize(RelationHandler::class);
3984  GeneralUtility::addInstance(RelationHandler::class, $relationHandlerProphecy->reveal());
3985  $relationHandlerProphecy->start(Argument::cetera())->shouldNotBeCalled();
3986  $relationHandlerProphecy->getValueArray(Argument::cetera())->shouldNotBeCalled();
3987 
3988  $input = [
3989  'tableName' => 'aTable',
3990  'databaseRow' => [
3991  'aField' => '1,2,bar,foo',
3992  ],
3993  'processedTca' => [
3994  'columns' => [
3995  'aField' => [
3996  'config' => [
3997  'type' => 'select',
3998  'renderType' => 'selectSingle',
3999  'maxitems' => 99999,
4000  'items' => [
4001  ['foo', 'foo', null, null, null],
4002  ],
4003  ],
4004  ],
4005  ],
4006  ],
4007  ];
4008 
4009  $expected = $input;
4010  $expected['databaseRow']['aField'] = ['foo'];
4011  $expected['processedTca']['columns']['aField']['config']['items'] = [
4012  ['[ INVALID VALUE "bar" ]', 'bar', null, 'none', null],
4013  ['[ INVALID VALUE "2" ]', '2', null, 'none', null],
4014  ['[ INVALID VALUE "1" ]', '1', null, 'none', null],
4015  ['foo', 'foo', null, null, null],
4016  ];
4017  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
4018  }
4019 
4024  {
4025  $input = [
4026  'tableName' => 'aTable',
4027  'databaseRow' => [
4028  'aField' => '1,foo,foo,2,bar',
4029  ],
4030  'processedTca' => [
4031  'columns' => [
4032  'aField' => [
4033  'config' => [
4034  'type' => 'select',
4035  'renderType' => 'selectSingle',
4036  'multiple' => true,
4037  'maxitems' => 999,
4038  'items' => [
4039  ['1', '1', null, null, null],
4040  ['foo', 'foo', null, null, null],
4041  ['bar', 'bar', null, null, null],
4042  ['2', '2', null, null, null],
4043  ],
4044  ],
4045  ],
4046  ],
4047  ],
4048  ];
4049 
4050  $expected = $input;
4051  $expected['databaseRow']['aField'] = [
4052  '1',
4053  'foo',
4054  'foo',
4055  '2',
4056  'bar'
4057  ];
4058 
4059  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
4060  }
4061 
4066  {
4067  $input = [
4068  'tableName' => 'aTable',
4069  'databaseRow' => [
4070  'aField' => '1,foo,foo,2,bar',
4071  ],
4072  'processedTca' => [
4073  'columns' => [
4074  'aField' => [
4075  'config' => [
4076  'type' => 'select',
4077  'renderType' => 'selectSingle',
4078  'multiple' => false,
4079  'maxitems' => 999,
4080  'items' => [
4081  ['1', '1', null, null, null],
4082  ['foo', 'foo', null, null, null],
4083  ['bar', 'bar', null, null, null],
4084  ['2', '2', null, null, null],
4085  ],
4086  ],
4087  ],
4088  ],
4089  ],
4090  ];
4091 
4092  $expected = $input;
4093  $expected['databaseRow']['aField'] = [
4094  0 => '1',
4095  1 => 'foo',
4096  3 => '2',
4097  4 => 'bar',
4098  ];
4099 
4100  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
4101  }
4102 
4109  {
4110  return [
4111  'Relation with MM table and new status with default values' => [
4112  [
4113  'tableName' => 'aTable',
4114  'command' => 'new',
4115  'effectivePid' => 42,
4116  'databaseRow' => [
4117  'uid' => 'NEW1234',
4118  'aField' => '24,35',
4119  ],
4120  'processedTca' => [
4121  'columns' => [
4122  'aField' => [
4123  'config' => [
4124  'type' => 'select',
4125  'renderType' => 'selectSingle',
4126  'maxitems' => 999,
4127  'MM' => 'mm_aTable_foreignTable',
4128  'foreign_table' => 'foreignTable',
4129  'items' => [],
4130  ],
4131  ],
4132  ],
4133  ],
4134  ],
4135  [
4136  'MM' => ''
4137  ],
4138  [
4139  24, 35
4140  ]
4141  ],
4142  'Relation with MM table and item array in list but no new status' => [
4143  [
4144  'tableName' => 'aTable',
4145  'command' => 'edit',
4146  'effectivePid' => 42,
4147  'databaseRow' => [
4148  'uid' => 42,
4149  'aField' => '2',
4150  ],
4151  'processedTca' => [
4152  'columns' => [
4153  'aField' => [
4154  'config' => [
4155  'type' => 'select',
4156  'renderType' => 'selectSingle',
4157  'maxitems' => 999,
4158  'MM' => 'mm_aTable_foreignTable',
4159  'foreign_table' => 'foreignTable',
4160  'items' => [],
4161  ],
4162  ],
4163  ],
4164  ],
4165  ],
4166  [
4167  'relationHandlerStartItemList' => '',
4168  ],
4169  []
4170  ],
4171  'Relation with MM table and maxitems = 1 processes field value (item count)' => [
4172  [
4173  'tableName' => 'aTable',
4174  'command' => 'edit',
4175  'effectivePid' => 42,
4176  'databaseRow' => [
4177  'uid' => 42,
4178  // MM relation with one item has 1 in field value
4179  'aField' => 1,
4180  ],
4181  'processedTca' => [
4182  'columns' => [
4183  'aField' => [
4184  'config' => [
4185  'type' => 'select',
4186  'renderType' => 'selectSingle',
4187  'maxitems' => 1,
4188  'MM' => 'mm_aTable_foreignTable',
4189  'foreign_table' => 'foreignTable',
4190  'items' => [],
4191  ],
4192  ],
4193  ],
4194  ],
4195  ],
4196  [
4197  'relationHandlerStartItemList' => '',
4198  ],
4199  [
4200  24
4201  ]
4202  ],
4203  'Relation with MM table and maxitems = 1 results in empty array if no items are set' => [
4204  [
4205  'tableName' => 'aTable',
4206  'command' => 'edit',
4207  'effectivePid' => 42,
4208  'databaseRow' => [
4209  'uid' => 58,
4210  // MM relation with no items has 0 in field value
4211  'aField' => 0,
4212  ],
4213  'processedTca' => [
4214  'columns' => [
4215  'aField' => [
4216  'config' => [
4217  'type' => 'select',
4218  'renderType' => 'selectSingle',
4219  'maxitems' => 1,
4220  'MM' => 'mm_aTable_foreignTable',
4221  'foreign_table' => 'foreignTable',
4222  'items' => [],
4223  ],
4224  ],
4225  ],
4226  ],
4227  ],
4228  [
4229  'relationHandlerStartItemList' => '',
4230  ],
4231  []
4232  ]
4233  ];
4234  }
4235 
4244  public function ‪processSelectFieldSetsCorrectValuesForMmRelations(array $input, array $overrideRelationHandlerSettings, array $relationHandlerUids): void
4245  {
4246  $field = $overrideRelationHandlerSettings['relationHandlerStartItemList'] ?? $input['databaseRow']['aField'];
4247  $foreignTable = $overrideRelationHandlerSettings['foreign_table'] ?? $input['processedTca']['columns']['aField']['config']['foreign_table'];
4248  $mmTable = $overrideRelationHandlerSettings['MM'] ?? $input['processedTca']['columns']['aField']['config']['MM'];
4249  $uid = $input['databaseRow']['uid'];
4250  $tableName = $input['tableName'];
4251  $fieldConfig = $input['processedTca']['columns']['aField']['config'];
4252 
4253  ‪$GLOBALS['TCA'][$foreignTable] = [];
4254 
4255  $fileRepositoryProphecy = $this->prophesize(FileRepository::class);
4256  $fileRepositoryProphecy->findByRelation(Argument::cetera())->shouldNotBeCalled();
4257  GeneralUtility::setSingletonInstance(FileRepository::class, $fileRepositoryProphecy->reveal());
4258 
4260  $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
4261  ‪$GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
4262  $backendUserProphecy->getPagePermsClause(Argument::cetera())->willReturn(' 1=1');
4263 
4265 
4267  $relationHandlerProphecy = $this->prophesize(RelationHandler::class);
4268  GeneralUtility::addInstance(RelationHandler::class, $relationHandlerProphecy->reveal());
4269 
4270  $relationHandlerProphecy->start($field, $foreignTable, $mmTable, $uid, $tableName, $fieldConfig)->shouldBeCalled();
4271  $relationHandlerProphecy->processDeletePlaceholder()->shouldBeCalled();
4272  $relationHandlerProphecy->getValueArray()->shouldBeCalled()->willReturn($relationHandlerUids);
4273 
4274  $expected = $input;
4275  $expected['databaseRow']['aField'] = $relationHandlerUids;
4276 
4277  self::assertEquals($expected, (new ‪TcaSelectItems())->addData($input));
4278  }
4279 }
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataReplacesMarkersInForeignTableClause
‪addDataReplacesMarkersInForeignTableClause($foreignTableWhere, $expectedWhere, array $inputOverride)
Definition: TcaSelectItemsTest.php:1742
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataReplacesMarkersInForeignTableClauseDataProvider
‪addDataReplacesMarkersInForeignTableClauseDataProvider()
Definition: TcaSelectItemsTest.php:1496
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsFileItemsWithConfiguredFileFolder
‪addDataAddsFileItemsWithConfiguredFileFolder()
Definition: TcaSelectItemsTest.php:1304
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataCallsItemsProcFunc
‪addDataCallsItemsProcFunc()
Definition: TcaSelectItemsTest.php:2855
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsExplicitAllowFieldsWithSpecialExplicitValues
‪addDataAddsExplicitAllowFieldsWithSpecialExplicitValues()
Definition: TcaSelectItemsTest.php:785
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:35
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsExplicitIndividualAllowFieldsWithSpecialExplicitValues
‪addDataAddsExplicitIndividualAllowFieldsWithSpecialExplicitValues()
Definition: TcaSelectItemsTest.php:931
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataItemsProcFuncReceivesParameters
‪addDataItemsProcFuncReceivesParameters()
Definition: TcaSelectItemsTest.php:3397
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueDoesNotCallRelationManagerForStaticOnlyItems
‪processSelectFieldValueDoesNotCallRelationManagerForStaticOnlyItems()
Definition: TcaSelectItemsTest.php:3939
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsItemsByAddItemsFromPageTsConfig
‪addDataAddsItemsByAddItemsFromPageTsConfig()
Definition: TcaSelectItemsTest.php:1384
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsDividersIfItemGroupsAreDefined
‪addDataAddsDividersIfItemGroupsAreDefined()
Definition: TcaSelectItemsTest.php:287
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataForeignTableSplitsGroupOrderAndLimit
‪addDataForeignTableSplitsGroupOrderAndLimit()
Definition: TcaSelectItemsTest.php:1846
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataKeepsAllowedPageTypesForNonAdminUser
‪addDataKeepsAllowedPageTypesForNonAdminUser()
Definition: TcaSelectItemsTest.php:2804
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueReturnsEmptyValueForSingleSelect
‪processSelectFieldValueReturnsEmptyValueForSingleSelect()
Definition: TcaSelectItemsTest.php:3872
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataRemovesItemsByLanguageFieldUserRestriction
‪addDataRemovesItemsByLanguageFieldUserRestriction()
Definition: TcaSelectItemsTest.php:2650
‪TYPO3\CMS\Core\Database\RelationHandler
Definition: RelationHandler.php:35
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\mockDatabaseConnection
‪array mockDatabaseConnection($tableName='fTable')
Definition: TcaSelectItemsTest.php:98
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataThrowsExceptionForInvalidFileFolder
‪addDataThrowsExceptionForInvalidFileFolder()
Definition: TcaSelectItemsTest.php:1358
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueRemovesInvalidDynamicValues
‪processSelectFieldValueRemovesInvalidDynamicValues()
Definition: TcaSelectItemsTest.php:3782
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataRemovesItemsByUserAuthModeRestriction
‪addDataRemovesItemsByUserAuthModeRestriction()
Definition: TcaSelectItemsTest.php:2711
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\setUp
‪setUp()
Definition: TcaSelectItemsTest.php:57
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataRemovesAllItemsByEmptyKeepItemsPageTsConfig
‪addDataRemovesAllItemsByEmptyKeepItemsPageTsConfig()
Definition: TcaSelectItemsTest.php:2350
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsItemsByAddItemsWithDuplicateValuesFromPageTsConfig
‪addDataAddsItemsByAddItemsWithDuplicateValuesFromPageTsConfig()
Definition: TcaSelectItemsTest.php:1440
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:33
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataKeepsAllPagesDoktypesForAdminUser
‪addDataKeepsAllPagesDoktypesForAdminUser()
Definition: TcaSelectItemsTest.php:2761
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataItemsProcFuncWillUseItemsFromForeignTable
‪addDataItemsProcFuncWillUseItemsFromForeignTable()
Definition: TcaSelectItemsTest.php:3015
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldSetsCorrectValuesForMmRelations
‪processSelectFieldSetsCorrectValuesForMmRelations(array $input, array $overrideRelationHandlerSettings, array $relationHandlerUids)
Definition: TcaSelectItemsTest.php:4244
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsExcludeFieldsWithSpecialExcludeDataProvider
‪addDataAddsExcludeFieldsWithSpecialExcludeDataProvider()
Definition: TcaSelectItemsTest.php:553
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataThrowsExceptionIfAnItemIsNotAnArray
‪addDataThrowsExceptionIfAnItemIsNotAnArray()
Definition: TcaSelectItemsTest.php:212
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:52
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:40
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataForeignTableHandlesForeignTableRows
‪addDataForeignTableHandlesForeignTableRows()
Definition: TcaSelectItemsTest.php:2011
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataRemovesItemsThatAreRestrictedByUserStorageAddedByForeignTable
‪addDataRemovesItemsThatAreRestrictedByUserStorageAddedByForeignTable()
Definition: TcaSelectItemsTest.php:2102
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataKeepExistingItems
‪addDataKeepExistingItems()
Definition: TcaSelectItemsTest.php:173
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueAddsInvalidValuesToItemsForSingleSelects
‪processSelectFieldValueAddsInvalidValuesToItemsForSingleSelects()
Definition: TcaSelectItemsTest.php:3976
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsExcludeFieldsFromFlexWithSpecialExclude
‪addDataAddsExcludeFieldsFromFlexWithSpecialExclude()
Definition: TcaSelectItemsTest.php:704
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldSetsCorrectValuesForMmRelationsDataProvider
‪array processSelectFieldSetsCorrectValuesForMmRelationsDataProvider()
Definition: TcaSelectItemsTest.php:4108
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataTranslatesItemLabels
‪addDataTranslatesItemLabels()
Definition: TcaSelectItemsTest.php:240
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\mockDatabaseConnectionForProcessSelectField
‪mockDatabaseConnectionForProcessSelectField()
Definition: TcaSelectItemsTest.php:135
‪TYPO3\CMS\Core\Resource\FileRepository
Definition: FileRepository.php:33
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsExplicitIndividualDenyFieldsWithSpecialExplicitValues
‪addDataAddsExplicitIndividualDenyFieldsWithSpecialExplicitValues()
Definition: TcaSelectItemsTest.php:1028
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueSetsForeignRelationValues
‪processSelectFieldValueSetsForeignRelationValues()
Definition: TcaSelectItemsTest.php:3722
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataForeignTableItemsWillReceiveTheLabelFromForeignTableLabelField
‪addDataForeignTableItemsWillReceiveTheLabelFromForeignTableLabelField()
Definition: TcaSelectItemsTest.php:2916
‪TYPO3\CMS\Backend\Module\ModuleLoader
Definition: ModuleLoader.php:34
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataForeignTableQueuesFlashMessageOnDatabaseError
‪addDataForeignTableQueuesFlashMessageOnDatabaseError()
Definition: TcaSelectItemsTest.php:1911
‪TYPO3\CMS\Core\Imaging\IconRegistry
Definition: IconRegistry.php:38
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsGroupItemsWithSpecialModListGroup
‪addDataAddsGroupItemsWithSpecialModListGroup()
Definition: TcaSelectItemsTest.php:1244
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:35
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataItemsProcFuncWillUseItemsFromForeignTableAndRemoveItemsByPageTsConfig
‪addDataItemsProcFuncWillUseItemsFromForeignTableAndRemoveItemsByPageTsConfig()
Definition: TcaSelectItemsTest.php:3136
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsIconsFromPageTsConfig
‪addDataAddsIconsFromPageTsConfig()
Definition: TcaSelectItemsTest.php:3605
‪TYPO3\CMS\Backend\Form\FormDataProvider\TcaSelectItems
Definition: TcaSelectItems.php:26
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueReturnsDuplicateValuesForMultipleSelect
‪processSelectFieldValueReturnsDuplicateValuesForMultipleSelect()
Definition: TcaSelectItemsTest.php:4023
‪$args
‪$args
Definition: validateRstFiles.php:214
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataRemovesItemsByZeroValueRemoveItemsPageTsConfig
‪addDataRemovesItemsByZeroValueRemoveItemsPageTsConfig()
Definition: TcaSelectItemsTest.php:2537
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsExcludeFieldsWithSpecialExclude
‪addDataAddsExcludeFieldsWithSpecialExclude($tca, $expectedItems)
Definition: TcaSelectItemsTest.php:676
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueTrimsEmptyValueForMultiValueSelect
‪processSelectFieldValueTrimsEmptyValueForMultiValueSelect()
Definition: TcaSelectItemsTest.php:3902
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:122
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:92
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:24
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataTranslatesItemLabelsFromPageTsConfig
‪addDataTranslatesItemLabelsFromPageTsConfig()
Definition: TcaSelectItemsTest.php:3548
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsTablesWithSpecialTables
‪addDataAddsTablesWithSpecialTables()
Definition: TcaSelectItemsTest.php:428
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsLanguagesWithSpecialLanguages
‪addDataAddsLanguagesWithSpecialLanguages()
Definition: TcaSelectItemsTest.php:1125
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataEvaluatesKeepItemsBeforeAddItemsFromPageTsConfig
‪addDataEvaluatesKeepItemsBeforeAddItemsFromPageTsConfig()
Definition: TcaSelectItemsTest.php:2401
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataRemovesItemsByKeepItemsPageTsConfig
‪addDataRemovesItemsByKeepItemsPageTsConfig()
Definition: TcaSelectItemsTest.php:2291
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsCustomOptionsWithSpecialCustom
‪addDataAddsCustomOptionsWithSpecialCustom()
Definition: TcaSelectItemsTest.php:1178
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueReturnsUniqueValuesForMultipleSelect
‪processSelectFieldValueReturnsUniqueValuesForMultipleSelect()
Definition: TcaSelectItemsTest.php:4065
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueSetsMmForeignRelationValues
‪processSelectFieldValueSetsMmForeignRelationValues()
Definition: TcaSelectItemsTest.php:3660
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\mockForeignTableItemsQuery
‪array mockForeignTableItemsQuery()
Definition: TcaSelectItemsTest.php:1990
‪$tca
‪$tca
Definition: sys_file_metadata.php:5
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataForeignTableResolvesIconFromSelicon
‪addDataForeignTableResolvesIconFromSelicon()
Definition: TcaSelectItemsTest.php:2204
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataRemovesItemsByRemoveItemsPageTsConfig
‪addDataRemovesItemsByRemoveItemsPageTsConfig()
Definition: TcaSelectItemsTest.php:2478
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsTablesWithSpecialPageTypes
‪addDataAddsTablesWithSpecialPageTypes()
Definition: TcaSelectItemsTest.php:490
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataItemsProcFuncEnqueuesFlashMessageOnException
‪addDataItemsProcFuncEnqueuesFlashMessageOnException()
Definition: TcaSelectItemsTest.php:3481
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:22
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest
Definition: TcaSelectItemsTest.php:53
‪TYPO3\CMS\Core\Messaging\FlashMessageQueue
Definition: FlashMessageQueue.php:29
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataRemovesItemsAddedByAddItemsFromPageTsConfigByRemoveItemsPageTsConfig
‪addDataRemovesItemsAddedByAddItemsFromPageTsConfigByRemoveItemsPageTsConfig()
Definition: TcaSelectItemsTest.php:2595
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\processSelectFieldValueKeepsValuesFromStaticItems
‪processSelectFieldValueKeepsValuesFromStaticItems()
Definition: TcaSelectItemsTest.php:3836
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataThrowsExceptionIfForeignTableIsNotDefinedInTca
‪addDataThrowsExceptionIfForeignTableIsNotDefinedInTca()
Definition: TcaSelectItemsTest.php:1820
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataAddsExplicitDenyFieldsWithSpecialExplicitValues
‪addDataAddsExplicitDenyFieldsWithSpecialExplicitValues()
Definition: TcaSelectItemsTest.php:858
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataThrowsExceptionWithUnknownSpecialValue
‪addDataThrowsExceptionWithUnknownSpecialValue()
Definition: TcaSelectItemsTest.php:402
‪TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer
Definition: DefaultRestrictionContainer.php:24
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\tearDown
‪tearDown()
Definition: TcaSelectItemsTest.php:85
‪TYPO3\CMS\Core\Core\Environment\getVarPath
‪static string getVarPath()
Definition: Environment.php:192
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider
Definition: DatabaseDefaultLanguagePageRowTest.php:18
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataItemsProcFuncWillUseItemsFromForeignTableAndAddItemsByPageTsConfig
‪addDataItemsProcFuncWillUseItemsFromForeignTableAndAddItemsByPageTsConfig()
Definition: TcaSelectItemsTest.php:3265
‪TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider\TcaSelectItemsTest\addDataKeepsIconFromItem
‪addDataKeepsIconFromItem()
Definition: TcaSelectItemsTest.php:364