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