TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
DatabaseConnect.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Install\Controller\Action\Step;
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 
17 use Doctrine\DBAL\DBALException;
20 
28 {
35  public function execute()
36  {
37  $result = [];
38 
40  $configurationManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
41 
42  $postValues = $this->postValues['values'];
43 
44  $localConfigurationPathValuePairs = [];
45 
46  if (isset($postValues['username'])) {
47  $value = $postValues['username'];
48  if (strlen($value) <= 50) {
49  $localConfigurationPathValuePairs['DB/Connections/Default/user'] = $value;
50  } else {
52  $errorStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
53  $errorStatus->setTitle('Database username not valid');
54  $errorStatus->setMessage('Given username must be shorter than fifty characters.');
55  $result[] = $errorStatus;
56  }
57  }
58 
59  if (isset($postValues['password'])) {
60  $value = $postValues['password'];
61  if (strlen($value) <= 50) {
62  $localConfigurationPathValuePairs['DB/Connections/Default/password'] = $value;
63  } else {
65  $errorStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
66  $errorStatus->setTitle('Database password not valid');
67  $errorStatus->setMessage('Given password must be shorter than fifty characters.');
68  $result[] = $errorStatus;
69  }
70  }
71 
72  if (isset($postValues['host'])) {
73  $value = $postValues['host'];
74  if (preg_match('/^[a-zA-Z0-9_\\.-]+(:.+)?$/', $value) && strlen($value) <= 255) {
75  $localConfigurationPathValuePairs['DB/Connections/Default/host'] = $value;
76  } else {
78  $errorStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
79  $errorStatus->setTitle('Database host not valid');
80  $errorStatus->setMessage('Given host is not alphanumeric (a-z, A-Z, 0-9 or _-.:) or longer than 255 characters.');
81  $result[] = $errorStatus;
82  }
83  }
84 
85  if (isset($postValues['port']) && $postValues['host'] !== 'localhost') {
86  $value = $postValues['port'];
87  if (preg_match('/^[0-9]+(:.+)?$/', $value) && $value > 0 && $value <= 65535) {
88  $localConfigurationPathValuePairs['DB/Connections/Default/port'] = (int)$value;
89  } else {
91  $errorStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
92  $errorStatus->setTitle('Database port not valid');
93  $errorStatus->setMessage('Given port is not numeric or within range 1 to 65535.');
94  $result[] = $errorStatus;
95  }
96  }
97 
98  if (isset($postValues['socket']) && $postValues['socket'] !== '') {
99  if (@file_exists($postValues['socket'])) {
100  $localConfigurationPathValuePairs['DB/Connections/Default/unix_socket'] = $postValues['socket'];
101  } else {
103  $errorStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
104  $errorStatus->setTitle('Socket does not exist');
105  $errorStatus->setMessage('Given socket location does not exist on server.');
106  $result[] = $errorStatus;
107  }
108  }
109 
110  if (isset($postValues['database'])) {
111  $value = $postValues['database'];
112  if (strlen($value) <= 50) {
113  $localConfigurationPathValuePairs['DB/Connections/Default/dbname'] = $value;
114  } else {
116  $errorStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
117  $errorStatus->setTitle('Database name not valid');
118  $errorStatus->setMessage('Given database name must be shorter than fifty characters.');
119  $result[] = $errorStatus;
120  }
121  }
122 
123  if (!empty($localConfigurationPathValuePairs)) {
124  $configurationManager->setLocalConfigurationValuesByPathValuePairs($localConfigurationPathValuePairs);
125 
126  // After setting new credentials, test again and create an error message if connect is not successful
127  // @TODO: This could be simplified, if isConnectSuccessful could be released from TYPO3_CONF_VARS
128  // and fed with connect values directly in order to obsolete the bootstrap reload.
130  ->populateLocalConfiguration()
131  ->disableCoreCache();
132  if (!$this->isConnectSuccessful()) {
134  $errorStatus = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
135  $errorStatus->setTitle('Database connect not successful');
136  $errorStatus->setMessage('Connecting to the database with given settings failed. Please check.');
137  $result[] = $errorStatus;
138  }
139  }
140 
141  return $result;
142  }
143 
150  public function needsExecution()
151  {
152  if ($this->isConnectSuccessful() && $this->isConfigurationComplete()) {
153  return false;
154  }
155  if (!$this->isHostConfigured()) {
156  $this->useDefaultValuesForNotConfiguredOptions();
157  throw new \TYPO3\CMS\Install\Controller\Exception\RedirectException(
158  'Wrote default settings to LocalConfiguration.php, redirect needed',
159  1377611168
160  );
161  }
162  return true;
163  }
164 
170  protected function executeAction()
171  {
172  $this->view
173  ->assign('username', $this->getConfiguredUsername())
174  ->assign('password', $this->getConfiguredPassword())
175  ->assign('host', $this->getConfiguredHost())
176  ->assign('port', $this->getConfiguredOrDefaultPort())
177  ->assign('database', $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['dbname'] ?: '')
178  ->assign('socket', $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['unix_socket'] ?: '')
179  ->assign('renderConnectDetailsUsername', true)
180  ->assign('renderConnectDetailsPassword', true)
181  ->assign('renderConnectDetailsHost', true)
182  ->assign('renderConnectDetailsPort', true)
183  ->assign('renderConnectDetailsSocket', true);
184 
185  $this->assignSteps();
186 
187  return $this->view->render();
188  }
189 
195  protected function getConfiguredOrDefaultPort()
196  {
197  $configuredPort = (int)$this->getConfiguredPort();
198  if (!$configuredPort) {
199  $port = 3306;
200  } else {
201  $port = $configuredPort;
202  }
203  return $port;
204  }
205 
211  protected function isConnectSuccessful()
212  {
213  try {
214  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionByName('Default')->ping();
215  } catch (DBALException $e) {
216  return false;
217  }
218  return true;
219  }
220 
228  protected function isHostConfigured()
229  {
230  $hostConfigured = true;
231  if (empty($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'])) {
232  $hostConfigured = false;
233  }
234  if (!isset($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['port'])
235  && !isset($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['unix_socket'])
236  ) {
237  $hostConfigured = false;
238  }
239  return $hostConfigured;
240  }
241 
250  protected function isConfigurationComplete()
251  {
252  $configurationComplete = $this->isHostConfigured();
253  if (!isset($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'])) {
254  $configurationComplete = false;
255  }
256  if (!isset($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'])) {
257  $configurationComplete = false;
258  }
259  return $configurationComplete;
260  }
261 
278  protected function useDefaultValuesForNotConfiguredOptions()
279  {
280  $localConfigurationPathValuePairs = [];
281 
282  $localConfigurationPathValuePairs['DB/Connections/Default/host'] = $this->getConfiguredHost();
283 
284  // If host is "local" either by upgrading or by first install, we try a socket
285  // connection first and use TCP/IP as fallback
286  if ($localConfigurationPathValuePairs['DB/Connections/Default/host'] === 'localhost'
287  || GeneralUtility::cmpIP($localConfigurationPathValuePairs['DB/Connections/Default/host'], '127.*.*.*')
288  || (string)$localConfigurationPathValuePairs['DB/Connections/Default/host'] === ''
289  ) {
291  $localConfigurationPathValuePairs['DB/Connections/Default/host'] = 'localhost';
292  $localConfigurationPathValuePairs['DB/Connections/Default/unix_socket'] = $this->getConfiguredSocket();
293  } else {
294  if (!GeneralUtility::isFirstPartOfStr($localConfigurationPathValuePairs['DB/Connections/Default/host'], '127.')) {
295  $localConfigurationPathValuePairs['DB/Connections/Default/host'] = '127.0.0.1';
296  }
297  }
298  }
299 
300  if (!isset($localConfigurationPathValuePairs['DB/Connections/Default/unix_socket'])) {
301  // Make sure a default port is set if not configured yet
302  // This is independent from any host configuration
303  $port = $this->getConfiguredPort();
304  if ($port > 0) {
305  $localConfigurationPathValuePairs['DB/Connections/Default/port'] = $port;
306  } else {
307  $localConfigurationPathValuePairs['DB/Connections/Default/port'] = $this->getConfiguredOrDefaultPort();
308  }
309  }
310 
312  $configurationManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
313  $configurationManager->setLocalConfigurationValuesByPathValuePairs($localConfigurationPathValuePairs);
314  }
315 
323  {
324  $result = false;
325  // Use configured socket
326  $socket = (string)$this->getConfiguredSocket();
327  if ($socket === '') {
328  // If no configured socket, use default php socket
329  $defaultSocket = (string)ini_get('mysqli.default_socket');
330  if ($defaultSocket !== '') {
331  $socket = $defaultSocket;
332  }
333  }
334  if ($socket !== '') {
335  $socketOpenResult = @fsockopen('unix://' . $socket);
336  if ($socketOpenResult) {
337  fclose($socketOpenResult);
338  $result = true;
339  }
340  }
341  return $result;
342  }
343 
349  protected function getConfiguredUsername()
350  {
351  $username = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'] ?? '';
352  return $username;
353  }
354 
360  protected function getConfiguredPassword()
361  {
362  $password = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'] ?? '';
363  return $password;
364  }
365 
371  protected function getConfiguredHost()
372  {
373  $host = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'] ?? '';
374  $port = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['port'] ?? '';
375  if (strlen($port) < 1 && substr_count($host, ':') === 1) {
376  list($host) = explode(':', $host);
377  }
378  return $host;
379  }
380 
386  protected function getConfiguredPort()
387  {
388  $host = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'] ?? '';
389  $port = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['port'] ?? '';
390  if ($port === '' && substr_count($host, ':') === 1) {
391  $hostPortArray = explode(':', $host);
392  $port = $hostPortArray[1];
393  }
394  return (int)$port;
395  }
396 
402  protected function getConfiguredSocket()
403  {
404  $socket = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['unix_socket'] ?? '';
405  return $socket;
406  }
407 }
static isFirstPartOfStr($str, $partStr)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)