‪TYPO3CMS  ‪main
TcaItemsProcessorFunctionsTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
22 use Psr\EventDispatcher\EventDispatcherInterface;
35 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
36 
37 final class ‪TcaItemsProcessorFunctionsTest extends UnitTestCase
38 {
39  protected function ‪setUp(): void
40  {
41  parent::setUp();
42 
43  // Default LANG mock just returns incoming value as label if calling ->sL()
44  $languageServiceMock = $this->createMock(LanguageService::class);
45  $languageServiceMock->method('sL')->with(self::anything())->willReturnArgument(0);
46  ‪$GLOBALS['LANG'] = $languageServiceMock;
47 
48  $iconRegistryMock = $this->createMock(IconRegistry::class);
49  GeneralUtility::setSingletonInstance(IconRegistry::class, $iconRegistryMock);
50  $iconFactoryMock = $this->createMock(IconFactory::class);
51  // Two instances are needed due to the push/pop behavior of addInstance()
52  GeneralUtility::addInstance(IconFactory::class, $iconFactoryMock);
53  GeneralUtility::addInstance(IconFactory::class, $iconFactoryMock);
54  }
55 
59  protected function ‪tearDown(): void
60  {
61  GeneralUtility::purgeInstances();
62  parent::tearDown();
63  }
64 
65  #[Test]
66  public function ‪populateAvailableTablesTest(): void
67  {
68  $fieldDefinition = ['items' => [0 => ['label' => '---', 'value' => 0]]];
69 
70  ‪$GLOBALS['TCA'] = [
71  'notInResult' => [
72  'ctrl' => [
73  'adminOnly' => true,
74  ],
75  ],
76  'aTable' => [
77  'ctrl' => [
78  'title' => 'aTitle',
79  ],
80  ],
81  ];
82 
83  $expected = [
84  'items' => [
85  0 => [
86  'label' => '---',
87  'value' => 0,
88  ],
89  1 => [
90  'label' => 'aTitle',
91  'value' => 'aTable',
92  'icon' => null,
93  ],
94  ],
95  ];
96 
97  (new ‪TcaItemsProcessorFunctions())->populateAvailableTables($fieldDefinition);
98  self::assertSame($expected, $fieldDefinition);
99  }
100 
101  #[Test]
102  public function ‪populateAvailablePageTypesTest(): void
103  {
104  $fieldDefinition = ['items' => []];
105 
106  (new ‪TcaItemsProcessorFunctions())->populateAvailablePageTypes($fieldDefinition);
107  self::assertSame($fieldDefinition, $fieldDefinition);
108 
109  ‪$GLOBALS['TCA']['pages']['columns']['doktype']['config']['items'] = [
110  0 => [
111  'label' => 'Divider',
112  'value' => '--div--',
113  ],
114  1 => [
115  'label' => 'invalid',
116  ],
117  2 => [
118  'label' => 'aLabel',
119  'value' => 'aValue',
120  ],
121  ];
122 
123  $fieldDefinition = ['items' => [0 => ['---', 0]]];
124 
125  $expected = [
126  'items' => [
127  0 => [
128  0 => '---',
129  1 => 0,
130  ],
131  1 => [
132  'label' => 'aLabel',
133  'value' => 'aValue',
134  'icon' => null,
135  ],
136  ],
137  ];
138 
139  (new ‪TcaItemsProcessorFunctions())->populateAvailablePageTypes($fieldDefinition);
140  self::assertSame($expected, $fieldDefinition);
141  }
142 
143  #[Test]
144  public function ‪populateAvailableUserModulesTest(): void
145  {
146  $moduleProviderMock = $this->createMock(ModuleProvider::class);
147  GeneralUtility::addInstance(ModuleProvider::class, $moduleProviderMock);
148 
149  $moduleFactory = new ‪ModuleFactory($this->createMock(IconRegistry::class), new ‪NoopEventDispatcher());
150 
151  $moduleProviderMock->method('getUserModules')->willReturn([
152  'aModule' => $moduleFactory->createModule('aModule', [
153  'iconIdentifier' => 'a-module',
154  'labels' => 'LLL:EXT:a-module/locallang',
155  'packageName' => 'typo3/cms-testing',
156  ]),
157  'bModule' => $moduleFactory->createModule('bModule', [
158  'iconIdentifier' => 'b-module',
159  'labels' => 'LLL:EXT:b-module/locallang',
160  'packageName' => 'typo3/cms-testing',
161  ]),
162  ]);
163 
164  $fieldDefinition = $expected = ['items' => []];
165  $expected['items'] = [
166  0 => [
167  'label' => 'LLL:EXT:a-module/locallang:mlang_tabs_tab',
168  'value' => 'aModule',
169  'icon' => 'a-module',
170  'description' => [
171  'title' => 'LLL:EXT:a-module/locallang:mlang_labels_tablabel',
172  'description' => 'LLL:EXT:a-module/locallang:mlang_labels_tabdescr',
173  ],
174  ],
175  1 => [
176  'label' => 'LLL:EXT:b-module/locallang:mlang_tabs_tab',
177  'value' => 'bModule',
178  'icon' => 'b-module',
179  'description' => [
180  'title' => 'LLL:EXT:b-module/locallang:mlang_labels_tablabel',
181  'description' => 'LLL:EXT:b-module/locallang:mlang_labels_tabdescr',
182  ],
183  ],
184  ];
185 
186  (new ‪TcaItemsProcessorFunctions())->populateAvailableUserModules($fieldDefinition);
187  self::assertSame($expected, $fieldDefinition);
188  }
189 
190  #[DataProvider('populateExcludeFieldsTestDataProvider')]
191  #[Test]
192  public function ‪populateExcludeFieldsTest(array ‪$tca, array $expectedItems): void
193  {
194  ‪$GLOBALS['TCA'] = ‪$tca;
195  $fieldDefinition = ['items' => []];
196  $expected = [
197  'items' => $expectedItems,
198  ];
199 
200  $eventDispatcher = new ‪MockEventDispatcher();
201  GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
202  GeneralUtility::addInstance(FlexFormTools::class, new ‪FlexFormTools($eventDispatcher));
203 
204  (new ‪TcaItemsProcessorFunctions())->populateExcludeFields($fieldDefinition);
205  self::assertSame($expected, $fieldDefinition);
206  }
207 
208  public static function ‪populateExcludeFieldsTestDataProvider(): array
209  {
210  return [
211  'Table with exclude and non exclude field returns exclude item' => [
212  [
213  // input tca
214  'fooTable' => [
215  'ctrl' => [
216  'title' => 'fooTableTitle',
217  ],
218  'columns' => [
219  'bar' => [
220  'label' => 'barColumnTitle',
221  'exclude' => true,
222  ],
223  'baz' => [
224  'label' => 'bazColumnTitle',
225  ],
226  ],
227  ],
228  ],
229  [
230  // expected items
231  'fooTable' => [
232  'label' => 'fooTableTitle',
233  'value' => '--div--',
234  'icon' => null,
235  ],
236  0 => [
237  'label' => 'barColumnTitle (bar)',
238  'value' => 'fooTable:bar',
239  'icon' => 'empty-empty',
240  ],
241  ],
242  ],
243  'Root level table with ignored root level restriction returns exclude item' => [
244  [
245  // input tca
246  'fooTable' => [
247  'ctrl' => [
248  'title' => 'fooTableTitle',
249  'rootLevel' => 1,
250  'security' => [
251  'ignoreRootLevelRestriction' => true,
252  ],
253  ],
254  'columns' => [
255  'bar' => [
256  'label' => 'barColumnTitle',
257  'exclude' => true,
258  ],
259  ],
260  ],
261  ],
262  [
263  // expected items
264  'fooTable' => [
265  'label' => 'fooTableTitle',
266  'value' => '--div--',
267  'icon' => null,
268  ],
269  0 => [
270  'label' => 'barColumnTitle (bar)',
271  'value' => 'fooTable:bar',
272  'icon' => 'empty-empty',
273  ],
274  ],
275  ],
276  'Root level table without ignored root level restriction returns no item' => [
277  [
278  // input tca
279  'fooTable' => [
280  'ctrl' => [
281  'title' => 'fooTableTitle',
282  'rootLevel' => 1,
283  ],
284  'columns' => [
285  'bar' => [
286  'label' => 'barColumnTitle',
287  'exclude' => true,
288  ],
289  ],
290  ],
291  ],
292  [
293  // no items
294  ],
295  ],
296  'Admin table returns no item' => [
297  [
298  // input tca
299  'fooTable' => [
300  'ctrl' => [
301  'title' => 'fooTableTitle',
302  'adminOnly' => true,
303  ],
304  'columns' => [
305  'bar' => [
306  'label' => 'barColumnTitle',
307  'exclude' => true,
308  ],
309  ],
310  ],
311  ],
312  [
313  // no items
314  ],
315  ],
316  ];
317  }
318 
319  #[Test]
321  {
322  ‪$GLOBALS['TCA'] = [
323  'fooTable' => [
324  'ctrl' => [
325  'title' => 'fooTableTitle',
326  ],
327  'columns' => [
328  'aFlexField' => [
329  'label' => 'aFlexFieldTitle',
330  'config' => [
331  'type' => 'flex',
332  'title' => 'title',
333  'ds' => [
334  'dummy' => '
335  <T3DataStructure>
336  <ROOT>
337  <type>array</type>
338  <el>
339  <input1>
340  <label>flexInputLabel</label>
341  <exclude>1</exclude>
342  <config>
343  <type>input</type>
344  <size>23</size>
345  </config>
346  </input1>
347  </el>
348  </ROOT>
349  </T3DataStructure>
350  ',
351  ],
352  ],
353  ],
354  ],
355  ],
356  ];
357 
358  $fieldDefinition = ['items' => []];
359  $expected = [
360  'items' => [
361  'fooTableTitle aFlexFieldTitle dummy' => [
362  'label' => 'fooTableTitle aFlexFieldTitle dummy',
363  'value' => '--div--',
364  'icon' => null,
365  ],
366  0 => [
367  'label' => 'flexInputLabel (input1)',
368  'value' => 'fooTable:aFlexField;dummy;sDEF;input1',
369  'icon' => 'empty-empty',
370  ],
371  ],
372  ];
373 
374  $cacheManagerMock = $this->createMock(CacheManager::class);
375  $cacheMock = $this->createMock(FrontendInterface::class);
376  $cacheManagerMock->method('getCache')->with('runtime')->willReturn($cacheMock);
377  GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerMock);
378 
379  $eventDispatcher = new ‪MockEventDispatcher();
380  GeneralUtility::addInstance(EventDispatcherInterface::class, $eventDispatcher);
381  GeneralUtility::addInstance(FlexFormTools::class, new ‪FlexFormTools($eventDispatcher));
382 
383  (new ‪TcaItemsProcessorFunctions())->populateExcludeFields($fieldDefinition);
384  self::assertSame($expected, $fieldDefinition);
385  }
386 
387  #[DataProvider('populateExplicitAuthValuesTestDataProvider')]
388  #[Test]
389  public function ‪populateExplicitAuthValuesTest(array ‪$tca, array $expectedItems): void
390  {
391  ‪$GLOBALS['TCA'] = ‪$tca;
392  $fieldDefinition = ['items' => []];
393  $expected = [
394  'items' => $expectedItems,
395  ];
396  (new ‪TcaItemsProcessorFunctions())->populateExplicitAuthValues($fieldDefinition);
397  self::assertSame($expected, $fieldDefinition);
398  }
399 
400  public static function ‪populateExplicitAuthValuesTestDataProvider(): \Generator
401  {
402  yield 'ExplicitAllow fields with special explicit values' => [
403  [
404  'fooTable' => [
405  'ctrl' => [
406  'title' => 'fooTableTitle',
407  ],
408  'columns' => [
409  'aField' => [
410  'label' => 'aFieldTitle',
411  'config' => [
412  'type' => 'select',
413  'renderType' => 'selectSingle',
414  'authMode' => 'explicitAllow',
415  'items' => [
416  0 => [
417  'label' => 'anItemTitle',
418  'value' => 'anItemValue',
419  ],
420  ],
421  ],
422  ],
423  ],
424  ],
425  ],
426  [
427  0 => [
428  'label' => 'fooTableTitle: aFieldTitle',
429  'value' => '--div--',
430  ],
431  1 => [
432  'label' => 'anItemTitle',
433  'value' => 'fooTable:aField:anItemValue',
434  'icon' => 'status-status-permission-granted',
435  ],
436  ],
437  ];
438  }
439 
440  #[Test]
442  {
443  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['customPermOptions'] = [
444  'aKey' => [
445  'header' => 'aHeader',
446  'items' => [
447  'anItemKey' => [
448  0 => 'anItemTitle',
449  ],
450  'anotherKey' => [
451  0 => 'anotherTitle',
452  1 => 'status-status-permission-denied',
453  2 => 'aDescription',
454  ],
455  ],
456  ],
457  ];
458  $fieldDefinition = ['items' => []];
459  $expected = [
460  'items' => [
461  0 => [
462  'label' => 'aHeader',
463  'value' => '--div--',
464  ],
465  1 => [
466  'label' => 'anItemTitle',
467  'value' => 'aKey:anItemKey',
468  'icon' => 'empty-empty',
469  'description' => '',
470  ],
471  2 => [
472  'label' => 'anotherTitle',
473  'value' => 'aKey:anotherKey',
474  'icon' => 'empty-empty',
475  'description' => 'aDescription',
476  ],
477  ],
478  ];
479  (new ‪TcaItemsProcessorFunctions())->populateCustomPermissionOptions($fieldDefinition);
480  self::assertSame($expected, $fieldDefinition);
481  }
482 
483  #[Test]
485  {
486  $this->expectException(\UnexpectedValueException::class);
487  $this->expectExceptionCode(1627565458);
488 
489  $fieldDefinition = ['items' => [], 'config' => []];
491  }
492 
493  #[Test]
495  {
496  $this->expectException(\RuntimeException::class);
497  $this->expectExceptionCode(1627565459);
498 
499  $fieldDefinition = ['items' => [], 'config' => ['itemsProcConfig' => ['table' => 'aTable']]];
501  }
502 
503  #[DataProvider('populateAvailableCategoryFieldsDataProvider')]
504  #[Test]
505  public function ‪populateAvailableCategoryFields(array $itemsProcConfig, array $expectedItems): void
506  {
507  ‪$GLOBALS['TCA']['aTable']['columns'] = [
508  'aField' => [
509  'label' => 'aField label',
510  'config' => [
511  'type' => 'category',
512  'relationship' => 'manyToMany',
513  ],
514  ],
515  'bField' => [
516  'label' => 'bField label',
517  'config' => [
518  'type' => 'category',
519  ],
520  ],
521  'cField' => [
522  'label' => 'cField label',
523  'config' => [
524  'type' => 'category',
525  'relationship' => 'oneToMany',
526  ],
527  ],
528  'dField' => [
529  'label' => 'dField label',
530  'config' => [
531  'type' => 'category',
532  'relationship' => 'manyToMany',
533  ],
534  ],
535  ];
536  $fieldDefinition = ['items' => [], 'config' => ['itemsProcConfig' => $itemsProcConfig]];
537  $expected = $fieldDefinition;
538  $expected['items'] = $expectedItems;
540  self::assertSame($expected, $fieldDefinition);
541  }
542 
543  public static function ‪populateAvailableCategoryFieldsDataProvider(): \Generator
544  {
545  yield 'falls back to default relationship (manyToMany)' => [
546  [
547  'table' => 'aTable',
548  ],
549  [
550  0 => [
551  'label' => 'aField label',
552  'value' => 'aField',
553  ],
554  1 => [
555  'label' => 'dField label',
556  'value' => 'dField',
557  ],
558  ],
559  ];
560  yield 'relationship oneToMany given' => [
561  [
562  'table' => 'aTable',
563  'allowedRelationships' => ['oneToMany'],
564  ],
565  [
566  0 => [
567  'label' => 'cField label',
568  'value' => 'cField',
569  ],
570  ],
571  ];
572  yield 'relationship oneToOne given' => [
573  [
574  'table' => 'aTable',
575  'allowedRelationships' => ['oneToOne'],
576  ],
577  [],
578  ];
579  yield 'multiple relationships given' => [
580  [
581  'table' => 'aTable',
582  'allowedRelationships' => ['oneToOne', 'oneToMany', 'manyToMany'],
583  ],
584  [
585  0 => [
586  'label' => 'aField label',
587  'value' => 'aField',
588  ],
589  1 => [
590  'label' => 'cField label',
591  'value' => 'cField',
592  ],
593  2 => [
594  'label' => 'dField label',
595  'value' => 'dField',
596  ],
597  ],
598  ];
599  }
600 }
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateExplicitAuthValuesTestDataProvider
‪static populateExplicitAuthValuesTestDataProvider()
Definition: TcaItemsProcessorFunctionsTest.php:400
‪TYPO3\CMS\Backend\Module\ModuleFactory
Definition: ModuleFactory.php:29
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateAvailableCategoryFieldsDataProvider
‪static populateAvailableCategoryFieldsDataProvider()
Definition: TcaItemsProcessorFunctionsTest.php:543
‪TYPO3\CMS\Core\Tests\Unit\Hooks
Definition: TcaItemsProcessorFunctionsTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateExcludeFieldsWithFlexFormTest
‪populateExcludeFieldsWithFlexFormTest()
Definition: TcaItemsProcessorFunctionsTest.php:320
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateAvailableCategoryFieldsThrowsExceptionOnInvalidTable
‪populateAvailableCategoryFieldsThrowsExceptionOnInvalidTable()
Definition: TcaItemsProcessorFunctionsTest.php:494
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateAvailableTablesTest
‪populateAvailableTablesTest()
Definition: TcaItemsProcessorFunctionsTest.php:66
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest
Definition: TcaItemsProcessorFunctionsTest.php:38
‪TYPO3\CMS\Backend\Module\ModuleProvider
Definition: ModuleProvider.php:29
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateAvailableUserModulesTest
‪populateAvailableUserModulesTest()
Definition: TcaItemsProcessorFunctionsTest.php:144
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateAvailablePageTypesTest
‪populateAvailablePageTypesTest()
Definition: TcaItemsProcessorFunctionsTest.php:102
‪TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools
Definition: FlexFormTools.php:40
‪TYPO3\CMS\Core\Imaging\IconRegistry
Definition: IconRegistry.php:32
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateAvailableCategoryFieldsThrowsExceptionOnMissingTable
‪populateAvailableCategoryFieldsThrowsExceptionOnMissingTable()
Definition: TcaItemsProcessorFunctionsTest.php:484
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateExplicitAuthValuesTest
‪populateExplicitAuthValuesTest(array $tca, array $expectedItems)
Definition: TcaItemsProcessorFunctionsTest.php:389
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\tearDown
‪tearDown()
Definition: TcaItemsProcessorFunctionsTest.php:59
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateCustomPermissionOptionsTest
‪populateCustomPermissionOptionsTest()
Definition: TcaItemsProcessorFunctionsTest.php:441
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateAvailableCategoryFields
‪populateAvailableCategoryFields(array $itemsProcConfig, array $expectedItems)
Definition: TcaItemsProcessorFunctionsTest.php:505
‪TYPO3\CMS\Core\EventDispatcher\NoopEventDispatcher
Definition: NoopEventDispatcher.php:29
‪TYPO3\CMS\Core\Hooks\TcaItemsProcessorFunctions
Definition: TcaItemsProcessorFunctions.php:34
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\setUp
‪setUp()
Definition: TcaItemsProcessorFunctionsTest.php:39
‪TYPO3\CMS\Core\Tests\Unit\Fixtures\EventDispatcher\MockEventDispatcher
Definition: MockEventDispatcher.php:30
‪$tca
‪$tca
Definition: sys_file_metadata.php:5
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateExcludeFieldsTestDataProvider
‪static populateExcludeFieldsTestDataProvider()
Definition: TcaItemsProcessorFunctionsTest.php:208
‪TYPO3\CMS\Core\Tests\Unit\Hooks\TcaItemsProcessorFunctionsTest\populateExcludeFieldsTest
‪populateExcludeFieldsTest(array $tca, array $expectedItems)
Definition: TcaItemsProcessorFunctionsTest.php:192