diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php index 8647029..b757556 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandler.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php @@ -706,4 +706,11 @@ public function getName($module) { return $module_data[$module]->info['name']; } + /** + * {@inheritdoc} + */ + public function isCoreCompatible($core) { + return substr(\Drupal::CORE_COMPATIBILITY, 0, 1) == substr($core, 0, 1) && !version_compare(\Drupal::VERSION, $core, '<'); + } + } diff --git a/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php b/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php index f6c7be5..9708940 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php @@ -311,4 +311,15 @@ public function getModuleDirectories(); */ public function getName($theme); + /** + * Check a module's core compatibility + * + * @param string $core + * The value of the core key in a module .info.yml file. + * + * @return bool + * FALSE if invalid or incompatible, TRUE otherwise. + */ + public function isCoreCompatible($core); + } diff --git a/core/modules/system/src/Controller/SystemController.php b/core/modules/system/src/Controller/SystemController.php index 22bade6..d21674f 100644 --- a/core/modules/system/src/Controller/SystemController.php +++ b/core/modules/system/src/Controller/SystemController.php @@ -230,7 +230,7 @@ public function themesPage() { // Ensure this theme is compatible with this version of core. // Require the 'content' region to make sure the main page // content has a common place in all themes. - $theme->incompatible_core = !isset($theme->info['core']) || ($theme->info['core'] != \DRUPAL::CORE_COMPATIBILITY) || !isset($theme->info['regions']['content']); + $theme->incompatible_core = !isset($theme->info['core']) || !$this->moduleHandler()->isCoreCompatible($theme->info['core']) || !isset($theme->info['regions']['content']); $theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0; // Confirmed that the base theme is available. $theme->incompatible_base = isset($theme->info['base theme']) && !isset($themes[$theme->info['base theme']]); diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php index 2486ca4..3ae43f0 100644 --- a/core/modules/system/src/Form/ModulesListForm.php +++ b/core/modules/system/src/Form/ModulesListForm.php @@ -348,10 +348,10 @@ protected function buildRow(array $modules, Extension $module, $distribution) { $reasons = array(); // Check the core compatibility. - if ($module->info['core'] != \Drupal::CORE_COMPATIBILITY) { + if (!$this->moduleHandler->isCoreCompatible($module->info['core'])) { $compatible = FALSE; $reasons[] = $this->t('This version is not compatible with Drupal !core_version and should be replaced.', array( - '!core_version' => \Drupal::CORE_COMPATIBILITY, + '!core_version' => \Drupal::VERSION, )); } @@ -393,7 +393,7 @@ protected function buildRow(array $modules, Extension $module, $distribution) { } // Disable the checkbox if the dependency is incompatible with this // version of Drupal core. - elseif ($modules[$dependency]->info['core'] != \Drupal::CORE_COMPATIBILITY) { + elseif (!$this->moduleHandler->isCoreCompatible($modules[$dependency]->info['core'])) { $row['#requires'][$dependency] = $this->t('@module (incompatible with this version of Drupal core)', array( '@module' => $name, )); diff --git a/core/modules/system/src/Tests/Module/DependencyTest.php b/core/modules/system/src/Tests/Module/DependencyTest.php index 6454baf..d20bfe3 100644 --- a/core/modules/system/src/Tests/Module/DependencyTest.php +++ b/core/modules/system/src/Tests/Module/DependencyTest.php @@ -81,6 +81,24 @@ function testIncompatibleCoreVersionDependency() { } /** + * Tests enabling modules with different core version specifications. + */ + function testCoreVersionDependency() { + $this->drupalGet('admin/modules'); + $checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="modules[Testing][system_incompatible_core_version_test_9x][enable]"]'); + $this->assert(count($checkbox) == 1, 'Checkbox for the 9.x module is disabled.'); + $checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="modules[Testing][system_compatible_core_version_test_80x][enable]"]'); + $this->assert(count($checkbox) == 0, 'Checkbox for the 8.0.x module is not disabled.'); + $checkbox = $this->xpath('//input[@type="checkbox" and @name="modules[Testing][system_compatible_core_version_test_80x][enable]"]'); + $this->assert(count($checkbox) == 1, 'Checkbox for the 8.0.x module is present.'); + // Attempt to install the module. + $edit = array(); + $edit['modules[Testing][system_compatible_core_version_test_80x][enable]'] = 'system_compatible_core_version_test_80x'; + $this->drupalPostForm('admin/modules', $edit, t('Save configuration')); + $this->assertModules(array('system_compatible_core_version_test_80x'), TRUE); + } + + /** * Tests enabling a module that depends on a module which fails hook_requirements(). */ function testEnableRequirementsFailureDependency() { diff --git a/core/modules/system/tests/modules/system_compatible_core_version_test_80x/system_compatible_core_version_test_80x.info.yml b/core/modules/system/tests/modules/system_compatible_core_version_test_80x/system_compatible_core_version_test_80x.info.yml new file mode 100644 index 0000000..eeb9970 --- /dev/null +++ b/core/modules/system/tests/modules/system_compatible_core_version_test_80x/system_compatible_core_version_test_80x.info.yml @@ -0,0 +1,6 @@ +name: 'System compatible core 8.0.x version test' +type: module +description: 'Support module for testing system dependencies.' +package: Testing +version: VERSION +core: 8.0.x diff --git a/core/modules/system/tests/modules/system_incompatible_core_version_test_9x/system_incompatible_core_version_test_9x.info.yml b/core/modules/system/tests/modules/system_incompatible_core_version_test_9x/system_incompatible_core_version_test_9x.info.yml new file mode 100644 index 0000000..4bc6e45 --- /dev/null +++ b/core/modules/system/tests/modules/system_incompatible_core_version_test_9x/system_incompatible_core_version_test_9x.info.yml @@ -0,0 +1,6 @@ +name: 'System incompatible core 9.x version test' +type: module +description: 'Support module for testing system dependencies.' +package: Testing +version: 9.0.0 +core: 9.x diff --git a/core/modules/system/tests/modules/system_test/system_test.module b/core/modules/system/tests/modules/system_test/system_test.module index b44e0a0..86cc9e4 100644 --- a/core/modules/system/tests/modules/system_test/system_test.module +++ b/core/modules/system/tests/modules/system_test/system_test.module @@ -53,6 +53,8 @@ function system_test_system_info_alter(&$info, Extension $file, $type) { 'system_incompatible_core_version_dependencies_test', 'system_incompatible_module_version_test', 'system_incompatible_core_version_test', + 'system_incompatible_core_version_test_9x', + 'system_compatible_core_version_test_80x', ))) { $info['hidden'] = FALSE; } diff --git a/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php index c5e5dcb..9962d7c 100644 --- a/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php +++ b/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php @@ -10,6 +10,7 @@ use Drupal\Core\Extension\Extension; use Drupal\Core\Extension\ModuleHandler; use Drupal\Tests\UnitTestCase; +use Symfony\Component\Validator\Constraints\False; /** * @coversDefaultClass \Drupal\Core\Extension\ModuleHandler @@ -510,4 +511,43 @@ public function testGetModuleDirectories() { $this->moduleHandler->addModule('module', 'place'); $this->assertEquals(array('module' => $this->root . '/place'), $this->moduleHandler->getModuleDirectories()); } + + /** + * @dataProvider providerIsCoreCompatible + * @covers ::isCoreCompatible + */ + public function testIsCoreCompatible($version, $compatible) { + $this->assertEquals($compatible, $this->moduleHandler->isCoreCompatible($version)); + } + + /** + * Provides data for the invalid core test. + * + * @return array + * An array of versions and whether they should be valid. + */ + public function providerIsCoreCompatible() { + $current = \Drupal::VERSION; + list($major, $minor) = explode('.', $current); + + // Calculate older and newer. + $older = $major - 1; + $newer = $major + 1; + $newer_minor = $major . '.' . ($minor + 1); + + // Core version => valid. + $versions = array( + // Invalid. + array("{$older}.x", FALSE), + array("{$older}.24", FALSE), + array("{$newer_minor}.x", FALSE), + array("{$newer}.0.x", FALSE), + // Valid. + array("{$major}.x", TRUE), + array("{$major}.{$minor}.x", TRUE), + ); + + return $versions; + } + }