TYPO3 CMS  TYPO3_8-7
DatabaseConnect.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 
24 
32 {
39  public function execute()
40  {
41  $result = [];
42  $postValues = $this->postValues['values'];
43  $defaultConnectionSettings = [];
44 
45  if ($postValues['availableSet'] === 'configurationFromEnvironment') {
46  $defaultConnectionSettings = $this->getConfigurationFromEnvironment();
47  } else {
48  if (isset($postValues['driver'])) {
49  $validDrivers = [
50  'mysqli',
51  'pdo_mysql',
52  'pdo_pgsql',
53  'mssql',
54  ];
55  if (in_array($postValues['driver'], $validDrivers, true)) {
56  $defaultConnectionSettings['driver'] = $postValues['driver'];
57  } else {
58  $errorStatus = GeneralUtility::makeInstance(ErrorStatus::class);
59  $errorStatus->setTitle('Database driver unknown');
60  $errorStatus->setMessage('Given driver must be one of ' . implode(', ', $validDrivers));
61  $result[] = $errorStatus;
62  }
63  }
64  if (isset($postValues['username'])) {
65  $value = $postValues['username'];
66  if (strlen($value) <= 50) {
67  $defaultConnectionSettings['user'] = $value;
68  } else {
69  $errorStatus = GeneralUtility::makeInstance(ErrorStatus::class);
70  $errorStatus->setTitle('Database username not valid');
71  $errorStatus->setMessage('Given username must be shorter than fifty characters.');
72  $result[] = $errorStatus;
73  }
74  }
75  if (isset($postValues['password'])) {
76  $defaultConnectionSettings['password'] = $postValues['password'];
77  }
78  if (isset($postValues['host'])) {
79  $value = $postValues['host'];
80  if (preg_match('/^[a-zA-Z0-9_\\.-]+(:.+)?$/', $value) && strlen($value) <= 255) {
81  $defaultConnectionSettings['host'] = $value;
82  } else {
83  $errorStatus = GeneralUtility::makeInstance(ErrorStatus::class);
84  $errorStatus->setTitle('Database host not valid');
85  $errorStatus->setMessage('Given host is not alphanumeric (a-z, A-Z, 0-9 or _-.:) or longer than 255 characters.');
86  $result[] = $errorStatus;
87  }
88  }
89  if (isset($postValues['port']) && $postValues['host'] !== 'localhost') {
90  $value = $postValues['port'];
91  if (preg_match('/^[0-9]+(:.+)?$/', $value) && $value > 0 && $value <= 65535) {
92  $defaultConnectionSettings['port'] = (int)$value;
93  } else {
94  $errorStatus = GeneralUtility::makeInstance(ErrorStatus::class);
95  $errorStatus->setTitle('Database port not valid');
96  $errorStatus->setMessage('Given port is not numeric or within range 1 to 65535.');
97  $result[] = $errorStatus;
98  }
99  }
100  if (isset($postValues['socket']) && $postValues['socket'] !== '') {
101  if (@file_exists($postValues['socket'])) {
102  $defaultConnectionSettings['unix_socket'] = $postValues['socket'];
103  } else {
104  $errorStatus = GeneralUtility::makeInstance(ErrorStatus::class);
105  $errorStatus->setTitle('Socket does not exist');
106  $errorStatus->setMessage('Given socket location does not exist on server.');
107  $result[] = $errorStatus;
108  }
109  }
110  if (isset($postValues['database'])) {
111  $value = $postValues['database'];
112  if (strlen($value) <= 50) {
113  $defaultConnectionSettings['dbname'] = $value;
114  } else {
115  $errorStatus = GeneralUtility::makeInstance(ErrorStatus::class);
116  $errorStatus->setTitle('Database name not valid');
117  $errorStatus->setMessage('Given database name must be shorter than fifty characters.');
118  $result[] = $errorStatus;
119  }
120  }
121  }
122 
123  if (!empty($defaultConnectionSettings)) {
124  // Test connection settings and write to config if connect is successful
125  try {
126  $connectionParams = $defaultConnectionSettings;
127  $connectionParams['wrapperClass'] = Connection::class;
128  $connectionParams['charset'] = 'utf-8';
129  DriverManager::getConnection($connectionParams)->ping();
130  } catch (DBALException $e) {
131  $errorStatus = GeneralUtility::makeInstance(ErrorStatus::class);
132  $errorStatus->setTitle('Database connect not successful');
133  $errorStatus->setMessage('Connecting to the database with given settings failed: ' . $e->getMessage());
134  $result[] = $errorStatus;
135  }
136  $localConfigurationPathValuePairs = [];
137  foreach ($defaultConnectionSettings as $settingsName => $value) {
138  $localConfigurationPathValuePairs['DB/Connections/Default/' . $settingsName] = $value;
139  }
140  $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
141  // Remove full default connection array
142  $configurationManager->removeLocalConfigurationKeysByPath([ 'DB/Connections/Default' ]);
143  // Write new values
144  $configurationManager->setLocalConfigurationValuesByPathValuePairs($localConfigurationPathValuePairs);
145  }
146 
147  return $result;
148  }
149 
156  public function needsExecution()
157  {
158  if ($this->isConnectSuccessful() && $this->isConfigurationComplete()) {
159  return false;
160  }
161  return true;
162  }
163 
169  protected function executeAction()
170  {
171  $hasAtLeastOneOption = false;
172  $activeAvailableOption = '';
173  if (extension_loaded('mysqli')) {
174  $hasAtLeastOneOption = true;
175  $this->view->assign('hasMysqliManualConfiguration', true);
176  $mysqliManualConfigurationOptions = [
177  'username' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'] ?? '',
178  'password' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'] ?? '',
179  'port' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['port'] ?? 3306,
180  ];
181  $host = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'] ?? '127.0.0.1';
182  if ($host === 'localhost') {
183  $host = '127.0.0.1';
184  }
185  $mysqliManualConfigurationOptions['host'] = $host;
186  $this->view->assign('mysqliManualConfigurationOptions', $mysqliManualConfigurationOptions);
187  $activeAvailableOption = 'mysqliManualConfiguration';
188 
189  $this->view->assign('hasMysqliSocketManualConfiguration', true);
190  $this->view->assign(
191  'mysqliSocketManualConfigurationOptions',
192  [
193  'username' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'] ?? '',
194  'password' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'] ?? '',
195  'socket' => $this->getConfiguredMysqliSocket(),
196  ]
197  );
198  if ($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['driver'] === 'mysqli'
199  && $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'] === 'localhost') {
200  $activeAvailableOption = 'mysqliSocketManualConfiguration';
201  }
202  }
203  if (extension_loaded('pdo_pgsql')) {
204  $hasAtLeastOneOption = true;
205  $this->view->assign('hasPostgresManualConfiguration', true);
206  $this->view->assign(
207  'postgresManualConfigurationOptions',
208  [
209  'username' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'] ?? '',
210  'password' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'] ?? '',
211  'host' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'] ?? '127.0.0.1',
212  'port' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['port'] ?? 5432,
213  'database' => $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['dbname'] ?? '',
214  ]
215  );
216  if ($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['driver'] === 'pdo_pgsql') {
217  $activeAvailableOption = 'postgresManualConfiguration';
218  }
219  }
220 
221  if (!empty($this->getConfigurationFromEnvironment())) {
222  $hasAtLeastOneOption = true;
223  $activeAvailableOption = 'configurationFromEnvironment';
224  $this->view->assign('hasConfigurationFromEnvironment', true);
225  }
226 
227  $this->view->assign('hasAtLeastOneOption', $hasAtLeastOneOption);
228  $this->view->assign('activeAvailableOption', $activeAvailableOption);
229 
230  $this->assignSteps();
231 
232  return $this->view->render();
233  }
234 
240  protected function isConnectSuccessful()
241  {
242  return empty($this->isConnectSuccessfulWithExceptionMessage());
243  }
244 
250  protected function isConnectSuccessfulWithExceptionMessage(): string
251  {
252  try {
253  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionByName('Default')->ping();
254  } catch (DBALException $e) {
255  return $e->getMessage();
256  }
257  return '';
258  }
259 
266  protected function isConfigurationComplete()
267  {
268  $configurationComplete = true;
269  if (!isset($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'])) {
270  $configurationComplete = false;
271  }
272  if (!isset($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'])) {
273  $configurationComplete = false;
274  }
275  return $configurationComplete;
276  }
277 
283  protected function getConfiguredMysqliSocket()
284  {
285  $socket = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['unix_socket'] ?? '';
286  if ($socket === '') {
287  // If no configured socket, use default php socket
288  $defaultSocket = (string)ini_get('mysqli.default_socket');
289  if ($defaultSocket !== '') {
290  $socket = $defaultSocket;
291  }
292  }
293  return $socket;
294  }
295 
301  protected function getConfigurationFromEnvironment(): array
302  {
303  $envCredentials = [];
304  foreach (['driver', 'host', 'user', 'password', 'port', 'dbname', 'unix_socket'] as $value) {
305  $envVar = 'TYPO3_INSTALL_DB_' . strtoupper($value);
306  if (getenv($envVar) !== false) {
307  $envCredentials[$value] = getenv($envVar);
308  }
309  }
310  if (!empty($envCredentials)) {
311  $connectionParams = $envCredentials;
312  $connectionParams['wrapperClass'] = Connection::class;
313  $connectionParams['charset'] = 'utf-8';
314  try {
315  DriverManager::getConnection($connectionParams)->ping();
316  return $envCredentials;
317  } catch (DBALException $e) {
318  return [];
319  }
320  }
321  return [];
322  }
323 }
static makeInstance($className,... $constructorArguments)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']