TYPO3 CMS  TYPO3_8-7
PackageManagerTest.php
Go to the documentation of this file.
1 <?php
3 
4 /* *
5  * This script belongs to the TYPO3 Flow framework. *
6  * *
7  * It is free software; you can redistribute it and/or modify it under *
8  * the terms of the GNU Lesser General Public License, either version 3 *
9  * of the License, or (at your option) any later version. *
10  * *
11  * The TYPO3 project - inspiring people to share! *
12  * */
13 
22 
26 class PackageManagerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
27 {
31  protected $packageManager;
32 
36  protected function setUp()
37  {
38  vfsStream::setup('Test');
39 
41  $mockCache = $this->getMockBuilder(PhpFrontend::class)
42  ->setMethods(['has', 'set', 'getBackend'])
43  ->disableOriginalConstructor()
44  ->getMock();
45  $mockCacheBackend = $this->getMockBuilder(SimpleFileBackend::class)
46  ->setMethods(['has', 'set', 'getBackend', 'getCacheDirectory'])
47  ->disableOriginalConstructor()
48  ->getMock();
49  $mockCache->expects($this->any())->method('has')->will($this->returnValue(false));
50  $mockCache->expects($this->any())->method('set')->will($this->returnValue(true));
51  $mockCache->expects($this->any())->method('getBackend')->will($this->returnValue($mockCacheBackend));
52  $mockCacheBackend->expects($this->any())->method('getCacheDirectory')->will($this->returnValue('vfs://Test/Cache'));
53  $this->packageManager = $this->getAccessibleMock(PackageManager::class, ['sortAndSavePackageStates', 'sortActivePackagesByDependencies', 'registerTransientClassLoadingInformationForPackage']);
54 
55  mkdir('vfs://Test/Packages/Application', 0700, true);
56  mkdir('vfs://Test/Configuration');
57  file_put_contents('vfs://Test/Configuration/PackageStates.php', "<?php return array ('packages' => array(), 'version' => 5); ");
58 
59  $composerNameToPackageKeyMap = [
60  'typo3/flow' => 'TYPO3.Flow'
61  ];
62 
63  $this->packageManager->injectCoreCache($mockCache);
64  $this->inject($this->packageManager, 'composerNameToPackageKeyMap', $composerNameToPackageKeyMap);
65  $this->packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
66  $this->packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
67  }
68 
73  protected function createPackage($packageKey)
74  {
75  $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
76  mkdir($packagePath, 0770, true);
77  file_put_contents($packagePath . 'ext_emconf.php', '<?php' . LF . '$EM_CONF[$_EXTKEY] = [];');
78  file_put_contents($packagePath . 'composer.json', '{}');
79  $package = new Package($this->packageManager, $packageKey, $packagePath);
80  $this->packageManager->registerPackage($package);
81  $this->packageManager->activatePackage($packageKey);
82 
83  return $package;
84  }
85 
90  {
91  $this->createPackage('TYPO3.MyPackage');
92  $package = $this->packageManager->getPackage('TYPO3.MyPackage');
93 
94  $this->assertInstanceOf(Package::class, $package, 'The result of getPackage() was no valid package object.');
95  }
96 
101  {
102  $this->expectException(UnknownPackageException::class);
103  $this->expectExceptionCode(1166546734);
104 
105  $this->packageManager->getPackage('PrettyUnlikelyThatThisPackageExists');
106  }
107 
112  {
113  $expectedPackageKeys = [
114  $this->getUniqueId('TYPO3.CMS'),
115  $this->getUniqueId('TYPO3.CMS.Test'),
116  $this->getUniqueId('TYPO3.YetAnotherTestPackage'),
117  $this->getUniqueId('Lolli.Pop.NothingElse')
118  ];
119 
120  foreach ($expectedPackageKeys as $packageKey) {
121  $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
122 
123  mkdir($packagePath, 0770, true);
124  file_put_contents($packagePath . 'composer.json', '{"name": "' . $packageKey . '", "type": "typo3-test"}');
125  }
126 
127  $packageManager = $this->getAccessibleMock(PackageManager::class, ['sortAndSavePackageStates']);
128  $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
129  $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
130 
131  $packageManager->_set('packages', []);
132  $packageManager->_call('scanAvailablePackages');
133 
134  $packageStates = require('vfs://Test/Configuration/PackageStates.php');
135  $actualPackageKeys = array_keys($packageStates['packages']);
136  $this->assertEquals(sort($expectedPackageKeys), sort($actualPackageKeys));
137  }
138 
142  public function scanAvailablePackagesKeepsExistingPackageConfiguration()
143  {
144  $expectedPackageKeys = [
145  $this->getUniqueId('TYPO3.CMS'),
146  $this->getUniqueId('TYPO3.CMS.Test'),
147  $this->getUniqueId('TYPO3.YetAnotherTestPackage'),
148  $this->getUniqueId('Lolli.Pop.NothingElse')
149  ];
150 
151  $packagePaths = [];
152  foreach ($expectedPackageKeys as $packageKey) {
153  $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
154  $packagePaths[] = $packagePath;
155 
156  mkdir($packagePath, 0770, true);
157  file_put_contents($packagePath . 'composer.json', '{"name": "' . $packageKey . '", "type": "typo3-cms-test"}');
158  file_put_contents($packagePath . 'ext_emconf.php', '<?php' . LF . '$EM_CONF[$_EXTKEY] = [];');
159  }
160 
162  $packageManager = $this->getAccessibleMock(PackageManager::class, ['dummy']);
163  $packageManager->_set('packagesBasePaths', $packagePaths);
164  $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
165  $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
166 
168  $dependencyResolver = $this->createMock(DependencyResolver::class);
169  $dependencyResolver
170  ->expects($this->any())
171  ->method('sortPackageStatesConfigurationByDependency')
172  ->willReturnCallback('array_keys');
173 
174  $packageManager->injectDependencyResolver($dependencyResolver);
175 
176  $packageKey = $expectedPackageKeys[0];
177  $packageManager->_set('packageStatesConfiguration', [
178  'packages' => [
179  $packageKey => [
180  'packagePath' => 'Application/' . $packageKey . '/'
181  ]
182  ],
183  'version' => 5
184  ]);
185  $packageManager->_call('scanAvailablePackages');
186  $packageManager->_call('sortAndSavePackageStates');
187 
188  $packageStates = require('vfs://Test/Configuration/PackageStates.php');
189  $this->assertEquals('Application/' . $packageKey . '/', $packageStates['packages'][$packageKey]['packagePath']);
190  }
191 
195  public function packageStatesConfigurationContainsRelativePaths()
196  {
197  $packageKeys = [
198  $this->getUniqueId('Lolli.Pop.NothingElse'),
199  $this->getUniqueId('TYPO3.Package'),
200  $this->getUniqueId('TYPO3.YetAnotherTestPackage')
201  ];
202 
203  $packagePaths = [];
204  foreach ($packageKeys as $packageKey) {
205  $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
206 
207  mkdir($packagePath, 0770, true);
208  file_put_contents($packagePath . 'composer.json', '{"name": "' . $packageKey . '", "type": "typo3-cms-test"}');
209  file_put_contents($packagePath . 'ext_emconf.php', '<?php' . LF . '$EM_CONF[$_EXTKEY] = [];');
210  $packagePaths[] = $packagePath;
211  }
212 
214  $packageManager = $this->getAccessibleMock(PackageManager::class, ['sortAndSavePackageStates']);
215  $packageManager->_set('packagesBasePaths', $packagePaths);
216  $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
217  $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
218 
220  $dependencyResolver = $this->createMock(DependencyResolver::class);
221  $dependencyResolver
222  ->expects($this->any())
223  ->method('sortPackageStatesConfigurationByDependency')
224  ->willReturnCallback('array_keys');
225 
226  $packageManager->injectDependencyResolver($dependencyResolver);
227 
228  $packageManager->_set('packages', []);
229  $packageManager->_call('scanAvailablePackages');
230 
231  $expectedPackageStatesConfiguration = [];
232  foreach ($packageKeys as $packageKey) {
233  $expectedPackageStatesConfiguration[$packageKey] = [
234  'packagePath' => 'Application/' . $packageKey . '/'
235  ];
236  $packageManager->activatePackage($packageKey);
237  }
238 
239  $actualPackageStatesConfiguration = $packageManager->_get('packageStatesConfiguration');
240  $this->assertEquals($expectedPackageStatesConfiguration, $actualPackageStatesConfiguration['packages']);
241  }
242 
248  public function packageKeysAndPaths()
249  {
250  return [
251  ['TYPO3.YetAnotherTestPackage', 'vfs://Test/Packages/Application/TYPO3.YetAnotherTestPackage/'],
252  ['Lolli.Pop.NothingElse', 'vfs://Test/Packages/Application/Lolli.Pop.NothingElse/']
253  ];
254  }
255 
260  public function createPackageCreatesPackageFolderAndReturnsPackage($packageKey, $expectedPackagePath)
261  {
262  $actualPackage = $this->createPackage($packageKey);
263  $actualPackagePath = $actualPackage->getPackagePath();
264 
265  $this->assertEquals($expectedPackagePath, $actualPackagePath);
266  $this->assertTrue(is_dir($actualPackagePath), 'Package path should exist after createPackage()');
267  $this->assertEquals($packageKey, $actualPackage->getPackageKey());
268  $this->assertTrue($this->packageManager->isPackageAvailable($packageKey));
269  }
270 
275  {
276  $packageKey = 'Acme.YetAnotherTestPackage';
277 
278  $this->createPackage($packageKey);
279 
280  $this->packageManager->expects($this->any())->method('sortActivePackagesByDependencies')->will($this->returnValue([]));
281 
282  $this->packageManager->deactivatePackage($packageKey);
283  $this->assertFalse($this->packageManager->isPackageActive($packageKey));
284 
285  $this->packageManager->activatePackage($packageKey);
286  $this->assertTrue($this->packageManager->isPackageActive($packageKey));
287  }
288 
293  {
294  $this->expectException(ProtectedPackageKeyException::class);
295  $this->expectExceptionCode(1308662891);
296 
297  $package = $this->createPackage('Acme.YetAnotherTestPackage');
298  $package->setProtected(true);
299  $this->packageManager->expects($this->any())->method('sortActivePackagesByDependencies')->will($this->returnValue([]));
300  $this->packageManager->deactivatePackage('Acme.YetAnotherTestPackage');
301  }
302 
307  {
308  $this->expectException(UnknownPackageException::class);
309  $this->expectExceptionCode(1166543253);
310 
311  $this->packageManager->expects($this->any())->method('sortActivePackagesByDependencies')->will($this->returnValue([]));
312  $this->packageManager->deletePackage('PrettyUnlikelyThatThisPackageExists');
313  }
314 
319  {
320  $this->expectException(ProtectedPackageKeyException::class);
321  $this->expectExceptionCode(1220722120);
322 
323  $package = $this->createPackage('Acme.YetAnotherTestPackage');
324  $package->setProtected(true);
325  $this->packageManager->deletePackage('Acme.YetAnotherTestPackage');
326  }
327 
332  {
333  $this->createPackage('Acme.YetAnotherTestPackage');
334 
335  $this->packageManager->expects($this->any())->method('sortActivePackagesByDependencies')->will($this->returnValue([]));
336 
337  $this->assertTrue($this->packageManager->isPackageActive('Acme.YetAnotherTestPackage'));
338  $this->assertTrue($this->packageManager->isPackageAvailable('Acme.YetAnotherTestPackage'));
339 
340  $this->packageManager->deletePackage('Acme.YetAnotherTestPackage');
341 
342  $this->assertFalse($this->packageManager->isPackageActive('Acme.YetAnotherTestPackage'));
343  $this->assertFalse($this->packageManager->isPackageAvailable('Acme.YetAnotherTestPackage'));
344  }
345 
349  public function composerNamesAndPackageKeys()
350  {
351  return [
352  ['imagine/Imagine', 'imagine.Imagine'],
353  ['imagine/imagine', 'imagine.Imagine'],
354  ['typo3/cms', 'TYPO3.CMS'],
355  ['TYPO3/CMS', 'TYPO3.CMS']
356  ];
357  }
358 
363  public function getPackageKeyFromComposerNameIgnoresCaseDifferences($composerName, $packageKey)
364  {
365  $packageStatesConfiguration = [
366  'packages' => [
367  'TYPO3.CMS',
368  'imagine.Imagine'
369  ]
370  ];
371  $composerNameToPackageKeyMap = [
372  'typo3/cms' => 'TYPO3.CMS',
373  'imagine/imagine' => 'imagine.Imagine'
374  ];
375 
376  $packageManager = $this->getAccessibleMock(PackageManager::class, ['resolvePackageDependencies']);
377  $packageManager->_set('packageStatesConfiguration', $packageStatesConfiguration);
378  $packageManager->_set('composerNameToPackageKeyMap', $composerNameToPackageKeyMap);
379 
380  $this->assertEquals($packageKey, $packageManager->_call('getPackageKeyFromComposerName', $composerName));
381  }
382 }
createPackageCreatesPackageFolderAndReturnsPackage($packageKey, $expectedPackagePath)
getPackageKeyFromComposerNameIgnoresCaseDifferences($composerName, $packageKey)