Issue #3105701 by tedbow, xjm, Gábor Hojtsy, Krzysztof Domański, dww, Wim Leers, jungle: Do not allow core: 9.x in info.yml files

merge-requests/2419/head
Alex Pott 2020-03-13 22:25:24 +00:00
parent 8ed835c0bc
commit 6aee149769
No known key found for this signature in database
GPG Key ID: 31905460D4A69276
18 changed files with 200 additions and 86 deletions

View File

@ -56,7 +56,7 @@ class InfoParserDynamic implements InfoParserInterface {
if (!empty($missing_keys)) {
throw new InfoParserException('Missing required keys (' . implode(', ', $missing_keys) . ') in ' . $filename);
}
if (!isset($parsed_info['core']) && !isset($parsed_info['core_version_requirement'])) {
if (!isset($parsed_info['core_version_requirement'])) {
if (strpos($filename, 'core/') === 0 || strpos($filename, $this->root . '/core/') === 0) {
// Core extensions do not need to specify core compatibility: they are
// by definition compatible so a sensible default is used. Core
@ -70,12 +70,9 @@ class InfoParserDynamic implements InfoParserInterface {
}
else {
// Non-core extensions must specify core compatibility.
throw new InfoParserException("The 'core' or the 'core_version_requirement' key must be present in " . $filename);
throw new InfoParserException("The 'core_version_requirement' key must be present in " . $filename);
}
}
if (isset($parsed_info['core']) && !preg_match("/^\d\.x$/", $parsed_info['core'])) {
throw new InfoParserException("Invalid 'core' value \"{$parsed_info['core']}\" in " . $filename);
}
if (isset($parsed_info['core_version_requirement'])) {
try {
$supports_pre_core_version_requirement_version = static::isConstraintSatisfiedByPreviousVersion($parsed_info['core_version_requirement'], static::FIRST_CORE_VERSION_REQUIREMENT_SUPPORTED_VERSION);
@ -99,6 +96,9 @@ class InfoParserDynamic implements InfoParserInterface {
throw new InfoParserException("The 'core_version_requirement' can not be used to specify compatibility for a specific version before " . static::FIRST_CORE_VERSION_REQUIREMENT_SUPPORTED_VERSION . " in $filename");
}
}
if (isset($parsed_info['core']) && $parsed_info['core'] !== '8.x') {
throw new InfoParserException("'core: {$parsed_info['core']}' is not supported. Use 'core_version_requirement' to specify core compatibility. Only 'core: 8.x' is supported to provide backwards compatibility for Drupal 8 when needed in $filename");
}
// Determine if the extension is compatible with the current version of
// Drupal core.

View File

@ -1,6 +1,5 @@
name: 'Database Statement Monitoring Test'
type: module
description: 'Support module for Database layer tests that need to monitor executed database statements.'
core: 8.x
package: Testing
version: VERSION

View File

@ -1,5 +1,4 @@
name: 'Delay Cache Tags Invalidation Test'
type: module
core: 8.x
package: Testing
version: VERSION

View File

@ -4,4 +4,4 @@ description: 'Support module for testing system dependencies.'
package: Testing
version: VERSION
dependencies:
- drupal:system_incompatible_core_version_test
- drupal:system_core_incompatible_semver_test

View File

@ -1,6 +0,0 @@
name: 'System incompatible core version test'
type: module
description: 'Support module for testing system dependencies.'
package: Testing
version: VERSION
core: 5.x

View File

@ -1,6 +0,0 @@
name: 'System incompatible core 1.x version test'
type: module
description: 'Support module for testing system core incompatibility.'
package: Testing
version: 1.0.0
core: 1.x

View File

@ -70,8 +70,6 @@ function system_test_system_info_alter(&$info, Extension $file, $type) {
'system_incompatible_module_version_dependencies_test',
'system_incompatible_core_version_dependencies_test',
'system_incompatible_module_version_test',
'system_incompatible_core_version_test',
'system_incompatible_core_version_test_1x',
])) {
$info['hidden'] = FALSE;
}

View File

@ -56,29 +56,68 @@ class ModulesListFormWebTest extends BrowserTestBase {
$this->assertText('dblog');
}
/**
* Tests the module form with modules with invalid info.yml files.
*/
public function testModulesListFormWithInvalidInfoFile() {
$broken_info_yml = <<<BROKEN
name: Module With Broken Info file
type: module
BROKEN;
$path = \Drupal::getContainer()->getParameter('site.path') . "/modules/broken";
mkdir($path, 0777, TRUE);
file_put_contents("$path/broken.info.yml", $broken_info_yml);
$file_path = "$path/broken.info.yml";
$broken_infos = [
[
'yml' => <<<BROKEN
name: Module with no core_version_requirement or core
type: module
BROKEN,
'expected_error' => "The 'core_version_requirement' key must be present in $file_path",
],
[
'yml' => <<<BROKEN
name: Module no core_version_requirement and invalid core
type: module
core: 9.x
BROKEN,
// Checking for 'core_version_requirement' is done before checking
// for a valid 'core' value.
'expected_error' => "The 'core_version_requirement' key must be present in $file_path",
],
[
'yml' => <<<BROKEN
name: Module with core_version_requirement and invalid core
type: module
core: 9.x
core_version_requirement: ^8 || ^9
BROKEN,
'expected_error' => "'core: 9.x' is not supported. Use 'core_version_requirement' to specify core compatibility. Only 'core: 8.x' is supported to provide backwards compatibility for Drupal 8 when needed in $file_path",
],
];
$this->drupalLogin(
$this->drupalCreateUser(
['administer modules', 'administer permissions']
)
);
$this->drupalGet('admin/modules');
$this->assertSession()->statusCodeEquals(200);
// Confirm that the error message is shown.
$this->assertSession()
->pageTextContains("The 'core' or the 'core_version_requirement' key must be present in " . $path . '/broken.info.yml');
foreach ($broken_infos as $broken_info) {
file_put_contents($file_path, $broken_info['yml']);
// Check that the module filter text box is available.
$this->assertSession()->elementExists('xpath', '//input[@name="text"]');
$this->drupalGet('admin/modules');
$this->assertSession()->statusCodeEquals(200);
$this->assertSession()
->pageTextContains('Modules could not be listed due to an error: ' . $broken_info['expected_error']);
// Check that the module filter text box is available.
$this->assertSession()->elementExists('xpath', '//input[@name="text"]');
unlink($file_path);
$this->drupalGet('admin/modules');
$this->assertSession()->statusCodeEquals(200);
// Check that the module filter text box is available.
$this->assertSession()->elementExists('xpath', '//input[@name="text"]');
$this->assertSession()->pageTextNotContains('Modules could not be listed due to an error');
}
}
}

View File

@ -91,7 +91,7 @@ class DependencyTest extends ModuleTestBase {
// marked as having an incompatible dependency.
$this->drupalGet('admin/modules');
$this->assertRaw(t('@module (<span class="admin-missing">incompatible with</span> this version of Drupal core)', [
'@module' => 'System incompatible core version test',
'@module' => 'System core incompatible semver test',
]), 'A module that depends on a module with an incompatible core version is marked as such.');
$checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="modules[system_incompatible_core_version_dependencies_test][enable]"]');
$this->assert(count($checkbox) == 1, 'Checkbox for the module is disabled.');
@ -115,7 +115,6 @@ class DependencyTest extends ModuleTestBase {
// Test incompatible 'core_version_requirement'.
$this->drupalGet('admin/modules');
$assert_session->fieldDisabled('modules[system_incompatible_core_version_test_1x][enable]');
$assert_session->fieldDisabled('modules[system_core_incompatible_semver_test][enable]');
// Test compatible 'core_version_requirement' and compatible 'core'.

View File

@ -376,7 +376,6 @@ class ThemeTest extends BrowserTestBase {
// Check for the error text of a theme with the wrong core version
// using 7.x and ^7.
$incompatible_core_message = 'This theme is not compatible with Drupal ' . \Drupal::VERSION . ". Check that the .info.yml file contains a compatible 'core' or 'core_version_requirement' value.";
$this->assertThemeIncompatibleText('Theme test with invalid core version', $incompatible_core_message);
$this->assertThemeIncompatibleText('Theme test with invalid semver core version', $incompatible_core_message);
// Check for the error text of a theme without a content region.
$this->assertText("This theme is missing a 'content' region.");

View File

@ -240,17 +240,6 @@ class UpdateScriptTest extends BrowserTestBase {
$incompatible_module_message = "The following module is installed, but it is incompatible with Drupal " . \Drupal::VERSION . ":";
$incompatible_theme_message = "The following theme is installed, but it is incompatible with Drupal " . \Drupal::VERSION . ":";
return [
'module: core key incompatible' => [
[
'core_version_requirement' => '^8 || ^9',
'type' => 'module',
],
[
'core' => '7.x',
'type' => 'module',
],
$incompatible_module_message,
],
'module: core_version_requirement key incompatible' => [
[
'core_version_requirement' => '^8 || ^9',
@ -262,17 +251,6 @@ class UpdateScriptTest extends BrowserTestBase {
],
$incompatible_module_message,
],
'theme: core key incompatible' => [
[
'core_version_requirement' => '^8 || ^9',
'type' => 'theme',
],
[
'core' => '7.x',
'type' => 'theme',
],
$incompatible_theme_message,
],
'theme: core_version_requirement key incompatible' => [
[
'core_version_requirement' => '^8 || ^9',

View File

@ -1,6 +0,0 @@
name: 'Theme test with invalid core version'
type: theme
base theme: stable
description: 'Test theme which has an invalid core version.'
version: VERSION
core: 7.x

View File

@ -2,8 +2,8 @@ name: 'Theme Legacy Test Stylesheets Remove'
type: theme
description: 'Test theme using legacy stylesheets-remove.'
version: VERSION
core: 8.x
base theme: classy
package: Testing
libraries: { }
stylesheets-remove:
- '@classy/css/components/action-links.css'

View File

@ -2,5 +2,5 @@ name: 'Test legacy theme'
type: theme
description: 'Test theme to test deprecated functionality.'
version: VERSION
core: 8.x
package: Testing
base theme: test_theme

View File

@ -2,5 +2,5 @@ name: 'Theme test subtheme'
type: theme
description: 'Test theme which uses test_basetheme as the base theme.'
version: VERSION
core: 8.x
base theme: classy
package: Testing

View File

@ -34,7 +34,7 @@ class SingleVisibleProfileTest extends InstallerTestBase {
foreach ($profiles as $profile) {
$info = [
'type' => 'profile',
'core' => \Drupal::CORE_COMPATIBILITY,
'core_version_requirement' => '^8 || ^9 || ^10',
'name' => 'Override ' . $profile,
'hidden' => TRUE,
];

View File

@ -103,14 +103,6 @@ class ModuleInstallerTest extends KernelTestBase {
*/
public function providerTestInvalidCoreInstall() {
return [
'no dependencies system_incompatible_core_version_test_1x' => [
'system_incompatible_core_version_test_1x',
FALSE,
],
'install_dependencies system_incompatible_core_version_test_1x' => [
'system_incompatible_core_version_test_1x',
TRUE,
],
'no dependencies system_core_incompatible_semver_test' => [
'system_core_incompatible_semver_test',
FALSE,
@ -129,7 +121,7 @@ class ModuleInstallerTest extends KernelTestBase {
*/
public function testDependencyInvalidCoreInstall() {
$this->expectException(MissingDependencyException::class);
$this->expectExceptionMessage("Unable to install modules: module 'system_incompatible_core_version_dependencies_test'. Its dependency module 'system_incompatible_core_version_test' is incompatible with this version of Drupal core.");
$this->expectExceptionMessage("Unable to install modules: module 'system_incompatible_core_version_dependencies_test'. Its dependency module 'system_core_incompatible_semver_test' is incompatible with this version of Drupal core.");
$this->container->get('module_installer')->install(['system_incompatible_core_version_dependencies_test']);
}

View File

@ -125,7 +125,7 @@ MISSING_CORE_AND_CORE_VERSION_REQUIREMENT;
'missing_core_and_core_version_requirement-duplicate.info.txt' => $missing_core_and_core_version_requirement,
],
]);
$exception_message = "The 'core' or the 'core_version_requirement' key must be present in vfs://modules/fixtures/missing_core_and_core_version_requirement";
$exception_message = "The 'core_version_requirement' key must be present in vfs://modules/fixtures/missing_core_and_core_version_requirement";
// Set the expected exception for the 2nd call to parse().
$this->expectException('\Drupal\Core\Extension\InfoParserException');
$this->expectExceptionMessage("$exception_message-duplicate.info.txt");
@ -237,12 +237,15 @@ BOTH_CORE_CORE_VERSION_REQUIREMENT_88;
* Tests a invalid 'core' key.
*
* @covers ::parse
*
* @dataProvider providerInvalidCore
*/
public function testInvalidCore() {
public function testInvalidCore($core, $filename) {
$invalid_core = <<<INVALID_CORE
# info.yml for testing invalid core key.
package: Core
core: ^8
core: $core
core_version_requirement: ^8 || ^9
version: VERSION
type: module
name: Llama or Alpaca
@ -255,25 +258,151 @@ INVALID_CORE;
vfsStream::setup('modules');
vfsStream::create([
'fixtures' => [
'invalid_core.info.txt' => $invalid_core,
'invalid_core-duplicate.info.txt' => $invalid_core,
"invalid_core-$filename.info.txt" => $invalid_core,
"invalid_core-$filename-duplicate.info.txt" => $invalid_core,
],
]);
$exception_message = "Invalid 'core' value \"^8\" in vfs://modules/fixtures/invalid_core";
$exception_message = "'core: {$core}' is not supported. Use 'core_version_requirement' to specify core compatibility. Only 'core: 8.x' is supported to provide backwards compatibility for Drupal 8 when needed in vfs://modules/fixtures/invalid_core-$filename";
// Set the expected exception for the 2nd call to parse().
$this->expectException('\Drupal\Core\Extension\InfoParserException');
$this->expectExceptionMessage("$exception_message-duplicate.info.txt");
try {
$this->infoParser->parse(vfsStream::url('modules/fixtures/invalid_core.info.txt'));
$this->infoParser->parse(vfsStream::url("modules/fixtures/invalid_core-$filename.info.txt"));
}
catch (InfoParserException $exception) {
$this->assertSame("$exception_message.info.txt", $exception->getMessage());
$this->infoParser->parse(vfsStream::url('modules/fixtures/invalid_core-duplicate.info.txt'));
$this->infoParser->parse(vfsStream::url("modules/fixtures/invalid_core-$filename-duplicate.info.txt"));
}
}
public function providerInvalidCore() {
return [
'^8' => [
'^8',
'caret8',
],
'^9' => [
'^9',
'caret9',
],
'7.x' => [
'7.x',
'7.x',
],
'9.x' => [
'9.x',
'9.x',
],
'10.x' => [
'10.x',
'10.x',
],
];
}
/**
* Tests a 'core: 8.x' with different values for 'core_version_requirement'.
*
* @covers ::parse
*
* @dataProvider providerCore8x
*/
public function testCore8x($core_version_requirement, $filename) {
$core_8x = <<<CORE_8X
package: Tests
core: 8.x
core_version_requirement: '$core_version_requirement'
version: VERSION
type: module
name: Yet another test module
description: Sorry, I am running out of witty descriptions
CORE_8X;
vfsStream::setup('modules');
vfsStream::create([
'fixtures' => [
"core_8x-$filename.info.txt" => $core_8x,
"core_8x-$filename-duplicate.info.txt" => $core_8x,
],
]);
$parsed = $this->infoParser->parse(vfsStream::url("modules/fixtures/core_8x-$filename.info.txt"));
$this->assertSame($core_version_requirement, $parsed['core_version_requirement']);
$this->infoParser->parse(vfsStream::url("modules/fixtures/core_8x-$filename-duplicate.info.txt"));
$this->assertSame($core_version_requirement, $parsed['core_version_requirement']);
}
/**
* Dataprovider for testCore8x().
*/
public function providerCore8x() {
return [
'^8 || ^9' => [
'^8 || ^9',
'all-8-9',
],
'*' => [
'*',
'asterisk',
],
'>=8' => [
">=8",
'gte8',
],
];
}
/**
* Tests setting the 'core' key without the 'core_version_requirement' key.
*
* @covers ::parse
*
* @dataProvider providerCoreWithoutCoreVersionRequirement
*/
public function testCoreWithoutCoreVersionRequirement($core) {
$core_without_core_version_requirement = <<<CORE_WITHOUT_CORE_VERSION_REQUIREMENT
package: Dogs
core: $core
version: VERSION
type: module
name: Gracie Daily Picture
description: Shows a random picture of Gracie the Dog everyday.
CORE_WITHOUT_CORE_VERSION_REQUIREMENT;
vfsStream::setup('modules');
vfsStream::create([
'fixtures' => [
"core_without_core_version_requirement-$core.info.txt" => $core_without_core_version_requirement,
"core_without_core_version_requirement-$core-duplicate.info.txt" => $core_without_core_version_requirement,
],
]);
$exception_message = "The 'core_version_requirement' key must be present in vfs://modules/fixtures/core_without_core_version_requirement-$core";
// Set the expected exception for the 2nd call to parse().
$this->expectException('\Drupal\Core\Extension\InfoParserException');
$this->expectExceptionMessage("$exception_message-duplicate.info.txt");
try {
$this->infoParser->parse(vfsStream::url("modules/fixtures/core_without_core_version_requirement-$core.info.txt"));
}
catch (InfoParserException $exception) {
$this->assertSame("$exception_message.info.txt", $exception->getMessage());
$this->infoParser->parse(vfsStream::url("modules/fixtures/core_without_core_version_requirement-$core-duplicate.info.txt"));
}
}
/**
* DataProvider for testCoreWithoutCoreVersionRequirement().
*/
public function providerCoreWithoutCoreVersionRequirement() {
return [
'7.x' => ['7.x'],
'8.x' => ['8.x'],
'9.x' => ['9.x'],
'10.x' => ['10.x'],
];
}
/**
* Tests a invalid 'core_version_requirement'.
*