‪TYPO3CMS  ‪main
MySql.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\Platforms\MariaDBPlatform as DoctrineMariaDBPlatform;
21 use Doctrine\DBAL\Platforms\MySQLPlatform as DoctrineMySQLPlatform;
28 
41 {
42  protected const ‪PLATFORM_MYSQL = 'mysql';
43  protected const ‪PLATFORM_MARIADB = 'mariadb';
44 
50  protected array ‪$minimumVersion = [
51  self::PLATFORM_MYSQL => '8.0.17',
52  self::PLATFORM_MARIADB => '10.4.3',
53  ];
54 
58  protected array ‪$platformLabel = [
59  self::PLATFORM_MYSQL => 'MySQL',
60  self::PLATFORM_MARIADB => 'MariaDB',
61  ];
62 
68  protected ‪$incompatibleSqlModes = [
69  'NO_BACKSLASH_ESCAPES',
70  ];
71 
76  protected ‪$databaseCharsetToCheck = [
77  'utf8',
78  'utf8mb3',
79  'utf8mb4',
80  ];
81 
87  'utf8',
88  'utf8mb3',
89  'utf8mb4',
90  ];
91 
98  public function ‪getStatus(): ‪FlashMessageQueue
99  {
100  $defaultConnection = GeneralUtility::makeInstance(ConnectionPool::class)
101  ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
102  $platform = $defaultConnection->getDatabasePlatform();
103  if (!($platform instanceof DoctrineMariaDBPlatform || $platform instanceof DoctrineMySQLPlatform)) {
104  return ‪$this->messageQueue;
105  }
106  $this->‪checkMySQLOrMariaDBVersion($defaultConnection);
107  $this->‪checkInvalidSqlModes($defaultConnection);
108  $this->‪checkDefaultDatabaseCharset($defaultConnection);
109  $this->‪checkDefaultDatabaseServerCharset($defaultConnection);
110  $this->‪checkDatabaseName($defaultConnection);
111  return ‪$this->messageQueue;
112  }
113 
119  protected function ‪checkInvalidSqlModes(‪Connection $connection)
120  {
121  $detectedIncompatibleSqlModes = $this->‪getIncompatibleSqlModes($connection);
122  if (!empty($detectedIncompatibleSqlModes)) {
123  $this->messageQueue->enqueue(new ‪FlashMessage(
124  'Incompatible SQL modes have been detected:'
125  . ' ' . implode(', ', $detectedIncompatibleSqlModes) . '.'
126  . ' The listed modes are not compatible with TYPO3 CMS.'
127  . ' You have to change that setting in your MySQL environment'
128  . ' or in $GLOBALS[\'TYPO3_CONF_VARS\'][\'DB\'][\'Connections\'][\'Default\'][\'initCommands\']',
129  'Incompatible SQL modes found!',
130  ContextualFeedbackSeverity::ERROR
131  ));
132  } else {
133  $this->messageQueue->enqueue(new ‪FlashMessage(
134  '',
135  'No incompatible SQL modes found.'
136  ));
137  }
138  }
139 
145  protected function ‪checkMySQLOrMariaDBVersion(Connection $connection): void
146  {
147  ‪$platformLabel = $this->‪getPlatformLabel($connection);
148  ‪$minimumVersion = $this->‪getMinimumVersion($connection);
149  $serverVersion = $connection->getPlatformServerVersion();
150  preg_match('/MySQL (5\.5\.5-|)((\d+\.)*(\d+\.)*\d+)/', $serverVersion, $match);
151  $currentMysqlVersion = $match[2] ?? null;
152  if ($currentMysqlVersion === null) {
153  $this->messageQueue->enqueue(new FlashMessage(
154  'Your ' . ‪$platformLabel . ' version could not be determined. Verify manually to have at least '
155  . ‪$platformLabel . ' ' . ‪$minimumVersion . ' installed. Version value: ' . $serverVersion,
156  ‪$platformLabel . ' version invalid',
157  ContextualFeedbackSeverity::ERROR
158  ));
159  } elseif (version_compare($currentMysqlVersion, ‪$minimumVersion, '<')) {
160  $this->messageQueue->enqueue(new FlashMessage(
161  'Your ' . ‪$platformLabel . ' version ' . $currentMysqlVersion . ' is too old. TYPO3 CMS does not run'
162  . ' with this version. Update to at least ' . ‪$platformLabel . ' ' . ‪$minimumVersion,
163  ‪$platformLabel . ' version too low',
164  ContextualFeedbackSeverity::ERROR
165  ));
166  } else {
167  $this->messageQueue->enqueue(new FlashMessage(
168  '',
169  ‪$platformLabel . ' version ' . $currentMysqlVersion . ' is fine'
170  ));
171  }
172  }
173 
179  public function ‪checkDefaultDatabaseCharset(Connection $connection): void
180  {
181  $queryBuilder = $connection->createQueryBuilder();
182  $defaultDatabaseCharset = (string)$queryBuilder->select('DEFAULT_CHARACTER_SET_NAME')
183  ->from('information_schema.SCHEMATA')
184  ->where(
185  $queryBuilder->expr()->eq(
186  'SCHEMA_NAME',
187  $queryBuilder->createNamedParameter($connection->getDatabase())
188  )
189  )
190  ->setMaxResults(1)
191  ->executeQuery()
192  ->fetchOne();
193 
194  ‪$platformLabel = $this->‪getPlatformLabel($connection);
195  if (!in_array($defaultDatabaseCharset, $this->databaseCharsetToCheck, true)) {
196  $this->messageQueue->enqueue(new FlashMessage(
197  sprintf(
198  'Checking database character set failed, got key "%s" instead of "%s"',
199  $defaultDatabaseCharset,
200  implode(' or ', $this->databaseCharsetToCheck)
201  ),
202  ‪$platformLabel . ' database character set check failed',
203  ContextualFeedbackSeverity::ERROR
204  ));
205  } else {
206  $this->messageQueue->enqueue(new FlashMessage(
207  '',
208  sprintf('%s database uses %s. All good.', ‪$platformLabel, implode(' or ', $this->databaseCharsetToCheck))
209  ));
210  }
211  }
212 
219  protected function ‪getIncompatibleSqlModes(Connection $connection): array
220  {
221  $sqlModes = explode(',', (string)$connection->executeQuery('SELECT @@SESSION.sql_mode;')->fetchOne());
222  return array_intersect($this->incompatibleSqlModes, $sqlModes);
223  }
224 
230  public function ‪checkDefaultDatabaseServerCharset(Connection $connection): void
231  {
232  $defaultServerCharset = $connection->executeQuery('SHOW VARIABLES LIKE \'character_set_server\'')->fetchAssociative();
233  ‪$platformLabel = $this->‪getPlatformLabel($connection);
234  if (!in_array($defaultServerCharset['Value'], $this->databaseServerCharsetToCheck, true)) {
235  $this->messageQueue->enqueue(new FlashMessage(
236  sprintf(
237  'Checking server character set failed, got key "%s" instead of "%s"',
238  $defaultServerCharset['Value'],
239  implode(' or ', $this->databaseServerCharsetToCheck)
240  ),
241  ‪$platformLabel . ' database server character set check failed',
242  ContextualFeedbackSeverity::INFO
243  ));
244  } else {
245  $this->messageQueue->enqueue(new FlashMessage(
246  '',
247  sprintf('%s server default uses %s. All good.', ‪$platformLabel, implode(' or ', $this->databaseCharsetToCheck))
248  ));
249  }
250  }
251 
255  public static function ‪isValidDatabaseName(string $databaseName): bool
256  {
257  return strlen($databaseName) <= static::SCHEMA_NAME_MAX_LENGTH && preg_match('/^[\x{0001}-\x{FFFF}]*$/u', $databaseName);
258  }
259 
260  protected function ‪checkDatabaseName(‪Connection $connection): void
261  {
262  if (static::isValidDatabaseName((string)$connection->getDatabase())) {
263  return;
264  }
265 
266  $this->messageQueue->enqueue(
267  new ‪FlashMessage(
268  'The given database name must not be longer than ' . static::SCHEMA_NAME_MAX_LENGTH . ' characters'
269  . ' and consist of the Unicode Basic Multilingual Plane (BMP), except U+0000',
270  'Database name not valid',
271  ContextualFeedbackSeverity::ERROR
272  )
273  );
274  }
275 
276  protected function ‪getMinimumVersion(‪Connection $connection): string
277  {
278  return $this->minimumVersion[$this->‪getPlatformType($connection)];
279  }
280 
281  protected function ‪getPlatformType(‪Connection $connection): string
282  {
284  }
285 
286  protected function ‪getPlatformLabel(‪Connection $connection): string
287  {
288  return $this->platformLabel[$this->‪getPlatformType($connection)];
289  }
290 
291  protected function ‪isMariaDb(‪Connection $connection): bool
292  {
293  return $connection->getDatabasePlatform() instanceof DoctrineMariaDBPlatform;
294  }
295 }
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\getStatus
‪getStatus()
Definition: MySql.php:95
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\getMinimumVersion
‪getMinimumVersion(Connection $connection)
Definition: MySql.php:273
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\isMariaDb
‪isMariaDb(Connection $connection)
Definition: MySql.php:288
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\PLATFORM_MARIADB
‪const PLATFORM_MARIADB
Definition: MySql.php:43
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\$incompatibleSqlModes
‪array $incompatibleSqlModes
Definition: MySql.php:67
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\checkMySQLOrMariaDBVersion
‪checkMySQLOrMariaDBVersion(Connection $connection)
Definition: MySql.php:142
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\AbstractPlatform
Definition: AbstractPlatform.php:29
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform
Definition: AbstractPlatform.php:18
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\getPlatformType
‪getPlatformType(Connection $connection)
Definition: MySql.php:278
‪TYPO3\CMS\Core\Database\Connection\createQueryBuilder
‪createQueryBuilder()
Definition: Connection.php:114
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\PLATFORM_MYSQL
‪const PLATFORM_MYSQL
Definition: MySql.php:42
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\isValidDatabaseName
‪static isValidDatabaseName(string $databaseName)
Definition: MySql.php:252
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\AbstractPlatform\$messageQueue
‪FlashMessageQueue $messageQueue
Definition: AbstractPlatform.php:32
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\checkDefaultDatabaseServerCharset
‪checkDefaultDatabaseServerCharset(Connection $connection)
Definition: MySql.php:227
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\checkDefaultDatabaseCharset
‪checkDefaultDatabaseCharset(Connection $connection)
Definition: MySql.php:176
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:27
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\checkDatabaseName
‪checkDatabaseName(Connection $connection)
Definition: MySql.php:257
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\getPlatformLabel
‪getPlatformLabel(Connection $connection)
Definition: MySql.php:283
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\$databaseCharsetToCheck
‪array $databaseCharsetToCheck
Definition: MySql.php:74
‪TYPO3\CMS\Core\Database\Connection\getPlatformServerVersion
‪getPlatformServerVersion()
Definition: Connection.php:361
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\checkInvalidSqlModes
‪checkInvalidSqlModes(Connection $connection)
Definition: MySql.php:116
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\$platformLabel
‪array $platformLabel
Definition: MySql.php:58
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Messaging\FlashMessageQueue
Definition: FlashMessageQueue.php:29
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\$minimumVersion
‪array $minimumVersion
Definition: MySql.php:50
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql
Definition: MySql.php:41
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\$databaseServerCharsetToCheck
‪array $databaseServerCharsetToCheck
Definition: MySql.php:83
‪TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform\MySql\getIncompatibleSqlModes
‪array getIncompatibleSqlModes(Connection $connection)
Definition: MySql.php:216