diff --git a/core/modules/mysql/src/Hook/MysqlRequirements.php b/core/modules/mysql/src/Hook/MysqlRequirements.php index c3dfb10ca434cd096fa0db34203e88f578af93f0..55a3e144bbafafb6f52a3c781af0c0f40cbb9836 100644 --- a/core/modules/mysql/src/Hook/MysqlRequirements.php +++ b/core/modules/mysql/src/Hook/MysqlRequirements.php @@ -5,16 +5,16 @@ namespace Drupal\mysql\Hook; use Drupal\Core\Database\Database; -use Drupal\Core\Extension\Requirement\RequirementSeverity; use Drupal\Core\Hook\Attribute\Hook; -use Drupal\Core\Render\Markup; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\mysql\RequirementsTrait; /** * Requirements for the MySQL module. */ class MysqlRequirements { + use RequirementsTrait; use StringTranslationTrait; /** @@ -22,65 +22,17 @@ class MysqlRequirements { */ #[Hook('runtime_requirements')] public function runtime(): array { - $requirements = []; - // Test with MySql databases. - if (Database::isActiveConnection()) { - $connection = Database::getConnection(); - // Only show requirements when MySQL is the default database connection. - if (!($connection->driver() === 'mysql' && $connection->getProvider() === 'mysql')) { - return []; - } - - $query = $connection->isMariaDb() ? 'SELECT @@SESSION.tx_isolation' : 'SELECT @@SESSION.transaction_isolation'; - - $isolation_level = $connection->query($query)->fetchField(); - - $tables_missing_primary_key = []; - $tables = $connection->schema()->findTables('%'); - foreach ($tables as $table) { - $primary_key_column = Database::getConnection()->query("SHOW KEYS FROM {" . $table . "} WHERE Key_name = 'PRIMARY'")->fetchAllAssoc('Column_name'); - if (empty($primary_key_column)) { - $tables_missing_primary_key[] = $table; - } - } - - $description = []; - if ($isolation_level == 'READ-COMMITTED') { - if (empty($tables_missing_primary_key)) { - $severity_level = RequirementSeverity::OK; - } - else { - $severity_level = RequirementSeverity::Error; - } - } - else { - if ($isolation_level == 'REPEATABLE-READ') { - $severity_level = RequirementSeverity::Warning; - } - else { - $severity_level = RequirementSeverity::Error; - $description[] = $this->t('This is not supported by Drupal.'); - } - $description[] = $this->t('The recommended level for Drupal is "READ COMMITTED".'); - } - - if (!empty($tables_missing_primary_key)) { - $description[] = $this->t('For this to work correctly, all tables must have a primary key. The following table(s) do not have a primary key: @tables.', ['@tables' => implode(', ', $tables_missing_primary_key)]); - } - - $description[] = $this->t('See the <a href=":performance_doc">setting MySQL transaction isolation level</a> page for more information.', [ - ':performance_doc' => 'https://www.drupal.org/docs/system-requirements/setting-the-mysql-transaction-isolation-level', - ]); + if (!Database::isActiveConnection()) { + return []; + } - $requirements['mysql_transaction_level'] = [ - 'title' => $this->t('Transaction isolation level'), - 'severity' => $severity_level, - 'value' => $isolation_level, - 'description' => Markup::create(implode(' ', $description)), - ]; + $connection = Database::getConnection(); + // Only show requirements when MySQL is the default database connection. + if (!($connection->driver() === 'mysql' && $connection->getProvider() === 'mysql')) { + return []; } - return $requirements; + return $this->getRuntimeRequirements($connection); } } diff --git a/core/modules/mysql/src/RequirementsTrait.php b/core/modules/mysql/src/RequirementsTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..3aa18b1760445227c376750787d885aceca1fdf4 --- /dev/null +++ b/core/modules/mysql/src/RequirementsTrait.php @@ -0,0 +1,77 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\mysql; + +use Drupal\Core\Database\Connection; +use Drupal\Core\Extension\Requirement\RequirementSeverity; +use Drupal\Core\Render\Markup; + +/** + * Runtime requirements trait. + * + * The mysql and the mysqli drivers share the same requirements; this trait + * helps sharing them. + */ +trait RequirementsTrait { + + /** + * Returns runtime requirements. + */ + public function getRuntimeRequirements(Connection $connection): array { + $requirements = []; + + // Transaction isolation level. + $query = $connection->isMariaDb() ? 'SELECT @@SESSION.tx_isolation' : 'SELECT @@SESSION.transaction_isolation'; + $isolation_level = $connection->query($query)->fetchField(); + + // Tables missing primary key. + $tables_missing_primary_key = []; + $tables = $connection->schema()->findTables('%'); + foreach ($tables as $table) { + $primary_key_column = $connection->query("SHOW KEYS FROM {" . $table . "} WHERE Key_name = 'PRIMARY'")->fetchAllAssoc('Column_name'); + if (empty($primary_key_column)) { + $tables_missing_primary_key[] = $table; + } + } + + $description = []; + if ($isolation_level == 'READ-COMMITTED') { + if (empty($tables_missing_primary_key)) { + $severity_level = RequirementSeverity::OK; + } + else { + $severity_level = RequirementSeverity::Error; + } + } + else { + if ($isolation_level == 'REPEATABLE-READ') { + $severity_level = RequirementSeverity::Warning; + } + else { + $severity_level = RequirementSeverity::Error; + $description[] = $this->t('This is not supported by Drupal.'); + } + $description[] = $this->t('The recommended level for Drupal is "READ COMMITTED".'); + } + + if (!empty($tables_missing_primary_key)) { + $description[] = $this->t('For this to work correctly, all tables must have a primary key. The following table(s) do not have a primary key: @tables.', ['@tables' => implode(', ', $tables_missing_primary_key)]); + } + + $description[] = $this->t('See the <a href=":performance_doc">setting MySQL transaction isolation level</a> page for more information.', [ + ':performance_doc' => 'https://www.drupal.org/docs/system-requirements/setting-the-mysql-transaction-isolation-level', + ]); + + $requirements['mysql_transaction_level'] = [ + 'title' => $this->t('Transaction isolation level'), + 'severity' => $severity_level, + 'value' => $isolation_level, + 'description' => Markup::create(implode(' ', $description)), + ]; + + return $requirements; + } + +} diff --git a/core/modules/mysqli/src/Hook/MysqliHooks.php b/core/modules/mysqli/src/Hook/MysqliHooks.php index 340b17373a1214c8b487dd7d66a8b474481e3f43..556ea12846c4a6bfc483b7e4c07bd8ea222d5c0b 100644 --- a/core/modules/mysqli/src/Hook/MysqliHooks.php +++ b/core/modules/mysqli/src/Hook/MysqliHooks.php @@ -3,17 +3,17 @@ namespace Drupal\mysqli\Hook; use Drupal\Core\Database\Database; -use Drupal\Core\Extension\Requirement\RequirementSeverity; use Drupal\Core\Hook\Attribute\Hook; -use Drupal\Core\Render\Markup; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\mysql\RequirementsTrait; /** * Hook implementations for mysqli. */ class MysqliHooks { + use RequirementsTrait; use StringTranslationTrait; /** @@ -37,66 +37,17 @@ public function help($route_name, RouteMatchInterface $route_match): ?string { */ #[Hook('runtime_requirements')] public function runtimeRequirements(): array { - $requirements = []; - - // Test with MySql databases. - if (Database::isActiveConnection()) { - $connection = Database::getConnection(); - // Only show requirements when MySQLi is the default database connection. - if (!($connection->driver() === 'mysqli' && $connection->getProvider() === 'mysqli')) { - return []; - } - - $query = $connection->isMariaDb() ? 'SELECT @@SESSION.tx_isolation' : 'SELECT @@SESSION.transaction_isolation'; - - $isolation_level = $connection->query($query)->fetchField(); - - $tables_missing_primary_key = []; - $tables = $connection->schema()->findTables('%'); - foreach ($tables as $table) { - $primary_key_column = Database::getConnection()->query("SHOW KEYS FROM {" . $table . "} WHERE Key_name = 'PRIMARY'")->fetchAllAssoc('Column_name'); - if (empty($primary_key_column)) { - $tables_missing_primary_key[] = $table; - } - } - - $description = []; - if ($isolation_level == 'READ-COMMITTED') { - if (empty($tables_missing_primary_key)) { - $severity_level = RequirementSeverity::OK; - } - else { - $severity_level = RequirementSeverity::Error; - } - } - else { - if ($isolation_level == 'REPEATABLE-READ') { - $severity_level = RequirementSeverity::Warning; - } - else { - $severity_level = RequirementSeverity::Error; - $description[] = $this->t('This is not supported by Drupal.'); - } - $description[] = $this->t('The recommended level for Drupal is "READ COMMITTED".'); - } - - if (!empty($tables_missing_primary_key)) { - $description[] = $this->t('For this to work correctly, all tables must have a primary key. The following table(s) do not have a primary key: @tables.', ['@tables' => implode(', ', $tables_missing_primary_key)]); - } - - $description[] = $this->t('See the <a href=":performance_doc">setting MySQL transaction isolation level</a> page for more information.', [ - ':performance_doc' => 'https://www.drupal.org/docs/system-requirements/setting-the-mysql-transaction-isolation-level', - ]); + if (!Database::isActiveConnection()) { + return []; + } - $requirements['mysql_transaction_level'] = [ - 'title' => $this->t('Transaction isolation level'), - 'severity' => $severity_level, - 'value' => $isolation_level, - 'description' => Markup::create(implode(' ', $description)), - ]; + $connection = Database::getConnection(); + // Only show requirements when MySQLi is the default database connection. + if (!($connection->driver() === 'mysqli' && $connection->getProvider() === 'mysqli')) { + return []; } - return $requirements; + return $this->getRuntimeRequirements($connection); } }