CCC Update test';
$this->assertTrue(strpos($this->getRawContent(), $bbb_project_link) < strpos($this->getRawContent(), $ccc_project_link), "'BBB Update test' project is listed before the 'CCC Update test' project");
}
@@ -375,7 +375,7 @@ public function testUpdateBrokenFetchURL() {
// The other two should be listed as projects.
$this->assertRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project appears.');
$this->assertNoRaw(\Drupal::l(t('BBB Update test'), Url::fromUri('http://example.com/project/bbb_update_test')), 'Link to bbb_update_test project does not appear.');
- $this->assertRaw(\Drupal::l(t('CCC Update test'), Url::fromUri('http://example.com/project/ccc_update_test')), 'Link to bbb_update_test project appears.');
+ $this->assertRaw(\Drupal::l(t('CCC Update test'), Url::fromUri('http://example.com/project/ccc_update_test')), 'Link to ccc_update_test project appears.');
}
/**
diff --git a/core/modules/update/tests/src/Functional/UpdateCoreTest.php b/core/modules/update/tests/src/Functional/UpdateCoreTest.php
index 5cd4b10260..65e6ca644a 100644
--- a/core/modules/update/tests/src/Functional/UpdateCoreTest.php
+++ b/core/modules/update/tests/src/Functional/UpdateCoreTest.php
@@ -82,8 +82,7 @@ public function testNormalUpdateAvailable() {
$this->checkForMetaRefresh();
$this->assertNoText(t('Security update required!'));
$this->assertRaw(\Drupal::l("8.$minor_version.1" . $extra_version, Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release appears.');
- $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version.tar.gz")), 'Link to download appears.');
- $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release notes appears.');
+ $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to download appears.');
switch ($minor_version) {
case 0:
@@ -146,8 +145,7 @@ public function testMajorUpdateAvailable() {
$this->checkForMetaRefresh();
$this->assertNoText(t('Security update required!'));
$this->assertRaw(\Drupal::l('9.0.0', Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release appears.');
- $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-9-0-0.tar.gz")), 'Link to download appears.');
- $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release notes appears.');
+ $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to download appears.');
$this->assertNoText(t('Up to date'));
$this->assertText(t('Not supported!'));
$this->assertText(t('Recommended version:'));
@@ -170,8 +168,7 @@ public function testSecurityUpdateAvailable() {
$this->assertNoText(t('Update available'));
$this->assertText(t('Security update required!'));
$this->assertRaw(\Drupal::l("8.$minor_version.2", Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release appears.');
- $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-2.tar.gz")), 'Link to download appears.');
- $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release notes appears.');
+ $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to download appears.');
$this->assertRaw('error.svg', 'Error icon was found.');
}
}
diff --git a/core/modules/update/update.compare.inc b/core/modules/update/update.compare.inc
index 2ba5fdce75..9e2fce96a8 100644
--- a/core/modules/update/update.compare.inc
+++ b/core/modules/update/update.compare.inc
@@ -177,6 +177,10 @@ function update_calculate_project_update_status(&$project_data, $available) {
}
}
+ // For dev releases, existing_version looks like '8.4.0-dev', while
+ // updates.drupal.org provides '8.4.x-dev'.
+ $project_data['version_normalized'] = preg_replace('/0-dev$/', 'x-dev', $project_data['existing_version']);
+
// If the project status is marked as something bad, there's nothing else
// to consider.
if (isset($available['project_status'])) {
@@ -296,6 +300,7 @@ function update_calculate_project_update_status(&$project_data, $available) {
foreach ($available['releases'] as $version => $release) {
// First, if this is the existing release, check a few conditions.
if ($project_data['existing_version'] === $version) {
+ $project_data['releases'][$version] = $release;
if (isset($release['terms']['Release type']) &&
in_array('Insecure', $release['terms']['Release type'])) {
$project_data['status'] = UPDATE_NOT_SECURE;
diff --git a/core/modules/update/update.install b/core/modules/update/update.install
index c616412ac4..da2ec2a484 100644
--- a/core/modules/update/update.install
+++ b/core/modules/update/update.install
@@ -5,6 +5,8 @@
* Install, update, and uninstall functions for the Update Manager module.
*/
+use Drupal\Core\Site\Settings;
+use Drupal\Core\Link;
use Drupal\Core\Url;
/**
@@ -33,8 +35,29 @@ function update_requirements($phase) {
if ($available = update_get_available(FALSE)) {
module_load_include('inc', 'update', 'update.compare');
$data = update_calculate_project_data($available);
- // First, populate the requirements for core:
+
+ if (Settings::get('update_warn_drupalorg_security', TRUE)) {
+ // Check if all projects have security advisory coverage.
+ $requirements['update_covered'] = [
+ 'title' => t('Drupal.org security advisory coverage'),
+ 'value' => t('Currently installed modules and themes from Drupal.org receive coverage.'),
+ 'description' => t('Learn more about
Drupal.org security advisory coverage.'),
+ ];
+ foreach ($data as $project) {
+ // 'security_covered' boolean makes a positive assertion of coverage.
+ // 'security' string confirms there is no coverage. Check both so
+ // non-www.drupal.org projects are not false positives.
+ if (isset($project['releases'][$project['version_normalized']]) && empty($project['releases'][$project['version_normalized']]['security_covered']) && !empty($project['releases'][$project['version_normalized']]['security'])) {
+ $requirements['update_covered']['value'] = Link::createFromRoute(t('Modules and themes without security advisory coverage found'), 'update.status');
+ $requirements['update_covered']['severity'] = REQUIREMENT_WARNING;
+ break;
+ }
+ }
+ }
+
+ // Populate the requirements for core:
$requirements['update_core'] = _update_requirement_check($data['drupal'], 'core');
+
// We don't want to check drupal a second time.
unset($data['drupal']);
if (!empty($data)) {
diff --git a/core/modules/update/update.report.inc b/core/modules/update/update.report.inc
index 7b14a05852..a95fa4baf1 100644
--- a/core/modules/update/update.report.inc
+++ b/core/modules/update/update.report.inc
@@ -8,6 +8,7 @@
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
+use Drupal\update\UpdateManagerInterface;
/**
* Prepares variables for project status report templates.
@@ -39,45 +40,35 @@ function template_preprocess_update_report(&$variables) {
$variables['no_updates_message'] = _update_no_data();
}
- $rows = [];
-
+ $projects = [];
foreach ($data as $project) {
- $project_status = [
- '#theme' => 'update_project_status',
- '#project' => $project,
- ];
-
- // Build project rows.
- if (!isset($rows[$project['project_type']])) {
- $rows[$project['project_type']] = [
- '#type' => 'table',
- '#attributes' => ['class' => ['update']],
- ];
- }
- $row_key = !empty($project['title']) ? Unicode::strtolower($project['title']) : Unicode::strtolower($project['name']);
-
- // Add the project status row and details.
- $rows[$project['project_type']][$row_key]['status'] = $project_status;
-
- // Add project status class attribute to the table row.
+ // Add the project status and details.
switch ($project['status']) {
- case UPDATE_CURRENT:
- $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-success']];
+ case UpdateManagerInterface::CURRENT:
+ $class = 'color-success';
break;
- case UPDATE_UNKNOWN:
- case UPDATE_FETCH_PENDING:
- case UPDATE_NOT_FETCHED:
- case UPDATE_NOT_SECURE:
- case UPDATE_REVOKED:
- case UPDATE_NOT_SUPPORTED:
- $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-error']];
+
+ case UpdateManagerInterface::NOT_SECURE:
+ case UpdateManagerInterface::REVOKED:
+ case UpdateManagerInterface::NOT_SUPPORTED:
+ $class = 'color-error';
break;
- case UPDATE_NOT_CHECKED:
- case UPDATE_NOT_CURRENT:
+
+ case UpdateManagerInterface::NOT_CURRENT:
default:
- $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-warning']];
+ $class = 'color-warning';
break;
}
+ $projects[$project['project_type']][Unicode::strtolower(!empty($project['title']) ? $project['title'] : $project['name'])] = [
+ '#theme' => 'admin_block',
+ '#block' => [
+ 'content' => [
+ '#theme' => 'update_project_status',
+ '#project' => $project,
+ ],
+ 'attributes' => ['class' => [$class]],
+ ],
+ ];
}
$project_types = [
@@ -90,11 +81,11 @@ function template_preprocess_update_report(&$variables) {
$variables['project_types'] = [];
foreach ($project_types as $type_name => $type_label) {
- if (!empty($rows[$type_name])) {
- ksort($rows[$type_name]);
+ if (!empty($projects[$type_name])) {
+ ksort($projects[$type_name]);
$variables['project_types'][] = [
'label' => $type_label,
- 'table' => $rows[$type_name],
+ 'content' => $projects[$type_name],
];
}
}
@@ -127,6 +118,14 @@ function template_preprocess_update_project_status(&$variables) {
$versions_inner = [];
$security_class = [];
$version_class = [];
+ if (isset($project['releases'][$project['version_normalized']])) {
+ $versions_inner[] = [
+ '#theme' => 'update_version',
+ '#version' => $project['releases'][$project['version_normalized']],
+ '#title' => t('Installed version:'),
+ '#attributes' => ['class' => ['project-update__version--installed']],
+ ];
+ }
if (isset($project['recommended'])) {
if ($project['status'] != UPDATE_CURRENT || $project['existing_version'] !== $project['recommended']) {
diff --git a/core/themes/stable/css/update/update.admin.theme.css b/core/themes/stable/css/update/update.admin.theme.css
index abf0a88243..27da7735a7 100644
--- a/core/themes/stable/css/update/update.admin.theme.css
+++ b/core/themes/stable/css/update/update.admin.theme.css
@@ -8,10 +8,12 @@
font-size: 110%;
}
.project-update__status {
+ text-align: right; /* LTR */
float: right; /* LTR */
font-size: 110%;
}
[dir="rtl"] .project-update__status {
+ text-align: left;
float: left;
}
.project-update__status--not-supported {
@@ -32,12 +34,22 @@
padding-left: 0;
padding-right: 0.5em;
}
+.project-update__status-icon img {
+ vertical-align: top;
+}
.project-update__details {
padding: 1em 1em 0.25em 1em;
}
.project-update__version {
- padding: 1em 0;
+ border-top: 1px solid #bfbfbf;
+ padding: 0.5em 0;
+}
+.project-update__version:last-child {
+ padding-bottom: 0;
+}
+.project-update__version--installed {
+ border-top: none;
}
.project-update__version-date {
white-space: nowrap;
@@ -51,12 +63,10 @@
}
.project-update__version-links {
text-align: right; /* LTR */
- padding-right: 1em; /* LTR */
list-style-type: none;
}
[dir="rtl"] .project-update__version-links {
text-align: left;
- padding-left: 1em;
}
.project-update__version--recommended-strong .project-update__version-title {
font-weight: bold;
diff --git a/core/themes/stable/templates/admin/update-project-status.html.twig b/core/themes/stable/templates/admin/update-project-status.html.twig
index 5a6d2ecea7..780d8557c2 100644
--- a/core/themes/stable/templates/admin/update-project-status.html.twig
+++ b/core/themes/stable/templates/admin/update-project-status.html.twig
@@ -45,24 +45,14 @@
+
+{% if versions %}
+ {% for version in versions %}
+ {{ version }}
+ {% endfor %}
+{% endif %}
diff --git a/core/themes/stable/templates/admin/update-report.html.twig b/core/themes/stable/templates/admin/update-report.html.twig
index 9efebc06ae..648d31ea98 100644
--- a/core/themes/stable/templates/admin/update-report.html.twig
+++ b/core/themes/stable/templates/admin/update-report.html.twig
@@ -17,7 +17,7 @@
{% for project_type in project_types %}
{% endfor %}
diff --git a/core/themes/stable/templates/admin/update-version.html.twig b/core/themes/stable/templates/admin/update-version.html.twig
index 6c23584a68..d57ceedb80 100644
--- a/core/themes/stable/templates/admin/update-version.html.twig
+++ b/core/themes/stable/templates/admin/update-version.html.twig
@@ -15,20 +15,24 @@
#}