1<?php 2declare(strict_types = 1); 3namespace TYPO3\CMS\Core\Preparations; 4 5/* 6 * This file is part of the TYPO3 CMS project. 7 * 8 * It is free software; you can redistribute it and/or modify it under 9 * the terms of the GNU General Public License, either version 2 10 * of the License, or any later version. 11 * 12 * For the full copyright and license information, please read the 13 * LICENSE.txt file that was distributed with this source code. 14 * 15 * The TYPO3 project - inspiring people to share! 16 */ 17 18use TYPO3\CMS\Core\Database\ConnectionPool; 19use TYPO3\CMS\Core\Database\Query\QueryHelper; 20use TYPO3\CMS\Core\Utility\GeneralUtility; 21 22/** 23 * Prepare TCA. Used in bootstrap and Flex Form Data Structures. 24 * 25 * @internal Class and API may change any time. 26 */ 27class TcaPreparation 28{ 29 30 /** 31 * Prepare TCA 32 * 33 * This class is typically called within bootstrap with empty caches after all TCA 34 * files from extensions have been loaded. The preparation is then applied and 35 * the prepared result is cached. 36 * For flex form TCA, this class is called dynamically if opening a record in the backend. 37 * 38 * See unit tests for details. 39 * 40 * @param array $tca 41 * @return array 42 */ 43 public function prepare(array $tca): array 44 { 45 $tca = $this->prepareQuotingOfTableNamesAndColumnNames($tca); 46 return $tca; 47 } 48 49 /** 50 * Quote all table and field names in definitions known to possibly have quoted identifiers like '{#tablename}.{#columnname}=' 51 * 52 * @param array $tca Incoming TCA 53 * @return array Prepared TCA 54 */ 55 protected function prepareQuotingOfTableNamesAndColumnNames(array $tca): array 56 { 57 $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); 58 59 $newTca = $tca; 60 $configToPrepareQuoting = [ 61 'foreign_table_where', 62 'MM_table_where', 63 'search' => 'andWhere' 64 ]; 65 foreach ($tca as $table => $tableDefinition) { 66 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) { 67 continue; 68 } 69 70 foreach ($tableDefinition['columns'] as $columnName => $columnConfig) { 71 foreach ($configToPrepareQuoting as $level => $value) { 72 if (is_string($level)) { 73 $sqlQueryPartToPrepareQuotingIn = $columnConfig['config'][$level][$value] ?? ''; 74 } else { 75 $sqlQueryPartToPrepareQuotingIn = $columnConfig['config'][$value] ?? ''; 76 } 77 if (mb_strpos($sqlQueryPartToPrepareQuotingIn, '{#') !== false) { 78 $quoted = QueryHelper::quoteDatabaseIdentifiers( 79 $connectionPool->getConnectionForTable($table), 80 $sqlQueryPartToPrepareQuotingIn 81 ); 82 if (is_string($level)) { 83 $newTca[$table]['columns'][$columnName]['config'][$level][$value] = $quoted; 84 } else { 85 $newTca[$table]['columns'][$columnName]['config'][$value] = $quoted; 86 } 87 } 88 } 89 } 90 } 91 92 return $newTca; 93 } 94} 95