From ade46ac78180633c863c59055c4db342f8e1f0d8 Mon Sep 17 00:00:00 2001 From: Manuel Selbach <manuel_selbach@yahoo.de> Date: Fri, 20 Jan 2017 09:59:49 +0100 Subject: [PATCH] [TASK] Add SystemStatusCheck for PostgreSQL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SystemStatusCheck for PostgreSQL checks the server and the libpq version. It’s important to use the correct libpq version as this will lead to problems if it differs to much from the server version. Change-Id: I370b57cc8e516624ee7a299b0c3710d834175386 Resolves: #79331 Releases: master Reviewed-on: https://review.typo3.org/51368 Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Manuel Selbach <manuel_selbach@yahoo.de> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de> --- .../Classes/SystemEnvironment/Check.php | 4 +- .../SystemEnvironment/CheckInterface.php | 36 ++++ .../SystemEnvironment/DatabaseCheck.php | 137 ++------------ .../DatabasePlatform/MySqlCheck.php | 173 ++++++++++++++++++ .../DatabasePlatform/PostgreSqlCheck.php | 130 +++++++++++++ .../Classes/SystemEnvironment/SetupCheck.php | 4 +- 6 files changed, 358 insertions(+), 126 deletions(-) create mode 100644 typo3/sysext/install/Classes/SystemEnvironment/CheckInterface.php create mode 100644 typo3/sysext/install/Classes/SystemEnvironment/DatabasePlatform/MySqlCheck.php create mode 100644 typo3/sysext/install/Classes/SystemEnvironment/DatabasePlatform/PostgreSqlCheck.php diff --git a/typo3/sysext/install/Classes/SystemEnvironment/Check.php b/typo3/sysext/install/Classes/SystemEnvironment/Check.php index 087d7c60babc..7760796a67aa 100644 --- a/typo3/sysext/install/Classes/SystemEnvironment/Check.php +++ b/typo3/sysext/install/Classes/SystemEnvironment/Check.php @@ -44,7 +44,7 @@ use TYPO3\CMS\Install\Status; * text only. The return values of this class are not bound to HTML * and can be used in different scopes (eg. as json array). */ -class Check +class Check implements CheckInterface { /** * @var array List of required PHP extensions @@ -70,7 +70,7 @@ class Check * * @return array<\TYPO3\CMS\Install\Status\StatusInterface> */ - public function getStatus() + public function getStatus(): array { $status = []; $status[] = $this->checkCurrentDirectoryIsInIncludePath(); diff --git a/typo3/sysext/install/Classes/SystemEnvironment/CheckInterface.php b/typo3/sysext/install/Classes/SystemEnvironment/CheckInterface.php new file mode 100644 index 000000000000..be33574859d7 --- /dev/null +++ b/typo3/sysext/install/Classes/SystemEnvironment/CheckInterface.php @@ -0,0 +1,36 @@ +<?php + +namespace TYPO3\CMS\Install\SystemEnvironment; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Check system environment status + * + * This interface needs to be implemented by hardcoded requirement + * checks of the underlying server and PHP system. + * + * The status messages and title *must not* include HTML, use + * plain text only. The return values of this class can be used + * in different scopes (eg. as json array). + */ +interface CheckInterface +{ + /** + * Get all status information as array with status objects + * + * @return \TYPO3\CMS\Install\Status\StatusInterface[] + */ + public function getStatus(): array; +} diff --git a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck.php b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck.php index df6122b2e9cf..02db02f49f3c 100644 --- a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck.php +++ b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck.php @@ -13,12 +13,9 @@ namespace TYPO3\CMS\Install\SystemEnvironment; * * The TYPO3 project - inspiring people to share! */ - -use TYPO3\CMS\Core\Database\Connection; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Install\Status; +use TYPO3\CMS\Install\SystemEnvironment\DatabasePlatform\MySqlCheck; +use TYPO3\CMS\Install\SystemEnvironment\DatabasePlatform\PostgreSqlCheck; /** * Check database configuration status @@ -29,135 +26,31 @@ use TYPO3\CMS\Install\Status; * text only. The return values of this class are not bound to HTML * and can be used in different scopes (eg. as json array). */ -class DatabaseCheck +class DatabaseCheck implements CheckInterface { /** - * List of MySQL modes that are incompatible with TYPO3 CMS + * List of database platforms to check * * @var array */ - protected $incompatibleSqlModes = [ - 'NO_BACKSLASH_ESCAPES' + protected $databasePlatformChecks = [ + MySqlCheck::class, + PostgreSqlCheck::class, ]; /** - * Get all status information as array with status objects + * Get status of each database platform defined in the list * - * @return \TYPO3\CMS\Install\Status\StatusInterface[] + * @return array + * @throws \InvalidArgumentException */ - public function getStatus() + public function getStatus(): array { - $statusArray = []; - $defaultConnection = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME); - if (strpos($defaultConnection->getServerVersion(), 'MySQL') !== 0) { - return $statusArray; - } - $statusArray[] = $this->checkMysqlVersion($defaultConnection); - $statusArray[] = $this->checkInvalidSqlModes($defaultConnection); - $statusArray[] = $this->checkMysqlDatabaseUtf8Status($defaultConnection); - return $statusArray; - } + $databaseStatus = []; - /** - * Check if any SQL mode is set which is not compatible with TYPO3 - * - * @param Connection Connection to the database to be checked - * @return Status\StatusInterface - */ - protected function checkInvalidSqlModes($connection) - { - $detectedIncompatibleSqlModes = $this->getIncompatibleSqlModes($connection); - if (!empty($detectedIncompatibleSqlModes)) { - $status = new Status\ErrorStatus(); - $status->setTitle('Incompatible SQL modes found!'); - $status->setMessage( - 'Incompatible SQL modes have been detected:' . - ' ' . implode(', ', $detectedIncompatibleSqlModes) . '.' . - ' The listed modes are not compatible with TYPO3 CMS.' . - ' You have to change that setting in your MySQL environment' . - ' or in $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'setDBinit\']' - ); - } else { - $status = new Status\OkStatus(); - $status->setTitle('No incompatible SQL modes found.'); - } - - return $status; - } - - /** - * Check minimum MySQL version - * - * @param Connection Connection to the database to be checked - * @return Status\StatusInterface - */ - protected function checkMysqlVersion($connection) - { - $minimumMysqlVersion = '5.5.0'; - preg_match('/MySQL ((\d+\.)*(\d+\.)*\d+)/', $connection->getServerVersion(), $match); - $currentMysqlVersion = $match[1]; - if (version_compare($currentMysqlVersion, $minimumMysqlVersion) < 0) { - $status = new Status\ErrorStatus(); - $status->setTitle('MySQL version too low'); - $status->setMessage( - 'Your MySQL version ' . $currentMysqlVersion . ' is too old. TYPO3 CMS does not run' . - ' with this version. Update to at least MySQL ' . $minimumMysqlVersion - ); - } else { - $status = new Status\OkStatus(); - $status->setTitle('MySQL version is fine'); + foreach ($this->databasePlatformChecks as $databasePlatformCheckClass) { + $databaseStatus += GeneralUtility::makeInstance($databasePlatformCheckClass)->getStatus(); } - - return $status; - } - - /** - * Checks the character set of the database and reports an error if it is not utf-8. - * - * @param Connection $connection to the database to be checked - * @return Status\StatusInterface - */ - protected function checkMysqlDatabaseUtf8Status(Connection $connection) - { - /** @var QueryBuilder $queryBuilder */ - $queryBuilder = $connection->createQueryBuilder(); - $defaultDatabaseCharset = (string)$queryBuilder->select('DEFAULT_CHARACTER_SET_NAME') - ->from('information_schema.SCHEMATA') - ->where( - $queryBuilder->expr()->eq( - 'SCHEMA_NAME', - $queryBuilder->createNamedParameter($connection->getDatabase(), \PDO::PARAM_STR) - ) - ) - ->setMaxResults(1) - ->execute() - ->fetchColumn(); - // also allow utf8mb4 - if (strpos($defaultDatabaseCharset, 'utf8') !== 0) { - $status = new Status\ErrorStatus(); - $status->setTitle('MySQL database character set check failed'); - $status->setMessage( - 'Checking database character set failed, got key "' - . $defaultDatabaseCharset . '" instead of "utf8" or "utf8mb4"' - ); - } else { - $status = new Status\OkStatus(); - $status->setTitle('Your database uses utf-8. All good.'); - } - return $status; - } - - /** - * Returns an array with the current sql mode settings - * - * @param Connection Connection to the database to be checked - * @return array Contains all configured SQL modes that are incompatible - */ - protected function getIncompatibleSqlModes($connection) - { - $sqlModes = explode(',', $connection->executeQuery('SELECT @@SESSION.sql_mode;') - ->fetch(0)['@@SESSION.sql_mode']); - return array_intersect($this->incompatibleSqlModes, $sqlModes); + return $databaseStatus; } } diff --git a/typo3/sysext/install/Classes/SystemEnvironment/DatabasePlatform/MySqlCheck.php b/typo3/sysext/install/Classes/SystemEnvironment/DatabasePlatform/MySqlCheck.php new file mode 100644 index 000000000000..5699584b36fe --- /dev/null +++ b/typo3/sysext/install/Classes/SystemEnvironment/DatabasePlatform/MySqlCheck.php @@ -0,0 +1,173 @@ +<?php + +namespace TYPO3\CMS\Install\SystemEnvironment\DatabasePlatform; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryBuilder; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Status; +use TYPO3\CMS\Install\SystemEnvironment\CheckInterface; + +/** + * Check database configuration status for MySQL server + * + * This class is a hardcoded requirement check for the database server. + * + * The status messages and title *must not* include HTML, use plain + * text only. The return values of this class are not bound to HTML + * and can be used in different scopes (eg. as json array). + */ +class MySqlCheck implements CheckInterface +{ + /** + * Minimum supported MySQL version + * + * @var string + */ + protected $minimumMySQLVersion = '5.5.0'; + + /** + * List of MySQL modes that are incompatible with TYPO3 CMS + * + * @var array + */ + protected $incompatibleSqlModes = [ + 'NO_BACKSLASH_ESCAPES' + ]; + + /** + * Get all status information as array with status objects + * + * @return \TYPO3\CMS\Install\Status\StatusInterface[] + * @throws \InvalidArgumentException + * @throws \Doctrine\DBAL\DBALException + */ + public function getStatus(): array + { + $statusArray = []; + $defaultConnection = GeneralUtility::makeInstance(ConnectionPool::class) + ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME); + if (strpos($defaultConnection->getServerVersion(), 'MySQL') !== 0) { + return $statusArray; + } + $statusArray[] = $this->checkMysqlVersion($defaultConnection); + $statusArray[] = $this->checkInvalidSqlModes($defaultConnection); + $statusArray[] = $this->checkMysqlDatabaseUtf8Status($defaultConnection); + return $statusArray; + } + + /** + * Check if any SQL mode is set which is not compatible with TYPO3 + * + * @param Connection Connection to the database to be checked + * @return Status\StatusInterface + */ + protected function checkInvalidSqlModes($connection) + { + $detectedIncompatibleSqlModes = $this->getIncompatibleSqlModes($connection); + if (!empty($detectedIncompatibleSqlModes)) { + $status = new Status\ErrorStatus(); + $status->setTitle('Incompatible SQL modes found!'); + $status->setMessage( + 'Incompatible SQL modes have been detected:' . + ' ' . implode(', ', $detectedIncompatibleSqlModes) . '.' . + ' The listed modes are not compatible with TYPO3 CMS.' . + ' You have to change that setting in your MySQL environment' . + ' or in $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'setDBinit\']' + ); + } else { + $status = new Status\OkStatus(); + $status->setTitle('No incompatible SQL modes found.'); + } + + return $status; + } + + /** + * Check minimum MySQL version + * + * @param Connection Connection to the database to be checked + * @return Status\StatusInterface + */ + protected function checkMysqlVersion($connection) + { + preg_match('/MySQL ((\d+\.)*(\d+\.)*\d+)/', $connection->getServerVersion(), $match); + $currentMysqlVersion = $match[1]; + if (version_compare($currentMysqlVersion, $this->minimumMySQLVersion, '<')) { + $status = new Status\ErrorStatus(); + $status->setTitle('MySQL version too low'); + $status->setMessage( + 'Your MySQL version ' . $currentMysqlVersion . ' is too old. TYPO3 CMS does not run' . + ' with this version. Update to at least MySQL ' . $this->minimumMySQLVersion + ); + } else { + $status = new Status\OkStatus(); + $status->setTitle('MySQL version is fine'); + } + + return $status; + } + + /** + * Checks the character set of the database and reports an error if it is not utf-8. + * + * @param Connection $connection to the database to be checked + * @return Status\StatusInterface + */ + protected function checkMysqlDatabaseUtf8Status(Connection $connection) + { + /** @var QueryBuilder $queryBuilder */ + $queryBuilder = $connection->createQueryBuilder(); + $defaultDatabaseCharset = (string)$queryBuilder->select('DEFAULT_CHARACTER_SET_NAME') + ->from('information_schema.SCHEMATA') + ->where( + $queryBuilder->expr()->eq( + 'SCHEMA_NAME', + $queryBuilder->createNamedParameter($connection->getDatabase(), \PDO::PARAM_STR) + ) + ) + ->setMaxResults(1) + ->execute() + ->fetchColumn(); + // also allow utf8mb4 + if (strpos($defaultDatabaseCharset, 'utf8') !== 0) { + $status = new Status\ErrorStatus(); + $status->setTitle('MySQL database character set check failed'); + $status->setMessage( + 'Checking database character set failed, got key "' + . $defaultDatabaseCharset . '" instead of "utf8" or "utf8mb4"' + ); + } else { + $status = new Status\OkStatus(); + $status->setTitle('Your database uses utf-8. All good.'); + } + return $status; + } + + /** + * Returns an array with the current sql mode settings + * + * @param Connection Connection to the database to be checked + * @return array Contains all configured SQL modes that are incompatible + */ + protected function getIncompatibleSqlModes($connection) + { + $sqlModes = explode(',', $connection->executeQuery('SELECT @@SESSION.sql_mode;') + ->fetch(0)['@@SESSION.sql_mode']); + return array_intersect($this->incompatibleSqlModes, $sqlModes); + } +} diff --git a/typo3/sysext/install/Classes/SystemEnvironment/DatabasePlatform/PostgreSqlCheck.php b/typo3/sysext/install/Classes/SystemEnvironment/DatabasePlatform/PostgreSqlCheck.php new file mode 100644 index 000000000000..98f8e0ec230c --- /dev/null +++ b/typo3/sysext/install/Classes/SystemEnvironment/DatabasePlatform/PostgreSqlCheck.php @@ -0,0 +1,130 @@ +<?php + +namespace TYPO3\CMS\Install\SystemEnvironment\DatabasePlatform; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Status; +use TYPO3\CMS\Install\SystemEnvironment\CheckInterface; + +/** + * Check database configuration status for PostgreSQL + * + * This class is a hardcoded requirement check for the database server. + * + * The status messages and title *must not* include HTML, use plain + * text only. The return values of this class are not bound to HTML + * and can be used in different scopes (eg. as json array). + */ +class PostgreSqlCheck implements CheckInterface +{ + /** + * Minimum supported PostgreSQL Server version + * + * @var string + */ + protected $minimumPostgreSQLVerion = '9.2'; + + /** + * Minimum supported libpq version + * @var string + */ + protected $minimumLibPQVersion = '9.0'; + + /** + * Get all status information as array with status objects + * + * @return array + * @throws \Doctrine\DBAL\DBALException + * @throws \InvalidArgumentException + */ + public function getStatus(): array + { + $statusArray = []; + $defaultConnection = GeneralUtility::makeInstance(ConnectionPool::class) + ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME); + if (strpos($defaultConnection->getServerVersion(), 'PostgreSQL') !== 0) { + return $statusArray; + } + + $statusArray[] = $this->checkPostgreSqlVersion($defaultConnection); + $statusArray[] = $this->checkLibpqVersion(); + return $statusArray; + } + + /** + * Check minimum PostgreSQL version + * + * @param Connection Connection to the database to be checked + * @return Status\StatusInterface + */ + protected function checkPostgreSqlVersion($connection): Status\StatusInterface + { + preg_match('/PostgreSQL ((\d+\.)*(\d+\.)*\d+)/', $connection->getServerVersion(), $match); + $currentPostgreSqlVersion = $match[1]; + if (version_compare($currentPostgreSqlVersion, $this->minimumPostgreSQLVerion, '<')) { + $status = new Status\ErrorStatus(); + $status->setTitle('PostgreSQL Server version is unsupported'); + $status->setMessage( + 'Your PostgreSQL version ' . $currentPostgreSqlVersion . ' is not supported. TYPO3 CMS does not run' . + ' with this version. The minimum supported PostgreSQL version is ' . $this->minimumPostgreSQLVerion + ); + } else { + $status = new Status\OkStatus(); + $status->setTitle('PostgreSQL Server version is supported'); + } + + return $status; + } + + /** + * Check the version of ligpq within the PostgreSQL driver + * + * @return Status\StatusInterface + */ + protected function checkLibpqVersion(): Status\StatusInterface + { + if (!defined('PGSQL_LIBPQ_VERSION_STR')) { + $status = new Status\WarningStatus(); + $status->setTitle('PostgreSQL libpq version cannot be determined'); + $status->setMessage( + 'It is not possible to retrieve your PostgreSQL libpq version. Please check the version' . + ' in the "phpinfo" area of the "System environment" module in the install tool manually.' . + ' This should be found in section "pdo_pgsql".' . + ' You should have at least the following version of PostgreSQL libpq installed: ' . + $this->minimumLibPQVersion + ); + } else { + preg_match('/PostgreSQL ((\d+\.)*(\d+\.)*\d+)/', \PGSQL_LIBPQ_VERSION_STR, $match); + $currentPostgreSqlLibpqVersion = $match[1]; + + if (version_compare($currentPostgreSqlLibpqVersion, $this->minimumLibPQVersion, '<')) { + $status = new Status\ErrorStatus(); + $status->setTitle('PostgreSQL libpq version is unsupported'); + $status->setMessage( + 'Your PostgreSQL libpq version "' . $currentPostgreSqlLibpqVersion . '" is unsupported.' . + ' TYPO3 CMS does not run with this version. The minimum supported libpq version is ' . + $this->minimumLibPQVersion + ); + } else { + $status = new Status\OkStatus(); + $status->setTitle('PostgreSQL libpq version is supported'); + } + } + return $status; + } +} diff --git a/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php b/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php index 14c19c17d341..a9fa51ac6c6f 100644 --- a/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php +++ b/typo3/sysext/install/Classes/SystemEnvironment/SetupCheck.php @@ -27,14 +27,14 @@ use TYPO3\CMS\Install\Status; * text only. The return values of this class are not bound to HTML * and can be used in different scopes (eg. as json array). */ -class SetupCheck +class SetupCheck implements CheckInterface { /** * Get all status information as array with status objects * * @return array<\TYPO3\CMS\Install\Status\StatusInterface> */ - public function getStatus() + public function getStatus(): array { $status = []; -- GitLab