|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /* ************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) webservices.nl 00006 * (c) 2006-2010 Karsten Dambekalns <karsten@typo3.org> 00007 * All rights reserved 00008 * 00009 * This script is part of the TYPO3 project. The TYPO3 project is 00010 * free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * The GNU General Public License can be found at 00016 * http://www.gnu.org/copyleft/gpl.html. 00017 * A copy is found in the textfile GPL.txt and important notices to the license 00018 * from the author is found in LICENSE.txt distributed with these scripts. 00019 * 00020 * 00021 * This script is distributed in the hope that it will be useful, 00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00024 * GNU General Public License for more details. 00025 * 00026 * This copyright notice MUST APPEAR in all copies of the script! 00027 ***************************************************************/ 00028 /** 00029 * class.tx_em_tools.php 00030 * 00031 * $Id: class.tx_em_tools.php 2084 2010-03-22 01:46:37Z steffenk $ 00032 */ 00033 00034 /** 00035 * Static tools for extension manager 00036 * Some of them should be moved later to t3lib static libraries 00037 * 00038 */ 00039 final class tx_em_Tools { 00040 00041 /** 00042 * Keeps default categories. 00043 * 00044 * @var array 00045 */ 00046 protected static $defaultCategories = array( 00047 'be' => 0, 00048 'module' => 1, 00049 'fe' => 2, 00050 'plugin' => 3, 00051 'misc' => 4, 00052 'services' => 5, 00053 'templates' => 6, 00054 'doc' => 8, 00055 'example' => 9, 00056 ); 00057 /** 00058 * Keeps default states. 00059 * 00060 * @var array 00061 */ 00062 protected static $defaultStates = array( 00063 'alpha' => 0, 00064 'beta' => 1, 00065 'stable' => 2, 00066 'experimental' => 3, 00067 'test' => 4, 00068 'obsolete' => 5, 00069 'excludeFromUpdates' => 6, 00070 'n/a' => 999, 00071 ); 00072 00073 /** 00074 * Colors for states 00075 * 00076 * @var array 00077 */ 00078 protected static $stateColors = array( 00079 'alpha' => '#d12438', 00080 'beta' => '#97b17e', 00081 'stable' => '#3bb65c', 00082 'experimental' => '#007eba', 00083 'test' => '#979797', 00084 'obsolete' => '#000000', 00085 'excludeFromUpdates' => '#cf7307' 00086 ); 00087 00088 /** 00089 * Gets the stateColor array 00090 * 00091 * @static 00092 * @return array 00093 */ 00094 public static function getStateColors() { 00095 return self::$stateColors; 00096 } 00097 00098 /** 00099 * Unzips a zip file in the given path. 00100 * 00101 * Uses unzip binary if available, otherwise a pure PHP unzip is used. 00102 * 00103 * @param string $file Full path to zip file 00104 * @param string $path Path to change to before extracting 00105 * @return boolean True on success, false in failure 00106 */ 00107 public static function unzip($file, $path) { 00108 if (strlen($GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'])) { 00109 chdir($path); 00110 $cmd = $GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'] . ' -o ' . escapeshellarg($file); 00111 t3lib_utility_Command::exec($cmd, $list, $ret); 00112 return ($ret === 0); 00113 } else { 00114 // we use a pure PHP unzip 00115 $unzip = t3lib_div::makeInstance('tx_em_Tools_Unzip', $file); 00116 $ret = $unzip->extract(array('add_path' => $path)); 00117 return (is_array($ret)); 00118 } 00119 } 00120 00121 00122 /** 00123 * Refreshes the global extension list 00124 * 00125 * @return void 00126 */ 00127 public static function refreshGlobalExtList() { 00128 global $TYPO3_LOADED_EXT; 00129 00130 $TYPO3_LOADED_EXT = t3lib_extMgm::typo3_loadExtensions(); 00131 if ($TYPO3_LOADED_EXT['_CACHEFILE']) { 00132 require(PATH_typo3conf . $TYPO3_LOADED_EXT['_CACHEFILE'] . '_ext_localconf.php'); 00133 } 00134 return; 00135 00136 $GLOBALS['TYPO3_LOADED_EXT'] = t3lib_extMgm::typo3_loadExtensions(); 00137 if ($TYPO3_LOADED_EXT['_CACHEFILE']) { 00138 require(PATH_typo3conf . $TYPO3_LOADED_EXT['_CACHEFILE'] . '_ext_localconf.php'); 00139 } else { 00140 $temp_TYPO3_LOADED_EXT = $TYPO3_LOADED_EXT; 00141 foreach ($temp_TYPO3_LOADED_EXT as $_EXTKEY => $temp_lEDat) { 00142 if (is_array($temp_lEDat) && $temp_lEDat['ext_localconf.php']) { 00143 $_EXTCONF = $GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY]; 00144 require($temp_lEDat['ext_localconf.php']); 00145 } 00146 } 00147 } 00148 } 00149 00150 /** 00151 * Set category array entries for extension 00152 * 00153 * @param array Category index array 00154 * @param array Part of list array for extension. 00155 * @param string Extension key 00156 * @return array Modified category index array 00157 */ 00158 public static function setCat(&$cat, $listArrayPart, $extKey) { 00159 00160 // Getting extension title: 00161 $extTitle = $listArrayPart['EM_CONF']['title']; 00162 00163 // Category index: 00164 $index = $listArrayPart['EM_CONF']['category']; 00165 $cat['cat'][$index][$extKey] = $extTitle; 00166 00167 // Author index: 00168 $index = $listArrayPart['EM_CONF']['author'] . ($listArrayPart['EM_CONF']['author_company'] ? ', ' . $listArrayPart['EM_CONF']['author_company'] : ''); 00169 $cat['author_company'][$index][$extKey] = $extTitle; 00170 00171 // State index: 00172 $index = $listArrayPart['EM_CONF']['state']; 00173 $cat['state'][$index][$extKey] = $extTitle; 00174 00175 // Type index: 00176 $index = $listArrayPart['type']; 00177 $cat['type'][$index][$extKey] = $extTitle; 00178 00179 // Return categories: 00180 return $cat; 00181 } 00182 00183 /** 00184 * Returns upload folder for extension 00185 * 00186 * @param string Extension key 00187 * @return string Upload folder for extension 00188 */ 00189 public static function uploadFolder($extKey) { 00190 return 'uploads/tx_' . str_replace('_', '', $extKey) . '/'; 00191 } 00192 00193 00194 /** 00195 * Returns image tag for "uninstall" 00196 * 00197 * @return string <img> tag 00198 */ 00199 public static function removeButton() { 00200 return t3lib_iconWorks::getSpriteIcon('actions-system-extension-uninstall', array('title' => $GLOBALS['LANG']->getLL('ext_details_remove_ext'))); 00201 } 00202 00203 /** 00204 * Returns image for "install" 00205 * 00206 * @return string <img> tag 00207 */ 00208 public static function installButton() { 00209 return t3lib_iconWorks::getSpriteIcon('actions-system-extension-install', array('title' => $GLOBALS['LANG']->getLL('helperFunction_install_extension'))); 00210 } 00211 00212 /** 00213 * Warning (<img> + text string) message about the impossibility to import extensions (both local and global locations are disabled...) 00214 * 00215 * @return string <img> + text string. 00216 */ 00217 public static function noImportMsg() { 00218 return t3lib_iconWorks::getSpriteIcon('status-dialog-warning') . 00219 '<strong>' . $GLOBALS['LANG']->getLL('helperFunction_import_not_possible') . '</strong>'; 00220 } 00221 00222 00223 /** 00224 * Fixes an old style ext_emconf.php array by adding constraints if needed and removing deprecated keys 00225 * 00226 * @param array $emConf 00227 * @return array 00228 */ 00229 public static function fixEMCONF($emConf) { 00230 if (!isset($emConf['constraints']) || !isset($emConf['constraints']['depends']) || !isset($emConf['constraints']['conflicts']) || !isset($emConf['constraints']['suggests'])) { 00231 if (!isset($emConf['constraints']) || !isset($emConf['constraints']['depends'])) { 00232 $emConf['constraints']['depends'] = self::stringToDep($emConf['dependencies']); 00233 if (strlen($emConf['PHP_version'])) { 00234 $versionRange = self::splitVersionRange($emConf['PHP_version']); 00235 if (version_compare($versionRange[0], '3.0.0', '<')) { 00236 $versionRange[0] = '3.0.0'; 00237 } 00238 if (version_compare($versionRange[1], '3.0.0', '<')) { 00239 $versionRange[1] = '0.0.0'; 00240 } 00241 $emConf['constraints']['depends']['php'] = implode('-', $versionRange); 00242 } 00243 if (strlen($emConf['TYPO3_version'])) { 00244 $versionRange = self::splitVersionRange($emConf['TYPO3_version']); 00245 if (version_compare($versionRange[0], '3.5.0', '<')) { 00246 $versionRange[0] = '3.5.0'; 00247 } 00248 if (version_compare($versionRange[1], '3.5.0', '<')) { 00249 $versionRange[1] = '0.0.0'; 00250 } 00251 $emConf['constraints']['depends']['typo3'] = implode('-', $versionRange); 00252 } 00253 } 00254 if (!isset($emConf['constraints']) || !isset($emConf['constraints']['conflicts'])) { 00255 $emConf['constraints']['conflicts'] = self::stringToDep($emConf['conflicts']); 00256 } 00257 if (!isset($emConf['constraints']) || !isset($emConf['constraints']['suggests'])) { 00258 $emConf['constraints']['suggests'] = array(); 00259 } 00260 } elseif (isset($emConf['constraints']) && isset($emConf['dependencies'])) { 00261 $emConf['suggests'] = isset($emConf['suggests']) ? $emConf['suggests'] : array(); 00262 $emConf['dependencies'] = self::depToString($emConf['constraints']); 00263 $emConf['conflicts'] = self::depToString($emConf['constraints'], 'conflicts'); 00264 } 00265 00266 // sanity check for version numbers, intentionally only checks php and typo3 00267 if (isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['php'])) { 00268 $versionRange = self::splitVersionRange($emConf['constraints']['depends']['php']); 00269 if (version_compare($versionRange[0], '3.0.0', '<')) { 00270 $versionRange[0] = '3.0.0'; 00271 } 00272 if (version_compare($versionRange[1], '3.0.0', '<')) { 00273 $versionRange[1] = '0.0.0'; 00274 } 00275 $emConf['constraints']['depends']['php'] = implode('-', $versionRange); 00276 } 00277 if (isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['typo3'])) { 00278 $versionRange = self::splitVersionRange($emConf['constraints']['depends']['typo3']); 00279 if (version_compare($versionRange[0], '3.5.0', '<')) { 00280 $versionRange[0] = '3.5.0'; 00281 } 00282 if (version_compare($versionRange[1], '3.5.0', '<')) { 00283 $versionRange[1] = '0.0.0'; 00284 } 00285 $emConf['constraints']['depends']['typo3'] = implode('-', $versionRange); 00286 } 00287 00288 unset($emConf['private']); 00289 unset($emConf['download_password']); 00290 unset($emConf['TYPO3_version']); 00291 unset($emConf['PHP_version']); 00292 00293 return $emConf; 00294 } 00295 00296 00297 /** 00298 * Returns the $EM_CONF array from an extensions ext_emconf.php file 00299 * 00300 * @param string Absolute path to EMCONF file. 00301 * @param string Extension key. 00302 * @return array EMconf array values. 00303 */ 00304 public static function includeEMCONF($path, $_EXTKEY) { 00305 $EM_CONF = NULL; 00306 @include($path); 00307 if (is_array($EM_CONF[$_EXTKEY])) { 00308 return self::fixEMCONF($EM_CONF[$_EXTKEY]); 00309 } 00310 return FALSE; 00311 } 00312 00313 00314 /** 00315 * Extracts the directories in the $files array 00316 * 00317 * @param array Array of files / directories 00318 * @return array Array of directories from the input array. 00319 */ 00320 public static function extractDirsFromFileList($files) { 00321 $dirs = array(); 00322 00323 if (is_array($files)) { 00324 // Traverse files / directories array: 00325 foreach ($files as $file) { 00326 if (substr($file, -1) == '/') { 00327 $dirs[$file] = $file; 00328 } else { 00329 $pI = pathinfo($file); 00330 if (strcmp($pI['dirname'], '') && strcmp($pI['dirname'], '.')) { 00331 $dirs[$pI['dirname'] . '/'] = $pI['dirname'] . '/'; 00332 } 00333 } 00334 } 00335 } 00336 return $dirs; 00337 } 00338 00339 /** 00340 * Splits a version range into an array. 00341 * 00342 * If a single version number is given, it is considered a minimum value. 00343 * If a dash is found, the numbers left and right are considered as minimum and maximum. Empty values are allowed. 00344 * 00345 * @param string $ver A string with a version range. 00346 * @return array 00347 */ 00348 public static function splitVersionRange($ver) { 00349 $versionRange = array(); 00350 if (strstr($ver, '-')) { 00351 $versionRange = explode('-', $ver, 2); 00352 } else { 00353 $versionRange[0] = $ver; 00354 $versionRange[1] = ''; 00355 } 00356 00357 if (!$versionRange[0]) { 00358 $versionRange[0] = '0.0.0'; 00359 } 00360 if (!$versionRange[1]) { 00361 $versionRange[1] = '0.0.0'; 00362 } 00363 00364 return $versionRange; 00365 } 00366 00367 /** 00368 * Checks whether the passed dependency is TER2-style (array) and returns a single string for displaying the dependencies. 00369 * 00370 * It leaves out all version numbers and the "php" and "typo3" dependencies, as they are implicit and of no interest without the version number. 00371 * 00372 * @param mixed $dep Either a string or an array listing dependencies. 00373 * @param string $type The dependency type to list if $dep is an array 00374 * @return string A simple dependency list for display 00375 */ 00376 public static function depToString($dep, $type = 'depends') { 00377 if (is_array($dep)) { 00378 unset($dep[$type]['php']); 00379 unset($dep[$type]['typo3']); 00380 $s = (count($dep[$type])) ? implode(',', array_keys($dep[$type])) : ''; 00381 return $s; 00382 } 00383 return ''; 00384 } 00385 00386 /** 00387 * Checks whether the passed dependency is TER-style (string) or TER2-style (array) and returns a single string for displaying the dependencies. 00388 * 00389 * It leaves out all version numbers and the "php" and "typo3" dependencies, as they are implicit and of no interest without the version number. 00390 * 00391 * @param mixed $dep Either a string or an array listing dependencies. 00392 * @param string $type The dependency type to list if $dep is an array 00393 * @return string A simple dependency list for display 00394 */ 00395 public static function stringToDep($dep) { 00396 $constraint = array(); 00397 if (is_string($dep) && strlen($dep)) { 00398 $dep = explode(',', $dep); 00399 foreach ($dep as $v) { 00400 $constraint[$v] = ''; 00401 } 00402 } 00403 return $constraint; 00404 } 00405 00406 00407 /** 00408 * Returns version information 00409 * 00410 * @param string Version code, x.x.x 00411 * @param string part: "", "int", "main", "sub", "dev" 00412 * @return string 00413 * @see renderVersion() 00414 */ 00415 public static function makeVersion($v, $mode) { 00416 $vDat = self::renderVersion($v); 00417 return $vDat['version_' . $mode]; 00418 } 00419 00420 /** 00421 * Parses the version number x.x.x and returns an array with the various parts. 00422 * 00423 * @param string Version code, x.x.x 00424 * @param string Increase version part: "main", "sub", "dev" 00425 * @return string 00426 */ 00427 public static function renderVersion($v, $raise = '') { 00428 $parts = t3lib_div::intExplode('.', $v . '..'); 00429 $parts[0] = t3lib_div::intInRange($parts[0], 0, 999); 00430 $parts[1] = t3lib_div::intInRange($parts[1], 0, 999); 00431 $parts[2] = t3lib_div::intInRange($parts[2], 0, 999); 00432 00433 switch ((string) $raise) { 00434 case 'main': 00435 $parts[0]++; 00436 $parts[1] = 0; 00437 $parts[2] = 0; 00438 break; 00439 case 'sub': 00440 $parts[1]++; 00441 $parts[2] = 0; 00442 break; 00443 case 'dev': 00444 $parts[2]++; 00445 break; 00446 } 00447 00448 $res = array(); 00449 $res['version'] = $parts[0] . '.' . $parts[1] . '.' . $parts[2]; 00450 $res['version_int'] = intval($parts[0] * 1000000 + $parts[1] * 1000 + $parts[2]); 00451 $res['version_main'] = $parts[0]; 00452 $res['version_sub'] = $parts[1]; 00453 $res['version_dev'] = $parts[2]; 00454 00455 return $res; 00456 } 00457 00458 /** 00459 * Render version from intVersion 00460 * 00461 * @static 00462 * @param int $intVersion 00463 * @return string version 00464 */ 00465 public static function versionFromInt($intVersion) { 00466 $versionString = str_pad($intVersion, 9, '0', STR_PAD_LEFT); 00467 $parts = array( 00468 substr($versionString, 0, 3), 00469 substr($versionString, 3, 3), 00470 substr($versionString, 6, 3) 00471 ); 00472 return intval($parts[0]) . '.' . intval($parts[1]) . '.' . intval($parts[2]); 00473 } 00474 00475 /** 00476 * Evaluates differences in version numbers with three parts, x.x.x. Returns true if $v1 is greater than $v2 00477 * 00478 * @param string Version number 1 00479 * @param string Version number 2 00480 * @param integer Tolerance factor. For instance, set to 1000 to ignore difference in dev-version (third part) 00481 * @return boolean True if version 1 is greater than version 2 00482 */ 00483 public static function versionDifference($v1, $v2, $div = 1) { 00484 return floor(self::makeVersion($v1, 'int') / $div) > floor(self::makeVersion($v2, 'int') / $div); 00485 } 00486 00487 00488 /** 00489 * Returns true if the $str is found as the first part of a string in $array 00490 * 00491 * @param string String to test with. 00492 * @param array Input array 00493 * @param boolean If set, the test is case insensitive 00494 * @return boolean True if found. 00495 */ 00496 public static function first_in_array($str, $array, $caseInsensitive = FALSE) { 00497 if ($caseInsensitive) { 00498 $str = strtolower($str); 00499 } 00500 if (is_array($array)) { 00501 foreach ($array as $cl) { 00502 if ($caseInsensitive) { 00503 $cl = strtolower($cl); 00504 } 00505 if (t3lib_div::isFirstPartOfStr($cl, $str)) { 00506 return TRUE; 00507 } 00508 } 00509 } 00510 return FALSE; 00511 } 00512 00513 /** 00514 * Compares two arrays with MD5-hash values for analysis of which files has changed. 00515 * 00516 * @param array Current values 00517 * @param array Past values 00518 * @return array Affected files 00519 */ 00520 public static function findMD5ArrayDiff($current, $past) { 00521 if (!is_array($current)) { 00522 $current = array(); 00523 } 00524 if (!is_array($past)) { 00525 $past = array(); 00526 } 00527 $filesInCommon = array_intersect($current, $past); 00528 $diff1 = array_keys(array_diff($past, $filesInCommon)); 00529 $diff2 = array_keys(array_diff($current, $filesInCommon)); 00530 $affectedFiles = array_unique(array_merge($diff1, $diff2)); 00531 return $affectedFiles; 00532 } 00533 00534 /** 00535 * Returns title and style attribute for mouseover help text. 00536 * 00537 * @param string Help text. 00538 * @return string title="" attribute prepended with a single space 00539 */ 00540 public static function labelInfo($str) { 00541 return ' title="' . htmlspecialchars($str) . '" style="cursor:help;"'; 00542 } 00543 00544 00545 /** 00546 * Returns the absolute path where the extension $extKey is installed (based on 'type' (SGL)) 00547 * 00548 * @param string Extension key 00549 * @param string Install scope type: L, G, S 00550 * @return string Returns the absolute path to the install scope given by input $type variable. It is checked if the path is a directory. Slash is appended. 00551 */ 00552 public static function getExtPath($extKey, $type, $returnWithoutExtKey = FALSE) { 00553 $typePath = self::typePath($type); 00554 00555 if ($typePath) { 00556 $path = $typePath . ($returnWithoutExtKey ? '' : $extKey . '/'); 00557 return $path; # @is_dir($path) ? $path : ''; 00558 } else { 00559 return ''; 00560 } 00561 } 00562 00563 /** 00564 * Get type of extension (G,S,L) from extension path 00565 * 00566 * @param string $path 00567 */ 00568 public static function getExtTypeFromPath($path) { 00569 if (strpos($path, TYPO3_mainDir . 'sysext/') !== FALSE) { 00570 return 'S'; 00571 } elseif (strpos($path, TYPO3_mainDir . 'ext/') !== FALSE) { 00572 return 'G'; 00573 } elseif (strpos($path, 'typo3conf/ext/') !== FALSE) { 00574 return 'L'; 00575 } 00576 } 00577 00578 /** 00579 * Get path from type 00580 * 00581 * @param string $type S/G/L 00582 */ 00583 public static function typePath($type) { 00584 if ($type === 'S') { 00585 return PATH_typo3 . 'sysext/'; 00586 } elseif ($type === 'G') { 00587 return PATH_typo3 . 'ext/'; 00588 } elseif ($type === 'L') { 00589 return PATH_typo3conf . 'ext/'; 00590 } 00591 } 00592 00593 /** 00594 * Get relative path from type 00595 * 00596 * @param string $type S/G/L 00597 */ 00598 public static function typeRelPath($type) { 00599 if ($type === 'S') { 00600 return 'sysext/'; 00601 } elseif ($type === 'G') { 00602 return 'ext/'; 00603 } elseif ($type === 'L') { 00604 return '../typo3conf/ext/'; 00605 } 00606 } 00607 00608 /** 00609 * Get backpath from type 00610 * 00611 * @param string $type S/G/L 00612 */ 00613 public static function typeBackPath($type) { 00614 if ($type === 'L') { 00615 return '../../../../' . TYPO3_mainDir; 00616 } else { 00617 return '../../../'; 00618 } 00619 } 00620 00621 /** 00622 * Reads locallang file into array (for possible include in header) 00623 * 00624 * @param $file 00625 * @return array 00626 * @deprecated since TYPO3 4.5.1, will be removed in TYPO3 4.7 - use pageRenderer->addInlineLanguageLabelFile() instead 00627 */ 00628 public static function getArrayFromLocallang($file, $key = 'default') { 00629 $content = t3lib_div::getURL($file); 00630 $array = t3lib_div::xml2array($content); 00631 00632 return $array['data'][$key]; 00633 } 00634 00635 /** 00636 * Include a locallang file and return the $LOCAL_LANG array serialized. 00637 * 00638 * @param string Absolute path to locallang file to include. 00639 * @param string Old content of a locallang file (keeping the header content) 00640 * @return array Array with header/content as key 0/1 00641 * @see makeUploadarray() 00642 */ 00643 public static function getSerializedLocalLang($file, $content) { 00644 $LOCAL_LANG = NULL; 00645 $returnParts = explode('$LOCAL_LANG', $content, 2); 00646 00647 include($file); 00648 if (is_array($LOCAL_LANG)) { 00649 $returnParts[1] = serialize($LOCAL_LANG); 00650 return $returnParts; 00651 } else { 00652 return array(); 00653 } 00654 } 00655 00656 00657 /** 00658 * Enter description here... 00659 * 00660 * @param unknown_type $array 00661 * @param unknown_type $lines 00662 * @param unknown_type $level 00663 * @return unknown 00664 */ 00665 public static function arrayToCode($array, $level = 0) { 00666 $lines = 'array(' . LF; 00667 $level++; 00668 foreach ($array as $k => $v) { 00669 if (strlen($k) && is_array($v)) { 00670 $lines .= str_repeat(TAB, $level) . "'" . $k . "' => " . self::arrayToCode($v, $level); 00671 } elseif (strlen($k)) { 00672 $lines .= str_repeat(TAB, $level) . "'" . $k . "' => " . (t3lib_div::testInt($v) ? intval($v) : "'" . t3lib_div::slashJS(trim($v), 1) . "'") . ',' . LF; 00673 } 00674 } 00675 00676 $lines .= str_repeat(TAB, $level - 1) . ')' . ($level - 1 == 0 ? '' : ',' . LF); 00677 return $lines; 00678 } 00679 00680 00681 /** 00682 * Traverse the array of installed extensions keys and arranges extensions in the priority order they should be in 00683 * 00684 * @param array Array of extension keys as values 00685 * @param array Extension information array 00686 * @return array Modified array of extention keys as values 00687 * @see addExtToList() 00688 */ 00689 public static function managesPriorities($listArr, $instExtInfo) { 00690 00691 // Initialize: 00692 $levels = array( 00693 'top' => array(), 00694 'middle' => array(), 00695 'bottom' => array(), 00696 ); 00697 00698 // Traverse list of extensions: 00699 foreach ($listArr as $ext) { 00700 $prio = trim($instExtInfo[$ext]['EM_CONF']['priority']); 00701 switch ((string) $prio) { 00702 case 'top': 00703 case 'bottom': 00704 $levels[$prio][] = $ext; 00705 break; 00706 default: 00707 $levels['middle'][] = $ext; 00708 break; 00709 } 00710 } 00711 return array_merge( 00712 $levels['top'], 00713 $levels['middle'], 00714 $levels['bottom'] 00715 ); 00716 } 00717 00718 00719 /** 00720 * Returns either array with all default categories or index/title 00721 * of a category entry. 00722 * 00723 * @access public 00724 * @param mixed $cat category title or category index 00725 * @return mixed 00726 */ 00727 public static function getDefaultCategory($cat = NULL) { 00728 if (is_null($cat)) { 00729 return self::$defaultCategories; 00730 } else { 00731 if (is_string($cat)) { 00732 // default category 00733 $catIndex = 4; 00734 if (array_key_exists(strtolower($cat), self::$defaultCategories)) { 00735 $catIndex = self::$defaultCategories[strtolower($cat)]; 00736 } 00737 return $catIndex; 00738 } else { 00739 if (is_int($cat) && $cat >= 0) { 00740 $catTitle = array_search($cat, self::$defaultCategories); 00741 // default category 00742 if (!$catTitle) { 00743 $catTitle = 'misc'; 00744 } 00745 return $catTitle; 00746 } 00747 } 00748 } 00749 } 00750 00751 /** 00752 * Returns either array with all default states or index/title 00753 * of a state entry. 00754 * 00755 * @access public 00756 * @param mixed $state state title or state index 00757 * @return mixed 00758 */ 00759 public static function getDefaultState($state = NULL) { 00760 if (is_null($state)) { 00761 return self::$defaultStates; 00762 } else { 00763 if (is_string($state)) { 00764 // default state 00765 $stateIndex = 999; 00766 if (array_key_exists(strtolower($state), self::$defaultStates)) { 00767 $stateIndex = self::$defaultStates[strtolower($state)]; 00768 } 00769 return $stateIndex; 00770 } else { 00771 if (is_int($state) && $state >= 0) { 00772 $stateTitle = array_search($state, self::$defaultStates); 00773 // default state 00774 if (!$stateTitle) { 00775 $stateTitle = 'n/a'; 00776 } 00777 return $stateTitle; 00778 } 00779 } 00780 } 00781 } 00782 00783 /** 00784 * Extension States 00785 * Content must be redundant with the same internal variable as in class.tx_extrep.php! 00786 * 00787 * @static 00788 * @return array 00789 */ 00790 public static function getStates() { 00791 return array( 00792 'alpha' => $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:state_alpha'), 00793 'beta' => $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:state_beta'), 00794 'stable' => $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:state_stable'), 00795 'experimental' => $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:state_experimental'), 00796 'test' => $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:state_test'), 00797 'obsolete' => $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:state_obsolete'), 00798 'excludeFromUpdates' => $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:state_exclude_from_updates') 00799 ); 00800 } 00801 00802 /** 00803 * Reports back if installation in a certain scope is possible. 00804 * 00805 * @param string Scope: G, L, S 00806 * @param string Extension lock-type (eg. "L" or "G") 00807 * @return boolean True if installation is allowed. 00808 */ 00809 public static function importAsType($type, $lockType = '') { 00810 switch ($type) { 00811 case 'G': 00812 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] && (!$lockType || !strcmp($lockType, $type)); 00813 break; 00814 case 'L': 00815 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'] && (!$lockType || !strcmp($lockType, $type)); 00816 break; 00817 case 'S': 00818 return isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowSystemInstall']) && $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowSystemInstall']; 00819 break; 00820 default: 00821 return FALSE; 00822 } 00823 } 00824 00825 /** 00826 * Returns true if extensions in scope, $type, can be deleted (or installed for that sake) 00827 * 00828 * @param string Scope: "G" or "L" 00829 * @return boolean True if possible. 00830 */ 00831 public static function deleteAsType($type) { 00832 switch ($type) { 00833 case 'G': 00834 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall']; 00835 break; 00836 case 'L': 00837 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall']; 00838 break; 00839 default: 00840 return FALSE; 00841 } 00842 } 00843 00844 00845 /** 00846 * Creates directories in $extDirPath 00847 * 00848 * @param array Array of directories to create relative to extDirPath, eg. "blabla", "blabla/blabla" etc... 00849 * @param string Absolute path to directory. 00850 * @return mixed Returns false on success or an error string 00851 */ 00852 public static function createDirsInPath($dirs, $extDirPath) { 00853 if (is_array($dirs)) { 00854 foreach ($dirs as $dir) { 00855 $error = t3lib_div::mkdir_deep($extDirPath, $dir); 00856 if ($error) { 00857 return $error; 00858 } 00859 } 00860 } 00861 00862 return FALSE; 00863 } 00864 00865 /** 00866 * Analyses the php-scripts of an available extension on server 00867 * 00868 * @param string Absolute path to extension 00869 * @param string Prefix for tables/classes. 00870 * @param string Extension key 00871 * @return array Information array. 00872 * @see makeDetailedExtensionAnalysis() 00873 */ 00874 public static function getClassIndexLocallangFiles($absPath, $table_class_prefix, $extKey) { 00875 $excludeForPackaging = $GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging']; 00876 $filesInside = t3lib_div::removePrefixPathFromList(t3lib_div::getAllFilesAndFoldersInPath(array(), $absPath, 'php,inc', 0, 99, $excludeForPackaging), $absPath); 00877 $out = array(); 00878 $reg = array(); 00879 00880 foreach ($filesInside as $fileName) { 00881 if (substr($fileName, 0, 4) != 'ext_' && substr($fileName, 0, 6) != 'tests/') { // ignore supposed-to-be unit tests as well 00882 $baseName = basename($fileName); 00883 if (substr($baseName, 0, 9) == 'locallang' && substr($baseName, -4) == '.php') { 00884 $out['locallang'][] = $fileName; 00885 } elseif ($baseName != 'conf.php') { 00886 if (filesize($absPath . $fileName) < 500 * 1024) { 00887 $fContent = t3lib_div::getUrl($absPath . $fileName); 00888 unset($reg); 00889 if (preg_match('/\n[[:space:]]*class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/', $fContent, $reg)) { 00890 00891 // Find classes: 00892 $lines = explode(LF, $fContent); 00893 foreach ($lines as $l) { 00894 $line = trim($l); 00895 unset($reg); 00896 if (preg_match('/^class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/', $line, $reg)) { 00897 $out['classes'][] = $reg[1]; 00898 $out['files'][$fileName]['classes'][] = $reg[1]; 00899 if ($reg[1] !== 'ext_update' && substr($reg[1], 0, 3) != 'ux_' && !t3lib_div::isFirstPartOfStr($reg[1], $table_class_prefix) && strcmp(substr($table_class_prefix, 0, -1), $reg[1])) { 00900 $out['NSerrors']['classname'][] = $reg[1]; 00901 } else { 00902 $out['NSok']['classname'][] = $reg[1]; 00903 } 00904 } 00905 } 00906 // If class file prefixed 'class.'.... 00907 if (substr($baseName, 0, 6) == 'class.') { 00908 $fI = pathinfo($baseName); 00909 $testName = substr($baseName, 6, -(1 + strlen($fI['extension']))); 00910 if ($testName !== 'ext_update' && substr($testName, 0, 3) != 'ux_' && !t3lib_div::isFirstPartOfStr($testName, $table_class_prefix) && strcmp(substr($table_class_prefix, 0, -1), $testName)) { 00911 $out['NSerrors']['classfilename'][] = $baseName; 00912 } else { 00913 $out['NSok']['classfilename'][] = $baseName; 00914 if (is_array($out['files'][$fileName]['classes']) && tx_em_Tools::first_in_array($testName, $out['files'][$fileName]['classes'], 1)) { 00915 $out['msg'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_class_ok'), 00916 $fileName, $testName 00917 ); 00918 } else { 00919 $out['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_class_not_ok'), 00920 $fileName, $testName 00921 ); 00922 } 00923 } 00924 } 00925 // Check for proper XCLASS definition 00926 // Match $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS'] with single or doublequotes 00927 $XclassSearch = '\$TYPO3_CONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]'; 00928 $XclassParts = preg_split('/if \(defined\([\'"]TYPO3_MODE[\'"]\)(.*)' . $XclassSearch . '/', $fContent, 2); 00929 if (count($XclassParts) !== 2) { 00930 // Match $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS'] with single or doublequotes 00931 $XclassSearch = '\$GLOBALS\[[\'"]TYPO3_CONF_VARS[\'"]\]\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]'; 00932 $XclassParts = preg_split('/if \(defined\([\'"]TYPO3_MODE[\'"]\)(.*)' . $XclassSearch . '/', $fContent, 2); 00933 } 00934 00935 if (count($XclassParts) == 2) { 00936 unset($reg); 00937 preg_match('/^\[[\'"]([[:alnum:]_\/\.]*)[\'"]\]/', $XclassParts[1], $reg); 00938 if ($reg[1]) { 00939 $cmpF = 'ext/' . $extKey . '/' . $fileName; 00940 if (!strcmp($reg[1], $cmpF)) { 00941 if (preg_match('/_once[[:space:]]*\(' . $XclassSearch . '\[[\'"]' . preg_quote($cmpF, '/') . '[\'"]\]\);/', $XclassParts[1])) { 00942 $out['msg'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_xclass_ok'), $fileName); 00943 } else { 00944 $out['errors'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_xclass_no_include'); 00945 } 00946 } else { 00947 $out['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_xclass_incorrect'), 00948 $reg[1], $cmpF 00949 ); 00950 } 00951 } else { 00952 $out['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_no_xclass_filename'), $fileName); 00953 } 00954 } elseif (!tx_em_Tools::first_in_array('ux_', $out['files'][$fileName]['classes'])) { 00955 // No Xclass definition required if classname starts with 'ux_' 00956 $out['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_no_xclass_found'), $fileName); 00957 } 00958 } 00959 } 00960 } 00961 } 00962 } 00963 return $out; 00964 } 00965 00966 /** 00967 * Write new TYPO3_MOD_PATH to "conf.php" file. 00968 * 00969 * @param string Absolute path to a "conf.php" file of the backend module which we want to write back to. 00970 * @param string Install scope type: L, G, S 00971 * @param string Relative path for the module folder in extension 00972 * @return string Returns message about the status. 00973 * @see modConfFileAnalysis() 00974 */ 00975 public static function writeTYPO3_MOD_PATH($confFilePath, $type, $mP) { 00976 $lines = explode(LF, t3lib_div::getUrl($confFilePath)); 00977 $confFileInfo = array(); 00978 $confFileInfo['lines'] = $lines; 00979 $reg = array(); 00980 00981 $flag_M = 0; 00982 $flag_B = 0; 00983 $flag_Dispatch = 0; 00984 00985 foreach ($lines as $k => $l) { 00986 $line = trim($l); 00987 00988 unset($reg); 00989 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/', $line, $reg)) { 00990 $lines[$k] = str_replace($reg[0], 'define(\'TYPO3_MOD_PATH\', \'' . self::typeRelPath($type) . $mP . '\');', $lines[$k]); 00991 $flag_M = $k + 1; 00992 } 00993 00994 unset($reg); 00995 if (preg_match('/^\$BACK_PATH[[:space:]]*=[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*;/', $line, $reg)) { 00996 $lines[$k] = str_replace($reg[0], '$BACK_PATH=\'' . self::typeBackPath($type) . '\';', $lines[$k]); 00997 $flag_B = $k + 1; 00998 } 00999 01000 // Check if this module uses new API (see http://bugs.typo3.org/view.php?id=5278) 01001 // where TYPO3_MOD_PATH and BACK_PATH are not required 01002 unset($reg); 01003 if (preg_match('/^\$MCONF\[["\']script["\']\][[:space:]]*=[[:space:]]*["\']_DISPATCH["\'][[:space:]]*;/', $line, $reg)) { 01004 $flag_Dispatch = $k + 1; 01005 } 01006 01007 } 01008 01009 if ($flag_B && $flag_M) { 01010 t3lib_div::writeFile($confFilePath, implode(LF, $lines)); 01011 return sprintf($GLOBALS['LANG']->getLL('writeModPath_ok'), 01012 substr($confFilePath, strlen(PATH_site))); 01013 } elseif ($flag_Dispatch) { 01014 return sprintf( 01015 $GLOBALS['LANG']->getLL('writeModPath_notRequired'), 01016 substr($confFilePath, strlen(PATH_site)) 01017 ); 01018 } else { 01019 return self::rfw( 01020 sprintf($GLOBALS['LANG']->getLL('writeModPath_error'), 01021 $confFilePath) 01022 ); 01023 } 01024 } 01025 01026 /** 01027 * Sends content of file for download 01028 * 01029 * @static 01030 * @param $path 01031 * @return void 01032 */ 01033 public static function sendFile($path) { 01034 $path = t3lib_div::resolveBackPath(PATH_site . $path); 01035 01036 if (is_file($path) && is_readable($path) && t3lib_div::isAllowedAbsPath($path)) { 01037 header('Content-Type: application/octet-stream'); 01038 header('Content-Disposition: attachment; filename=' . basename($path)); 01039 readfile($path); 01040 exit; 01041 } 01042 } 01043 01044 /** 01045 * Rename a file / folder 01046 * @static 01047 * @param $file 01048 * @param $newName 01049 * @return bool 01050 */ 01051 public static function renameFile($file, $newName) { 01052 if($file[0] == '/') { 01053 $file = substr($file, 1); 01054 } 01055 if($newName[0] == '/') { 01056 $newName = substr($newName, 1); 01057 } 01058 01059 $file = t3lib_div::resolveBackPath(PATH_site . $file); 01060 $newName = t3lib_div::resolveBackPath(PATH_site . $newName); 01061 if (is_writable($file) && t3lib_div::isAllowedAbsPath($file) && t3lib_div::isAllowedAbsPath($newName)) { 01062 return rename($file, $newName); 01063 } 01064 01065 return false; 01066 } 01067 01068 01069 /** 01070 * Creates a new file 01071 * 01072 * Returns an array with 01073 * 0: boolean success 01074 * 1: string absolute path of written file/folder 01075 * 2: error code 01076 * 01077 * The error code returns 01078 * 0: no error 01079 * -1: not writable 01080 * -2: not allowed path 01081 * -3: already exists 01082 * -4: not able to create 01083 * 01084 * @static 01085 * @param $folder 01086 * @param $file 01087 * @param $isFolder 01088 * @return array 01089 */ 01090 public static function createNewFile($folder, $file, $isFolder) { 01091 $success = FALSE; 01092 $error = 0; 01093 01094 if (substr($folder, -1) !== '/') { 01095 $folder .= '/'; 01096 } 01097 01098 01099 $newFile = t3lib_div::resolveBackPath(PATH_site . $folder . $file); 01100 01101 if (!is_writable(dirname($newFile))) { 01102 $error = -1; 01103 } elseif (!t3lib_div::isAllowedAbsPath($newFile)) { 01104 $error = -2; 01105 } elseif (file_exists($newFile)) { 01106 $error = -3; 01107 } else { 01108 if ($isFolder) { 01109 $success = t3lib_div::mkdir($newFile); 01110 } else { 01111 $success = t3lib_div::writeFile($newFile, ''); 01112 } 01113 01114 if (!$success) { 01115 $error = -4; 01116 } 01117 } 01118 01119 return array( 01120 $success, 01121 $newFile, 01122 $error 01123 ); 01124 } 01125 01126 01127 /** 01128 * Wrapping input string in a link tag with link to email address 01129 * 01130 * @param string Input string, being wrapped in <a> tags 01131 * @param string Email address for use in link. 01132 * @return string Output 01133 */ 01134 public static function wrapEmail($str, $email) { 01135 if ($email) { 01136 $str = '<a href="mailto:' . htmlspecialchars($email) . '">' . htmlspecialchars($str) . '</a>'; 01137 } 01138 return $str; 01139 } 01140 01141 /** 01142 * red-fontwrap. Returns the string wrapped in a <span>-tag defining the color to be red 01143 * 01144 * @param string Input string 01145 * @return string Output string 01146 */ 01147 public static function rfw($string) { 01148 return '<span class="typo3-red">' . $string . '</span>'; 01149 } 01150 01151 /** 01152 * dimmed-fontwrap. Returns the string wrapped in a <span>-tag defining the color to be gray/dimmed 01153 * 01154 * @param string Input string 01155 * @return string Output string 01156 */ 01157 public static function dfw($string) { 01158 return '<span class="typo3-dimmed">' . $string . '</span>'; 01159 } 01160 } 01161 01162 ?>
1.8.0