TYPO3 API  SVNRelease
class.t3lib_install.php
Go to the documentation of this file.
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 ?>