120bdc040c117c58bd667a73cb2ddde40a09c723
[Packages/TYPO3.CMS.git] / typo3 / sysext / em / classes / install / class.tx_em_install.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 Steffen Kamper (info@sk-typo3.de)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Module: Extension manager, (un-)install extensions
29 *
30 * $Id: class.tx_em_install.php 2073 2010-03-19 10:42:38Z steffenk $
31 *
32 * @author Steffen Kamper <info@sk-typo3.de>
33 */
34
35
36 class tx_em_Install {
37
38 /**
39 * Parent module object
40 *
41 * @var SC_mod_tools_em_index
42 */
43 protected $parentObject;
44
45 /**
46 * Instance of EM API
47 *
48 * @var tx_em_API
49 */
50 protected $api;
51
52 /**
53 *
54 * @var t3lib_install
55 */
56 public $install;
57
58
59 /**
60 * @var integer
61 */
62 protected $systemInstall = 0; // If "1" then installs in the sysext directory is allowed. Default: 0
63
64 /**
65 * @var boolean
66 */
67 protected $silentMode;
68
69 /**
70 * Constructor
71 *
72 * @param SC_mod_tools_em_index $parentObject
73 */
74 public function __construct($parentObject = NULL) {
75 $GLOBALS['LANG']->includeLLFile(t3lib_extMgm::extPath('em', 'language/locallang.xml'));
76 $this->parentObject = $parentObject;
77 $this->api = t3lib_div::makeInstance('tx_em_API');
78 $this->install = t3lib_div::makeInstance('t3lib_install');
79 $this->install->INSTALL = t3lib_div::_GP('TYPO3_INSTALL');
80 $this->systemInstall = isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowSystemInstall']) && $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowSystemInstall'];
81 }
82
83 /**
84 * Set silent mode to prevent flashmessages
85 *
86 * @param boolean $silentMode
87 * @return void
88 */
89 public function setSilentMode($silentMode) {
90 $this->silentMode = $silentMode ? TRUE : FALSE;
91 }
92
93 /**
94 * Imports the data of an extension from upload
95 *
96 * @param $uploadedTempFile
97 * @param $location
98 * @param bool $uploadOverwrite
99 * @return array
100 */
101 public function uploadExtensionFile($uploadedTempFile, $location, $uploadOverwrite = FALSE) {
102 $error = '';
103 $fileContent = t3lib_div::getUrl($uploadedTempFile);
104 if (!$fileContent) {
105 return array(
106 'success' => FALSE,
107 'error' => $GLOBALS['LANG']->getLL('ext_import_file_empty')
108 );
109 }
110
111 // Decode file data:
112 $terConnection = t3lib_div::makeInstance('tx_em_Connection_Ter', $this);
113 $fetchData = $terConnection->decodeExchangeData($fileContent);
114 if (is_array($fetchData)) {
115 $extKey = $fetchData[0]['extKey'];
116 if ($extKey) {
117 if (!$uploadOverwrite) {
118 $comingExtPath = tx_em_Tools::typePath($location) . $extKey . '/';
119 if (@is_dir($comingExtPath)) {
120 $error = sprintf($GLOBALS['LANG']->getLL('ext_import_ext_present_no_overwrite'), $comingExtPath) .
121 '<br />' . $GLOBALS['LANG']->getLL('ext_import_ext_present_nothing_done');
122
123 } // ... else go on, install...
124 } // ... else go on, install...
125 } else {
126 $error = $GLOBALS['LANG']->getLL('ext_import_no_key');
127 }
128 } else {
129 $error = sprintf($GLOBALS['LANG']->getLL('ext_import_wrong_file_format'), $fetchData);
130 }
131
132 if ($error) {
133 return array(FALSE, $error);
134 } else {
135 return array(TRUE, $fetchData);
136 }
137
138 }
139
140 /**
141 * Installs an extension.
142 *
143 * @param $fetchData
144 * @param $loc
145 * @param $version
146 * @param $uploadedTempFile
147 * @param $dontDelete
148 * @return mixed|string
149 */
150 public function installExtension($fetchData, $loc, $version, $uploadedTempFile, $dontDelete) {
151 $xmlHandler =& $this->parentObject->xmlHandler;
152 $extensionList =& $this->parentObject->extensionList;
153 $extensionDetails =& $this->parentObject->extensionDetails;
154 $content = '';
155
156 if (tx_em_Tools::importAsType($loc)) {
157 if (is_array($fetchData)) { // There was some data successfully transferred
158 if ($fetchData[0]['extKey'] && is_array($fetchData[0]['FILES'])) {
159 $extKey = $fetchData[0]['extKey'];
160 if (!isset($fetchData[0]['EM_CONF']['constraints'])) {
161 $fetchData[0]['EM_CONF']['constraints'] = $xmlHandler->extensionsXML[$extKey]['versions'][$version]['dependencies'];
162 }
163 $EM_CONF = tx_em_Tools::fixEMCONF($fetchData[0]['EM_CONF']);
164 if (!$EM_CONF['lockType'] || !strcmp($EM_CONF['lockType'], $loc)) {
165 // check dependencies, act accordingly if ext is loaded
166 list($instExtInfo,) = $extensionList->getInstalledExtensions();
167 $depStatus = $this->checkDependencies($extKey, $EM_CONF, $instExtInfo);
168 if (t3lib_extMgm::isLoaded($extKey) && !$depStatus['returnCode']) {
169 $content .= $depStatus['html'];
170 if ($uploadedTempFile) {
171 $content .= '<input type="hidden" name="CMD[alreadyUploaded]" value="' . $uploadedTempFile . '" />';
172 }
173 } else {
174 $res = $this->clearAndMakeExtensionDir($fetchData[0], $loc, $dontDelete);
175 if (is_array($res)) {
176 $extDirPath = trim($res[0]);
177 if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath, -1) == '/') {
178
179 $emConfFile = $extensionDetails->construct_ext_emconf_file($extKey, $EM_CONF);
180 $dirs = tx_em_Tools::extractDirsFromFileList(array_keys($fetchData[0]['FILES']));
181
182 $res = tx_em_Tools::createDirsInPath($dirs, $extDirPath);
183 if (!$res) {
184 $writeFiles = $fetchData[0]['FILES'];
185 $writeFiles['ext_emconf.php']['content'] = $emConfFile;
186 $writeFiles['ext_emconf.php']['content_md5'] = md5($emConfFile);
187
188 // Write files:
189 foreach ($writeFiles as $theFile => $fileData) {
190 t3lib_div::writeFile($extDirPath . $theFile, $fileData['content']);
191 if (!@is_file($extDirPath . $theFile)) {
192 if (!$this->silentMode) {
193 $flashMessage = t3lib_div::makeInstance(
194 't3lib_FlashMessage',
195 sprintf($GLOBALS['LANG']->getLL('ext_import_file_not_created'),
196 $extDirPath . $theFile),
197 '',
198 t3lib_FlashMessage::ERROR
199 );
200 $content .= $flashMessage->render();
201 } else {
202 if (!$this->silentMode) {
203 $flashMessage = t3lib_div::makeInstance(
204 't3lib_FlashMessage',
205 sprintf($GLOBALS['LANG']->getLL('ext_import_file_not_created'), $extDirPath . $theFile),
206 '',
207 t3lib_FlashMessage::ERROR
208 );
209 $content .= $flashMessage->render();
210 } else {
211 $content .= sprintf($GLOBALS['LANG']->getLL('ext_import_file_not_created'),
212 $extDirPath . $theFile) . '<br />';
213 }
214 }
215 } elseif (md5(t3lib_div::getUrl($extDirPath . $theFile)) != $fileData['content_md5']) {
216 $content .= sprintf($GLOBALS['LANG']->getLL('ext_import_file_corrupted'),
217 $extDirPath . $theFile) . '<br />';
218 }
219 }
220
221 t3lib_div::fixPermissions($extDirPath, TRUE);
222
223 // No content, no errors. Create success output here:
224 if (!$content) {
225 $messageContent = sprintf($GLOBALS['LANG']->getLL('ext_import_success_folder'), $extDirPath) . '<br />';
226
227 $uploadSucceed = true;
228
229 // Fix TYPO3_MOD_PATH for backend modules in extension:
230 $modules = t3lib_div::trimExplode(',', $EM_CONF['module'], 1);
231 if (count($modules)) {
232 foreach ($modules as $mD) {
233 $confFileName = $extDirPath . $mD . '/conf.php';
234 if (@is_file($confFileName)) {
235 $messageContent .= tx_em_Tools::writeTYPO3_MOD_PATH($confFileName, $loc, $extKey . '/' . $mD . '/') . '<br />';
236 } else {
237 $messageContent .= sprintf($GLOBALS['LANG']->getLL('ext_import_no_conf_file'),
238 $confFileName) . '<br />';
239 }
240 }
241 }
242 // NOTICE: I used two hours trying to find out why a script, ext_emconf.php, written twice and in between included by PHP did not update correct the second time. Probably something with PHP-A cache and mtime-stamps.
243 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder).
244
245 // Writing to ext_emconf.php:
246 $sEMD5A = $extensionDetails->serverExtensionMD5array($extKey, array('type' => $loc, 'EM_CONF' => array(), 'files' => array()));
247 $EM_CONF['_md5_values_when_last_written'] = serialize($sEMD5A);
248 $emConfFile = $extensionDetails->construct_ext_emconf_file($extKey, $EM_CONF);
249 t3lib_div::writeFile($extDirPath . 'ext_emconf.php', $emConfFile);
250
251 $messageContent .= 'ext_emconf.php: ' . $extDirPath . 'ext_emconf.php<br />';
252 $messageContent .= $GLOBALS['LANG']->getLL('ext_import_ext_type') . ' ';
253 $messageContent .= $this->api->typeLabels[$loc] . '<br />';
254 $messageContent .= '<br />';
255
256 // Remove cache files:
257 $updateContent = '';
258 if (t3lib_extMgm::isLoaded($extKey)) {
259 if (t3lib_extMgm::removeCacheFiles()) {
260 $messageContent .= $GLOBALS['LANG']->getLL('ext_import_cache_files_removed') . '<br />';
261 }
262
263 list($new_list) = $this->parentObject->extensionList->getInstalledExtensions();
264 $updateContent = $this->updatesForm($extKey, $new_list[$extKey], 1, t3lib_div::linkThisScript(array(
265 'CMD[showExt]' => $extKey,
266 'SET[singleDetails]' => 'info'
267 )));
268 }
269
270 if (!$this->silentMode) {
271 $flashMessage = t3lib_div::makeInstance(
272 't3lib_FlashMessage',
273 $messageContent,
274 $GLOBALS['LANG']->getLL('ext_import_success')
275 );
276 $content = $flashMessage->render() . $updateContent;
277 } else {
278 $content = $updateContent;
279 }
280
281
282 // Install / Uninstall:
283 if (!$this->parentObject->CMD['standAlone']) {
284 $content .= '<h3>' . $GLOBALS['LANG']->getLL('ext_import_install_uninstall') . '</h3>';
285 $content .= $new_list[$extKey] ?
286 '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
287 'CMD[showExt]' => $extKey,
288 'CMD[remove]' => 1,
289 'CMD[clrCmd]' => 1,
290 'SET[singleDetails]' => 'info'
291 ))) . '">' .
292 tx_em_Tools::removeButton() . ' ' . $GLOBALS['LANG']->getLL('ext_import_uninstall') . '</a>' :
293 '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
294 'CMD[showExt]' => $extKey,
295 'CMD[load]' => 1,
296 'CMD[clrCmd]' => 1,
297 'SET[singleDetails]' => 'info'
298 ))) . '">' .
299 tx_em_Tools::installButton() . ' ' . $GLOBALS['LANG']->getLL('ext_import_install') . '</a>';
300 } else {
301 $content = $GLOBALS['LANG']->getLL('ext_import_imported') .
302 '<br /><br />';
303 if ($this->silentMode || t3lib_div::_GP('nodoc')) {
304 $content .= '<a id="closewindow" href="javascript:parent.TYPO3.EM.Tools.closeImportWindow();">' . $GLOBALS['LANG']->getLL('ext_import_close') . '</a>';
305 } else {
306 $content .= '<a href="javascript:opener.top.list.iframe.document.forms[0].submit();window.close();">' .
307 $GLOBALS['LANG']->getLL('ext_import_close_check') . '</a>';
308 }
309
310 }
311 }
312 } else {
313 if (!$this->silentMode) {
314 $flashMessage = t3lib_div::makeInstance(
315 't3lib_FlashMessage',
316 $res,
317 '',
318 t3lib_FlashMessage::ERROR
319 );
320 $content = $flashMessage->render();
321 } else {
322 $content = $res;
323 }
324 }
325 } else {
326 if (!$this->silentMode) {
327 $flashMessage = t3lib_div::makeInstance(
328 't3lib_FlashMessage',
329 sprintf($GLOBALS['LANG']->getLL('ext_import_ext_path_different'), $extDirPath),
330 '',
331 t3lib_FlashMessage::ERROR
332 );
333 $content = $flashMessage->render();
334 } else {
335 $content = sprintf($GLOBALS['LANG']->getLL('ext_import_ext_path_different'), $extDirPath);
336 }
337 }
338 } else {
339 if (!$this->silentMode) {
340 $flashMessage = t3lib_div::makeInstance(
341 't3lib_FlashMessage',
342 $res,
343 '',
344 t3lib_FlashMessage::ERROR
345 );
346 $content = $flashMessage->render();
347 } else {
348 $content = $res;
349 }
350 }
351 }
352 } else {
353 if (!$this->silentMode) {
354 $flashMessage = t3lib_div::makeInstance(
355 't3lib_FlashMessage',
356 sprintf($GLOBALS['LANG']->getLL('ext_import_ext_only_here'),
357 $this->typePaths[$EM_CONF['lockType']], $EM_CONF['lockType']),
358 '',
359 t3lib_FlashMessage::ERROR
360 );
361 $content = $flashMessage->render();
362 } else {
363 $content = sprintf($GLOBALS['LANG']->getLL('ext_import_ext_only_here'),
364 tx_em_Tools::typePath($EM_CONF['lockType']), $EM_CONF['lockType']);
365 }
366 }
367 } else {
368 if (!$this->silentMode) {
369 $flashMessage = t3lib_div::makeInstance(
370 't3lib_FlashMessage',
371 $GLOBALS['LANG']->getLL('ext_import_no_ext_key_files'),
372 '',
373 t3lib_FlashMessage::ERROR
374 );
375 $content = $flashMessage->render();
376 } else {
377 $content = $GLOBALS['LANG']->getLL('ext_import_no_ext_key_files');
378 }
379 }
380 } else {
381 if (!$this->silentMode) {
382 $flashMessage = t3lib_div::makeInstance(
383 't3lib_FlashMessage',
384 sprintf($GLOBALS['LANG']->getLL('ext_import_data_transfer'), $fetchData),
385 '',
386 t3lib_FlashMessage::ERROR
387 );
388 $content = $flashMessage->render();
389 } else {
390 $content = sprintf($GLOBALS['LANG']->getLL('ext_import_data_transfer'), $fetchData);
391 }
392 }
393 } else {
394 if (!$this->silentMode) {
395 $flashMessage = t3lib_div::makeInstance(
396 't3lib_FlashMessage',
397 sprintf($GLOBALS['LANG']->getLL('ext_import_no_install_here'), $this->typePaths[$loc]),
398 '',
399 t3lib_FlashMessage::ERROR
400 );
401 $content = $flashMessage->render();
402 } else {
403 $content = sprintf($GLOBALS['LANG']->getLL('ext_import_no_install_here'), tx_em_Tools::typePath($loc));
404 }
405 }
406
407 return $content;
408 }
409
410 /**
411 *Check extension dependencies
412 *
413 * @param string $extKey
414 * @param array $conf
415 * @param array $instExtInfo
416 * @return array
417 */
418 function checkDependencies($extKey, $conf, $instExtInfo) {
419 $content = '';
420 $depError = false;
421 $depIgnore = false;
422 $msg = array();
423 $depsolver = t3lib_div::_POST('depsolver');
424
425 if (isset($conf['constraints']['depends']) && is_array($conf['constraints']['depends'])) {
426 foreach ($conf['constraints']['depends'] as $depK => $depV) {
427 if ($depsolver['ignore'][$depK]) {
428 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ignored'),
429 $depK) . '
430 <input type="hidden" value="1" name="depsolver[ignore][' . $depK . ']" />';
431 $depIgnore = true;
432 continue;
433 }
434 if ($depK == 'php') {
435 if (!$depV) {
436 continue;
437 }
438 $versionRange = tx_em_Tools::splitVersionRange($depV);
439 $phpv = strstr(PHP_VERSION, '-') ? substr(PHP_VERSION, 0, strpos(PHP_VERSION, '-')) : PHP_VERSION; // Linux distributors like to add suffixes, like in 5.1.2-1. Those must be ignored!
440 if ($versionRange[0] != '0.0.0' && version_compare($phpv, $versionRange[0], '<')) {
441 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_php_too_low'),
442 $phpv, $versionRange[0]);
443 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
444 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
445 $depError = true;
446 continue;
447 } elseif ($versionRange[1] != '0.0.0' && version_compare($phpv, $versionRange[1], '>')) {
448 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_php_too_high'),
449 $phpv, $versionRange[1]);
450 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
451 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
452 $depError = true;
453 continue;
454 }
455
456 } elseif ($depK == 'typo3') {
457 if (!$depV) {
458 continue;
459 }
460
461 // if the current TYPO3 version is a development version (like TYPO3 4.4-dev),
462 // then it should behave like TYPO3 4.4.0
463 $t3version = TYPO3_version;
464 if (stripos($t3version, '-dev')
465 || stripos($t3version, '-alpha')
466 || stripos($t3version, '-beta')
467 || stripos($t3version, '-RC')) {
468 // find the last occurence of "-" and replace that part with a ".0"
469 $t3version = substr($t3version, 0, strrpos($t3version, '-')) . '.0';
470 }
471
472 $versionRange = tx_em_Tools::splitVersionRange($depV);
473 if ($versionRange[0] != '0.0.0' && version_compare($t3version, $versionRange[0], '<')) {
474 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_typo3_too_low'),
475 $t3version, $versionRange[0]);
476 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
477 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
478 $depError = true;
479 continue;
480 } elseif ($versionRange[1] != '0.0.0' && version_compare($t3version, $versionRange[1], '>')) {
481 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_typo3_too_high'),
482 $t3version, $versionRange[1]);
483 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
484 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
485 $depError = true;
486 continue;
487 }
488 } elseif (strlen($depK) && !t3lib_extMgm::isLoaded($depK)) { // strlen check for braindead empty dependencies coming from extensions...
489 if (!isset($instExtInfo[$depK])) {
490 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_not_available'),
491 $depK);
492 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-import', array('title' => $GLOBALS['LANG']->getLL('checkDependencies_import_ext'))) . '&nbsp;
493 <a href="' . t3lib_div::linkThisUrl($this->parentObject->script, array(
494 'CMD[importExt]' => $depK,
495 'CMD[loc]' => 'L',
496 'CMD[standAlone]' => 1
497 )) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_import_now') . '</a>';
498 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
499 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_ext_requirement') . '</label>';
500 } else {
501 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_not_installed'),
502 $depK, $instExtInfo[$depK]['EM_CONF']['title']);
503 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . tx_em_Tools::installButton() . '&nbsp;
504 <a href="' . t3lib_div::linkThisUrl($this->parentObject->script, array(
505 'CMD[showExt]' => $depK,
506 'CMD[load]' => 1,
507 'CMD[clrCmd]' => 1,
508 'CMD[standAlone]' => 1,
509 'SET[singleDetails]' => 'info'
510 )) .
511 '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_install_now') . '</a>';
512 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
513 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_ext_requirement') . '</label>';
514 }
515 $depError = true;
516 } else {
517 $versionRange = tx_em_Tools::splitVersionRange($depV);
518 if ($versionRange[0] != '0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'], $versionRange[0], '<')) {
519 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_too_low'),
520 $depK, $instExtInfo[$depK]['EM_CONF']['version'], $versionRange[0]);
521 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
522 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
523 $depError = true;
524 continue;
525 } elseif ($versionRange[1] != '0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'], $versionRange[1], '>')) {
526 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_too_high'),
527 $depK, $instExtInfo[$depK]['EM_CONF']['version'], $versionRange[1]);
528 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
529 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
530 $depError = true;
531 continue;
532 }
533 }
534 }
535 }
536
537 if ($depError || $depIgnore) {
538 // dependent of the context in which we are (AJAX with tx_em_connection_ExtDirectServer or
539 // old-school rendering with historic pages in shiny ExtJS frames) we have various options
540 if ($this->parentObject instanceof SC_mod_tools_em_index) {
541 // we're in the lucky position to ask the user to uninstall the extension again
542 $content .= $this->parentObject->doc->section(
543 $GLOBALS['LANG']->getLL('removeExtFromList_dependency_error'),
544 implode('<br />', $msg), 0, 1, 2
545 );
546 } elseif ($this->parentObject instanceof tx_em_Connection_ExtDirectServer) {
547 // with ExtDirect, we are in a context, where we cannot ask the user for feedback
548 // thus we silently uninstall the newly uploaded extension
549 $this->parentObject->disableExtension($extKey);
550 }
551 }
552
553 // Check conflicts with other extensions:
554 $conflictError = false;
555 $conflictIgnore = false;
556 $msg = array();
557
558 if (isset($conf['constraints']['conflicts']) && is_array($conf['constraints']['conflicts'])) {
559 foreach ((array) $conf['constraints']['conflicts'] as $conflictK => $conflictV) {
560 if ($depsolver['ignore'][$conflictK]) {
561 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_conflict_ignored'),
562 $conflictK) . '
563 <input type="hidden" value="1" name="depsolver[ignore][' . $conflictK . ']" />';
564 $conflictIgnore = true;
565 continue;
566 }
567 if (t3lib_extMgm::isLoaded($conflictK)) {
568 $versionRange = tx_em_Tools::splitVersionRange($conflictV);
569 if ($versionRange[0] != '0.0.0' && version_compare($instExtInfo[$conflictK]['EM_CONF']['version'], $versionRange[0], '<')) {
570 continue;
571 }
572 elseif ($versionRange[1] != '0.0.0' && version_compare($instExtInfo[$conflictK]['EM_CONF']['version'], $versionRange[1], '>')) {
573 continue;
574 }
575 $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_conflict_remove'),
576 $extKey, $conflictK, $instExtInfo[$conflictK]['EM_CONF']['title'], $conflictK, $extKey);
577 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . tx_em_Tools::removeButton() . '&nbsp;
578 <a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
579 'CMD[showExt]' => $conflictK,
580 'CMD[remove]' => 1,
581 'CMD[clrCmd]' => 1,
582 'CMD[standAlone]' => 1,
583 'SET[singleDetails]' => 'info'
584 ))) .
585 '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_remove_now') . '</a>';
586 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $conflictK . ']" id="checkIgnore_' . $conflictK . '" />
587 <label for="checkIgnore_' . $conflictK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_conflict') . '</label>';
588 $conflictError = true;
589 }
590 }
591 }
592
593 if ($conflictError || $conflictIgnore) {
594 // dependent of the context in which we are (AJAX with tx_em_connection_ExtDirectServer or
595 // old-school rendering with historic pages in shiny ExtJS frames) we have various options
596 if ($this->parentObject instanceof SC_mod_tools_em_index) {
597 // we're in the lucky position to ask the user to uninstall the extension again
598 $content .= $this->parentObject->doc->section(
599 $GLOBALS['LANG']->getLL('checkDependencies_conflict_error'), implode('<br />', $msg), 0, 1, 2
600 );
601 } elseif ($this->parentObject instanceof tx_em_Connection_ExtDirectServer) {
602 // with ExtDirect, we are in a context, where we cannot ask the user for feedback
603 // thus we silently uninstall the newly uploaded extension
604 $this->parentObject->disableExtension($extKey);
605 }
606 }
607
608 // Check suggests on other extensions:
609 if (isset($conf['constraints']['suggests']) && is_array($conf['constraints']['suggests'])) {
610 $suggestion = false;
611 $suggestionIgnore = false;
612 $msg = array();
613 foreach ($conf['constraints']['suggests'] as $suggestK => $suggestV) {
614 if ($depsolver['ignore'][$suggestK]) {
615 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggestion_ignored'),
616 $suggestK) . '
617 <input type="hidden" value="1" name="depsolver[ignore][' . $suggestK . ']" />';
618 $suggestionIgnore = true;
619 continue;
620 }
621 if (!t3lib_extMgm::isLoaded($suggestK)) {
622 if (!isset($instExtInfo[$suggestK])) {
623 $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggest_import'),
624 $suggestK);
625 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-import', array('title' => $GLOBALS['LANG']->getLL('checkDependencies_import_ext'))) . '&nbsp;
626 <a href="' . t3lib_div::linkThisScript(array(
627 'CMD[importExt]' => $suggestK,
628 'CMD[loc]' => 'L',
629 'CMD[standAlone]' => 1
630 )) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_import_now') . '</a>';
631 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $suggestK . ']" id="checkIgnore_' . $suggestK . '" />
632 <label for="checkIgnore_' . $suggestK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_suggestion') . '</label>';
633 } else {
634 $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggest_installation'),
635 $suggestK, $instExtInfo[$suggestK]['EM_CONF']['title']);
636 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . tx_em_Tools::installButton() . '&nbsp;
637 <a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
638 'CMD[showExt]' => $suggestK,
639 'CMD[load]' => 1,
640 'CMD[clrCmd]' => 1,
641 'CMD[standAlone]' => 1,
642 'SET[singleDetails]' => 'info'
643 ))) .
644 '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_install_now') . '</a>';
645 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $suggestK . ']" id="checkIgnore_' . $suggestK . '" />
646 <label for="checkIgnore_' . $suggestK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_suggestion') . '</label>';
647 }
648 $suggestion = true;
649 }
650 }
651
652 if ($suggestion || $suggestionIgnore) {
653 // dependent of the context in which we are (AJAX with tx_em_connection_ExtDirectServer or
654 // old-school rendering with historic pages in shiny ExtJS frames) we have various options
655 if ($this->parentObject instanceof SC_mod_tools_em_index) {
656 // we're in the lucky position to ask the user to uninstall the extension again
657 $content .= $this->parentObject->doc->section(
658 sprintf($GLOBALS['LANG']->getLL('checkDependencies_exts_suggested_by_ext'), $extKey),
659 implode('<br />', $msg), 0, 1, 1
660 );
661 } elseif ($this->parentObject instanceof tx_em_Connection_ExtDirectServer) {
662 // with ExtDirect, we are in a context, where we cannot ask the user for feedback
663 // thus we silently uninstall the newly uploaded extension
664 $this->parentObject->disableExtension($extKey);
665 }
666 }
667 }
668
669 // only when we are in old-school HTML output mode (thus not ExtDirect), we can ask for user feedback
670 if (($depError || $conflictError || $suggestion) && ($this->parentObject instanceof SC_mod_tools_em_index)) {
671 foreach ($this->parentObject->CMD as $k => $v) {
672 $content .= '<input type="hidden" name="CMD[' . $k . ']" value="' . $v . '" />';
673 }
674 $content .= '<br /><br /><input type="submit" value="' . $GLOBALS['LANG']->getLL('checkDependencies_try_again') . '" />';
675
676 if (t3lib_div::_GP('nodoc')) {
677 $content .= '<input type="hidden" name="nodoc" value="1" />';
678 }
679
680 return array(
681 'returnCode' => FALSE,
682 'html' => '<form action="' . $this->parentObject->script . '" method="post" name="depform">' . $content . '</form>');
683 }
684
685 return array(
686 'returnCode' => TRUE
687 );
688 }
689
690
691 /**
692 * Delete extension from the file system
693 *
694 * @param string Extension key
695 * @param array Extension info array
696 * @return string Returns message string about the status of the operation
697 */
698 function extDelete($extKey, $extInfo, $command) {
699 $content = '';
700 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
701 if (t3lib_extMgm::isLoaded($extKey)) {
702 return $GLOBALS['LANG']->getLL('extDelete_ext_active');
703 } elseif (!tx_em_Tools::deleteAsType($extInfo['type'])) {
704 return sprintf($GLOBALS['LANG']->getLL('extDelete_wrong_scope'),
705 $this->api->typeLabels[$extInfo['type']]
706 );
707 } elseif (t3lib_div::inList('G,L', $extInfo['type'])) {
708 if ($command['doDelete'] && !strcmp($absPath, urldecode($command['absPath']))) {
709 $res = $this->removeExtDirectory($absPath);
710 if ($res) {
711 if (!$this->silentMode) {
712 $flashMessage = t3lib_div::makeInstance(
713 't3lib_FlashMessage',
714 nl2br($res),
715 sprintf($GLOBALS['LANG']->getLL('extDelete_remove_dir_failed'), $absPath),
716 t3lib_FlashMessage::ERROR
717 );
718 return $flashMessage->render();
719 }
720 return '';
721 } else {
722 if (!$this->silentMode) {
723 $flashMessage = t3lib_div::makeInstance(
724 't3lib_FlashMessage',
725 sprintf($GLOBALS['LANG']->getLL('extDelete_removed'), $absPath),
726 $GLOBALS['LANG']->getLL('extDelete_removed_header'),
727 t3lib_FlashMessage::OK
728 );
729 return $flashMessage->render();
730 }
731 return '';
732 }
733 } else {
734 $areYouSure = $GLOBALS['LANG']->getLL('extDelete_sure');
735 $deleteFromServer = $GLOBALS['LANG']->getLL('extDelete_from_server');
736 $onClick = "if (confirm('$areYouSure')) {window.location.href='" . t3lib_div::linkThisScript(array(
737 'CMD[showExt]' => $extKey,
738 'CMD[doDelete]' => 1,
739 'CMD[absPath]' => rawurlencode($absPath)
740 )) . "';}";
741 $content .= '<a class="t3-link deleteLink" href="#" onclick="' . htmlspecialchars($onClick) .
742 ' return false;"><strong>' . $deleteFromServer . '</strong> ' .
743 sprintf($GLOBALS['LANG']->getLL('extDelete_from_location'),
744 $this->api->typeLabels[$extInfo['type']],
745 substr($absPath, strlen(PATH_site))
746 ) . '</a>';
747 $content .= '<br /><br />' . $GLOBALS['LANG']->getLL('extDelete_backup');
748 return $content;
749 }
750 } else {
751 return $GLOBALS['LANG']->getLL('extDelete_neither_global_nor_local');
752 }
753 }
754
755 /**
756 * Removes the extension directory (including content)
757 *
758 * @param string Extension directory to remove (with trailing slash)
759 * @param boolean If set, will leave the extension directory
760 * @return boolean False on success, otherwise error string.
761 */
762 function removeExtDirectory($removePath, $removeContentOnly = 0) {
763 $errors = array();
764 if (@is_dir($removePath) && substr($removePath, -1) == '/' && (
765 t3lib_div::isFirstPartOfStr($removePath, tx_em_Tools::typePath('G')) ||
766 t3lib_div::isFirstPartOfStr($removePath, tx_em_Tools::typePath('L')) ||
767 (t3lib_div::isFirstPartOfStr($removePath, tx_em_Tools::typePath('S')) && $this->systemInstall) ||
768 t3lib_div::isFirstPartOfStr($removePath, PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . '_temp_/')) // Playing-around directory...
769 ) {
770
771 // All files in extension directory:
772 $fileArr = t3lib_div::getAllFilesAndFoldersInPath(array(), $removePath, '', 1);
773 if (is_array($fileArr)) {
774
775 // Remove files in dirs:
776 foreach ($fileArr as $removeFile) {
777 if (!@is_dir($removeFile)) {
778 if (@is_file($removeFile) && t3lib_div::isFirstPartOfStr($removeFile, $removePath) && strcmp($removeFile, $removePath)) { // ... we are very paranoid, so we check what cannot go wrong: that the file is in fact within the prefix path!
779 @unlink($removeFile);
780 clearstatcache();
781 if (@is_file($removeFile)) {
782 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_could_not_be_deleted'),
783 $removeFile
784 );
785 }
786 } else {
787 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_error_file'),
788 $removeFile, $removePath
789 );
790 }
791 }
792 }
793
794 // Remove directories:
795 $remDirs = tx_em_Tools::extractDirsFromFileList(t3lib_div::removePrefixPathFromList($fileArr, $removePath));
796 $remDirs = array_reverse($remDirs); // Must delete outer directories first...
797 foreach ($remDirs as $removeRelDir) {
798 $removeDir = $removePath . $removeRelDir;
799 if (@is_dir($removeDir)) {
800 @rmdir($removeDir);
801 clearstatcache();
802 if (@is_dir($removeDir)) {
803 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_error_files_left'),
804 $removeDir
805 );
806 }
807 } else {
808 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_error_no_dir'),
809 $removeDir
810 );
811 }
812 }
813
814 // If extension dir should also be removed:
815 if (!$removeContentOnly) {
816 @rmdir($removePath);
817 clearstatcache();
818 if (@is_dir($removePath)) {
819 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_error_folders_left'),
820 $removePath
821 );
822 }
823 }
824 } else {
825 $errors[] = $GLOBALS['LANG']->getLL('rmExtDir_error') . ' ' . $fileArr;
826 }
827 } else {
828 $errors[] = $GLOBALS['LANG']->getLL('rmExtDir_error_unallowed_path') . ' ' . $removePath;
829 }
830
831 // Return errors if any:
832 return implode(LF, $errors);
833 }
834
835 /**
836 * Validates the database according to extension requirements
837 * Prints form for changes if any. If none, returns blank. If an update is ordered, empty is returned as well.
838 * DBAL compliant (based on Install Tool code)
839 *
840 * @param string Extension key
841 * @param array Extension information array
842 * @param boolean If true, returns array with info.
843 * @return mixed If $infoOnly, returns array with information. Otherwise performs update.
844 */
845 function checkDBupdates($extKey, $extInfo, $infoOnly = 0) {
846
847
848 $dbStatus = array();
849 $content = '';
850
851 // Updating tables and fields?
852 $showUpdateStatements = TRUE;
853 if (is_array($extInfo['files']) && in_array('ext_tables.sql', $extInfo['files'])) {
854 $path = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
855 $fileContent = t3lib_div::getUrl($path . 'ext_tables.sql');
856
857 $FDfile = $this->install->getFieldDefinitions_fileContent($fileContent);
858 if (count($FDfile)) {
859 $FDdb = $this->install->getFieldDefinitions_database(TYPO3_db);
860 $diff = $this->install->getDatabaseExtra($FDfile, $FDdb);
861 $update_statements = $this->install->getUpdateSuggestions($diff);
862
863 $dbStatus['structure']['tables_fields'] = $FDfile;
864 $dbStatus['structure']['diff'] = $diff;
865
866 // Updating database...
867 if (!$infoOnly && is_array($this->install->INSTALL['database_update'])) {
868 $this->install->performUpdateQueries($update_statements['add'], $this->install->INSTALL['database_update']);
869 $this->install->performUpdateQueries($update_statements['change'], $this->install->INSTALL['database_update']);
870 $this->install->performUpdateQueries($update_statements['create_table'], $this->install->INSTALL['database_update']);
871 } else {
872 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/mod/tools/em/index.php']['checkDBupdates'])) {
873 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/mod/tools/em/index.php']['checkDBupdates'] as $classData) {
874 $hookObject = t3lib_div::getUserObj($classData);
875
876 if (!($hookObject instanceof tx_em_Index_CheckDatabaseUpdatesHook)) {
877 throw new UnexpectedValueException('$hookObject must implement interface em_index_checkDatabaseUpdatesHook', 1288418476);
878 }
879
880 /* @var $hookObject tx_em_Index_CheckDatabaseUpdatesHook */
881 $preprocessContent = $hookObject->preProcessDatabaseUpdates($extKey, $extInfo, $diff, $this->install, $this);
882 if ($preprocessContent) {
883 $content .= $preprocessContent;
884 $showUpdateStatements = FALSE;
885 break;
886 }
887 }
888 }
889 if ($showUpdateStatements) {
890 $content .= $this->install->generateUpdateDatabaseForm_checkboxes(
891 $update_statements['add'], $GLOBALS['LANG']->getLL('checkDBupdates_add_fields'));
892 $content .= $this->install->generateUpdateDatabaseForm_checkboxes(
893 $update_statements['change'], $GLOBALS['LANG']->getLL('checkDBupdates_changing_fields'), 1, 0, $update_statements['change_currentValue']);
894 $content .= $this->install->generateUpdateDatabaseForm_checkboxes(
895 $update_statements['create_table'], $GLOBALS['LANG']->getLL('checkDBupdates_add_tables'));
896 }
897 }
898 }
899 }
900
901 // Importing static tables?
902 if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql', $extInfo['files'])) {
903 $fileContent = t3lib_div::getUrl(tx_em_Tools::getExtPath($extKey, $extInfo['type']) . 'ext_tables_static+adt.sql');
904
905 $statements = $this->install->getStatementarray($fileContent, 1);
906 list($statements_table, $insertCount) = $this->install->getCreateTables($statements, 1);
907
908 // Execute import of static table content:
909 if (!$infoOnly && is_array($this->install->INSTALL['database_import'])) {
910
911 // Traverse the tables
912 foreach ($this->install->INSTALL['database_import'] as $table => $md5str) {
913 if ($md5str == md5($statements_table[$table])) {
914 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS ' . $table);
915 $GLOBALS['TYPO3_DB']->admin_query($statements_table[$table]);
916
917 if ($insertCount[$table]) {
918 $statements_insert = $this->install->getTableInsertStatements($statements, $table);
919
920 foreach ($statements_insert as $v) {
921 $GLOBALS['TYPO3_DB']->admin_query($v);
922 }
923 }
924 }
925 }
926 } else {
927 $whichTables = $this->install->getListOfTables();
928 if (count($statements_table)) {
929 $out = '';
930 foreach ($statements_table as $table => $definition) {
931 $exist = isset($whichTables[$table]);
932
933 $dbStatus['static'][$table]['exists'] = $exist;
934 $dbStatus['static'][$table]['count'] = $insertCount[$table];
935
936 $out .= '<tr>
937 <td><input type="checkbox" name="TYPO3_INSTALL[database_import][' . $table . ']" checked="checked" value="' . md5($definition) . '" /></td>
938 <td><strong>' . $table . '</strong></td>
939 <td><img src="clear.gif" width="10" height="1" alt="" /></td>
940 <td nowrap="nowrap">' .
941 ($insertCount[$table] ?
942 $GLOBALS['LANG']->getLL('checkDBupdates_rows') . ' ' . $insertCount[$table]
943 : '') .
944 '</td>
945 <td><img src="clear.gif" width="10" height="1" alt="" /></td>
946 <td nowrap="nowrap">' .
947 ($exist ?
948 t3lib_iconWorks::getSpriteIcon('status-dialog-warning') .
949 $GLOBALS['LANG']->getLL('checkDBupdates_table_exists')
950 : '') .
951 '</td>
952 </tr>';
953 }
954 $content .= '
955 <br />
956 <h3>' . $GLOBALS['LANG']->getLL('checkDBupdates_import_static_data') . '</h3>
957 <table border="0" cellpadding="0" cellspacing="0">' . $out . '</table>
958 ';
959 }
960 }
961 }
962
963 // Return array of information if $infoOnly, otherwise content.
964 return $infoOnly ? $dbStatus : $content;
965 }
966
967 /**
968 * Removes the current extension of $type and creates the base folder for the new one (which is going to be imported)
969 *
970 * @param array Data for imported extension
971 * @param string Extension installation scope (L,G,S)
972 * @param boolean If set, nothing will be deleted (neither directory nor files)
973 * @return mixed Returns array on success (with extension directory), otherwise an error string.
974 */
975 function clearAndMakeExtensionDir($importedData, $type, $dontDelete = 0) {
976 if (!$importedData['extKey']) {
977 return $GLOBALS['LANG']->getLL('clearMakeExtDir_no_ext_key');
978 }
979
980 // Setting install path (L, G, S or fileadmin/_temp_/)
981 $path = '';
982 switch ((string) $type) {
983 case 'G':
984 case 'L':
985 $path = tx_em_Tools::typePath($type);
986 $suffix = '';
987
988 // Creates the typo3conf/ext/ directory if it does NOT already exist:
989 if ((string) $type == 'L' && !@is_dir($path)) {
990 t3lib_div::mkdir($path);
991 }
992 break;
993 default:
994 if ($this->systemInstall && (string) $type == 'S') {
995 $path = tx_em_Tools::typePath($type);
996 $suffix = '';
997 } else {
998 $path = PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . '_temp_/';
999 $suffix = '_' . date('dmy-His');
1000 }
1001 break;
1002 }
1003
1004 // If the install path is OK...
1005 if ($path && @is_dir($path)) {
1006
1007 // Set extension directory:
1008 $extDirPath = $path . $importedData['extKey'] . $suffix . '/';
1009
1010 // Install dir was found, remove it then:
1011 if (@is_dir($extDirPath)) {
1012 if ($dontDelete) {
1013 return array($extDirPath);
1014 }
1015 $res = $this->removeExtDirectory($extDirPath);
1016 if ($res) {
1017 if (!$this->silentMode) {
1018 $flashMessage = t3lib_div::makeInstance(
1019 't3lib_FlashMessage',
1020 nl2br($res),
1021 sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_could_not_remove_dir'), $extDirPath),
1022 t3lib_FlashMessage::ERROR
1023 );
1024 return $flashMessage->render();
1025 }
1026 return '';
1027 }
1028 }
1029
1030 // We go create...
1031 t3lib_div::mkdir($extDirPath);
1032 if (!is_dir($extDirPath)) {
1033 return sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_could_not_create_dir'),
1034 $extDirPath);
1035 }
1036 return array($extDirPath);
1037 } else {
1038 return sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_no_dir'),
1039 $path);
1040 }
1041 }
1042
1043
1044 /*******************************
1045 *
1046 * Extension analyzing (detailed information)
1047 *
1048 ******************************/
1049
1050 /**
1051 * Perform a detailed, technical analysis of the available extension on server!
1052 * Includes all kinds of verifications
1053 * Takes some time to process, therfore use with care, in particular in listings.
1054 *
1055 * @param string Extension key
1056 * @param array Extension information
1057 * @param boolean If set, checks for validity of classes etc.
1058 * @return array Information in an array.
1059 */
1060 function makeDetailedExtensionAnalysis($extKey, $extInfo, $validity = 0) {
1061
1062 // Get absolute path of the extension
1063 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
1064 $extensionDetails = t3lib_div::makeInstance('tx_em_Extensions_Details', $this);
1065 $infoArray = array();
1066
1067 $table_class_prefix = substr($extKey, 0, 5) == 'user_' ? 'user_' : 'tx_' . str_replace('_', '', $extKey) . '_';
1068 $module_prefix = substr($extKey, 0, 5) == 'user_' ? 'u' : 'tx' . str_replace('_', '', $extKey);
1069
1070 // Database status:
1071 $dbInfo = $this->checkDBupdates($extKey, $extInfo, 1);
1072
1073 // Database structure required:
1074 if (is_array($dbInfo['structure']['tables_fields'])) {
1075 $modify_tables = t3lib_div::trimExplode(',', $extInfo['EM_CONF']['modify_tables'], 1);
1076 $infoArray['dump_tf'] = array();
1077
1078 foreach ($dbInfo['structure']['tables_fields'] as $tN => $d) {
1079 if (in_array($tN, $modify_tables)) {
1080 $infoArray['fields'][] = $tN . ': <i>' .
1081 (is_array($d['fields']) ? implode(', ', array_keys($d['fields'])) : '') .
1082 (is_array($d['keys']) ?
1083 ' + ' . count($d['keys']) . ' ' . $GLOBALS['LANG']->getLL('detailedExtAnalysis_keys') : '') .
1084 '</i>';
1085 if (is_array($d['fields'])) {
1086 foreach ($d['fields'] as $fN => $value) {
1087 $infoArray['dump_tf'][] = $tN . '.' . $fN;
1088 if (!t3lib_div::isFirstPartOfStr($fN, $table_class_prefix)) {
1089 $infoArray['NSerrors']['fields'][$fN] = $fN;
1090 } else {
1091 $infoArray['NSok']['fields'][$fN] = $fN;
1092 }
1093 }
1094 }
1095 if (is_array($d['keys'])) {
1096 foreach ($d['keys'] as $fN => $value) {
1097 $infoArray['dump_tf'][] = $tN . '.KEY:' . $fN;
1098 }
1099 }
1100 } else {
1101 $infoArray['dump_tf'][] = $tN;
1102 $infoArray['tables'][] = $tN;
1103 if (!t3lib_div::isFirstPartOfStr($tN, $table_class_prefix)) {
1104 $infoArray['NSerrors']['tables'][$tN] = $tN;
1105 } else {
1106 $infoArray['NSok']['tables'][$tN] = $tN;
1107 }
1108 }
1109 }
1110 if (count($dbInfo['structure']['diff']['diff']) || count($dbInfo['structure']['diff']['extra'])) {
1111 $msg = array();
1112 if (count($dbInfo['structure']['diff']['diff'])) {
1113 $msg[] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_tables_are_missing');
1114 }
1115 if (count($dbInfo['structure']['diff']['extra'])) {
1116 $msg[] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_tables_are_of_wrong_type');
1117 }
1118 $infoArray['tables_error'] = 1;
1119 if (t3lib_extMgm::isLoaded($extKey)) {
1120 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_tables_are'),
1121 implode(' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:and') . ' ', $msg)
1122 );
1123 }
1124 }
1125 }
1126
1127 // Static tables?
1128 if (is_array($dbInfo['static'])) {
1129 $infoArray['static'] = array_keys($dbInfo['static']);
1130
1131 foreach ($dbInfo['static'] as $tN => $d) {
1132 if (!$d['exists']) {
1133 $infoArray['static_error'] = 1;
1134 if (t3lib_extMgm::isLoaded($extKey)) {
1135 $infoArray['errors'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_static_tables_missing');
1136 }
1137 if (!t3lib_div::isFirstPartOfStr($tN, $table_class_prefix)) {
1138 $infoArray['NSerrors']['tables'][$tN] = $tN;
1139 } else {
1140 $infoArray['NSok']['tables'][$tN] = $tN;
1141 }
1142 }
1143 }
1144 }
1145
1146 // Backend Module-check:
1147 $knownModuleList = t3lib_div::trimExplode(',', $extInfo['EM_CONF']['module'], 1);
1148 foreach ($knownModuleList as $mod) {
1149 if (@is_dir($absPath . $mod)) {
1150 if (@is_file($absPath . $mod . '/conf.php')) {
1151 $confFileInfo = $extensionDetails->modConfFileAnalysis($absPath . $mod . '/conf.php');
1152 if (is_array($confFileInfo['TYPO3_MOD_PATH'])) {
1153 $shouldBePath = tx_em_Tools::typeRelPath($extInfo['type']) . $extKey . '/' . $mod . '/';
1154 if (strcmp($confFileInfo['TYPO3_MOD_PATH'][1][1], $shouldBePath)) {
1155 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_wrong_mod_path'),
1156 $confFileInfo['TYPO3_MOD_PATH'][1][1],
1157 $shouldBePath
1158 );
1159 }
1160 } else {
1161 // It seems like TYPO3_MOD_PATH and therefore also this warning is no longer needed.
1162 // $infoArray['errors'][] = 'No definition of TYPO3_MOD_PATH constant found inside!';
1163 }
1164 if (is_array($confFileInfo['MCONF_name'])) {
1165 $mName = $confFileInfo['MCONF_name'][1][1];
1166 $mNameParts = explode('_', $mName);
1167 $infoArray['moduleNames'][] = $mName;
1168 if (!t3lib_div::isFirstPartOfStr($mNameParts[0], $module_prefix) &&
1169 (!$mNameParts[1] || !t3lib_div::isFirstPartOfStr($mNameParts[1], $module_prefix))) {
1170 $infoArray['NSerrors']['modname'][] = $mName;
1171 } else {
1172 $infoArray['NSok']['modname'][] = $mName;
1173 }
1174 } else {
1175 $infoArray['errors'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_mconf_missing');
1176 }
1177 } else {
1178 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_be_module_conf_missing'),
1179 $mod . '/conf.php'
1180 );
1181 }
1182 } else {
1183 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_module_folder_missing'),
1184 $mod . '/'
1185 );
1186 }
1187 }
1188 $dirs = t3lib_div::get_dirs($absPath);
1189 if (is_array($dirs)) {
1190 reset($dirs);
1191 while (list(, $mod) = each($dirs)) {
1192 if (!in_array($mod, $knownModuleList) && @is_file($absPath . $mod . '/conf.php')) {
1193 $confFileInfo = $extensionDetails->modConfFileAnalysis($absPath . $mod . '/conf.php');
1194 if (is_array($confFileInfo)) {
1195 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_unconfigured_module'),
1196 $mod . '/conf.php'
1197 );
1198 }
1199 }
1200 }
1201 }
1202
1203 // ext_tables.php:
1204 if (@is_file($absPath . 'ext_tables.php')) {
1205 $content = t3lib_div::getUrl($absPath . 'ext_tables.php');
1206 if (stristr($content, 't3lib_extMgm::addModule')) {
1207 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_module');
1208 }
1209 if (stristr($content, 't3lib_extMgm::insertModuleFunction')) {
1210 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_module_and_more');
1211 }
1212 if (stristr($content, 't3lib_div::loadTCA')) {
1213 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_loadTCA');
1214 }
1215 if (stristr($content, '$TCA[')) {
1216 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_TCA');
1217 }
1218 if (stristr($content, 't3lib_extMgm::addPlugin')) {
1219 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_plugin');
1220 }
1221 }
1222
1223 // ext_localconf.php:
1224 if (@is_file($absPath . 'ext_localconf.php')) {
1225 $content = t3lib_div::getUrl($absPath . 'ext_localconf.php');
1226 if (stristr($content, 't3lib_extMgm::addPItoST43')) {
1227 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_plugin_st43');
1228 }
1229 if (stristr($content, 't3lib_extMgm::addPageTSConfig')) {
1230 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_page_ts');
1231 }
1232 if (stristr($content, 't3lib_extMgm::addUserTSConfig')) {
1233 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_user_ts');
1234 }
1235 if (stristr($content, 't3lib_extMgm::addTypoScriptSetup')) {
1236 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_ts_setup');
1237 }
1238 if (stristr($content, 't3lib_extMgm::addTypoScriptConstants')) {
1239 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_ts_constants');
1240 }
1241 }
1242
1243 if (@is_file($absPath . 'ext_typoscript_constants.txt')) {
1244 $infoArray['TSfiles'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_constants');
1245 }
1246 if (@is_file($absPath . 'ext_typoscript_setup.txt')) {
1247 $infoArray['TSfiles'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_setup');
1248 }
1249 if (@is_file($absPath . 'ext_conf_template.txt')) {
1250 $infoArray['conf'] = 1;
1251 }
1252
1253 // Classes:
1254 if ($validity) {
1255 $filesInside = tx_em_Tools::getClassIndexLocallangFiles($absPath, $table_class_prefix, $extKey);
1256 if (is_array($filesInside['errors'])) {
1257 $infoArray['errors'] = array_merge((array) $infoArray['errors'], $filesInside['errors']);
1258 }
1259 if (is_array($filesInside['NSerrors'])) {
1260 $infoArray['NSerrors'] = array_merge((array) $infoArray['NSerrors'], $filesInside['NSerrors']);
1261 }
1262 if (is_array($filesInside['NSok'])) {
1263 $infoArray['NSok'] = array_merge((array) $infoArray['NSok'], $filesInside['NSok']);
1264 }
1265 $infoArray['locallang'] = $filesInside['locallang'];
1266 $infoArray['classes'] = $filesInside['classes'];
1267 }
1268
1269 // Upload folders
1270 if ($extInfo['EM_CONF']['uploadfolder']) {
1271 $infoArray['uploadfolder'] = tx_em_Tools::uploadFolder($extKey);
1272 if (!@is_dir(PATH_site . $infoArray['uploadfolder'])) {
1273 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_no_upload_folder'),
1274 $infoArray['uploadfolder']
1275 );
1276 $infoArray['uploadfolder'] = '';
1277 }
1278 }
1279
1280 // Create directories:
1281 if ($extInfo['EM_CONF']['createDirs']) {
1282 $infoArray['createDirs'] = array_unique(t3lib_div::trimExplode(',', $extInfo['EM_CONF']['createDirs'], 1));
1283 foreach ($infoArray['createDirs'] as $crDir) {
1284 if (!@is_dir(PATH_site . $crDir)) {
1285 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_no_upload_folder'),
1286 $crDir
1287 );
1288 }
1289 }
1290 }
1291
1292 // Return result array:
1293 return $infoArray;
1294 }
1295
1296
1297 /**
1298 * Produces the config form for an extension (if any template file, ext_conf_template.txt is found)
1299 *
1300 * @param string Extension key
1301 * @param array Extension information array
1302 * @param boolean If true, the form HTML content is returned, otherwise the content is set in $this->content.
1303 * @param string Submit-to URL (supposedly)
1304 * @param string Additional form fields to include.
1305 * @return string Depending on $output. Can return the whole form.
1306 */
1307 function tsStyleConfigForm($extKey, $extInfo, $output = 0, $script = '', $addFields = '') {
1308 global $TYPO3_CONF_VARS;
1309
1310 // Initialize:
1311 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
1312 $relPath = tx_em_Tools::typeRelPath($extInfo['type']) . $extKey . '/';
1313
1314 $form = '';
1315
1316 // Look for template file for form:
1317 if (t3lib_extMgm::isLoaded($extKey) && @is_file($absPath . 'ext_conf_template.txt')) {
1318
1319 // Load tsStyleConfig class and parse configuration template:
1320 $tsStyleConfig = t3lib_div::makeInstance('t3lib_tsStyleConfig');
1321 $tsStyleConfig->doNotSortCategoriesBeforeMakingForm = TRUE;
1322 $theConstants = $tsStyleConfig->ext_initTSstyleConfig(
1323 t3lib_div::getUrl($absPath . 'ext_conf_template.txt'),
1324 $relPath,
1325 $absPath,
1326 $GLOBALS['BACK_PATH']
1327 );
1328
1329 // Load the list of resources.
1330 $tsStyleConfig->ext_loadResources($absPath . 'res/');
1331
1332 // Load current value:
1333 $arr = unserialize($TYPO3_CONF_VARS['EXT']['extConf'][$extKey]);
1334 $arr = is_array($arr) ? $arr : array();
1335
1336 // Call processing function for constants config and data before write and form rendering:
1337 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'])) {
1338 $_params = array('fields' => &$theConstants, 'data' => &$arr, 'extKey' => $extKey);
1339 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'] as $_funcRef) {
1340 t3lib_div::callUserFunction($_funcRef, $_params, $this);
1341 }
1342 unset($_params);
1343 }
1344
1345 // If saving operation is done:
1346 if (t3lib_div::_POST('submit')) {
1347 $tsStyleConfig->ext_procesInput(t3lib_div::_POST(), array(), $theConstants, array());
1348 $arr = $tsStyleConfig->ext_mergeIncomingWithExisting($arr);
1349 $this->writeTsStyleConfig($extKey, $arr);
1350 }
1351
1352 // Setting value array
1353 $tsStyleConfig->ext_setValuearray($theConstants, $arr);
1354
1355 // Getting session data:
1356 $MOD_MENU = array();
1357 $MOD_MENU['constant_editor_cat'] = $tsStyleConfig->ext_getCategoriesForModMenu();
1358 $MOD_SETTINGS = t3lib_BEfunc::getModuleData($MOD_MENU, t3lib_div::_GP('SET'), 'xMod_test');
1359
1360 // Resetting the menu (stop)
1361 if (count($MOD_MENU['constant_editor_cat']) > 1) {
1362 $menu = $GLOBALS['LANG']->getLL('extInfoArray_category') . ' ' .
1363 t3lib_BEfunc::getFuncMenu(0, 'SET[constant_editor_cat]', $MOD_SETTINGS['constant_editor_cat'], $MOD_MENU['constant_editor_cat'], '', '&CMD[showExt]=' . $extKey);
1364 // add class to select
1365 $menu = str_replace('<select', '<select class="mod-menu-template-select"', $menu);
1366 if ($this->silentMode) {
1367 $menu = str_replace('jumpToUrl', 'abc', $menu);
1368 }
1369
1370 if ($this->parentObject instanceof SC_mod_tools_em_index) {
1371 $this->parentObject->content .= $this->parentObject->doc->section('', '<span class="nobr">' . $menu . '</span>');
1372 $this->parentObject->content .= $this->parentObject->doc->spacer(10);
1373 } else {
1374 $form .= '<h3>' . '<span class="nobr">' . $menu . '</span></h3>';
1375 }
1376 }
1377
1378 // Category and constant editor config:
1379 $form .= '
1380 <table border="0" cellpadding="0" cellspacing="0" width="600">
1381 <tr>
1382 <td>' . $tsStyleConfig->ext_getForm(
1383 $MOD_SETTINGS['constant_editor_cat'],
1384 $theConstants,
1385 $script,
1386 $addFields,
1387 $extKey,
1388 !$this->silentMode
1389 ) . ($this->silentMode ? '' : '</form>') .'</td>
1390 </tr>
1391 </table>';
1392 } else {
1393 if (!$this->silentMode) {
1394 $flashMessage = t3lib_div::makeInstance(
1395 't3lib_FlashMessage',
1396 $GLOBALS['LANG']->getLL('tsStyleConfigForm_additional_config'),
1397 '',
1398 t3lib_FlashMessage::INFO
1399 );
1400 }
1401
1402 $form = '
1403 <table border="0" cellpadding="0" cellspacing="0" width="600">
1404 <tr>
1405 <td>
1406 <form action="' . htmlspecialchars($script) . '" method="post">' .
1407 $addFields .
1408 ($this->silentMode ? '' : $flashMessage->render()) .
1409 (t3lib_div::_GP('nodoc') ? '<input type="hidden" name="nodoc" value="1" />' : '') .
1410 '<br /><input type="submit" id="configuration-submit-' . $extKey . '" name="write" value="' . $GLOBALS['LANG']->getLL('updatesForm_make_updates') . '" />
1411 </form>
1412 </td>
1413 </tr>
1414 </table>';
1415 }
1416
1417
1418 return $form;
1419
1420 }
1421
1422 /**
1423 * Writes the TSstyleconf values to "localconf.php"
1424 * Removes the temp_CACHED* files before return.
1425 *
1426 * @param string Extension key
1427 * @param array Configuration array to write back
1428 * @return void
1429 */
1430 function writeTsStyleConfig($extKey, $arr) {
1431
1432 // Instance of install tool
1433 $instObj = new t3lib_install;
1434 $instObj->allowUpdateLocalConf = 1;
1435 $instObj->updateIdentity = 'TYPO3 Extension Manager';
1436
1437 // Get lines from localconf file
1438 $lines = $instObj->writeToLocalconf_control();
1439 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extConf\'][\'' . $extKey . '\']', serialize($arr)); // This will be saved only if there are no linebreaks in it !
1440 $instObj->writeToLocalconf_control($lines);
1441
1442 t3lib_extMgm::removeCacheFiles();
1443 }
1444
1445
1446 /**
1447 * Creates a form for an extension which contains all options for configuration, updates of database, clearing of cache etc.
1448 *
1449 * @param string $extKey Extension key
1450 * @param array $extInfo Extension information array
1451 * @param boolean $notSilent If set, the form will ONLY show if fields/tables should be updated (suppressing forms like general configuration and cache clearing).
1452 * @param string $script Alternative action=""-script
1453 * @param string $addFields Additional form fields
1454 * @param boolean $addFormTags TRUE if it shopuld be wrapped with form tag
1455 * @param boolean $excludeDatabaseCheck TRUE if no database check should be done
1456 * @return string
1457 */
1458 function updatesForm($extKey, $extInfo, $notSilent = FALSE, $script = '', $addFields = '', $addFormTag = TRUE, $excludeDatabaseCheck = FALSE) {
1459 $script = $script ? $script : t3lib_div::linkThisScript();
1460 if ($addFormTag) {
1461 $formWrap = array('<form action="' . htmlspecialchars($script) . '" method="POST">', '</form>');
1462 } else {
1463 $formWrap = array('', '');
1464 }
1465 $extensionDetails = t3lib_div::makeInstance('tx_em_Extensions_Details', $this);
1466 $updates = '';
1467
1468 if (!$excludeDatabaseCheck) {
1469 $updates .= $this->checkDBupdates($extKey, $extInfo);
1470 }
1471
1472 $uCache = $this->checkClearCache($extInfo);
1473 if ($notSilent) {
1474 $updates .= $uCache;
1475 }
1476 $updates .= $extensionDetails->checkUploadFolder($extKey, $extInfo);
1477
1478 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
1479 if ($notSilent && @is_file($absPath . 'ext_conf_template.txt')) {
1480 $configForm = $this->tsStyleConfigForm($extKey, $extInfo, 1, $script, $updates . $addFields . '<br />');
1481 }
1482
1483 if ($updates || $configForm) {
1484 if ($configForm) {
1485 $updates = $formWrap[0] . $configForm . $formWrap[1];
1486 } else {
1487 $updates = $formWrap[0] . $updates . $addFields . '
1488 <br /><input type="submit" name="write" id="update-submit-' . $extKey . '" value="' . $GLOBALS['LANG']->getLL('updatesForm_make_updates') . '" />
1489 ' . $formWrap[1];
1490 }
1491 }
1492 return $updates;
1493 }
1494
1495
1496 /**
1497 * Check if clear-cache should be performed, otherwise show form (for installation of extension)
1498 * Shown only if the extension has the clearCacheOnLoad flag set.
1499 *
1500 * @param string Extension key
1501 * @param array Extension information array
1502 * @return string HTML output (if form is shown)
1503 */
1504 function checkClearCache($extInfo) {
1505 $content = '';
1506 if ($extInfo['EM_CONF']['clearCacheOnLoad']) {
1507 if (t3lib_div::_POST('_clear_all_cache')) { // Action: Clearing the cache
1508 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
1509 $tce->stripslashes_values = 0;
1510 $tce->start(array(), array());
1511 $tce->clear_cacheCmd('all');
1512 } else { // Show checkbox for clearing cache:
1513 $content .= '
1514 <br />
1515 <h3>' . $GLOBALS['LANG']->getLL('checkUploadFolder_clear_cache') . '</h3>
1516 <p>' . $GLOBALS['LANG']->getLL('checkUploadFolder_clear_cache_requested') . '<br />
1517 <label for="check_clear_all_cache">' . $GLOBALS['LANG']->getLL('checkUploadFolder_clear_all_cache') . '</label>
1518 <input type="checkbox" name="_clear_all_cache" id="check_clear_all_cache" checked="checked" value="1" /><br />
1519 </p>
1520 ';
1521 }
1522 }
1523 return $content;
1524 }
1525
1526 /**
1527 * Writes the extension list to "localconf.php" file
1528 * Removes the temp_CACHED* files before return.
1529 *
1530 * @param string List of extensions
1531 * @return void
1532 */
1533 function writeNewExtensionList($newExtList) {
1534 $strippedExtensionList = $this->stripNonFrontendExtensions($newExtList);
1535
1536 // Instance of install tool
1537 $instObj = new t3lib_install;
1538 $instObj->allowUpdateLocalConf = 1;
1539 $instObj->updateIdentity = 'TYPO3 Extension Manager';
1540
1541 // Get lines from localconf file
1542 $lines = $instObj->writeToLocalconf_control();
1543 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extList\']', $newExtList);
1544 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extList_FE\']', $strippedExtensionList);
1545 $instObj->writeToLocalconf_control($lines);
1546
1547 $GLOBALS['TYPO3_CONF_VARS']['EXT']['extList'] = $newExtList;
1548 $GLOBALS['TYPO3_CONF_VARS']['EXT']['extList_FE'] = $strippedExtensionList;
1549 t3lib_extMgm::removeCacheFiles();
1550 }
1551
1552 /**
1553 * Removes unneeded extensions from the frontend based on
1554 * EMCONF doNotLoadInFE = 1
1555 *
1556 * @param string $extList
1557 * @return string
1558 */
1559 function stripNonFrontendExtensions($extList) {
1560 $fullExtList = $this->parentObject->extensionList->getInstalledExtensions();
1561 $extListArray = t3lib_div::trimExplode(',', $extList);
1562 foreach ($extListArray as $arrayKey => $extKey) {
1563 if ($fullExtList[0][$extKey]['EM_CONF']['doNotLoadInFE'] == 1) {
1564 unset($extListArray[$arrayKey]);
1565 }
1566 }
1567 $nonFEList = implode(',', $extListArray);
1568 return $nonFEList;
1569 }
1570
1571 /**
1572 * Updates the database according to extension requirements
1573 * DBAL compliant (based on Install Tool code)
1574 *
1575 * @param string Extension key
1576 * @param array Extension information array
1577 * @return void
1578 */
1579 function forceDBupdates($extKey, $extInfo) {
1580 $instObj = new t3lib_install;
1581
1582 // Updating tables and fields?
1583 if (is_array($extInfo['files']) && in_array('ext_tables.sql', $extInfo['files'])) {
1584 $fileContent = t3lib_div::getUrl(tx_em_Tools::getExtPath($extKey, $extInfo['type']) . 'ext_tables.sql');
1585
1586 $FDfile = $instObj->getFieldDefinitions_fileContent($fileContent);
1587 if (count($FDfile)) {
1588 $FDdb = $instObj->getFieldDefinitions_database(TYPO3_db);
1589 $diff = $instObj->getDatabaseExtra($FDfile, $FDdb);
1590 $update_statements = $instObj->getUpdateSuggestions($diff);
1591
1592 foreach ((array) $update_statements['add'] as $string) {
1593 $GLOBALS['TYPO3_DB']->admin_query($string);
1594 }
1595 foreach ((array) $update_statements['change'] as $string) {
1596 $GLOBALS['TYPO3_DB']->admin_query($string);
1597 }
1598 foreach ((array) $update_statements['create_table'] as $string) {
1599 $GLOBALS['TYPO3_DB']->admin_query($string);
1600 }
1601 }
1602 }
1603
1604 // Importing static tables?
1605 if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql', $extInfo['files'])) {
1606 $fileContent = t3lib_div::getUrl(tx_em_Tools::getExtPath($extKey, $extInfo['type']) . 'ext_tables_static+adt.sql');
1607
1608 $statements = $instObj->getStatementarray($fileContent, 1);
1609 list($statements_table, $insertCount) = $instObj->getCreateTables($statements, 1);
1610
1611 // Traverse the tables
1612 foreach ($statements_table as $table => $query) {
1613 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS ' . $table);
1614 $GLOBALS['TYPO3_DB']->admin_query($query);
1615
1616 if ($insertCount[$table]) {
1617 $statements_insert = $instObj->getTableInsertStatements($statements, $table);
1618
1619 foreach ($statements_insert as $v) {
1620 $GLOBALS['TYPO3_DB']->admin_query($v);
1621 }
1622 }
1623 }
1624 }
1625 }
1626
1627 }
1628
1629 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/sysext/em/classes/install/class.tx_em_install.php'])) {
1630 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/sysext/em/classes/install/class.tx_em_install.php']);
1631 }
1632
1633 ?>