BBB Update test';
+ $ccc_project_link = '
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 +377,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/src/UpdateProcessor.php b/core/modules/update/src/UpdateProcessor.php
index 25dfc7a004..9115357274 100644
--- a/core/modules/update/src/UpdateProcessor.php
+++ b/core/modules/update/src/UpdateProcessor.php
@@ -231,6 +231,9 @@ protected function parseXml($raw_xml) {
foreach ($release->children() as $k => $v) {
$data['releases'][$version][$k] = (string) $v;
}
+ if ($release->security['covered']) {
+ $data['releases'][$version]['security_covered'] = TRUE;
+ }
$data['releases'][$version]['terms'] = [];
if ($release->terms) {
foreach ($release->terms->children() as $term) {
diff --git a/core/modules/update/templates/update-project-status.html.twig b/core/modules/update/templates/update-project-status.html.twig
index 4cc9a19e8b..402bb77600 100644
--- a/core/modules/update/templates/update-project-status.html.twig
+++ b/core/modules/update/templates/update-project-status.html.twig
@@ -47,24 +47,14 @@
-
+
{%- if url -%}
{{ title }}
{%- else -%}
{{ title }}
{%- endif %}
- {{ existing_version }}
- {% if install_type == 'dev' and datestamp %}
-
({{ datestamp }})
- {% endif %}
-{% if versions %}
- {% for version in versions %}
- {{ version }}
- {% endfor %}
-{% endif %}
-
{%
set extra_classes = [
project.status == constant('UPDATE_NOT_SECURE') ? 'project-not-secure',
@@ -104,3 +94,9 @@
{% endtrans %}
{% endif %}
+
+{% if versions %}
+ {% for version in versions %}
+ {{ version }}
+ {% endfor %}
+{% endif %}
diff --git a/core/modules/update/templates/update-report.html.twig b/core/modules/update/templates/update-report.html.twig
index ae121cc3b4..25ccc45238 100644
--- a/core/modules/update/templates/update-report.html.twig
+++ b/core/modules/update/templates/update-report.html.twig
@@ -19,7 +19,7 @@
{% for project_type in project_types %}
{{ project_type.label }}
- {{ project_type.table }}
+ {{ project_type.content }}
{% else %}
{{ no_updates_message }}
{% endfor %}
diff --git a/core/modules/update/templates/update-version.html.twig b/core/modules/update/templates/update-version.html.twig
index c21c4f0ba4..25dbcce4c0 100644
--- a/core/modules/update/templates/update-version.html.twig
+++ b/core/modules/update/templates/update-version.html.twig
@@ -17,20 +17,24 @@
#}
-
{{ title }}
-
+
{{ title }}
+
-
+ {% if attributes.class != 'project-update__version--installed' %}
+
+ {% endif %}
diff --git a/core/modules/update/tests/modules/update_test/aaa_update_test.1_0.xml b/core/modules/update/tests/modules/update_test/aaa_update_test.1_0.xml
index 82362fe846..9405cb3e38 100644
--- a/core/modules/update/tests/modules/update_test/aaa_update_test.1_0.xml
+++ b/core/modules/update/tests/modules/update_test/aaa_update_test.1_0.xml
@@ -29,6 +29,7 @@
Release typeNew features
Release typeBug fixes
+
AAA is not covered!
diff --git a/core/modules/update/tests/modules/update_test/bbb_update_test.1_0.xml b/core/modules/update/tests/modules/update_test/bbb_update_test.1_0.xml
index 8d705b5f96..2142c04efa 100644
--- a/core/modules/update/tests/modules/update_test/bbb_update_test.1_0.xml
+++ b/core/modules/update/tests/modules/update_test/bbb_update_test.1_0.xml
@@ -16,11 +16,11 @@
bbb_update_test 8.x-1.0
8.x-1.0
- DRUPAL-7--1-0
+ 8.x-1.0
1
0
published
- http://example.com/bbb_update_test-7-x-1-0-release
+ http://example.com/bbb_update_test-8-x-1-0-release
http://example.com/bbb_update_test-8.x-1.0.tar.gz
1250424521
b966255555d9c9b86d480ca08cfaa98e
@@ -29,6 +29,26 @@
Release typeNew features
Release typeBug fixes
+
+
+
+ bbb_update_test 8.x-1.0-beta1
+ 8.x-1.0-beta1
+ 8.x-1.0-beta1
+ 1
+ 0
+ beta1
+ published
+ http://example.com/bbb_update_test-8-x-1-0-beta1
+ http://example.com/bbb_update_test-8.x-1.0-beta1.tar.gz
+ 1250424521
+ 7da7b18ce17cef2122f5cbca1bfe626a
+ 1073751331
+
+ Release typeNew features
+ Release typeBug fixes
+
+ Not covered!
diff --git a/core/modules/update/tests/modules/update_test/ccc_update_test.1_0.xml b/core/modules/update/tests/modules/update_test/ccc_update_test.1_0.xml
index 82764c2c33..35e1f5f4ca 100644
--- a/core/modules/update/tests/modules/update_test/ccc_update_test.1_0.xml
+++ b/core/modules/update/tests/modules/update_test/ccc_update_test.1_0.xml
@@ -29,6 +29,7 @@
Release typeNew features
Release typeBug fixes
+
diff --git a/core/modules/update/update.compare.inc b/core/modules/update/update.compare.inc
index 2ba5fdce75..c8be5c325c 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'])) {
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..8bd2d192ac 100644
--- a/core/modules/update/update.report.inc
+++ b/core/modules/update/update.report.inc
@@ -6,6 +6,7 @@
*/
use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Site\Settings;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
@@ -39,45 +40,18 @@ 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,
+ // Add the project status and details.
+ $projects[$project['project_type']][Unicode::strtolower(!empty($project['title']) ? $project['title'] : $project['name'])] = [
+ '#theme' => 'admin_block',
+ '#block' => [
+ 'content' => [
+ '#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.
- switch ($project['status']) {
- case UPDATE_CURRENT:
- $rows[$project['project_type']][$row_key]['#attributes'] = ['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']];
- break;
- case UPDATE_NOT_CHECKED:
- case UPDATE_NOT_CURRENT:
- default:
- $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-warning']];
- break;
- }
}
$project_types = [
@@ -90,11 +64,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 +101,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 url -%}
{{ title }}
{%- else -%}
{{ title }}
{%- endif %}
- {{ existing_version }}
- {% if install_type == 'dev' and datestamp %}
-
({{ datestamp }})
- {% endif %}
-{% if versions %}
- {% for version in versions %}
- {{ version }}
- {% endfor %}
-{% endif %}
-
{%
set extra_classes = [
project.status == constant('UPDATE_NOT_SECURE') ? 'project-not-secure',
@@ -102,3 +92,9 @@
{% endtrans %}
{% endif %}
+
+{% 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 %}
{{ project_type.label }}
- {{ project_type.table }}
+ {{ project_type.content }}
{% else %}
{{ no_updates_message }}
{% 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..aa5ed5802b 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 @@
#}
-
{{ title }}
-
+
{{ title }}
+
-
+ {% if attributes.class != 'project-update__version--installed' %}
+
+ {% endif %}
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 1720d11e43..6cdd2421cf 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -736,6 +736,19 @@
*/
/**
+ * Hide Drupal.org security advisory policy warnings.
+ *
+ * By default, Update Manager module warns about modules and themes from
+ * Drupal.org that are not covered by Drupal.org’s security advisory policy.
+ *
+ * Security issues in non-covered projects are reported to the public issue
+ * queue and will not receive coordinated security announcements.
+ *
+ * @see https://www.drupal.org/security-advisory-policy
+ */
+# $settings['update_warn_drupalorg_security'] = FALSE;
+
+/**
* The default list of directories that will be ignored by Drupal's file API.
*
* By default ignore node_modules and bower_components folders to avoid issues