[TASK] Merge submodule workspaces into core
[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 */
39 public $objectManager;
40
41 /**
42 * @var \TYPO3\CMS\Install\Sql\SchemaMigrator
43 */
44 public $installToolSqlParser;
45
46 /**
47 * @var \TYPO3\CMS\Extensionmanager\Utility\DependencyUtility
48 */
49 protected $dependencyUtility;
50
51 /**
52 * @var \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
53 */
54 protected $fileHandlingUtility;
55
56 /**
57 * @var \TYPO3\CMS\Extensionmanager\Utility\ListUtility
58 */
59 protected $listUtility;
60
61 /**
62 * @var \TYPO3\CMS\Extensionmanager\Utility\DatabaseUtility
63 */
64 protected $databaseUtility;
65
66 /**
67 * @var \TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository
68 */
69 public $extensionRepository;
70
71 /**
72 * @param \TYPO3\CMS\Extensionmanager\Utility\ListUtility $listUtility
73 * @return void
74 */
75 public function injectListUtility(\TYPO3\CMS\Extensionmanager\Utility\ListUtility $listUtility) {
76 $this->listUtility = $listUtility;
77 }
78
79 /**
80 * @param \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility $filehandlingUtility
81 * @return void
82 */
83 public function injectFileHandlingUtility(\TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility $fileHandlingUtility) {
84 $this->fileHandlingUtility = $fileHandlingUtility;
85 }
86
87 /**
88 * @param \TYPO3\CMS\Extensionmanager\Utility\DependencyUtility $dependencyUtility
89 * @return void
90 */
91 public function injectDependencyUtility(\TYPO3\CMS\Extensionmanager\Utility\DependencyUtility $dependencyUtility) {
92 $this->dependencyUtility = $dependencyUtility;
93 }
94
95 /**
96 * @param \TYPO3\CMS\Extensionmanager\Utility\DatabaseUtility $databaseUtility
97 * @return void
98 */
99 public function injectDatabaseUtility(\TYPO3\CMS\Extensionmanager\Utility\DatabaseUtility $databaseUtility) {
100 $this->databaseUtility = $databaseUtility;
101 }
102
103 /**
104 * Inject emConfUtility
105 *
106 * @param \TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository $extensionRepository
107 * @return void
108 */
109 public function injectExtensionRepository(\TYPO3\CMS\Extensionmanager\Domain\Repository\ExtensionRepository $extensionRepository) {
110 $this->extensionRepository = $extensionRepository;
111 }
112
113 /**
114 * __construct
115 */
116 public function __construct() {
117 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
118 /** @var $installToolSqlParser \TYPO3\CMS\Install\Sql\SchemaMigrator */
119 $this->installToolSqlParser = $this->objectManager->get('TYPO3\\CMS\\Install\\Sql\\SchemaMigrator');
120 $this->dependencyUtility = $this->objectManager->get('TYPO3\\CMS\\Extensionmanager\\Utility\\DependencyUtility');
121 }
122
123 /**
124 * Helper function to install an extension
125 * also processes db updates and clears the cache if the extension asks for it
126 *
127 * @param string $extensionKey
128 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
129 * @return void
130 */
131 public function install($extensionKey) {
132 $extension = $this->enrichExtensionWithDetails($extensionKey);
133 $this->processDatabaseUpdates($extension);
134 $this->ensureConfiguredDirectoriesExist($extension);
135 if ($extension['clearcacheonload']) {
136 $GLOBALS['typo3CacheManager']->flushCaches();
137 }
138 if (!$this->isLoaded($extensionKey)) {
139 $this->loadExtension($extensionKey);
140 }
141 $this->reloadCaches();
142 $this->processCachingFrameworkUpdates();
143 $this->saveDefaultConfiguration($extension['key']);
144 }
145
146 /**
147 * Helper function to uninstall an extension
148 *
149 * @param string $extensionKey
150 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
151 * @return void
152 */
153 public function uninstall($extensionKey) {
154 $dependentExtensions = $this->dependencyUtility->findInstalledExtensionsThatDependOnMe($extensionKey);
155 if (is_array($dependentExtensions) && count($dependentExtensions) > 0) {
156 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Cannot deactivate extension ' . $extensionKey . ' - The extension(s) ' . implode(',', $dependentExtensions) . ' depend on it', 1342554622);
157 } else {
158 $this->unloadExtension($extensionKey);
159 }
160 }
161
162 /**
163 * Wrapper function to check for loaded extensions
164 *
165 * @param string $extensionKey
166 * @return boolean TRUE if extension is loaded
167 */
168 public function isLoaded($extensionKey) {
169 return \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extensionKey);
170 }
171
172 /**
173 * Wrapper function for loading extensions
174 *
175 * @param string $extensionKey
176 * @return void
177 */
178 protected function loadExtension($extensionKey) {
179 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::loadExtension($extensionKey);
180 }
181
182 /**
183 * Wrapper function for unloading extensions
184 *
185 * @param string $extensionKey
186 * @return void
187 */
188 protected function unloadExtension($extensionKey) {
189 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::unloadExtension($extensionKey);
190 }
191
192 /**
193 * Checks if an extension is available in the system
194 *
195 * @param $extensionKey
196 * @return boolean
197 */
198 public function isAvailable($extensionKey) {
199 $availableExtensions = $this->listUtility->getAvailableExtensions();
200 return array_key_exists($extensionKey, $availableExtensions);
201 }
202
203 /**
204 * Fetch additional information for an extension key
205 *
206 * @param string $extensionKey
207 * @access private
208 * @return array
209 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
210 */
211 public function enrichExtensionWithDetails($extensionKey) {
212 $availableExtensions = $this->listUtility->getAvailableExtensions();
213 if (isset($availableExtensions[$extensionKey])) {
214 $extension = $availableExtensions[$extensionKey];
215 } else {
216 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Extension ' . $extensionKey . ' is not available', 1342864081);
217 }
218 $availableAndInstalledExtensions = $this->listUtility->enrichExtensionsWithEmConfAndTerInformation(array($extensionKey => $extension));
219 return $availableAndInstalledExtensions[$extensionKey];
220 }
221
222 /**
223 * Creates directories as requested in ext_emconf.php
224 *
225 * @param array $extension
226 */
227 protected function ensureConfiguredDirectoriesExist(array $extension) {
228 $this->fileHandlingUtility->ensureConfiguredDirectoriesExist($extension);
229 }
230
231 /**
232 * Gets the content of the ext_tables.sql and ext_tables_static+adt.sql files
233 * Additionally adds the table definitions for the cache tables
234 *
235 * @param array $extension
236 */
237 public function processDatabaseUpdates(array $extension) {
238 $extTablesSqlFile = PATH_site . $extension['siteRelPath'] . '/ext_tables.sql';
239 $extTablesSqlContent = '';
240 if (file_exists($extTablesSqlFile)) {
241 $extTablesSqlContent .= \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($extTablesSqlFile);
242 }
243 if ($extTablesSqlContent !== '') {
244 $this->updateDbWithExtTablesSql($extTablesSqlContent);
245 }
246 $extTablesStaticSqlFile = PATH_site . $extension['siteRelPath'] . '/ext_tables_static+adt.sql';
247 if (file_exists($extTablesStaticSqlFile)) {
248 $extTablesStaticSqlContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($extTablesStaticSqlFile);
249 $this->importStaticSql($extTablesStaticSqlContent);
250 }
251 }
252
253 /**
254 * Gets all registered caches and creates required caching framework tables.
255 *
256 * @return void
257 */
258 protected function processCachingFrameworkUpdates() {
259 $extTablesSqlContent = '';
260
261 // @TODO: This should probably moved to TYPO3\CMS\Core\Cache\Cache->getDatabaseTableDefinitions ?!
262 $GLOBALS['typo3CacheManager']->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
263 $extTablesSqlContent .= \TYPO3\CMS\Core\Cache\Cache::getDatabaseTableDefinitions();
264
265 if ($extTablesSqlContent !== '') {
266 $this->updateDbWithExtTablesSql($extTablesSqlContent);
267 }
268 }
269
270 /**
271 * Reload Cache files and Typo3LoadedExtensions
272 *
273 * @return void
274 */
275 public function reloadCaches() {
276 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::removeCacheFiles();
277 // Set new extlist / extlistArray for extension load changes at runtime
278 /** @var $configurationManager \TYPO3\CMS\Core\Configuration\ConfigurationManager */
279 $configurationManager = $this->objectManager->get('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager');
280 $localConfiguration = $configurationManager->getLocalConfiguration();
281 $GLOBALS['TYPO3_CONF_VARS']['EXT']['extListArray'] = $localConfiguration['EXT']['extListArray'];
282 $GLOBALS['TYPO3_CONF_VARS']['EXT']['extList'] = implode(',', $GLOBALS['TYPO3_CONF_VARS']['EXT']['extListArray']);
283 \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->reloadTypo3LoadedExtAndClassLoaderAndExtLocalconf();
284 }
285
286 /**
287 * Save default configuration of an extension
288 *
289 * @param string $extensionKey
290 * @return void
291 */
292 protected function saveDefaultConfiguration($extensionKey) {
293 /** @var $configUtility \TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility */
294 $configUtility = $this->objectManager->get('TYPO3\\CMS\\Extensionmanager\\Utility\\ConfigurationUtility');
295 $configUtility->saveDefaultConfiguration($extensionKey);
296 }
297
298 /**
299 * Update database / process db updates from ext_tables
300 *
301 * @param string $rawDefinitions The raw SQL statements from ext_tables.sql
302 * @return void
303 */
304 public function updateDbWithExtTablesSql($rawDefinitions) {
305 $fieldDefinitionsFromFile = $this->installToolSqlParser->getFieldDefinitions_fileContent($rawDefinitions);
306 if (count($fieldDefinitionsFromFile)) {
307 $fieldDefinitionsFromCurrentDatabase = $this->installToolSqlParser->getFieldDefinitions_database();
308 $diff = $this->installToolSqlParser->getDatabaseExtra($fieldDefinitionsFromFile, $fieldDefinitionsFromCurrentDatabase);
309 $updateStatements = $this->installToolSqlParser->getUpdateSuggestions($diff);
310 foreach ((array) $updateStatements['add'] as $string) {
311 $GLOBALS['TYPO3_DB']->admin_query($string);
312 }
313 foreach ((array) $updateStatements['change'] as $string) {
314 $GLOBALS['TYPO3_DB']->admin_query($string);
315 }
316 foreach ((array) $updateStatements['create_table'] as $string) {
317 $GLOBALS['TYPO3_DB']->admin_query($string);
318 }
319 }
320 }
321
322 /**
323 * Import static SQL data (normally used for ext_tables_static+adt.sql)
324 *
325 * @param string $rawDefinitions
326 * @return void
327 */
328 public function importStaticSql($rawDefinitions) {
329 $statements = $this->installToolSqlParser->getStatementarray($rawDefinitions, 1);
330 list($statementsPerTable, $insertCount) = $this->installToolSqlParser->getCreateTables($statements, 1);
331 // Traverse the tables
332 foreach ($statementsPerTable as $table => $query) {
333 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS ' . $table);
334 $GLOBALS['TYPO3_DB']->admin_query($query);
335 if ($insertCount[$table]) {
336 $insertStatements = $this->installToolSqlParser->getTableInsertStatements($statements, $table);
337 foreach ($insertStatements as $statement) {
338 $GLOBALS['TYPO3_DB']->admin_query($statement);
339 }
340 }
341 }
342 }
343
344 /**
345 * Remove an extension (delete the directory)
346 *
347 * @param string $extension
348 * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
349 * @return void
350 */
351 public function removeExtension($extension) {
352 $absolutePath = $this->fileHandlingUtility->getAbsoluteExtensionPath($extension);
353 if ($this->fileHandlingUtility->isValidExtensionPath($absolutePath)) {
354 $this->fileHandlingUtility->removeDirectory($absolutePath);
355 } else {
356 throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('No valid extension path given.', 1342875724);
357 }
358 }
359
360 /**
361 * Get the data dump for an extension
362 *
363 * @param string $extension
364 * @return array
365 */
366 public function getExtensionSqlDataDump($extension) {
367 $extension = $this->enrichExtensionWithDetails($extension);
368 $filePrefix = PATH_site . $extension['siteRelPath'];
369 $sqlData['extTables'] = $this->getSqlDataDumpForFile($filePrefix . '/ext_tables.sql');
370 $sqlData['staticSql'] = $this->getSqlDataDumpForFile($filePrefix . '/ext_tables_static+adt.sql');
371 return $sqlData;
372 }
373
374 /**
375 * Gets the sql data dump for a specific sql file (for example ext_tables.sql)
376 *
377 * @param string $sqlFile
378 * @return string
379 */
380 protected function getSqlDataDumpForFile($sqlFile) {
381 $sqlData = '';
382 if (file_exists($sqlFile)) {
383 $sqlContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($sqlFile);
384 $fieldDefinitions = $this->installToolSqlParser->getFieldDefinitions_fileContent($sqlContent);
385 $sqlData = $this->databaseUtility->dumpStaticTables($fieldDefinitions);
386 }
387 return $sqlData;
388 }
389
390 /**
391 * Checks if an update for an extension is available
392 *
393 * @internal
394 * @param \TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData
395 * @return boolean
396 */
397 public function isUpdateAvailable(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension $extensionData) {
398 // Only check for update for TER extensions
399 $version = $extensionData->getIntegerVersion();
400 /** @var $highestTerVersionExtension \TYPO3\CMS\Extensionmanager\Domain\Model\Extension */
401 $highestTerVersionExtension = $this->extensionRepository->findHighestAvailableVersion($extensionData->getExtensionKey());
402 if ($highestTerVersionExtension instanceof \TYPO3\CMS\Extensionmanager\Domain\Model\Extension) {
403 $highestVersion = $highestTerVersionExtension->getIntegerVersion();
404 if ($highestVersion > $version) {
405 return TRUE;
406 }
407 }
408 return FALSE;
409 }
410
411 }
412
413
414 ?>