Issue #3102724 by dww, tedbow, bnjmnm, webchick, ckrina, Gábor Hojtsy, xjm, benjifisher, AaronMcHale, lauriii, shaal, andrewmacpherson, rainbreaw, worldlinemine: Improve usability of core compatibility ranges on available updates report

merge-requests/2419/head
Gábor Hojtsy 2020-02-27 11:27:01 +01:00
parent 5d4c083edf
commit f8d4b113f5
13 changed files with 290 additions and 48 deletions

View File

@ -7,12 +7,19 @@ use Composer\Semver\VersionParser;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
/** /**
* Utility class to set core compatibility messages for module updates. * Utility class to set core compatibility messages for project releases.
*/ */
class ProjectCoreCompatibility { class ProjectCoreCompatibility {
use StringTranslationTrait; use StringTranslationTrait;
/**
* The currently installed version of Drupal core.
*
* @var string
*/
protected $existingCoreVersion;
/** /**
* Cache of core versions that are available for updates. * Cache of core versions that are available for updates.
* *
@ -50,30 +57,29 @@ class ProjectCoreCompatibility {
*/ */
public function __construct(array $core_data, array $core_releases) { public function __construct(array $core_data, array $core_releases) {
if (isset($core_data['existing_version'])) { if (isset($core_data['existing_version'])) {
$this->possibleCoreUpdateVersions = $this->getPossibleCoreUpdateVersions($core_data['existing_version'], $core_releases); $this->existingCoreVersion = $core_data['existing_version'];
$this->possibleCoreUpdateVersions = $this->getPossibleCoreUpdateVersions($core_releases);
} }
} }
/** /**
* Gets the core versions that should be considered for compatibility ranges. * Gets the core versions that should be considered for compatibility ranges.
* *
* @param string $existing_version
* The existing (currently installed) version of Drupal core.
* @param array $core_releases * @param array $core_releases
* The Drupal core available releases. * The Drupal core available releases.
* *
* @return string[] * @return string[]
* The core version numbers that are possible to update the site to. * The core version numbers that are possible to update the site to.
*/ */
protected function getPossibleCoreUpdateVersions($existing_version, array $core_releases) { protected function getPossibleCoreUpdateVersions(array $core_releases) {
if (!isset($core_releases[$existing_version])) { if (!isset($core_releases[$this->existingCoreVersion])) {
// If we can't determine the existing version of core then we can't // If we can't determine the existing version of core then we can't
// calculate the core compatibility of a given release based on core // calculate the core compatibility of a given release based on core
// versions after the existing version. // versions after the existing version.
return []; return [];
} }
$core_release_versions = array_keys($core_releases); $core_release_versions = array_keys($core_releases);
$possible_core_update_versions = Semver::satisfiedBy($core_release_versions, '>= ' . $existing_version); $possible_core_update_versions = Semver::satisfiedBy($core_release_versions, '>= ' . $this->existingCoreVersion);
$possible_core_update_versions = Semver::sort($possible_core_update_versions); $possible_core_update_versions = Semver::sort($possible_core_update_versions);
$possible_core_update_versions = array_filter($possible_core_update_versions, function ($version) { $possible_core_update_versions = array_filter($possible_core_update_versions, function ($version) {
return VersionParser::parseStability($version) === 'stable'; return VersionParser::parseStability($version) === 'stable';
@ -131,11 +137,26 @@ class ProjectCoreCompatibility {
} }
foreach ($releases_to_set as &$release) { foreach ($releases_to_set as &$release) {
if (!empty($release['core_compatibility'])) { if (!empty($release['core_compatibility'])) {
$release['core_compatible'] = $this->isCoreCompatible($release['core_compatibility']);
$release['core_compatibility_message'] = $this->createMessageFromCoreCompatibility($release['core_compatibility']); $release['core_compatibility_message'] = $this->createMessageFromCoreCompatibility($release['core_compatibility']);
} }
} }
} }
/**
* Determines if a release is compatible with the currently installed core.
*
* @param string $core_compatibility_constraint
* A semantic version constraint.
*
* @return bool
* TRUE if the given constraint is satisfied by the currently installed
* version of Drupal core, otherwise FALSE.
*/
protected function isCoreCompatible($core_compatibility_constraint) {
return Semver::satisfies($this->existingCoreVersion, $core_compatibility_constraint);
}
/** /**
* Creates core a compatibility message from a semantic version constraint. * Creates core a compatibility message from a semantic version constraint.
* *
@ -157,7 +178,7 @@ class ProjectCoreCompatibility {
$range_messages[] = $core_compatibility_range[0]; $range_messages[] = $core_compatibility_range[0];
} }
} }
$this->compatibilityMessages[$core_compatibility_constraint] = $this->t('This module is compatible with Drupal core:') . ' ' . implode(', ', $range_messages); $this->compatibilityMessages[$core_compatibility_constraint] = $this->t('Requires Drupal core:') . ' ' . implode(', ', $range_messages);
} }
return $this->compatibilityMessages[$core_compatibility_constraint]; return $this->compatibilityMessages[$core_compatibility_constraint];
} }

View File

@ -6,11 +6,21 @@
* Available variables: * Available variables:
* - attributes: HTML attributes suitable for a container element. * - attributes: HTML attributes suitable for a container element.
* - title: The title of the project. * - title: The title of the project.
* - core_compatibility_details: Render array of core compatibility details.
* - version: A list of data about the latest released version, containing: * - version: A list of data about the latest released version, containing:
* - version: The version number. * - version: The version number.
* - date: The date of the release. * - date: The date of the release.
* - download_link: The URL for the downloadable file. * - download_link: The URL for the downloadable file.
* - release_link: The URL for the release notes. * - release_link: The URL for the release notes.
* - core_compatible: A flag indicating whether the project is compatible
* with the currently installed version of Drupal core. This flag is not
* set for the Drupal core project itself.
* - core_compatibility_message: A message indicating the versions of Drupal
* core with which this project is compatible. This message is also
* contained within the 'core_compatibility_details' variable documented
* above. This message is not set for the Drupal core project itself.
*
* @see template_preprocess_update_version()
* *
* @ingroup themeable * @ingroup themeable
*/ */
@ -21,18 +31,22 @@
<div class="project-update__version-details layout-column layout-column--quarter"> <div class="project-update__version-details layout-column layout-column--quarter">
<a href="{{ version.release_link }}">{{ version.version }}</a> <a href="{{ version.release_link }}">{{ version.version }}</a>
<span class="project-update__version-date">({{ version.date|date('Y-M-d') }})</span> <span class="project-update__version-date">({{ version.date|date('Y-M-d') }})</span>
{% if version.core_compatibility_message %}
<span class="project-update__core-compatibility-message">{{ version.core_compatibility_message }}</span>
{% endif %}
</div> </div>
<div class="layout-column layout-column--half"> <div class="layout-column layout-column--half">
<ul class="project-update__version-links"> <ul class="project-update__version-links">
<li class="project-update__download-link"> {% if version.core_compatible is not defined or version.core_compatible %}
<a href="{{ version.download_link }}">{{ 'Download'|t }}</a> <li class="project-update__download-link">
</li> <a href="{{ version.download_link }}">{{ 'Download'|t }}</a>
</li>
{% endif %}
<li class="project-update__release-notes-link"> <li class="project-update__release-notes-link">
<a href="{{ version.release_link }}">{{ 'Release notes'|t }}</a> <a href="{{ version.release_link }}">{{ 'Release notes'|t }}</a>
</li> </li>
{% if core_compatibility_details %}
<li class="project-update__compatibility-details">
{{ core_compatibility_details }}
</li>
{% endif %}
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<project xmlns:dc="http://purl.org/dc/elements/1.1/">
<title>AAA Update test</title>
<short_name>aaa_update_test</short_name>
<dc:creator>Drupal</dc:creator>
<supported_branches>8.x-1.,8.x-2.</supported_branches>
<project_status>published</project_status>
<link>http://example.com/project/aaa_update_test</link>
<terms>
<term><name>Projects</name><value>Modules</value></term>
</terms>
<releases>
<release>
<name>aaa_update_test 8.x-2.2</name>
<version>8.x-2.2</version>
<tag>8.x-2.2</tag>
<core_compatibility>^8.1.1</core_compatibility>
<status>published</status>
<release_link>http://example.com/aaa_update_test-8-x-2-2-release</release_link>
<download_link>http://example.com/aaa_update_test-8-x-2-2.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
<term><name>Release type</name><value>Security update</value></term>
</terms>
</release>
<release>
<name>aaa_update_test 8.x-1.2</name>
<version>8.x-1.2</version>
<tag>8.x-2.2</tag>
<core_compatibility>^8.1.0</core_compatibility>
<status>published</status>
<release_link>http://example.com/aaa_update_test-8-x-1-2-release</release_link>
<download_link>http://example.com/aaa_update_test-8-x-1-2.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
<term><name>Release type</name><value>Security update</value></term>
</terms>
</release>
<release>
<name>aaa_update_test 8.x-1.0</name>
<version>8.x-1.0</version>
<tag>8.x-2.2</tag>
<status>published</status>
<release_link>http://example.com/aaa_update_test-8-x-1-0-release</release_link>
<download_link>http://example.com/aaa_update_test-8-x-1-0.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
<term><name>Release type</name><value>Insecure</value></term>
</terms>
</release>
</releases>
</project>

View File

@ -30,7 +30,6 @@
<name>aaa_update_test 8.x-3.0-beta1</name> <name>aaa_update_test 8.x-3.0-beta1</name>
<version>8.x-3.0-beta1</version> <version>8.x-3.0-beta1</version>
<tag>8.x-3.0-beta1</tag> <tag>8.x-3.0-beta1</tag>
<core_compatibility>^8.1.1</core_compatibility>
<status>published</status> <status>published</status>
<release_link>http://example.com/aaa_update_test-8-x-3-0-beta1</release_link> <release_link>http://example.com/aaa_update_test-8-x-3-0-beta1</release_link>
<download_link>http://example.com/aaa_update_test--8-x-3-0-beta1.tar.gz</download_link> <download_link>http://example.com/aaa_update_test--8-x-3-0-beta1.tar.gz</download_link>
@ -48,7 +47,6 @@
<name>aaa_update_test 8.x-2.2</name> <name>aaa_update_test 8.x-2.2</name>
<version>8.x-2.2</version> <version>8.x-2.2</version>
<tag>DRUPAL-8--2-2</tag> <tag>DRUPAL-8--2-2</tag>
<core_compatibility>^8.1.1</core_compatibility>
<status>published</status> <status>published</status>
<release_link>http://example.com/aaa_update_test-8-x-2-2-release</release_link> <release_link>http://example.com/aaa_update_test-8-x-2-2-release</release_link>
<download_link>http://example.com/aaa_update_test-8-x-2-2.tar.gz</download_link> <download_link>http://example.com/aaa_update_test-8-x-2-2.tar.gz</download_link>
@ -92,7 +90,6 @@
<name>aaa_update_test 8.x-1.2</name> <name>aaa_update_test 8.x-1.2</name>
<version>8.x-1.2</version> <version>8.x-1.2</version>
<tag>DRUPAL-8--1-2</tag> <tag>DRUPAL-8--1-2</tag>
<core_compatibility>^8.1.0</core_compatibility>
<status>published</status> <status>published</status>
<release_link>http://example.com/aaa_update_test-8-x-1-2-release</release_link> <release_link>http://example.com/aaa_update_test-8-x-1-2-release</release_link>
<download_link>http://example.com/aaa_update_test-8-x-1-2.tar.gz</download_link> <download_link>http://example.com/aaa_update_test-8-x-1-2.tar.gz</download_link>

View File

@ -575,9 +575,9 @@ class UpdateContribTest extends UpdateTestBase {
// Confirm that messages are displayed for security and 'Also available' // Confirm that messages are displayed for security and 'Also available'
// updates. // updates.
$this->refreshUpdateStatus(['drupal' => '1.1', 'aaa_update_test' => 'sec.8.x-1.2_8.x-2.2']); $this->refreshUpdateStatus(['drupal' => '1.1', 'aaa_update_test' => 'core_compatibility.8.x-1.2_8.x-2.2']);
$this->assertCoreCompatibilityMessage('8.x-1.2', '8.1.0 to 8.1.1', 'Security update:'); $this->assertCoreCompatibilityMessage('8.x-1.2', '8.1.0 to 8.1.1', 'Security update:', FALSE);
$this->assertCoreCompatibilityMessage('8.x-2.2', '8.1.1', 'Also available:'); $this->assertCoreCompatibilityMessage('8.x-2.2', '8.1.1', 'Also available:', FALSE);
} }
/** /**
@ -788,17 +788,39 @@ class UpdateContribTest extends UpdateTestBase {
* *
* @param string $version * @param string $version
* The version of the update. * The version of the update.
* @param string $expected_compatibility_range * @param string $expected_range
* The expected core compatibility range. * The expected core compatibility range.
* @param string $expected_release_title * @param string $expected_release_title
* The expected release title. * The expected release title.
* @param bool $is_compatible
* If the update is compatible with the installed version of Drupal.
*/ */
protected function assertCoreCompatibilityMessage($version, $expected_compatibility_range, $expected_release_title) { protected function assertCoreCompatibilityMessage($version, $expected_range, $expected_release_title, $is_compatible = TRUE) {
$link = $this->getSession()->getPage()->findLink($version); $update_element = $this->findUpdateElementByLabel($expected_release_title);
$update_info_element = $link->getParent(); $this->assertTrue($update_element->hasLink($version));
$this->assertContains("This module is compatible with Drupal core: $expected_compatibility_range", $update_info_element->getText()); $compatibility_details = $update_element->find('css', '.project-update__compatibility-details details');
$update_title_element = $update_info_element->getParent()->find('css', '.project-update__version-title'); $this->assertContains("Requires Drupal core: $expected_range", $compatibility_details->getText());
$this->assertSame($expected_release_title, $update_title_element->getText()); $details_summary_element = $compatibility_details->find('css', 'summary');
if ($is_compatible) {
$download_version = str_replace('.', '-', $version);
// If an update is compatible with the installed version of Drupal core,
// it should have a download link and the details element should be closed
// by default.
$this->assertFalse($compatibility_details->hasAttribute('open'));
$this->assertSame('Compatible', $details_summary_element->getText());
$this->assertEquals(
$update_element->findLink('Download')->getAttribute('href'),
"http://example.com/{$this->updateProject}-$download_version.tar.gz"
);
}
else {
// If an update is not compatible with the installed version of Drupal
// core, it should not have a download link and the details element should
// be open by default.
$this->assertTrue($compatibility_details->hasAttribute('open'));
$this->assertSame('Not compatible', $details_summary_element->getText());
$this->assertFalse($update_element->hasLink('Download'));
}
} }
} }

View File

@ -195,7 +195,7 @@ abstract class UpdateTestBase extends BrowserTestBase {
*/ */
protected function assertVersionUpdateLinks($label, $version, $download_version = NULL) { protected function assertVersionUpdateLinks($label, $version, $download_version = NULL) {
$download_version = $download_version ?? $version; $download_version = $download_version ?? $version;
$update_element = $this->getSession()->getPage()->find('css', $this->updateTableLocator . " .project-update__version:contains(\"$label\")"); $update_element = $this->findUpdateElementByLabel($label);
// In the release notes URL the periods are replaced with dashes. // In the release notes URL the periods are replaced with dashes.
$url_version = str_replace('.', '-', $version); $url_version = str_replace('.', '-', $version);
@ -274,4 +274,21 @@ abstract class UpdateTestBase extends BrowserTestBase {
->elementContains('css', $this->updateTableLocator, $text); ->elementContains('css', $this->updateTableLocator, $text);
} }
/**
* Finds an update page element by label.
*
* @param string $label
* The label for the update, for example "Recommended version:" or
* "Latest version:".
*
* @return \Behat\Mink\Element\NodeElement
* The update element.
*/
protected function findUpdateElementByLabel($label) {
$update_elements = $this->getSession()->getPage()
->findAll('css', $this->updateTableLocator . " .project-update__version:contains(\"$label\")");
$this->assertCount(1, $update_elements);
return $update_elements[0];
}
} }

View File

@ -72,22 +72,26 @@ class ProjectCoreCompatibilityTest extends UnitTestCase {
'expected_releases' => [ 'expected_releases' => [
'1.0.1' => [ '1.0.1' => [
'core_compatibility' => '8.x', 'core_compatibility' => '8.x',
'core_compatibility_message' => 'This module is compatible with Drupal core: 8.8.0 to 8.9.2', 'core_compatible' => TRUE,
'core_compatibility_message' => 'Requires Drupal core: 8.8.0 to 8.9.2',
], ],
'1.2.3' => [ '1.2.3' => [
'core_compatibility' => '^8.9 || ^9', 'core_compatibility' => '^8.9 || ^9',
'core_compatibility_message' => 'This module is compatible with Drupal core: 8.9.0 to 8.9.2', 'core_compatible' => FALSE,
'core_compatibility_message' => 'Requires Drupal core: 8.9.0 to 8.9.2',
], ],
'1.2.4' => [ '1.2.4' => [
'core_compatibility' => '^8.9.2 || ^9', 'core_compatibility' => '^8.9.2 || ^9',
'core_compatibility_message' => 'This module is compatible with Drupal core: 8.9.2', 'core_compatible' => FALSE,
'core_compatibility_message' => 'Requires Drupal core: 8.9.2',
], ],
'1.2.6' => [], '1.2.6' => [],
], ],
'expected_security_updates' => [ 'expected_security_updates' => [
'1.2.5' => [ '1.2.5' => [
'core_compatibility' => '8.9.0 || 8.9.2 || ^9.0.1', 'core_compatibility' => '8.9.0 || 8.9.2 || ^9.0.1',
'core_compatibility_message' => 'This module is compatible with Drupal core: 8.9.0, 8.9.2', 'core_compatible' => FALSE,
'core_compatibility_message' => 'Requires Drupal core: 8.9.0, 8.9.2',
], ],
], ],
]; ];
@ -110,22 +114,26 @@ class ProjectCoreCompatibilityTest extends UnitTestCase {
$test_cases['with 9 full releases']['expected_releases'] = [ $test_cases['with 9 full releases']['expected_releases'] = [
'1.0.1' => [ '1.0.1' => [
'core_compatibility' => '8.x', 'core_compatibility' => '8.x',
'core_compatibility_message' => 'This module is compatible with Drupal core: 8.8.0 to 8.9.2', 'core_compatible' => TRUE,
'core_compatibility_message' => 'Requires Drupal core: 8.8.0 to 8.9.2',
], ],
'1.2.3' => [ '1.2.3' => [
'core_compatibility' => '^8.9 || ^9', 'core_compatibility' => '^8.9 || ^9',
'core_compatibility_message' => 'This module is compatible with Drupal core: 8.9.0 to 9.0.2', 'core_compatible' => FALSE,
'core_compatibility_message' => 'Requires Drupal core: 8.9.0 to 9.0.2',
], ],
'1.2.4' => [ '1.2.4' => [
'core_compatibility' => '^8.9.2 || ^9', 'core_compatibility' => '^8.9.2 || ^9',
'core_compatibility_message' => 'This module is compatible with Drupal core: 8.9.2 to 9.0.2', 'core_compatible' => FALSE,
'core_compatibility_message' => 'Requires Drupal core: 8.9.2 to 9.0.2',
], ],
'1.2.6' => [], '1.2.6' => [],
]; ];
$test_cases['with 9 full releases']['expected_security_updates'] = [ $test_cases['with 9 full releases']['expected_security_updates'] = [
'1.2.5' => [ '1.2.5' => [
'core_compatibility' => '8.9.0 || 8.9.2 || ^9.0.1', 'core_compatibility' => '8.9.0 || 8.9.2 || ^9.0.1',
'core_compatibility_message' => 'This module is compatible with Drupal core: 8.9.0, 8.9.2, 9.0.1 to 9.0.2', 'core_compatible' => FALSE,
'core_compatibility_message' => 'Requires Drupal core: 8.9.0, 8.9.2, 9.0.1 to 9.0.2',
], ],
]; ];
return $test_cases; return $test_cases;

View File

@ -101,6 +101,36 @@ function template_preprocess_update_report(&$variables) {
} }
} }
/**
* Prepares variables for update version templates.
*
* Default template: update-version.html.twig.
*
* @param array $variables
* An associative array containing:
* - version: An array of information about the release version.
*/
function template_preprocess_update_version(array &$variables) {
$version = $variables['version'];
if (empty($version['core_compatibility_message'])) {
return;
}
$core_compatible = !empty($version['core_compatible']);
$variables['core_compatibility_details'] = [
'#type' => 'details',
'#title' => $core_compatible ? t('Compatible') : t('Not compatible'),
'#open' => !$core_compatible,
'message' => [
'#markup' => $version['core_compatibility_message'],
],
'#attributes' => [
'class' => [
$core_compatible ? 'compatible' : 'not-compatible',
],
],
];
}
/** /**
* Prepares variables for update project status templates. * Prepares variables for update project status templates.
* *

View File

@ -6,11 +6,21 @@
* Available variables: * Available variables:
* - attributes: HTML attributes suitable for a container element. * - attributes: HTML attributes suitable for a container element.
* - title: The title of the project. * - title: The title of the project.
* - core_compatibility_details: Render array of core compatibility details.
* - version: A list of data about the latest released version, containing: * - version: A list of data about the latest released version, containing:
* - version: The version number. * - version: The version number.
* - date: The date of the release. * - date: The date of the release.
* - download_link: The URL for the downloadable file. * - download_link: The URL for the downloadable file.
* - release_link: The URL for the release notes. * - release_link: The URL for the release notes.
* - core_compatible: A flag indicating whether the project is compatible
* with the currently installed version of Drupal core. This flag is not
* set for the Drupal core project itself.
* - core_compatibility_message: A message indicating the versions of Drupal
* core with which this project is compatible. This message is also
* contained within the 'core_compatibility_details' variable documented
* above. This message is not set for the Drupal core project itself.
*
* @see template_preprocess_update_version()
*/ */
#} #}
<div class="{{ attributes.class }} project-update__version"{{ attributes|without('class') }}> <div class="{{ attributes.class }} project-update__version"{{ attributes|without('class') }}>
@ -19,18 +29,22 @@
<div class="project-update__version-details layout-column layout-column--quarter"> <div class="project-update__version-details layout-column layout-column--quarter">
<a href="{{ version.release_link }}">{{ version.version }}</a> <a href="{{ version.release_link }}">{{ version.version }}</a>
<span class="project-update__version-date">({{ version.date|date('Y-M-d') }})</span> <span class="project-update__version-date">({{ version.date|date('Y-M-d') }})</span>
{% if version.core_compatibility_message %}
<span class="project-update__core-compatibility-message">{{ version.core_compatibility_message }}</span>
{% endif %}
</div> </div>
<div class="layout-column layout-column--half"> <div class="layout-column layout-column--half">
<ul class="project-update__version-links"> <ul class="project-update__version-links">
<li class="project-update__download-link"> {% if version.core_compatible is not defined or version.core_compatible %}
<a href="{{ version.download_link }}">{{ 'Download'|t }}</a> <li class="project-update__download-link">
</li> <a href="{{ version.download_link }}">{{ 'Download'|t }}</a>
</li>
{% endif %}
<li class="project-update__release-notes-link"> <li class="project-update__release-notes-link">
<a href="{{ version.release_link }}">{{ 'Release notes'|t }}</a> <a href="{{ version.release_link }}">{{ 'Release notes'|t }}</a>
</li> </li>
{% if core_compatibility_details %}
<li class="project-update__compatibility-details">
{{ core_compatibility_details }}
</li>
{% endif %}
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -0,0 +1,28 @@
/**
* @file update-report.css
*
* Styling for the Available updates report at admin/reports/updates
*/
.project-update__compatibility-details details {
height: 20px;
margin: 2px 0;
border: 0;
background-color: inherit;
}
.project-update__compatibility-details details[open] {
overflow: visible;
height: auto;
white-space: normal;
}
.project-update__compatibility-details summary {
border: 0;
margin: 0;
padding: 0;
text-transform: none;
font-weight: normal;
}
.project-update__compatibility-details .details-wrapper {
margin: 0;
padding: 5px 0;
}

View File

@ -83,6 +83,12 @@ maintenance-page:
- system/maintenance - system/maintenance
- seven/global-styling - seven/global-styling
update-report:
version: VERSION
css:
theme:
css/theme/update-report.css: {}
install-page: install-page:
version: VERSION version: VERSION
js: js:

View File

@ -425,3 +425,16 @@ function seven_preprocess_image_widget(array &$variables) {
unset($data['preview']); unset($data['preview']);
} }
} }
/**
* Prepares variables for update version templates.
*
* Default template: update-version.html.twig.
*
* @param array $variables
* An associative array containing:
* - version: An array of information about the release version.
*/
function seven_preprocess_update_version(array &$variables) {
$variables['#attached']['library'][] = 'seven/update-report';
}

View File

@ -6,11 +6,21 @@
* Available variables: * Available variables:
* - attributes: HTML attributes suitable for a container element. * - attributes: HTML attributes suitable for a container element.
* - title: The title of the project. * - title: The title of the project.
* - core_compatibility_details: Render array of core compatibility details.
* - version: A list of data about the latest released version, containing: * - version: A list of data about the latest released version, containing:
* - version: The version number. * - version: The version number.
* - date: The date of the release. * - date: The date of the release.
* - download_link: The URL for the downloadable file. * - download_link: The URL for the downloadable file.
* - release_link: The URL for the release notes. * - release_link: The URL for the release notes.
* - core_compatible: A flag indicating whether the project is compatible
* with the currently installed version of Drupal core. This flag is not
* set for the Drupal core project itself.
* - core_compatibility_message: A message indicating the versions of Drupal
* core with which this project is compatible. This message is also
* contained within the 'core_compatibility_details' variable documented
* above. This message is not set for the Drupal core project itself.
*
* @see template_preprocess_update_version()
*/ */
#} #}
<div class="{{ attributes.class }} project-update__version"{{ attributes|without('class') }}> <div class="{{ attributes.class }} project-update__version"{{ attributes|without('class') }}>
@ -19,18 +29,22 @@
<div class="project-update__version-details layout-column layout-column--quarter"> <div class="project-update__version-details layout-column layout-column--quarter">
<a href="{{ version.release_link }}">{{ version.version }}</a> <a href="{{ version.release_link }}">{{ version.version }}</a>
<span class="project-update__version-date">({{ version.date|date('Y-M-d') }})</span> <span class="project-update__version-date">({{ version.date|date('Y-M-d') }})</span>
{% if version.core_compatibility_message %}
<span class="project-update__core-compatibility-message">{{ version.core_compatibility_message }}</span>
{% endif %}
</div> </div>
<div class="layout-column layout-column--half"> <div class="layout-column layout-column--half">
<ul class="project-update__version-links"> <ul class="project-update__version-links">
<li class="project-update__download-link"> {% if version.core_compatible is not defined or version.core_compatible %}
<a href="{{ version.download_link }}">{{ 'Download'|t }}</a> <li class="project-update__download-link">
</li> <a href="{{ version.download_link }}">{{ 'Download'|t }}</a>
</li>
{% endif %}
<li class="project-update__release-notes-link"> <li class="project-update__release-notes-link">
<a href="{{ version.release_link }}">{{ 'Release notes'|t }}</a> <a href="{{ version.release_link }}">{{ 'Release notes'|t }}</a>
</li> </li>
{% if core_compatibility_details %}
<li class="project-update__compatibility-details">
{{ core_compatibility_details }}
</li>
{% endif %}
</ul> </ul>
</div> </div>
</div> </div>