[TASK] Mock SignalSlot\Dispatcher Singletons in unit tests
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Utility / ExtensionManagementUtilityTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Utility;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Cache\CacheManager;
18 use TYPO3\CMS\Core\Cache\Frontend\PhpFrontend;
19 use TYPO3\CMS\Core\Category\CategoryRegistry;
20 use TYPO3\CMS\Core\Core\Environment;
21 use TYPO3\CMS\Core\Package\MetaData;
22 use TYPO3\CMS\Core\Package\Package;
23 use TYPO3\CMS\Core\Package\PackageManager;
24 use TYPO3\CMS\Core\Tests\Unit\Utility\AccessibleProxies\ExtensionManagementUtilityAccessibleProxy;
25 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Extbase\SignalSlot\Dispatcher as SignalSlotDispatcher;
28 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
29
30 /**
31 * Test case
32 */
33 class ExtensionManagementUtilityTest extends UnitTestCase
34 {
35 /**
36 * @var bool Reset singletons created by subject
37 */
38 protected $resetSingletonInstances = true;
39
40 /**
41 * @var \TYPO3\CMS\Core\Package\PackageManager
42 */
43 protected $backUpPackageManager;
44
45 /**
46 * Set up
47 */
48 protected function setUp()
49 {
50 $this->backUpPackageManager = ExtensionManagementUtilityAccessibleProxy::getPackageManager();
51 }
52
53 /**
54 * Tear down
55 */
56 protected function tearDown()
57 {
58 ExtensionManagementUtilityAccessibleProxy::setPackageManager($this->backUpPackageManager);
59 ExtensionManagementUtilityAccessibleProxy::setCacheManager(null);
60 ExtensionManagementUtilityAccessibleProxy::setSignalSlotDispatcher(null);
61 parent::tearDown();
62 }
63
64 /**
65 * @param string $packageKey
66 * @param array $packageMethods
67 * @return PackageManager|\PHPUnit_Framework_MockObject_MockObject
68 */
69 protected function createMockPackageManagerWithMockPackage($packageKey, $packageMethods = ['getPackagePath', 'getPackageKey'])
70 {
71 $packagePath = Environment::getVarPath() . '/tests/' . $packageKey . '/';
72 GeneralUtility::mkdir_deep($packagePath);
73 $this->testFilesToDelete[] = $packagePath;
74 $package = $this->getMockBuilder(Package::class)
75 ->disableOriginalConstructor()
76 ->setMethods($packageMethods)
77 ->getMock();
78 $packageManager = $this->getMockBuilder(PackageManager::class)
79 ->setMethods(['isPackageActive', 'getPackage', 'getActivePackages'])
80 ->disableOriginalConstructor()
81 ->getMock();
82 $package->expects($this->any())
83 ->method('getPackagePath')
84 ->will($this->returnValue($packagePath));
85 $package->expects($this->any())
86 ->method('getPackageKey')
87 ->will($this->returnValue($packageKey));
88 $packageManager->expects($this->any())
89 ->method('isPackageActive')
90 ->will($this->returnValueMap([
91 [null, false],
92 [$packageKey, true]
93 ]));
94 $packageManager->expects($this->any())
95 ->method('getPackage')
96 ->with($this->equalTo($packageKey))
97 ->will($this->returnValue($package));
98 $packageManager->expects($this->any())
99 ->method('getActivePackages')
100 ->will($this->returnValue([$packageKey => $package]));
101 return $packageManager;
102 }
103
104 ///////////////////////////////
105 // Tests concerning isLoaded
106 ///////////////////////////////
107 /**
108 * @test
109 */
110 public function isLoadedReturnsFalseIfExtensionIsNotLoaded()
111 {
112 $this->assertFalse(ExtensionManagementUtility::isLoaded($this->getUniqueId('foobar')));
113 }
114
115 ///////////////////////////////
116 // Tests concerning extPath
117 ///////////////////////////////
118 /**
119 * @test
120 */
121 public function extPathThrowsExceptionIfExtensionIsNotLoaded()
122 {
123 $this->expectException(\BadFunctionCallException::class);
124 $this->expectExceptionCode(1365429656);
125
126 $packageName = $this->getUniqueId('foo');
127 /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
128 $packageManager = $this->getMockBuilder(PackageManager::class)
129 ->setMethods(['isPackageActive'])
130 ->disableOriginalConstructor()
131 ->getMock();
132 $packageManager->expects($this->once())
133 ->method('isPackageActive')
134 ->with($this->equalTo($packageName))
135 ->will($this->returnValue(false));
136 ExtensionManagementUtility::setPackageManager($packageManager);
137 ExtensionManagementUtility::extPath($packageName);
138 }
139
140 /**
141 * @test
142 */
143 public function extPathAppendsScriptNameToPath()
144 {
145 $package = $this->getMockBuilder(Package::class)
146 ->disableOriginalConstructor()
147 ->setMethods(['getPackagePath'])
148 ->getMock();
149 /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
150 $packageManager = $this->getMockBuilder(PackageManager::class)
151 ->setMethods(['isPackageActive', 'getPackage'])
152 ->disableOriginalConstructor()
153 ->getMock();
154 $package->expects($this->once())
155 ->method('getPackagePath')
156 ->will($this->returnValue(Environment::getPublicPath() . '/foo/'));
157 $packageManager->expects($this->once())
158 ->method('isPackageActive')
159 ->with($this->equalTo('foo'))
160 ->will($this->returnValue(true));
161 $packageManager->expects($this->once())
162 ->method('getPackage')
163 ->with('foo')
164 ->will($this->returnValue($package));
165 ExtensionManagementUtility::setPackageManager($packageManager);
166 $this->assertSame(Environment::getPublicPath() . '/foo/bar.txt', ExtensionManagementUtility::extPath('foo', 'bar.txt'));
167 }
168
169 //////////////////////
170 // Utility functions
171 //////////////////////
172 /**
173 * Generates a basic TCA for a given table.
174 *
175 * @param string $table name of the table, must not be empty
176 * @return array generated TCA for the given table, will not be empty
177 */
178 private function generateTCAForTable($table)
179 {
180 $tca = [];
181 $tca[$table] = [];
182 $tca[$table]['columns'] = [
183 'fieldA' => [],
184 'fieldC' => []
185 ];
186 $tca[$table]['types'] = [
187 'typeA' => ['showitem' => 'fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1'],
188 'typeB' => ['showitem' => 'fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1'],
189 'typeC' => ['showitem' => 'fieldC;;paletteD']
190 ];
191 $tca[$table]['palettes'] = [
192 'paletteA' => ['showitem' => 'fieldX, fieldX1, fieldY'],
193 'paletteB' => ['showitem' => 'fieldX, fieldX1, fieldY'],
194 'paletteC' => ['showitem' => 'fieldX, fieldX1, fieldY'],
195 'paletteD' => ['showitem' => 'fieldX, fieldX1, fieldY']
196 ];
197 return $tca;
198 }
199
200 /**
201 * Data provider for getClassNamePrefixForExtensionKey.
202 *
203 * @return array
204 */
205 public function extensionKeyDataProvider()
206 {
207 return [
208 'Without underscores' => [
209 'testkey',
210 'tx_testkey'
211 ],
212 'With underscores' => [
213 'this_is_a_test_extension',
214 'tx_thisisatestextension'
215 ],
216 'With user prefix and without underscores' => [
217 'user_testkey',
218 'user_testkey'
219 ],
220 'With user prefix and with underscores' => [
221 'user_test_key',
222 'user_testkey'
223 ],
224 ];
225 }
226
227 /**
228 * @test
229 * @param string $extensionName
230 * @param string $expectedPrefix
231 * @dataProvider extensionKeyDataProvider
232 */
233 public function getClassNamePrefixForExtensionKey($extensionName, $expectedPrefix)
234 {
235 $this->assertSame($expectedPrefix, ExtensionManagementUtility::getCN($extensionName));
236 }
237
238 //////////////////////////////////////
239 // Tests concerning addToAllTCAtypes
240 //////////////////////////////////////
241 /**
242 * Tests whether fields can be add to all TCA types and duplicate fields are considered.
243 *
244 * @test
245 * @see ExtensionManagementUtility::addToAllTCAtypes()
246 */
247 public function canAddFieldsToAllTCATypesBeforeExistingOnes()
248 {
249 $table = $this->getUniqueId('tx_coretest_table');
250 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
251 ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', '', 'before:fieldD');
252 // Checking typeA:
253 $this->assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, newA, newB, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
254 // Checking typeB:
255 $this->assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, newA, newB, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeB']['showitem']);
256 }
257
258 /**
259 * Tests whether fields can be add to all TCA types and duplicate fields are considered.
260 *
261 * @test
262 * @see ExtensionManagementUtility::addToAllTCAtypes()
263 */
264 public function canAddFieldsToAllTCATypesAfterExistingOnes()
265 {
266 $table = $this->getUniqueId('tx_coretest_table');
267 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
268 ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', '', 'after:fieldC');
269 // Checking typeA:
270 $this->assertEquals('fieldA, fieldB, fieldC;labelC, newA, newB, --palette--;;paletteC, fieldC1, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
271 // Checking typeB:
272 $this->assertEquals('fieldA, fieldB, fieldC;labelC, newA, newB, --palette--;;paletteC, fieldC1, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeB']['showitem']);
273 }
274
275 /**
276 * Tests whether fields can be add to all TCA types and duplicate fields are considered.
277 *
278 * @test
279 * @see ExtensionManagementUtility::addToAllTCAtypes()
280 */
281 public function canAddFieldsToAllTCATypesRespectsPalettes()
282 {
283 $table = $this->getUniqueId('tx_coretest_table');
284 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
285 $GLOBALS['TCA'][$table]['types']['typeD'] = ['showitem' => 'fieldY, --palette--;;standard, fieldZ'];
286 ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', '', 'after:--palette--;;standard');
287 // Checking typeD:
288 $this->assertEquals('fieldY, --palette--;;standard, newA, newB, fieldA, fieldZ', $GLOBALS['TCA'][$table]['types']['typeD']['showitem']);
289 }
290
291 /**
292 * Tests whether fields can be add to all TCA types and fields in pallets are respected.
293 *
294 * @test
295 * @see ExtensionManagementUtility::addToAllTCAtypes()
296 */
297 public function canAddFieldsToAllTCATypesRespectsPositionFieldInPalette()
298 {
299 $table = $this->getUniqueId('tx_coretest_table');
300 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
301 ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', '', 'after:fieldX1');
302 // Checking typeA:
303 $this->assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, newA, newB, fieldC1, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
304 }
305
306 /**
307 * Tests whether fields can be add to a TCA type before existing ones
308 *
309 * @test
310 * @see ExtensionManagementUtility::addToAllTCAtypes()
311 */
312 public function canAddFieldsToTCATypeBeforeExistingOnes()
313 {
314 $table = $this->getUniqueId('tx_coretest_table');
315 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
316 ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', 'typeA', 'before:fieldD');
317 // Checking typeA:
318 $this->assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, newA, newB, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
319 // Checking typeB:
320 $this->assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeB']['showitem']);
321 }
322
323 /**
324 * Tests whether fields can be add to a TCA type after existing ones
325 *
326 * @test
327 * @see ExtensionManagementUtility::addToAllTCAtypes()
328 */
329 public function canAddFieldsToTCATypeAfterExistingOnes()
330 {
331 $table = $this->getUniqueId('tx_coretest_table');
332 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
333 ExtensionManagementUtility::addToAllTCAtypes($table, 'newA, newA, newB, fieldA', 'typeA', 'after:fieldC');
334 // Checking typeA:
335 $this->assertEquals('fieldA, fieldB, fieldC;labelC, newA, newB, --palette--;;paletteC, fieldC1, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
336 // Checking typeB:
337 $this->assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1', $GLOBALS['TCA'][$table]['types']['typeB']['showitem']);
338 }
339
340 /**
341 * @test
342 */
343 public function canAddFieldWithPartOfAlreadyExistingFieldname()
344 {
345 $table = $this->getUniqueId('tx_coretest_table');
346 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
347 ExtensionManagementUtility::addToAllTCAtypes($table, 'field', 'typeA', 'after:fieldD1');
348
349 $this->assertEquals('fieldA, fieldB, fieldC;labelC, --palette--;;paletteC, fieldC1, fieldD, fieldD1, field', $GLOBALS['TCA'][$table]['types']['typeA']['showitem']);
350 }
351
352 /**
353 * Test wheter replacing other TCA fields works as promissed
354 *
355 * @test
356 * @see ExtensionManagementUtility::addFieldsToAllPalettesOfField()
357 */
358 public function canAddFieldsToTCATypeAndReplaceExistingOnes()
359 {
360 $table = $this->getUniqueId('tx_coretest_table');
361 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
362 $typesBefore = $GLOBALS['TCA'][$table]['types'];
363 ExtensionManagementUtility::addToAllTCAtypes($table, 'fieldZ', '', 'replace:fieldX');
364 $this->assertEquals($typesBefore, $GLOBALS['TCA'][$table]['types'], 'It\'s wrong that the "types" array changes here - the replaced field is only on palettes');
365 // unchanged because the palette is not used
366 $this->assertEquals('fieldX, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
367 $this->assertEquals('fieldX, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteB']['showitem']);
368 // changed
369 $this->assertEquals('fieldZ, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteC']['showitem']);
370 $this->assertEquals('fieldZ, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteD']['showitem']);
371 }
372
373 /**
374 * @test
375 */
376 public function addToAllTCAtypesReplacesExistingOnes()
377 {
378 $table = $this->getUniqueId('tx_coretest_table');
379 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
380 $typesBefore = $GLOBALS['TCA'][$table]['types'];
381 ExtensionManagementUtility::addToAllTCAtypes($table, 'fieldX, --palette--;;foo', '', 'replace:fieldX');
382 $this->assertEquals($typesBefore, $GLOBALS['TCA'][$table]['types'], 'It\'s wrong that the "types" array changes here - the replaced field is only on palettes');
383 // unchanged because the palette is not used
384 $this->assertEquals('fieldX, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
385 $this->assertEquals('fieldX, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteB']['showitem']);
386 // changed
387 $this->assertEquals('fieldX, --palette--;;foo, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteC']['showitem']);
388 $this->assertEquals('fieldX, --palette--;;foo, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteD']['showitem']);
389 }
390
391 /**
392 * Tests whether fields can be added to a palette before existing elements.
393 *
394 * @test
395 * @see ExtensionManagementUtility::addFieldsToPalette()
396 */
397 public function canAddFieldsToPaletteBeforeExistingOnes()
398 {
399 $table = $this->getUniqueId('tx_coretest_table');
400 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
401 ExtensionManagementUtility::addFieldsToPalette($table, 'paletteA', 'newA, newA, newB, fieldX', 'before:fieldY');
402 $this->assertEquals('fieldX, fieldX1, newA, newB, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
403 }
404
405 /**
406 * Tests whether fields can be added to a palette after existing elements.
407 *
408 * @test
409 * @see ExtensionManagementUtility::addFieldsToPalette()
410 */
411 public function canAddFieldsToPaletteAfterExistingOnes()
412 {
413 $table = $this->getUniqueId('tx_coretest_table');
414 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
415 ExtensionManagementUtility::addFieldsToPalette($table, 'paletteA', 'newA, newA, newB, fieldX', 'after:fieldX');
416 $this->assertEquals('fieldX, newA, newB, fieldX1, fieldY', $GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
417 }
418
419 /**
420 * Tests whether fields can be added to a palette after a not existing elements.
421 *
422 * @test
423 * @see ExtensionManagementUtility::addFieldsToPalette()
424 */
425 public function canAddFieldsToPaletteAfterNotExistingOnes()
426 {
427 $table = $this->getUniqueId('tx_coretest_table');
428 $GLOBALS['TCA'] = $this->generateTCAForTable($table);
429 ExtensionManagementUtility::addFieldsToPalette($table, 'paletteA', 'newA, newA, newB, fieldX', 'after:' . $this->getUniqueId('notExisting'));
430 $this->assertEquals('fieldX, fieldX1, fieldY, newA, newB', $GLOBALS['TCA'][$table]['palettes']['paletteA']['showitem']);
431 }
432
433 /**
434 * @return array
435 */
436 public function removeDuplicatesForInsertionRemovesDuplicatesDataProvider()
437 {
438 return [
439 'Simple' => [
440 'field_b, field_d, field_c',
441 'field_a, field_b, field_c',
442 'field_d'
443 ],
444 'with linebreaks' => [
445 'field_b, --linebreak--, field_d, --linebreak--, field_c',
446 'field_a, field_b, field_c',
447 '--linebreak--, field_d, --linebreak--'
448 ],
449 'with linebreaks in list and insertion list' => [
450 'field_b, --linebreak--, field_d, --linebreak--, field_c',
451 'field_a, field_b, --linebreak--, field_c',
452 '--linebreak--, field_d, --linebreak--'
453 ],
454 ];
455 }
456
457 /**
458 * @test
459 * @dataProvider removeDuplicatesForInsertionRemovesDuplicatesDataProvider
460 * @param $insertionList
461 * @param $list
462 * @param $expected
463 */
464 public function removeDuplicatesForInsertionRemovesDuplicates($insertionList, $list, $expected)
465 {
466 $result = ExtensionManagementUtilityAccessibleProxy::removeDuplicatesForInsertion($insertionList, $list);
467 $this->assertSame($expected, $result);
468 }
469
470 ///////////////////////////////////////////////////
471 // Tests concerning addFieldsToAllPalettesOfField
472 ///////////////////////////////////////////////////
473
474 /**
475 * @test
476 */
477 public function addFieldsToAllPalettesOfFieldDoesNotAddAnythingIfFieldIsNotRegisteredInColumns()
478 {
479 $GLOBALS['TCA'] = [
480 'aTable' => [
481 'types' => [
482 'typeA' => [
483 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
484 ],
485 ],
486 'palettes' => [
487 'paletteA' => [
488 'showitem' => 'fieldX, fieldY',
489 ],
490 ],
491 ],
492 ];
493 $expected = $GLOBALS['TCA'];
494 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
495 'aTable',
496 'fieldA',
497 'newA'
498 );
499 $this->assertEquals($expected, $GLOBALS['TCA']);
500 }
501
502 /**
503 * @test
504 */
505 public function addFieldsToAllPalettesOfFieldAddsFieldsToPaletteAndSuppressesDuplicates()
506 {
507 $GLOBALS['TCA'] = [
508 'aTable' => [
509 'columns' => [
510 'fieldA' => [],
511 ],
512 'types' => [
513 'typeA' => [
514 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
515 ],
516 ],
517 'palettes' => [
518 'paletteA' => [
519 'showitem' => 'fieldX, fieldY',
520 ],
521 ],
522 ],
523 ];
524 $expected = [
525 'aTable' => [
526 'columns' => [
527 'fieldA' => [],
528 ],
529 'types' => [
530 'typeA' => [
531 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
532 ],
533 ],
534 'palettes' => [
535 'paletteA' => [
536 'showitem' => 'fieldX, fieldY, dupeA',
537 ],
538 ],
539 ],
540 ];
541 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
542 'aTable',
543 'fieldA',
544 'dupeA, dupeA' // Duplicate
545 );
546 $this->assertEquals($expected, $GLOBALS['TCA']);
547 }
548
549 /**
550 * @test
551 */
552 public function addFieldsToAllPalettesOfFieldDoesNotAddAFieldThatIsPartOfPaletteAlready()
553 {
554 $GLOBALS['TCA'] = [
555 'aTable' => [
556 'columns' => [
557 'fieldA' => [],
558 ],
559 'types' => [
560 'typeA' => [
561 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
562 ],
563 ],
564 'palettes' => [
565 'paletteA' => [
566 'showitem' => 'existingA',
567 ],
568 ],
569 ],
570 ];
571 $expected = [
572 'aTable' => [
573 'columns' => [
574 'fieldA' => [],
575 ],
576 'types' => [
577 'typeA' => [
578 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
579 ],
580 ],
581 'palettes' => [
582 'paletteA' => [
583 'showitem' => 'existingA',
584 ],
585 ],
586 ],
587 ];
588 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
589 'aTable',
590 'fieldA',
591 'existingA'
592 );
593 $this->assertEquals($expected, $GLOBALS['TCA']);
594 }
595
596 /**
597 * @test
598 */
599 public function addFieldsToAllPalettesOfFieldAddsFieldsToMultiplePalettes()
600 {
601 $GLOBALS['TCA'] = [
602 'aTable' => [
603 'columns' => [
604 'fieldA' => [],
605 ],
606 'types' => [
607 'typeA' => [
608 'showitem' => 'fieldA, --palette--;;palette1',
609 ],
610 'typeB' => [
611 'showitem' => 'fieldA;aLabel, --palette--;;palette2',
612 ],
613 ],
614 'palettes' => [
615 'palette1' => [
616 'showitem' => 'fieldX',
617 ],
618 'palette2' => [
619 'showitem' => 'fieldY',
620 ],
621 ],
622 ],
623 ];
624 $expected = [
625 'aTable' => [
626 'columns' => [
627 'fieldA' => [],
628 ],
629 'types' => [
630 'typeA' => [
631 'showitem' => 'fieldA, --palette--;;palette1',
632 ],
633 'typeB' => [
634 'showitem' => 'fieldA;aLabel, --palette--;;palette2',
635 ],
636 ],
637 'palettes' => [
638 'palette1' => [
639 'showitem' => 'fieldX, newA',
640 ],
641 'palette2' => [
642 'showitem' => 'fieldY, newA',
643 ],
644 ],
645 ],
646 ];
647 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
648 'aTable',
649 'fieldA',
650 'newA'
651 );
652 $this->assertEquals($expected, $GLOBALS['TCA']);
653 }
654
655 /**
656 * @test
657 */
658 public function addFieldsToAllPalettesOfFieldAddsMultipleFields()
659 {
660 $GLOBALS['TCA'] = [
661 'aTable' => [
662 'columns' => [
663 'fieldA' => [],
664 ],
665 'types' => [
666 'typeA' => [
667 'showitem' => 'fieldA, --palette--;;palette1',
668 ],
669 ],
670 'palettes' => [
671 'palette1' => [
672 'showitem' => 'fieldX',
673 ],
674 ],
675 ],
676 ];
677 $expected = [
678 'aTable' => [
679 'columns' => [
680 'fieldA' => [],
681 ],
682 'types' => [
683 'typeA' => [
684 'showitem' => 'fieldA, --palette--;;palette1',
685 ],
686 ],
687 'palettes' => [
688 'palette1' => [
689 'showitem' => 'fieldX, newA, newB',
690 ],
691 ],
692 ],
693 ];
694 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
695 'aTable',
696 'fieldA',
697 'newA, newB'
698 );
699 $this->assertEquals($expected, $GLOBALS['TCA']);
700 }
701
702 /**
703 * @test
704 */
705 public function addFieldsToAllPalettesOfFieldAddsBeforeExistingIfRequested()
706 {
707 $GLOBALS['TCA'] = [
708 'aTable' => [
709 'columns' => [
710 'fieldA' => [],
711 ],
712 'types' => [
713 'typeA' => [
714 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
715 ],
716 ],
717 'palettes' => [
718 'paletteA' => [
719 'showitem' => 'existingA, existingB',
720 ],
721 ],
722 ],
723 ];
724 $expected = [
725 'aTable' => [
726 'columns' => [
727 'fieldA' => [],
728 ],
729 'types' => [
730 'typeA' => [
731 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
732 ],
733 ],
734 'palettes' => [
735 'paletteA' => [
736 'showitem' => 'existingA, newA, existingB',
737 ],
738 ],
739 ],
740 ];
741 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
742 'aTable',
743 'fieldA',
744 'newA',
745 'before:existingB'
746 );
747 $this->assertEquals($expected, $GLOBALS['TCA']);
748 }
749
750 /**
751 * @test
752 */
753 public function addFieldsToAllPalettesOfFieldAddsFieldsAtEndIfBeforeRequestedDoesNotExist()
754 {
755 $GLOBALS['TCA'] = [
756 'aTable' => [
757 'columns' => [
758 'fieldA' => [],
759 ],
760 'types' => [
761 'typeA' => [
762 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
763 ],
764 ],
765 'palettes' => [
766 'paletteA' => [
767 'showitem' => 'fieldX, fieldY',
768 ],
769 ],
770 ],
771 ];
772 $expected = [
773 'aTable' => [
774 'columns' => [
775 'fieldA' => [],
776 ],
777 'types' => [
778 'typeA' => [
779 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
780 ],
781 ],
782 'palettes' => [
783 'paletteA' => [
784 'showitem' => 'fieldX, fieldY, newA, newB',
785 ],
786 ],
787 ],
788 ];
789 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
790 'aTable',
791 'fieldA',
792 'newA, newB',
793 'before:notExisting'
794 );
795 $this->assertEquals($expected, $GLOBALS['TCA']);
796 }
797
798 /**
799 * @test
800 */
801 public function addFieldsToAllPalettesOfFieldAddsAfterExistingIfRequested()
802 {
803 $GLOBALS['TCA'] = [
804 'aTable' => [
805 'columns' => [
806 'fieldA' => [],
807 ],
808 'types' => [
809 'typeA' => [
810 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
811 ],
812 ],
813 'palettes' => [
814 'paletteA' => [
815 'showitem' => 'existingA, existingB',
816 ],
817 ],
818 ],
819 ];
820 $expected = [
821 'aTable' => [
822 'columns' => [
823 'fieldA' => [],
824 ],
825 'types' => [
826 'typeA' => [
827 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
828 ],
829 ],
830 'palettes' => [
831 'paletteA' => [
832 'showitem' => 'existingA, newA, existingB',
833 ],
834 ],
835 ],
836 ];
837 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
838 'aTable',
839 'fieldA',
840 'newA',
841 'after:existingA'
842 );
843 $this->assertEquals($expected, $GLOBALS['TCA']);
844 }
845
846 /**
847 * @test
848 */
849 public function addFieldsToAllPalettesOfFieldAddsFieldsAtEndIfAfterRequestedDoesNotExist()
850 {
851 $GLOBALS['TCA'] = [
852 'aTable' => [
853 'columns' => [
854 'fieldA' => [],
855 ],
856 'types' => [
857 'typeA' => [
858 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
859 ],
860 ],
861 'palettes' => [
862 'paletteA' => [
863 'showitem' => 'existingA, existingB',
864 ],
865 ],
866 ],
867 ];
868 $expected = [
869 'aTable' => [
870 'columns' => [
871 'fieldA' => [],
872 ],
873 'types' => [
874 'typeA' => [
875 'showitem' => 'fieldA;labelA, --palette--;;paletteA',
876 ],
877 ],
878 'palettes' => [
879 'paletteA' => [
880 'showitem' => 'existingA, existingB, newA, newB',
881 ],
882 ],
883 ],
884 ];
885 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
886 'aTable',
887 'fieldA',
888 'newA, newB',
889 'after:notExistingA'
890 );
891 $this->assertEquals($expected, $GLOBALS['TCA']);
892 }
893
894 /**
895 * @test
896 */
897 public function addFieldsToAllPalettesOfFieldAddsNewPaletteIfFieldHasNoPaletteYet()
898 {
899 $GLOBALS['TCA'] = [
900 'aTable' => [
901 'columns' => [
902 'fieldA' => [],
903 ],
904 'types' => [
905 'typeA' => [
906 'showitem' => 'fieldA',
907 ],
908 ],
909 ],
910 ];
911 $expected = [
912 'aTable' => [
913 'columns' => [
914 'fieldA' => [],
915 ],
916 'types' => [
917 'typeA' => [
918 'showitem' => 'fieldA, --palette--;;generatedFor-fieldA',
919 ],
920 ],
921 'palettes' => [
922 'generatedFor-fieldA' => [
923 'showitem' => 'newA',
924 ],
925 ],
926 ],
927 ];
928 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
929 'aTable',
930 'fieldA',
931 'newA'
932 );
933 $this->assertEquals($expected, $GLOBALS['TCA']);
934 }
935
936 /**
937 * @test
938 */
939 public function addFieldsToAllPalettesOfFieldAddsNewPaletteIfFieldHasNoPaletteYetAndKeepsExistingLabel()
940 {
941 $GLOBALS['TCA'] = [
942 'aTable' => [
943 'columns' => [
944 'fieldA' => [],
945 ],
946 'types' => [
947 'typeA' => [
948 'showitem' => 'fieldA;labelA',
949 ],
950 ],
951 ],
952 ];
953 $expected = [
954 'aTable' => [
955 'columns' => [
956 'fieldA' => [],
957 ],
958 'types' => [
959 'typeA' => [
960 'showitem' => 'fieldA;labelA, --palette--;;generatedFor-fieldA',
961 ],
962 ],
963 'palettes' => [
964 'generatedFor-fieldA' => [
965 'showitem' => 'newA',
966 ],
967 ],
968 ],
969 ];
970 ExtensionManagementUtility::addFieldsToAllPalettesOfField(
971 'aTable',
972 'fieldA',
973 'newA'
974 );
975 $this->assertEquals($expected, $GLOBALS['TCA']);
976 }
977
978 ///////////////////////////////////////////////////
979 // Tests concerning executePositionedStringInsertion
980 ///////////////////////////////////////////////////
981
982 /**
983 * Data provider for executePositionedStringInsertionTrimsCorrectCharacters
984 * @return array
985 */
986 public function executePositionedStringInsertionTrimsCorrectCharactersDataProvider()
987 {
988 return [
989 'normal characters' => [
990 'tr0',
991 'tr0',
992 ],
993 'newlines' => [
994 "test\n",
995 'test',
996 ],
997 'newlines with carriage return' => [
998 "test\r\n",
999 'test',
1000 ],
1001 'tabs' => [
1002 "test\t",
1003 'test',
1004 ],
1005 'commas' => [
1006 'test,',
1007 'test',
1008 ],
1009 'multiple commas with trailing spaces' => [
1010 "test,,\t, \r\n",
1011 'test',
1012 ],
1013 ];
1014 }
1015
1016 /**
1017 * @test
1018 * @dataProvider executePositionedStringInsertionTrimsCorrectCharactersDataProvider
1019 * @param $string
1020 * @param $expectedResult
1021 */
1022 public function executePositionedStringInsertionTrimsCorrectCharacters($string, $expectedResult)
1023 {
1024 $extensionManagementUtility = $this->getAccessibleMock(ExtensionManagementUtility::class, ['dummy']);
1025 $string = $extensionManagementUtility->_call('executePositionedStringInsertion', $string, '');
1026 $this->assertEquals($expectedResult, $string);
1027 }
1028
1029 /////////////////////////////////////////
1030 // Tests concerning addTcaSelectItem
1031 /////////////////////////////////////////
1032 /**
1033 * @test
1034 */
1035 public function addTcaSelectItemThrowsExceptionIfTableIsNotOfTypeString()
1036 {
1037 $this->expectException(\InvalidArgumentException::class);
1038 $this->expectExceptionCode(1303236963);
1039
1040 ExtensionManagementUtility::addTcaSelectItem([], 'foo', []);
1041 }
1042
1043 /**
1044 * @test
1045 */
1046 public function addTcaSelectItemThrowsExceptionIfFieldIsNotOfTypeString()
1047 {
1048 $this->expectException(\InvalidArgumentException::class);
1049 $this->expectExceptionCode(1303236964);
1050
1051 ExtensionManagementUtility::addTcaSelectItem('foo', [], []);
1052 }
1053
1054 /**
1055 * @test
1056 */
1057 public function addTcaSelectItemThrowsExceptionIfRelativeToFieldIsNotOfTypeString()
1058 {
1059 $this->expectException(\InvalidArgumentException::class);
1060 $this->expectExceptionCode(1303236965);
1061
1062 ExtensionManagementUtility::addTcaSelectItem('foo', 'bar', [], []);
1063 }
1064
1065 /**
1066 * @test
1067 */
1068 public function addTcaSelectItemThrowsExceptionIfRelativePositionIsNotOfTypeString()
1069 {
1070 $this->expectException(\InvalidArgumentException::class);
1071 $this->expectExceptionCode(1303236966);
1072
1073 ExtensionManagementUtility::addTcaSelectItem('foo', 'bar', [], 'foo', []);
1074 }
1075
1076 /**
1077 * @test
1078 */
1079 public function addTcaSelectItemThrowsExceptionIfRelativePositionIsNotOneOfValidKeywords()
1080 {
1081 $this->expectException(\InvalidArgumentException::class);
1082 $this->expectExceptionCode(1303236967);
1083
1084 ExtensionManagementUtility::addTcaSelectItem('foo', 'bar', [], 'foo', 'not allowed keyword');
1085 }
1086
1087 /**
1088 * @test
1089 */
1090 public function addTcaSelectItemThrowsExceptionIfFieldIsNotFoundInTca()
1091 {
1092 $this->expectException(\RuntimeException::class);
1093 $this->expectExceptionCode(1303237468);
1094
1095 $GLOBALS['TCA'] = [];
1096 ExtensionManagementUtility::addTcaSelectItem('foo', 'bar', []);
1097 }
1098
1099 /**
1100 * Data provider for addTcaSelectItemInsertsItemAtSpecifiedPosition
1101 */
1102 public function addTcaSelectItemDataProvider()
1103 {
1104 // Every array splits into:
1105 // - relativeToField
1106 // - relativePosition
1107 // - expectedResultArray
1108 return [
1109 'add at end of array' => [
1110 '',
1111 '',
1112 [
1113 0 => ['firstElement'],
1114 1 => ['matchMe'],
1115 2 => ['thirdElement'],
1116 3 => ['insertedElement']
1117 ]
1118 ],
1119 'replace element' => [
1120 'matchMe',
1121 'replace',
1122 [
1123 0 => ['firstElement'],
1124 1 => ['insertedElement'],
1125 2 => ['thirdElement']
1126 ]
1127 ],
1128 'add element after' => [
1129 'matchMe',
1130 'after',
1131 [
1132 0 => ['firstElement'],
1133 1 => ['matchMe'],
1134 2 => ['insertedElement'],
1135 3 => ['thirdElement']
1136 ]
1137 ],
1138 'add element before' => [
1139 'matchMe',
1140 'before',
1141 [
1142 0 => ['firstElement'],
1143 1 => ['insertedElement'],
1144 2 => ['matchMe'],
1145 3 => ['thirdElement']
1146 ]
1147 ],
1148 'add at end if relative position was not found' => [
1149 'notExistingItem',
1150 'after',
1151 [
1152 0 => ['firstElement'],
1153 1 => ['matchMe'],
1154 2 => ['thirdElement'],
1155 3 => ['insertedElement']
1156 ]
1157 ]
1158 ];
1159 }
1160
1161 /**
1162 * @test
1163 * @dataProvider addTcaSelectItemDataProvider
1164 * @param $relativeToField
1165 * @param $relativePosition
1166 * @param $expectedResultArray
1167 */
1168 public function addTcaSelectItemInsertsItemAtSpecifiedPosition($relativeToField, $relativePosition, $expectedResultArray)
1169 {
1170 $GLOBALS['TCA'] = [
1171 'testTable' => [
1172 'columns' => [
1173 'testField' => [
1174 'config' => [
1175 'items' => [
1176 '0' => ['firstElement'],
1177 '1' => ['matchMe'],
1178 2 => ['thirdElement']
1179 ]
1180 ]
1181 ]
1182 ]
1183 ]
1184 ];
1185 ExtensionManagementUtility::addTcaSelectItem('testTable', 'testField', ['insertedElement'], $relativeToField, $relativePosition);
1186 $this->assertEquals($expectedResultArray, $GLOBALS['TCA']['testTable']['columns']['testField']['config']['items']);
1187 }
1188
1189 /////////////////////////////////////////
1190 // Tests concerning loadExtLocalconf
1191 /////////////////////////////////////////
1192 /**
1193 * @test
1194 */
1195 public function loadExtLocalconfDoesNotReadFromCacheIfCachingIsDenied()
1196 {
1197 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1198 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1199 ->setMethods(['getCache'])
1200 ->getMock();
1201 $mockCacheManager->expects($this->never())->method('getCache');
1202 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1203 $packageManager = $this->createMockPackageManagerWithMockPackage($this->getUniqueId());
1204 ExtensionManagementUtility::setPackageManager($packageManager);
1205 ExtensionManagementUtility::loadExtLocalconf(false);
1206 }
1207
1208 /**
1209 * @test
1210 */
1211 public function loadExtLocalconfRequiresCacheFileIfExistsAndCachingIsAllowed()
1212 {
1213 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1214 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1215 ->disableOriginalConstructor()
1216 ->getMock();
1217
1218 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1219 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1220 ->setMethods(['getCache'])
1221 ->getMock();
1222 $mockCacheManager->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
1223 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1224 $mockCache->expects($this->any())->method('has')->will($this->returnValue(true));
1225 $mockCache->expects($this->once())->method('require');
1226 ExtensionManagementUtility::loadExtLocalconf(true);
1227 }
1228
1229 /////////////////////////////////////////
1230 // Tests concerning loadSingleExtLocalconfFiles
1231 /////////////////////////////////////////
1232 /**
1233 * @test
1234 */
1235 public function loadSingleExtLocalconfFilesRequiresExtLocalconfFileRegisteredInGlobalTypo3LoadedExt()
1236 {
1237 $this->expectException(\RuntimeException::class);
1238 $this->expectExceptionCode(1340559079);
1239
1240 $extensionName = $this->getUniqueId('foo');
1241 $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1242 $extLocalconfLocation = $packageManager->getPackage($extensionName)->getPackagePath() . 'ext_localconf.php';
1243 file_put_contents($extLocalconfLocation, "<?php\n\nthrow new RuntimeException('', 1340559079);\n\n?>");
1244 ExtensionManagementUtility::setPackageManager($packageManager);
1245 ExtensionManagementUtilityAccessibleProxy::loadSingleExtLocalconfFiles();
1246 }
1247
1248 /////////////////////////////////////////
1249 // Tests concerning addModule
1250 /////////////////////////////////////////
1251
1252 /**
1253 * Data provider for addModule tests
1254 * @return array
1255 */
1256 public function addModulePositionTestsDataProvider()
1257 {
1258 return [
1259 'can add new main module if none exists' => [
1260 'top',
1261 '',
1262 'newModule'
1263 ],
1264 'can add new sub module if no position specified' => [
1265 '',
1266 'some,modules',
1267 'some,modules,newModule'
1268 ],
1269 'can add new sub module to top of module' => [
1270 'top',
1271 'some,modules',
1272 'newModule,some,modules'
1273 ],
1274 'can add new sub module if bottom of module' => [
1275 'bottom',
1276 'some,modules',
1277 'some,modules,newModule'
1278 ],
1279 'can add new sub module before specified sub module' => [
1280 'before:modules',
1281 'some,modules',
1282 'some,newModule,modules'
1283 ],
1284 'can add new sub module after specified sub module' => [
1285 'after:some',
1286 'some,modules',
1287 'some,newModule,modules'
1288 ],
1289 'can add new sub module at the bottom if specified sub module to add before does not exist' => [
1290 'before:modules',
1291 'some,otherModules',
1292 'some,otherModules,newModule'
1293 ],
1294 'can add new sub module at the bottom if specified sub module to add after does not exist' => [
1295 'after:some',
1296 'someOther,modules',
1297 'someOther,modules,newModule'
1298 ],
1299 ];
1300 }
1301
1302 /**
1303 * @test
1304 * @dataProvider addModulePositionTestsDataProvider
1305 * @param $position
1306 * @param $existing
1307 * @param $expected
1308 */
1309 public function addModuleCanAddModule($position, $existing, $expected)
1310 {
1311 $mainModule = 'foobar';
1312 $subModule = 'newModule';
1313 if ($existing) {
1314 $GLOBALS['TBE_MODULES'][$mainModule] = $existing;
1315 }
1316
1317 ExtensionManagementUtility::addModule($mainModule, $subModule, $position);
1318
1319 $this->assertTrue(isset($GLOBALS['TBE_MODULES'][$mainModule]));
1320 $this->assertEquals($expected, $GLOBALS['TBE_MODULES'][$mainModule]);
1321 }
1322
1323 /////////////////////////////////////////
1324 // Tests concerning createExtLocalconfCacheEntry
1325 /////////////////////////////////////////
1326 /**
1327 * @test
1328 */
1329 public function createExtLocalconfCacheEntryWritesCacheEntryWithContentOfLoadedExtensionExtLocalconf()
1330 {
1331 $extensionName = $this->getUniqueId('foo');
1332 $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1333 $extLocalconfLocation = $packageManager->getPackage($extensionName)->getPackagePath() . 'ext_localconf.php';
1334 $uniqueStringInLocalconf = $this->getUniqueId('foo');
1335 file_put_contents($extLocalconfLocation, "<?php\n\n" . $uniqueStringInLocalconf . "\n\n?>");
1336 ExtensionManagementUtility::setPackageManager($packageManager);
1337 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1338 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1339 ->disableOriginalConstructor()
1340 ->getMock();
1341
1342 $mockCache->expects($this->once())->method('set')->with($this->anything(), $this->stringContains($uniqueStringInLocalconf), $this->anything());
1343 ExtensionManagementUtilityAccessibleProxy::createExtLocalconfCacheEntry($mockCache);
1344 }
1345
1346 /**
1347 * @test
1348 */
1349 public function createExtLocalconfCacheEntryWritesCacheEntryWithExtensionContentOnlyIfExtLocalconfExists()
1350 {
1351 $extensionName = $this->getUniqueId('foo');
1352 $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1353 ExtensionManagementUtility::setPackageManager($packageManager);
1354 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1355 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1356 ->disableOriginalConstructor()
1357 ->getMock();
1358
1359 $mockCache->expects($this->once())
1360 ->method('set')
1361 ->with($this->anything(), $this->logicalNot($this->stringContains($extensionName)), $this->anything());
1362 ExtensionManagementUtilityAccessibleProxy::createExtLocalconfCacheEntry($mockCache);
1363 }
1364
1365 /**
1366 * @test
1367 */
1368 public function createExtLocalconfCacheEntryWritesCacheEntryWithNoTags()
1369 {
1370 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1371 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1372 ->disableOriginalConstructor()
1373 ->getMock();
1374 $mockCache->expects($this->once())->method('set')->with($this->anything(), $this->anything(), $this->equalTo([]));
1375 $packageManager = $this->createMockPackageManagerWithMockPackage($this->getUniqueId());
1376 ExtensionManagementUtility::setPackageManager($packageManager);
1377 ExtensionManagementUtilityAccessibleProxy::createExtLocalconfCacheEntry($mockCache);
1378 }
1379
1380 /////////////////////////////////////////
1381 // Tests concerning getExtLocalconfCacheIdentifier
1382 /////////////////////////////////////////
1383 /**
1384 * @test
1385 */
1386 public function getExtLocalconfCacheIdentifierCreatesSha1WithFourtyCharactersAndPrefix()
1387 {
1388 $prefix = 'ext_localconf_';
1389 $identifier = ExtensionManagementUtilityAccessibleProxy::getExtLocalconfCacheIdentifier();
1390 $this->assertStringStartsWith($prefix, $identifier);
1391 $sha1 = str_replace($prefix, '', $identifier);
1392 $this->assertEquals(40, strlen($sha1));
1393 }
1394
1395 /////////////////////////////////////////
1396 // Tests concerning loadBaseTca
1397 /////////////////////////////////////////
1398
1399 /**
1400 * @test
1401 */
1402 public function loadBaseTcaDoesNotReadFromCacheIfCachingIsDenied()
1403 {
1404 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1405 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1406 ->setMethods(['getCache'])
1407 ->getMock();
1408 $mockCacheManager->expects($this->never())->method('getCache');
1409 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1410 ExtensionManagementUtilityAccessibleProxy::loadBaseTca(false);
1411 }
1412
1413 /**
1414 * @test
1415 */
1416 public function loadBaseTcaRequiresCacheFileIfExistsAndCachingIsAllowed()
1417 {
1418 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1419 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1420 ->disableOriginalConstructor()
1421 ->getMock();
1422
1423 $mockCache->expects($this->once())->method('require')->willReturn(['tca' => [], 'categoryRegistry' => \serialize(CategoryRegistry::getInstance())]);
1424 ExtensionManagementUtilityAccessibleProxy::loadBaseTca(true, $mockCache);
1425 }
1426
1427 /**
1428 * @test
1429 */
1430 public function loadBaseTcaCreatesCacheFileWithContentOfAnExtensionsConfigurationTcaPhpFile()
1431 {
1432 $extensionName = $this->getUniqueId('test_baseTca_');
1433 $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1434 $packagePath = $packageManager->getPackage($extensionName)->getPackagePath();
1435 GeneralUtility::mkdir($packagePath);
1436 GeneralUtility::mkdir($packagePath . 'Configuration/');
1437 GeneralUtility::mkdir($packagePath . 'Configuration/TCA/');
1438 ExtensionManagementUtility::setPackageManager($packageManager);
1439 $uniqueTableName = $this->getUniqueId('table_name_');
1440 $uniqueStringInTableConfiguration = $this->getUniqueId('table_configuration_');
1441 $tableConfiguration = '<?php return array(\'foo\' => \'' . $uniqueStringInTableConfiguration . '\'); ?>';
1442 file_put_contents($packagePath . 'Configuration/TCA/' . $uniqueTableName . '.php', $tableConfiguration);
1443 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1444 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1445 ->disableOriginalConstructor()
1446 ->getMock();
1447
1448 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1449 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1450 ->setMethods(['getCache'])
1451 ->getMock();
1452 $mockCacheManager->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
1453 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1454 $mockCache->expects($this->once())->method('require')->will($this->returnValue(false));
1455 $mockCache->expects($this->once())->method('set')->with($this->anything(), $this->stringContains($uniqueStringInTableConfiguration), $this->anything());
1456
1457 $mockSignalSlotDispatcher = $this->createMock(SignalSlotDispatcher::class);
1458 $mockSignalSlotDispatcher->expects($this->once())->method('dispatch')->with($this->anything(), $this->anything(), $this->isType('array'))->will($this->returnArgument(2));
1459 ExtensionManagementUtilityAccessibleProxy::setSignalSlotDispatcher($mockSignalSlotDispatcher);
1460
1461 ExtensionManagementUtility::loadBaseTca(true);
1462 }
1463
1464 /**
1465 * @test
1466 */
1467 public function loadBaseTcaWritesCacheEntryWithNoTags()
1468 {
1469 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1470 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1471 ->disableOriginalConstructor()
1472 ->getMock();
1473
1474 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1475 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1476 ->setMethods(['getCache'])
1477 ->getMock();
1478 $mockCacheManager->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
1479 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1480 $mockCache->expects($this->once())->method('require')->will($this->returnValue(false));
1481 $mockCache->expects($this->once())->method('set')->with($this->anything(), $this->anything(), $this->equalTo([]));
1482 ExtensionManagementUtilityAccessibleProxy::loadBaseTca();
1483 }
1484
1485 /////////////////////////////////////////
1486 // Tests concerning getBaseTcaCacheIdentifier
1487 /////////////////////////////////////////
1488
1489 /**
1490 * @test
1491 */
1492 public function getBaseTcaCacheIdentifierCreatesSha1WithFourtyCharactersAndPrefix()
1493 {
1494 $prefix = 'tca_base_';
1495 $identifier = ExtensionManagementUtilityAccessibleProxy::getBaseTcaCacheIdentifier();
1496 $this->assertStringStartsWith($prefix, $identifier);
1497 $sha1 = str_replace($prefix, '', $identifier);
1498 $this->assertEquals(40, strlen($sha1));
1499 }
1500
1501 /////////////////////////////////////////
1502 // Tests concerning loadExtTables
1503 /////////////////////////////////////////
1504 /**
1505 * @test
1506 */
1507 public function loadExtTablesDoesNotReadFromCacheIfCachingIsDenied()
1508 {
1509 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1510 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1511 ->setMethods(['getCache'])
1512 ->getMock();
1513 $mockCacheManager->expects($this->never())->method('getCache');
1514 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1515 $packageManager = $this->createMockPackageManagerWithMockPackage($this->getUniqueId());
1516 ExtensionManagementUtility::setPackageManager($packageManager);
1517 ExtensionManagementUtility::loadExtLocalconf(false);
1518 }
1519
1520 /**
1521 * @test
1522 */
1523 public function loadExtTablesRequiresCacheFileIfExistsAndCachingIsAllowed()
1524 {
1525 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1526 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1527 ->disableOriginalConstructor()
1528 ->getMock();
1529
1530 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1531 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1532 ->setMethods(['getCache'])
1533 ->getMock();
1534 $mockCacheManager->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
1535 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1536 $mockCache->expects($this->any())->method('has')->will($this->returnValue(true));
1537 $mockCache->expects($this->once())->method('require');
1538 // Reset the internal cache access tracking variable of extMgm
1539 // This method is only in the ProxyClass!
1540 ExtensionManagementUtilityAccessibleProxy::resetExtTablesWasReadFromCacheOnceBoolean();
1541 ExtensionManagementUtility::loadExtTables(true);
1542 }
1543
1544 /////////////////////////////////////////
1545 // Tests concerning createExtTablesCacheEntry
1546 /////////////////////////////////////////
1547 /**
1548 * @test
1549 */
1550 public function createExtTablesCacheEntryWritesCacheEntryWithContentOfLoadedExtensionExtTables()
1551 {
1552 $extensionName = $this->getUniqueId('foo');
1553 $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1554 $extensionPath = $packageManager->getPackage($extensionName)->getPackagePath();
1555 $extTablesLocation = $extensionPath . 'ext_tables.php';
1556 $uniqueStringInTables = $this->getUniqueId('foo');
1557 file_put_contents($extTablesLocation, "<?php\n\n$uniqueStringInTables\n\n?>");
1558 ExtensionManagementUtility::setPackageManager($packageManager);
1559 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1560 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1561 ->disableOriginalConstructor()
1562 ->getMock();
1563
1564 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1565 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1566 ->setMethods(['getCache'])
1567 ->getMock();
1568 $mockCacheManager->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
1569 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1570 $mockCache->expects($this->once())->method('set')->with($this->anything(), $this->stringContains($uniqueStringInTables), $this->anything());
1571 ExtensionManagementUtilityAccessibleProxy::createExtTablesCacheEntry();
1572 }
1573
1574 /**
1575 * @test
1576 */
1577 public function createExtTablesCacheEntryWritesCacheEntryWithExtensionContentOnlyIfExtTablesExists()
1578 {
1579 $extensionName = $this->getUniqueId('foo');
1580 $packageManager = $this->createMockPackageManagerWithMockPackage($extensionName);
1581 ExtensionManagementUtility::setPackageManager($packageManager);
1582 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1583 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1584 ->disableOriginalConstructor()
1585 ->getMock();
1586
1587 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1588 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1589 ->setMethods(['getCache'])
1590 ->getMock();
1591 $mockCacheManager->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
1592 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1593 $mockCache->expects($this->once())
1594 ->method('set')
1595 ->with($this->anything(), $this->logicalNot($this->stringContains($extensionName)), $this->anything());
1596 ExtensionManagementUtilityAccessibleProxy::createExtTablesCacheEntry();
1597 }
1598
1599 /**
1600 * @test
1601 */
1602 public function createExtTablesCacheEntryWritesCacheEntryWithNoTags()
1603 {
1604 $mockCache = $this->getMockBuilder(PhpFrontend::class)
1605 ->setMethods(['getIdentifier', 'set', 'get', 'has', 'remove', 'flush', 'flushByTag', 'require'])
1606 ->disableOriginalConstructor()
1607 ->getMock();
1608
1609 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
1610 $mockCacheManager = $this->getMockBuilder(CacheManager::class)
1611 ->setMethods(['getCache'])
1612 ->getMock();
1613 $mockCacheManager->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
1614 ExtensionManagementUtilityAccessibleProxy::setCacheManager($mockCacheManager);
1615 $mockCache->expects($this->once())->method('set')->with($this->anything(), $this->anything(), $this->equalTo([]));
1616 $packageManager = $this->createMockPackageManagerWithMockPackage($this->getUniqueId());
1617 ExtensionManagementUtility::setPackageManager($packageManager);
1618 ExtensionManagementUtilityAccessibleProxy::createExtTablesCacheEntry();
1619 }
1620
1621 /////////////////////////////////////////
1622 // Tests concerning getExtTablesCacheIdentifier
1623 /////////////////////////////////////////
1624 /**
1625 * @test
1626 */
1627 public function getExtTablesCacheIdentifierCreatesSha1WithFourtyCharactersAndPrefix()
1628 {
1629 $prefix = 'ext_tables_';
1630 $identifier = ExtensionManagementUtilityAccessibleProxy::getExtTablesCacheIdentifier();
1631 $this->assertStringStartsWith($prefix, $identifier);
1632 $sha1 = str_replace($prefix, '', $identifier);
1633 $this->assertEquals(40, strlen($sha1));
1634 }
1635
1636 /////////////////////////////////////////
1637 // Tests concerning getExtensionVersion
1638 /////////////////////////////////////////
1639 /**
1640 * Data provider for negative getExtensionVersion() tests.
1641 *
1642 * @return array
1643 */
1644 public function getExtensionVersionFaultyDataProvider()
1645 {
1646 return [
1647 [''],
1648 [0],
1649 [new \stdClass()],
1650 [true]
1651 ];
1652 }
1653
1654 /**
1655 * @test
1656 * @dataProvider getExtensionVersionFaultyDataProvider
1657 * @param $key
1658 * @throws \TYPO3\CMS\Core\Package\Exception
1659 */
1660 public function getExtensionVersionForFaultyExtensionKeyThrowsException($key)
1661 {
1662 $this->expectException(\InvalidArgumentException::class);
1663 $this->expectExceptionCode(1294586096);
1664
1665 ExtensionManagementUtility::getExtensionVersion($key);
1666 }
1667
1668 /**
1669 * @test
1670 */
1671 public function getExtensionVersionForNotLoadedExtensionReturnsEmptyString()
1672 {
1673 $uniqueSuffix = $this->getUniqueId('test');
1674 $extensionKey = 'unloadedextension' . $uniqueSuffix;
1675 $this->assertEquals('', ExtensionManagementUtility::getExtensionVersion($extensionKey));
1676 }
1677
1678 /**
1679 * @test
1680 */
1681 public function getExtensionVersionForLoadedExtensionReturnsExtensionVersion()
1682 {
1683 $uniqueSuffix = $this->getUniqueId('test');
1684 $extensionKey = 'unloadedextension' . $uniqueSuffix;
1685 $packageMetaData = $this->getMockBuilder(MetaData::class)
1686 ->setMethods(['getVersion'])
1687 ->setConstructorArgs([$extensionKey])
1688 ->getMock();
1689 $packageMetaData->expects($this->any())->method('getVersion')->will($this->returnValue('1.2.3'));
1690 $packageManager = $this->createMockPackageManagerWithMockPackage($extensionKey, ['getPackagePath', 'getPackageKey', 'getPackageMetaData']);
1691 /** @var \PHPUnit_Framework_MockObject_MockObject $package */
1692 $package = $packageManager->getPackage($extensionKey);
1693 $package->expects($this->any())
1694 ->method('getPackageMetaData')
1695 ->will($this->returnValue($packageMetaData));
1696 ExtensionManagementUtility::setPackageManager($packageManager);
1697 $this->assertEquals('1.2.3', ExtensionManagementUtility::getExtensionVersion($extensionKey));
1698 }
1699
1700 /////////////////////////////////////////
1701 // Tests concerning loadExtension
1702 /////////////////////////////////////////
1703 /**
1704 * @test
1705 */
1706 public function loadExtensionThrowsExceptionIfExtensionIsLoaded()
1707 {
1708 $this->expectException(\RuntimeException::class);
1709 $this->expectExceptionCode(1342345486);
1710
1711 $extensionKey = $this->getUniqueId('test');
1712 $packageManager = $this->createMockPackageManagerWithMockPackage($extensionKey);
1713 ExtensionManagementUtility::setPackageManager($packageManager);
1714 ExtensionManagementUtility::loadExtension($extensionKey);
1715 }
1716
1717 /////////////////////////////////////////
1718 // Tests concerning unloadExtension
1719 /////////////////////////////////////////
1720 /**
1721 * @test
1722 */
1723 public function unloadExtensionThrowsExceptionIfExtensionIsNotLoaded()
1724 {
1725 $this->expectException(\RuntimeException::class);
1726 $this->expectExceptionCode(1342345487);
1727
1728 $packageName = $this->getUniqueId('foo');
1729 /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
1730 $packageManager = $this->getMockBuilder(PackageManager::class)
1731 ->setMethods(['isPackageActive'])
1732 ->disableOriginalConstructor()
1733 ->getMock();
1734 $packageManager->expects($this->once())
1735 ->method('isPackageActive')
1736 ->with($this->equalTo($packageName))
1737 ->will($this->returnValue(false));
1738 ExtensionManagementUtility::setPackageManager($packageManager);
1739 ExtensionManagementUtility::unloadExtension($packageName);
1740 }
1741
1742 /**
1743 * @test
1744 */
1745 public function unloadExtensionCallsPackageManagerToDeactivatePackage()
1746 {
1747 $packageName = $this->getUniqueId('foo');
1748 /** @var PackageManager|\PHPUnit_Framework_MockObject_MockObject $packageManager */
1749 $packageManager = $this->getMockBuilder(PackageManager::class)
1750 ->setMethods(['isPackageActive', 'deactivatePackage'])
1751 ->disableOriginalConstructor()
1752 ->getMock();
1753 $packageManager->expects($this->any())
1754 ->method('isPackageActive')
1755 ->will($this->returnValue(true));
1756 $packageManager->expects($this->once())
1757 ->method('deactivatePackage')
1758 ->with($packageName);
1759 ExtensionManagementUtility::setPackageManager($packageManager);
1760 ExtensionManagementUtility::unloadExtension($packageName);
1761 }
1762
1763 /////////////////////////////////////////
1764 // Tests concerning makeCategorizable
1765 /////////////////////////////////////////
1766 /**
1767 * @test
1768 */
1769 public function doesMakeCategorizableCallsTheCategoryRegistryWithDefaultFieldName()
1770 {
1771 $extensionKey = $this->getUniqueId('extension');
1772 $tableName = $this->getUniqueId('table');
1773
1774 /** @var CategoryRegistry|\PHPUnit_Framework_MockObject_MockObject $registryMock */
1775 $registryMock = $this->getMockBuilder(CategoryRegistry::class)->getMock();
1776 $registryMock->expects($this->once())->method('add')->with($extensionKey, $tableName, 'categories', []);
1777 GeneralUtility::setSingletonInstance(CategoryRegistry::class, $registryMock);
1778 ExtensionManagementUtility::makeCategorizable($extensionKey, $tableName);
1779 }
1780
1781 /**
1782 * @test
1783 */
1784 public function doesMakeCategorizableCallsTheCategoryRegistryWithFieldName()
1785 {
1786 $extensionKey = $this->getUniqueId('extension');
1787 $tableName = $this->getUniqueId('table');
1788 $fieldName = $this->getUniqueId('field');
1789
1790 /** @var CategoryRegistry|\PHPUnit_Framework_MockObject_MockObject $registryMock */
1791 $registryMock = $this->getMockBuilder(CategoryRegistry::class)->getMock();
1792 $registryMock->expects($this->once())->method('add')->with($extensionKey, $tableName, $fieldName, []);
1793 GeneralUtility::setSingletonInstance(CategoryRegistry::class, $registryMock);
1794 ExtensionManagementUtility::makeCategorizable($extensionKey, $tableName, $fieldName);
1795 }
1796
1797 ///////////////////////////////
1798 // Tests concerning addPlugin
1799 ///////////////////////////////
1800
1801 /**
1802 * @test
1803 */
1804 public function addPluginSetsTcaCorrectlyForGivenExtKeyAsParameter()
1805 {
1806 $extKey = 'indexed_search';
1807 $expectedTCA = [
1808 [
1809 'label',
1810 $extKey,
1811 'EXT:' . $extKey . '/Resources/Public/Icons/Extension.png'
1812 ]
1813 ];
1814 $GLOBALS['TCA']['tt_content']['columns']['list_type']['config']['items'] = [];
1815 ExtensionManagementUtility::addPlugin(['label', $extKey], 'list_type', $extKey);
1816 $this->assertEquals($expectedTCA, $GLOBALS['TCA']['tt_content']['columns']['list_type']['config']['items']);
1817 }
1818
1819 /**
1820 * @test
1821 */
1822 public function addPluginThrowsExceptionForMissingExtkey()
1823 {
1824 $this->expectException(\InvalidArgumentException::class);
1825 $this->expectExceptionCode(1404068038);
1826
1827 ExtensionManagementUtility::addPlugin('test');
1828 }
1829 }