|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 /** 00028 * Class to setup values in localconf.php and verify the TYPO3 DB tables/fields 00029 * 00030 * $Id: class.t3lib_install.php 10547 2011-02-22 20:03:57Z lolli $ 00031 * 00032 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00033 */ 00034 /** 00035 * [CLASS/FUNCTION INDEX of SCRIPT] 00036 * 00037 * 00038 * 00039 * 83: class t3lib_install 00040 * 108: function t3lib_install() 00041 * 00042 * SECTION: Writing to localconf.php 00043 * 132: function setValueInLocalconfFile(&$line_array, $variable, $value) 00044 * 183: function writeToLocalconf_control($inlines='',$absFullPath='') 00045 * 253: function checkForBadString($string) 00046 * 266: function slashValueForSingleDashes($value) 00047 * 00048 * SECTION: SQL 00049 * 291: function getFieldDefinitions_fileContent($fileContent) 00050 * 359: function getFieldDefinitions_sqlContent_parseTypes(&$total) 00051 * 406: function getFieldDefinitions_database() 00052 * 450: function getDatabaseExtra($FDsrc, $FDcomp, $onlyTableList='') 00053 * 496: function getUpdateSuggestions($diffArr,$keyList='extra,diff') 00054 * 589: function assembleFieldDefinition($row) 00055 * 611: function getStatementArray($sqlcode,$removeNonSQL=0,$query_regex='') 00056 * 649: function getCreateTables($statements, $insertCountFlag=0) 00057 * 683: function getTableInsertStatements($statements, $table) 00058 * 704: function performUpdateQueries($arr,$keyArr) 00059 * 720: function getListOfTables() 00060 * 736: function generateUpdateDatabaseForm_checkboxes($arr,$label,$checked=1,$iconDis=0,$currentValue=array(),$cVfullMsg=0) 00061 * 00062 * TOTAL FUNCTIONS: 17 00063 * (This index is automatically created/updated by the extension "extdeveval") 00064 * 00065 */ 00066 00067 00068 /** 00069 * Class to setup values in localconf.php and verify the TYPO3 DB tables/fields 00070 * 00071 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00072 * @package TYPO3 00073 * @subpackage t3lib 00074 */ 00075 class t3lib_install { 00076 00077 00078 // External, Static 00079 var $updateIdentity = ''; // Set to string which identifies the script using this class. 00080 var $deletedPrefixKey = 'zzz_deleted_'; // Prefix used for tables/fields when deleted/renamed. 00081 var $dbUpdateCheckboxPrefix = 'TYPO3_INSTALL[database_update]'; // Prefix for checkbox fields when updating database. 00082 var $localconf_addLinesOnly = 0; // If this is set, modifications to localconf.php is done by adding new lines to the array only. If unset, existing values are recognized and changed. 00083 var $localconf_editPointToken = 'INSTALL SCRIPT EDIT POINT TOKEN - all lines after this points may be changed by the install script!'; // If set and addLinesOnly is disabled, lines will be change only if they are after this token (on a single line!) in the file 00084 var $allowUpdateLocalConf = 0; // If true, this class will allow the user to update the localconf.php file. Is set true in the init.php file. 00085 var $backPath = '../'; // Backpath (used for icons etc.) 00086 00087 var $multiplySize = 1; // Multiplier of SQL field size (for char, varchar and text fields) 00088 var $character_sets = array(); // Caching output of $GLOBALS['TYPO3_DB']->admin_get_charsets() 00089 00090 // Internal, dynamic: 00091 var $setLocalconf = 0; // Used to indicate that a value is change in the line-array of localconf and that it should be written. 00092 var $messages = array(); // Used to set (error)messages from the executing functions like mail-sending, writing Localconf and such 00093 var $touchedLine = 0; // updated with line in localconf.php file that was changed. 00094 00095 00096 /** 00097 * Constructor function 00098 * 00099 * @return void 00100 */ 00101 function t3lib_install() { 00102 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize'] >= 1 && $GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize'] <= 5) { 00103 $this->multiplySize = (double) $GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize']; 00104 } 00105 } 00106 00107 00108 /************************************** 00109 * 00110 * Writing to localconf.php 00111 * 00112 00113 **************************************/ 00114 00115 /** 00116 * This functions takes an array with lines from localconf.php, finds a variable and inserts the new value. 00117 * 00118 * @param array $line_array the localconf.php file exploded into an array by linebreaks. (see writeToLocalconf_control()) 00119 * @param string $variable The variable name to find and substitute. This string must match the first part of a trimmed line in the line-array. Matching is done backwards so the last appearing line will be substituted. 00120 * @param string $value Is the value to be insert for the variable 00121 * @param boolean $quoteValue Whether the given value should be quoted before being written 00122 * @return void 00123 * @see writeToLocalconf_control() 00124 */ 00125 public function setValueInLocalconfFile(&$line_array, $variable, $value, $quoteValue = TRUE) { 00126 if (!$this->checkForBadString($value)) { 00127 return 0; 00128 } 00129 00130 // Initialize: 00131 $found = 0; 00132 $this->touchedLine = ''; 00133 $commentKey = '## '; 00134 $inArray = in_array($commentKey . $this->localconf_editPointToken, $line_array); 00135 $tokenSet = ($this->localconf_editPointToken && !$inArray); // Flag is set if the token should be set but is not yet... 00136 $stopAtToken = ($this->localconf_editPointToken && $inArray); 00137 $comment = ' Modified or inserted by ' . $this->updateIdentity . '.'; 00138 $replace = array('["', '"]'); 00139 $search = array('[\'', '\']'); 00140 $varDoubleQuotes = str_replace($search, $replace, $variable); 00141 00142 // Search for variable name: 00143 if (!$this->localconf_addLinesOnly && !$tokenSet) { 00144 $line_array = array_reverse($line_array); 00145 foreach ($line_array as $k => $v) { 00146 $v2 = trim($v); 00147 if ($stopAtToken && !strcmp($v2, $commentKey . $this->localconf_editPointToken)) { 00148 break; 00149 } // If stopAtToken and token found, break out of the loop.. 00150 if (!strcmp(substr($v2, 0, strlen($variable . ' ')), $variable . ' ')) { 00151 $mainparts = explode($variable, $v, 2); 00152 if (count($mainparts) == 2) { // should ALWAYS be.... 00153 $subparts = explode('//', $mainparts[1], 2); 00154 if ($quoteValue) { 00155 $value = '\'' . $this->slashValueForSingleDashes($value) . '\''; 00156 } 00157 $line_array[$k] = $mainparts[0] . $variable . " = " . $value . "; " . ('//' . $comment . str_replace($comment, '', $subparts[1])); 00158 $this->touchedLine = count($line_array) - $k - 1; 00159 $found = 1; 00160 break; 00161 } 00162 } elseif (!strcmp(substr($v2, 0, strlen($varDoubleQuotes . ' ')), $varDoubleQuotes . ' ')) { 00163 // Due to a bug in the update wizard (fixed in TYPO3 4.1.7) it is possible 00164 // that $TYPO3_CONF_VARS['SYS']['compat_version'] was enclosed by "" (double 00165 // quotes) instead of the expected '' (single quotes) when is was written to 00166 // localconf.php. The following code was added to make sure that values with 00167 // double quotes are updated, too. 00168 $mainparts = explode($varDoubleQuotes, $v, 2); 00169 if (count($mainparts) == 2) { // should ALWAYS be.... 00170 $subparts = explode('//', $mainparts[1], 2); 00171 if ($quoteValue) { 00172 $value = '\'' . $this->slashValueForSingleDashes($value) . '\''; 00173 } 00174 $line_array[$k] = $mainparts[0] . $variable . " = " . $value . "; " . ('//' . $comment . str_replace($comment, '', $subparts[1])); 00175 $this->touchedLine = count($line_array) - $k - 1; 00176 $found = 1; 00177 break; 00178 } 00179 } 00180 } 00181 $line_array = array_reverse($line_array); 00182 } 00183 if (!$found) { 00184 if ($tokenSet) { 00185 $line_array[] = $commentKey . $this->localconf_editPointToken; 00186 $line_array[] = ''; 00187 } 00188 if ($quoteValue) { 00189 $value = '\'' . $this->slashValueForSingleDashes($value) . '\''; 00190 } 00191 $line_array[] = $variable . " = " . $value . "; // " . $comment; 00192 $this->touchedLine = -1; 00193 } 00194 if ($variable == '$typo_db_password') { 00195 $this->messages[] = 'Updated ' . $variable; 00196 } else { 00197 $this->messages[] = $variable . " = " . htmlspecialchars($value); 00198 } 00199 $this->setLocalconf = 1; 00200 } 00201 00202 /** 00203 * Takes an array with lines from localconf.php, finds a variable and inserts the new array value. 00204 * 00205 * @param array $lines the localconf.php file exploded into an array by line breaks. {@see writeToLocalconf_control()} 00206 * @param string $variable the variable name to find and substitute. This string must match the first part of a trimmed line in the line-array. Matching is done backwards so the last appearing line will be substituted. 00207 * @param array $value value to be assigned to the variable 00208 * @return void 00209 * @see writeToLocalconf_control() 00210 */ 00211 public function setArrayValueInLocalconfFile(array &$lines, $variable, array $value) { 00212 $commentKey = '## '; 00213 $inArray = in_array($commentKey . $this->localconf_editPointToken, $lines); 00214 $tokenSet = $this->localconf_editPointToken && !$inArray; // Flag is set if the token should be set but is not yet 00215 $stopAtToken = $this->localconf_editPointToken && $inArray; 00216 $comment = 'Modified or inserted by ' . $this->updateIdentity . '.'; 00217 $format = "%s = %s;\t// " . $comment; 00218 00219 $insertPos = count($lines); 00220 $startPos = 0; 00221 if (!($this->localconf_addLinesOnly || $tokenSet)) { 00222 for ($i = count($lines) - 1; $i > 0; $i--) { 00223 $line = trim($lines[$i]); 00224 if ($stopAtToken && t3lib_div::isFirstPartOfStr($line, $this->localconf_editPointToken)) { 00225 break; 00226 } 00227 if (t3lib_div::isFirstPartOfStr($line, '?>')) { 00228 $insertPos = $i; 00229 } 00230 if (t3lib_div::isFirstPartOfStr($line, $variable)) { 00231 $startPos = $i; 00232 break; 00233 } 00234 } 00235 } 00236 if ($startPos) { 00237 $this->touchedLine = $startPos; 00238 $endPos = $startPos; 00239 for ($i = $startPos; $i < count($lines); $i++) { 00240 $line = trim($lines[$i]); 00241 if (t3lib_div::isFirstPartOfStr($line, ');')) { 00242 $endPos = $i; 00243 break; 00244 } 00245 } 00246 00247 $startLines = array_slice($lines, 0, $startPos); 00248 $endLines = array_slice($lines, $endPos + 1); 00249 00250 $lines = $startLines; 00251 $definition = $this->array_export($value); 00252 $lines[] = sprintf($format, $variable, $definition); 00253 foreach ($endLines as $line) { 00254 $lines[] = $line; 00255 } 00256 } else { 00257 $lines[$insertPos] = sprintf($format, $variable, $this->array_export($value)); 00258 $lines[] = '?>'; 00259 $this->touchedLine = -1; 00260 } 00261 } 00262 00263 /** 00264 * Returns a parsable string representation of an array variable. This methods enhances 00265 * standard method var_export from PHP to take TYPO3's CGL into account. 00266 * 00267 * @param array $variable 00268 * @return string 00269 */ 00270 protected function array_export(array $variable) { 00271 $lines = explode("\n", var_export($variable, TRUE)); 00272 $out = 'array('; 00273 00274 for ($i = 1; $i < count($lines); $i++) { 00275 $out .= "\n"; 00276 // Make the space-indented declaration tab-indented instead 00277 while (substr($lines[$i], 0, 2) === ' ') { 00278 $out .= "\t"; 00279 $lines[$i] = substr($lines[$i], 2); 00280 } 00281 $out .= $lines[$i]; 00282 // Array declaration should be next to the assignment and no space between 00283 // "array" and its opening parenthesis should exist 00284 if (preg_match('/\s=>\s$/', $lines[$i])) { 00285 $out .= preg_replace('/^\s*array \(/', 'array(', $lines[$i + 1]); 00286 $i++; 00287 } 00288 } 00289 00290 return $out; 00291 } 00292 00293 /** 00294 * Writes or returns lines from localconf.php 00295 * 00296 * @param array Array of lines to write back to localconf.php. Possibly 00297 * @param string Absolute path of alternative file to use (Notice: this path is not validated in terms of being inside 'TYPO3 space') 00298 * @return mixed If $inlines is not an array it will return an array with the lines from localconf.php. Otherwise it will return a status string, either "continue" (updated) or "nochange" (not updated) 00299 * @see setValueInLocalconfFile() 00300 */ 00301 function writeToLocalconf_control($inlines = '', $absFullPath = '') { 00302 $tmpExt = '.TMP.php'; 00303 $writeToLocalconf_dat = array(); 00304 $writeToLocalconf_dat['file'] = $absFullPath ? $absFullPath : PATH_typo3conf . 'localconf.php'; 00305 $writeToLocalconf_dat['tmpfile'] = $writeToLocalconf_dat['file'] . $tmpExt; 00306 00307 // Checking write state of localconf.php: 00308 if (!$this->allowUpdateLocalConf) { 00309 throw new RuntimeException( 00310 'TYPO3 Fatal Error: ->allowUpdateLocalConf flag in the install object is not set and therefore "localconf.php" cannot be altered.', 00311 1270853915 00312 ); 00313 } 00314 if (!@is_writable($writeToLocalconf_dat['file'])) { 00315 throw new RuntimeException( 00316 'TYPO3 Fatal Error: ' . $writeToLocalconf_dat['file'] . ' is not writable!', 00317 1270853916 00318 ); 00319 } 00320 00321 // Splitting localconf.php file into lines: 00322 $lines = explode(LF, str_replace(CR, '', trim(t3lib_div::getUrl($writeToLocalconf_dat['file'])))); 00323 $writeToLocalconf_dat['endLine'] = array_pop($lines); // Getting "? >" ending. 00324 00325 // Checking if "updated" line was set by this tool - if so remove old line. 00326 $updatedLine = array_pop($lines); 00327 $writeToLocalconf_dat['updatedText'] = '// Updated by ' . $this->updateIdentity . ' '; 00328 00329 if (!strstr($updatedLine, $writeToLocalconf_dat['updatedText'])) { 00330 array_push($lines, $updatedLine); 00331 } 00332 00333 if (is_array($inlines)) { // Setting a line and write: 00334 // Setting configuration 00335 $updatedLine = $writeToLocalconf_dat['updatedText'] . date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' H:i:s'); 00336 array_push($inlines, $updatedLine); 00337 array_push($inlines, $writeToLocalconf_dat['endLine']); 00338 00339 if ($this->setLocalconf) { 00340 $success = $this->writeToLocalconf($inlines, $absFullPath); 00341 00342 if ($success) { 00343 return 'continue'; 00344 } else { 00345 return 'nochange'; 00346 } 00347 } else { 00348 return 'nochange'; 00349 } 00350 } else { // Return lines found in localconf.php 00351 return $lines; 00352 } 00353 } 00354 00355 /** 00356 * Writes lines to localconf.php. 00357 * 00358 * @param array Array of lines to write back to localconf.php 00359 * @param string Absolute path of alternative file to use (Notice: this path is not validated in terms of being inside 'TYPO3 space') 00360 * @return boolean TRUE if method succeeded, otherwise FALSE 00361 */ 00362 public function writeToLocalconf(array $lines, $absFullPath = '') { 00363 $tmpExt = '.TMP.php'; 00364 $writeToLocalconf_dat = array(); 00365 $writeToLocalconf_dat['file'] = $absFullPath ? $absFullPath : PATH_typo3conf . 'localconf.php'; 00366 $writeToLocalconf_dat['tmpfile'] = $writeToLocalconf_dat['file'] . $tmpExt; 00367 00368 // Checking write state of localconf.php: 00369 if (!$this->allowUpdateLocalConf) { 00370 throw new RuntimeException( 00371 'TYPO3 Fatal Error: ->allowUpdateLocalConf flag in the install object is not set and therefore "localconf.php" cannot be altered.', 00372 1270853915 00373 ); 00374 } 00375 if (!@is_writable($writeToLocalconf_dat['file'])) { 00376 throw new RuntimeException( 00377 'TYPO3 Fatal Error: ' . $writeToLocalconf_dat['file'] . ' is not writable!', 00378 1270853916 00379 ); 00380 } 00381 00382 $writeToLocalconf_dat['endLine'] = array_pop($lines); // Getting "? >" ending. 00383 if (!strstr('?' . '>', $writeToLocalconf_dat['endLine'])) { 00384 $lines[] = $writeToLocalconf_dat['endLine']; 00385 $writeToLocalconf_dat['endLine'] = '?' . '>'; 00386 } 00387 // Checking if "updated" line was set by this tool - if so remove old line. 00388 $updatedLine = array_pop($lines); 00389 $writeToLocalconf_dat['updatedText'] = '// Updated by ' . $this->updateIdentity . ' '; 00390 00391 if (!strstr($updatedLine, $writeToLocalconf_dat['updatedText'])) { 00392 $lines[] = $updatedLine; 00393 } 00394 00395 $updatedLine = $writeToLocalconf_dat['updatedText'] . date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] . ' H:i:s'); 00396 $lines[] = $updatedLine; 00397 $lines[] = $writeToLocalconf_dat['endLine']; 00398 00399 $success = FALSE; 00400 if (!t3lib_div::writeFile($writeToLocalconf_dat['tmpfile'], implode(LF, $lines))) { 00401 $msg = 'typo3conf/localconf.php' . $tmpExt . ' could not be written - maybe a write access problem?'; 00402 } 00403 elseif (strcmp(t3lib_div::getUrl($writeToLocalconf_dat['tmpfile']), implode(LF, $lines))) { 00404 @unlink($writeToLocalconf_dat['tmpfile']); 00405 $msg = 'typo3conf/localconf.php' . $tmpExt . ' was NOT written properly (written content didn\'t match file content) - maybe a disk space problem?'; 00406 } 00407 elseif (!@copy($writeToLocalconf_dat['tmpfile'], $writeToLocalconf_dat['file'])) { 00408 $msg = 'typo3conf/localconf.php could not be replaced by typo3conf/localconf.php' . $tmpExt . ' - maybe a write access problem?'; 00409 } 00410 else { 00411 @unlink($writeToLocalconf_dat['tmpfile']); 00412 $success = TRUE; 00413 $msg = 'Configuration written to typo3conf/localconf.php'; 00414 } 00415 $this->messages[] = $msg; 00416 00417 if (!$success) { 00418 t3lib_div::sysLog($msg, 'Core', 3); 00419 } 00420 00421 return $success; 00422 } 00423 00424 /** 00425 * Checking for linebreaks in the string 00426 * 00427 * @param string String to test 00428 * @return boolean Returns TRUE if string is OK 00429 * @see setValueInLocalconfFile() 00430 */ 00431 function checkForBadString($string) { 00432 return preg_match('/[' . LF . CR . ']/', $string) ? FALSE : TRUE; 00433 } 00434 00435 /** 00436 * Replaces ' with \' and \ with \\ 00437 * 00438 * @param string Input value 00439 * @return string Output value 00440 * @see setValueInLocalconfFile() 00441 */ 00442 function slashValueForSingleDashes($value) { 00443 $value = str_replace("'.LF.'", '###INSTALL_TOOL_LINEBREAK###', $value); 00444 $value = str_replace("'", "\'", str_replace('\\', '\\\\', $value)); 00445 $value = str_replace('###INSTALL_TOOL_LINEBREAK###', "'.LF.'", $value); 00446 00447 return $value; 00448 } 00449 00450 00451 /************************************* 00452 * 00453 * SQL 00454 * 00455 *************************************/ 00456 00457 /** 00458 * Reads the field definitions for the input SQL-file string 00459 * 00460 * @param string Should be a string read from an SQL-file made with 'mysqldump [database_name] -d' 00461 * @return array Array with information about table. 00462 */ 00463 function getFieldDefinitions_fileContent($fileContent) { 00464 $lines = t3lib_div::trimExplode(LF, $fileContent, 1); 00465 $table = ''; 00466 $total = array(); 00467 00468 foreach ($lines as $value) { 00469 if (substr($value, 0, 1) == '#') { 00470 continue; // Ignore comments 00471 } 00472 00473 if (!strlen($table)) { 00474 $parts = t3lib_div::trimExplode(' ', $value, TRUE); 00475 if (strtoupper($parts[0]) === 'CREATE' && strtoupper($parts[1]) === 'TABLE') { 00476 $table = str_replace('`', '', $parts[2]); 00477 if (TYPO3_OS == 'WIN') { // tablenames are always lowercase on windows! 00478 $table = strtolower($table); 00479 } 00480 } 00481 } else { 00482 if (substr($value, 0, 1) == ')' && substr($value, -1) == ';') { 00483 $ttype = array(); 00484 if (preg_match('/(ENGINE|TYPE)[ ]*=[ ]*([a-zA-Z]*)/', $value, $ttype)) { 00485 $total[$table]['extra']['ENGINE'] = $ttype[2]; 00486 } // Otherwise, just do nothing: If table engine is not defined, just accept the system default. 00487 00488 // Set the collation, if specified 00489 if (preg_match('/(COLLATE)[ ]*=[ ]*([a-zA-z0-9_-]+)/', $value, $tcollation)) { 00490 $total[$table]['extra']['COLLATE'] = $tcollation[2]; 00491 } else { 00492 // Otherwise, get the CHARACTER SET and try to find the default collation for it as returned by "SHOW CHARACTER SET" query (for details, see http://dev.mysql.com/doc/refman/5.1/en/charset-table.html) 00493 if (preg_match('/(CHARSET|CHARACTER SET)[ ]*=[ ]*([a-zA-z0-9_-]+)/', $value, $tcharset)) { // Note: Keywords "DEFAULT CHARSET" and "CHARSET" are the same, so "DEFAULT" can just be ignored 00494 $charset = $tcharset[2]; 00495 } else { 00496 $charset = $GLOBALS['TYPO3_DB']->default_charset; // Fallback to default charset 00497 } 00498 $total[$table]['extra']['COLLATE'] = $this->getCollationForCharset($charset); 00499 } 00500 00501 $table = ''; // Remove table marker and start looking for the next "CREATE TABLE" statement 00502 } else { 00503 $lineV = preg_replace('/,$/', '', $value); // Strip trailing commas 00504 $lineV = str_replace('`', '', $lineV); 00505 $lineV = str_replace(' ', ' ', $lineV); // Remove double blanks 00506 00507 $parts = explode(' ', $lineV, 2); 00508 if (!preg_match('/(PRIMARY|UNIQUE|FULLTEXT|INDEX|KEY)/', $parts[0])) { // Field definition 00509 00510 // Make sure there is no default value when auto_increment is set 00511 if (stristr($parts[1], 'auto_increment')) { 00512 $parts[1] = preg_replace('/ default \'0\'/i', '', $parts[1]); 00513 } 00514 // "default" is always lower-case 00515 if (stristr($parts[1], ' DEFAULT ')) { 00516 $parts[1] = str_ireplace(' DEFAULT ', ' default ', $parts[1]); 00517 } 00518 00519 // Change order of "default" and "null" statements 00520 $parts[1] = preg_replace('/(.*) (default .*) (NOT NULL)/', '$1 $3 $2', $parts[1]); 00521 $parts[1] = preg_replace('/(.*) (default .*) (NULL)/', '$1 $3 $2', $parts[1]); 00522 00523 $key = $parts[0]; 00524 $total[$table]['fields'][$key] = $parts[1]; 00525 00526 } else { // Key definition 00527 $search = array('/UNIQUE (INDEX|KEY)/', '/FULLTEXT (INDEX|KEY)/', '/INDEX/'); 00528 $replace = array('UNIQUE', 'FULLTEXT', 'KEY'); 00529 $lineV = preg_replace($search, $replace, $lineV); 00530 00531 if (preg_match('/PRIMARY|UNIQUE|FULLTEXT/', $parts[0])) { 00532 $parts[1] = preg_replace('/^(KEY|INDEX) /', '', $parts[1]); 00533 } 00534 00535 $newParts = explode(' ', $parts[1], 2); 00536 $key = $parts[0] == 'PRIMARY' ? $parts[0] : $newParts[0]; 00537 00538 $total[$table]['keys'][$key] = $lineV; 00539 00540 // This is a protection against doing something stupid: Only allow clearing of cache_* and index_* tables. 00541 if (preg_match('/^(cache|index)_/', $table)) { 00542 // Suggest to truncate (clear) this table 00543 $total[$table]['extra']['CLEAR'] = 1; 00544 } 00545 } 00546 } 00547 } 00548 } 00549 00550 $this->getFieldDefinitions_sqlContent_parseTypes($total); 00551 return $total; 00552 } 00553 00554 /** 00555 * Multiplies varchars/tinytext fields in size according to $this->multiplySize 00556 * Useful if you want to use UTF-8 in the database and needs to extend the field sizes in the database so UTF-8 chars are not discarded. For most charsets available as single byte sets, multiplication with 2 should be enough. For chinese, use 3. 00557 * 00558 * @param array Total array (from getFieldDefinitions_fileContent()) 00559 * @return void 00560 * @access private 00561 * @see getFieldDefinitions_fileContent() 00562 */ 00563 function getFieldDefinitions_sqlContent_parseTypes(&$total) { 00564 00565 $mSize = (double) $this->multiplySize; 00566 if ($mSize > 1) { 00567 00568 // Init SQL parser: 00569 $sqlParser = t3lib_div::makeInstance('t3lib_sqlparser'); 00570 foreach ($total as $table => $cfg) { 00571 if (is_array($cfg['fields'])) { 00572 foreach ($cfg['fields'] as $fN => $fType) { 00573 $orig_fType = $fType; 00574 $fInfo = $sqlParser->parseFieldDef($fType); 00575 00576 switch ($fInfo['fieldType']) { 00577 case 'char': 00578 case 'varchar': 00579 $newSize = round($fInfo['value'] * $mSize); 00580 00581 if ($newSize <= 255) { 00582 $fInfo['value'] = $newSize; 00583 } else { 00584 $fInfo = array( 00585 'fieldType' => 'text', 00586 'featureIndex' => array( 00587 'NOTNULL' => array( 00588 'keyword' => 'NOT NULL' 00589 ) 00590 ) 00591 ); 00592 // Change key definition if necessary (must use "prefix" on TEXT columns) 00593 if (is_array($cfg['keys'])) { 00594 foreach ($cfg['keys'] as $kN => $kType) { 00595 $match = array(); 00596 preg_match('/^([^(]*)\(([^)]+)\)(.*)/', $kType, $match); 00597 $keys = array(); 00598 foreach (t3lib_div::trimExplode(',', $match[2]) as $kfN) { 00599 if ($fN == $kfN) { 00600 $kfN .= '(' . $newSize . ')'; 00601 } 00602 $keys[] = $kfN; 00603 } 00604 $total[$table]['keys'][$kN] = $match[1] . '(' . implode(',', $keys) . ')' . $match[3]; 00605 } 00606 } 00607 } 00608 break; 00609 case 'tinytext': 00610 $fInfo['fieldType'] = 'text'; 00611 break; 00612 } 00613 00614 $total[$table]['fields'][$fN] = $sqlParser->compileFieldCfg($fInfo); 00615 if ($sqlParser->parse_error) { 00616 throw new RuntimeException( 00617 'TYPO3 Fatal Error: ' . $sqlParser->parse_error, 00618 1270853961 00619 ); 00620 } 00621 } 00622 } 00623 } 00624 } 00625 } 00626 00627 /** 00628 * Look up the default collation for specified character set based on "SHOW CHARACTER SET" output 00629 * 00630 * @param string Character set 00631 * @return string Corresponding default collation 00632 */ 00633 function getCollationForCharset($charset) { 00634 // Load character sets, if not cached already 00635 if (!count($this->character_sets)) { 00636 if (method_exists($GLOBALS['TYPO3_DB'], 'admin_get_charsets')) { 00637 $this->character_sets = $GLOBALS['TYPO3_DB']->admin_get_charsets(); 00638 } else { 00639 $this->character_sets[$charset] = array(); // Add empty element to avoid that the check will be repeated 00640 } 00641 } 00642 00643 $collation = ''; 00644 if (isset($this->character_sets[$charset]['Default collation'])) { 00645 $collation = $this->character_sets[$charset]['Default collation']; 00646 } 00647 00648 return $collation; 00649 } 00650 00651 /** 00652 * Reads the field definitions for the current database 00653 * 00654 * @return array Array with information about table. 00655 */ 00656 function getFieldDefinitions_database() { 00657 $total = array(); 00658 $tempKeys = array(); 00659 $tempKeysPrefix = array(); 00660 00661 $GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db); 00662 echo $GLOBALS['TYPO3_DB']->sql_error(); 00663 00664 $tables = $GLOBALS['TYPO3_DB']->admin_get_tables(TYPO3_db); 00665 foreach ($tables as $tableName => $tableStatus) { 00666 00667 // Fields: 00668 $fieldInformation = $GLOBALS['TYPO3_DB']->admin_get_fields($tableName); 00669 foreach ($fieldInformation as $fN => $fieldRow) { 00670 $total[$tableName]['fields'][$fN] = $this->assembleFieldDefinition($fieldRow); 00671 } 00672 00673 // Keys: 00674 $keyInformation = $GLOBALS['TYPO3_DB']->admin_get_keys($tableName); 00675 00676 foreach ($keyInformation as $keyRow) { 00677 $keyName = $keyRow['Key_name']; 00678 $colName = $keyRow['Column_name']; 00679 if ($keyRow['Sub_part']) { 00680 $colName .= '(' . $keyRow['Sub_part'] . ')'; 00681 } 00682 $tempKeys[$tableName][$keyName][$keyRow['Seq_in_index']] = $colName; 00683 if ($keyName == 'PRIMARY') { 00684 $prefix = 'PRIMARY KEY'; 00685 } else { 00686 if ($keyRow['Index_type'] == 'FULLTEXT') { 00687 $prefix = 'FULLTEXT'; 00688 } elseif ($keyRow['Non_unique']) { 00689 $prefix = 'KEY'; 00690 } else { 00691 $prefix = 'UNIQUE'; 00692 } 00693 $prefix .= ' ' . $keyName; 00694 } 00695 $tempKeysPrefix[$tableName][$keyName] = $prefix; 00696 } 00697 00698 // Table status (storage engine, collaction, etc.) 00699 if (is_array($tableStatus)) { 00700 $tableExtraFields = array( 00701 'Engine' => 'ENGINE', 00702 'Collation' => 'COLLATE', 00703 ); 00704 00705 foreach ($tableExtraFields as $mysqlKey => $internalKey) { 00706 if (isset($tableStatus[$mysqlKey])) { 00707 $total[$tableName]['extra'][$internalKey] = $tableStatus[$mysqlKey]; 00708 } 00709 } 00710 } 00711 } 00712 00713 // Compile key information: 00714 if (count($tempKeys)) { 00715 foreach ($tempKeys as $table => $keyInf) { 00716 foreach ($keyInf as $kName => $index) { 00717 ksort($index); 00718 $total[$table]['keys'][$kName] = $tempKeysPrefix[$table][$kName] . ' (' . implode(',', $index) . ')'; 00719 } 00720 } 00721 } 00722 00723 return $total; 00724 } 00725 00726 /** 00727 * Compares two arrays with field information and returns information about fields that are MISSING and fields that have CHANGED. 00728 * FDsrc and FDcomp can be switched if you want the list of stuff to remove rather than update. 00729 * 00730 * @param array Field definitions, source (from getFieldDefinitions_fileContent()) 00731 * @param array Field definitions, comparison. (from getFieldDefinitions_database()) 00732 * @param string Table names (in list) which is the ONLY one observed. 00733 * @param boolean If set, this function ignores NOT NULL statements of the SQL file field definition when comparing current field definition from database with field definition from SQL file. This way, NOT NULL statements will be executed when the field is initially created, but the SQL parser will never complain about missing NOT NULL statements afterwards. 00734 * @return array Returns an array with 1) all elements from $FDsrc that is not in $FDcomp (in key 'extra') and 2) all elements from $FDsrc that is different from the ones in $FDcomp 00735 */ 00736 function getDatabaseExtra($FDsrc, $FDcomp, $onlyTableList = '', $ignoreNotNullWhenComparing = TRUE) { 00737 $extraArr = array(); 00738 $diffArr = array(); 00739 00740 if (is_array($FDsrc)) { 00741 foreach ($FDsrc as $table => $info) { 00742 if (!strlen($onlyTableList) || t3lib_div::inList($onlyTableList, $table)) { 00743 if (!isset($FDcomp[$table])) { 00744 $extraArr[$table] = $info; // If the table was not in the FDcomp-array, the result array is loaded with that table. 00745 $extraArr[$table]['whole_table'] = 1; 00746 } else { 00747 $keyTypes = explode(',', 'extra,fields,keys'); 00748 foreach ($keyTypes as $theKey) { 00749 if (is_array($info[$theKey])) { 00750 foreach ($info[$theKey] as $fieldN => $fieldC) { 00751 $fieldN = str_replace('`', '', $fieldN); 00752 if ($fieldN == 'COLLATE') { 00753 continue; // TODO: collation support is currently disabled (needs more testing) 00754 } 00755 00756 if (!isset($FDcomp[$table][$theKey][$fieldN])) { 00757 $extraArr[$table][$theKey][$fieldN] = $fieldC; 00758 } else { 00759 $fieldC = trim($fieldC); 00760 if ($ignoreNotNullWhenComparing) { 00761 $fieldC = str_replace(' NOT NULL', '', $fieldC); 00762 $FDcomp[$table][$theKey][$fieldN] = str_replace(' NOT NULL', '', $FDcomp[$table][$theKey][$fieldN]); 00763 } 00764 if ($fieldC !== $FDcomp[$table][$theKey][$fieldN]) { 00765 $diffArr[$table][$theKey][$fieldN] = $fieldC; 00766 $diffArr_cur[$table][$theKey][$fieldN] = $FDcomp[$table][$theKey][$fieldN]; 00767 } 00768 } 00769 } 00770 } 00771 } 00772 } 00773 } 00774 } 00775 } 00776 00777 $output = array( 00778 'extra' => $extraArr, 00779 'diff' => $diffArr, 00780 'diff_currentValues' => $diffArr_cur 00781 ); 00782 00783 return $output; 00784 } 00785 00786 /** 00787 * Returns an array with SQL-statements that is needed to update according to the diff-array 00788 * 00789 * @param array Array with differences of current and needed DB settings. (from getDatabaseExtra()) 00790 * @param string List of fields in diff array to take notice of. 00791 * @return array Array of SQL statements (organized in keys depending on type) 00792 */ 00793 function getUpdateSuggestions($diffArr, $keyList = 'extra,diff') { 00794 $statements = array(); 00795 $deletedPrefixKey = $this->deletedPrefixKey; 00796 $remove = 0; 00797 if ($keyList == 'remove') { 00798 $remove = 1; 00799 $keyList = 'extra'; 00800 } 00801 $keyList = explode(',', $keyList); 00802 foreach ($keyList as $theKey) { 00803 if (is_array($diffArr[$theKey])) { 00804 foreach ($diffArr[$theKey] as $table => $info) { 00805 $whole_table = array(); 00806 if (is_array($info['fields'])) { 00807 foreach ($info['fields'] as $fN => $fV) { 00808 if ($info['whole_table']) { 00809 $whole_table[] = $fN . ' ' . $fV; 00810 } else { 00811 // Special case to work around MySQL problems when adding auto_increment fields: 00812 if (stristr($fV, 'auto_increment')) { 00813 // The field can only be set "auto_increment" if there exists a PRIMARY key of that field already. 00814 // The check does not look up which field is primary but just assumes it must be the field with the auto_increment value... 00815 if (isset($diffArr['extra'][$table]['keys']['PRIMARY'])) { 00816 // Remove "auto_increment" from the statement - it will be suggested in a 2nd step after the primary key was created 00817 $fV = str_replace(' auto_increment', '', $fV); 00818 } else { 00819 // In the next step, attempt to clear the table once again (2 = force) 00820 $info['extra']['CLEAR'] = 2; 00821 } 00822 } 00823 if ($theKey == 'extra') { 00824 if ($remove) { 00825 if (substr($fN, 0, strlen($deletedPrefixKey)) != $deletedPrefixKey) { 00826 $statement = 'ALTER TABLE ' . $table . ' CHANGE ' . $fN . ' ' . $deletedPrefixKey . $fN . ' ' . $fV . ';'; 00827 $statements['change'][md5($statement)] = $statement; 00828 } else { 00829 $statement = 'ALTER TABLE ' . $table . ' DROP ' . $fN . ';'; 00830 $statements['drop'][md5($statement)] = $statement; 00831 } 00832 } else { 00833 $statement = 'ALTER TABLE ' . $table . ' ADD ' . $fN . ' ' . $fV . ';'; 00834 $statements['add'][md5($statement)] = $statement; 00835 } 00836 } elseif ($theKey == 'diff') { 00837 $statement = 'ALTER TABLE ' . $table . ' CHANGE ' . $fN . ' ' . $fN . ' ' . $fV . ';'; 00838 $statements['change'][md5($statement)] = $statement; 00839 $statements['change_currentValue'][md5($statement)] = $diffArr['diff_currentValues'][$table]['fields'][$fN]; 00840 } 00841 } 00842 } 00843 } 00844 if (is_array($info['keys'])) { 00845 foreach ($info['keys'] as $fN => $fV) { 00846 if ($info['whole_table']) { 00847 $whole_table[] = $fV; 00848 } else { 00849 if ($theKey == 'extra') { 00850 if ($remove) { 00851 $statement = 'ALTER TABLE ' . $table . ($fN == 'PRIMARY' ? ' DROP PRIMARY KEY' : ' DROP KEY ' . $fN) . ';'; 00852 $statements['drop'][md5($statement)] = $statement; 00853 } else { 00854 $statement = 'ALTER TABLE ' . $table . ' ADD ' . $fV . ';'; 00855 $statements['add'][md5($statement)] = $statement; 00856 } 00857 } elseif ($theKey == 'diff') { 00858 $statement = 'ALTER TABLE ' . $table . ($fN == 'PRIMARY' ? ' DROP PRIMARY KEY' : ' DROP KEY ' . $fN) . ';'; 00859 $statements['change'][md5($statement)] = $statement; 00860 $statement = 'ALTER TABLE ' . $table . ' ADD ' . $fV . ';'; 00861 $statements['change'][md5($statement)] = $statement; 00862 } 00863 } 00864 } 00865 } 00866 if (is_array($info['extra'])) { 00867 $extras = array(); 00868 $extras_currentValue = array(); 00869 $clear_table = FALSE; 00870 00871 foreach ($info['extra'] as $fN => $fV) { 00872 00873 // Only consider statements which are missing in the database but don't remove existing properties 00874 if (!$remove) { 00875 if (!$info['whole_table']) { // If the whole table is created at once, we take care of this later by imploding all elements of $info['extra'] 00876 if ($fN == 'CLEAR') { 00877 // Truncate table must happen later, not now 00878 // Valid values for CLEAR: 1=only clear if keys are missing, 2=clear anyway (force) 00879 if (count($info['keys']) || $fV == 2) { 00880 $clear_table = TRUE; 00881 } 00882 continue; 00883 } else { 00884 $extras[] = $fN . '=' . $fV; 00885 $extras_currentValue[] = $fN . '=' . $diffArr['diff_currentValues'][$table]['extra'][$fN]; 00886 } 00887 } 00888 } 00889 } 00890 if ($clear_table) { 00891 $statement = 'TRUNCATE TABLE ' . $table . ';'; 00892 $statements['clear_table'][md5($statement)] = $statement; 00893 } 00894 if (count($extras)) { 00895 $statement = 'ALTER TABLE ' . $table . ' ' . implode(' ', $extras) . ';'; 00896 $statements['change'][md5($statement)] = $statement; 00897 $statements['change_currentValue'][md5($statement)] = implode(' ', $extras_currentValue); 00898 } 00899 } 00900 if ($info['whole_table']) { 00901 if ($remove) { 00902 if (substr($table, 0, strlen($deletedPrefixKey)) != $deletedPrefixKey) { 00903 $statement = 'ALTER TABLE ' . $table . ' RENAME ' . $deletedPrefixKey . $table . ';'; 00904 $statements['change_table'][md5($statement)] = $statement; 00905 } else { 00906 $statement = 'DROP TABLE ' . $table . ';'; 00907 $statements['drop_table'][md5($statement)] = $statement; 00908 } 00909 // count: 00910 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', $table); 00911 $statements['tables_count'][md5($statement)] = $count ? 'Records in table: ' . $count : ''; 00912 } else { 00913 $statement = 'CREATE TABLE ' . $table . " (\n" . implode(",\n", $whole_table) . "\n)"; 00914 if ($info['extra']) { 00915 foreach ($info['extra'] as $k => $v) { 00916 if ($k == 'COLLATE' || $k == 'CLEAR') { 00917 continue; // Skip these special statements. TODO: collation support is currently disabled (needs more testing) 00918 } 00919 $statement .= ' ' . $k . '=' . $v; // Add extra attributes like ENGINE, CHARSET, etc. 00920 } 00921 } 00922 $statement .= ';'; 00923 $statements['create_table'][md5($statement)] = $statement; 00924 } 00925 } 00926 } 00927 } 00928 } 00929 00930 return $statements; 00931 } 00932 00933 /** 00934 * Converts a result row with field information into the SQL field definition string 00935 * 00936 * @param array MySQL result row 00937 * @return string Field definition 00938 */ 00939 function assembleFieldDefinition($row) { 00940 $field = array($row['Type']); 00941 00942 if ($row['Null'] == 'NO') { 00943 $field[] = 'NOT NULL'; 00944 } 00945 if (!strstr($row['Type'], 'blob') && !strstr($row['Type'], 'text')) { 00946 // Add a default value if the field is not auto-incremented (these fields never have a default definition) 00947 if (!stristr($row['Extra'], 'auto_increment')) { 00948 $field[] = 'default \'' . addslashes($row['Default']) . '\''; 00949 } 00950 } 00951 if ($row['Extra']) { 00952 $field[] = $row['Extra']; 00953 } 00954 00955 return implode(' ', $field); 00956 } 00957 00958 /** 00959 * Returns an array where every entry is a single SQL-statement. Input must be formatted like an ordinary MySQL-dump files. 00960 * 00961 * @param string The SQL-file content. Provided that 1) every query in the input is ended with ';' and that a line in the file contains only one query or a part of a query. 00962 * @param boolean If set, non-SQL content (like comments and blank lines) is not included in the final output 00963 * @param string Regex to filter SQL lines to include 00964 * @return array Array of SQL statements 00965 */ 00966 function getStatementArray($sqlcode, $removeNonSQL = 0, $query_regex = '') { 00967 $sqlcodeArr = explode(LF, $sqlcode); 00968 00969 // Based on the assumption that the sql-dump has 00970 $statementArray = array(); 00971 $statementArrayPointer = 0; 00972 00973 foreach ($sqlcodeArr as $line => $lineContent) { 00974 $is_set = 0; 00975 00976 // auto_increment fields cannot have a default value! 00977 if (stristr($lineContent, 'auto_increment')) { 00978 $lineContent = preg_replace('/ default \'0\'/i', '', $lineContent); 00979 } 00980 00981 if (!$removeNonSQL || (strcmp(trim($lineContent), '') && substr(trim($lineContent), 0, 1) != '#' && substr(trim($lineContent), 0, 2) != '--')) { // '--' is seen as mysqldump comments from server version 3.23.49 00982 $statementArray[$statementArrayPointer] .= $lineContent; 00983 $is_set = 1; 00984 } 00985 if (substr(trim($lineContent), -1) == ';') { 00986 if (isset($statementArray[$statementArrayPointer])) { 00987 if (!trim($statementArray[$statementArrayPointer]) || ($query_regex && !preg_match('/' . $query_regex . '/i', trim($statementArray[$statementArrayPointer])))) { 00988 unset($statementArray[$statementArrayPointer]); 00989 } 00990 } 00991 $statementArrayPointer++; 00992 00993 } elseif ($is_set) { 00994 $statementArray[$statementArrayPointer] .= LF; 00995 } 00996 } 00997 00998 return $statementArray; 00999 } 01000 01001 /** 01002 * Returns tables to create and how many records in each 01003 * 01004 * @param array Array of SQL statements to analyse. 01005 * @param boolean If set, will count number of INSERT INTO statements following that table definition 01006 * @return array Array with table definitions in index 0 and count in index 1 01007 */ 01008 function getCreateTables($statements, $insertCountFlag = 0) { 01009 $crTables = array(); 01010 $insertCount = array(); 01011 foreach ($statements as $line => $lineContent) { 01012 $reg = array(); 01013 if (preg_match('/^create[[:space:]]*table[[:space:]]*[`]?([[:alnum:]_]*)[`]?/i', substr($lineContent, 0, 100), $reg)) { 01014 $table = trim($reg[1]); 01015 if ($table) { 01016 // table names are always lowercase on Windows! 01017 if (TYPO3_OS == 'WIN') { 01018 $table = strtolower($table); 01019 } 01020 $sqlLines = explode(LF, $lineContent); 01021 foreach ($sqlLines as $k => $v) { 01022 if (stristr($v, 'auto_increment')) { 01023 $sqlLines[$k] = preg_replace('/ default \'0\'/i', '', $v); 01024 } 01025 } 01026 $lineContent = implode(LF, $sqlLines); 01027 $crTables[$table] = $lineContent; 01028 } 01029 } elseif ($insertCountFlag && preg_match('/^insert[[:space:]]*into[[:space:]]*[`]?([[:alnum:]_]*)[`]?/i', substr($lineContent, 0, 100), $reg)) { 01030 $nTable = trim($reg[1]); 01031 $insertCount[$nTable]++; 01032 } 01033 } 01034 01035 return array($crTables, $insertCount); 01036 } 01037 01038 /** 01039 * Extracts all insert statements from $statement array where content is inserted into $table 01040 * 01041 * @param array Array of SQL statements 01042 * @param string Table name 01043 * @return array Array of INSERT INTO statements where table match $table 01044 */ 01045 function getTableInsertStatements($statements, $table) { 01046 $outStatements = array(); 01047 foreach ($statements as $line => $lineContent) { 01048 $reg = array(); 01049 if (preg_match('/^insert[[:space:]]*into[[:space:]]*[`]?([[:alnum:]_]*)[`]?/i', substr($lineContent, 0, 100), $reg)) { 01050 $nTable = trim($reg[1]); 01051 if ($nTable && !strcmp($table, $nTable)) { 01052 $outStatements[] = $lineContent; 01053 } 01054 } 01055 } 01056 return $outStatements; 01057 } 01058 01059 /** 01060 * Performs the queries passed from the input array. 01061 * 01062 * @param array Array of SQL queries to execute. 01063 * @param array Array with keys that must match keys in $arr. Only where a key in this array is set and true will the query be executed (meant to be passed from a form checkbox) 01064 * @return mixed Array with error message from database if any occured. Otherwise true if everything was executed successfully. 01065 */ 01066 function performUpdateQueries($arr, $keyArr) { 01067 $result = array(); 01068 if (is_array($arr)) { 01069 foreach ($arr as $key => $string) { 01070 if (isset($keyArr[$key]) && $keyArr[$key]) { 01071 $res = $GLOBALS['TYPO3_DB']->admin_query($string); 01072 if ($res === FALSE) { 01073 $result[$key] = $GLOBALS['TYPO3_DB']->sql_error(); 01074 } elseif (is_resource($res)) { 01075 $GLOBALS['TYPO3_DB']->sql_free_result($res); 01076 } 01077 } 01078 } 01079 } 01080 if (count($result) > 0) { 01081 return $result; 01082 } else { 01083 return TRUE; 01084 } 01085 } 01086 01087 /** 01088 * Returns list of tables in the database 01089 * 01090 * @return array List of tables. 01091 * @see t3lib_db::admin_get_tables() 01092 */ 01093 function getListOfTables() { 01094 $whichTables = $GLOBALS['TYPO3_DB']->admin_get_tables(TYPO3_db); 01095 foreach ($whichTables as $key => &$value) { 01096 $value = $key; 01097 } 01098 return $whichTables; 01099 } 01100 01101 /** 01102 * Creates a table which checkboxes for updating database. 01103 * 01104 * @param array Array of statements (key / value pairs where key is used for the checkboxes) 01105 * @param string Label for the table. 01106 * @param boolean If set, then checkboxes are set by default. 01107 * @param boolean If set, then icons are shown. 01108 * @param array Array of "current values" for each key/value pair in $arr. Shown if given. 01109 * @param boolean If set, will show the prefix "Current value" if $currentValue is given. 01110 * @return string HTML table with checkboxes for update. Must be wrapped in a form. 01111 */ 01112 function generateUpdateDatabaseForm_checkboxes($arr, $label, $checked = 1, $iconDis = 0, $currentValue = array(), $cVfullMsg = 0) { 01113 $out = array(); 01114 if (is_array($arr)) { 01115 $tableId = uniqid('table'); 01116 if (count($arr) > 1) { 01117 $out[] = ' 01118 <tr class="update-db-fields-batch"> 01119 <td valign="top"> 01120 <input type="checkbox" id="' . $tableId . '-checkbox"' . ($checked ? ' checked="checked"' : '') . ' 01121 onclick="$(\'' . $tableId . '\').select(\'input[type=checkbox]\').invoke(\'setValue\', $(this).checked);" /> 01122 </td> 01123 <td nowrap="nowrap"><label for="' . $tableId . '-checkbox" style="cursor:pointer"><strong>select/deselect all</strong></label></td> 01124 </tr>'; 01125 } 01126 foreach ($arr as $key => $string) { 01127 $ico = ''; 01128 $warnings = array(); 01129 01130 if ($iconDis) { 01131 if (preg_match('/^TRUNCATE/i', $string)) { 01132 $ico .= '<img src="' . $this->backPath . 'gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong> </strong>'; 01133 $warnings['clear_table_info'] = 'Clearing the table is sometimes neccessary when adding new keys. In case of cache_* tables this should not hurt at all. However, use it with care.'; 01134 } elseif (stristr($string, ' user_')) { 01135 $ico .= '<img src="' . $this->backPath . 'gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(USER) </strong>'; 01136 } elseif (stristr($string, ' app_')) { 01137 $ico .= '<img src="' . $this->backPath . 'gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(APP) </strong>'; 01138 } elseif (stristr($string, ' ttx_') || stristr($string, ' tx_')) { 01139 $ico .= '<img src="' . $this->backPath . 'gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(EXT) </strong>'; 01140 } 01141 } 01142 $out[] = ' 01143 <tr> 01144 <td valign="top"><input type="checkbox" id="db-' . $key . '" name="' . $this->dbUpdateCheckboxPrefix . '[' . $key . ']" value="1"' . ($checked ? ' checked="checked"' : '') . ' /></td> 01145 <td nowrap="nowrap"><label for="db-' . $key . '">' . nl2br($ico . htmlspecialchars($string)) . '</label></td> 01146 </tr>'; 01147 if (isset($currentValue[$key])) { 01148 $out[] = ' 01149 <tr> 01150 <td valign="top"></td> 01151 <td nowrap="nowrap" style="color:#666666;">' . nl2br((!$cVfullMsg ? "Current value: " : "") . '<em>' . $currentValue[$key] . '</em>') . '</td> 01152 </tr>'; 01153 } 01154 } 01155 if (count($warnings)) { 01156 $out[] = ' 01157 <tr> 01158 <td valign="top"></td> 01159 <td style="color:#666666;"><em>' . implode('<br />', $warnings) . '</em></td> 01160 </tr>'; 01161 } 01162 01163 // Compile rows: 01164 $content = ' 01165 <!-- Update database fields / tables --> 01166 <h3>' . $label . '</h3> 01167 <table border="0" cellpadding="2" cellspacing="2" id="' . $tableId . '" class="update-db-fields">' . implode('', $out) . ' 01168 </table>'; 01169 } 01170 01171 return $content; 01172 } 01173 } 01174 01175 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_install.php'])) { 01176 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_install.php']); 01177 } 01178 01179 ?>
1.8.0