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