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