2 /* **************************************************************
6 * (c) 2006-2010 Karsten Dambekalns <karsten@typo3.org>
9 * This script is part of the TYPO3 project. The TYPO3 project is
10 * free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * The GNU General Public License can be found at
16 * http://www.gnu.org/copyleft/gpl.html.
17 * A copy is found in the textfile GPL.txt and important notices to the license
18 * from the author is found in LICENSE.txt distributed with these scripts.
21 * This script is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * This copyright notice MUST APPEAR in all copies of the script!
27 ***************************************************************/
29 * class.tx_em_tools.php
31 * $Id: class.tx_em_tools.php 2084 2010-03-22 01:46:37Z steffenk $
35 * Static tools for extension manager
36 * Some of them should be moved later to t3lib static libraries
39 final class tx_em_Tools
{
42 * Keeps default categories.
46 static protected $defaultCategories = array('be' => 0,
57 * Keeps default states.
61 static protected $defaultStates = array('alpha' => 0,
67 'excludeFromUpdates' => 6,
72 * Unzips a zip file in the given path.
74 * Uses unzip binary if available, otherwise a pure PHP unzip is used.
76 * @param string $file Full path to zip file
77 * @param string $path Path to change to before extracting
78 * @return boolean True on success, false in failure
80 public function unzip($file, $path) {
81 if (strlen($GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'])) {
83 $cmd = $GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'] . ' -o ' . escapeshellarg($file);
84 exec($cmd, $list, $ret);
87 // we use a pure PHP unzip
88 $unzip = t3lib_div
::makeInstance('tx_em_Tools_Unzip', $file);
89 $ret = $unzip->extract(array('add_path' => $path));
90 return (is_array($ret));
96 * Refreshes the global extension list
100 function refreshGlobalExtList() {
101 global $TYPO3_LOADED_EXT;
103 $TYPO3_LOADED_EXT = t3lib_extMgm
::typo3_loadExtensions();
104 if ($TYPO3_LOADED_EXT['_CACHEFILE']) {
105 require(PATH_typo3conf
. $TYPO3_LOADED_EXT['_CACHEFILE'] . '_ext_localconf.php');
109 $GLOBALS['TYPO3_LOADED_EXT'] = t3lib_extMgm
::typo3_loadExtensions();
110 if ($TYPO3_LOADED_EXT['_CACHEFILE']) {
111 require(PATH_typo3conf
. $TYPO3_LOADED_EXT['_CACHEFILE'] . '_ext_localconf.php');
113 $temp_TYPO3_LOADED_EXT = $TYPO3_LOADED_EXT;
114 foreach ($temp_TYPO3_LOADED_EXT as $_EXTKEY => $temp_lEDat) {
115 if (is_array($temp_lEDat) && $temp_lEDat['ext_localconf.php']) {
116 $_EXTCONF = $GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY];
117 require($temp_lEDat['ext_localconf.php']);
124 * Set category array entries for extension
126 * @param array Category index array
127 * @param array Part of list array for extension.
128 * @param string Extension key
129 * @return array Modified category index array
131 public function setCat(&$cat, $listArrayPart, $extKey) {
133 // Getting extension title:
134 $extTitle = $listArrayPart['EM_CONF']['title'];
137 $index = $listArrayPart['EM_CONF']['category'];
138 $cat['cat'][$index][$extKey] = $extTitle;
141 $index = $listArrayPart['EM_CONF']['author'] . ($listArrayPart['EM_CONF']['author_company'] ?
', ' . $listArrayPart['EM_CONF']['author_company'] : '');
142 $cat['author_company'][$index][$extKey] = $extTitle;
145 $index = $listArrayPart['EM_CONF']['state'];
146 $cat['state'][$index][$extKey] = $extTitle;
149 $index = $listArrayPart['type'];
150 $cat['type'][$index][$extKey] = $extTitle;
152 // Return categories:
157 * Returns upload folder for extension
159 * @param string Extension key
160 * @return string Upload folder for extension
162 public function uploadFolder($extKey) {
163 return 'uploads/tx_' . str_replace('_', '', $extKey) . '/';
168 * Returns image tag for "uninstall"
170 * @return string <img> tag
172 public function removeButton() {
173 return t3lib_iconWorks
::getSpriteIcon('actions-system-extension-uninstall', array('title' => $GLOBALS['LANG']->getLL('ext_details_remove_ext')));
177 * Returns image for "install"
179 * @return string <img> tag
181 public function installButton() {
182 return t3lib_iconWorks
::getSpriteIcon('actions-system-extension-install', array('title' => $GLOBALS['LANG']->getLL('helperFunction_install_extension')));
186 * Warning (<img> + text string) message about the impossibility to import extensions (both local and global locations are disabled...)
188 * @return string <img> + text string.
190 public function noImportMsg() {
191 return t3lib_iconWorks
::getSpriteIcon('status-dialog-warning') .
192 '<strong>' . $GLOBALS['LANG']->getLL('helperFunction_import_not_possible') . '</strong>';
197 * Fixes an old style ext_emconf.php array by adding constraints if needed and removing deprecated keys
199 * @param array $emConf
202 public function fixEMCONF($emConf) {
203 if (!isset($emConf['constraints']) ||
!isset($emConf['constraints']['depends']) ||
!isset($emConf['constraints']['conflicts']) ||
!isset($emConf['constraints']['suggests'])) {
204 if (!isset($emConf['constraints']) ||
!isset($emConf['constraints']['depends'])) {
205 $emConf['constraints']['depends'] = self
::stringToDep($emConf['dependencies']);
206 if (strlen($emConf['PHP_version'])) {
207 $versionRange = self
::splitVersionRange($emConf['PHP_version']);
208 if (version_compare($versionRange[0], '3.0.0', '<')) {
209 $versionRange[0] = '3.0.0';
211 if (version_compare($versionRange[1], '3.0.0', '<')) {
212 $versionRange[1] = '0.0.0';
214 $emConf['constraints']['depends']['php'] = implode('-', $versionRange);
216 if (strlen($emConf['TYPO3_version'])) {
217 $versionRange = self
::splitVersionRange($emConf['TYPO3_version']);
218 if (version_compare($versionRange[0], '3.5.0', '<')) {
219 $versionRange[0] = '3.5.0';
221 if (version_compare($versionRange[1], '3.5.0', '<')) {
222 $versionRange[1] = '0.0.0';
224 $emConf['constraints']['depends']['typo3'] = implode('-', $versionRange);
227 if (!isset($emConf['constraints']) ||
!isset($emConf['constraints']['conflicts'])) {
228 $emConf['constraints']['conflicts'] = self
::stringToDep($emConf['conflicts']);
230 if (!isset($emConf['constraints']) ||
!isset($emConf['constraints']['suggests'])) {
231 $emConf['constraints']['suggests'] = array();
233 } elseif (isset($emConf['constraints']) && isset($emConf['dependencies'])) {
234 $emConf['suggests'] = isset($emConf['suggests']) ?
$emConf['suggests'] : array();
235 $emConf['dependencies'] = self
::depToString($emConf['constraints']);
236 $emConf['conflicts'] = self
::depToString($emConf['constraints'], 'conflicts');
239 // sanity check for version numbers, intentionally only checks php and typo3
240 if (isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['php'])) {
241 $versionRange = self
::splitVersionRange($emConf['constraints']['depends']['php']);
242 if (version_compare($versionRange[0], '3.0.0', '<')) {
243 $versionRange[0] = '3.0.0';
245 if (version_compare($versionRange[1], '3.0.0', '<')) {
246 $versionRange[1] = '0.0.0';
248 $emConf['constraints']['depends']['php'] = implode('-', $versionRange);
250 if (isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['typo3'])) {
251 $versionRange = self
::splitVersionRange($emConf['constraints']['depends']['typo3']);
252 if (version_compare($versionRange[0], '3.5.0', '<')) {
253 $versionRange[0] = '3.5.0';
255 if (version_compare($versionRange[1], '3.5.0', '<')) {
256 $versionRange[1] = '0.0.0';
258 $emConf['constraints']['depends']['typo3'] = implode('-', $versionRange);
261 unset($emConf['private']);
262 unset($emConf['download_password']);
263 unset($emConf['TYPO3_version']);
264 unset($emConf['PHP_version']);
271 * Returns the $EM_CONF array from an extensions ext_emconf.php file
273 * @param string Absolute path to EMCONF file.
274 * @param string Extension key.
275 * @return array EMconf array values.
277 public function includeEMCONF($path, $_EXTKEY) {
280 if (is_array($EM_CONF[$_EXTKEY])) {
281 return self
::fixEMCONF($EM_CONF[$_EXTKEY]);
288 * Extracts the directories in the $files array
290 * @param array Array of files / directories
291 * @return array Array of directories from the input array.
293 function extractDirsFromFileList($files) {
296 if (is_array($files)) {
297 // Traverse files / directories array:
298 foreach ($files as $file) {
299 if (substr($file, -1) == '/') {
300 $dirs[$file] = $file;
302 $pI = pathinfo($file);
303 if (strcmp($pI['dirname'], '') && strcmp($pI['dirname'], '.')) {
304 $dirs[$pI['dirname'] . '/'] = $pI['dirname'] . '/';
313 * Splits a version range into an array.
315 * If a single version number is given, it is considered a minimum value.
316 * If a dash is found, the numbers left and right are considered as minimum and maximum. Empty values are allowed.
318 * @param string $ver A string with a version range.
321 public function splitVersionRange($ver) {
322 $versionRange = array();
323 if (strstr($ver, '-')) {
324 $versionRange = explode('-', $ver, 2);
326 $versionRange[0] = $ver;
327 $versionRange[1] = '';
330 if (!$versionRange[0]) {
331 $versionRange[0] = '0.0.0';
333 if (!$versionRange[1]) {
334 $versionRange[1] = '0.0.0';
337 return $versionRange;
341 * Checks whether the passed dependency is TER2-style (array) and returns a single string for displaying the dependencies.
343 * It leaves out all version numbers and the "php" and "typo3" dependencies, as they are implicit and of no interest without the version number.
345 * @param mixed $dep Either a string or an array listing dependencies.
346 * @param string $type The dependency type to list if $dep is an array
347 * @return string A simple dependency list for display
349 public function depToString($dep, $type = 'depends') {
350 if (is_array($dep)) {
351 unset($dep[$type]['php']);
352 unset($dep[$type]['typo3']);
353 $s = (count($dep[$type])) ?
implode(',', array_keys($dep[$type])) : '';
360 * Checks whether the passed dependency is TER-style (string) or TER2-style (array) and returns a single string for displaying the dependencies.
362 * It leaves out all version numbers and the "php" and "typo3" dependencies, as they are implicit and of no interest without the version number.
364 * @param mixed $dep Either a string or an array listing dependencies.
365 * @param string $type The dependency type to list if $dep is an array
366 * @return string A simple dependency list for display
368 public function stringToDep($dep) {
369 $constraint = array();
370 if (is_string($dep) && strlen($dep)) {
371 $dep = explode(',', $dep);
372 foreach ($dep as $v) {
373 $constraint[$v] = '';
381 * Returns version information
383 * @param string Version code, x.x.x
384 * @param string part: "", "int", "main", "sub", "dev"
386 * @see renderVersion()
388 public function makeVersion($v, $mode) {
389 $vDat = self
::renderVersion($v);
390 return $vDat['version_' . $mode];
394 * Parses the version number x.x.x and returns an array with the various parts.
396 * @param string Version code, x.x.x
397 * @param string Increase version part: "main", "sub", "dev"
400 public function renderVersion($v, $raise = '') {
401 $parts = t3lib_div
::intExplode('.', $v . '..');
402 $parts[0] = t3lib_div
::intInRange($parts[0], 0, 999);
403 $parts[1] = t3lib_div
::intInRange($parts[1], 0, 999);
404 $parts[2] = t3lib_div
::intInRange($parts[2], 0, 999);
406 switch ((string) $raise) {
422 $res['version'] = $parts[0] . '.' . $parts[1] . '.' . $parts[2];
423 $res['version_int'] = intval($parts[0] * 1000000 +
$parts[1] * 1000 +
$parts[2]);
424 $res['version_main'] = $parts[0];
425 $res['version_sub'] = $parts[1];
426 $res['version_dev'] = $parts[2];
432 * Evaluates differences in version numbers with three parts, x.x.x. Returns true if $v1 is greater than $v2
434 * @param string Version number 1
435 * @param string Version number 2
436 * @param integer Tolerance factor. For instance, set to 1000 to ignore difference in dev-version (third part)
437 * @return boolean True if version 1 is greater than version 2
439 public function versionDifference($v1, $v2, $div = 1) {
440 return floor(self
::makeVersion($v1, 'int') / $div) > floor(self
::makeVersion($v2, 'int') / $div);
445 * Returns true if the $str is found as the first part of a string in $array
447 * @param string String to test with.
448 * @param array Input array
449 * @param boolean If set, the test is case insensitive
450 * @return boolean True if found.
452 public function first_in_array($str, $array, $caseInsensitive = FALSE) {
453 if ($caseInsensitive) {
454 $str = strtolower($str);
456 if (is_array($array)) {
457 foreach ($array as $cl) {
458 if ($caseInsensitive) {
459 $cl = strtolower($cl);
461 if (t3lib_div
::isFirstPartOfStr($cl, $str)) {
470 * Compares two arrays with MD5-hash values for analysis of which files has changed.
472 * @param array Current values
473 * @param array Past values
474 * @return array Affected files
476 function findMD5ArrayDiff($current, $past) {
477 if (!is_array($current)) {
480 if (!is_array($past)) {
483 $filesInCommon = array_intersect($current, $past);
484 $diff1 = array_keys(array_diff($past, $filesInCommon));
485 $diff2 = array_keys(array_diff($current, $filesInCommon));
486 $affectedFiles = array_unique(array_merge($diff1, $diff2));
487 return $affectedFiles;
491 * Returns title and style attribute for mouseover help text.
493 * @param string Help text.
494 * @return string title="" attribute prepended with a single space
496 public function labelInfo($str) {
497 return ' title="' . htmlspecialchars($str) . '" style="cursor:help;"';
502 * Returns the absolute path where the extension $extKey is installed (based on 'type' (SGL))
504 * @param string Extension key
505 * @param string Install scope type: L, G, S
506 * @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.
508 public function getExtPath($extKey, $type, $returnWithoutExtKey = FALSE) {
509 $typePath = self
::typePath($type);
512 $path = $typePath . ($returnWithoutExtKey ?
'' : $extKey . '/');
513 return $path; # @is_dir($path) ? $path : '';
520 * Get type of extension (G,S,L) from extension path
522 * @param string $path
524 public function getExtTypeFromPath($path) {
525 if (strpos($path, TYPO3_mainDir
. 'sysext/') !== false) {
527 } elseif (strpos($path, TYPO3_mainDir
. 'ext/') !== false) {
529 } elseif (strpos($path, 'typo3conf/ext/') !== false) {
537 * @param string $type S/G/L
539 public function typePath($type) {
541 return PATH_typo3
. 'sysext/';
542 } elseif ($type === 'G') {
543 return PATH_typo3
. 'ext/';
544 } elseif ($type === 'L') {
545 return PATH_typo3conf
. 'ext/';
550 * Get relative path from type
552 * @param string $type S/G/L
554 public function typeRelPath($type) {
557 } elseif ($type === 'G') {
559 } elseif ($type === 'L') {
560 return '../typo3conf/ext/';
565 * Get backpath from type
567 * @param string $type S/G/L
569 public function typeBackPath($type) {
571 return '../../../../' . TYPO3_mainDir
;
578 * Reads locallang file into array (for possible include in header)
582 public function getArrayFromLocallang($file, $key = 'default') {
583 $content = t3lib_div
::getURL($file);
584 $array = t3lib_div
::xml2array($content);
585 return $array['data'][$key];
590 * Include a locallang file and return the $LOCAL_LANG array serialized.
592 * @param string Absolute path to locallang file to include.
593 * @param string Old content of a locallang file (keeping the header content)
594 * @return array Array with header/content as key 0/1
595 * @see makeUploadarray()
597 function getSerializedLocalLang($file, $content) {
599 $returnParts = explode('$LOCAL_LANG', $content, 2);
602 if (is_array($LOCAL_LANG)) {
603 $returnParts[1] = serialize($LOCAL_LANG);
612 * Enter description here...
614 * @param unknown_type $array
615 * @param unknown_type $lines
616 * @param unknown_type $level
619 function arrayToCode($array, $level = 0) {
620 $lines = 'array(' . LF
;
622 foreach ($array as $k => $v) {
623 if (strlen($k) && is_array($v)) {
624 $lines .= str_repeat(TAB
, $level) . "'" . $k . "' => " . self
::arrayToCode($v, $level);
625 } elseif (strlen($k)) {
626 $lines .= str_repeat(TAB
, $level) . "'" . $k . "' => " . (t3lib_div
::testInt($v) ?
intval($v) : "'" . t3lib_div
::slashJS(trim($v), 1) . "'") . ',' . LF
;
630 $lines .= str_repeat(TAB
, $level - 1) . ')' . ($level - 1 == 0 ?
'' : ',' . LF
);
636 * Traverse the array of installed extensions keys and arranges extensions in the priority order they should be in
638 * @param array Array of extension keys as values
639 * @param array Extension information array
640 * @return array Modified array of extention keys as values
641 * @see addExtToList()
643 function managesPriorities($listArr, $instExtInfo) {
652 // Traverse list of extensions:
653 foreach ($listArr as $ext) {
654 $prio = trim($instExtInfo[$ext]['EM_CONF']['priority']);
655 switch ((string) $prio) {
658 $levels[$prio][] = $ext;
661 $levels['middle'][] = $ext;
674 * Returns either array with all default categories or index/title
675 * of a category entry.
678 * @param mixed $cat category title or category index
681 static public function getDefaultCategory($cat = NULL) {
683 return self
::$defaultCategories;
685 if (is_string($cat)) {
688 if (array_key_exists(strtolower($cat), self
::$defaultCategories)) {
689 $catIndex = self
::$defaultCategories[strtolower($cat)];
693 if (is_int($cat) && $cat >= 0) {
694 $catTitle = array_search($cat, self
::$defaultCategories);
706 * Returns either array with all default states or index/title
710 * @param mixed $state state title or state index
713 static public function getDefaultState($state = NULL) {
714 if (is_null($state)) {
715 return self
::$defaultStates;
717 if (is_string($state)) {
720 if (array_key_exists(strtolower($state), self
::$defaultStates)) {
721 $stateIndex = self
::$defaultStates[strtolower($state)];
725 if (is_int($state) && $state >= 0) {
726 $stateTitle = array_search($state, self
::$defaultStates);
738 * Reports back if installation in a certain scope is possible.
740 * @param string Scope: G, L, S
741 * @param string Extension lock-type (eg. "L" or "G")
742 * @return boolean True if installation is allowed.
744 function importAsType($type, $lockType = '') {
747 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] && (!$lockType ||
!strcmp($lockType, $type));
750 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'] && (!$lockType ||
!strcmp($lockType, $type));
753 return $this->systemInstall
;
761 * Returns true if extensions in scope, $type, can be deleted (or installed for that sake)
763 * @param string Scope: "G" or "L"
764 * @return boolean True if possible.
766 function deleteAsType($type) {
769 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'];
772 return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'];
781 * Creates directories in $extDirPath
783 * @param array Array of directories to create relative to extDirPath, eg. "blabla", "blabla/blabla" etc...
784 * @param string Absolute path to directory.
785 * @return mixed Returns false on success or an error string
787 function createDirsInPath($dirs, $extDirPath) {
788 if (is_array($dirs)) {
789 foreach ($dirs as $dir) {
790 $error = t3lib_div
::mkdir_deep($extDirPath, $dir);
801 * Analyses the php-scripts of an available extension on server
803 * @param string Absolute path to extension
804 * @param string Prefix for tables/classes.
805 * @param string Extension key
806 * @return array Information array.
807 * @see makeDetailedExtensionAnalysis()
809 function getClassIndexLocallangFiles($absPath, $table_class_prefix, $extKey) {
810 $filesInside = t3lib_div
::removePrefixPathFromList(t3lib_div
::getAllFilesAndFoldersInPath(array(), $absPath, 'php,inc', 0, 99, $this->excludeForPackaging
), $absPath);
814 foreach ($filesInside as $fileName) {
815 if (substr($fileName, 0, 4) != 'ext_' && substr($fileName, 0, 6) != 'tests/') { // ignore supposed-to-be unit tests as well
816 $baseName = basename($fileName);
817 if (substr($baseName, 0, 9) == 'locallang' && substr($baseName, -4) == '.php') {
818 $out['locallang'][] = $fileName;
819 } elseif ($baseName != 'conf.php') {
820 if (filesize($absPath . $fileName) < 500 * 1024) {
821 $fContent = t3lib_div
::getUrl($absPath . $fileName);
823 if (preg_match('/\n[[:space:]]*class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/', $fContent, $reg)) {
826 $lines = explode(LF
, $fContent);
827 foreach ($lines as $l) {
830 if (preg_match('/^class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/', $line, $reg)) {
831 $out['classes'][] = $reg[1];
832 $out['files'][$fileName]['classes'][] = $reg[1];
833 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])) {
834 $out['NSerrors']['classname'][] = $reg[1];
836 $out['NSok']['classname'][] = $reg[1];
840 // If class file prefixed 'class.'....
841 if (substr($baseName, 0, 6) == 'class.') {
842 $fI = pathinfo($baseName);
843 $testName = substr($baseName, 6, -(1 +
strlen($fI['extension'])));
844 if ($testName!=='ext_update' && substr($testName, 0, 3) != 'ux_' && !t3lib_div
::isFirstPartOfStr($testName, $table_class_prefix) && strcmp(substr($table_class_prefix, 0, -1), $testName)) {
845 $out['NSerrors']['classfilename'][] = $baseName;
847 $out['NSok']['classfilename'][] = $baseName;
848 if (is_array($out['files'][$fileName]['classes']) && tx_em_Tools
::first_in_array($testName, $out['files'][$fileName]['classes'], 1)) {
849 $out['msg'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_class_ok'),
853 $out['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_class_not_ok'),
859 // Check for proper XCLASS definition
860 // Match $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS'] with single or doublequotes
861 $XclassSearch = '\$TYPO3_CONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]';
862 $XclassParts = preg_split('/if \(defined\([\'"]TYPO3_MODE[\'"]\) && ' . $XclassSearch . '/', $fContent, 2);
863 if (count($XclassParts) !== 2) {
864 // Match $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS'] with single or doublequotes
865 $XclassSearch = '\$GLOBALS\[[\'"]TYPO3_CONF_VARS[\'"]\]\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]';
866 $XclassParts = preg_split('/if \(defined\([\'"]TYPO3_MODE[\'"]\) && ' . $XclassSearch . '/', $fContent, 2);
868 if (count($XclassParts) == 2) {
870 preg_match('/^\[[\'"]([[:alnum:]_\/\.]*)[\'"]\]/', $XclassParts[1], $reg);
872 $cmpF = 'ext/' . $extKey . '/' . $fileName;
873 if (!strcmp($reg[1], $cmpF)) {
874 if (preg_match('/_once[[:space:]]*\(' . $XclassSearch . '\[[\'"]' . preg_quote($cmpF, '/') . '[\'"]\]\);/', $XclassParts[1])) {
875 $out['msg'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_xclass_ok'), $fileName);
877 $out['errors'][] = $GLOBALS['LANG']->getLL('detailedExtAnalysis_xclass_no_include');
880 $out['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_xclass_incorrect'),
885 $out['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_no_xclass_filename'), $fileName);
887 } elseif (!tx_em_Tools
::first_in_array('ux_', $out['files'][$fileName]['classes'])) {
888 // No Xclass definition required if classname starts with 'ux_'
889 $out['errors'][] = sprintf($GLOBALS['LANG']->getLL('detailedExtAnalysis_no_xclass_found'), $fileName);
900 * Write new TYPO3_MOD_PATH to "conf.php" file.
902 * @param string Absolute path to a "conf.php" file of the backend module which we want to write back to.
903 * @param string Install scope type: L, G, S
904 * @param string Relative path for the module folder in extension
905 * @return string Returns message about the status.
906 * @see modConfFileAnalysis()
908 function writeTYPO3_MOD_PATH($confFilePath, $type, $mP) {
909 $lines = explode(LF
, t3lib_div
::getUrl($confFilePath));
910 $confFileInfo = array();
911 $confFileInfo['lines'] = $lines;
918 foreach ($lines as $k => $l) {
922 if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/', $line, $reg)) {
923 $lines[$k] = str_replace($reg[0], 'define(\'TYPO3_MOD_PATH\', \'' . self
::typeRelPath($type) . $mP . '\');', $lines[$k]);
928 if (preg_match('/^\$BACK_PATH[[:space:]]*=[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*;/', $line, $reg)) {
929 $lines[$k] = str_replace($reg[0], '$BACK_PATH=\'' . self
::typeBackPath($type) . '\';', $lines[$k]);
933 // Check if this module uses new API (see http://bugs.typo3.org/view.php?id=5278)
934 // where TYPO3_MOD_PATH and BACK_PATH are not required
936 if (preg_match('/^\$MCONF\[["\']script["\']\][[:space:]]*=[[:space:]]*["\']_DISPATCH["\'][[:space:]]*;/', $line, $reg)) {
937 $flag_Dispatch = $k +
1;
942 if ($flag_B && $flag_M) {
943 t3lib_div
::writeFile($confFilePath, implode(LF
, $lines));
944 return sprintf($GLOBALS['LANG']->getLL('writeModPath_ok'),
945 substr($confFilePath, strlen(PATH_site
)));
946 } elseif ($flag_Dispatch) {
948 $GLOBALS['LANG']->getLL('writeModPath_notRequired'),
949 substr($confFilePath, strlen(PATH_site
))
952 return $GLOBALS["TBE_TEMPLATE"]->rfw(
953 sprintf($GLOBALS['LANG']->getLL('writeModPath_error'),
960 * Wrapping input string in a link tag with link to email address
962 * @param string Input string, being wrapped in <a> tags
963 * @param string Email address for use in link.
964 * @return string Output
966 function wrapEmail($str, $email) {
968 $str = '<a href="mailto:' . htmlspecialchars($email) . '">' . htmlspecialchars($str) . '</a>';
974 * red-fontwrap. Returns the string wrapped in a <span>-tag defining the color to be red
976 * @param string Input string
977 * @return string Output string
979 function rfw($string) {
980 return '<span class="typo3-red">' . $string . '</span>';
984 * dimmed-fontwrap. Returns the string wrapped in a <span>-tag defining the color to be gray/dimmed
986 * @param string Input string
987 * @return string Output string
989 function dfw($string) {
990 return '<span class="typo3-dimmed">' . $string . '</span>';