5ba790eeca16d3ec3216fa294f23d5370c59f73e
[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 *
47 * @var t3lib_install
48 */
49 protected $install;
50
51
52 protected $systemInstall = 0; // If "1" then installs in the sysext directory is allowed. Default: 0
53
54 /**
55 * Constructor
56 *
57 * @param SC_mod_tools_em_index $parentObject
58 */
59 public function __construct($parentObject = NULL) {
60 $GLOBALS['LANG']->includeLLFile(t3lib_extMgm::extPath('em', 'language/locallang.xml'));
61 $this->parentObject = $parentObject;
62 $this->install = t3lib_div::makeInstance('t3lib_install');
63 $this->install->INSTALL = t3lib_div::_GP('TYPO3_INSTALL');
64 $this->systemInstall = isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowSystemInstall']) && $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowSystemInstall'];
65 }
66
67 /**
68 * Imports the data of an extension from upload
69 *
70 * @param $uploadedTempFile
71 * @param $location
72 * @param bool $uploadOverwrite
73 * @return array
74 */
75 public function uploadExtensionFile($uploadedTempFile, $location, $uploadOverwrite = FALSE) {
76 $error = '';
77 $fileContent = t3lib_div::getUrl($uploadedTempFile);
78 if (!$fileContent) {
79 return array(
80 'success' => FALSE,
81 'error' => $GLOBALS['LANG']->getLL('ext_import_file_empty')
82 );
83 }
84
85 // Decode file data:
86 $terConnection = t3lib_div::makeInstance('tx_em_Connection_Ter', $this);
87 $fetchData = $terConnection->decodeExchangeData($fileContent);
88 if (is_array($fetchData)) {
89 $extKey = $fetchData[0]['extKey'];
90 if ($extKey) {
91 if (!$uploadOverwrite) {
92 $comingExtPath = tx_em_Tools::typePath($location) . $extKey . '/';
93 if (@is_dir($comingExtPath)) {
94 $error = sprintf($GLOBALS['LANG']->getLL('ext_import_ext_present_no_overwrite'), $comingExtPath) .
95 '<br />' . $GLOBALS['LANG']->getLL('ext_import_ext_present_nothing_done');
96
97 } // ... else go on, install...
98 } // ... else go on, install...
99 } else {
100 $error = $GLOBALS['LANG']->getLL('ext_import_no_key');
101 }
102 } else {
103 $error = sprintf($GLOBALS['LANG']->getLL('ext_import_wrong_file_format'), $fetchData);
104 }
105
106 if ($error) {
107 return array(FALSE, $error);
108 } else {
109 return array(TRUE, $fetchData);
110 }
111
112 }
113
114 /**
115 * Installs an extension.
116 *
117 * @param $fetchData
118 * @param $loc
119 * @param $version
120 * @param $uploadedTempFile
121 * @param $dontDelete
122 * @return mixed|string
123 */
124 public function installExtension($fetchData, $loc, $version, $uploadedTempFile, $dontDelete) {
125 $xmlhandler =& $this->parentObject->xmlhandler;
126 $extensionList =& $this->parentObject->extensionList;
127 $extensionDetails =& $this->parentObject->extensionDetails;
128
129 if (tx_em_Tools::importAsType($loc)) {
130 if (is_array($fetchData)) { // There was some data successfully transferred
131 if ($fetchData[0]['extKey'] && is_array($fetchData[0]['FILES'])) {
132 $extKey = $fetchData[0]['extKey'];
133 if (!isset($fetchData[0]['EM_CONF']['constraints'])) {
134 $fetchData[0]['EM_CONF']['constraints'] = $xmlhandler->extensionsXML[$extKey]['versions'][$version]['dependencies'];
135 }
136 $EM_CONF = tx_em_Tools::fixEMCONF($fetchData[0]['EM_CONF']);
137 if (!$EM_CONF['lockType'] || !strcmp($EM_CONF['lockType'], $loc)) {
138 // check dependencies, act accordingly if ext is loaded
139 list($instExtInfo,) = $extensionList->getInstalledExtensions();
140 $depStatus = $this->checkDependencies($extKey, $EM_CONF, $instExtInfo);
141 if (t3lib_extMgm::isLoaded($extKey) && !$depStatus['returnCode']) {
142 $this->content .= $depStatus['html'];
143 if ($uploadedTempFile) {
144 $this->content .= '<input type="hidden" name="CMD[alreadyUploaded]" value="' . $uploadedTempFile . '" />';
145 }
146 } else {
147 $res = $this->clearAndMakeExtensionDir($fetchData[0], $loc, $dontDelete);
148 if (is_array($res)) {
149 $extDirPath = trim($res[0]);
150 if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath, -1) == '/') {
151
152 $emConfFile = $extensionDetails->construct_ext_emconf_file($extKey, $EM_CONF);
153 $dirs = tx_em_Tools::extractDirsFromFileList(array_keys($fetchData[0]['FILES']));
154
155 $res = tx_em_Tools::createDirsInPath($dirs, $extDirPath);
156 if (!$res) {
157 $writeFiles = $fetchData[0]['FILES'];
158 $writeFiles['ext_emconf.php']['content'] = $emConfFile;
159 $writeFiles['ext_emconf.php']['content_md5'] = md5($emConfFile);
160
161 // Write files:
162 foreach ($writeFiles as $theFile => $fileData) {
163 t3lib_div::writeFile($extDirPath . $theFile, $fileData['content']);
164 if (!@is_file($extDirPath . $theFile)) {
165 $content .= sprintf($GLOBALS['LANG']->getLL('ext_import_file_not_created'),
166 $extDirPath . $theFile) . '<br />';
167 } elseif (md5(t3lib_div::getUrl($extDirPath . $theFile)) != $fileData['content_md5']) {
168 $content .= sprintf($GLOBALS['LANG']->getLL('ext_import_file_corrupted'),
169 $extDirPath . $theFile) . '<br />';
170 }
171 }
172
173 t3lib_div::fixPermissions($extDirPath, TRUE);
174
175 // No content, no errors. Create success output here:
176 if (!$content) {
177 $messageContent = sprintf($GLOBALS['LANG']->getLL('ext_import_success_folder'), $extDirPath) . '<br />';
178
179 $uploadSucceed = true;
180
181 // Fix TYPO3_MOD_PATH for backend modules in extension:
182 $modules = t3lib_div::trimExplode(',', $EM_CONF['module'], 1);
183 if (count($modules)) {
184 foreach ($modules as $mD) {
185 $confFileName = $extDirPath . $mD . '/conf.php';
186 if (@is_file($confFileName)) {
187 $messageContent .= tx_em_Tools::writeTYPO3_MOD_PATH($confFileName, $loc, $extKey . '/' . $mD . '/') . '<br />';
188 } else {
189 $messageContent .= sprintf($GLOBALS['LANG']->getLL('ext_import_no_conf_file'),
190 $confFileName) . '<br />';
191 }
192 }
193 }
194 // 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.
195 // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder).
196
197 // Writing to ext_emconf.php:
198 $sEMD5A = $extensionDetails->serverExtensionMD5array($extKey, array('type' => $loc, 'EM_CONF' => array(), 'files' => array()));
199 $EM_CONF['_md5_values_when_last_written'] = serialize($sEMD5A);
200 $emConfFile = $extensionDetails->construct_ext_emconf_file($extKey, $EM_CONF);
201 t3lib_div::writeFile($extDirPath . 'ext_emconf.php', $emConfFile);
202
203 $messageContent .= 'ext_emconf.php: ' . $extDirPath . 'ext_emconf.php<br />';
204 $messageContent .= $GLOBALS['LANG']->getLL('ext_import_ext_type') . ' ';
205 $messageContent .= $this->typeLabels[$loc] . '<br />';
206 $messageContent .= '<br />';
207
208 // Remove cache files:
209 $updateContent = '';
210 if (t3lib_extMgm::isLoaded($extKey)) {
211 if (t3lib_extMgm::removeCacheFiles()) {
212 $messageContent .= $GLOBALS['LANG']->getLL('ext_import_cache_files_removed') . '<br />';
213 }
214
215 list($new_list) = $this->parentObject->extensionList->getInstalledExtensions();
216 $updateContent = $this->updatesForm($extKey, $new_list[$extKey], 1, t3lib_div::linkThisScript(array(
217 'CMD[showExt]' => $extKey,
218 'SET[singleDetails]' => 'info'
219 )));
220 }
221
222 $flashMessage = t3lib_div::makeInstance(
223 't3lib_FlashMessage',
224 $messageContent,
225 $GLOBALS['LANG']->getLL('ext_import_success')
226 );
227 $content = $flashMessage->render() . $updateContent;
228
229
230 // Install / Uninstall:
231 if (!$this->parentObject->CMD['standAlone']) {
232 $content .= '<h3>' . $GLOBALS['LANG']->getLL('ext_import_install_uninstall') . '</h3>';
233 $content .= $new_list[$extKey] ?
234 '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
235 'CMD[showExt]' => $extKey,
236 'CMD[remove]' => 1,
237 'CMD[clrCmd]' => 1,
238 'SET[singleDetails]' => 'info'
239 ))) . '">' .
240 tx_em_Tools::removeButton() . ' ' . $GLOBALS['LANG']->getLL('ext_import_uninstall') . '</a>' :
241 '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
242 'CMD[showExt]' => $extKey,
243 'CMD[load]' => 1,
244 'CMD[clrCmd]' => 1,
245 'SET[singleDetails]' => 'info'
246 ))) . '">' .
247 tx_em_Tools::installButton() . ' ' . $GLOBALS['LANG']->getLL('ext_import_install') . '</a>';
248 } else {
249 $content = $GLOBALS['LANG']->getLL('ext_import_imported') .
250 '<br /><br /><a href="javascript:opener.top.list.iframe.document.forms[0].submit();window.close();">' .
251 $GLOBALS['LANG']->getLL('ext_import_close_check') . '</a>';
252 }
253 }
254 } else {
255 $content = $res;
256 }
257 } else {
258 $content = sprintf($GLOBALS['LANG']->getLL('ext_import_ext_path_different'), $extDirPath);
259 }
260 } else {
261 $content = $res;
262 }
263 }
264 } else {
265 $content = sprintf($GLOBALS['LANG']->getLL('ext_import_ext_only_here'),
266 tx_em_Tools::typePath($EM_CONF['lockType']), $EM_CONF['lockType']);
267 }
268 } else {
269 $content = $GLOBALS['LANG']->getLL('ext_import_no_ext_key_files');
270 }
271 } else {
272 $content = sprintf($GLOBALS['LANG']->getLL('ext_import_data_transfer'), $fetchData);
273 }
274 } else {
275 $content = sprintf($GLOBALS['LANG']->getLL('ext_import_no_install_here'), tx_em_Tools::typePath($loc));
276 }
277
278 return $content;
279 }
280
281 /**
282 *Check extension dependencies
283 *
284 * @param string $extKey
285 * @param array $conf
286 * @param array $instExtInfo
287 * @return array
288 */
289 function checkDependencies($extKey, $conf, $instExtInfo) {
290 $content = '';
291 $depError = false;
292 $depIgnore = false;
293 $msg = array();
294 $depsolver = t3lib_div::_POST('depsolver');
295
296 if (isset($conf['constraints']['depends']) && is_array($conf['constraints']['depends'])) {
297 foreach ($conf['constraints']['depends'] as $depK => $depV) {
298 if ($depsolver['ignore'][$depK]) {
299 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ignored'),
300 $depK) . '
301 <input type="hidden" value="1" name="depsolver[ignore][' . $depK . ']" />';
302 $depIgnore = true;
303 continue;
304 }
305 if ($depK == 'php') {
306 if (!$depV) {
307 continue;
308 }
309 $versionRange = tx_em_Tools::splitVersionRange($depV);
310 $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!
311 if ($versionRange[0] != '0.0.0' && version_compare($phpv, $versionRange[0], '<')) {
312 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_php_too_low'),
313 $phpv, $versionRange[0]);
314 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
315 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
316 $depError = true;
317 continue;
318 } elseif ($versionRange[1] != '0.0.0' && version_compare($phpv, $versionRange[1], '>')) {
319 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_php_too_high'),
320 $phpv, $versionRange[1]);
321 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
322 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
323 $depError = true;
324 continue;
325 }
326
327 } elseif ($depK == 'typo3') {
328 if (!$depV) {
329 continue;
330 }
331
332 // if the current TYPO3 version is a development version (like TYPO3 4.4-dev),
333 // then it should behave like TYPO3 4.4.0
334 $t3version = TYPO3_version;
335 if (stripos($t3version, '-dev')
336 || stripos($t3version, '-alpha')
337 || stripos($t3version, '-beta')
338 || stripos($t3version, '-RC')) {
339 // find the last occurence of "-" and replace that part with a ".0"
340 $t3version = substr($t3version, 0, strrpos($t3version, '-')) . '.0';
341 }
342
343 $versionRange = tx_em_Tools::splitVersionRange($depV);
344 if ($versionRange[0] != '0.0.0' && version_compare($t3version, $versionRange[0], '<')) {
345 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_typo3_too_low'),
346 $t3version, $versionRange[0]);
347 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
348 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
349 $depError = true;
350 continue;
351 } elseif ($versionRange[1] != '0.0.0' && version_compare($t3version, $versionRange[1], '>')) {
352 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_typo3_too_high'),
353 $t3version, $versionRange[1]);
354 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
355 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
356 $depError = true;
357 continue;
358 }
359 } elseif (strlen($depK) && !t3lib_extMgm::isLoaded($depK)) { // strlen check for braindead empty dependencies coming from extensions...
360 if (!isset($instExtInfo[$depK])) {
361 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_not_available'),
362 $depK);
363 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-import', array('title' => $GLOBALS['LANG']->getLL('checkDependencies_import_ext'))) . '&nbsp;
364 <a href="' . t3lib_div::linkThisUrl($this->parentObject->script, array(
365 'CMD[importExt]' => $depK,
366 'CMD[loc]' => 'L',
367 'CMD[standAlone]' => 1
368 )) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_import_now') . '</a>';
369 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
370 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_ext_requirement') . '</label>';
371 } else {
372 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_not_installed'),
373 $depK, $instExtInfo[$depK]['EM_CONF']['title']);
374 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . tx_em_Tools::installButton() . '&nbsp;
375 <a href="' . t3lib_div::linkThisUrl($this->parentObject->script, array(
376 'CMD[showExt]' => $depK,
377 'CMD[load]' => 1,
378 'CMD[clrCmd]' => 1,
379 'CMD[standAlone]' => 1,
380 'SET[singleDetails]' => 'info'
381 )) .
382 '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_install_now') . '</a>';
383 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
384 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_ext_requirement') . '</label>';
385 }
386 $depError = true;
387 } else {
388 $versionRange = tx_em_Tools::splitVersionRange($depV);
389 if ($versionRange[0] != '0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'], $versionRange[0], '<')) {
390 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_too_low'),
391 $depK, $instExtInfo[$depK]['EM_CONF']['version'], $versionRange[0]);
392 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
393 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
394 $depError = true;
395 continue;
396 } elseif ($versionRange[1] != '0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'], $versionRange[1], '>')) {
397 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_ext_too_high'),
398 $depK, $instExtInfo[$depK]['EM_CONF']['version'], $versionRange[1]);
399 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $depK . ']" id="checkIgnore_' . $depK . '" />
400 <label for="checkIgnore_' . $depK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_requirement') . '</label>';
401 $depError = true;
402 continue;
403 }
404 }
405 }
406 }
407 if ($depError || $depIgnore) {
408 $content .= $GLOBALS['TBE_TEMPLATE']->section(
409 $GLOBALS['LANG']->getLL('removeExtFromList_dependency_error'),
410 implode('<br />', $msg), 0, 1, 2
411 );
412 }
413
414 // Check conflicts with other extensions:
415 $conflictError = false;
416 $conflictIgnore = false;
417 $msg = array();
418
419 if (isset($conf['constraints']['conflicts']) && is_array($conf['constraints']['conflicts'])) {
420 foreach ((array) $conf['constraints']['conflicts'] as $conflictK => $conflictV) {
421 if ($depsolver['ignore'][$conflictK]) {
422 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_conflict_ignored'),
423 $conflictK) . '
424 <input type="hidden" value="1" name="depsolver[ignore][' . $conflictK . ']" />';
425 $conflictIgnore = true;
426 continue;
427 }
428 if (t3lib_extMgm::isLoaded($conflictK)) {
429 $versionRange = tx_em_Tools::splitVersionRange($conflictV);
430 if ($versionRange[0] != '0.0.0' && version_compare($instExtInfo[$conflictK]['EM_CONF']['version'], $versionRange[0], '<')) {
431 continue;
432 }
433 elseif ($versionRange[1] != '0.0.0' && version_compare($instExtInfo[$conflictK]['EM_CONF']['version'], $versionRange[1], '>')) {
434 continue;
435 }
436 $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_conflict_remove'),
437 $extKey, $conflictK, $instExtInfo[$conflictK]['EM_CONF']['title'], $conflictK, $extKey);
438 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . tx_em_Tools::removeButton() . '&nbsp;
439 <a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
440 'CMD[showExt]' => $conflictK,
441 'CMD[remove]' => 1,
442 'CMD[clrCmd]' => 1,
443 'CMD[standAlone]' => 1,
444 'SET[singleDetails]' => 'info'
445 ))) .
446 '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_remove_now') . '</a>';
447 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $conflictK . ']" id="checkIgnore_' . $conflictK . '" />
448 <label for="checkIgnore_' . $conflictK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_conflict') . '</label>';
449 $conflictError = true;
450 }
451 }
452 }
453 if ($conflictError || $conflictIgnore) {
454 $content .= $GLOBALS['TBE_TEMPLATE']->section(
455 $GLOBALS['LANG']->getLL('checkDependencies_conflict_error'), implode('<br />', $msg), 0, 1, 2
456 );
457 }
458
459 // Check suggests on other extensions:
460 if (isset($conf['constraints']['suggests']) && is_array($conf['constraints']['suggests'])) {
461 $suggestion = false;
462 $suggestionIgnore = false;
463 $msg = array();
464 foreach ($conf['constraints']['suggests'] as $suggestK => $suggestV) {
465 if ($depsolver['ignore'][$suggestK]) {
466 $msg[] = '<br />' . sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggestion_ignored'),
467 $suggestK) . '
468 <input type="hidden" value="1" name="depsolver[ignore][' . $suggestK . ']" />';
469 $suggestionIgnore = true;
470 continue;
471 }
472 if (!t3lib_extMgm::isLoaded($suggestK)) {
473 if (!isset($instExtInfo[$suggestK])) {
474 $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggest_import'),
475 $suggestK);
476 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-import', array('title' => $GLOBALS['LANG']->getLL('checkDependencies_import_ext'))) . '&nbsp;
477 <a href="' . t3lib_div::linkThisScript(array(
478 'CMD[importExt]' => $suggestK,
479 'CMD[loc]' => 'L',
480 'CMD[standAlone]' => 1
481 )) . '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_import_now') . '</a>';
482 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $suggestK . ']" id="checkIgnore_' . $suggestK . '" />
483 <label for="checkIgnore_' . $suggestK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_suggestion') . '</label>';
484 } else {
485 $msg[] = sprintf($GLOBALS['LANG']->getLL('checkDependencies_suggest_installation'),
486 $suggestK, $instExtInfo[$suggestK]['EM_CONF']['title']);
487 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;' . tx_em_Tools::installButton() . '&nbsp;
488 <a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
489 'CMD[showExt]' => $suggestK,
490 'CMD[load]' => 1,
491 'CMD[clrCmd]' => 1,
492 'CMD[standAlone]' => 1,
493 'SET[singleDetails]' => 'info'
494 ))) .
495 '" target="_blank">' . $GLOBALS['LANG']->getLL('checkDependencies_install_now') . '</a>';
496 $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore][' . $suggestK . ']" id="checkIgnore_' . $suggestK . '" />
497 <label for="checkIgnore_' . $suggestK . '">' . $GLOBALS['LANG']->getLL('checkDependencies_ignore_suggestion') . '</label>';
498 }
499 $suggestion = true;
500 }
501 }
502 if ($suggestion || $suggestionIgnore) {
503 $content .= $GLOBALS['TBE_TEMPLATE']->section(
504 sprintf($GLOBALS['LANG']->getLL('checkDependencies_exts_suggested_by_ext'), $extKey),
505 implode('<br />', $msg), 0, 1, 1
506 );
507 }
508 }
509
510 if ($depError || $conflictError || $suggestion) {
511 foreach ($this->parentObject->CMD as $k => $v) {
512 $content .= '<input type="hidden" name="CMD[' . $k . ']" value="' . $v . '" />';
513 }
514 $content .= '<br /><br /><input type="submit" value="' . $GLOBALS['LANG']->getLL('checkDependencies_try_again') . '" />';
515
516 return array(
517 'returnCode' => FALSE,
518 'html' => '<form action="' . $this->parentObject->script . '" method="post" name="depform">' . $content . '</form>');
519 }
520
521 return array(
522 'returnCode' => TRUE
523 );
524 }
525
526
527 /**
528 * Delete extension from the file system
529 *
530 * @param string Extension key
531 * @param array Extension info array
532 * @return string Returns message string about the status of the operation
533 */
534 function extDelete($extKey, $extInfo, $command) {
535 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
536 if (t3lib_extMgm::isLoaded($extKey)) {
537 return $GLOBALS['LANG']->getLL('extDelete_ext_active');
538 } elseif (!tx_em_Tools::deleteAsType($extInfo['type'])) {
539 return sprintf($GLOBALS['LANG']->getLL('extDelete_wrong_scope'),
540 $this->typeLabels[$extInfo['type']]
541 );
542 } elseif (t3lib_div::inList('G,L', $extInfo['type'])) {
543 if ($command['doDelete'] && !strcmp($absPath, $command['absPath'])) {
544 $res = $this->removeExtDirectory($absPath);
545 if ($res) {
546 $flashMessage = t3lib_div::makeInstance(
547 't3lib_FlashMessage',
548 nl2br($res),
549 sprintf($GLOBALS['LANG']->getLL('extDelete_remove_dir_failed'), $absPath),
550 t3lib_FlashMessage::ERROR
551 );
552 return $flashMessage->render();
553 } else {
554 $flashMessage = t3lib_div::makeInstance(
555 't3lib_FlashMessage',
556 sprintf($GLOBALS['LANG']->getLL('extDelete_removed'), $absPath),
557 $GLOBALS['LANG']->getLL('extDelete_removed_header'),
558 t3lib_FlashMessage::OK
559 );
560 return $flashMessage->render();
561 }
562 } else {
563 $areYouSure = $GLOBALS['LANG']->getLL('extDelete_sure');
564 $deleteFromServer = $GLOBALS['LANG']->getLL('extDelete_from_server');
565 $onClick = "if (confirm('$areYouSure')) {window.location.href='" . t3lib_div::linkThisScript(array(
566 'CMD[showExt]' => $extKey,
567 'CMD[doDelete]' => 1,
568 'CMD[absPath]' => rawurlencode($absPath)
569 )) . "';}";
570 $content .= '<a class="t3-link" href="#" onclick="' . htmlspecialchars($onClick) .
571 ' return false;"><strong>' . $deleteFromServer . '</strong> ' .
572 sprintf($GLOBALS['LANG']->getLL('extDelete_from_location'),
573 $this->typeLabels[$extInfo['type']],
574 substr($absPath, strlen(PATH_site))
575 ) . '</a>';
576 $content .= '<br /><br />' . $GLOBALS['LANG']->getLL('extDelete_backup');
577 return $content;
578 }
579 } else {
580 return $GLOBALS['LANG']->getLL('extDelete_neither_global_nor_local');
581 }
582 }
583
584 /**
585 * Removes the extension directory (including content)
586 *
587 * @param string Extension directory to remove (with trailing slash)
588 * @param boolean If set, will leave the extension directory
589 * @return boolean False on success, otherwise error string.
590 */
591 function removeExtDirectory($removePath, $removeContentOnly = 0) {
592 $errors = array();
593 if (@is_dir($removePath) && substr($removePath, -1) == '/' && (
594 t3lib_div::isFirstPartOfStr($removePath, tx_em_Tools::typePath('G')) ||
595 t3lib_div::isFirstPartOfStr($removePath, tx_em_Tools::typePath('L')) ||
596 (t3lib_div::isFirstPartOfStr($removePath, tx_em_Tools::typePath('S')) && $this->systemInstall) ||
597 t3lib_div::isFirstPartOfStr($removePath, PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . '_temp_/')) // Playing-around directory...
598 ) {
599
600 // All files in extension directory:
601 $fileArr = t3lib_div::getAllFilesAndFoldersInPath(array(), $removePath, '', 1);
602 if (is_array($fileArr)) {
603
604 // Remove files in dirs:
605 foreach ($fileArr as $removeFile) {
606 if (!@is_dir($removeFile)) {
607 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!
608 @unlink($removeFile);
609 clearstatcache();
610 if (@is_file($removeFile)) {
611 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_could_not_be_deleted'),
612 $removeFile
613 );
614 }
615 } else {
616 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_error_file'),
617 $removeFile, $removePath
618 );
619 }
620 }
621 }
622
623 // Remove directories:
624 $remDirs = tx_em_Tools::extractDirsFromFileList(t3lib_div::removePrefixPathFromList($fileArr, $removePath));
625 $remDirs = array_reverse($remDirs); // Must delete outer directories first...
626 foreach ($remDirs as $removeRelDir) {
627 $removeDir = $removePath . $removeRelDir;
628 if (@is_dir($removeDir)) {
629 @rmdir($removeDir);
630 clearstatcache();
631 if (@is_dir($removeDir)) {
632 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_error_files_left'),
633 $removeDir
634 );
635 }
636 } else {
637 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_error_no_dir'),
638 $removeDir
639 );
640 }
641 }
642
643 // If extension dir should also be removed:
644 if (!$removeContentOnly) {
645 @rmdir($removePath);
646 clearstatcache();
647 if (@is_dir($removePath)) {
648 $errors[] = sprintf($GLOBALS['LANG']->getLL('rmExtDir_error_folders_left'),
649 $removePath
650 );
651 }
652 }
653 } else {
654 $errors[] = $GLOBALS['LANG']->getLL('rmExtDir_error') . ' ' . $fileArr;
655 }
656 } else {
657 $errors[] = $GLOBALS['LANG']->getLL('rmExtDir_error_unallowed_path') . ' ' . $removePath;
658 }
659
660 // Return errors if any:
661 return implode(LF, $errors);
662 }
663
664 /**
665 * Validates the database according to extension requirements
666 * Prints form for changes if any. If none, returns blank. If an update is ordered, empty is returned as well.
667 * DBAL compliant (based on Install Tool code)
668 *
669 * @param string Extension key
670 * @param array Extension information array
671 * @param boolean If true, returns array with info.
672 * @return mixed If $infoOnly, returns array with information. Otherwise performs update.
673 */
674 function checkDBupdates($extKey, $extInfo, $infoOnly = 0) {
675
676
677 $dbStatus = array();
678
679 // Updating tables and fields?
680 if (is_array($extInfo['files']) && in_array('ext_tables.sql', $extInfo['files'])) {
681 $fileContent = t3lib_div::getUrl(tx_em_Tools::getExtPath($extKey, $extInfo['type']) . 'ext_tables.sql');
682
683 $FDfile = $this->install->getFieldDefinitions_fileContent($fileContent);
684 if (count($FDfile)) {
685 $FDdb = $this->install->getFieldDefinitions_database(TYPO3_db);
686 $diff = $this->install->getDatabaseExtra($FDfile, $FDdb);
687 $update_statements = $this->install->getUpdateSuggestions($diff);
688
689 $dbStatus['structure']['tables_fields'] = $FDfile;
690 $dbStatus['structure']['diff'] = $diff;
691
692 // Updating database...
693 if (!$infoOnly && is_array($this->install->INSTALL['database_update'])) {
694 $this->install->performUpdateQueries($update_statements['add'], $this->install->INSTALL['database_update']);
695 $this->install->performUpdateQueries($update_statements['change'], $this->install->INSTALL['database_update']);
696 $this->install->performUpdateQueries($update_statements['create_table'], $this->install->INSTALL['database_update']);
697 } else {
698 $content .= $this->install->generateUpdateDatabaseForm_checkboxes(
699 $update_statements['add'], $GLOBALS['LANG']->getLL('checkDBupdates_add_fields'));
700 $content .= $this->install->generateUpdateDatabaseForm_checkboxes(
701 $update_statements['change'], $GLOBALS['LANG']->getLL('checkDBupdates_changing_fields'), 1, 0, $update_statements['change_currentValue']);
702 $content .= $this->install->generateUpdateDatabaseForm_checkboxes(
703 $update_statements['create_table'], $GLOBALS['LANG']->getLL('checkDBupdates_add_tables'));
704 }
705 }
706 }
707
708 // Importing static tables?
709 if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql', $extInfo['files'])) {
710 $fileContent = t3lib_div::getUrl(tx_em_Tools::getExtPath($extKey, $extInfo['type']) . 'ext_tables_static+adt.sql');
711
712 $statements = $this->install->getStatementarray($fileContent, 1);
713 list($statements_table, $insertCount) = $this->install->getCreateTables($statements, 1);
714
715 // Execute import of static table content:
716 if (!$infoOnly && is_array($this->install->INSTALL['database_import'])) {
717
718 // Traverse the tables
719 foreach ($this->install->INSTALL['database_import'] as $table => $md5str) {
720 if ($md5str == md5($statements_table[$table])) {
721 $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS ' . $table);
722 $GLOBALS['TYPO3_DB']->admin_query($statements_table[$table]);
723
724 if ($insertCount[$table]) {
725 $statements_insert = $this->install->getTableInsertStatements($statements, $table);
726
727 foreach ($statements_insert as $v) {
728 $GLOBALS['TYPO3_DB']->admin_query($v);
729 }
730 }
731 }
732 }
733 } else {
734 $whichTables = $this->install->getListOfTables();
735 if (count($statements_table)) {
736 $out = '';
737 foreach ($statements_table as $table => $definition) {
738 $exist = isset($whichTables[$table]);
739
740 $dbStatus['static'][$table]['exists'] = $exist;
741 $dbStatus['static'][$table]['count'] = $insertCount[$table];
742
743 $out .= '<tr>
744 <td><input type="checkbox" name="TYPO3_INSTALL[database_import][' . $table . ']" checked="checked" value="' . md5($definition) . '" /></td>
745 <td><strong>' . $table . '</strong></td>
746 <td><img src="clear.gif" width="10" height="1" alt="" /></td>
747 <td nowrap="nowrap">' .
748 ($insertCount[$table] ?
749 $GLOBALS['LANG']->getLL('checkDBupdates_rows') . ' ' . $insertCount[$table]
750 : '') .
751 '</td>
752 <td><img src="clear.gif" width="10" height="1" alt="" /></td>
753 <td nowrap="nowrap">' .
754 ($exist ?
755 t3lib_iconWorks::getSpriteIcon('status-dialog-warning') .
756 $GLOBALS['LANG']->getLL('checkDBupdates_table_exists')
757 : '') .
758 '</td>
759 </tr>';
760 }
761 $content .= '
762 <br />
763 <h3>' . $GLOBALS['LANG']->getLL('checkDBupdates_import_static_data') . '</h3>
764 <table border="0" cellpadding="0" cellspacing="0">' . $out . '</table>
765 ';
766 }
767 }
768 }
769
770 // Return array of information if $infoOnly, otherwise content.
771 return $infoOnly ? $dbStatus : $content;
772 }
773
774 /**
775 * Removes the current extension of $type and creates the base folder for the new one (which is going to be imported)
776 *
777 * @param array Data for imported extension
778 * @param string Extension installation scope (L,G,S)
779 * @param boolean If set, nothing will be deleted (neither directory nor files)
780 * @return mixed Returns array on success (with extension directory), otherwise an error string.
781 */
782 function clearAndMakeExtensionDir($importedData, $type, $dontDelete = 0) {
783 if (!$importedData['extKey']) {
784 return $GLOBALS['LANG']->getLL('clearMakeExtDir_no_ext_key');
785 }
786
787 // Setting install path (L, G, S or fileadmin/_temp_/)
788 $path = '';
789 switch ((string) $type) {
790 case 'G':
791 case 'L':
792 $path = tx_em_Tools::typePath($type);
793 $suffix = '';
794
795 // Creates the typo3conf/ext/ directory if it does NOT already exist:
796 if ((string) $type == 'L' && !@is_dir($path)) {
797 t3lib_div::mkdir($path);
798 }
799 break;
800 default:
801 if ($this->systemInstall && (string) $type == 'S') {
802 $path = tx_em_Tools::typePath($type);
803 $suffix = '';
804 } else {
805 $path = PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . '_temp_/';
806 $suffix = '_' . date('dmy-His');
807 }
808 break;
809 }
810
811 // If the install path is OK...
812 if ($path && @is_dir($path)) {
813
814 // Set extension directory:
815 $extDirPath = $path . $importedData['extKey'] . $suffix . '/';
816
817 // Install dir was found, remove it then:
818 if (@is_dir($extDirPath)) {
819 if ($dontDelete) {
820 return array($extDirPath);
821 }
822 $res = $this->removeExtDirectory($extDirPath);
823 if ($res) {
824 $flashMessage = t3lib_div::makeInstance(
825 't3lib_FlashMessage',
826 nl2br($res),
827 sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_could_not_remove_dir'), $extDirPath),
828 t3lib_FlashMessage::ERROR
829 );
830 return $flashMessage->render();
831 }
832 }
833
834 // We go create...
835 t3lib_div::mkdir($extDirPath);
836 if (!is_dir($extDirPath)) {
837 return sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_could_not_create_dir'),
838 $extDirPath);
839 }
840 return array($extDirPath);
841 } else {
842 return sprintf($GLOBALS['LANG']->getLL('clearMakeExtDir_no_dir'),
843 $path);
844 }
845 }
846
847
848 /*******************************
849 *
850 * Extension analyzing (detailed information)
851 *
852 ******************************/
853
854 /**
855 * Perform a detailed, technical analysis of the available extension on server!
856 * Includes all kinds of verifications
857 * Takes some time to process, therfore use with care, in particular in listings.
858 *
859 * @param string Extension key
860 * @param array Extension information
861 * @param boolean If set, checks for validity of classes etc.
862 * @return array Information in an array.
863 */
864 function makeDetailedExtensionAnalysis($extKey, $extInfo, $validity = 0) {
865
866 // Get absolute path of the extension
867 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
868 $extensionDetails = t3lib_div::makeInstance('tx_em_Extensions_Details', $this);
869 $infoArray = array();
870
871 $table_class_prefix = substr($extKey, 0, 5) == 'user_' ? 'user_' : 'tx_' . str_replace('_', '', $extKey) . '_';
872 $module_prefix = substr($extKey, 0, 5) == 'user_' ? 'u' : 'tx' . str_replace('_', '', $extKey);
873
874 // Database status:
875 $dbInfo = $this->checkDBupdates($extKey, $extInfo, 1);
876
877 // Database structure required:
878 if (is_array($dbInfo['structure']['tables_fields'])) {
879 $modify_tables = t3lib_div::trimExplode(',', $extInfo['EM_CONF']['modify_tables'], 1);
880 $infoArray['dump_tf'] = array();
881
882 foreach ($dbInfo['structure']['tables_fields'] as $tN => $d) {
883 if (in_array($tN, $modify_tables)) {
884 $infoArray['fields'][] = $tN . ': <i>' .
885 (is_array($d['fields']) ? implode(', ', array_keys($d['fields'])) : '') .
886 (is_array($d['keys']) ?
887 ' + ' . count($d['keys']) . ' ' . $GLOBALS['LANG']->getLL('detailedExtAnalysis_keys') : '') .
888 '</i>';
889 if (is_array($d['fields'])) {
890 foreach ($d['fields'] as $fN => $value) {
891 $infoArray['dump_tf'][] = $tN . '.' . $fN;
892 if (!t3lib_div::isFirstPartOfStr($fN, $table_class_prefix)) {
893 $infoArray['NSerrors']['fields'][$fN] = $fN;
894 } else {
895 $infoArray['NSok']['fields'][$fN] = $fN;
896 }
897 }
898 }
899 if (is_array($d['keys'])) {
900 foreach ($d['keys'] as $fN => $value) {
901 $infoArray['dump_tf'][] = $tN . '.KEY:' . $fN;
902 }
903 }
904 } else {
905 $infoArray['dump_tf'][] = $tN;
906 $infoArray['tables'][] = $tN;
907 if (!t3lib_div::isFirstPartOfStr($tN, $table_class_prefix)) {
908 $infoArray['NSerrors']['tables'][$tN] = $tN;
909 } else {
910 $infoArray['NSok']['tables'][$tN] = $tN;
911 }
912 }
913 }
914 if (count($dbInfo['structure']['diff']['diff']) || count($dbInfo['structure']['diff']['extra'])) {
915 $msg = array();
916 if (count($dbInfo['structure']['diff']['diff'])) {
917 $msg[] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_tables_are_missing');
918 }
919 if (count($dbInfo['structure']['diff']['extra'])) {
920 $msg[] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_tables_are_of_wrong_type');
921 }
922 $infoArray['tables_error'] = 1;
923 if (t3lib_extMgm::isLoaded($extKey)) {
924 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_tables_are'),
925 implode(' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:and') . ' ', $msg)
926 );
927 }
928 }
929 }
930
931 // Static tables?
932 if (is_array($dbInfo['static'])) {
933 $infoArray['static'] = array_keys($dbInfo['static']);
934
935 foreach ($dbInfo['static'] as $tN => $d) {
936 if (!$d['exists']) {
937 $infoArray['static_error'] = 1;
938 if (t3lib_extMgm::isLoaded($extKey)) {
939 $infoArray['errors'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_static_tables_missing');
940 }
941 if (!t3lib_div::isFirstPartOfStr($tN, $table_class_prefix)) {
942 $infoArray['NSerrors']['tables'][$tN] = $tN;
943 } else {
944 $infoArray['NSok']['tables'][$tN] = $tN;
945 }
946 }
947 }
948 }
949
950 // Backend Module-check:
951 $knownModuleList = t3lib_div::trimExplode(',', $extInfo['EM_CONF']['module'], 1);
952 foreach ($knownModuleList as $mod) {
953 if (@is_dir($absPath . $mod)) {
954 if (@is_file($absPath . $mod . '/conf.php')) {
955 $confFileInfo = $extensionDetails->modConfFileAnalysis($absPath . $mod . '/conf.php');
956 if (is_array($confFileInfo['TYPO3_MOD_PATH'])) {
957 $shouldBePath = $this->typeRelPaths[$extInfo['type']] . $extKey . '/' . $mod . '/';
958 if (strcmp($confFileInfo['TYPO3_MOD_PATH'][1][1], $shouldBePath)) {
959 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_wrong_mod_path'),
960 $confFileInfo['TYPO3_MOD_PATH'][1][1],
961 $shouldBePath
962 );
963 }
964 } else {
965 // It seems like TYPO3_MOD_PATH and therefore also this warning is no longer needed.
966 // $infoArray['errors'][] = 'No definition of TYPO3_MOD_PATH constant found inside!';
967 }
968 if (is_array($confFileInfo['MCONF_name'])) {
969 $mName = $confFileInfo['MCONF_name'][1][1];
970 $mNameParts = explode('_', $mName);
971 $infoArray['moduleNames'][] = $mName;
972 if (!t3lib_div::isFirstPartOfStr($mNameParts[0], $module_prefix) &&
973 (!$mNameParts[1] || !t3lib_div::isFirstPartOfStr($mNameParts[1], $module_prefix))) {
974 $infoArray['NSerrors']['modname'][] = $mName;
975 } else {
976 $infoArray['NSok']['modname'][] = $mName;
977 }
978 } else {
979 $infoArray['errors'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_mconf_missing');
980 }
981 } else {
982 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_be_module_conf_missing'),
983 $mod . '/conf.php'
984 );
985 }
986 } else {
987 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_module_folder_missing'),
988 $mod . '/'
989 );
990 }
991 }
992 $dirs = t3lib_div::get_dirs($absPath);
993 if (is_array($dirs)) {
994 reset($dirs);
995 while (list(, $mod) = each($dirs)) {
996 if (!in_array($mod, $knownModuleList) && @is_file($absPath . $mod . '/conf.php')) {
997 $confFileInfo = $extensionDetails->modConfFileAnalysis($absPath . $mod . '/conf.php');
998 if (is_array($confFileInfo)) {
999 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_unconfigured_module'),
1000 $mod . '/conf.php'
1001 );
1002 }
1003 }
1004 }
1005 }
1006
1007 // ext_tables.php:
1008 if (@is_file($absPath . 'ext_tables.php')) {
1009 $content = t3lib_div::getUrl($absPath . 'ext_tables.php');
1010 if (stristr($content, 't3lib_extMgm::addModule')) {
1011 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_module');
1012 }
1013 if (stristr($content, 't3lib_extMgm::insertModuleFunction')) {
1014 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_module_and_more');
1015 }
1016 if (stristr($content, 't3lib_div::loadTCA')) {
1017 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_loadTCA');
1018 }
1019 if (stristr($content, '$TCA[')) {
1020 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_TCA');
1021 }
1022 if (stristr($content, 't3lib_extMgm::addPlugin')) {
1023 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_plugin');
1024 }
1025 }
1026
1027 // ext_localconf.php:
1028 if (@is_file($absPath . 'ext_localconf.php')) {
1029 $content = t3lib_div::getUrl($absPath . 'ext_localconf.php');
1030 if (stristr($content, 't3lib_extMgm::addPItoST43')) {
1031 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_plugin_st43');
1032 }
1033 if (stristr($content, 't3lib_extMgm::addPageTSConfig')) {
1034 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_page_ts');
1035 }
1036 if (stristr($content, 't3lib_extMgm::addUserTSConfig')) {
1037 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_user_ts');
1038 }
1039 if (stristr($content, 't3lib_extMgm::addTypoScriptSetup')) {
1040 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_ts_setup');
1041 }
1042 if (stristr($content, 't3lib_extMgm::addTypoScriptConstants')) {
1043 $infoArray['flags'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_ts_constants');
1044 }
1045 }
1046
1047 if (@is_file($absPath . 'ext_typoscript_constants.txt')) {
1048 $infoArray['TSfiles'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_constants');
1049 }
1050 if (@is_file($absPath . 'ext_typoscript_setup.txt')) {
1051 $infoArray['TSfiles'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_setup');
1052 }
1053 if (@is_file($absPath . 'ext_conf_template.txt')) {
1054 $infoArray['conf'] = 1;
1055 }
1056
1057 // Classes:
1058 if ($validity) {
1059 $filesInside = tx_em_Tools::getClassIndexLocallangFiles($absPath, $table_class_prefix, $extKey);
1060 if (is_array($filesInside['errors'])) {
1061 $infoArray['errors'] = array_merge((array) $infoArray['errors'], $filesInside['errors']);
1062 }
1063 if (is_array($filesInside['NSerrors'])) {
1064 $infoArray['NSerrors'] = array_merge((array) $infoArray['NSerrors'], $filesInside['NSerrors']);
1065 }
1066 if (is_array($filesInside['NSok'])) {
1067 $infoArray['NSok'] = array_merge((array) $infoArray['NSok'], $filesInside['NSok']);
1068 }
1069 $infoArray['locallang'] = $filesInside['locallang'];
1070 $infoArray['classes'] = $filesInside['classes'];
1071 }
1072
1073 // Upload folders
1074 if ($extInfo['EM_CONF']['uploadfolder']) {
1075 $infoArray['uploadfolder'] = tx_em_Tools::uploadFolder($extKey);
1076 if (!@is_dir(PATH_site . $infoArray['uploadfolder'])) {
1077 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_no_upload_folder'),
1078 $infoArray['uploadfolder']
1079 );
1080 $infoArray['uploadfolder'] = '';
1081 }
1082 }
1083
1084 // Create directories:
1085 if ($extInfo['EM_CONF']['createDirs']) {
1086 $infoArray['createDirs'] = array_unique(t3lib_div::trimExplode(',', $extInfo['EM_CONF']['createDirs'], 1));
1087 foreach ($infoArray['createDirs'] as $crDir) {
1088 if (!@is_dir(PATH_site . $crDir)) {
1089 $infoArray['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_no_upload_folder'),
1090 $crDir
1091 );
1092 }
1093 }
1094 }
1095
1096 // Return result array:
1097 return $infoArray;
1098 }
1099
1100
1101 /**
1102 * Produces the config form for an extension (if any template file, ext_conf_template.txt is found)
1103 *
1104 * @param string Extension key
1105 * @param array Extension information array
1106 * @param boolean If true, the form HTML content is returned, otherwise the content is set in $this->content.
1107 * @param string Submit-to URL (supposedly)
1108 * @param string Additional form fields to include.
1109 * @return string Depending on $output. Can return the whole form.
1110 */
1111 function tsStyleConfigForm($extKey, $extInfo, $output = 0, $script = '', $addFields = '') {
1112 global $TYPO3_CONF_VARS;
1113
1114 // Initialize:
1115 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
1116 $relPath = $this->typeRelPaths[$extInfo['type']] . $extKey . '/';
1117
1118 // Look for template file for form:
1119 if (t3lib_extMgm::isLoaded($extKey) && @is_file($absPath . 'ext_conf_template.txt')) {
1120
1121 // Load tsStyleConfig class and parse configuration template:
1122 $tsStyleConfig = t3lib_div::makeInstance('t3lib_tsStyleConfig');
1123 $tsStyleConfig->doNotSortCategoriesBeforeMakingForm = TRUE;
1124 $theConstants = $tsStyleConfig->ext_initTSstyleConfig(
1125 t3lib_div::getUrl($absPath . 'ext_conf_template.txt'),
1126 $relPath,
1127 $absPath,
1128 $GLOBALS['BACK_PATH']
1129 );
1130
1131 // Load the list of resources.
1132 $tsStyleConfig->ext_loadResources($absPath . 'res/');
1133
1134 // Load current value:
1135 $arr = unserialize($TYPO3_CONF_VARS['EXT']['extConf'][$extKey]);
1136 $arr = is_array($arr) ? $arr : array();
1137
1138 // Call processing function for constants config and data before write and form rendering:
1139 if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'])) {
1140 $_params = array('fields' => &$theConstants, 'data' => &$arr, 'extKey' => $extKey);
1141 foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'] as $_funcRef) {
1142 t3lib_div::callUserFunction($_funcRef, $_params, $this);
1143 }
1144 unset($_params);
1145 }
1146
1147 // If saving operation is done:
1148 if (t3lib_div::_POST('submit')) {
1149 $tsStyleConfig->ext_procesInput(t3lib_div::_POST(), array(), $theConstants, array());
1150 $arr = $tsStyleConfig->ext_mergeIncomingWithExisting($arr);
1151 $this->writeTsStyleConfig($extKey, $arr);
1152 }
1153
1154 // Setting value array
1155 $tsStyleConfig->ext_setValuearray($theConstants, $arr);
1156
1157 // Getting session data:
1158 $MOD_MENU = array();
1159 $MOD_MENU['constant_editor_cat'] = $tsStyleConfig->ext_getCategoriesForModMenu();
1160 $MOD_SETTINGS = t3lib_BEfunc::getModuleData($MOD_MENU, t3lib_div::_GP('SET'), 'xMod_test');
1161 /*
1162 // Resetting the menu (stop)
1163 if (count($MOD_MENU['constant_editor_cat']) > 1) {
1164 $menu = $GLOBALS['LANG']->getLL('extInfoArray_category') . ' ' .
1165 t3lib_BEfunc::getFuncMenu(0, 'SET[constant_editor_cat]', $MOD_SETTINGS['constant_editor_cat'], $MOD_MENU['constant_editor_cat'], '', '&CMD[showExt]=' . $extKey);
1166 $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>');
1167 $this->content.=$this->doc->spacer(10);
1168 }
1169 */
1170 // Category and constant editor config:
1171 $form = '
1172 <table border="0" cellpadding="0" cellspacing="0" width="600">
1173 <tr>
1174 <td>' . $tsStyleConfig->ext_getForm($MOD_SETTINGS['constant_editor_cat'], $theConstants, $script, $addFields) . '</form></td>
1175 </tr>
1176 </table>';
1177 } else {
1178 $flashMessage = t3lib_div::makeInstance(
1179 't3lib_FlashMessage',
1180 $GLOBALS['LANG']->getLL('tsStyleConfigForm_additional_config'),
1181 '',
1182 t3lib_FlashMessage::INFO
1183 );
1184
1185 $form = '
1186 <table border="0" cellpadding="0" cellspacing="0" width="600">
1187 <tr>
1188 <td>
1189 <form action="' . htmlspecialchars($script) . '" method="post">' .
1190 $addFields .
1191 $flashMessage->render() .
1192 '<br /><input type="submit" name="write" value="' . $GLOBALS['LANG']->getLL('updatesForm_make_updates') . '" />
1193 </form>
1194 </td>
1195 </tr>
1196 </table>';
1197 }
1198
1199 #if ($output) {
1200 return $form;
1201 #} else {
1202 # $this->content.=$this->doc->section('', $form);
1203 #}
1204
1205
1206 }
1207
1208 /**
1209 * Writes the TSstyleconf values to "localconf.php"
1210 * Removes the temp_CACHED* files before return.
1211 *
1212 * @param string Extension key
1213 * @param array Configuration array to write back
1214 * @return void
1215 */
1216 function writeTsStyleConfig($extKey, $arr) {
1217
1218 // Instance of install tool
1219 $instObj = new t3lib_install;
1220 $instObj->allowUpdateLocalConf = 1;
1221 $instObj->updateIdentity = 'TYPO3 Extension Manager';
1222
1223 // Get lines from localconf file
1224 $lines = $instObj->writeToLocalconf_control();
1225 $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extConf\'][\'' . $extKey . '\']', serialize($arr)); // This will be saved only if there are no linebreaks in it !
1226 $instObj->writeToLocalconf_control($lines);
1227
1228 t3lib_extMgm::removeCacheFiles();
1229 }
1230
1231
1232 /**
1233 * Creates a form for an extension which contains all options for configuration, updates of database, clearing of cache etc.
1234 * This form is shown when
1235 *
1236 * @param string Extension key
1237 * @param array Extension information array
1238 * @param boolean If set, the form will ONLY show if fields/tables should be updated (suppressing forms like general configuration and cache clearing).
1239 * @param string Alternative action=""-script
1240 * @param string HTML: Additional form fields
1241 * @return string HTML
1242 */
1243 function updatesForm($extKey, $extInfo, $notSilent = 0, $script = '', $addFields = '', $addForm = TRUE) {
1244 $script = $script ? $script : t3lib_div::linkThisScript();
1245 if ($addForm) {
1246 $formWrap = array('<form action="' . htmlspecialchars($script) . '" method="POST">', '</form>');
1247 } else {
1248 $formWrap = array('', '');
1249 }
1250 $extensionDetails = t3lib_div::makeInstance('tx_em_Extensions_Details', $this);
1251
1252 $updates .= $this->checkDBupdates($extKey, $extInfo);
1253 $uCache = $this->checkClearCache($extInfo);
1254 if ($notSilent) {
1255 $updates .= $uCache;
1256 }
1257 $updates .= $extensionDetails->checkUploadFolder($extKey, $extInfo);
1258
1259 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
1260 if ($notSilent && @is_file($absPath . 'ext_conf_template.txt')) {
1261 $configForm = $this->tsStyleConfigForm($extKey, $extInfo, 1, $script, $updates . $addFields . '<br />');
1262 }
1263
1264 if ($updates || $configForm) {
1265 if ($configForm) {
1266 $updates = $configForm;
1267 } else {
1268 $updates = $formWrap[0] . $updates . $addFields . '
1269 <br /><input type="submit" name="write" id="update-submit-' . $extKey . '" value="' . $GLOBALS['LANG']->getLL('updatesForm_make_updates') . '" />
1270 ' . $formWrap[1];
1271 }
1272 }
1273
1274 return $updates;
1275 }
1276
1277
1278 /**
1279 * Check if clear-cache should be performed, otherwise show form (for installation of extension)
1280 * Shown only if the extension has the clearCacheOnLoad flag set.
1281 *
1282 * @param string Extension key
1283 * @param array Extension information array
1284 * @return string HTML output (if form is shown)
1285 */
1286 function checkClearCache($extInfo) {
1287 if ($extInfo['EM_CONF']['clearCacheOnLoad']) {
1288 if (t3lib_div::_POST('_clear_all_cache')) { // Action: Clearing the cache
1289 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
1290 $tce->stripslashes_values = 0;
1291 $tce->start(array(), array());
1292 $tce->clear_cacheCmd('all');
1293 } else { // Show checkbox for clearing cache:
1294 $content .= '
1295 <br />
1296 <h3>' . $GLOBALS['LANG']->getLL('checkUploadFolder_clear_cache') . '</h3>
1297 <p>' . $GLOBALS['LANG']->getLL('checkUploadFolder_clear_cache_requested') . '<br />
1298 <label for="check_clear_all_cache">' . $GLOBALS['LANG']->getLL('checkUploadFolder_clear_all_cache') . '</label>
1299 <input type="checkbox" name="_clear_all_cache" id="check_clear_all_cache" checked="checked" value="1" /><br />
1300 </p>
1301 ';
1302 }
1303 }
1304 return $content;
1305 }
1306
1307 }
1308
1309 ?>