Fixed bug #16526: EM resolve dependencies by moving common objects to API class
[Packages/TYPO3.CMS.git] / typo3 / sysext / em / classes / extensions / class.tx_em_extensions_details.php
1 <?php
2 /* **************************************************************
3 * Copyright notice
4 *
5 * (c) webservices.nl
6 * (c) 2006-2010 Karsten Dambekalns <karsten@typo3.org>
7 * (c) 2010 Steffen Kamper <steffen@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /* $Id: class.tx_em_extensions_details.php 2058 2010-03-17 09:39:15Z steffenk $ */
30
31 /**
32 * This class handles extension details
33 *
34 */
35
36 class tx_em_Extensions_Details {
37
38 protected $maxUploadSize = 31457280;
39 protected $descrTable = '_MOD_tools_em';
40 protected $parentObject;
41
42 /**
43 * Instance of EM API
44 *
45 * @var tx_em_API
46 */
47 protected $api;
48
49 /**
50 * Class for install extensions
51 *
52 * @var em_install
53 */
54 public $install;
55
56 /**
57 * Constructor
58 *
59 * @param object $parentObject
60 */
61 public function __construct($parentObject = NULL) {
62 $this->parentObject = $parentObject;
63 $this->api = t3lib_div::makeInstance('tx_em_API');
64 $this->install = t3lib_div::makeInstance('tx_em_Install', $this);
65 $GLOBALS['LANG']->includeLLFile(t3lib_extMgm::extPath('em') . 'language/locallang.xml');
66 }
67
68
69 /**
70 * Reads $confFilePath (a module $conf-file) and returns information on the existence of TYPO3_MOD_PATH definition and MCONF_name
71 *
72 * @param string Absolute path to a "conf.php" file of a module which we are analysing.
73 * @return array Information found.
74 * @see writeTYPO3_MOD_PATH()
75 */
76 function modConfFileAnalysis($confFilePath) {
77 $lines = explode(LF, t3lib_div::getUrl($confFilePath));
78 $confFileInfo = array();
79 $confFileInfo['lines'] = $lines;
80 $reg = array();
81
82 foreach ($lines as $k => $l) {
83 $line = trim($l);
84
85 unset($reg);
86 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/', $line, $reg)) {
87 $confFileInfo['TYPO3_MOD_PATH'] = array($k, $reg);
88 }
89
90 unset($reg);
91 if (preg_match('/^\$MCONF\[["\']?name["\']?\][[:space:]]*=[[:space:]]*["\']([[:alnum:]_]+)["\'];/', $line, $reg)) {
92 $confFileInfo['MCONF_name'] = array($k, $reg);
93 }
94 }
95 return $confFileInfo;
96 }
97
98 /**
99 * Check if upload folder / "createDir" directories should be created.
100 *
101 * @param string Extension key
102 * @param array Extension information array
103 * @return string HTML content.
104 */
105 function checkUploadFolder($extKey, $extInfo) {
106
107 // Checking for upload folder:
108 $uploadFolder = PATH_site . tx_em_Tools::uploadFolder($extKey);
109 if ($extInfo['EM_CONF']['uploadfolder'] && !@is_dir($uploadFolder)) {
110 if (t3lib_div::_POST('_uploadfolder')) { // CREATE dir:
111 t3lib_div::mkdir($uploadFolder);
112 $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
113 <HTML>
114 <HEAD>
115 <TITLE></TITLE>
116 <META http-equiv=Refresh Content="0; Url=../../">
117 </HEAD>
118 </HTML>';
119 t3lib_div::writeFile($uploadFolder . 'index.html', $indexContent);
120 } else { // Show checkbox / HTML for creation:
121 $content .= '
122 <br /><h3>' . $GLOBALS['LANG']->getLL('checkUploadFolder_create_upload_folder') . '</h3>
123 <p>' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_upload_folder_needed'),
124 tx_em_Tools::uploadFolder($extKey)
125 ) . '<br />
126 <label for="check_uploadfolder">' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_create_dir'),
127 tx_em_Tools::uploadFolder($extKey)
128 ) . '</label>
129 <input type="checkbox" name="_uploadfolder" id="check_uploadfolder" checked="checked" value="1" /><br />
130 </p>
131 ';
132 }
133 }
134
135 // Additional directories that should be created:
136 if ($extInfo['EM_CONF']['createDirs']) {
137 $createDirs = array_unique(t3lib_div::trimExplode(',', $extInfo['EM_CONF']['createDirs'], 1));
138
139 foreach ($createDirs as $crDir) {
140 if (!@is_dir(PATH_site . $crDir)) {
141 if (t3lib_div::_POST('_createDir_' . md5($crDir))) { // CREATE dir:
142
143 // Initialize:
144 $crDirStart = '';
145 $dirs_in_path = explode('/', preg_replace('/\/$/', '', $crDir));
146
147 // Traverse each part of the dir path and create it one-by-one:
148 foreach ($dirs_in_path as $dirP) {
149 if (strcmp($dirP, '')) {
150 $crDirStart .= $dirP . '/';
151 if (!@is_dir(PATH_site . $crDirStart)) {
152 t3lib_div::mkdir(PATH_site . $crDirStart);
153 $finalDir = PATH_site . $crDirStart;
154 }
155 } else {
156 throw new RuntimeException(
157 'TYPO3 Fatal Error: ' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_error'), PATH_site . $crDir),
158 1270853982
159 );
160 }
161 }
162 if ($finalDir) {
163 $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
164 <HTML>
165 <HEAD>
166 <TITLE></TITLE>
167 <META http-equiv=Refresh Content="0; Url=/">
168 </HEAD>
169 </HTML>';
170 t3lib_div::writeFile($finalDir . 'index.html', $indexContent);
171 }
172 } else { // Show checkbox / HTML for creation:
173 $md5CrDir = md5($crDir);
174 $content .= '
175 <br />
176 <h3>' . $GLOBALS['LANG']->getLL('checkUploadFolder_create_folder') . '</h3>
177 <p>' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_folder_needed'),
178 $crDir
179 ) . '<br />
180 <label for="check_createDir_' . $md5CrDir . '">' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_create_dir'),
181 $crDir
182 ) . '</label>
183 <input type="checkbox" name="_createDir_' . $md5CrDir . '" id="check_createDir_' . $md5CrDir . '" checked="checked" value="1" /><br />
184 </p>
185 ';
186 }
187 }
188 }
189 }
190
191 return $content;
192 }
193
194
195 /**
196 * Processes return-data from online repository.
197 * Currently only the returned emconf array is written to extension.
198 *
199 * @param array Command array returned from TER
200 * @return string Message
201 */
202 function uploadExtensionToTER($em) {
203 $msg = '';
204 $response = $this->parentObject->terConnection->uploadToTER($em);
205
206 if (!is_array($response)) {
207 return $response;
208 }
209
210 if ($response['resultCode'] == TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED) {
211 $em['extInfo']['EM_CONF']['version'] = $response['version'];
212 $response['resultMessages'][] = sprintf($GLOBALS['LANG']->getLL('terCommunication_ext_version'),
213 $response['version']
214 );
215 $response['resultMessages'][] = $this->updateLocalEM_CONF($em['extKey'], $em['extInfo']);
216 }
217
218 $msg = '<ul><li>' . implode('</li><li>', $response['resultMessages']) . '</li></ul>';
219 return $msg;
220 }
221
222 /**
223 * Forces update of local EM_CONF. This will renew the information of changed files.
224 *
225 * @param string Extension key
226 * @param array Extension information array
227 * @return string Status message
228 */
229 function updateLocalEM_CONF($extKey, $extInfo) {
230 $extInfo['EM_CONF']['_md5_values_when_last_written'] = serialize($this->serverExtensionMD5array($extKey, $extInfo));
231 $emConfFileContent = $this->construct_ext_emconf_file($extKey, $extInfo['EM_CONF']);
232
233 $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
234 $emConfFileName = $absPath . 'ext_emconf.php';
235 if ($emConfFileContent) {
236
237 if (@is_file($emConfFileName)) {
238 if (t3lib_div::writeFile($emConfFileName, $emConfFileContent) === true) {
239 return sprintf($GLOBALS['LANG']->getLL('updateLocalEM_CONF_ok'),
240 substr($emConfFileName, strlen($absPath)));
241 } else {
242 return '<strong>' . sprintf($GLOBALS['LANG']->getLL('updateLocalEM_CONF_not_writable'),
243 $emConfFileName) . '</strong>';
244 }
245 } else {
246 return ('<strong>' . sprintf($GLOBALS['LANG']->getLL('updateLocalEM_CONF_not_found'),
247 $emConfFileName) . '</strong>');
248 }
249 } else {
250 return sprintf($GLOBALS['LANG']->getLL('updateLocalEM_CONF_no_content'),
251 substr($emConfFileName, strlen($absPath)));
252 }
253 }
254
255 /**
256 * Creates a MD5-hash array over the current files in the extension
257 *
258 * @param string Extension key
259 * @param array Extension information array
260 * @return array MD5-keys
261 */
262 function serverExtensionMD5array($extKey, $conf) {
263
264 // Creates upload-array - including filelist.
265 $mUA = $this->makeUploadarray($extKey, $conf);
266
267 $md5Array = array();
268 if (is_array($mUA['FILES'])) {
269
270 // Traverse files.
271 foreach ($mUA['FILES'] as $fN => $d) {
272 if ($fN != 'ext_emconf.php') {
273 $md5Array[$fN] = substr($d['content_md5'], 0, 4);
274 }
275 }
276 } else {
277 debug(array($mUA, $conf), 'serverExtensionMD5Array:' . $extKey);
278 }
279 return $md5Array;
280 }
281
282 /*******************************************
283 *
284 * Compiling upload information, emconf-file etc.
285 *
286 *******************************************/
287
288 /**
289 * Compiles the ext_emconf.php file
290 *
291 * @param string Extension key
292 * @param array EM_CONF array
293 * @return string PHP file content, ready to write to ext_emconf.php file
294 */
295 function construct_ext_emconf_file($extKey, $EM_CONF) {
296
297 // clean version number:
298 $vDat = tx_em_Tools::renderVersion($EM_CONF['version']);
299 $EM_CONF['version'] = $vDat['version'];
300
301 $code = '<?php
302
303 ########################################################################
304 # Extension Manager/Repository config file for ext "' . $extKey . '".
305 #
306 # Auto generated ' . date('d-m-Y H:i') . '
307 #
308 # Manual updates:
309 # Only the data in the array - everything else is removed by next
310 # writing. "version" and "dependencies" must not be touched!
311 ########################################################################
312
313 $EM_CONF[$_EXTKEY] = ' . tx_em_Tools::arrayToCode($EM_CONF, 0) . ';
314
315 ?>';
316 return str_replace(CR, '', $code);
317 }
318
319 /**
320 * Make upload array out of extension
321 *
322 * @param string Extension key
323 * @param array Extension information array
324 * @return mixed Returns array with extension upload array on success, otherwise an error string.
325 */
326 function makeUploadarray($extKey, $conf) {
327 $extPath = tx_em_Tools::getExtPath($extKey, $conf['type']);
328
329 if ($extPath) {
330
331 // Get files for extension:
332 $fileArr = array();
333 $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr, $extPath, '', 0, 99, $GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging']);
334
335 // Calculate the total size of those files:
336 $totalSize = 0;
337 foreach ($fileArr as $file) {
338 $totalSize += filesize($file);
339 }
340
341 // If the total size is less than the upper limit, proceed:
342 if ($totalSize < $this->maxUploadSize) {
343
344 // Initialize output array:
345 $uploadArray = array();
346 $uploadArray['extKey'] = $extKey;
347 $uploadArray['EM_CONF'] = $conf['EM_CONF'];
348 $uploadArray['misc']['codelines'] = 0;
349 $uploadArray['misc']['codebytes'] = 0;
350
351 $uploadArray['techInfo'] = $this->install->makeDetailedExtensionAnalysis($extKey, $conf, 1);
352
353 // Read all files:
354 foreach ($fileArr as $file) {
355 $relFileName = substr($file, strlen($extPath));
356 $fI = pathinfo($relFileName);
357 if ($relFileName != 'ext_emconf.php') { // This file should be dynamically written...
358 $uploadArray['FILES'][$relFileName] = array(
359 'name' => $relFileName,
360 'size' => filesize($file),
361 'mtime' => filemtime($file),
362 'is_executable' => (TYPO3_OS == 'WIN' ? 0 : is_executable($file)),
363 'content' => t3lib_div::getUrl($file)
364 );
365 if (t3lib_div::inList('php,inc', strtolower($fI['extension']))) {
366 $uploadArray['FILES'][$relFileName]['codelines'] = count(explode(LF, $uploadArray['FILES'][$relFileName]['content']));
367 $uploadArray['misc']['codelines'] += $uploadArray['FILES'][$relFileName]['codelines'];
368 $uploadArray['misc']['codebytes'] += $uploadArray['FILES'][$relFileName]['size'];
369
370 // locallang*.php files:
371 if (substr($fI['basename'], 0, 9) == 'locallang' && strstr($uploadArray['FILES'][$relFileName]['content'], '$LOCAL_LANG')) {
372 $uploadArray['FILES'][$relFileName]['LOCAL_LANG'] = tx_em_Tools::getSerializedLocalLang($file, $uploadArray['FILES'][$relFileName]['content']);
373 }
374 }
375 $uploadArray['FILES'][$relFileName]['content_md5'] = md5($uploadArray['FILES'][$relFileName]['content']);
376 }
377 }
378
379 // Return upload-array:
380 return $uploadArray;
381 } else {
382 return sprintf($GLOBALS['LANG']->getLL('makeUploadArray_error_size'),
383 $totalSize, t3lib_div::formatSize($this->maxUploadSize));
384 }
385 } else {
386 return sprintf($GLOBALS['LANG']->getLL('makeUploadArray_error_path'),
387 $extKey);
388 }
389 }
390
391
392 /**
393 * Prints a table with extension information in it.
394 *
395 * @param string Extension key
396 * @param array Extension information array
397 * @param boolean If set, the information array shows information for a remote extension in TER, not a local one.
398 * @return string HTML content.
399 */
400 function extInformationarray($extKey, $extInfo, $remote = 0) {
401 $emConf = $extInfo['EM_CONF'];
402
403 $lines = array();
404 $lines[] = '
405 <tr class="t3-row-header"><td colspan="2"><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_general_info') . '</strong></td></tr>';
406
407 // row for the extension title
408 $key = 'title';
409 $dataCol = $emConf['_icon'] . $emConf[$key];
410 $lines[] = array(
411 $this->headerCol($key),
412 $dataCol
413 );
414
415 // row for the extension description
416 $key = 'description';
417 $dataCol = nl2br(htmlspecialchars($emConf[$key]));
418 $lines[] = array(
419 $this->headerCol($key),
420 $dataCol
421 );
422
423 // row for the extension author
424 $key = 'author';
425 $dataCol = tx_em_Tools::wrapEmail($emConf['author'] . ($emConf['author_email'] ? ' <' . $emConf['author_email'] . '>' : ''), $emConf['author_email']);
426 if ($emConf['author_company']) {
427 $dataCol .= ', ' . $emConf['author_company'];
428 }
429 $lines[] = array(
430 $this->headerCol($key),
431 $dataCol
432 );
433
434 // row for the version
435 $key = 'version';
436 $dataCol = $emConf[$key];
437 $lines[] = array(
438 $this->headerCol($key),
439 $dataCol
440 );
441
442 // row for the category
443 $key = 'category';
444 $dataCol = $this->parentObject->categories[$emConf[$key]];
445 $lines[] = array(
446 $this->headerCol($key),
447 $dataCol
448 );
449
450 // row for the state
451 $key = 'state';
452 $dataCol = $this->parentObject->states[$emConf[$key]];
453 $lines[] = array(
454 $this->headerCol($key),
455 $dataCol
456 );
457
458 // row for the shy state
459 $key = 'shy';
460 if ($emConf[$key]) {
461 $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
462 } else {
463 $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
464 }
465 $lines[] = array(
466 $this->headerCol($key),
467 $dataCol
468 );
469
470 // row for the internal state
471 $key = 'internal';
472 if ($emConf[$key]) {
473 $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
474 } else {
475 $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
476 }
477 $lines[] = array(
478 $this->headerCol($key),
479 $dataCol
480 );
481
482 // row for the dependencies
483 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_depends_on');
484 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_dependencies', $headerCol);
485 $dataCol = tx_em_Tools::depToString($emConf['constraints']);
486 $lines[] = array(
487 $headerCol,
488 $dataCol
489 );
490
491 // row for the conflicts
492 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_conflicts_with');
493 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_conflicts', $headerCol);
494 $dataCol = tx_em_Tools::depToString($emConf['constraints'], 'conflicts');
495 $lines[] = array(
496 $headerCol,
497 $dataCol
498 );
499
500 // row for the suggestions
501 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_suggests');
502 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_conflicts', $headerCol);
503 $dataCol = tx_em_Tools::depToString($emConf['constraints'], 'suggests');
504 $lines[] = array(
505 $this->headerCol('suggests'),
506 $dataCol
507 );
508
509 if (!$remote) {
510
511 $key = 'priority';
512 $lines[] = array(
513 $this->headerCol($key),
514 $emConf[$key]
515 );
516
517
518 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_clear_cache');
519 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_clearCacheOnLoad', $headerCol);
520 if ($emConf['clearCacheOnLoad']) {
521 $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
522 } else {
523 $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
524 }
525 $lines[] = array(
526 $headerCol,
527 $dataCol
528 );
529
530 $key = 'module';
531 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_incl_modules');
532 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_module', $headerCol);
533 $lines[] = array(
534 $headerCol,
535 $emConf[$key]
536 );
537
538 $key = 'lockType';
539 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_lock_type');
540 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_lockType', $headerCol);
541 $lines[] = array(
542 $headerCol,
543 ($emConf[$key] ? $emConf[$key] : '')
544 );
545
546 $key = 'doNotLoadInFE';
547 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_load_in_frontend');
548 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_doNotLoadInFE', $headerCol);
549 if (!$emConf['doNotLoadInFE']) {
550 $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
551 } else {
552 $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
553 }
554 $lines[] = array(
555 $headerCol,
556 $dataCol
557 );
558
559 $key = 'modify_tables';
560 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_modifies_tables');
561 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_modify_tables', $headerCol);
562 $lines[] = array(
563 $headerCol,
564 $emConf[$key]
565 );
566
567
568 // Installation status:
569 $techInfo = $this->install->makeDetailedExtensionAnalysis($extKey, $extInfo, 1);
570 $lines[] = array('<tr><td colspan="2">&nbsp;</td></tr>');
571 $lines[] = array('<tr class="t3-row-header"><td colspan="2"><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_inst_status') . '</strong></td></tr>');
572
573
574 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_inst_type');
575 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_type', $headerCol);
576 $dataCol = $this->api->typeLabels[$extInfo['type']] . ' - <em>' . $this->parentObject->typeDescr[$extInfo['type']] . '</em>';
577 $lines[] = array($headerCol, $dataCol);
578
579
580 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_inst_twice');
581 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_doubleInstall', $headerCol);
582 $dataCol = $this->extInformationArray_dbInst($extInfo['doubleInstall'], $extInfo['type']);
583 $lines[] = array($headerCol, $dataCol);
584
585
586 if (is_array($extInfo['files'])) {
587 sort($extInfo['files']);
588 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_root_files');
589 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_rootfiles', $headerCol);
590 $dataCol = implode('<br />', $extInfo['files']);
591 $lines[] = array($headerCol, $dataCol);
592 }
593
594 if ($techInfo['tables'] || $techInfo['static'] || $techInfo['fields']) {
595 if (!$remote && t3lib_extMgm::isLoaded($extKey)) {
596 $tableStatus = tx_em_Tools::rfw(($techInfo['tables_error'] ?
597 '<strong>' . $GLOBALS['LANG']->getLL('extInfoArray_table_error') . '</strong><br />' .
598 $GLOBALS['LANG']->getLL('extInfoArray_missing_fields') : '') .
599 ($techInfo['static_error'] ?
600 '<strong>' . $GLOBALS['LANG']->getLL('extInfoArray_static_table_error') . '</strong><br />' .
601 $GLOBALS['LANG']->getLL('extInfoArray_static_tables_missing_empty') : ''));
602 } else {
603 $tableStatus = $techInfo['tables_error'] || $techInfo['static_error'] ?
604 $GLOBALS['LANG']->getLL('extInfoArray_db_update_needed') : $GLOBALS['LANG']->getLL('extInfoArray_tables_ok');
605 }
606 }
607
608 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_db_requirements');
609 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_dbReq', $headerCol);
610 $dataCol = $this->extInformationArray_dbReq($techInfo, 1);
611 $lines[] = array($headerCol, $dataCol);
612
613 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_db_status');
614 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_dbStatus', $headerCol);
615 $lines[] = array($headerCol, $tableStatus);
616
617 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_flags');
618 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_flags', $headerCol);
619 $dataCol = (is_array($techInfo['flags']) ? implode('<br />', $techInfo['flags']) : '');
620 $lines[] = array($headerCol, $dataCol);
621
622 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_config_template');
623 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_conf', $headerCol);
624 $dataCol = ($techInfo['conf'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '');
625 $lines[] = array($headerCol, $dataCol);
626
627 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_typoscript_files');
628 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_TSfiles', $headerCol);
629 $dataCol = (is_array($techInfo['TSfiles']) ? implode('<br />', $techInfo['TSfiles']) : '');
630 $lines[] = array($headerCol, $dataCol);
631
632 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_language_files');
633 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_locallang', $headerCol);
634 $dataCol = (is_array($techInfo['locallang']) ? implode('<br />', $techInfo['locallang']) : '');
635 $lines[] = array($headerCol, $dataCol);
636
637 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_upload_folder');
638 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_uploadfolder', $headerCol);
639 $dataCol = ($techInfo['uploadfolder'] ? $techInfo['uploadfolder'] : '');
640 $lines[] = array($headerCol, $dataCol);
641
642 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_create_directories');
643 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_createDirs', $headerCol);
644 $dataCol = (is_array($techInfo['createDirs']) ? implode('<br />', $techInfo['createDirs']) : '');
645 $lines[] = array($headerCol, $dataCol);
646
647 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_module_names');
648 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_moduleNames', $headerCol);
649 $dataCol = (is_array($techInfo['moduleNames']) ? implode('<br />', $techInfo['moduleNames']) : '');
650 $lines[] = array($headerCol, $dataCol);
651
652 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_class_names');
653 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_classNames', $headerCol);
654 $dataCol = (is_array($techInfo['classes']) ? implode('<br />', $techInfo['classes']) : '');
655 $lines[] = array($headerCol, $dataCol);
656
657 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_code_warnings') . '<br />' . $GLOBALS['LANG']->getLL('extInfoArray_dev_relevant');
658 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_errors', $headerCol);
659 $dataCol = (is_array($techInfo['errors']) ? tx_em_Tools::rfw(implode('<br />', $techInfo['errors'])) : '');
660 $lines[] = array($headerCol, $dataCol);
661
662 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_annoyances') . '<br />' . $GLOBALS['LANG']->getLL('extInfoArray_dev_relevant');
663 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_NSerrors', $headerCol);
664 if (is_array($techInfo['NSerrors'])) {
665 if (!t3lib_div::inList($this->parentObject->nameSpaceExceptions, $extKey)) {
666 $dataCol = t3lib_utility_Debug::viewarray($techInfo['NSerrors']);
667 } else {
668 $dataCol = $GLOBALS['TBE_TEMPLATE']->dfw($GLOBALS['LANG']->getLL('extInfoArray_exception'));
669 }
670
671 }
672 $lines[] = array($headerCol, $dataCol);
673
674 $currentMd5Array = $this->serverExtensionMD5array($extKey, $extInfo);
675 $affectedFiles = '';
676
677 $msgLines = array();
678 if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'], serialize($currentMd5Array))) {
679 $msgLines[] = tx_em_Tools::rfw('<br /><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_difference_detected') . '</strong>');
680 $affectedFiles = tx_em_Tools::findMD5ArrayDiff($currentMd5Array, unserialize($extInfo['EM_CONF']['_md5_values_when_last_written']));
681 if (count($affectedFiles)) {
682 $msgLines[] = '<br /><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_modified_files') . '</strong><br />' .
683 tx_em_Tools::rfw(implode('<br />', $affectedFiles));
684 }
685 }
686
687 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_files_changed');
688 $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_filesChanged', $headerCol);
689 $dataCol = implode('<br />', $msgLines);
690 $lines[] = array($headerCol, $dataCol);
691 }
692
693 $output = '';
694 foreach ($lines as $cols) {
695 // if it's just one line, we assume it's a headline,
696 // thus no need to wrap it in HTML table tags
697 if (count($cols) == 1) {
698 $output .= $cols[0];
699 } else {
700 $output .= '
701 <tr class="bgColor4">
702 <td>' . $cols[0] . '</td>
703 <td>' . $cols[1] . '</td>
704 </tr>';
705 }
706 }
707
708
709 return '<table border="0" cellpadding="1" cellspacing="2">
710 ' . $output . '
711 </table>';
712 }
713
714 /**
715 * Returns HTML with information about database requirements
716 *
717 * @param array Technical information array
718 * @param boolean Table header displayed
719 * @return string HTML content.
720 */
721 function extInformationArray_dbReq($techInfo, $tableHeader = 0) {
722 return nl2br(trim((is_array($techInfo['tables']) ?
723 ($tableHeader ?
724 "\n\n<strong>" . $GLOBALS['LANG']->getLL('extDumpTables_tables') . "</strong>\n" : '') .
725 implode(LF, $techInfo['tables']) : '') .
726 (is_array($techInfo['static']) ?
727 "\n\n<strong>" . $GLOBALS['LANG']->getLL('extBackup_static_tables') . "</strong>\n" .
728 implode(LF, $techInfo['static']) : '') .
729 (is_array($techInfo['fields']) ?
730 "\n\n<strong>" . $GLOBALS['LANG']->getLL('extInfoArray_additional_fields') . "</strong>\n" .
731 implode('<hr />', $techInfo['fields']) : '')));
732 }
733
734 /**
735 * Double install warning.
736 *
737 * @param string Double-install string, eg. "LG" etc.
738 * @param string Current scope, eg. "L" or "G" or "S"
739 * @return string Message
740 */
741 function extInformationArray_dbInst($dbInst, $current) {
742 if (strlen($dbInst) > 1) {
743 $others = array();
744 for ($a = 0; $a < strlen($dbInst); $a++) {
745 if (substr($dbInst, $a, 1) != $current) {
746 $others[] = '"' . $this->api->typeLabels[substr($dbInst, $a, 1)] . '"';
747 }
748 }
749 return tx_em_Tools::rfw(
750 sprintf($GLOBALS['LANG']->getLL('extInfoArray_double_installation_infotext'),
751 implode(' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:and') . ' ', $others),
752 $this->api->typeLabels[$current]
753 )
754 );
755 } else {
756 return '';
757 }
758 }
759
760
761 /**
762 * Returns help text if applicable.
763 *
764 * @param string Help text key
765 * @return string HTML table cell
766 * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7
767 */
768 function helpCol($key) {
769 global $BE_USER;
770 if ($BE_USER->uc['edit_showFieldHelp']) {
771 if (empty($key)) {
772 return '<td>&nbsp;</td>';
773 }
774 else {
775 return t3lib_BEfunc::cshItem($this->parentObject->descrTable, 'emconf_' . $key, $GLOBALS['BACK_PATH'], '<td>|</td>');
776 }
777 }
778 else {
779 return '';
780 }
781 }
782
783 /**
784 * Returns the header column (for the extension details item), and applies help text if available
785 *
786 * @param string field key
787 * @return string HTML ready to go
788 */
789 function headerCol($key) {
790 $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_' . $key);
791 return t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_' . $key, $headerCol);
792 }
793 }
794
795 ?>