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
parent
8ed835c0bc
commit
6aee149769
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
name: 'Delay Cache Tags Invalidation Test'
|
||||
type: module
|
||||
core: 8.x
|
||||
package: Testing
|
||||
version: VERSION
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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'.
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
];
|
||||
|
|
|
@ -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']);
|
||||
}
|
||||
|
||||
|
|
|
@ -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'.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue