[BUGFIX] Remove references to extListArray
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Utility / InstallUtility.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Utility;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2012-2013 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 * Extension Manager Install Utility
31 *
32 * @author Susanne Moog <susanne.moog@typo3.org>
33 */
34 class InstallUtility implements \TYPO3\CMS\Core\SingletonInterface {
35
36 /**
37 * @var \TYPO3\CMS\Extbase\Object\ObjectManager
38 * @inject
39 */
40 public $objectManager;
41
42 /**
43 * @var \TYPO3\CMS\Install\Service\SqlSchemaMigrationService
44 * @inject
45 */
46 public $installToolSqlParser;
47
48 /**
49 * @var \TYPO3\CMS\Extensionmanager\Utility\DependencyUtility
50 * @inject
51 */
52 protected $dependencyUtility;
53
54 /**
55 * @var \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
56 * @inject
57 */
58 protected $fileHandlingUtility;
59
60 /**
61 * @var \TYPO3\CMS\Extensionmanager\Utility\ListUtility
62 * @inject
63 */
64 protected $listUtility;
65
66 /**
67 * @var \TYPO3\CMS\Extensionmanager\Utility\DatabaseUtility
68 * @inject
69 */
70 protected $databaseUtility;
71
72 /**
73 * @var \TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository
74 * @inject
75 */
76 public $extensionRepository;
77
78 /**
79 * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
80 * @inject
81 */
82 protected $signalSlotDispatcher;
83
84 /**
85 * @var \TYPO3\CMS\Core\Registry
86 * @inject
87 */
88 protected $registry;
89
90 /**
91 * __construct
92 */
93 public function __construct() {
94 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
95 /** @var $installToolSqlParser \TYPO3\CMS\Install\Service\SqlSchemaMigrationService */
96 $this->installToolSqlParser = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\SqlSchemaMigrationService');
97 $this->dependencyUtility = $this->objectManager->get('TYPO3\\CMS\\Extensionmanager\\Utility\\DependencyUtility');
98 }
99
100 /**
101 * Helper function to install an extension
102 * also processes db updates and clears the cache if the extension asks for it
103 *
104 * @param string $extensionKey
105 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
106 * @return void
107 */
108 public function install($extensionKey) {
109 $extension = $this->enrichExtensionWithDetails($extensionKey);
110 $this->processDatabaseUpdates($extension);
111 $this->ensureConfiguredDirectoriesExist($extension);
112 $this->importInitialFiles($extension['siteRelPath'], $extensionKey);
113 if ($extension['clearcacheonload']) {
114 $GLOBALS['typo3CacheManager']->flushCaches();
115 }
116 if (!$this->isLoaded($extensionKey)) {
117 $this->loadExtension($extensionKey);
118 }
119 $this->reloadCaches();
120 $this->processCachingFrameworkUpdates();
121 $this->saveDefaultConfiguration($extension['key']);
122 }
123
124 /**
125 * Helper function to uninstall an extension
126 *
127 * @param string $extensionKey
128 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
129 * @return void
130 */
131 public function uninstall($extensionKey) {
132 $dependentExtensions = $this->dependencyUtility->findInstalledExtensionsThatDependOnMe($extensionKey);
133 if (is_array($dependentExtensions) && count($dependentExtensions) > 0) {
134 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(
135 \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
136 'extensionList.uninstall.dependencyError',
137 'extensionmanager',
138 array($extensionKey, implode(',', $dependentExtensions))
139 ),
140 1342554622
141 );
142 } else {
143 $this->unloadExtension($extensionKey);
144 }
145 }
146
147 /**
148 * Wrapper function to check for loaded extensions
149 *
150 * @param string $extensionKey
151 * @return boolean TRUE if extension is loaded
152 */
153 public function isLoaded($extensionKey) {
154 return \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extensionKey);
155 }
156
157 /**
158 * Wrapper function for loading extensions
159 *
160 * @param string $extensionKey
161 * @return void
162 */
163 protected function loadExtension($extensionKey) {
164 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::loadExtension($extensionKey);
165 }
166
167 /**
168 * Wrapper function for unloading extensions
169 *
170 * @param string $extensionKey
171 * @return void
172 */
173 protected function unloadExtension($extensionKey) {
174 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::unloadExtension($extensionKey);
175 $this->reloadCaches();
176 }
177
178 /**
179 * Checks if an extension is available in the system
180 *
181 * @param $extensionKey
182 * @return boolean
183 */
184 public function isAvailable($extensionKey) {
185 $availableExtensions = $this->listUtility->getAvailableExtensions();
186 return array_key_exists($extensionKey, $availableExtensions);
187 }
188
189 /**
190 * Fetch additional information for an extension key
191 *
192 * @param string $extensionKey
193 * @access private
194 * @return array
195 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
196 */
197 public function enrichExtensionWithDetails($extensionKey) {
198 $availableExtensions = $this->listUtility->getAvailableExtensions();
199 if (isset($availableExtensions[$extensionKey])) {
200 $extension = $availableExtensions[$extensionKey];
201 } else {
202 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Extension ' . $extensionKey . ' is not available', 1342864081);
203 }
204 $availableAndInstalledExtensions = $this->listUtility->enrichExtensionsWithEmConfAndTerInformation(array($extensionKey => $extension));
205 return $availableAndInstalledExtensions[$extensionKey];
206 }
207
208 /**
209 * Creates directories as requested in ext_emconf.php
210 *
211 * @param array $extension
212 */
213 protected function ensureConfiguredDirectoriesExist(array $extension) {
214 $this->fileHandlingUtility->ensureConfiguredDirectoriesExist($extension);
215 }
216
217 /**
218 * Gets the content of the ext_tables.sql and ext_tables_static+adt.sql files
219 * Additionally adds the table definitions for the cache tables
220 *
221 * @param array $extension
222 */
223 public function processDatabaseUpdates(array $extension) {
224 $extTablesSqlFile = PATH_site . $extension['siteRelPath'] . '/ext_tables.sql';
225 $extTablesSqlContent = '';
226 if (file_exists($extTablesSqlFile)) {
227 $extTablesSqlContent .= \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($extTablesSqlFile);
228 }
229 if ($extTablesSqlContent !== '') {
230 $this->updateDbWithExtTablesSql($extTablesSqlContent);
231 }
232
233 $this->importStaticSqlFile($extension['siteRelPath']);
234 $this->importT3DFile($extension['siteRelPath']);
235 }
236
237 /**
238 * Gets all registered caches and creates required caching framework tables.
239 *
240 * @return void
241 */
242 protected function processCachingFrameworkUpdates() {
243 $extTablesSqlContent = '';
244
245 // @TODO: This should probably moved to TYPO3\CMS\Core\Cache\Cache->getDatabaseTableDefinitions ?!
246 $GLOBALS['typo3CacheManager']->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
247 $extTablesSqlContent .= \TYPO3\CMS\Core\Cache\Cache::getDatabaseTableDefinitions();
248
249 if ($extTablesSqlContent !== '') {
250 $this->updateDbWithExtTablesSql($extTablesSqlContent);
251 }
252 }
253
254 /**
255 * Reload Cache files and Typo3LoadedExtensions
256 *
257 * @return void
258 */
259 public function reloadCaches() {
260 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::removeCacheFiles();
261 \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->reloadTypo3LoadedExtAndClassLoaderAndExtLocalconf();
262 }
263
264 /**
265 * Save default configuration of an extension
266 *
267 * @param string $extensionKey
268 * @return void
269 */
270 protected function saveDefaultConfiguration($extensionKey) {
271 /** @var $configUtility \TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility */
272 $configUtility = $this->objectManager->get('TYPO3\\CMS\\Extensionmanager\\Utility\\ConfigurationUtility');
273 $configUtility->saveDefaultConfiguration($extensionKey);
274 }
275
276 /**
277 * Update database / process db updates from ext_tables
278 *
279 * @param string $rawDefinitions The raw SQL statements from ext_tables.sql
280 * @return void
281 */
282 public function updateDbWithExtTablesSql($rawDefinitions) {
283 $fieldDefinitionsFromFile = $this->installToolSqlParser->getFieldDefinitions_fileContent($rawDefinitions);
284 if (count($fieldDefinitionsFromFile)) {
285 $fieldDefinitionsFromCurrentDatabase = $this->installToolSqlParser->getFieldDefinitions_database();
286 $diff = $this->installToolSqlParser->getDatabaseExtra($fieldDefinitionsFromFile, $fieldDefinitionsFromCurrentDatabase);
287 $updateStatements = $this->installToolSqlParser->getUpdateSuggestions($diff);
288 foreach ((array) $updateStatements['add'] as $string) {
289 $GLOBALS['TYPO3_DB']->admin_query($string);
290 }
291 foreach ((array) $updateStatements['change'] as $string) {
292 $GLOBALS['TYPO3_DB']->admin_query($string);
293 }
294 foreach ((array) $updateStatements['create_table'] as $string) {
295 $GLOBALS['TYPO3_DB']->admin_query($string);
296 }
297 }
298 }
299
300 /**
301 * Import static SQL data (normally used for ext_tables_static+adt.sql)
302 *
303 * @param string $rawDefinitions
304 * @return void
305 */
306 public function importStaticSql($rawDefinitions) {
307 $statements = $this->installToolSqlParser->getStatementarray($rawDefinitions, 1);
308 list($statementsPerTable, $insertCount) = $this->installToolSqlParser->getCreateTables($statements, 1);
309 // Traverse the tables
310 foreach ($statementsPerTable as $table => $query) {
311 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS ' . $table);
312 $GLOBALS['TYPO3_DB']->admin_query($query);
313 if ($insertCount[$table]) {
314 $insertStatements = $this->installToolSqlParser->getTableInsertStatements($statements, $table);
315 foreach ($insertStatements as $statement) {
316 $GLOBALS['TYPO3_DB']->admin_query($statement);
317 }
318 }
319 }
320 }
321
322 /**
323 * Remove an extension (delete the directory)
324 *
325 * @param string $extension
326 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
327 * @return void
328 */
329 public function removeExtension($extension) {
330 $absolutePath = $this->fileHandlingUtility->getAbsoluteExtensionPath($extension);
331 if ($this->fileHandlingUtility->isValidExtensionPath($absolutePath)) {
332 $this->fileHandlingUtility->removeDirectory($absolutePath);
333 } else {
334 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('No valid extension path given.', 1342875724);
335 }
336 }
337
338 /**
339 * Get the data dump for an extension
340 *
341 * @param string $extension
342 * @return array
343 */
344 public function getExtensionSqlDataDump($extension) {
345 $extension = $this->enrichExtensionWithDetails($extension);
346 $filePrefix = PATH_site . $extension['siteRelPath'];
347 $sqlData['extTables'] = $this->getSqlDataDumpForFile($filePrefix . '/ext_tables.sql');
348 $sqlData['staticSql'] = $this->getSqlDataDumpForFile($filePrefix . '/ext_tables_static+adt.sql');
349 return $sqlData;
350 }
351
352 /**
353 * Gets the sql data dump for a specific sql file (for example ext_tables.sql)
354 *
355 * @param string $sqlFile
356 * @return string
357 */
358 protected function getSqlDataDumpForFile($sqlFile) {
359 $sqlData = '';
360 if (file_exists($sqlFile)) {
361 $sqlContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($sqlFile);
362 $fieldDefinitions = $this->installToolSqlParser->getFieldDefinitions_fileContent($sqlContent);
363 $sqlData = $this->databaseUtility->dumpStaticTables($fieldDefinitions);
364 }
365 return $sqlData;
366 }
367
368 /**
369 * Checks if an update for an extension is available
370 *
371 * @internal
372 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData
373 * @return boolean
374 */
375 public function isUpdateAvailable(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData) {
376 // Only check for update for TER extensions
377 $version = $extensionData->getIntegerVersion();
378 /** @var $highestTerVersionExtension \TYPO3\CMS\Extensionmanager\Domain\Model\Extension */
379 $highestTerVersionExtension = $this->extensionRepository->findHighestAvailableVersion($extensionData->getExtensionKey());
380 if ($highestTerVersionExtension instanceof \TYPO3\CMS\Extensionmanager\Domain\Model\Extension) {
381 $highestVersion = $highestTerVersionExtension->getIntegerVersion();
382 if ($highestVersion > $version) {
383 return TRUE;
384 }
385 }
386 return FALSE;
387 }
388
389 /**
390 * Uses the export import extension to import a T3DFile to PID 0
391 * Execution state is saved in the this->registry, so it only happens once
392 *
393 * @param string $extensionSiteRelPath
394 * @return void
395 */
396 protected function importT3DFile($extensionSiteRelPath) {
397 $t3dImportRelFile = $extensionSiteRelPath . '/Initialisation/data.t3d';
398 if (!$this->registry->get('extensionDataImport', $t3dImportRelFile)) {
399 $t3dImportFile = PATH_site . $t3dImportRelFile;
400 if (file_exists($t3dImportFile)) {
401 $importExportUtility = $this->objectManager->get('TYPO3\\CMS\\Impexp\\Utility\\ImportExportUtility');
402 try {
403 $importResult = $importExportUtility->importT3DFile($t3dImportFile, 0);
404 $this->registry->set('extensionDataImport', $t3dImportRelFile, 1);
405 $this->signalSlotDispatcher->dispatch(__CLASS__, 'afterExtensionT3DImport', array($t3dImportRelFile, $importResult, $this));
406 } catch (\ErrorException $e) {
407 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
408 $logger = $this->objectManager->get('TYPO3\\CMS\\Core\\Log\\LogManager')->getLogger(__CLASS__);
409 $logger->log(\TYPO3\CMS\Core\Log\LogLevel::WARNING, $e->getMessage());
410 }
411 }
412 }
413 }
414
415 /**
416 * Imports a static tables SQL File (ext_tables_static+adt)
417 * Execution state is saved in the this->registry, so it only happens once
418 *
419 * @param string $extensionSiteRelPath
420 * @return void
421 */
422 protected function importStaticSqlFile($extensionSiteRelPath) {
423 $extTablesStaticSqlRelFile = $extensionSiteRelPath . '/ext_tables_static+adt.sql';
424 if (!$this->registry->get('extensionDataImport', $extTablesStaticSqlRelFile)) {
425 $extTablesStaticSqlFile = PATH_site . $extTablesStaticSqlRelFile;
426 if (file_exists($extTablesStaticSqlFile)) {
427 $extTablesStaticSqlContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($extTablesStaticSqlFile);
428 $this->importStaticSql($extTablesStaticSqlContent);
429 }
430 $this->registry->set('extensionDataImport', $extTablesStaticSqlRelFile, 1);
431 $this->signalSlotDispatcher->dispatch(__CLASS__, 'afterExtensionStaticSqlImport', array($extTablesStaticSqlRelFile, $this));
432 }
433 }
434
435 /**
436 * Imports files from Initialisation/Files to fileadmin
437 * via lowlevel copy directory method
438 *
439 * @param string $extensionSiteRelPath relative path to extension dir
440 * @param string $extensionKey
441 */
442 protected function importInitialFiles($extensionSiteRelPath, $extensionKey) {
443 $importRelFolder = $extensionSiteRelPath . '/Initialisation/Files';
444 if (!$this->registry->get('extensionDataImport', $importRelFolder)) {
445 $importFolder = PATH_site . $importRelFolder;
446 if (file_exists($importFolder)) {
447 $destinationRelPath = $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . $extensionKey;
448 $destinationAbsolutePath = PATH_site . $destinationRelPath;
449 if (!file_exists($destinationAbsolutePath) &&
450 \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($destinationAbsolutePath)
451 ) {
452 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($destinationAbsolutePath);
453 }
454 \TYPO3\CMS\Core\Utility\GeneralUtility::copyDirectory($importRelFolder, $destinationRelPath);
455 $this->registry->set('extensionDataImport', $importRelFolder, 1);
456 $this->signalSlotDispatcher->dispatch(__CLASS__, 'afterExtensionFileImport', array($destinationAbsolutePath, $this));
457 }
458 }
459 }
460 }