Commit 1b4c4238 authored by catch's avatar catch

Issue #3123537 by tedbow, dww, DamienMcKenna, xjm, Berdir, tim.plunkett,...

Issue #3123537 by tedbow, dww, DamienMcKenna, xjm, Berdir, tim.plunkett, pingwin4eg: /admin/reports/status should not WSOD if it finds an extension missing core_version_requirement in its info.yml file
parent 15c4512b
......@@ -68,7 +68,7 @@ public function parse($filename) {
// easier for contrib to use test modules.
$parsed_info['core_version_requirement'] = \Drupal::VERSION;
}
else {
elseif (!isset($parsed_info['core'])) {
// Non-core extensions must specify core compatibility.
throw new InfoParserException("The 'core_version_requirement' key must be present in " . $filename);
}
......
......@@ -209,11 +209,19 @@ public function themesPage() {
$theme_groups = ['installed' => [], 'uninstalled' => []];
$admin_theme = $config->get('admin');
$admin_theme_options = [];
$incompatible_installed = FALSE;
foreach ($themes as &$theme) {
if (!empty($theme->info['hidden'])) {
continue;
}
if (!$incompatible_installed && $theme->info['core_incompatible'] && $theme->status) {
$incompatible_installed = TRUE;
$this->messenger()->addWarning($this->t(
'There are errors with some installed themes. Visit the <a href=":link">status report page</a> for more information.',
[':link' => Url::fromRoute('system.status')->toString()]
));
}
$theme->is_default = ($theme->getName() == $theme_default);
$theme->is_admin = ($theme->getName() == $admin_theme || ($theme->is_default && empty($admin_theme)));
$theme->is_experimental = isset($theme->info['experimental']) && $theme->info['experimental'];
......
......@@ -171,12 +171,20 @@ public function buildForm(array $form, FormStateInterface $form_state) {
// Iterate over each of the modules.
$form['modules']['#tree'] = TRUE;
$incompatible_installed = FALSE;
foreach ($modules as $filename => $module) {
if (empty($module->info['hidden'])) {
$package = $module->info['package'];
$form['modules'][$package][$filename] = $this->buildRow($modules, $module, $distribution);
$form['modules'][$package][$filename]['#parents'] = ['modules', $filename];
}
if (!$incompatible_installed && $module->status && $module->info['core_incompatible']) {
$incompatible_installed = TRUE;
$this->messenger()->addWarning($this->t(
'There are errors with some installed modules. Visit the <a href=":link">status report page</a> for more information.',
[':link' => Url::fromRoute('system.status')->toString()]
));
}
}
// Add a wrapper around every package.
......
......@@ -2,6 +2,7 @@
namespace Drupal\Tests\system\Functional\Form;
use Drupal\Core\Serialization\Yaml;
use Drupal\Tests\BrowserTestBase;
/**
......@@ -73,9 +74,7 @@ public function testModulesListFormWithInvalidInfoFile() {
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",
'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",
],
[
'yml' => <<<BROKEN
......@@ -123,4 +122,56 @@ public function testRequiredByThemeMessage() {
$this->assertSession()->pageTextContains('Test Theme Depending on Modules (Theme) (Disabled)');
}
/**
* Tests that incompatible modules message is shown.
*/
public function testInstalledIncompatibleModule() {
$incompatible_modules_message = 'There are errors with some installed modules. Visit the status report page for more information.';
$path = \Drupal::getContainer()->getParameter('site.path') . "/modules/changing_module";
mkdir($path, 0777, TRUE);
$file_path = "$path/changing_module.info.yml";
$info = [
'name' => 'Module that changes',
'type' => 'module',
];
$compatible_info = $info + ['core_version_requirement' => '*'];
file_put_contents($file_path, Yaml::encode($compatible_info));
$edit = ['modules[changing_module][enable]' => 'changing_module'];
$this->drupalGet('admin/modules');
$this->drupalPostForm('admin/modules', $edit, t('Install'));
$this->assertText('Module Module that changes has been enabled.');
$incompatible_updates = [
[
'core_version_requirement' => '^1',
],
[
'core' => '8.x',
],
];
foreach ($incompatible_updates as $incompatible_update) {
$incompatible_info = $info + $incompatible_update;
file_put_contents($file_path, Yaml::encode($incompatible_info));
$this->drupalGet('admin/modules');
$this->assertText($incompatible_modules_message);
file_put_contents($file_path, Yaml::encode($compatible_info));
$this->drupalGet('admin/modules');
$this->assertNoText($incompatible_modules_message);
}
// Uninstall the module and ensure that incompatible modules message is not
// displayed for modules that are not installed.
$edit = ['uninstall[changing_module]' => 'changing_module'];
$this->drupalPostForm('admin/modules/uninstall', $edit, t('Uninstall'));
$this->drupalPostForm(NULL, NULL, t('Uninstall'));
$this->assertText('The selected modules have been uninstalled.');
foreach ($incompatible_updates as $incompatible_update) {
$incompatible_info = $info + $incompatible_update;
file_put_contents($file_path, Yaml::encode($incompatible_info));
$this->drupalGet('admin/modules');
$this->assertNoText($incompatible_modules_message);
}
}
}
......@@ -2,6 +2,7 @@
namespace Drupal\Tests\system\Functional\Theme;
use Drupal\Core\Serialization\Yaml;
use Drupal\Tests\BrowserTestBase;
/**
......@@ -318,4 +319,59 @@ public function testInstallModuleWithIncompatibleDependencies() {
$this->assertStringContainsString('This theme requires the listed modules to operate correctly.', $theme_container->getText());
}
/**
* Tests that incompatible themes message is shown.
*/
public function testInstalledIncompatibleTheme() {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$incompatitable_themes_message = 'There are errors with some installed themes. Visit the status report page for more information.';
$path = \Drupal::getContainer()->getParameter('site.path') . "/themes/changing_theme";
mkdir($path, 0777, TRUE);
$file_path = "$path/changing_theme.info.yml";
$theme_name = 'Theme that changes';
$info = [
'name' => $theme_name,
'type' => 'theme',
'base theme' => FALSE,
];
$compatible_info = $info + ['core_version_requirement' => '*'];
file_put_contents($file_path, Yaml::encode($compatible_info));
$this->drupalGet('admin/appearance');
$this->assertNoText($incompatitable_themes_message);
$page->clickLink("Install $theme_name theme");
$assert_session->addressEquals('admin/appearance');
$assert_session->pageTextContains("The $theme_name theme has been installed");
$incompatible_updates = [
[
'core_version_requirement' => '^1',
],
[
'core' => '8.x',
],
];
foreach ($incompatible_updates as $incompatible_update) {
$incompatible_info = $info + $incompatible_update;
file_put_contents($file_path, Yaml::encode($incompatible_info));
$this->drupalGet('admin/appearance');
$this->assertText($incompatitable_themes_message);
file_put_contents($file_path, Yaml::encode($compatible_info));
$this->drupalGet('admin/appearance');
$this->assertNoText($incompatitable_themes_message);
}
// Uninstall the theme and ensure that incompatible themes message is not
// displayed for themes that are not installed.
$this->uninstallTheme($theme_name);
foreach ($incompatible_updates as $incompatible_update) {
$incompatible_info = $info + $incompatible_update;
file_put_contents($file_path, Yaml::encode($incompatible_info));
$this->drupalGet('admin/appearance');
$this->assertNoText($incompatitable_themes_message);
}
}
}
......@@ -323,6 +323,28 @@ public function providerExtensionCompatibilityChange() {
],
'The following theme is installed, but it is incompatible with PHP ' . phpversion() . ":",
],
'module: core_version_requirement key missing' => [
[
'core_version_requirement' => '^8 || ^9',
'type' => 'module',
],
[
'core' => '8.x',
'type' => 'module',
],
$incompatible_module_message,
],
'theme: core_version_requirement key missing' => [
[
'core_version_requirement' => '^8 || ^9',
'type' => 'theme',
],
[
'core' => '8.x',
'type' => 'theme',
],
$incompatible_theme_message,
],
];
}
......
......@@ -377,7 +377,7 @@ public function testCoreWithoutCoreVersionRequirement($core) {
"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";
$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/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");
......@@ -397,7 +397,6 @@ public function testCoreWithoutCoreVersionRequirement($core) {
public function providerCoreWithoutCoreVersionRequirement() {
return [
'7.x' => ['7.x'],
'8.x' => ['8.x'],
'9.x' => ['9.x'],
'10.x' => ['10.x'],
];
......@@ -663,4 +662,33 @@ public function testUnparsableCoreVersionRequirement() {
$this->infoParser->parse(vfsStream::url('modules/fixtures/unparsable_core_version_requirement.info.txt'));
}
/**
* Tests an info file with 'core: 8.x' but without 'core_version_requirement'.
*
* @covers ::parse
*/
public function testCore8xNoCoreVersionRequirement() {
$info = <<<INFO
package: Core
core: 8.x
version: VERSION
type: module
name: Module for That
dependencies:
- field
INFO;
vfsStream::setup('modules');
foreach (['1', '2'] as $file_delta) {
$filename = "core_version_requirement-$file_delta.info.txt";
vfsStream::create([
'fixtures' => [
$filename => $info,
],
]);
$info_values = $this->infoParser->parse(vfsStream::url("modules/fixtures/$filename"));
$this->assertSame(TRUE, $info_values['core_incompatible'], "Expected 'core_incompatible's for file: $filename");
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment