TYPO3 CMS  TYPO3_6-2
FileHandlingUtilityTest.php
Go to the documentation of this file.
1 <?php
3 
22 
26  protected $fakedExtensions = array();
27 
31  protected $resourcesToRemove = array();
32 
36  public function tearDown() {
37  foreach ($this->fakedExtensions as $extension => $dummy) {
38  \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir(PATH_site . 'typo3conf/ext/' . $extension, TRUE);
39  }
40  foreach ($this->resourcesToRemove as $resource) {
41  if (file_exists($resource) && is_file($resource)) {
42  unlink($resource);
43  } elseif(file_exists($resource) && is_dir($resource)) {
44  rmdir($resource);
45  }
46  }
47  parent::tearDown();
48  }
49 
57  protected function createFakeExtension($extkeyOnly = FALSE) {
58  $extKey = strtolower($this->getUniqueId('testing'));
59  $absExtPath = PATH_site . 'typo3conf/ext/' . $extKey . '/';
60  $relPath = 'typo3conf/ext/' . $extKey . '/';
61  $this->fakedExtensions[$extKey] = array(
62  'siteRelPath' => $relPath,
63  'siteAbsPath' => $absExtPath
64  );
65  if ($extkeyOnly === TRUE) {
66  return $extKey;
67  }
69  return $extKey;
70  }
71 
77  $extKey = $this->createFakeExtension();
78  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('removeDirectory', 'addDirectory'));
79  $fileHandlerMock->expects($this->once())->method('removeDirectory')->with(PATH_site . 'typo3conf/ext/' . $extKey . '/');
80  $fileHandlerMock->_call('makeAndClearExtensionDir', $extKey);
81  }
82 
86  public function invalidRelativePathDataProvider() {
87  return array(
88  array('../../'),
89  array('/foo/bar'),
90  array('foo//bar'),
91  array('foo/bar' . chr(0)),
92  );
93  }
94 
101  public function getAbsolutePathThrowsExceptionForInvalidRelativePaths($invalidRelativePath) {
102  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('dummy'));
103  $fileHandlerMock->_call('getAbsolutePath', $invalidRelativePath);
104  }
105 
109  public function validRelativePathDataProvider() {
110  return array(
111  array('foo/../bar', PATH_site . 'bar'),
112  array('bas', PATH_site . 'bas'),
113  );
114  }
115 
122  public function getAbsolutePathReturnsAbsolutePathForValidRelativePaths($validRelativePath, $expectedAbsolutePath) {
123  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('dummy'));
124  $this->assertSame($expectedAbsolutePath, $fileHandlerMock->_call('getAbsolutePath', $validRelativePath));
125  }
126 
132  $extKey = $this->createFakeExtension();
133  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('removeDirectory', 'addDirectory'));
134  $fileHandlerMock->expects($this->once())->method('addDirectory')->with(PATH_site . 'typo3conf/ext/' . $extKey . '/');
135  $fileHandlerMock->_call('makeAndClearExtensionDir', $extKey);
136  }
137 
144  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('removeDirectory', 'addDirectory'));
145  $fileHandlerMock->_call('makeAndClearExtensionDir', 'testing123', 'fakepath');
146  }
147 
152  public function addDirectoryAddsDirectory() {
153  $extDirPath = $this->fakedExtensions[$this->createFakeExtension(TRUE)]['siteAbsPath'];
154  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('dummy'));
155  $this->assertFalse(is_dir($extDirPath));
156  $fileHandlerMock->_call('addDirectory', $extDirPath);
157  $this->assertTrue(is_dir($extDirPath));
158  }
159 
165  $extDirPath = $this->fakedExtensions[$this->createFakeExtension()]['siteAbsPath'];
166  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('dummy'));
167  $this->assertTrue(is_dir($extDirPath));
168  $fileHandlerMock->_call('removeDirectory', $extDirPath);
169  $this->assertFalse(is_dir($extDirPath));
170  }
171 
176  public function removeDirectoryRemovesSymlink() {
177  $absoluteSymlinkPath = PATH_site . 'typo3temp/' . $this->getUniqueId('test_symlink_');
178  $absoluteFilePath = PATH_site . 'typo3temp/' . $this->getUniqueId('test_file_');
179  touch($absoluteFilePath);
180  $this->resourcesToRemove[] = $absoluteFilePath;
181  symlink($absoluteFilePath, $absoluteSymlinkPath);
182  $fileHandler = new \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility();
183  $fileHandler->removeDirectory($absoluteSymlinkPath);
184  $this->assertFalse(is_link($absoluteSymlinkPath));
185  }
186 
192  $absoluteSymlinkPath = PATH_site . 'typo3temp/' . $this->getUniqueId('test_symlink_');
193  $absoluteDirectoryPath = PATH_site . 'typo3temp/' . $this->getUniqueId('test_dir_') . '/';
194  $relativeFilePath = $this->getUniqueId('test_file_');
195 
196  mkdir($absoluteDirectoryPath);
197  touch($absoluteDirectoryPath . $relativeFilePath);
198 
199  $this->resourcesToRemove[] = $absoluteDirectoryPath . $relativeFilePath;
200  $this->resourcesToRemove[] = $absoluteDirectoryPath;
201 
202  symlink($absoluteDirectoryPath, $absoluteSymlinkPath);
203 
204  $fileHandler = new \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility();
205  $fileHandler->removeDirectory($absoluteSymlinkPath);
206  $this->assertTrue(is_file($absoluteDirectoryPath . $relativeFilePath));
207  }
208 
214  $extensionData = array(
215  'extKey' => 'test'
216  );
217  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array(
218  'makeAndClearExtensionDir',
219  'writeEmConfToFile',
220  'extractFilesArrayFromExtensionData',
221  'extractDirectoriesFromExtensionData',
222  'createDirectoriesForExtensionFiles',
223  'writeExtensionFiles'
224  ));
225  $fileHandlerMock->expects($this->once())->method('extractFilesArrayFromExtensionData')->will($this->returnValue(array()));
226  $fileHandlerMock->expects($this->once())->method('extractDirectoriesFromExtensionData')->will($this->returnValue(array()));
227  $fileHandlerMock->expects($this->once())->method('makeAndClearExtensionDir')->with($extensionData['extKey']);
228  $fileHandlerMock->_call('unpackExtensionFromExtensionDataArray', $extensionData);
229  }
230 
236  $extensionData = array(
237  'extKey' => 'test'
238  );
239  $files = array(
240  'ChangeLog' => array(
241  'name' => 'ChangeLog',
242  'size' => 4559,
243  'mtime' => 1219448527,
244  'is_executable' => FALSE,
245  'content' => 'some content to write'
246  ),
247  'doc/' => array(
248  'name' => 'doc/',
249  'size' => 0,
250  'mtime' => 1219448527,
251  'is_executable' => FALSE,
252  'content' => ''
253  ),
254  'doc/ChangeLog' => array(
255  'name' => 'ChangeLog',
256  'size' => 4559,
257  'mtime' => 1219448527,
258  'is_executable' => FALSE,
259  'content' => 'some content to write'
260  ),
261  );
262  $cleanedFiles = array(
263  'ChangeLog' => array(
264  'name' => 'ChangeLog',
265  'size' => 4559,
266  'mtime' => 1219448527,
267  'is_executable' => FALSE,
268  'content' => 'some content to write'
269  ),
270  'doc/ChangeLog' => array(
271  'name' => 'ChangeLog',
272  'size' => 4559,
273  'mtime' => 1219448527,
274  'is_executable' => FALSE,
275  'content' => 'some content to write'
276  ),
277  );
278  $directories = array(
279  'doc/',
280  'mod/doc/'
281  );
282 
283  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array(
284  'makeAndClearExtensionDir',
285  'writeEmConfToFile',
286  'extractFilesArrayFromExtensionData',
287  'extractDirectoriesFromExtensionData',
288  'createDirectoriesForExtensionFiles',
289  'writeExtensionFiles'
290  ));
291  $fileHandlerMock->expects($this->once())->method('extractFilesArrayFromExtensionData')->will($this->returnValue($files));
292  $fileHandlerMock->expects($this->once())->method('extractDirectoriesFromExtensionData')->will($this->returnValue($directories));
293  $fileHandlerMock->expects($this->once())->method('createDirectoriesForExtensionFiles')->with($directories);
294  $fileHandlerMock->expects($this->once())->method('writeExtensionFiles')->with($cleanedFiles);
295  $fileHandlerMock->_call('unpackExtensionFromExtensionDataArray', $extensionData);
296  }
297 
303  $extensionData = array(
304  'key' => 'test',
305  'FILES' => array(
306  'filename1' => 'dummycontent',
307  'filename2' => 'dummycontent2'
308  )
309  );
310  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
311  $extractedFiles = $fileHandlerMock->_call('extractFilesArrayFromExtensionData', $extensionData);
312  $this->assertArrayHasKey('filename1', $extractedFiles);
313  $this->assertArrayHasKey('filename2', $extractedFiles);
314  }
315 
320  public function writeExtensionFilesWritesFiles() {
321  $files = array(
322  'ChangeLog' => array(
323  'name' => 'ChangeLog',
324  'size' => 4559,
325  'mtime' => 1219448527,
326  'is_executable' => FALSE,
327  'content' => 'some content to write'
328  ),
329  'README' => array(
330  'name' => 'README',
331  'size' => 4566,
332  'mtime' => 1219448533,
333  'is_executable' => FALSE,
334  'content' => 'FEEL FREE TO ADD SOME DOCUMENTATION HERE'
335  )
336  );
337  $rootPath = ($extDirPath = $this->fakedExtensions[$this->createFakeExtension()]['siteAbsPath']);
338  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
339  $fileHandlerMock->_call('writeExtensionFiles', $files, $rootPath);
340  $this->assertTrue(file_exists($rootPath . 'ChangeLog'));
341  }
342 
348  $files = array(
349  'ChangeLog' => array(
350  'name' => 'ChangeLog',
351  'size' => 4559,
352  'mtime' => 1219448527,
353  'is_executable' => FALSE,
354  'content' => 'some content to write'
355  ),
356  'doc/' => array(
357  'name' => 'doc/',
358  'size' => 0,
359  'mtime' => 1219448527,
360  'is_executable' => FALSE,
361  'content' => ''
362  ),
363  'doc/ChangeLog' => array(
364  'name' => 'ChangeLog',
365  'size' => 4559,
366  'mtime' => 1219448527,
367  'is_executable' => FALSE,
368  'content' => 'some content to write'
369  ),
370  'doc/README' => array(
371  'name' => 'README',
372  'size' => 4566,
373  'mtime' => 1219448533,
374  'is_executable' => FALSE,
375  'content' => 'FEEL FREE TO ADD SOME DOCUMENTATION HERE'
376  ),
377  'mod/doc/README' => array(
378  'name' => 'README',
379  'size' => 4566,
380  'mtime' => 1219448533,
381  'is_executable' => FALSE,
382  'content' => 'FEEL FREE TO ADD SOME DOCUMENTATION HERE'
383  )
384  );
385  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
386  $extractedDirectories = $fileHandlerMock->_call('extractDirectoriesFromExtensionData', $files);
387  $expected = array(
388  'doc/',
389  'mod/doc/'
390  );
391  $this->assertSame($expected, array_values($extractedDirectories));
392  }
393 
399  $rootPath = $this->fakedExtensions[$this->createFakeExtension()]['siteAbsPath'];
400  $directories = array(
401  'doc/',
402  'mod/doc/'
403  );
404  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
405  $this->assertFalse(is_dir($rootPath . 'doc/'));
406  $this->assertFalse(is_dir($rootPath . 'mod/doc/'));
407  $fileHandlerMock->_call('createDirectoriesForExtensionFiles', $directories, $rootPath);
408  $this->assertTrue(is_dir($rootPath . 'doc/'));
409  $this->assertTrue(is_dir($rootPath . 'mod/doc/'));
410  }
411 
416  public function writeEmConfWritesEmConfFile() {
417  $extKey = $this->createFakeExtension();
418  $extensionData = array(
419  'extKey' => $extKey,
420  'EM_CONF' => array(
421  'title' => 'Plugin cache engine',
422  'description' => 'Provides an interface to cache plugin content elements based on 4.3 caching framework',
423  'category' => 'Frontend',
424  'shy' => 0
425  )
426  );
427  $rootPath = $this->fakedExtensions[$extKey]['siteAbsPath'];
428  $emConfUtilityMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\EmConfUtility', array('constructEmConf'));
429  $emConfUtilityMock->expects($this->once())->method('constructEmConf')->with($extensionData)->will($this->returnValue(var_export($extensionData['EM_CONF'], TRUE)));
430  $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
431  $fileHandlerMock->_set('emConfUtility', $emConfUtilityMock);
432  $fileHandlerMock->_call('writeEmConfToFile', $extensionData, $rootPath);
433  $this->assertTrue(file_exists($rootPath . 'ext_emconf.php'));
434  }
435 
439  protected function getPreparedFileHandlingMockForDirectoryCreationTests() {
441  $fileHandlerMock = $this->getMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('createNestedDirectory', 'getAbsolutePath', 'directoryExists'));
442  $fileHandlerMock->expects($this->any())
443  ->method('getAbsolutePath')
444  ->will($this->returnArgument(0));
445  return $fileHandlerMock;
446  }
447 
452  $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
453  $fileHandlerMock->expects($this->never())
454  ->method('createNestedDirectory');
455  $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
456  'key' => 'foo_bar',
457  'uploadfolder' => 0,
458  )
459  );
460  }
461 
466  $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
467  $fileHandlerMock->expects($this->never())
468  ->method('createNestedDirectory');
469  $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
470  'key' => 'foo_bar',
471  'createDirs' => '',
472  )
473  );
474  }
475 
480  $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
481  $fileHandlerMock->expects($this->once())
482  ->method('createNestedDirectory')
483  ->with('uploads/tx_foobar/');
484  $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
485  'key' => 'foo_bar',
486  'uploadfolder' => 1,
487  )
488  );
489  }
490 
495  $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
496  $fileHandlerMock->expects($this->exactly(2))
497  ->method('createNestedDirectory')
498  ->will($this->returnCallback(function($path) {
499  if (!in_array($path, array('foo/bar', 'baz/foo'))) {
500  throw new \Exception('Path "' . $path . '" is not expected to be created');
501  }
502 
503  })
504  );
505  $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
506  'key' => 'foo_bar',
507  'createDirs' => 'foo/bar, baz/foo',
508  )
509  );
510  }
511 
516  $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
517  $fileHandlerMock->expects($this->exactly(3))
518  ->method('directoryExists')
519  ->will($this->returnValue(TRUE));
520  $fileHandlerMock->expects($this->never())
521  ->method('createNestedDirectory');
522  $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
523  'key' => 'foo_bar',
524  'uploadfolder' => 1,
525  'createDirs' => 'foo/bar, baz/foo',
526  )
527  );
528  }
529 
536  // Create extension for testing:
537  $extKey = $this->createFakeExtension();
538  $extensionRoot = $this->fakedExtensions[$extKey]['siteAbsPath'];
539 
540  // Build mocked fileHandlingUtility:
541  $fileHandlerMock = $this->getAccessibleMock(
542  'TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility',
543  array('getAbsoluteExtensionPath', 'getExtensionVersion')
544  );
545  $fileHandlerMock->expects($this->any())
546  ->method('getAbsoluteExtensionPath')
547  ->will($this->returnValue($extensionRoot));
548  $fileHandlerMock->expects($this->any())
549  ->method('getExtensionVersion')
550  ->will($this->returnValue('0.0.0'));
551 
552  // Add files and directories to extension:
553  touch($extensionRoot . 'emptyFile.txt');
554  file_put_contents($extensionRoot . 'notEmptyFile.txt', 'content');
555  touch($extensionRoot . '.hiddenFile');
556  mkdir($extensionRoot . 'emptyDir');
557  mkdir($extensionRoot . 'notEmptyDir');
558  touch($extensionRoot . 'notEmptyDir/file.txt');
559 
560  // Create zip-file from extension
561  $filename = $fileHandlerMock->_call('createZipFileFromExtension', $extKey);
562 
563  $expectedFilename = PATH_site . 'typo3temp/' . $extKey . '_0.0.0_' . date('YmdHi') . '.zip';
564  $this->assertEquals($expectedFilename, $filename, 'Archive file name differs from expectation');
565 
566  // File was created
567  $this->assertTrue(file_exists($filename), 'Zip file not created');
568  $this->resourcesToRemove[] = $filename;
569 
570  // Read archive and check its contents
571  $archive = new \ZipArchive();
572  $this->assertTrue($archive->open($filename), 'Unable to open archive');
573  $this->assertEquals($archive->statName('emptyFile.txt')->size, 0, 'Empty file not in archive');
574  $this->assertEquals($archive->getFromName('notEmptyFile.txt'), 'content', 'Expected content not found');
575  $this->assertFalse($archive->statName('.hiddenFile'), 'Hidden file not in archive');
576  $this->assertTrue(is_array($archive->statName('emptyDir/')), 'Empty directory not in archive');
577  $this->assertTrue(is_array($archive->statName('notEmptyDir/')), 'Not empty directory not in archive');
578  $this->assertTrue(is_array($archive->statName('notEmptyDir/file.txt')), 'File within directory not in archive');
579 
580  // Check that the archive has no additional content
581  $this->assertEquals($archive->numFiles, 5, 'Too many or too less files in archive');
582  }
583 }
static rmdir($path, $removeNonEmpty=FALSE)
getAccessibleMock( $originalClassName, array $methods=array(), array $arguments=array(), $mockClassName='', $callOriginalConstructor=TRUE, $callOriginalClone=TRUE, $callAutoload=TRUE)
getAbsolutePathReturnsAbsolutePathForValidRelativePaths($validRelativePath, $expectedAbsolutePath)