‪TYPO3CMS  11.5
ConnectionPool.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
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 
19 
20 use Doctrine\DBAL\DriverManager;
21 use Doctrine\DBAL\Events;
22 use Doctrine\DBAL\Types\Type;
27 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
34 
46 {
50  public const ‪DEFAULT_CONNECTION_NAME = 'Default';
51 
55  protected static ‪$connections = [];
56 
60  protected ‪$customDoctrineTypes = [
61  ‪EnumType::TYPE => EnumType::class,
62  ‪SetType::TYPE => SetType::class,
63  ];
64 
70  protected static ‪$driverMap = [
71  'pdo_mysql' => PDOMySqlDriver::class,
72  'pdo_sqlite' => PDOSqliteDriver::class,
73  'pdo_pgsql' => PDOPgSqlDriver::class,
74  'pdo_sqlsrv' => PDOSqlsrvDriver::class,
75  // TODO: not supported yet, need to be checked later
76  // 'pdo_oci' => PDOOCIDriver::class,
77  // 'drizzle_pdo_mysql' => DrizzlePDOMySQLDriver::class,
78  ];
79 
89  public function ‪getConnectionForTable(string $tableName): ‪Connection
90  {
91  if (empty($tableName)) {
92  throw new \UnexpectedValueException(
93  'ConnectionPool->getConnectionForTable() requires a table name to be provided.',
94  1459421719
95  );
96  }
97 
98  $connectionName = ‪self::DEFAULT_CONNECTION_NAME;
99  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName])) {
100  $connectionName = (string)‪$GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName];
101  }
102 
103  return $this->‪getConnectionByName($connectionName);
104  }
105 
116  public function ‪getConnectionByName(string $connectionName): ‪Connection
117  {
118  if (empty($connectionName)) {
119  throw new \UnexpectedValueException(
120  'ConnectionPool->getConnectionByName() requires a connection name to be provided.',
121  1459422125
122  );
123  }
124 
125  if (isset(static::$connections[$connectionName])) {
126  return static::$connections[$connectionName];
127  }
128 
129  $connectionParams = ‪$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][$connectionName] ?? [];
130  if (empty($connectionParams)) {
131  throw new \RuntimeException(
132  'The requested database connection named "' . $connectionName . '" has not been configured.',
133  1459422492
134  );
135  }
136 
137  if (empty($connectionParams['wrapperClass'])) {
138  $connectionParams['wrapperClass'] = Connection::class;
139  }
140 
141  if (!is_a($connectionParams['wrapperClass'], Connection::class, true)) {
142  throw new \UnexpectedValueException(
143  'The "wrapperClass" for the connection name "' . $connectionName .
144  '" needs to be a subclass of "' . Connection::class . '".',
145  1459422968
146  );
147  }
148 
149  // Transform TYPO3 `tableoptions` to valid `doctrine/dbal` connection param option `defaultTableOptions`
150  // @todo TYPO3 database configuration should be changed to directly write defaultTableOptions instead,
151  // with proper upgrade migration. Along with that, default table options for MySQL in
152  // testing-framework and core should be adjusted.
153  if (isset($connectionParams['tableoptions'])) {
154  $connectionParams['defaultTableOptions'] = array_replace(
155  $connectionParams['defaultTableOptions'] ?? [],
156  $connectionParams['tableoptions']
157  );
158  unset($connectionParams['tableoptions']);
159  }
160 
161  static::$connections[$connectionName] = $this->‪getDatabaseConnection($connectionParams);
162 
163  return static::$connections[$connectionName];
164  }
165 
172  protected function ‪mapCustomDriver(array $connectionParams): array
173  {
174  // if no custom driver is provided, map TYPO3 specific drivers
175  if (!isset($connectionParams['driverClass']) && isset(static::$driverMap[$connectionParams['driver']])) {
176  $connectionParams['driverClass'] = static::$driverMap[$connectionParams['driver']];
177  }
178 
179  return $connectionParams;
180  }
181 
188  protected function ‪getDatabaseConnection(array $connectionParams): Connection
189  {
190  // Default to UTF-8 connection charset
191  if (empty($connectionParams['charset'])) {
192  $connectionParams['charset'] = 'utf8';
193  }
194 
195  $connectionParams = $this->‪mapCustomDriver($connectionParams);
196 
198  $conn = DriverManager::getConnection($connectionParams);
199  $conn->setFetchMode(\PDO::FETCH_ASSOC);
200  $conn->prepareConnection($connectionParams['initCommands'] ?? '');
201 
202  // Register custom data types
203  foreach ($this->customDoctrineTypes as $type => $className) {
204  if (!Type::hasType($type)) {
205  Type::addType($type, $className);
206  }
207  }
208 
209  // Register all custom data types in the type mapping
210  foreach ($this->customDoctrineTypes as $type => $className) {
211  $conn->getDatabasePlatform()->registerDoctrineTypeMapping($type, $type);
212  }
213 
214  // Handler for building custom data type column definitions
215  // in the SchemaManager
216  $conn->getDatabasePlatform()->getEventManager()->addEventListener(
217  Events::onSchemaColumnDefinition,
218  GeneralUtility::makeInstance(SchemaColumnDefinitionListener::class)
219  );
220 
221  // Handler for enhanced index definitions in the SchemaManager
222  $conn->getDatabasePlatform()->getEventManager()->addEventListener(
223  Events::onSchemaIndexDefinition,
224  GeneralUtility::makeInstance(SchemaIndexDefinitionListener::class)
225  );
226 
227  // Handler for adding custom database platform options to ALTER TABLE
228  // requests in the SchemaManager
229  $conn->getDatabasePlatform()->getEventManager()->addEventListener(
230  Events::onSchemaAlterTable,
231  GeneralUtility::makeInstance(SchemaAlterTableListener::class)
232  );
233 
234  return $conn;
235  }
236 
244  public function ‪getQueryBuilderForTable(string $tableName): QueryBuilder
245  {
246  if (empty($tableName)) {
247  throw new \UnexpectedValueException(
248  'ConnectionPool->getQueryBuilderForTable() requires a connection name to be provided.',
249  1459423448
250  );
251  }
252 
253  return $this->‪getConnectionForTable($tableName)->‪createQueryBuilder();
254  }
255 
265  public function ‪getConnectionNames(): array
266  {
267  return array_keys(‪$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']);
268  }
269 
279  public function ‪getCustomDoctrineTypes(): array
280  {
282  }
283 
289  public function ‪resetConnections(): void
290  {
291  static::$connections = [];
292  }
293 }
‪TYPO3\CMS\Core\Database\Driver\PDOPgSql\Driver
Definition: Driver.php:31
‪TYPO3\CMS\Core\Database\Driver\PDOMySql\Driver
Definition: Driver.php:30
‪TYPO3\CMS\Core\Database\Schema\EventListener\SchemaIndexDefinitionListener
Definition: SchemaIndexDefinitionListener.php:30
‪TYPO3\CMS\Core\Database\Schema\Types\SetType
Definition: SetType.php:27
‪TYPO3\CMS\Core\Database\Driver\PDOSqlsrv\Driver
Definition: Driver.php:28
‪TYPO3\CMS\Core\Database\Schema\Types\EnumType
Definition: EnumType.php:27
‪TYPO3\CMS\Core\Database\ConnectionPool\$driverMap
‪static string[] $driverMap
Definition: ConnectionPool.php:67
‪TYPO3\CMS\Core\Database\Driver\PDOSqlite\Driver
Definition: Driver.php:31
‪TYPO3\CMS\Core\Database\Schema\Types\EnumType\TYPE
‪const TYPE
Definition: EnumType.php:28
‪TYPO3\CMS\Core\Database\ConnectionPool\DEFAULT_CONNECTION_NAME
‪const DEFAULT_CONNECTION_NAME
Definition: ConnectionPool.php:50
‪TYPO3\CMS\Core\Database\ConnectionPool\getCustomDoctrineTypes
‪array getCustomDoctrineTypes()
Definition: ConnectionPool.php:276
‪TYPO3\CMS\Core\Database\ConnectionPool\$customDoctrineTypes
‪array $customDoctrineTypes
Definition: ConnectionPool.php:58
‪TYPO3\CMS\Core\Database\ConnectionPool\mapCustomDriver
‪array mapCustomDriver(array $connectionParams)
Definition: ConnectionPool.php:169
‪TYPO3\CMS\Core\Database\ConnectionPool\getConnectionForTable
‪Connection getConnectionForTable(string $tableName)
Definition: ConnectionPool.php:86
‪TYPO3\CMS\Core\Database\ConnectionPool\$connections
‪static Connection[] $connections
Definition: ConnectionPool.php:54
‪TYPO3\CMS\Core\Database\ConnectionPool\getConnectionByName
‪Connection getConnectionByName(string $connectionName)
Definition: ConnectionPool.php:113
‪TYPO3\CMS\Core\Database\Schema\EventListener\SchemaAlterTableListener
Definition: SchemaAlterTableListener.php:28
‪TYPO3\CMS\Core\Database\ConnectionPool\getQueryBuilderForTable
‪QueryBuilder getQueryBuilderForTable(string $tableName)
Definition: ConnectionPool.php:241
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:38
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Database\Connection\createQueryBuilder
‪TYPO3 CMS Core Database Query QueryBuilder createQueryBuilder()
Definition: Connection.php:117
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Core\Database\Schema\Types\SetType\TYPE
‪const TYPE
Definition: SetType.php:28
‪TYPO3\CMS\Core\Database\ConnectionPool\resetConnections
‪resetConnections()
Definition: ConnectionPool.php:286
‪TYPO3\CMS\Core\Database\ConnectionPool\getDatabaseConnection
‪Connection getDatabaseConnection(array $connectionParams)
Definition: ConnectionPool.php:185
‪TYPO3\CMS\Core\Database
Definition: Connection.php:18
‪TYPO3\CMS\Core\Database\Schema\EventListener\SchemaColumnDefinitionListener
Definition: SchemaColumnDefinitionListener.php:30
‪TYPO3\CMS\Core\Database\ConnectionPool\getConnectionNames
‪array getConnectionNames()
Definition: ConnectionPool.php:262