TYPO3 CMS  TYPO3_7-6
SqlSchemaMigrationService.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
22 {
27 
31  protected $deletedPrefixKey = 'zzz_deleted_';
32 
36  protected $character_sets = [];
37 
43  public function setDeletedPrefixKey($prefix)
44  {
45  $this->deletedPrefixKey = $prefix;
46  }
47 
53  public function getDeletedPrefixKey()
54  {
56  }
57 
64  public function getFieldDefinitions_fileContent($fileContent)
65  {
66  $lines = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(LF, $fileContent, true);
67  $table = '';
68  $total = [];
69  foreach ($lines as $value) {
70  if ($value[0] === '#') {
71  // Ignore comments
72  continue;
73  }
74  if ($table === '') {
75  $parts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(' ', $value, true);
76  if (strtoupper($parts[0]) === 'CREATE' && strtoupper($parts[1]) === 'TABLE') {
77  $table = str_replace('`', '', $parts[2]);
78  // tablenames are always lowercase on windows!
79  if (TYPO3_OS == 'WIN') {
80  $table = strtolower($table);
81  }
82  }
83  } else {
84  if ($value[0] === ')' && substr($value, -1) === ';') {
85  $ttype = [];
86  if (preg_match('/(ENGINE|TYPE)[ ]*=[ ]*([a-zA-Z]*)/', $value, $ttype)) {
87  $total[$table]['extra']['ENGINE'] = $ttype[2];
88  }
89  // Otherwise, just do nothing: If table engine is not defined, just accept the system default.
90  // Set the collation, if specified
91  if (preg_match('/(COLLATE)[ ]*=[ ]*([a-zA-z0-9_-]+)/', $value, $tcollation)) {
92  $total[$table]['extra']['COLLATE'] = $tcollation[2];
93  } else {
94  // 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)
95  if (preg_match('/(CHARSET|CHARACTER SET)[ ]*=[ ]*([a-zA-z0-9_-]+)/', $value, $tcharset)) {
96  // Note: Keywords "DEFAULT CHARSET" and "CHARSET" are the same, so "DEFAULT" can just be ignored
97  $charset = $tcharset[2];
98  } else {
99  $charset = $this->getDatabaseConnection()->default_charset;
100  }
101  $total[$table]['extra']['COLLATE'] = $this->getCollationForCharset($charset);
102  }
103  // Remove table marker and start looking for the next "CREATE TABLE" statement
104  $table = '';
105  } else {
106  // Strip trailing commas
107  $lineV = preg_replace('/,$/', '', $value);
108  $lineV = str_replace('`', '', $lineV);
109  // Reduce multiple blanks and tabs except newline
110  $lineV = preg_replace('/\h+/', ' ', $lineV);
111  $parts = explode(' ', $lineV, 2);
112  // Field definition
113  if (!preg_match('/(PRIMARY|UNIQUE|FULLTEXT|SPATIAL|INDEX|KEY)/', $parts[0])) {
114  // Make sure there is no default value when auto_increment is set
115  if (stristr($parts[1], 'auto_increment')) {
116  $parts[1] = preg_replace('/ default \'0\'/i', '', $parts[1]);
117  }
118  // "default" is always lower-case
119  if (stristr($parts[1], ' DEFAULT ')) {
120  $parts[1] = str_ireplace(' DEFAULT ', ' default ', $parts[1]);
121  }
122  // Change order of "default" and "NULL" statements
123  $parts[1] = preg_replace('/(.*) (default .*) (NOT NULL)/', '$1 $3 $2', $parts[1]);
124  $parts[1] = preg_replace('/(.*) (default .*) (NULL)/', '$1 $3 $2', $parts[1]);
125  $key = $parts[0];
126  $total[$table]['fields'][$key] = $parts[1];
127  } else {
128  // Key definition
129  $search = ['/UNIQUE (INDEX|KEY)/', '/FULLTEXT (INDEX|KEY)/', '/SPATIAL (INDEX|KEY)/', '/INDEX/'];
130  $replace = ['UNIQUE', 'FULLTEXT', 'SPATIAL', 'KEY'];
131  $lineV = preg_replace($search, $replace, $lineV);
132  if (preg_match('/PRIMARY|UNIQUE|FULLTEXT|SPATIAL/', $parts[0])) {
133  $parts[1] = preg_replace('/^(KEY|INDEX) /', '', $parts[1]);
134  }
135  $newParts = explode(' ', $parts[1], 2);
136  $key = $parts[0] == 'PRIMARY' ? $parts[0] : $newParts[0];
137  $total[$table]['keys'][$key] = $lineV;
138  // This is a protection against doing something stupid: Only allow clearing of cache_* and index_* tables.
139  if (preg_match('/^(cache|index)_/', $table)) {
140  // Suggest to truncate (clear) this table
141  $total[$table]['extra']['CLEAR'] = 1;
142  }
143  }
144  }
145  }
146  }
147  return $total;
148  }
149 
156  public function getCollationForCharset($charset)
157  {
158  // Load character sets, if not cached already
159  if (empty($this->character_sets)) {
160  $databaseConnection = $this->getDatabaseConnection();
161  if (method_exists($databaseConnection, 'admin_get_charsets')) {
162  $this->character_sets = $databaseConnection->admin_get_charsets();
163  } else {
164  // Add empty element to avoid that the check will be repeated
165  $this->character_sets[$charset] = [];
166  }
167  }
168  $collation = '';
169  if (isset($this->character_sets[$charset]['Default collation'])) {
170  $collation = $this->character_sets[$charset]['Default collation'];
171  }
172  return $collation;
173  }
174 
181  {
182  $total = [];
183  $tempKeys = [];
184  $tempKeysPrefix = [];
185  $databaseConnection = $this->getDatabaseConnection();
186  $databaseConnection->connectDB();
187  echo $databaseConnection->sql_error();
188  $tables = $databaseConnection->admin_get_tables();
189  foreach ($tables as $tableName => $tableStatus) {
190  // Fields
191  $fieldInformation = $databaseConnection->admin_get_fields($tableName);
192  foreach ($fieldInformation as $fN => $fieldRow) {
193  $total[$tableName]['fields'][$fN] = $this->assembleFieldDefinition($fieldRow);
194  }
195  // Keys
196  $keyInformation = $databaseConnection->admin_get_keys($tableName);
197  foreach ($keyInformation as $keyRow) {
198  $keyName = $keyRow['Key_name'];
199  $colName = $keyRow['Column_name'];
200  if ($keyRow['Sub_part'] && $keyRow['Index_type'] !== 'SPATIAL') {
201  $colName .= '(' . $keyRow['Sub_part'] . ')';
202  }
203  $tempKeys[$tableName][$keyName][$keyRow['Seq_in_index']] = $colName;
204  if ($keyName == 'PRIMARY') {
205  $prefix = 'PRIMARY KEY';
206  } else {
207  if ($keyRow['Index_type'] === 'FULLTEXT') {
208  $prefix = 'FULLTEXT';
209  } elseif ($keyRow['Index_type'] === 'SPATIAL') {
210  $prefix = 'SPATIAL';
211  } elseif ($keyRow['Non_unique']) {
212  $prefix = 'KEY';
213  } else {
214  $prefix = 'UNIQUE';
215  }
216  $prefix .= ' ' . $keyName;
217  }
218  $tempKeysPrefix[$tableName][$keyName] = $prefix;
219  }
220  // Table status (storage engine, collaction, etc.)
221  if (is_array($tableStatus)) {
222  $tableExtraFields = [
223  'Engine' => 'ENGINE',
224  'Collation' => 'COLLATE'
225  ];
226  foreach ($tableExtraFields as $mysqlKey => $internalKey) {
227  if (isset($tableStatus[$mysqlKey])) {
228  $total[$tableName]['extra'][$internalKey] = $tableStatus[$mysqlKey];
229  }
230  }
231  }
232  }
233  // Compile key information:
234  if (!empty($tempKeys)) {
235  foreach ($tempKeys as $table => $keyInf) {
236  foreach ($keyInf as $kName => $index) {
237  ksort($index);
238  $total[$table]['keys'][$kName] = $tempKeysPrefix[$table][$kName] . ' (' . implode(',', $index) . ')';
239  }
240  }
241  }
242  return $total;
243  }
244 
255  public function getDatabaseExtra($FDsrc, $FDcomp, $onlyTableList = '', $ignoreNotNullWhenComparing = false)
256  {
257  $extraArr = [];
258  $diffArr = [];
259  if (is_array($FDsrc)) {
260  foreach ($FDsrc as $table => $info) {
261  if ($onlyTableList === '' || \TYPO3\CMS\Core\Utility\GeneralUtility::inList($onlyTableList, $table)) {
262  if (!isset($FDcomp[$table])) {
263  // If the table was not in the FDcomp-array, the result array is loaded with that table.
264  $extraArr[$table] = $info;
265  $extraArr[$table]['whole_table'] = 1;
266  } else {
267  $keyTypes = explode(',', 'extra,fields,keys');
268  foreach ($keyTypes as $theKey) {
269  if (is_array($info[$theKey])) {
270  foreach ($info[$theKey] as $fieldN => $fieldC) {
271  $fieldN = str_replace('`', '', $fieldN);
272  if ($this->isDbalEnabled() && $fieldN === 'ENGINE') {
273  continue;
274  }
275  if ($fieldN == 'COLLATE') {
276  // @todo collation support is currently disabled (needs more testing)
277  continue;
278  }
279  if (!isset($FDcomp[$table][$theKey][$fieldN])) {
280  $extraArr[$table][$theKey][$fieldN] = $fieldC;
281  } else {
282  $fieldC = trim($fieldC);
283 
284  // Lowercase the field type to surround false-positive schema changes to be
285  // reported just because of different caseing of characters
286  // The regex does just trigger for the first word followed by parentheses
287  // that contain a length. It does not trigger for e.g. "PRIMARY KEY" because
288  // "PRIMARY KEY" is being returned from the DB in upper case.
289  $fieldC = preg_replace_callback(
290  '/^([a-zA-Z0-9]+)(\([^)]*\)\s.*)/',
291  function ($matches) {
292  return strtolower($matches[1]) . $matches[2];
293  },
294  $fieldC
295  );
296 
297  if ($this->isDbalEnabled()) {
298  // Ignore nonstandard MySQL numeric field attributes UNSIGNED and ZEROFILL
299  if (preg_match('/^(TINYINT|SMALLINT|MEDIUMINT|INT|INTEGER|BIGINT|REAL|DOUBLE|FLOAT|DECIMAL|NUMERIC)\([^\)]+\)\s+(UNSIGNED|ZEROFILL)/i', $fieldC)) {
300  $fieldC = str_ireplace([' UNSIGNED', ' ZEROFILL'], '', $fieldC);
301  $FDcomp[$table][$theKey][$fieldN] = str_ireplace([' UNSIGNED', ' ZEROFILL'], '', $FDcomp[$table][$theKey][$fieldN]);
302  }
303 
304  // Replace field and index definitions with functionally equivalent statements
305  if ($fieldC !== $FDcomp[$table][$theKey][$fieldN]) {
306  switch ($theKey) {
307  case 'fields':
308  $fieldC = $this->getDatabaseConnection()->getEquivalentFieldDefinition($fieldC);
309  break;
310  case 'keys':
311  $fieldC = $this->getDatabaseConnection()->getEquivalentIndexDefinition($fieldC);
312  break;
313  }
314  }
315  }
316  if ($ignoreNotNullWhenComparing) {
317  $fieldC = str_replace(' NOT NULL', '', $fieldC);
318  $FDcomp[$table][$theKey][$fieldN] = str_replace(' NOT NULL', '', $FDcomp[$table][$theKey][$fieldN]);
319  }
320  if ($fieldC !== $FDcomp[$table][$theKey][$fieldN]) {
321  $diffArr[$table][$theKey][$fieldN] = $fieldC;
322  $diffArr_cur[$table][$theKey][$fieldN] = $FDcomp[$table][$theKey][$fieldN];
323  }
324  }
325  }
326  }
327  }
328  }
329  }
330  }
331  }
332  $output = [
333  'extra' => $extraArr,
334  'diff' => $diffArr,
335  'diff_currentValues' => $diffArr_cur
336  ];
337  return $output;
338  }
339 
347  public function getUpdateSuggestions($diffArr, $keyList = 'extra,diff')
348  {
349  $statements = [];
351  $deletedPrefixLength = strlen($deletedPrefixKey);
352  $remove = 0;
353  if ($keyList == 'remove') {
354  $remove = 1;
355  $keyList = 'extra';
356  }
357  $keyList = explode(',', $keyList);
358  foreach ($keyList as $theKey) {
359  if (is_array($diffArr[$theKey])) {
360  foreach ($diffArr[$theKey] as $table => $info) {
361  $whole_table = [];
362  if (isset($info['keys']) && is_array($info['keys'])) {
363  foreach ($info['keys'] as $fN => $fV) {
364  if (!$info['whole_table'] && $theKey === 'extra' && $remove) {
365  $statement = 'ALTER TABLE ' . $table . ($fN === 'PRIMARY' ? ' DROP PRIMARY KEY' : ' DROP KEY ' . $fN) . ';';
366  $statements['drop'][md5($statement)] = $statement;
367  }
368  }
369  }
370  if (is_array($info['fields'])) {
371  foreach ($info['fields'] as $fN => $fV) {
372  if ($info['whole_table']) {
373  $whole_table[] = $fN . ' ' . $fV;
374  } else {
375  // Special case to work around MySQL problems when adding auto_increment fields:
376  if (stristr($fV, 'auto_increment')) {
377  // The field can only be set "auto_increment" if there exists a PRIMARY key of that field already.
378  // The check does not look up which field is primary but just assumes it must be the field with the auto_increment value...
379  if (isset($info['keys']['PRIMARY'])) {
380  if (!$this->isDbalEnabled()) {
381  // Combine adding the field and the primary key into a single statement
382  $fV .= ', ADD PRIMARY KEY (' . $fN . ')';
383  unset($info['keys']['PRIMARY']);
384  }
385  } else {
386  // In the next step, attempt to clear the table once again (2 = force)
387  $info['extra']['CLEAR'] = 2;
388  }
389  }
390  if ($theKey == 'extra') {
391  if ($remove) {
392  if (substr($fN, 0, $deletedPrefixLength) !== $deletedPrefixKey) {
393  // we've to make sure we don't exceed the maximal length
394  $prefixedFieldName = $deletedPrefixKey . substr($fN, ($deletedPrefixLength - self::MYSQL_MAXIMUM_FIELD_WIDTH));
395  $statement = 'ALTER TABLE ' . $table . ' CHANGE ' . $fN . ' ' . $prefixedFieldName . ' ' . $fV . ';';
396  $statements['change'][md5($statement)] = $statement;
397  } else {
398  $statement = 'ALTER TABLE ' . $table . ' DROP ' . $fN . ';';
399  $statements['drop'][md5($statement)] = $statement;
400  }
401  } else {
402  $statement = 'ALTER TABLE ' . $table . ' ADD ' . $fN . ' ' . $fV . ';';
403  $statements['add'][md5($statement)] = $statement;
404  }
405  } elseif ($theKey == 'diff') {
406  $statement = 'ALTER TABLE ' . $table . ' CHANGE ' . $fN . ' ' . $fN . ' ' . $fV . ';';
407  $statements['change'][md5($statement)] = $statement;
408  $statements['change_currentValue'][md5($statement)] = $diffArr['diff_currentValues'][$table]['fields'][$fN];
409  }
410  }
411  }
412  }
413  if (is_array($info['keys'])) {
414  foreach ($info['keys'] as $fN => $fV) {
415  if ($info['whole_table']) {
416  $whole_table[] = $fV;
417  } else {
418  if ($theKey == 'extra') {
419  if (!$remove) {
420  $statement = 'ALTER TABLE ' . $table . ' ADD ' . $fV . ';';
421  $statements['add'][md5($statement)] = $statement;
422  }
423  } elseif ($theKey == 'diff') {
424  $statement = 'ALTER TABLE ' . $table . ($fN == 'PRIMARY' ? ' DROP PRIMARY KEY' : ' DROP KEY ' . $fN) . ';';
425  $statements['change'][md5($statement)] = $statement;
426  $statement = 'ALTER TABLE ' . $table . ' ADD ' . $fV . ';';
427  $statements['change'][md5($statement)] = $statement;
428  }
429  }
430  }
431  }
432  if (is_array($info['extra'])) {
433  $extras = [];
434  $extras_currentValue = [];
435  $clear_table = false;
436  foreach ($info['extra'] as $fN => $fV) {
437  // Only consider statements which are missing in the database but don't remove existing properties
438  if (!$remove) {
439  if (!$info['whole_table']) {
440  // If the whole table is created at once, we take care of this later by imploding all elements of $info['extra']
441  if ($fN == 'CLEAR') {
442  // Truncate table must happen later, not now
443  // Valid values for CLEAR: 1=only clear if keys are missing, 2=clear anyway (force)
444  if (!empty($info['keys']) || $fV == 2) {
445  $clear_table = true;
446  }
447  continue;
448  } else {
449  $extras[] = $fN . '=' . $fV;
450  $extras_currentValue[] = $fN . '=' . $diffArr['diff_currentValues'][$table]['extra'][$fN];
451  }
452  }
453  }
454  }
455  if ($clear_table) {
456  $statement = 'TRUNCATE TABLE ' . $table . ';';
457  $statements['clear_table'][md5($statement)] = $statement;
458  }
459  if (!empty($extras)) {
460  $statement = 'ALTER TABLE ' . $table . ' ' . implode(' ', $extras) . ';';
461  $statements['change'][md5($statement)] = $statement;
462  $statements['change_currentValue'][md5($statement)] = implode(' ', $extras_currentValue);
463  }
464  }
465  if ($info['whole_table']) {
466  if ($remove) {
467  if (substr($table, 0, $deletedPrefixLength) !== $deletedPrefixKey) {
468  // we've to make sure we don't exceed the maximal length
469  $prefixedTableName = $deletedPrefixKey . substr($table, ($deletedPrefixLength - self::MYSQL_MAXIMUM_FIELD_WIDTH));
470  $statement = 'ALTER TABLE ' . $table . ' RENAME ' . $prefixedTableName . ';';
471  $statements['change_table'][md5($statement)] = $statement;
472  } else {
473  $statement = 'DROP TABLE ' . $table . ';';
474  $statements['drop_table'][md5($statement)] = $statement;
475  }
476  // Count
477  $count = $this->getDatabaseConnection()->exec_SELECTcountRows('*', $table);
478  $statements['tables_count'][md5($statement)] = $count ? 'Records in table: ' . $count : '';
479  } else {
480  $statement = 'CREATE TABLE ' . $table . ' (
481 ' . implode(',
482 ', $whole_table) . '
483 )';
484  if ($info['extra']) {
485  foreach ($info['extra'] as $k => $v) {
486  if ($k == 'COLLATE' || $k == 'CLEAR') {
487  // Skip these special statements.
488  // @todo collation support is currently disabled (needs more testing)
489  continue;
490  }
491  // Add extra attributes like ENGINE, CHARSET, etc.
492  $statement .= ' ' . $k . '=' . $v;
493  }
494  }
495  $statement .= ';';
496  $statements['create_table'][md5($statement)] = $statement;
497  }
498  }
499  }
500  }
501  }
502  return $statements;
503  }
504 
511  public function assembleFieldDefinition($row)
512  {
513  $field = [$row['Type']];
514  if ($row['Null'] == 'NO') {
515  $field[] = 'NOT NULL';
516  }
517  if (!strstr($row['Type'], 'blob') && !strstr($row['Type'], 'text')) {
518  // Add a default value if the field is not auto-incremented (these fields never have a default definition)
519  if (!stristr($row['Extra'], 'auto_increment')) {
520  if ($row['Default'] === null) {
521  $field[] = 'default NULL';
522  } else {
523  $field[] = 'default \'' . addslashes($row['Default']) . '\'';
524  }
525  }
526  }
527  if ($row['Extra']) {
528  $field[] = $row['Extra'];
529  }
530  if (trim($row['Comment']) !== '') {
531  $field[] = "COMMENT '" . $row['Comment'] . "'";
532  }
533  return implode(' ', $field);
534  }
535 
544  public function getStatementArray($sqlcode, $removeNonSQL = false, $query_regex = '')
545  {
546  $sqlcodeArr = explode(LF, $sqlcode);
547  // Based on the assumption that the sql-dump has
548  $statementArray = [];
549  $statementArrayPointer = 0;
550  foreach ($sqlcodeArr as $line => $lineContent) {
551  $lineContent = trim($lineContent);
552  $is_set = 0;
553  // Auto_increment fields cannot have a default value!
554  if (stristr($lineContent, 'auto_increment')) {
555  $lineContent = preg_replace('/ default \'0\'/i', '', $lineContent);
556  }
557  if (!$removeNonSQL || $lineContent !== '' && $lineContent[0] !== '#' && substr($lineContent, 0, 2) !== '--') {
558  // '--' is seen as mysqldump comments from server version 3.23.49
559  $statementArray[$statementArrayPointer] .= $lineContent;
560  $is_set = 1;
561  }
562  if (substr($lineContent, -1) === ';') {
563  if (isset($statementArray[$statementArrayPointer])) {
564  if (!trim($statementArray[$statementArrayPointer]) || $query_regex && !preg_match(('/' . $query_regex . '/i'), trim($statementArray[$statementArrayPointer]))) {
565  unset($statementArray[$statementArrayPointer]);
566  }
567  }
568  $statementArrayPointer++;
569  } elseif ($is_set) {
570  $statementArray[$statementArrayPointer] .= LF;
571  }
572  }
573  return $statementArray;
574  }
575 
583  public function getCreateTables($statements, $insertCountFlag = false)
584  {
585  $crTables = [];
586  $insertCount = [];
587  foreach ($statements as $line => $lineContent) {
588  $reg = [];
589  if (preg_match('/^create[[:space:]]*table[[:space:]]*[`]?([[:alnum:]_]*)[`]?/i', substr($lineContent, 0, 100), $reg)) {
590  $table = trim($reg[1]);
591  if ($table) {
592  // Table names are always lowercase on Windows!
593  if (TYPO3_OS == 'WIN') {
594  $table = strtolower($table);
595  }
596  $sqlLines = explode(LF, $lineContent);
597  foreach ($sqlLines as $k => $v) {
598  if (stristr($v, 'auto_increment')) {
599  $sqlLines[$k] = preg_replace('/ default \'0\'/i', '', $v);
600  }
601  }
602  $lineContent = implode(LF, $sqlLines);
603  $crTables[$table] = $lineContent;
604  }
605  } elseif ($insertCountFlag && preg_match('/^insert[[:space:]]*into[[:space:]]*[`]?([[:alnum:]_]*)[`]?/i', substr($lineContent, 0, 100), $reg)) {
606  $nTable = trim($reg[1]);
607  $insertCount[$nTable]++;
608  }
609  }
610  return [$crTables, $insertCount];
611  }
612 
620  public function getTableInsertStatements($statements, $table)
621  {
622  $outStatements = [];
623  foreach ($statements as $line => $lineContent) {
624  $reg = [];
625  if (preg_match('/^insert[[:space:]]*into[[:space:]]*[`]?([[:alnum:]_]*)[`]?/i', substr($lineContent, 0, 100), $reg)) {
626  $nTable = trim($reg[1]);
627  if ($nTable && $table === $nTable) {
628  $outStatements[] = $lineContent;
629  }
630  }
631  }
632  return $outStatements;
633  }
634 
642  public function performUpdateQueries($arr, $keyArr)
643  {
644  $result = [];
645  if (is_array($arr)) {
646  $databaseConnection = $this->getDatabaseConnection();
647  foreach ($arr as $key => $string) {
648  if (isset($keyArr[$key]) && $keyArr[$key]) {
649  $res = $databaseConnection->admin_query($string);
650  if ($res === false) {
651  $result[$key] = $databaseConnection->sql_error();
652  } elseif (is_resource($res) || is_a($res, '\\mysqli_result')) {
653  $databaseConnection->sql_free_result($res);
654  }
655  }
656  }
657  }
658  if (!empty($result)) {
659  return $result;
660  } else {
661  return true;
662  }
663  }
664 
671  public function getListOfTables()
672  {
673  $whichTables = $this->getDatabaseConnection()->admin_get_tables(TYPO3_db);
674  foreach ($whichTables as $key => &$value) {
675  $value = $key;
676  }
677  unset($value);
678  return $whichTables;
679  }
680 
686  protected function isDbalEnabled()
687  {
688  return \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('dbal');
689  }
690 
694  protected function getDatabaseConnection()
695  {
696  return $GLOBALS['TYPO3_DB'];
697  }
698 }
getDatabaseExtra($FDsrc, $FDcomp, $onlyTableList='', $ignoreNotNullWhenComparing=false)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
getStatementArray($sqlcode, $removeNonSQL=false, $query_regex='')
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']