diff --git a/core/includes/schema.inc b/core/includes/schema.inc index 314939471d..3289c8068c 100644 --- a/core/includes/schema.inc +++ b/core/includes/schema.inc @@ -164,22 +164,16 @@ function drupal_uninstall_schema($module) { * @param string $table * The name of the table. If not given, the module's complete schema * is returned. + * + * @deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use + * SchemaVersionHandlerInterface::getSchema() instead. + * + * @see https://www.drupal.org/node/2970993 + * @see \Drupal\Core\Extension\ModuleInstallerInterface::getSchema() */ function drupal_get_module_schema($module, $table = NULL) { - // Load the .install file to get hook_schema. - module_load_install($module); - $schema = \Drupal::moduleHandler()->invoke($module, 'schema'); - - if (isset($table)) { - if (isset($schema[$table])) { - return $schema[$table]; - } - return []; - } - elseif (!empty($schema)) { - return $schema; - } - return []; + @trigger_error('drupal_get_module_schema() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use \Drupal\Core\Extension\ModuleInstallerInterface::getSchema() instead. See https://www.drupal.org/node/2970993', E_USER_DEPRECATED); + return \Drupal::service('module_installer')->getSchema($module, $table); } /** diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php index 62501c4570..9593438bc7 100644 --- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php +++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php @@ -618,66 +618,72 @@ public function validateUninstall(array $module_list) { } /** - * Fills in required default values for table definitions from hook_schema(). - * - * @param array $schema - * The schema definition array as it was returned by the module's - * hook_schema(). - * @param string $module - * The module for which hook_schema() was invoked. + * {@inheritdoc} */ - private function schemaInitialize(array &$schema, $module) { - // Set the name and module key for all tables. - foreach ($schema as $name => &$table) { - if (empty($table['module'])) { - $table['module'] = $module; - } - if (!isset($table['name'])) { - $table['name'] = $name; - } + public function getSchema($module, $table = NULL) { + // Load the .install file to use hook_schema() implementation. + $this->moduleHandler->loadInclude($module, 'install'); + $tables = $this->populateSchemaTables($module); + + if (isset($table)) { + return $tables[$table] ?? []; } + return $tables; } /** * Creates all tables defined in a module's hook_schema(). * - * Note: This function does not pass the module's schema through - * hook_schema_alter(). The module's tables will be created exactly as the - * module defines them. - * * @param string $module * The module for which the tables will be created. */ - private function schemaInstall($module) { - $schema = drupal_get_module_schema($module); - $this->schemaInitialize($schema, $module); - $connection_schema = $this->connection->schema(); + private function installSchema($module) { + $tables = $this->populateSchemaTables($module); + $schema = $this->connection->schema(); - foreach ($schema as $name => $table) { - $connection_schema->createTable($name, $table); + foreach ($tables as $name => $table) { + $schema->createTable($name, $table); } } /** * Removes all tables defined in a module's hook_schema(). * - * Note: This function does not pass the module's schema through - * hook_schema_alter(). The module's tables will be deleted exactly as the - * module defines them. - * * @param string $module * The module for which the tables will be removed. */ - private function schemaUninstall($module) { - $tables = drupal_get_module_schema($module); - $this->schemaInitialize($tables, $module); - $connection_schema = $this->connection->schema(); + private function uninstallSchema($module) { + $tables = $this->populateSchemaTables($module); + $schema = $this->connection->schema(); foreach ($tables as $table) { - if ($connection_schema->tableExists($table['name'])) { - $connection_schema->dropTable($table['name']); + if ($schema->tableExists($table['name'])) { + $schema->dropTable($table['name']); + } + } + } + + /** + * Fills in required default values for table definitions from hook_schema(). + * + * @param string $module + * The module for which hook_schema() should be invoked. + * + * @return array + * An array of schema definition provided by hook_schema(). + */ + private function populateSchemaTables($module) { + $tables = $this->moduleHandler->invoke($module, 'schema') ?? []; + // Set the name and module key for all tables. + foreach ($tables as $name => &$table) { + if (empty($table['module'])) { + $table['module'] = $module; + } + if (!isset($table['name'])) { + $table['name'] = $name; } } + return $tables; } } diff --git a/core/lib/Drupal/Core/Extension/ModuleInstallerInterface.php b/core/lib/Drupal/Core/Extension/ModuleInstallerInterface.php index c8221a1722..74288effb6 100644 --- a/core/lib/Drupal/Core/Extension/ModuleInstallerInterface.php +++ b/core/lib/Drupal/Core/Extension/ModuleInstallerInterface.php @@ -81,4 +81,31 @@ public function addUninstallValidator(ModuleUninstallValidatorInterface $uninsta */ public function validateUninstall(array $module_list); + /** + * Returns the module's schema. + * + * This function can be used to retrieve a schema specification in + * hook_schema(), so it allows you to derive your tables from existing + * specifications. + * + * It is also used by ::install() and ::uninstall() to ensure that a module's + * tables are created exactly as specified. + * + * Note: This function does not pass the module's schema through + * hook_schema_alter(). The module's tables will be returned exactly as the + * module defines them. + * + * @param string $module + * The module to which the table belongs. + * @param string $table + * (optional) The name of the table. Defaults to NULL, which means that the + * module's complete schema is returned. + * + * @return array + * An array of schema definition provided by hook_schema(). + * + * @see \hook_schema() + */ + public function getSchema($module, $table = NULL); + } diff --git a/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php index 174f7fb744..3a6759449a 100644 --- a/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php +++ b/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php @@ -99,6 +99,14 @@ public function validateUninstall(array $module_list) return $this->lazyLoadItself()->validateUninstall($module_list); } + /** + * {@inheritdoc} + */ + public function getSchema($module, $table = NULL) + { + return $this->lazyLoadItself()->getSchema($module, $table); + } + } } diff --git a/core/modules/system/tests/modules/module_test/module_test.install b/core/modules/system/tests/modules/module_test/module_test.install index 9d80d89605..89631eebd4 100644 --- a/core/modules/system/tests/modules/module_test/module_test.install +++ b/core/modules/system/tests/modules/module_test/module_test.install @@ -30,7 +30,7 @@ function module_test_schema() { * Implements hook_install(). */ function module_test_install() { - $schema = drupal_get_module_schema('module_test', 'module_test'); + $schema = \Drupal::service('module_installer')->getSchema('module_test', 'module_test'); Database::getConnection()->insert('module_test') ->fields([ 'data' => $schema['fields']['data']['type'], diff --git a/core/modules/system/tests/src/Functional/Module/ModuleTestBase.php b/core/modules/system/tests/src/Functional/Module/ModuleTestBase.php index e83f558df1..3c0dd87338 100644 --- a/core/modules/system/tests/src/Functional/Module/ModuleTestBase.php +++ b/core/modules/system/tests/src/Functional/Module/ModuleTestBase.php @@ -56,7 +56,7 @@ public function assertTableCount($base_table, $count = TRUE) { * The name of the module. */ public function assertModuleTablesExist($module) { - $tables = array_keys(drupal_get_module_schema($module)); + $tables = array_keys(\Drupal::service('module_installer')->getSchema($module)); $tables_exist = TRUE; $schema = Database::getConnection()->schema(); foreach ($tables as $table) { @@ -74,7 +74,7 @@ public function assertModuleTablesExist($module) { * The name of the module. */ public function assertModuleTablesDoNotExist($module) { - $tables = array_keys(drupal_get_module_schema($module)); + $tables = array_keys(\Drupal::service('module_installer')->getSchema($module)); $tables_exist = FALSE; $schema = Database::getConnection()->schema(); foreach ($tables as $table) { diff --git a/core/tests/Drupal/KernelTests/Core/Database/InsertDefaultsTest.php b/core/tests/Drupal/KernelTests/Core/Database/InsertDefaultsTest.php index 8c0f57f020..8cc9e6287e 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/InsertDefaultsTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/InsertDefaultsTest.php @@ -18,7 +18,7 @@ public function testDefaultInsert() { $query = $this->connection->insert('test')->useDefaults(['job']); $id = $query->execute(); - $schema = drupal_get_module_schema('database_test', 'test'); + $schema = \Drupal::service('module_installer')->getSchema('database_test', 'test'); $job = $this->connection->query('SELECT job FROM {test} WHERE id = :id', [':id' => $id])->fetchField(); $this->assertEqual($job, $schema['fields']['job']['default'], 'Default field value is set.'); @@ -52,7 +52,7 @@ public function testDefaultInsertWithFields() { ->useDefaults(['job']); $id = $query->execute(); - $schema = drupal_get_module_schema('database_test', 'test'); + $schema = \Drupal::service('module_installer')->getSchema('database_test', 'test'); $job = $this->connection->query('SELECT job FROM {test} WHERE id = :id', [':id' => $id])->fetchField(); $this->assertEqual($job, $schema['fields']['job']['default'], 'Default field value is set.'); diff --git a/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php b/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php index 696a4f798b..3f47af15c2 100644 --- a/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php +++ b/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php @@ -79,11 +79,16 @@ public function testCacheBinCleanup() { /** * Ensure that rebuilding the container in hook_install() works. + * + * @covers ::getSchema */ public function testKernelRebuildDuringHookInstall() { \Drupal::state()->set('module_test_install:rebuild_container', TRUE); $module_installer = $this->container->get('module_installer'); $this->assertTrue($module_installer->install(['module_test'])); + $schema = $module_installer->getSchema('module_test'); + $this->assertSame('module_test', $schema['module_test']['module']); + $this->assertSame('module_test', $schema['module_test']['name']); } /** diff --git a/core/tests/Drupal/KernelTests/Core/Extension/SchemaDeprecationTest.php b/core/tests/Drupal/KernelTests/Core/Extension/SchemaDeprecationTest.php index 0e1816aaf5..470ba66d7f 100644 --- a/core/tests/Drupal/KernelTests/Core/Extension/SchemaDeprecationTest.php +++ b/core/tests/Drupal/KernelTests/Core/Extension/SchemaDeprecationTest.php @@ -20,6 +20,7 @@ class SchemaDeprecationTest extends KernelTestBase { /** * @expectedDeprecation drupal_install_schema() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. No direct replacement is provided. See https://www.drupal.org/node/2970993 * @expectedDeprecation drupal_uninstall_schema() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. No direct replacement is provided. See https://www.drupal.org/node/2970993 + * @expectedDeprecation drupal_get_module_schema() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use \Drupal\Core\Extension\ModuleInstallerInterface::getSchema() instead. See https://www.drupal.org/node/2970993 */ public function testDeprecatedInstallSchema() { drupal_install_schema('dblog'); diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index b1ebad5e32..51906423a7 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -699,7 +699,7 @@ protected function installConfig($modules) { * If $module is not enabled or the table schema cannot be found. */ protected function installSchema($module, $tables) { - // drupal_get_module_schema() is technically able to install a schema + // Module installer is technically able to install a schema // of a non-enabled module, but its ability to load the module's .install // file depends on many other factors. To prevent differences in test // behavior and non-reproducible test failures, we only allow the schema of @@ -707,9 +707,11 @@ protected function installSchema($module, $tables) { if (!$this->container->get('module_handler')->moduleExists($module)) { throw new \LogicException("$module module is not enabled."); } + /** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */ + $module_installer = $this->container->get('module_installer'); $tables = (array) $tables; foreach ($tables as $table) { - $schema = drupal_get_module_schema($module, $table); + $schema = $module_installer->getSchema($module, $table); if (empty($schema)) { throw new \LogicException("$module module does not define a schema for table '$table'."); }