‪TYPO3CMS  10.4
FileHandlingUtility.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\Log\LoggerAwareInterface;
19 use Psr\Log\LoggerAwareTrait;
29 
34 class ‪FileHandlingUtility implements ‪SingletonInterface, LoggerAwareInterface
35 {
36  use LoggerAwareTrait;
37 
41  protected ‪$emConfUtility;
42 
46  protected ‪$installUtility;
47 
51  protected ‪$languageService;
52 
56  public function ‪injectEmConfUtility(EmConfUtility ‪$emConfUtility)
57  {
58  $this->emConfUtility = ‪$emConfUtility;
59  }
60 
65  {
66  $this->installUtility = ‪$installUtility;
67  }
68 
73  {
74  $this->languageService = ‪$languageService;
75  }
76 
80  public function ‪initializeObject()
81  {
82  $this->languageService->includeLLFile('EXT:extensionmanager/Resources/Private/Language/locallang.xlf');
83  }
84 
92  public function ‪unpackExtensionFromExtensionDataArray(array $extensionData, ‪Extension $extension = null, $pathType = 'Local')
93  {
94  $extensionDir = $this->‪makeAndClearExtensionDir($extensionData['extKey'], $pathType);
95  $files = $this->‪extractFilesArrayFromExtensionData($extensionData);
96  $directories = $this->‪extractDirectoriesFromExtensionData($files);
97  $files = array_diff_key($files, array_flip($directories));
98  $this->‪createDirectoriesForExtensionFiles($directories, $extensionDir);
99  $this->‪writeExtensionFiles($files, $extensionDir);
100  $this->‪writeEmConfToFile($extensionData, $extensionDir, $extension);
101  $this->‪reloadPackageInformation($extensionData['extKey']);
102  }
103 
110  protected function ‪extractDirectoriesFromExtensionData(array $files)
111  {
112  $directories = [];
113  foreach ($files as $filePath => $file) {
114  preg_match('/(.*)\\//', $filePath, $matches);
115  if (!empty($matches[0])) {
116  $directories[] = $matches[0];
117  }
118  }
119  return array_unique($directories);
120  }
121 
128  protected function ‪extractFilesArrayFromExtensionData(array $extensionData)
129  {
130  return $extensionData['FILES'];
131  }
132 
140  protected function ‪createDirectoriesForExtensionFiles(array $directories, $rootPath)
141  {
142  foreach ($directories as $directory) {
143  $this->‪createNestedDirectory($rootPath . $directory);
144  }
145  }
146 
153  protected function ‪createNestedDirectory($directory)
154  {
155  try {
156  ‪GeneralUtility::mkdir_deep($directory);
157  } catch (\RuntimeException $exception) {
159  sprintf($this->languageService->getLL('fileHandling.couldNotCreateDirectory'), $this->getRelativePath($directory)),
160  1337280416
161  );
162  }
163  }
164 
171  protected function ‪writeExtensionFiles(array $files, $rootPath)
172  {
173  foreach ($files as $file) {
174  ‪GeneralUtility::writeFile($rootPath . $file['name'], $file['content']);
175  }
176  }
177 
187  protected function ‪makeAndClearExtensionDir($extensionKey, $pathType = 'Local')
188  {
189  $extDirPath = $this->‪getExtensionDir($extensionKey, $pathType);
190  if (is_dir($extDirPath)) {
191  $this->‪removeDirectory($extDirPath);
192  }
193  $this->‪addDirectory($extDirPath);
194 
195  return $extDirPath;
196  }
197 
206  public function ‪getExtensionDir($extensionKey, $pathType = 'Local')
207  {
209  $path = $paths[$pathType] ?? '';
210  if (!$path || !is_dir($path) || !$extensionKey) {
212  sprintf($this->languageService->getLL('fileHandling.installPathWasNoDirectory'), $this->getRelativePath($path)),
213  1337280417
214  );
215  }
216 
217  return $path . $extensionKey . '/';
218  }
219 
226  protected function ‪addDirectory($extDirPath)
227  {
228  ‪GeneralUtility::mkdir($extDirPath);
229  if (!is_dir($extDirPath)) {
231  sprintf($this->languageService->getLL('fileHandling.couldNotCreateDirectory'), $this->getRelativePath($extDirPath)),
232  1337280418
233  );
234  }
235  }
236 
243  public function ‪removeDirectory($extDirPath)
244  {
245  $extDirPath = GeneralUtility::fixWindowsFilePath($extDirPath);
246  $extensionPathWithoutTrailingSlash = rtrim($extDirPath, '/');
247  if (is_link($extensionPathWithoutTrailingSlash) && !‪Environment::isWindows()) {
248  $result = unlink($extensionPathWithoutTrailingSlash);
249  } else {
250  $result = ‪GeneralUtility::rmdir($extDirPath, true);
251  }
252  if ($result === false) {
254  sprintf($this->languageService->getLL('fileHandling.couldNotRemoveDirectory'), $this->getRelativePath($extDirPath)),
255  1337280415
256  );
257  }
258  }
259 
268  protected function ‪writeEmConfToFile(array $extensionData, $rootPath, ‪Extension $extension = null)
269  {
270  $emConfFileData = [];
271  if (file_exists($rootPath . 'ext_emconf.php')) {
272  $emConfFileData = $this->emConfUtility->includeEmConf(
273  $extensionData['extKey'],
274  [
275  'packagePath' => $rootPath,
276  'siteRelPath' => ‪PathUtility::stripPathSitePrefix($rootPath)
277  ]
278  );
279  $emConfFileData = is_array($emConfFileData) ? $emConfFileData : [];
280  }
281  $extensionData['EM_CONF'] = array_replace_recursive($emConfFileData, $extensionData['EM_CONF']);
282  $emConfContent = $this->emConfUtility->constructEmConf($extensionData, $extension);
283  ‪GeneralUtility::writeFile($rootPath . 'ext_emconf.php', $emConfContent);
284  }
285 
292  public function ‪isValidExtensionPath($path)
293  {
294  $allowedPaths = ‪Extension::returnAllowedInstallPaths();
295  foreach ($allowedPaths as $allowedPath) {
296  if (GeneralUtility::isFirstPartOfStr($path, $allowedPath)) {
297  return true;
298  }
299  }
300  return false;
301  }
302 
310  protected function ‪getAbsolutePath($relativePath)
311  {
312  $absolutePath = GeneralUtility::getFileAbsFileName(GeneralUtility::resolveBackPath(‪Environment::getPublicPath() . '/' . $relativePath));
313  if (empty($absolutePath)) {
314  throw new ‪ExtensionManagerException('Illegal relative path given', 1350742864);
315  }
316  return $absolutePath;
317  }
318 
325  protected function ‪getRelativePath(string $absolutePath): string
326  {
327  return ‪PathUtility::stripPathSitePrefix($absolutePath);
328  }
329 
336  public function ‪getAbsoluteExtensionPath(string $extensionKey): string
337  {
338  $extension = $this->installUtility->enrichExtensionWithDetails($extensionKey);
339  return $this->‪getAbsolutePath($extension['siteRelPath']);
340  }
341 
348  protected function ‪getExtensionVersion(string $extensionKey): string
349  {
350  $extensionData = $this->installUtility->enrichExtensionWithDetails($extensionKey);
351  return (string)$extensionData['version'];
352  }
353 
360  public function ‪createZipFileFromExtension($extensionKey): string
361  {
362  $extensionPath = $this->‪getAbsoluteExtensionPath($extensionKey);
363 
364  // Add trailing slash to the extension path, getAllFilesAndFoldersInPath explicitly requires that.
365  $extensionPath = ‪PathUtility::sanitizeTrailingSeparator($extensionPath);
366 
367  $version = $this->‪getExtensionVersion($extensionKey);
368  if (empty($version)) {
369  $version = '0.0.0';
370  }
371 
372  $temporaryPath = ‪Environment::getVarPath() . '/transient/';
373  if (!@is_dir($temporaryPath)) {
374  ‪GeneralUtility::mkdir($temporaryPath);
375  }
376  $fileName = $temporaryPath . $extensionKey . '_' . $version . '_' . date('YmdHi', ‪$GLOBALS['EXEC_TIME']) . '.zip';
377 
378  $zip = new \ZipArchive();
379  $zip->open($fileName, \ZipArchive::CREATE);
380 
381  $excludePattern = ‪$GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging'];
382 
383  // Get all the files of the extension, but exclude the ones specified in the excludePattern
384  $files = GeneralUtility::getAllFilesAndFoldersInPath(
385  [], // No files pre-added
386  $extensionPath, // Start from here
387  '', // Do not filter files by extension
388  true, // Include subdirectories
389  PHP_INT_MAX, // Recursion level
390  $excludePattern // Files and directories to exclude.
391  );
392 
393  // Make paths relative to extension root directory.
394  $files = GeneralUtility::removePrefixPathFromList($files, $extensionPath);
395  $files = is_array($files) ? $files : [];
396 
397  // Remove the one empty path that is the extension dir itself.
398  $files = array_filter($files);
399 
400  foreach ($files as $file) {
401  $fullPath = $extensionPath . $file;
402  // Distinguish between files and directories, as creation of the archive
403  // fails on Windows when trying to add a directory with "addFile".
404  if (is_dir($fullPath)) {
405  $zip->addEmptyDir($file);
406  } else {
407  $zip->addFile($fullPath, $file);
408  }
409  }
410 
411  $zip->close();
412  return $fileName;
413  }
414 
423  public function ‪unzipExtensionFromFile($file, $fileName, $pathType = 'Local')
424  {
425  $extensionDir = $this->‪makeAndClearExtensionDir($fileName, $pathType);
426 
427  try {
428  $zipService = GeneralUtility::makeInstance(ZipService::class);
429  if ($zipService->verify($file)) {
430  $zipService->extract($file, $extensionDir);
431  }
432  } catch (‪ExtractException $e) {
433  $this->logger->error('Extracting the extension archive failed', ['exception' => $e]);
434  throw new ‪ExtensionManagerException('Extracting the extension archive failed: ' . $e->getMessage(), 1565777179, $e);
435  }
436 
437  ‪GeneralUtility::fixPermissions($extensionDir, true);
438  }
439 
443  protected function ‪reloadPackageInformation($extensionKey)
444  {
445  $this->installUtility->reloadPackageInformation($extensionKey);
446  }
447 }
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\returnAllowedInstallPaths
‪static array returnAllowedInstallPaths()
Definition: Extension.php:458
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\createNestedDirectory
‪createNestedDirectory($directory)
Definition: FileHandlingUtility.php:150
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Extensionmanager\Utility
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:180
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension
Definition: Extension.php:29
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\removeDirectory
‪removeDirectory($extDirPath)
Definition: FileHandlingUtility.php:240
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\unzipExtensionFromFile
‪unzipExtensionFromFile($file, $fileName, $pathType='Local')
Definition: FileHandlingUtility.php:420
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\writeEmConfToFile
‪writeEmConfToFile(array $extensionData, $rootPath, Extension $extension=null)
Definition: FileHandlingUtility.php:265
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\extractFilesArrayFromExtensionData
‪mixed extractFilesArrayFromExtensionData(array $extensionData)
Definition: FileHandlingUtility.php:125
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:372
‪TYPO3\CMS\Core\Exception\Archive\ExtractException
Definition: ExtractException.php:26
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getAbsoluteExtensionPath
‪string getAbsoluteExtensionPath(string $extensionKey)
Definition: FileHandlingUtility.php:333
‪TYPO3\CMS\Core\Core\Environment\isWindows
‪static bool isWindows()
Definition: Environment.php:292
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\$languageService
‪LanguageService $languageService
Definition: FileHandlingUtility.php:48
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\$installUtility
‪InstallUtility $installUtility
Definition: FileHandlingUtility.php:44
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\injectLanguageService
‪injectLanguageService(LanguageService $languageService)
Definition: FileHandlingUtility.php:69
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
Definition: FileHandlingUtility.php:35
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\extractDirectoriesFromExtensionData
‪array extractDirectoriesFromExtensionData(array $files)
Definition: FileHandlingUtility.php:107
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\isValidExtensionPath
‪bool isValidExtensionPath($path)
Definition: FileHandlingUtility.php:289
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility
Definition: InstallUtility.php:55
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\initializeObject
‪initializeObject()
Definition: FileHandlingUtility.php:77
‪TYPO3\CMS\Core\Utility\GeneralUtility\fixPermissions
‪static mixed fixPermissions($path, $recursive=false)
Definition: GeneralUtility.php:1863
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\createZipFileFromExtension
‪string createZipFileFromExtension($extensionKey)
Definition: FileHandlingUtility.php:357
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir_deep
‪static mkdir_deep($directory)
Definition: GeneralUtility.php:2022
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getExtensionVersion
‪string getExtensionVersion(string $extensionKey)
Definition: FileHandlingUtility.php:345
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\injectInstallUtility
‪injectInstallUtility(InstallUtility $installUtility)
Definition: FileHandlingUtility.php:61
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\$emConfUtility
‪EmConfUtility $emConfUtility
Definition: FileHandlingUtility.php:40
‪TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
Definition: ExtensionManagerException.php:24
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\reloadPackageInformation
‪reloadPackageInformation($extensionKey)
Definition: FileHandlingUtility.php:440
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\makeAndClearExtensionDir
‪string makeAndClearExtensionDir($extensionKey, $pathType='Local')
Definition: FileHandlingUtility.php:184
‪TYPO3\CMS\Core\Utility\PathUtility\sanitizeTrailingSeparator
‪static string sanitizeTrailingSeparator($path, $separator='/')
Definition: PathUtility.php:148
‪TYPO3\CMS\Core\Service\Archive\ZipService
Definition: ZipService.php:29
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getExtensionDir
‪string getExtensionDir($extensionKey, $pathType='Local')
Definition: FileHandlingUtility.php:203
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\unpackExtensionFromExtensionDataArray
‪unpackExtensionFromExtensionDataArray(array $extensionData, Extension $extension=null, $pathType='Local')
Definition: FileHandlingUtility.php:89
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getRelativePath
‪string getRelativePath(string $absolutePath)
Definition: FileHandlingUtility.php:322
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\addDirectory
‪addDirectory($extDirPath)
Definition: FileHandlingUtility.php:223
‪TYPO3\CMS\Core\Utility\GeneralUtility\rmdir
‪static bool rmdir($path, $removeNonEmpty=false)
Definition: GeneralUtility.php:2075
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\writeExtensionFiles
‪writeExtensionFiles(array $files, $rootPath)
Definition: FileHandlingUtility.php:168
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\injectEmConfUtility
‪injectEmConfUtility(EmConfUtility $emConfUtility)
Definition: FileHandlingUtility.php:53
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir
‪static bool mkdir($newFolder)
Definition: GeneralUtility.php:2005
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\returnInstallPaths
‪static array returnInstallPaths()
Definition: Extension.php:442
‪TYPO3\CMS\Core\Utility\GeneralUtility\writeFile
‪static bool writeFile($file, $content, $changePermissions=false)
Definition: GeneralUtility.php:1836
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\createDirectoriesForExtensionFiles
‪createDirectoriesForExtensionFiles(array $directories, $rootPath)
Definition: FileHandlingUtility.php:137
‪TYPO3\CMS\Core\Core\Environment\getVarPath
‪static string getVarPath()
Definition: Environment.php:192
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility\getAbsolutePath
‪string getAbsolutePath($relativePath)
Definition: FileHandlingUtility.php:307