[TASK] Add more fixers for php-cs-fixer
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Database / ConnectionPool.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Core\Database;
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
18 use Doctrine\DBAL\Configuration;
19 use Doctrine\DBAL\DriverManager;
20 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
21
22 /**
23 * Manager that handles opening/retrieving database connections.
24 *
25 * It's a facade to the actual Doctrine DBAL DriverManager that implements TYPO3
26 * specific functionality like mapping individual tables to different database
27 * connections.
28 *
29 * getConnectionForTable() is the only supported way to get a connection that
30 * honors the table mapping configuration.
31 */
32 class ConnectionPool
33 {
34 /**
35 * @var string
36 */
37 const DEFAULT_CONNECTION_NAME = 'Default';
38
39 /**
40 * @var Connection[]
41 */
42 protected static $connections = [];
43
44 /**
45 * Creates a connection object based on the specified table name.
46 *
47 * This is the official entry point to get a database connection to ensure
48 * that the mapping of table names to database connections is honored.
49 *
50 * @param string $tableName
51 * @return Connection
52 */
53 public function getConnectionForTable(string $tableName): Connection
54 {
55 if (empty($tableName)) {
56 throw new \UnexpectedValueException(
57 'ConnectionPool->getConnectionForTable() requires a table name to be provided.',
58 1459421719
59 );
60 }
61
62 $connectionName = self::DEFAULT_CONNECTION_NAME;
63 if (!empty($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName])) {
64 $connectionName = (string)$GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'][$tableName];
65 }
66
67 return $this->getConnectionByName($connectionName);
68 }
69
70 /**
71 * Creates a connection object based on the specified identifier.
72 *
73 * This method should only be used in edge cases. Use getConnectionForTable() so
74 * that the tablename<>databaseConnection mapping will be taken into account.
75 *
76 * @param string $connectionName
77 * @return Connection
78 * @throws \Doctrine\DBAL\DBALException
79 * @internal
80 */
81 public function getConnectionByName(string $connectionName): Connection
82 {
83 if (empty($connectionName)) {
84 throw new \UnexpectedValueException(
85 'ConnectionPool->getConnectionByName() requires a connection name to be provided.',
86 1459422125
87 );
88 }
89
90 if (isset(static::$connections[$connectionName])) {
91 return static::$connections[$connectionName];
92 }
93
94 if (empty($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][$connectionName])
95 || !is_array($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][$connectionName])
96 ) {
97 throw new \RuntimeException(
98 'The requested database connection named "' . $connectionName . '" has not been configured.',
99 1459422492
100 );
101 }
102
103 $connectionParams = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][$connectionName];
104 if (empty($connectionParams['wrapperClass'])) {
105 $connectionParams['wrapperClass'] = Connection::class;
106 }
107
108 if (!is_a($connectionParams['wrapperClass'], Connection::class, true)) {
109 throw new \UnexpectedValueException(
110 'The "wrapperClass" for the connection name "' . $connectionName .
111 '" needs to be a subclass of "' . Connection::class . '".',
112 1459422968
113 );
114 }
115
116 static::$connections[$connectionName] = $this->getDatabaseConnection($connectionParams);
117
118 return static::$connections[$connectionName];
119 }
120
121 /**
122 * Creates a connection object based on the specified parameters
123 *
124 * @param array $connectionParams
125 * @return Connection
126 */
127 protected function getDatabaseConnection(array $connectionParams): Connection
128 {
129 // Default to UTF-8 connection charset
130 if (empty($connectionParams['charset'])) {
131 $connectionParams['charset'] = 'utf-8';
132 }
133 /** @var Connection $conn */
134 $conn = DriverManager::getConnection($connectionParams);
135 $conn->setFetchMode(\PDO::FETCH_ASSOC);
136 $conn->prepareConnection($connectionParams['initCommands'] ?? '');
137
138 return $conn;
139 }
140
141 /**
142 * Returns the connection specific query builder object that can be used to build
143 * complex SQL queries using and object oriented approach.
144 *
145 * @param string $tableName
146 * @return QueryBuilder
147 */
148 public function getQueryBuilderForTable(string $tableName): QueryBuilder
149 {
150 if (empty($tableName)) {
151 throw new \UnexpectedValueException(
152 'ConnectionPool->getQueryBuilderForTable() requires a connection name to be provided.',
153 1459423448
154 );
155 }
156
157 return $this->getConnectionForTable($tableName)->createQueryBuilder();
158 }
159
160 /**
161 * Returns an array containing the names of all currently configured connections.
162 *
163 * This method should only be used in edge cases. Use getConnectionForTable() so
164 * that the tablename<>databaseConnection mapping will be taken into account.
165 *
166 * @internal
167 * @return array
168 */
169 public function getConnectionNames(): array
170 {
171 return array_keys($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']);
172 }
173 }