TYPO3 CMS  TYPO3_8-7
ConnectionPool.php
Go to the documentation of this file.
1 <?php
2 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 
29 
41 {
45  const DEFAULT_CONNECTION_NAME = 'Default';
46 
50  protected static $connections = [];
51 
55  protected $customDoctrineTypes = [
56  EnumType::TYPE => EnumType::class,
57  SetType::TYPE => SetType::class,
58  ];
59 
69  public function getConnectionForTable(string $tableName): Connection
70  {
71  if (empty($tableName)) {
72  throw new \UnexpectedValueException(
73  'ConnectionPool->getConnectionForTable() requires a table name to be provided.',
74  1459421719
75  );
76  }
77 
78  $connectionName = self::DEFAULT_CONNECTION_NAME;
79  if (!empty($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName])) {
80  $connectionName = (string)$GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName];
81  }
82 
83  return $this->getConnectionByName($connectionName);
84  }
85 
96  public function getConnectionByName(string $connectionName): Connection
97  {
98  if (empty($connectionName)) {
99  throw new \UnexpectedValueException(
100  'ConnectionPool->getConnectionByName() requires a connection name to be provided.',
101  1459422125
102  );
103  }
104 
105  if (isset(static::$connections[$connectionName])) {
106  return static::$connections[$connectionName];
107  }
108 
109  if (empty($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][$connectionName])
110  || !is_array($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][$connectionName])
111  ) {
112  throw new \RuntimeException(
113  'The requested database connection named "' . $connectionName . '" has not been configured.',
114  1459422492
115  );
116  }
117 
118  $connectionParams = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][$connectionName];
119  if (empty($connectionParams['wrapperClass'])) {
120  $connectionParams['wrapperClass'] = Connection::class;
121  }
122 
123  if (!is_a($connectionParams['wrapperClass'], Connection::class, true)) {
124  throw new \UnexpectedValueException(
125  'The "wrapperClass" for the connection name "' . $connectionName .
126  '" needs to be a subclass of "' . Connection::class . '".',
127  1459422968
128  );
129  }
130 
131  static::$connections[$connectionName] = $this->getDatabaseConnection($connectionParams);
132 
133  return static::$connections[$connectionName];
134  }
135 
142  protected function getDatabaseConnection(array $connectionParams): Connection
143  {
144  // Default to UTF-8 connection charset
145  if (empty($connectionParams['charset'])) {
146  $connectionParams['charset'] = 'utf8';
147  }
148 
149  // Force consistent handling of binary objects across datbase platforms
150  // MySQL returns strings by default, PostgreSQL streams.
151  if (strpos($connectionParams['driver'], 'pdo_') === 0) {
152  $connectionParams['driverOptions'][\PDO::ATTR_STRINGIFY_FETCHES] = true;
153  }
154 
156  $conn = DriverManager::getConnection($connectionParams);
157  $conn->setFetchMode(\PDO::FETCH_ASSOC);
158  $conn->prepareConnection($connectionParams['initCommands'] ?? '');
159 
160  // Register custom data types
161  foreach ($this->customDoctrineTypes as $type => $className) {
162  if (!Type::hasType($type)) {
163  Type::addType($type, $className);
164  }
165  }
166 
167  // Register all custom data types in the type mapping
168  foreach ($this->customDoctrineTypes as $type => $className) {
169  $conn->getDatabasePlatform()->registerDoctrineTypeMapping($type, $type);
170  }
171 
172  // Handler for building custom data type column definitions
173  // in the SchemaManager
174  $conn->getDatabasePlatform()->getEventManager()->addEventListener(
175  Events::onSchemaColumnDefinition,
176  GeneralUtility::makeInstance(SchemaColumnDefinitionListener::class)
177  );
178 
179  // Handler for enhanced index definitions in the SchemaManager
180  $conn->getDatabasePlatform()->getEventManager()->addEventListener(
181  Events::onSchemaIndexDefinition,
182  GeneralUtility::makeInstance(SchemaIndexDefinitionListener::class)
183  );
184 
185  // Handler for adding custom database platform options to ALTER TABLE
186  // requests in the SchemaManager
187  $conn->getDatabasePlatform()->getEventManager()->addEventListener(
188  Events::onSchemaAlterTable,
189  GeneralUtility::makeInstance(SchemaAlterTableListener::class)
190  );
191 
192  return $conn;
193  }
194 
202  public function getQueryBuilderForTable(string $tableName): QueryBuilder
203  {
204  if (empty($tableName)) {
205  throw new \UnexpectedValueException(
206  'ConnectionPool->getQueryBuilderForTable() requires a connection name to be provided.',
207  1459423448
208  );
209  }
210 
211  return $this->getConnectionForTable($tableName)->createQueryBuilder();
212  }
213 
223  public function getConnectionNames(): array
224  {
225  return array_keys($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']);
226  }
227 
237  public function getCustomDoctrineTypes(): array
238  {
240  }
241 }
static makeInstance($className,... $constructorArguments)
getConnectionByName(string $connectionName)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']