‪TYPO3CMS  10.4
ExtensionManagementUtilityTest.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 Prophecy\Argument;
19 use Psr\EventDispatcher\EventDispatcherInterface;
26 use TYPO3\CMS\Core\Package\PackageManager;
31 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
32 
36 class ExtensionManagementUtilityTest extends UnitTestCase
37 {
41  protected $resetSingletonInstances = true;
42 
46  protected $backUpPackageManager;
47 
51  protected function setUp(): void
52  {
53  parent::setUp();
55  }
56 
60  protected function tearDown(): void
61  {
64  parent::tearDown();
65  }
66 
72  protected function createMockPackageManagerWithMockPackage($packageKey, $packageMethods = ['getPackagePath', 'getPackageKey'])
73  {
74  $packagePath = ‪Environment::getVarPath() . '/tests/' . $packageKey . '/';
75  ‪GeneralUtility::mkdir_deep($packagePath);
76  $this->testFilesToDelete[] = $packagePath;
77  $package = $this->getMockBuilder(Package::class)
78  ->disableOriginalConstructor()
79  ->setMethods($packageMethods)
80  ->getMock();
81  $packageManager = $this->getMockBuilder(PackageManager::class)
82  ->setMethods(['isPackageActive', 'getPackage', 'getActivePackages'])
83  ->disableOriginalConstructor()
84  ->getMock();
85  $package->expects(self::any())
86  ->method('getPackagePath')
87  ->willReturn($packagePath);
88  $package->expects(self::any())
89  ->method('getPackageKey')
90  ->willReturn($packageKey);
91  $packageManager->expects(self::any())
92  ->method('isPackageActive')
93  ->willReturnMap([
94  [null, false],
95  [$packageKey, true]
96  ]);
97  $packageManager->expects(self::any())
98  ->method('getPackage')
99  ->with(self::equalTo($packageKey))
100  ->willReturn($package);
101  $packageManager->expects(self::any())
102  ->method('getActivePackages')
103  ->willReturn([$packageKey => $package]);
104  return $packageManager;
105  }
106 
108  // Tests concerning isLoaded
110 
113  public function isLoadedReturnsFalseIfExtensionIsNotLoaded()
114  {
116  }
117 
119  // Tests concerning extPath
121 
124  public function extPathThrowsExceptionIfExtensionIsNotLoaded()
125  {
126  $this->expectException(\BadFunctionCallException::class);
127  $this->expectExceptionCode(1365429656);
128 
129  $packageName = ‪StringUtility::getUniqueId('foo');
131  $packageManager = $this->getMockBuilder(PackageManager::class)
132  ->setMethods(['isPackageActive'])
133  ->disableOriginalConstructor()
134  ->getMock();
135  $packageManager->expects(self::once())
136  ->method('isPackageActive')
137  ->with(self::equalTo($packageName))
138  ->willReturn(false);
141  }
142 
146  public function extPathAppendsScriptNameToPath()
147  {
148  $package = $this->getMockBuilder(Package::class)
149  ->disableOriginalConstructor()
150  ->setMethods(['getPackagePath'])
151  ->getMock();
153  $packageManager = $this->getMockBuilder(PackageManager::class)
154  ->setMethods(['isPackageActive', 'getPackage'])
155  ->disableOriginalConstructor()
156  ->getMock();
157  $package->expects(self::once())
158  ->method('getPackagePath')
159  ->willReturn(‪Environment::getPublicPath() . '/foo/');
160  $packageManager->expects(self::once())
161  ->method('isPackageActive')
162  ->with(self::equalTo('foo'))
163  ->willReturn(true);
164  $packageManager->expects(self::once())
165  ->method('getPackage')
166  ->with('foo')
167  ->willReturn($package);
169  self::assertSame(‪Environment::getPublicPath() . '/foo/bar.txt', ‪ExtensionManagementUtility::extPath('foo', 'bar.txt'));
170  }
171 
173  // Utility functions
175 
181  private function generateTCAForTable($table)
182  {
183  ‪$tca = [];
184  ‪$tca[$table] = [];
185  ‪$tca[$table]['columns'] = [
186  'fieldA' => [],
187  'fieldC' => []
188  ];
189  ‪$tca[$table]['types'] = [
190  'typeA' => ['showitem' => 'fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1'],
191  'typeB' => ['showitem' => 'fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1'],
192  'typeC' => ['showitem' => 'fieldC;;paletteD']
193  ];
194  ‪$tca[$table]['palettes'] = [
195  'paletteA' => ['showitem' => 'fieldX, fieldX1, fieldY'],
196  'paletteB' => ['showitem' => 'fieldX, fieldX1, fieldY'],
197  'paletteC' => ['showitem' => 'fieldX, fieldX1, fieldY'],
198  'paletteD' => ['showitem' => 'fieldX, fieldX1, fieldY']
199  ];
200  return ‪$tca;
201  }
202 
208  public function extensionKeyDataProvider()
209  {
210  return [
211  'Without underscores' => [
212  'testkey',
213  'tx_testkey'
214  ],
215  'With underscores' => [
216  'this_is_a_test_extension',
217  'tx_thisisatestextension'
218  ],
219  'With user prefix and without underscores' => [
220  'user_testkey',
221  'user_testkey'
222  ],
223  'With user prefix and with underscores' => [
224  'user_test_key',
225  'user_testkey'
226  ],
227  ];
228  }
229 
236  public function getClassNamePrefixForExtensionKey($extensionName, $expectedPrefix)
237  {
238  self::assertSame($expectedPrefix, ‪ExtensionManagementUtility::getCN($extensionName));
239  }
240 
242  // Tests concerning addToAllTCAtypes
244 
250  public function canAddFieldsToAllTCATypesBeforeExistingOnes()
251  {
252  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
253  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
254  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', '', 'before:fieldD');
255  // Checking typeA:
256  self::assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, newA, newB, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
257  // Checking typeB:
258  self::assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, newA, newB, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeB']['showitem']);
259  }
260 
267  public function canAddFieldsToAllTCATypesAfterExistingOnes()
268  {
269  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
270  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
271  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', '', 'after:fieldC');
272  // Checking typeA:
273  self::assertEquals('fieldA, fieldB, fieldC;labelC, newA, newB, --palette--;;paletteC, fieldC1, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
274  // Checking typeB:
275  self::assertEquals('fieldA, fieldB, fieldC;labelC, newA, newB, --palette--;;paletteC, fieldC1, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeB']['showitem']);
276  }
277 
284  public function canAddFieldsToAllTCATypesRespectsPalettes()
285  {
286  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
287  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
288  ‪$GLOBALS['TCA'][$table]['types']['typeD'] = ['showitem' => 'fieldY, --palette--;;standard, fieldZ'];
289  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', '', 'after:--palette--;;standard');
290  // Checking typeD:
291  self::assertEquals('fieldY, --palette--;;standard, newA, newB, fieldA, fieldZ', ‪$GLOBALS['TCA'][$table]['types']['typeD']['showitem']);
292  }
293 
300  public function canAddFieldsToAllTCATypesRespectsPositionFieldInPalette()
301  {
302  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
303  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
304  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', '', 'after:fieldX1');
305  // Checking typeA:
306  self::assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, newA, newB, fieldC1, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
307  }
308 
315  public function canAddFieldsToTCATypeBeforeExistingOnes()
316  {
317  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
318  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
319  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', 'typeA', 'before:fieldD');
320  // Checking typeA:
321  self::assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, newA, newB, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
322  // Checking typeB:
323  self::assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeB']['showitem']);
324  }
325 
332  public function canAddFieldsToTCATypeAfterExistingOnes()
333  {
334  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
335  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
336  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', 'typeA', 'after:fieldC');
337  // Checking typeA:
338  self::assertEquals('fieldA, fieldB, fieldC;labelC, newA, newB, --palette--;;paletteC, fieldC1, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
339  // Checking typeB:
340  self::assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1', ‪$GLOBALS['TCA'][$table]['types']['typeB']['showitem']);
341  }
342 
346  public function canAddFieldWithPartOfAlreadyExistingFieldname()
347  {
348  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
349  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
350  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'field', 'typeA', 'after:fieldD1');
351 
352  self::assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1, field', ‪$GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
353  }
354 
361  public function canAddFieldsToTCATypeAndReplaceExistingOnes()
362  {
363  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
364  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
365  $typesBefore = ‪$GLOBALS['TCA'][$table]['types'];
366  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'fieldZ', '', 'replace:fieldX');
367  self::assertEquals($typesBefore, ‪$GLOBALS['TCA'][$table]['types'], 'It\'s wrong that the "types" array changes here - the replaced field is only on palettes');
368  // unchanged because the palette is not used
369  self::assertEquals('fieldX, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
370  self::assertEquals('fieldX, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteB']['showitem']);
371  // changed
372  self::assertEquals('fieldZ, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteC']['showitem']);
373  self::assertEquals('fieldZ, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteD']['showitem']);
374  }
375 
379  public function addToAllTCAtypesReplacesExistingOnes()
380  {
381  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
382  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
383  $typesBefore = ‪$GLOBALS['TCA'][$table]['types'];
384  ‪ExtensionManagementUtility::addToAllTCAtypes($table, 'fieldX, --palette--;;foo', '', 'replace:fieldX');
385  self::assertEquals($typesBefore, ‪$GLOBALS['TCA'][$table]['types'], 'It\'s wrong that the "types" array changes here - the replaced field is only on palettes');
386  // unchanged because the palette is not used
387  self::assertEquals('fieldX, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
388  self::assertEquals('fieldX, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteB']['showitem']);
389  // changed
390  self::assertEquals('fieldX, --palette--;;foo, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteC']['showitem']);
391  self::assertEquals('fieldX, --palette--;;foo, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteD']['showitem']);
392  }
393 
400  public function canAddFieldsToPaletteBeforeExistingOnes()
401  {
402  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
403  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
404  ‪ExtensionManagementUtility::addFieldsToPalette($table, 'paletteA', 'newA, newA, newB, fieldX', 'before:fieldY');
405  self::assertEquals('fieldX, fieldX1, newA, newB, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
406  }
407 
414  public function canAddFieldsToPaletteAfterExistingOnes()
415  {
416  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
417  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
418  ‪ExtensionManagementUtility::addFieldsToPalette($table, 'paletteA', 'newA, newA, newB, fieldX', 'after:fieldX');
419  self::assertEquals('fieldX, newA, newB, fieldX1, fieldY', ‪$GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
420  }
421 
428  public function canAddFieldsToPaletteAfterNotExistingOnes()
429  {
430  $table = ‪StringUtility::getUniqueId('tx_coretest_table');
431  ‪$GLOBALS['TCA'] = $this->generateTCAForTable($table);
432  ‪ExtensionManagementUtility::addFieldsToPalette($table, 'paletteA', 'newA, newA, newB, fieldX', 'after:' . ‪StringUtility::getUniqueId('notExisting'));
433  self::assertEquals('fieldX, fieldX1, fieldY, newA, newB', ‪$GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
434  }
435 
439  public function removeDuplicatesForInsertionRemovesDuplicatesDataProvider()
440  {
441  return [
442  'Simple' => [
443  'field_b, field_d, field_c',
444  'field_a, field_b, field_c',
445  'field_d'
446  ],
447  'with linebreaks' => [
448  'field_b, --linebreak--, field_d, --linebreak--, field_c',
449  'field_a, field_b, field_c',
450  '--linebreak--, field_d, --linebreak--'
451  ],
452  'with linebreaks in list and insertion list' => [
453  'field_b, --linebreak--, field_d, --linebreak--, field_c',
454  'field_a, field_b, --linebreak--, field_c',
455  '--linebreak--, field_d, --linebreak--'
456  ],
457  ];
458  }
459 
467  public function removeDuplicatesForInsertionRemovesDuplicates($insertionList, $list, $expected)
468  {
470  self::assertSame($expected, $result);
471  }
472 
474  // Tests concerning addFieldsToAllPalettesOfField
476 
480  public function addFieldsToAllPalettesOfFieldDoesNotAddAnythingIfFieldIsNotRegisteredInColumns()
481  {
482  ‪$GLOBALS['TCA'] = [
483  'aTable' => [
484  'types' => [
485  'typeA' => [
486  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
487  ],
488  ],
489  'palettes' => [
490  'paletteA' => [
491  'showitem' => 'fieldX, fieldY',
492  ],
493  ],
494  ],
495  ];
496  $expected = ‪$GLOBALS['TCA'];
498  'aTable',
499  'fieldA',
500  'newA'
501  );
502  self::assertEquals($expected, ‪$GLOBALS['TCA']);
503  }
504 
508  public function addFieldsToAllPalettesOfFieldAddsFieldsToPaletteAndSuppressesDuplicates()
509  {
510  ‪$GLOBALS['TCA'] = [
511  'aTable' => [
512  'columns' => [
513  'fieldA' => [],
514  ],
515  'types' => [
516  'typeA' => [
517  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
518  ],
519  ],
520  'palettes' => [
521  'paletteA' => [
522  'showitem' => 'fieldX, fieldY',
523  ],
524  ],
525  ],
526  ];
527  $expected = [
528  'aTable' => [
529  'columns' => [
530  'fieldA' => [],
531  ],
532  'types' => [
533  'typeA' => [
534  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
535  ],
536  ],
537  'palettes' => [
538  'paletteA' => [
539  'showitem' => 'fieldX, fieldY, dupeA',
540  ],
541  ],
542  ],
543  ];
545  'aTable',
546  'fieldA',
547  'dupeA, dupeA' // Duplicate
548  );
549  self::assertEquals($expected, ‪$GLOBALS['TCA']);
550  }
551 
555  public function addFieldsToAllPalettesOfFieldDoesNotAddAFieldThatIsPartOfPaletteAlready()
556  {
557  ‪$GLOBALS['TCA'] = [
558  'aTable' => [
559  'columns' => [
560  'fieldA' => [],
561  ],
562  'types' => [
563  'typeA' => [
564  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
565  ],
566  ],
567  'palettes' => [
568  'paletteA' => [
569  'showitem' => 'existingA',
570  ],
571  ],
572  ],
573  ];
574  $expected = [
575  'aTable' => [
576  'columns' => [
577  'fieldA' => [],
578  ],
579  'types' => [
580  'typeA' => [
581  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
582  ],
583  ],
584  'palettes' => [
585  'paletteA' => [
586  'showitem' => 'existingA',
587  ],
588  ],
589  ],
590  ];
592  'aTable',
593  'fieldA',
594  'existingA'
595  );
596  self::assertEquals($expected, ‪$GLOBALS['TCA']);
597  }
598 
602  public function addFieldsToAllPalettesOfFieldAddsFieldsToMultiplePalettes()
603  {
604  ‪$GLOBALS['TCA'] = [
605  'aTable' => [
606  'columns' => [
607  'fieldA' => [],
608  ],
609  'types' => [
610  'typeA' => [
611  'showitem' => 'fieldA, --palette--;;palette1',
612  ],
613  'typeB' => [
614  'showitem' => 'fieldA;aLabel, --palette--;;palette2',
615  ],
616  ],
617  'palettes' => [
618  'palette1' => [
619  'showitem' => 'fieldX',
620  ],
621  'palette2' => [
622  'showitem' => 'fieldY',
623  ],
624  ],
625  ],
626  ];
627  $expected = [
628  'aTable' => [
629  'columns' => [
630  'fieldA' => [],
631  ],
632  'types' => [
633  'typeA' => [
634  'showitem' => 'fieldA, --palette--;;palette1',
635  ],
636  'typeB' => [
637  'showitem' => 'fieldA;aLabel, --palette--;;palette2',
638  ],
639  ],
640  'palettes' => [
641  'palette1' => [
642  'showitem' => 'fieldX, newA',
643  ],
644  'palette2' => [
645  'showitem' => 'fieldY, newA',
646  ],
647  ],
648  ],
649  ];
651  'aTable',
652  'fieldA',
653  'newA'
654  );
655  self::assertEquals($expected, ‪$GLOBALS['TCA']);
656  }
657 
661  public function addFieldsToAllPalettesOfFieldAddsMultipleFields()
662  {
663  ‪$GLOBALS['TCA'] = [
664  'aTable' => [
665  'columns' => [
666  'fieldA' => [],
667  ],
668  'types' => [
669  'typeA' => [
670  'showitem' => 'fieldA, --palette--;;palette1',
671  ],
672  ],
673  'palettes' => [
674  'palette1' => [
675  'showitem' => 'fieldX',
676  ],
677  ],
678  ],
679  ];
680  $expected = [
681  'aTable' => [
682  'columns' => [
683  'fieldA' => [],
684  ],
685  'types' => [
686  'typeA' => [
687  'showitem' => 'fieldA, --palette--;;palette1',
688  ],
689  ],
690  'palettes' => [
691  'palette1' => [
692  'showitem' => 'fieldX, newA, newB',
693  ],
694  ],
695  ],
696  ];
698  'aTable',
699  'fieldA',
700  'newA, newB'
701  );
702  self::assertEquals($expected, ‪$GLOBALS['TCA']);
703  }
704 
708  public function addFieldsToAllPalettesOfFieldAddsBeforeExistingIfRequested()
709  {
710  ‪$GLOBALS['TCA'] = [
711  'aTable' => [
712  'columns' => [
713  'fieldA' => [],
714  ],
715  'types' => [
716  'typeA' => [
717  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
718  ],
719  ],
720  'palettes' => [
721  'paletteA' => [
722  'showitem' => 'existingA, existingB',
723  ],
724  ],
725  ],
726  ];
727  $expected = [
728  'aTable' => [
729  'columns' => [
730  'fieldA' => [],
731  ],
732  'types' => [
733  'typeA' => [
734  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
735  ],
736  ],
737  'palettes' => [
738  'paletteA' => [
739  'showitem' => 'existingA, newA, existingB',
740  ],
741  ],
742  ],
743  ];
745  'aTable',
746  'fieldA',
747  'newA',
748  'before:existingB'
749  );
750  self::assertEquals($expected, ‪$GLOBALS['TCA']);
751  }
752 
756  public function addFieldsToAllPalettesOfFieldAddsFieldsAtEndIfBeforeRequestedDoesNotExist()
757  {
758  ‪$GLOBALS['TCA'] = [
759  'aTable' => [
760  'columns' => [
761  'fieldA' => [],
762  ],
763  'types' => [
764  'typeA' => [
765  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
766  ],
767  ],
768  'palettes' => [
769  'paletteA' => [
770  'showitem' => 'fieldX, fieldY',
771  ],
772  ],
773  ],
774  ];
775  $expected = [
776  'aTable' => [
777  'columns' => [
778  'fieldA' => [],
779  ],
780  'types' => [
781  'typeA' => [
782  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
783  ],
784  ],
785  'palettes' => [
786  'paletteA' => [
787  'showitem' => 'fieldX, fieldY, newA, newB',
788  ],
789  ],
790  ],
791  ];
793  'aTable',
794  'fieldA',
795  'newA, newB',
796  'before:notExisting'
797  );
798  self::assertEquals($expected, ‪$GLOBALS['TCA']);
799  }
800 
804  public function addFieldsToAllPalettesOfFieldAddsAfterExistingIfRequested()
805  {
806  ‪$GLOBALS['TCA'] = [
807  'aTable' => [
808  'columns' => [
809  'fieldA' => [],
810  ],
811  'types' => [
812  'typeA' => [
813  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
814  ],
815  ],
816  'palettes' => [
817  'paletteA' => [
818  'showitem' => 'existingA, existingB',
819  ],
820  ],
821  ],
822  ];
823  $expected = [
824  'aTable' => [
825  'columns' => [
826  'fieldA' => [],
827  ],
828  'types' => [
829  'typeA' => [
830  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
831  ],
832  ],
833  'palettes' => [
834  'paletteA' => [
835  'showitem' => 'existingA, newA, existingB',
836  ],
837  ],
838  ],
839  ];
841  'aTable',
842  'fieldA',
843  'newA',
844  'after:existingA'
845  );
846  self::assertEquals($expected, ‪$GLOBALS['TCA']);
847  }
848 
852  public function addFieldsToAllPalettesOfFieldAddsFieldsAtEndIfAfterRequestedDoesNotExist()
853  {
854  ‪$GLOBALS['TCA'] = [
855  'aTable' => [
856  'columns' => [
857  'fieldA' => [],
858  ],
859  'types' => [
860  'typeA' => [
861  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
862  ],
863  ],
864  'palettes' => [
865  'paletteA' => [
866  'showitem' => 'existingA, existingB',
867  ],
868  ],
869  ],
870  ];
871  $expected = [
872  'aTable' => [
873  'columns' => [
874  'fieldA' => [],
875  ],
876  'types' => [
877  'typeA' => [
878  'showitem' => 'fieldA;labelA, --palette--;;paletteA',
879  ],
880  ],
881  'palettes' => [
882  'paletteA' => [
883  'showitem' => 'existingA, existingB, newA, newB',
884  ],
885  ],
886  ],
887  ];
889  'aTable',
890  'fieldA',
891  'newA, newB',
892  'after:notExistingA'
893  );
894  self::assertEquals($expected, ‪$GLOBALS['TCA']);
895  }
896 
900  public function addFieldsToAllPalettesOfFieldAddsNewPaletteIfFieldHasNoPaletteYet()
901  {
902  ‪$GLOBALS['TCA'] = [
903  'aTable' => [
904  'columns' => [
905  'fieldA' => [],
906  ],
907  'types' => [
908  'typeA' => [
909  'showitem' => 'fieldA',
910  ],
911  ],
912  ],
913  ];
914  $expected = [
915  'aTable' => [
916  'columns' => [
917  'fieldA' => [],
918  ],
919  'types' => [
920  'typeA' => [
921  'showitem' => 'fieldA, --palette--;;generatedFor-fieldA',
922  ],
923  ],
924  'palettes' => [
925  'generatedFor-fieldA' => [
926  'showitem' => 'newA',
927  ],
928  ],
929  ],
930  ];
932  'aTable',
933  'fieldA',
934  'newA'
935  );
936  self::assertEquals($expected, ‪$GLOBALS['TCA']);
937  }
938 
942  public function addFieldsToAllPalettesOfFieldAddsNewPaletteIfFieldHasNoPaletteYetAndKeepsExistingLabel()
943  {
944  ‪$GLOBALS['TCA'] = [
945  'aTable' => [
946  'columns' => [
947  'fieldA' => [],
948  ],
949  'types' => [
950  'typeA' => [
951  'showitem' => 'fieldA;labelA',
952  ],
953  ],
954  ],
955  ];
956  $expected = [
957  'aTable' => [
958  'columns' => [
959  'fieldA' => [],
960  ],
961  'types' => [
962  'typeA' => [
963  'showitem' => 'fieldA;labelA, --palette--;;generatedFor-fieldA',
964  ],
965  ],
966  'palettes' => [
967  'generatedFor-fieldA' => [
968  'showitem' => 'newA',
969  ],
970  ],
971  ],
972  ];
974  'aTable',
975  'fieldA',
976  'newA'
977  );
978  self::assertEquals($expected, ‪$GLOBALS['TCA']);
979  }
980 
982  // Tests concerning executePositionedStringInsertion
984 
989  public function executePositionedStringInsertionTrimsCorrectCharactersDataProvider()
990  {
991  return [
992  'normal characters' => [
993  'tr0',
994  'tr0',
995  ],
996  'newlines' => [
997  "test\n",
998  'test',
999  ],
1000  'newlines with carriage return' => [
1001  "test\r\n",
1002  'test',
1003  ],
1004  'tabs' => [
1005  "test\t",
1006  'test',
1007  ],
1008  'commas' => [
1009  'test,',
1010  'test',
1011  ],
1012  'multiple commas with trailing spaces' => [
1013  "test,,\t, \r\n",
1014  'test',
1015  ],
1016  ];
1017  }
1018 
1025  public function executePositionedStringInsertionTrimsCorrectCharacters($string, $expectedResult)
1026  {
1027  $extensionManagementUtility = $this->getAccessibleMock(ExtensionManagementUtility::class, ['dummy']);
1028  $string = $extensionManagementUtility->_call('executePositionedStringInsertion', $string, '');
1029  self::assertEquals($expectedResult, $string);
1030  }
1031 
1033  // Tests concerning addTcaSelectItem
1035 
1038  public function addTcaSelectItemThrowsExceptionIfTableIsNotOfTypeString()
1039  {
1040  $this->expectException(\InvalidArgumentException::class);
1041  $this->expectExceptionCode(1303236963);
1042 
1044  }
1045 
1049  public function addTcaSelectItemThrowsExceptionIfFieldIsNotOfTypeString()
1050  {
1051  $this->expectException(\InvalidArgumentException::class);
1052  $this->expectExceptionCode(1303236964);
1053 
1055  }
1056 
1060  public function addTcaSelectItemThrowsExceptionIfRelativeToFieldIsNotOfTypeString()
1061  {
1062  $this->expectException(\InvalidArgumentException::class);
1063  $this->expectExceptionCode(1303236965);
1064 
1066  }
1067 
1071  public function addTcaSelectItemThrowsExceptionIfRelativePositionIsNotOfTypeString()
1072  {
1073  $this->expectException(\InvalidArgumentException::class);
1074  $this->expectExceptionCode(1303236966);
1075 
1076  ‪ExtensionManagementUtility::addTcaSelectItem('foo', 'bar', [], 'foo', []);
1077  }
1078 
1082  public function addTcaSelectItemThrowsExceptionIfRelativePositionIsNotOneOfValidKeywords()
1083  {
1084  $this->expectException(\InvalidArgumentException::class);
1085  $this->expectExceptionCode(1303236967);
1086 
1087  ‪ExtensionManagementUtility::addTcaSelectItem('foo', 'bar', [], 'foo', 'not allowed keyword');
1088  }
1089 
1093  public function addTcaSelectItemThrowsExceptionIfFieldIsNotFoundInTca()
1094  {
1095  $this->expectException(\RuntimeException::class);
1096  $this->expectExceptionCode(1303237468);
1097 
1098  ‪$GLOBALS['TCA'] = [];
1100  }
1101 
1105  public function addTcaSelectItemDataProvider()
1106  {
1107  // Every array splits into:
1108  // - relativeToField
1109  // - relativePosition
1110  // - expectedResultArray
1111  return [
1112  'add at end of array' => [
1113  '',
1114  '',
1115  [
1116  0 => ['firstElement'],
1117  1 => ['matchMe'],
1118  2 => ['thirdElement'],
1119  3 => ['insertedElement']
1120  ]
1121  ],
1122  'replace element' => [
1123  'matchMe',
1124  'replace',
1125  [
1126  0 => ['firstElement'],
1127  1 => ['insertedElement'],
1128  2 => ['thirdElement']
1129  ]
1130  ],
1131  'add element after' => [
1132  'matchMe',
1133  'after',
1134  [
1135  0 => ['firstElement'],
1136  1 => ['matchMe'],
1137  2 => ['insertedElement'],
1138  3 => ['thirdElement']
1139  ]
1140  ],
1141  'add element before' => [
1142  'matchMe',
1143  'before',
1144  [
1145  0 => ['firstElement'],
1146  1 => ['insertedElement'],
1147  2 => ['matchMe'],
1148  3 => ['thirdElement']
1149  ]
1150  ],
1151  'add at end if relative position was not found' => [
1152  'notExistingItem',
1153  'after',
1154  [
1155  0 => ['firstElement'],
1156  1 => ['matchMe'],
1157  2 => ['thirdElement'],
1158  3 => ['insertedElement']
1159  ]
1160  ]
1161  ];
1162  }
1163 
1171  public function addTcaSelectItemInsertsItemAtSpecifiedPosition($relativeToField, $relativePosition, $expectedResultArray)
1172  {
1173  ‪$GLOBALS['TCA'] = [
1174  'testTable' => [
1175  'columns' => [
1176  'testField' => [
1177  'config' => [
1178  'items' => [
1179  '0' => ['firstElement'],
1180  '1' => ['matchMe'],
1181  2 => ['thirdElement']
1182  ]
1183  ]
1184  ]
1185  ]
1186  ]
1187  ];
1188  ‪ExtensionManagementUtility::addTcaSelectItem('testTable', 'testField', ['insertedElement'], $relativeToField, $relativePosition);
1189  self::assertEquals($expectedResultArray, ‪$GLOBALS['TCA']['testTable']['columns']['testField']['config']['items']);
1190  }
1191 
1193  // Tests concerning loadExtLocalconf
1195 
1198  public function loadExtLocalconfDoesNotReadFromCacheIfCachingIsDenied()
1199  {
1201  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1202  ->setMethods(['getCache'])
1203  ->getMock();
1204  $mockCacheManager->expects(self::never())->method('getCache');
1206  $packageManager = $this->createMockPackageManagerWithMockPackage(‪StringUtility::getUniqueId());
1209  }
1210 
1214  public function loadExtLocalconfRequiresCacheFileIfExistsAndCachingIsAllowed()
1215  {
1216  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1217  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1218  ->disableOriginalConstructor()
1219  ->getMock();
1220 
1222  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1223  ->setMethods(['getCache'])
1224  ->getMock();
1225  $mockCacheManager->expects(self::any())->method('getCache')->willReturn($mockCache);
1227  $mockCache->expects(self::any())->method('has')->willReturn(true);
1228  $mockCache->expects(self::once())->method('require');
1230  }
1231 
1233  // Tests concerning loadSingleExtLocalconfFiles
1235 
1238  public function loadSingleExtLocalconfFilesRequiresExtLocalconfFileRegisteredInGlobalTypo3LoadedExt()
1239  {
1240  $this->expectException(\RuntimeException::class);
1241  $this->expectExceptionCode(1340559079);
1242 
1243  $extensionName = ‪StringUtility::getUniqueId('foo');
1244  $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1245  $extLocalconfLocation = $packageManager->getPackage($extensionName)->getPackagePath() . 'ext_localconf.php';
1246  file_put_contents($extLocalconfLocation, "<?php\n\nthrow new RuntimeException('', 1340559079);\n\n?>");
1249  }
1250 
1252  // Tests concerning addModule
1254 
1259  public function addModulePositionTestsDataProvider()
1260  {
1261  return [
1262  'can add new main module if none exists' => [
1263  'top',
1264  '',
1265  'newModule'
1266  ],
1267  'can add new sub module if no position specified' => [
1268  '',
1269  'some,modules',
1270  'some,modules,newModule'
1271  ],
1272  'can add new sub module to top of module' => [
1273  'top',
1274  'some,modules',
1275  'newModule,some,modules'
1276  ],
1277  'can add new sub module if bottom of module' => [
1278  'bottom',
1279  'some,modules',
1280  'some,modules,newModule'
1281  ],
1282  'can add new sub module before specified sub module' => [
1283  'before:modules',
1284  'some,modules',
1285  'some,newModule,modules'
1286  ],
1287  'can add new sub module after specified sub module' => [
1288  'after:some',
1289  'some,modules',
1290  'some,newModule,modules'
1291  ],
1292  'can add new sub module at the bottom if specified sub module to add before does not exist' => [
1293  'before:modules',
1294  'some,otherModules',
1295  'some,otherModules,newModule'
1296  ],
1297  'can add new sub module at the bottom if specified sub module to add after does not exist' => [
1298  'after:some',
1299  'someOther,modules',
1300  'someOther,modules,newModule'
1301  ],
1302  ];
1303  }
1304 
1312  public function addModuleCanAddModule($position, $existing, $expected)
1313  {
1314  $mainModule = 'foobar';
1315  $subModule = 'newModule';
1316  if ($existing) {
1317  ‪$GLOBALS['TBE_MODULES'][$mainModule] = $existing;
1318  }
1319 
1320  ‪ExtensionManagementUtility::addModule($mainModule, $subModule, $position);
1321 
1322  self::assertTrue(isset(‪$GLOBALS['TBE_MODULES'][$mainModule]));
1323  self::assertEquals($expected, ‪$GLOBALS['TBE_MODULES'][$mainModule]);
1324  }
1325 
1333  public function addModuleCanAddMainModule($position, $existing, $expected)
1334  {
1335  $mainModule = 'newModule';
1336  if ($existing) {
1337  foreach (explode(',', $existing) as $existingMainModule) {
1338  ‪$GLOBALS['TBE_MODULES'][$existingMainModule] = '';
1339  }
1340  }
1341 
1342  ‪ExtensionManagementUtility::addModule($mainModule, '', $position);
1343 
1344  self::assertTrue(isset(‪$GLOBALS['TBE_MODULES'][$mainModule]));
1345  unset(‪$GLOBALS['TBE_MODULES']['_configuration']);
1346  unset(‪$GLOBALS['TBE_MODULES']['_navigationComponents']);
1347  self::assertEquals($expected, implode(',', array_keys(‪$GLOBALS['TBE_MODULES'])));
1348  }
1349 
1351  // Tests concerning createExtLocalconfCacheEntry
1353 
1356  public function createExtLocalconfCacheEntryWritesCacheEntryWithContentOfLoadedExtensionExtLocalconf()
1357  {
1358  $extensionName = ‪StringUtility::getUniqueId('foo');
1359  $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1360  $extLocalconfLocation = $packageManager->getPackage($extensionName)->getPackagePath() . 'ext_localconf.php';
1361  $uniqueStringInLocalconf = ‪StringUtility::getUniqueId('foo');
1362  file_put_contents($extLocalconfLocation, "<?php\n\n" . $uniqueStringInLocalconf . "\n\n?>");
1364  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1365  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1366  ->disableOriginalConstructor()
1367  ->getMock();
1368 
1369  $mockCache->expects(self::once())->method('set')->with(self::anything(), self::stringContains($uniqueStringInLocalconf), self::anything());
1371  }
1372 
1376  public function createExtLocalconfCacheEntryWritesCacheEntryWithExtensionContentOnlyIfExtLocalconfExists()
1377  {
1378  $extensionName = ‪StringUtility::getUniqueId('foo');
1379  $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1381  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1382  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1383  ->disableOriginalConstructor()
1384  ->getMock();
1385 
1386  $mockCache->expects(self::once())
1387  ->method('set')
1388  ->with(self::anything(), self::logicalNot(self::stringContains($extensionName)), self::anything());
1390  }
1391 
1395  public function createExtLocalconfCacheEntryWritesCacheEntryWithNoTags()
1396  {
1397  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1398  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1399  ->disableOriginalConstructor()
1400  ->getMock();
1401  $mockCache->expects(self::once())->method('set')->with(self::anything(), self::anything(), self::equalTo([]));
1402  $packageManager = $this->createMockPackageManagerWithMockPackage(‪StringUtility::getUniqueId());
1405  }
1406 
1408  // Tests concerning getExtLocalconfCacheIdentifier
1410 
1413  public function getExtLocalconfCacheIdentifierCreatesSha1WithFourtyCharactersAndPrefix()
1414  {
1415  $prefix = 'ext_localconf_';
1417  self::assertStringStartsWith($prefix, $identifier);
1418  $sha1 = str_replace($prefix, '', $identifier);
1419  self::assertEquals(40, strlen($sha1));
1420  }
1421 
1423  // Tests concerning loadBaseTca
1425 
1429  public function loadBaseTcaDoesNotReadFromCacheIfCachingIsDenied()
1430  {
1432  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1433  ->setMethods(['getCache'])
1434  ->getMock();
1435  $mockCacheManager->expects(self::never())->method('getCache');
1438  }
1439 
1443  public function loadBaseTcaRequiresCacheFileIfExistsAndCachingIsAllowed()
1444  {
1445  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1446  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1447  ->disableOriginalConstructor()
1448  ->getMock();
1449 
1450  $mockCache->expects(self::once())->method('require')->willReturn(['tca' => [], 'categoryRegistry' => \serialize(‪CategoryRegistry::getInstance())]);
1452  }
1453 
1457  public function loadBaseTcaCreatesCacheFileWithContentOfAnExtensionsConfigurationTcaPhpFile()
1458  {
1459  $extensionName = ‪StringUtility::getUniqueId('test_baseTca_');
1460  $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1461  $packagePath = $packageManager->getPackage($extensionName)->getPackagePath();
1462  ‪GeneralUtility::mkdir($packagePath);
1463  ‪GeneralUtility::mkdir($packagePath . 'Configuration/');
1464  ‪GeneralUtility::mkdir($packagePath . 'Configuration/TCA/');
1466  $uniqueTableName = ‪StringUtility::getUniqueId('table_name_');
1467  $uniqueStringInTableConfiguration = ‪StringUtility::getUniqueId('table_configuration_');
1468  $tableConfiguration = '<?php return array(\'foo\' => \'' . $uniqueStringInTableConfiguration . '\'); ?>';
1469  file_put_contents($packagePath . 'Configuration/TCA/' . $uniqueTableName . '.php', $tableConfiguration);
1470  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1471  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1472  ->disableOriginalConstructor()
1473  ->getMock();
1474 
1476  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1477  ->setMethods(['getCache'])
1478  ->getMock();
1479  $mockCacheManager->expects(self::any())->method('getCache')->willReturn($mockCache);
1480  ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1481  $mockCache->expects(self::once())->method('require')->willReturn(false);
1482  $mockCache->expects(self::once())->method('set')->with(self::anything(), self::stringContains($uniqueStringInTableConfiguration), self::anything());
1483 
1484  $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
1485  $eventDispatcher->dispatch(Argument::any())->shouldBeCalled()->willReturnArgument(0);
1486  ExtensionManagementUtility::setEventDispatcher($eventDispatcher->reveal());
1487 
1488  ExtensionManagementUtility::loadBaseTca(true);
1489  }
1490 
1494  public function loadBaseTcaWritesCacheEntryWithNoTags()
1495  {
1496  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1497  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1498  ->disableOriginalConstructor()
1499  ->getMock();
1500 
1502  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1503  ->setMethods(['getCache'])
1504  ->getMock();
1505  $mockCacheManager->expects(self::any())->method('getCache')->willReturn($mockCache);
1506  ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1507  $mockCache->expects(self::once())->method('require')->willReturn(false);
1508  $mockCache->expects(self::once())->method('set')->with(self::anything(), self::anything(), self::equalTo([]));
1509  ExtensionManagementUtilityAccessibleProxy::loadBaseTca();
1510  }
1511 
1513  // Tests concerning getBaseTcaCacheIdentifier
1515 
1519  public function getBaseTcaCacheIdentifierCreatesSha1WithFourtyCharactersAndPrefix()
1520  {
1521  $prefix = 'tca_base_';
1522  $identifier = ExtensionManagementUtilityAccessibleProxy::getBaseTcaCacheIdentifier();
1523  self::assertStringStartsWith($prefix, $identifier);
1524  $sha1 = str_replace($prefix, '', $identifier);
1525  self::assertEquals(40, strlen($sha1));
1526  }
1527 
1529  // Tests concerning loadExtTables
1531 
1534  public function loadExtTablesDoesNotReadFromCacheIfCachingIsDenied()
1535  {
1537  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1538  ->setMethods(['getCache'])
1539  ->getMock();
1540  $mockCacheManager->expects(self::never())->method('getCache');
1541  ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1542  $packageManager = $this->createMockPackageManagerWithMockPackage(StringUtility::getUniqueId());
1543  ExtensionManagementUtility::setPackageManager($packageManager);
1544  ExtensionManagementUtility::loadExtLocalconf(false);
1545  }
1546 
1550  public function loadExtTablesRequiresCacheFileIfExistsAndCachingIsAllowed()
1551  {
1552  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1553  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1554  ->disableOriginalConstructor()
1555  ->getMock();
1556 
1558  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1559  ->setMethods(['getCache'])
1560  ->getMock();
1561  $mockCacheManager->expects(self::any())->method('getCache')->willReturn($mockCache);
1562  ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1563  $mockCache->expects(self::any())->method('has')->willReturn(true);
1564  $mockCache->expects(self::once())->method('require');
1565  // Reset the internal cache access tracking variable of extMgm
1566  // This method is only in the ProxyClass!
1567  ExtensionManagementUtilityAccessibleProxy::resetExtTablesWasReadFromCacheOnceBoolean();
1568  ExtensionManagementUtility::loadExtTables(true);
1569  }
1570 
1572  // Tests concerning createExtTablesCacheEntry
1574 
1577  public function createExtTablesCacheEntryWritesCacheEntryWithContentOfLoadedExtensionExtTables()
1578  {
1579  $extensionName = StringUtility::getUniqueId('foo');
1580  $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1581  $extensionPath = $packageManager->getPackage($extensionName)->getPackagePath();
1582  $extTablesLocation = $extensionPath . 'ext_tables.php';
1583  $uniqueStringInTables = StringUtility::getUniqueId('foo');
1584  file_put_contents($extTablesLocation, "<?php\n\n$uniqueStringInTables\n\n?>");
1585  ExtensionManagementUtility::setPackageManager($packageManager);
1586  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1587  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1588  ->disableOriginalConstructor()
1589  ->getMock();
1590 
1592  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1593  ->setMethods(['getCache'])
1594  ->getMock();
1595  $mockCacheManager->expects(self::any())->method('getCache')->willReturn($mockCache);
1596  ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1597  $mockCache->expects(self::once())->method('set')->with(self::anything(), self::stringContains($uniqueStringInTables), self::anything());
1598  ExtensionManagementUtilityAccessibleProxy::createExtTablesCacheEntry();
1599  }
1600 
1604  public function createExtTablesCacheEntryWritesCacheEntryWithExtensionContentOnlyIfExtTablesExists()
1605  {
1606  $extensionName = StringUtility::getUniqueId('foo');
1607  $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1608  ExtensionManagementUtility::setPackageManager($packageManager);
1609  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1610  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1611  ->disableOriginalConstructor()
1612  ->getMock();
1613 
1615  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1616  ->setMethods(['getCache'])
1617  ->getMock();
1618  $mockCacheManager->expects(self::any())->method('getCache')->willReturn($mockCache);
1619  ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1620  $mockCache->expects(self::once())
1621  ->method('set')
1622  ->with(self::anything(), self::logicalNot(self::stringContains($extensionName)), self::anything());
1623  ExtensionManagementUtilityAccessibleProxy::createExtTablesCacheEntry();
1624  }
1625 
1629  public function createExtTablesCacheEntryWritesCacheEntryWithNoTags()
1630  {
1631  $mockCache = $this->getMockBuilder(PhpFrontend::class)
1632  ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1633  ->disableOriginalConstructor()
1634  ->getMock();
1635 
1637  $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1638  ->setMethods(['getCache'])
1639  ->getMock();
1640  $mockCacheManager->expects(self::any())->method('getCache')->willReturn($mockCache);
1641  ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1642  $mockCache->expects(self::once())->method('set')->with(self::anything(), self::anything(), self::equalTo([]));
1643  $packageManager = $this->createMockPackageManagerWithMockPackage(StringUtility::getUniqueId());
1644  ExtensionManagementUtility::setPackageManager($packageManager);
1645  ExtensionManagementUtilityAccessibleProxy::createExtTablesCacheEntry();
1646  }
1647 
1649  // Tests concerning getExtTablesCacheIdentifier
1651 
1654  public function getExtTablesCacheIdentifierCreatesSha1WithFourtyCharactersAndPrefix()
1655  {
1656  $prefix = 'ext_tables_';
1657  $identifier = ExtensionManagementUtilityAccessibleProxy::getExtTablesCacheIdentifier();
1658  self::assertStringStartsWith($prefix, $identifier);
1659  $sha1 = str_replace($prefix, '', $identifier);
1660  self::assertEquals(40, strlen($sha1));
1661  }
1662 
1664  // Tests concerning getExtensionVersion
1666 
1671  public function getExtensionVersionFaultyDataProvider()
1672  {
1673  return [
1674  [''],
1675  [0],
1676  [new \stdClass()],
1677  [true]
1678  ];
1679  }
1680 
1687  public function getExtensionVersionForFaultyExtensionKeyThrowsException($key)
1688  {
1689  $this->expectException(\InvalidArgumentException::class);
1690  $this->expectExceptionCode(1294586096);
1691 
1692  ExtensionManagementUtility::getExtensionVersion($key);
1693  }
1694 
1698  public function getExtensionVersionForNotLoadedExtensionReturnsEmptyString()
1699  {
1700  $uniqueSuffix = StringUtility::getUniqueId('test');
1701  $extensionKey = 'unloadedextension' . $uniqueSuffix;
1702  self::assertEquals('', ExtensionManagementUtility::getExtensionVersion($extensionKey));
1703  }
1704 
1708  public function getExtensionVersionForLoadedExtensionReturnsExtensionVersion()
1709  {
1710  $uniqueSuffix = StringUtility::getUniqueId('test');
1711  $extensionKey = 'unloadedextension' . $uniqueSuffix;
1712  $packageMetaData = $this->getMockBuilder(MetaData::class)
1713  ->setMethods(['getVersion'])
1714  ->setConstructorArgs([$extensionKey])
1715  ->getMock();
1716  $packageMetaData->expects(self::any())->method('getVersion')->willReturn('1.2.3');
1717  $packageManager = $this->createMockPackageManagerWithMockPackage($extensionKey, ['getPackagePath', 'getPackageKey', 'getPackageMetaData']);
1719  $package = $packageManager->getPackage($extensionKey);
1720  $package->expects(self::any())
1721  ->method('getPackageMetaData')
1722  ->willReturn($packageMetaData);
1723  ExtensionManagementUtility::setPackageManager($packageManager);
1724  self::assertEquals('1.2.3', ExtensionManagementUtility::getExtensionVersion($extensionKey));
1725  }
1726 
1728  // Tests concerning loadExtension
1730 
1733  public function loadExtensionThrowsExceptionIfExtensionIsLoaded()
1734  {
1735  $this->expectException(\RuntimeException::class);
1736  $this->expectExceptionCode(1342345486);
1737 
1738  $extensionKey = StringUtility::getUniqueId('test');
1739  $packageManager = $this->createMockPackageManagerWithMockPackage($extensionKey);
1740  ExtensionManagementUtility::setPackageManager($packageManager);
1741  ExtensionManagementUtility::loadExtension($extensionKey);
1742  }
1743 
1745  // Tests concerning unloadExtension
1747 
1750  public function unloadExtensionThrowsExceptionIfExtensionIsNotLoaded()
1751  {
1752  $this->expectException(\RuntimeException::class);
1753  $this->expectExceptionCode(1342345487);
1754 
1755  $packageName = StringUtility::getUniqueId('foo');
1757  $packageManager = $this->getMockBuilder(PackageManager::class)
1758  ->setMethods(['isPackageActive'])
1759  ->disableOriginalConstructor()
1760  ->getMock();
1761  $packageManager->expects(self::once())
1762  ->method('isPackageActive')
1763  ->with(self::equalTo($packageName))
1764  ->willReturn(false);
1765  ExtensionManagementUtility::setPackageManager($packageManager);
1766  ExtensionManagementUtility::unloadExtension($packageName);
1767  }
1768 
1772  public function unloadExtensionCallsPackageManagerToDeactivatePackage()
1773  {
1774  $packageName = StringUtility::getUniqueId('foo');
1776  $packageManager = $this->getMockBuilder(PackageManager::class)
1777  ->setMethods(['isPackageActive', 'deactivatePackage'])
1778  ->disableOriginalConstructor()
1779  ->getMock();
1780  $packageManager->expects(self::any())
1781  ->method('isPackageActive')
1782  ->willReturn(true);
1783  $packageManager->expects(self::once())
1784  ->method('deactivatePackage')
1785  ->with($packageName);
1786  ExtensionManagementUtility::setPackageManager($packageManager);
1787  ExtensionManagementUtility::unloadExtension($packageName);
1788  }
1789 
1791  // Tests concerning makeCategorizable
1793 
1796  public function doesMakeCategorizableCallsTheCategoryRegistryWithDefaultFieldName()
1797  {
1798  $extensionKey = StringUtility::getUniqueId('extension');
1799  $tableName = StringUtility::getUniqueId('table');
1800 
1802  $registryMock = $this->getMockBuilder(CategoryRegistry::class)->getMock();
1803  $registryMock->expects(self::once())->method('add')->with($extensionKey, $tableName, 'categories', []);
1804  GeneralUtility::setSingletonInstance(CategoryRegistry::class, $registryMock);
1805  ExtensionManagementUtility::makeCategorizable($extensionKey, $tableName);
1806  }
1807 
1811  public function doesMakeCategorizableCallsTheCategoryRegistryWithFieldName()
1812  {
1813  $extensionKey = StringUtility::getUniqueId('extension');
1814  $tableName = StringUtility::getUniqueId('table');
1815  $fieldName = StringUtility::getUniqueId('field');
1816 
1818  $registryMock = $this->getMockBuilder(CategoryRegistry::class)->getMock();
1819  $registryMock->expects(self::once())->method('add')->with($extensionKey, $tableName, $fieldName, []);
1820  GeneralUtility::setSingletonInstance(CategoryRegistry::class, $registryMock);
1821  ExtensionManagementUtility::makeCategorizable($extensionKey, $tableName, $fieldName);
1822  }
1823 
1825  // Tests concerning addPlugin
1827 
1831  public function addPluginSetsTcaCorrectlyForGivenExtKeyAsParameter()
1832  {
1833  $extKey = 'indexed_search';
1834  $expectedTCA = [
1835  [
1836  'label',
1837  $extKey,
1838  'EXT:' . $extKey . '/Resources/Public/Icons/Extension.png',
1839  'default'
1840  ]
1841  ];
1842  $GLOBALS['TCA']['tt_content']['columns']['list_type']['config']['items'] = [];
1843  ExtensionManagementUtility::addPlugin(['label', $extKey], 'list_type', $extKey);
1844  self::assertEquals($expectedTCA, $GLOBALS['TCA']['tt_content']['columns']['list_type']['config']['items']);
1845  }
1846 
1850  public function addPluginThrowsExceptionForMissingExtkey()
1851  {
1852  $this->expectException(\InvalidArgumentException::class);
1853  $this->expectExceptionCode(1404068038);
1854 
1855  ExtensionManagementUtility::addPlugin('test');
1856  }
1857 
1858  public function addTcaSelectItemGroupAddsGroupDataProvider()
1859  {
1860  return [
1861  'add the first group' => [
1862  'my_group',
1863  'my_group_label',
1864  null,
1865  null,
1866  [
1867  'my_group' => 'my_group_label'
1868  ]
1869  ],
1870  'add a new group at the bottom' => [
1871  'my_group',
1872  'my_group_label',
1873  'bottom',
1874  [
1875  'default' => 'default_label'
1876  ],
1877  [
1878  'default' => 'default_label',
1879  'my_group' => 'my_group_label'
1880  ]
1881  ],
1882  'add a new group at the top' => [
1883  'my_group',
1884  'my_group_label',
1885  'top',
1886  [
1887  'default' => 'default_label'
1888  ],
1889  [
1890  'my_group' => 'my_group_label',
1891  'default' => 'default_label'
1892  ]
1893  ],
1894  'add a new group after an existing group' => [
1895  'my_group',
1896  'my_group_label',
1897  'after:default',
1898  [
1899  'default' => 'default_label',
1900  'special' => 'special_label'
1901  ],
1902  [
1903  'default' => 'default_label',
1904  'my_group' => 'my_group_label',
1905  'special' => 'special_label'
1906  ]
1907  ],
1908  'add a new group before an existing group' => [
1909  'my_group',
1910  'my_group_label',
1911  'before:default',
1912  [
1913  'default' => 'default_label',
1914  'special' => 'special_label'
1915  ],
1916  [
1917  'my_group' => 'my_group_label',
1918  'default' => 'default_label',
1919  'special' => 'special_label'
1920  ]
1921  ],
1922  'add a new group after a non-existing group moved to bottom' => [
1923  'my_group',
1924  'my_group_label',
1925  'after:default2',
1926  [
1927  'default' => 'default_label',
1928  'special' => 'special_label'
1929  ],
1930  [
1931  'default' => 'default_label',
1932  'special' => 'special_label',
1933  'my_group' => 'my_group_label',
1934  ]
1935  ],
1936  'add a new group which already exists does nothing' => [
1937  'my_group',
1938  'my_group_label',
1939  'does-not-matter',
1940  [
1941  'default' => 'default_label',
1942  'my_group' => 'existing_label',
1943  'special' => 'special_label'
1944  ],
1945  [
1946  'default' => 'default_label',
1947  'my_group' => 'existing_label',
1948  'special' => 'special_label'
1949  ]
1950  ],
1951  ];
1952  }
1953 
1963  public function addTcaSelectItemGroupAddsGroup(string $groupId, string $groupLabel, ?string $position, ?array $existingGroups, array $expectedGroups)
1964  {
1965  $GLOBALS['TCA']['tt_content']['columns']['CType']['config'] = [];
1966  if (is_array($existingGroups)) {
1967  $GLOBALS['TCA']['tt_content']['columns']['CType']['config']['itemGroups'] = $existingGroups;
1968  }
1969  ExtensionManagementUtility::addTcaSelectItemGroup('tt_content', 'CType', $groupId, $groupLabel, $position);
1970  self::assertEquals($expectedGroups, $GLOBALS['TCA']['tt_content']['columns']['CType']['config']['itemGroups']);
1971  }
1972 }
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addModule
‪static addModule($main, $sub='', $position='', $path=null, $moduleConfiguration=[])
Definition: ExtensionManagementUtility.php:820
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:180
‪TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy\setCacheManager
‪static setCacheManager(CacheManager $cacheManager=null)
Definition: ExtensionManagementUtilityAccessibleProxy.php:27
‪TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy\loadSingleExtLocalconfFiles
‪static loadSingleExtLocalconfFiles()
Definition: ExtensionManagementUtilityAccessibleProxy.php:42
‪TYPO3\CMS\Core\Cache\Frontend\PhpFrontend
Definition: PhpFrontend.php:25
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToPalette
‪static addFieldsToPalette($table, $palette, $addFields, $insertionPosition='')
Definition: ExtensionManagementUtility.php:390
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTcaSelectItem
‪static addTcaSelectItem($table, $field, array $item, $relativeToField='', $relativePosition='')
Definition: ExtensionManagementUtility.php:431
‪TYPO3\CMS\Core\Tests\Unit\Utility
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addToAllTCAtypes
‪static addToAllTCAtypes($table, $newFieldsString, $typeList='', $position='')
Definition: ExtensionManagementUtility.php:209
‪TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy\removeDuplicatesForInsertion
‪static removeDuplicatesForInsertion($insertionList, $list='')
Definition: ExtensionManagementUtilityAccessibleProxy.php:81
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToAllPalettesOfField
‪static addFieldsToAllPalettesOfField($table, $field, $addFields, $insertionPosition='')
Definition: ExtensionManagementUtility.php:337
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Core\Category\CategoryRegistry\getInstance
‪static CategoryRegistry getInstance()
Definition: CategoryRegistry.php:52
‪TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy\getExtLocalconfCacheIdentifier
‪static getExtLocalconfCacheIdentifier()
Definition: ExtensionManagementUtilityAccessibleProxy.php:37
‪TYPO3\CMS\Core\Category\CategoryRegistry
Definition: CategoryRegistry.php:29
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\setPackageManager
‪static setPackageManager(PackageManager $packageManager)
Definition: ExtensionManagementUtility.php:66
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir_deep
‪static mkdir_deep($directory)
Definition: GeneralUtility.php:2022
‪TYPO3\CMS\Core\Package\Package
Definition: Package.php:26
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:35
‪TYPO3\CMS\Core\Package\MetaData
Definition: PackageConstraint.php:16
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getCN
‪static string getCN($key)
Definition: ExtensionManagementUtility.php:142
‪TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy\getPackageManager
‪static getPackageManager()
Definition: ExtensionManagementUtilityAccessibleProxy.php:32
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:92
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy\createExtLocalconfCacheEntry
‪static createExtLocalconfCacheEntry(FrontendInterface $cache)
Definition: ExtensionManagementUtilityAccessibleProxy.php:57
‪$tca
‪$tca
Definition: sys_file_metadata.php:5
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:127
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadBaseTca
‪static loadBaseTca($allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1637
‪TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy
Definition: ExtensionManagementUtilityAccessibleProxy.php:26
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtLocalconf
‪static loadExtLocalconf($allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1550
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:22
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir
‪static bool mkdir($newFolder)
Definition: GeneralUtility.php:2005
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key)
Definition: ExtensionManagementUtility.php:114
‪TYPO3\CMS\Core\Core\Environment\getVarPath
‪static string getVarPath()
Definition: Environment.php:192