2419052a6203c427811f37f7f6bbe451dc04a837
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Tests / Unit / Utility / InstallUtilityTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Extensionmanager\Tests\Unit\Utility;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\Cache\CacheManager;
19 use TYPO3\CMS\Core\Registry;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Extensionmanager\Utility\DependencyUtility;
22 use TYPO3\CMS\Extensionmanager\Utility\InstallUtility;
23 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
24
25 /**
26 * Test case
27 */
28 class InstallUtilityTest extends UnitTestCase
29 {
30 /**
31 * @var string
32 */
33 protected $extensionKey;
34
35 /**
36 * @var array
37 */
38 protected $extensionData = [];
39
40 /**
41 * @var array List of created fake extensions to be deleted in tearDown() again
42 */
43 protected $fakedExtensions = [];
44
45 /**
46 * @var \PHPUnit_Framework_MockObject_MockObject|InstallUtility|\TYPO3\TestingFramework\Core\AccessibleObjectInterface
47 */
48 protected $installMock;
49
50 /**
51 */
52 protected function setUp()
53 {
54 $this->extensionKey = 'dummy';
55 $this->extensionData = [
56 'key' => $this->extensionKey
57 ];
58 $this->installMock = $this->getAccessibleMock(
59 InstallUtility::class,
60 [
61 'isLoaded',
62 'loadExtension',
63 'unloadExtension',
64 'processDatabaseUpdates',
65 'processRuntimeDatabaseUpdates',
66 'reloadCaches',
67 'processCachingFrameworkUpdates',
68 'saveDefaultConfiguration',
69 'getExtensionArray',
70 'enrichExtensionWithDetails',
71 'ensureConfiguredDirectoriesExist',
72 'importInitialFiles',
73 'emitAfterExtensionInstallSignal'
74 ],
75 [],
76 '',
77 false
78 );
79 $dependencyUtility = $this->getMockBuilder(DependencyUtility::class)->getMock();
80 $this->installMock->_set('dependencyUtility', $dependencyUtility);
81 $this->installMock->expects($this->any())
82 ->method('getExtensionArray')
83 ->with($this->extensionKey)
84 ->will($this->returnCallback([$this, 'getExtensionData']));
85 $this->installMock->expects($this->any())
86 ->method('enrichExtensionWithDetails')
87 ->with($this->extensionKey)
88 ->will($this->returnCallback([$this, 'getExtensionData']));
89 }
90
91 /**
92 * @return array
93 */
94 public function getExtensionData(): array
95 {
96 return $this->extensionData;
97 }
98
99 /**
100 */
101 protected function tearDown()
102 {
103 foreach ($this->fakedExtensions as $fakeExtkey => $fakeExtension) {
104 $this->testFilesToDelete[] = PATH_site . 'typo3temp/var/tests/' . $fakeExtkey;
105 }
106 parent::tearDown();
107 }
108
109 /**
110 * Creates a fake extension inside typo3temp/. No configuration is created,
111 * just the folder
112 *
113 * @return string The extension key
114 */
115 protected function createFakeExtension(): string
116 {
117 $extKey = strtolower($this->getUniqueId('testing'));
118 $absExtPath = PATH_site . 'typo3temp/var/tests/' . $extKey;
119 $relPath = 'typo3temp/var/tests/' . $extKey . '/';
120 GeneralUtility::mkdir($absExtPath);
121 $this->fakedExtensions[$extKey] = [
122 'siteRelPath' => $relPath
123 ];
124 return $extKey;
125 }
126
127 /**
128 * @test
129 */
130 public function installCallsProcessRuntimeDatabaseUpdates()
131 {
132 $this->installMock->expects($this->once())
133 ->method('processRuntimeDatabaseUpdates')
134 ->with($this->extensionKey);
135
136 $cacheManagerMock = $this->getMockBuilder(CacheManager::class)->getMock();
137 $cacheManagerMock->expects($this->once())->method('flushCachesInGroup');
138 $this->installMock->_set('cacheManager', $cacheManagerMock);
139 $this->installMock->install($this->extensionKey);
140 }
141
142 /**
143 * @test
144 */
145 public function installCallsLoadExtension()
146 {
147 $cacheManagerMock = $this->getMockBuilder(CacheManager::class)->getMock();
148 $cacheManagerMock->expects($this->once())->method('flushCachesInGroup');
149 $this->installMock->_set('cacheManager', $cacheManagerMock);
150 $this->installMock->expects($this->once())->method('loadExtension');
151 $this->installMock->install($this->extensionKey);
152 }
153
154 /**
155 * @test
156 */
157 public function installCallsFlushCachesIfClearCacheOnLoadIsSet()
158 {
159 $this->extensionData['clearcacheonload'] = true;
160 $cacheManagerMock = $this->getMockBuilder(CacheManager::class)->getMock();
161 $cacheManagerMock->expects($this->once())->method('flushCaches');
162 $this->installMock->_set('cacheManager', $cacheManagerMock);
163 $this->installMock->install($this->extensionKey);
164 }
165
166 /**
167 * @test
168 */
169 public function installCallsFlushCachesIfClearCacheOnLoadCamelCasedIsSet()
170 {
171 $this->extensionData['clearCacheOnLoad'] = true;
172 $cacheManagerMock = $this->getMockBuilder(CacheManager::class)->getMock();
173 $cacheManagerMock->expects($this->once())->method('flushCaches');
174 $this->installMock->_set('cacheManager', $cacheManagerMock);
175 $this->installMock->install($this->extensionKey);
176 }
177
178 /**
179 * @test
180 */
181 public function installationOfAnExtensionWillCallEnsureThatDirectoriesExist()
182 {
183 $cacheManagerMock = $this->getMockBuilder(CacheManager::class)->getMock();
184 $cacheManagerMock->expects($this->once())->method('flushCachesInGroup');
185 $this->installMock->_set('cacheManager', $cacheManagerMock);
186 $this->installMock->expects($this->once())->method('ensureConfiguredDirectoriesExist');
187 $this->installMock->install($this->extensionKey);
188 }
189
190 /**
191 * @test
192 */
193 public function installCallsReloadCaches()
194 {
195 $cacheManagerMock = $this->getMockBuilder(CacheManager::class)->getMock();
196 $cacheManagerMock->expects($this->once())->method('flushCachesInGroup');
197 $this->installMock->_set('cacheManager', $cacheManagerMock);
198 $this->installMock->expects($this->once())->method('reloadCaches');
199 $this->installMock->install('dummy');
200 }
201
202 /**
203 * @test
204 */
205 public function installCallsSaveDefaultConfigurationWithExtensionKey()
206 {
207 $cacheManagerMock = $this->getMockBuilder(CacheManager::class)->getMock();
208 $cacheManagerMock->expects($this->once())->method('flushCachesInGroup');
209 $this->installMock->_set('cacheManager', $cacheManagerMock);
210 $this->installMock->expects($this->once())->method('saveDefaultConfiguration')->with('dummy');
211 $this->installMock->install('dummy');
212 }
213
214 /**
215 * @test
216 */
217 public function uninstallCallsUnloadExtension()
218 {
219 $this->installMock->expects($this->once())->method('unloadExtension');
220 $this->installMock->uninstall($this->extensionKey);
221 }
222
223 /**
224 * @test
225 */
226 public function processDatabaseUpdatesCallsUpdateDb()
227 {
228 $extKey = $this->createFakeExtension();
229 $extPath = PATH_site . 'typo3temp/var/tests/' . $extKey . '/';
230 $extTablesFile = $extPath . 'ext_tables.sql';
231 $fileContent = 'DUMMY TEXT';
232 file_put_contents($extTablesFile, $fileContent);
233 $installMock = $this->getAccessibleMock(
234 InstallUtility::class,
235 ['updateDbWithExtTablesSql', 'importStaticSqlFile', 'importT3DFile'],
236 [],
237 '',
238 false
239 );
240 $dependencyUtility = $this->getMockBuilder(DependencyUtility::class)->getMock();
241 $installMock->_set('dependencyUtility', $dependencyUtility);
242
243 $installMock->expects($this->once())->method('updateDbWithExtTablesSql');
244 $installMock->processDatabaseUpdates($this->fakedExtensions[$extKey]);
245 }
246
247 /**
248 * @test
249 */
250 public function processDatabaseUpdatesCallsImportStaticSqlFile()
251 {
252 $extKey = $this->createFakeExtension();
253 $extensionSiteRelPath = 'typo3temp/var/tests/' . $extKey . '/';
254 $installMock = $this->getAccessibleMock(
255 InstallUtility::class,
256 ['importStaticSqlFile', 'updateDbWithExtTablesSql', 'importT3DFile'],
257 [],
258 '',
259 false
260 );
261 $dependencyUtility = $this->getMockBuilder(DependencyUtility::class)->getMock();
262 $installMock->_set('dependencyUtility', $dependencyUtility);
263 $installMock->expects($this->once())->method('importStaticSqlFile')->with($extensionSiteRelPath);
264 $installMock->processDatabaseUpdates($this->fakedExtensions[$extKey]);
265 }
266
267 /**
268 * @return array
269 */
270 public function processDatabaseUpdatesCallsImportFileDataProvider(): array
271 {
272 return [
273 'T3D file' => [
274 'data.t3d'
275 ],
276 'XML file' => [
277 'data.xml'
278 ]
279 ];
280 }
281
282 /**
283 * @param string $fileName
284 * @test
285 * @dataProvider processDatabaseUpdatesCallsImportFileDataProvider
286 */
287 public function processDatabaseUpdatesCallsImportFile($fileName)
288 {
289 $extKey = $this->createFakeExtension();
290 $absPath = PATH_site . $this->fakedExtensions[$extKey]['siteRelPath'];
291 GeneralUtility::mkdir($absPath . '/Initialisation');
292 file_put_contents($absPath . '/Initialisation/' . $fileName, 'DUMMY');
293 $installMock = $this->getAccessibleMock(
294 InstallUtility::class,
295 ['updateDbWithExtTablesSql', 'importStaticSqlFile', 'importT3DFile'],
296 [],
297 '',
298 false
299 );
300 $dependencyUtility = $this->getMockBuilder(DependencyUtility::class)->getMock();
301 $installMock->_set('dependencyUtility', $dependencyUtility);
302 $installMock->expects($this->once())->method('importT3DFile')->with($this->fakedExtensions[$extKey]['siteRelPath']);
303 $installMock->processDatabaseUpdates($this->fakedExtensions[$extKey]);
304 }
305
306 /**
307 * @return array
308 */
309 public function importT3DFileDoesNotImportFileIfAlreadyImportedDataProvider(): array
310 {
311 return [
312 'Import T3D file when T3D was imported before extension to XML' => [
313 'data.t3d',
314 'dataImported',
315 'data.t3d',
316 ],
317 'Import T3D file when a file was imported after extension to XML' => [
318 'data.t3d',
319 'data.t3d',
320 'dataImported'
321 ],
322 'Import XML file when T3D was imported before extension to XML' => [
323 'data.xml',
324 'dataImported',
325 'data.t3d'
326 ],
327 'Import XML file when a file was imported after extension to XML' => [
328 'data.xml',
329 'data.t3d',
330 'dataImported'
331 ]
332 ];
333 }
334
335 /**
336 * @param string $fileName
337 * @param string $registryNameReturnsFalse
338 * @param string $registryNameReturnsTrue
339 * @test
340 * @dataProvider importT3DFileDoesNotImportFileIfAlreadyImportedDataProvider
341 */
342 public function importT3DFileDoesNotImportFileIfAlreadyImported($fileName, $registryNameReturnsFalse, $registryNameReturnsTrue)
343 {
344 $extKey = $this->createFakeExtension();
345 $absPath = PATH_site . $this->fakedExtensions[$extKey]['siteRelPath'];
346 GeneralUtility::mkdir($absPath . 'Initialisation');
347 file_put_contents($absPath . 'Initialisation/' . $fileName, 'DUMMY');
348 $registryMock = $this->getMockBuilder(Registry::class)
349 ->setMethods(['get', 'set'])
350 ->getMock();
351 $registryMock
352 ->expects($this->any())
353 ->method('get')
354 ->will($this->returnValueMap(
355 [
356 ['extensionDataImport', $this->fakedExtensions[$extKey]['siteRelPath'] . 'Initialisation/' . $registryNameReturnsFalse, null, false],
357 ['extensionDataImport', $this->fakedExtensions[$extKey]['siteRelPath'] . 'Initialisation/' . $registryNameReturnsTrue, null, true],
358 ]
359 ));
360 $installMock = $this->getAccessibleMock(
361 InstallUtility::class,
362 ['getRegistry', 'getImportExportUtility'],
363 [],
364 '',
365 false
366 );
367 $dependencyUtility = $this->getMockBuilder(DependencyUtility::class)->getMock();
368 $installMock->_set('dependencyUtility', $dependencyUtility);
369 $installMock->_set('registry', $registryMock);
370 $installMock->expects($this->never())->method('getImportExportUtility');
371 $installMock->_call('importT3DFile', $this->fakedExtensions[$extKey]['siteRelPath']);
372 }
373 }