d36fa67a5897de39977ff75b2a040b9cb92f39ed
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Utility / FileHandlingUtility.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Utility;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2012 Susanne Moog <susanne.moog@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Utility for dealing with files and folders
31 *
32 * @author Susanne Moog <susanne.moog@typo3.org>
33 * @package Extension Manager
34 * @subpackage Utility
35 */
36 class FileHandlingUtility implements \TYPO3\CMS\Core\SingletonInterface {
37
38 /**
39 * @var \TYPO3\CMS\Extensionmanager\Utility\EmConfUtility
40 */
41 protected $emConfUtility;
42
43 /**
44 * Injector for Tx_Extensionmanager_Utility_EmConf
45 *
46 * @param \TYPO3\CMS\Extensionmanager\Utility\EmConfUtility $emConfUtility
47 * @return void
48 */
49 public function injectEmConfUtility(\TYPO3\CMS\Extensionmanager\Utility\EmConfUtility $emConfUtility) {
50 $this->emConfUtility = $emConfUtility;
51 }
52
53 /**
54 * @var \TYPO3\CMS\Extensionmanager\Utility\InstallUtility
55 */
56 protected $installUtility;
57
58 /**
59 * Injector for Tx_Extensionmanager_Utility_Install
60 *
61 * @param \TYPO3\CMS\Extensionmanager\Utility\InstallUtility $installUtility
62 * @return void
63 */
64 public function injectInstallUtility(\TYPO3\CMS\Extensionmanager\Utility\InstallUtility $installUtility) {
65 $this->installUtility = $installUtility;
66 }
67
68 /**
69 * Unpack an extension in t3x data format and write files
70 *
71 * @param array $extensionData
72 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
73 * @param string $pathType
74 * @return void
75 */
76 public function unpackExtensionFromExtensionDataArray(array $extensionData, \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension = NULL, $pathType = 'Local') {
77 $extensionDir = $this->makeAndClearExtensionDir($extensionData['extKey'], $pathType);
78 $files = $this->extractFilesArrayFromExtensionData($extensionData);
79 $directories = $this->extractDirectoriesFromExtensionData($files);
80 $this->createDirectoriesForExtensionFiles($directories, $extensionDir);
81 $this->writeExtensionFiles($files, $extensionDir);
82 $this->writeEmConfToFile($extensionData, $extensionDir, $extension);
83 }
84
85 /**
86 * Extract needed directories from given extensionDataFilesArray
87 *
88 * @param array $files
89 * @return array
90 */
91 protected function extractDirectoriesFromExtensionData(array $files) {
92 $directories = array();
93 foreach ($files as $filePath => $file) {
94 preg_match('/(.*)\\//', $filePath, $matches);
95 $directories[] = $matches[0];
96 }
97 return $directories;
98 }
99
100 /**
101 * Returns the "FILES" part from the data array
102 *
103 * @param array $extensionData
104 * @return mixed
105 */
106 protected function extractFilesArrayFromExtensionData(array $extensionData) {
107 return $extensionData['FILES'];
108 }
109
110 /**
111 * Loops over an array of directories and creates them in the given root path
112 * It also creates nested directory structures
113 *
114 * @param array $directories
115 * @param string $rootPath
116 * @return void
117 */
118 protected function createDirectoriesForExtensionFiles(array $directories, $rootPath) {
119 foreach ($directories as $directory) {
120 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir_deep($rootPath . $directory);
121 }
122 }
123
124 /**
125 * Loops over an array of files and writes them to the given rootPath
126 *
127 * @param array $files
128 * @param string $rootPath
129 * @return void
130 */
131 protected function writeExtensionFiles(array $files, $rootPath) {
132 foreach ($files as $file) {
133 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($rootPath . $file['name'], $file['content']);
134 }
135 }
136
137 /**
138 * Removes the current extension of $type and creates the base folder for
139 * the new one (which is going to be imported)
140 *
141 * @param string $extensionkey
142 * @param string $pathType Extension installation scope (Local,Global,System)
143 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
144 * @return string
145 */
146 protected function makeAndClearExtensionDir($extensionkey, $pathType = 'Local') {
147 $paths = \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnInstallPaths();
148 $path = $paths[$pathType];
149 if (!$path || !is_dir($path) || !$extensionkey) {
150 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('ERROR: The extension install path "%s" was no directory!', $path), 1337280417);
151 } else {
152 $extDirPath = $path . $extensionkey . '/';
153 if (is_dir($extDirPath)) {
154 $this->removeDirectory($extDirPath);
155 }
156 $this->addDirectory($extDirPath);
157 }
158 return $extDirPath;
159 }
160
161 /**
162 * Add specified directory
163 *
164 * @param string $extDirPath
165 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
166 * @return void
167 */
168 protected function addDirectory($extDirPath) {
169 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($extDirPath);
170 if (!is_dir($extDirPath)) {
171 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_could_not_create_dir'), $extDirPath), 1337280416);
172 }
173 }
174
175 /**
176 * Remove specified directory
177 *
178 * @param string $extDirPath
179 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
180 * @return void
181 */
182 public function removeDirectory($extDirPath) {
183 $res = \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($extDirPath, TRUE);
184 if ($res === FALSE) {
185 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_could_not_remove_dir'), $extDirPath), 1337280415);
186 }
187 }
188
189 /**
190 * Constructs emConf and writes it to corresponding file
191 *
192 * @param array $extensionData
193 * @param string $rootPath
194 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension
195 * @return void
196 */
197 protected function writeEmConfToFile(array $extensionData, $rootPath, \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extension = NULL) {
198 $emConfContent = $this->emConfUtility->constructEmConf($extensionData, $extension);
199 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($rootPath . 'ext_emconf.php', $emConfContent);
200 }
201
202 /**
203 * Is the given path a valid path for extension installation
204 *
205 * @param string $path the absolute (!) path in question
206 * @return boolean
207 */
208 public function isValidExtensionPath($path) {
209 $allowedPaths = \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallPaths();
210 foreach ($allowedPaths as $allowedPath) {
211 if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($path, $allowedPath)) {
212 return TRUE;
213 }
214 }
215 return FALSE;
216 }
217
218 /**
219 * Returns absolute path
220 *
221 * @param string $relativePath
222 * @return string
223 */
224 public function returnAbsolutePath($relativePath) {
225 return \TYPO3\CMS\Core\Utility\GeneralUtility::resolveBackPath(PATH_site . $relativePath);
226 }
227
228 /**
229 * Get extension path for an available or installed extension
230 *
231 * @param string $extension
232 * @return string
233 */
234 public function getAbsoluteExtensionPath($extension) {
235 $extension = $this->installUtility->enrichExtensionWithDetails($extension);
236 $absolutePath = $this->returnAbsolutePath($extension['siteRelPath']);
237 return $absolutePath;
238 }
239
240 /**
241 * Create a zip file from an extension
242 *
243 * @param array $extension
244 * @return string
245 */
246 public function createZipFileFromExtension($extension) {
247 $extensionPath = $this->getAbsoluteExtensionPath($extension);
248 $fileName = PATH_site . 'typo3temp/' . $extension . '.zip';
249 $zip = new \ZipArchive();
250 $zip->open($fileName, \ZipArchive::CREATE);
251 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($extensionPath));
252 foreach ($iterator as $key => $value) {
253 $archiveName = str_replace($extensionPath, '', $key);
254 if (\TYPO3\CMS\Core\Utility\StringUtility::isLastPartOfString($key, '.')) {
255 continue;
256 } else {
257 $zip->addFile($key, $archiveName);
258 }
259 }
260 $zip->close();
261 return $fileName;
262 }
263
264 /**
265 * Unzip an extension.zip.
266 *
267 * @param string $file path to zip file
268 * @param string $fileName file name
269 * @param string $pathType path type (Local, Global, System)
270 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
271 * @return void
272 */
273 public function unzipExtensionFromFile($file, $fileName, $pathType = 'Local') {
274 $extensionDir = $this->makeAndClearExtensionDir($fileName, $pathType);
275 $zip = zip_open($file);
276 if (is_resource($zip)) {
277 while (($zipEntry = zip_read($zip)) !== FALSE) {
278 if (strpos(zip_entry_name($zipEntry), DIRECTORY_SEPARATOR) !== FALSE) {
279 $last = strrpos(zip_entry_name($zipEntry), DIRECTORY_SEPARATOR);
280 $dir = substr(zip_entry_name($zipEntry), 0, $last);
281 $file = substr(zip_entry_name($zipEntry), strrpos(zip_entry_name($zipEntry), DIRECTORY_SEPARATOR) + 1);
282 if (!is_dir($dir)) {
283 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir_deep($extensionDir . $dir);
284 }
285 if (strlen(trim($file)) > 0) {
286 $return = \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($extensionDir . $dir . '/' . $file, zip_entry_read($zipEntry, zip_entry_filesize($zipEntry)));
287 if ($return === FALSE) {
288 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Could not write file ' . $file, 1344691048);
289 }
290 }
291 } else {
292 \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($extensionDir . zip_entry_name($zipEntry), zip_entry_read($zipEntry, zip_entry_filesize($zipEntry)));
293 }
294 }
295 } else {
296 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Unable to open zip file ' . $file, 1344691049);
297 }
298 }
299
300 /**
301 * Sends a zip file to the browser and deletes it afterwards
302 *
303 * @param string $fileName
304 * @param string $downloadName
305 * @return void
306 */
307 public function sendZipFileToBrowserAndDelete($fileName, $downloadName = '') {
308 if ($downloadName === '') {
309 $downloadName = basename($fileName, '.zip');
310 }
311 header('Content-Type: application/zip');
312 header('Content-Length: ' . filesize($fileName));
313 header('Content-Disposition: attachment; filename="' . $downloadName . '.zip"');
314 readfile($fileName);
315 unlink($fileName);
316 die;
317 }
318
319 /**
320 * Sends the sql dump file to the browser and deletes it afterwards
321 *
322 * @param string $fileName
323 * @param string $downloadName
324 * @return void
325 */
326 public function sendSqlDumpFileToBrowserAndDelete($fileName, $downloadName = '') {
327 if ($downloadName === '') {
328 $downloadName = basename($fileName, '.sql');
329 } else {
330 $downloadName = basename($downloadName, '.sql');
331 }
332 header('Content-Type: text');
333 header('Content-Length: ' . filesize($fileName));
334 header('Content-Disposition: attachment; filename="' . $downloadName . '.sql"');
335 readfile($fileName);
336 unlink($fileName);
337 die;
338 }
339
340 }
341
342
343 ?>