diff --git a/core/modules/update/css/update.admin.theme.css b/core/modules/update/css/update.admin.theme.css index abf0a88243..19b4af2a25 100644 --- a/core/modules/update/css/update.admin.theme.css +++ b/core/modules/update/css/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,19 @@ 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-bottom: 1px solid #bfbfbf; + padding: 0.5em 0; +} +.project-update__version--installed { + border-bottom: none; } .project-update__version-date { white-space: nowrap; @@ -51,13 +60,12 @@ } .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 { +.project-update__version--recommended-strong .project-update__version-title, +.version-security .project-update__version-title { font-weight: bold; } 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..894379e785 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', @@ -83,24 +73,31 @@
{% endif %} {% set includes = includes|join(', ') %} - {% if disabled %} - {{ 'Includes:'|t }} - - {% else %} - {% trans %} - Includes: {{ includes|placeholder }} - {% endtrans %} - {% endif %} + +{% if versions %} + {% for version in versions %} + {{ version }} + {% endfor %} +{% endif %} + +{% if disabled %} + {{ 'Includes:'|t }} + +{% else %} + {% trans %} + Includes: {{ includes|placeholder }} + {% endtrans %} +{% 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..79f47c1fd8 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 }}
+
{{ version.version }} ({{ version.date|date('Y-M-d') }}) + {% if version.security_covered %} + {% trans %} + Covered by Drupal’s security advisory policy + {% endtrans %} + {% endif %}
- + {% 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/tests/src/Functional/UpdateContribTest.php b/core/modules/update/tests/src/Functional/UpdateContribTest.php index 20d397cd48..ee2e2ee311 100644 --- a/core/modules/update/tests/src/Functional/UpdateContribTest.php +++ b/core/modules/update/tests/src/Functional/UpdateContribTest.php @@ -176,8 +176,8 @@ public function testUpdateContribOrder() { // Instead of just searching for 'BBB Update test' or something, we want // to use the full markup that starts the project entry itself, so that // we're really testing that the project listings are in the right order. - $bbb_project_link = '
BBB Update test'; - $ccc_project_link = '
CCC Update test'; + $bbb_project_link = '
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 +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..65822b96f2 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: @@ -92,7 +91,7 @@ public function testNormalUpdateAvailable() { if ($extra_version == '') { $this->assertNoText(t('Up to date')); $this->assertText(t('Update available')); - $this->assertText(t('Recommended version:')); + $this->assertText(t('Recommended update:')); $this->assertNoText(t('Latest version:')); $this->assertRaw('warning.svg', 'Warning icon was found.'); } @@ -101,7 +100,7 @@ public function testNormalUpdateAvailable() { else { $this->assertText(t('Up to date')); $this->assertNoText(t('Update available')); - $this->assertNoText(t('Recommended version:')); + $this->assertNoText(t('Recommended update:')); $this->assertText(t('Latest version:')); $this->assertRaw('check.svg', 'Check icon was found.'); } @@ -112,7 +111,7 @@ public function testNormalUpdateAvailable() { if ($extra_version == '') { $this->assertNoText(t('Up to date')); $this->assertText(t('Update available')); - $this->assertText(t('Recommended version:')); + $this->assertText(t('Recommended update:')); $this->assertNoText(t('Latest version:')); $this->assertRaw('warning.svg', 'Warning icon was found.'); } @@ -121,7 +120,7 @@ public function testNormalUpdateAvailable() { else { $this->assertNoText(t('Up to date')); $this->assertText(t('Update available')); - $this->assertText(t('Recommended version:')); + $this->assertText(t('Recommended update:')); $this->assertText(t('Latest version:')); $this->assertRaw('warning.svg', 'Warning icon was found.'); } @@ -146,11 +145,10 @@ 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:')); + $this->assertText(t('Recommended update:')); $this->assertNoText(t('Latest version:')); $this->assertRaw('error.svg', 'Error icon was found.'); } @@ -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 4cff44c727..8b889b9895 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,26 @@ 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: + + // 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('Projects covered by Drupal’s security advisory policy will have security advisories responsibly disclosed when vulnerabilities are reported to Drupal’s security team. Projects from Drupal.org that are not covered may have publicly disclosed vulnerabilities.'), + ]; + 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'); + 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.module b/core/modules/update/update.module index 0545aef8b9..f2c8b3d22a 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -124,7 +124,7 @@ function update_help($route_name, RouteMatchInterface $route_match) { $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('Checking for available updates') . '
'; - $output .= '
' . t('The Available updates report displays core, contributed modules, and themes for which there are new releases available for download. On the report page, you can also check manually for updates. You can configure the frequency of update checks, which are performed during cron runs, and whether notifications are sent on the Update Manager settings page.', [':update-report' => \Drupal::url('update.status'), ':update-settings' => \Drupal::url('update.settings')]) . '
'; + $output .= '
' . t('The Available updates report displays core, contributed modules, and themes for which there are new releases available for download. On the report page, you can also check manually for updates. Projects covered by Drupal’s security advisory policy are noted. You can configure the frequency of update checks, which are performed during cron runs, and whether notifications are sent on the Update Manager settings page.', [':update-report' => \Drupal::url('update.status'), ':update-settings' => \Drupal::url('update.settings')]) . '
'; // Only explain the Update manager if it has not been disabled. if (_update_manager_access()) { $output .= '
' . t('Performing updates through the Update page') . '
'; @@ -136,7 +136,8 @@ function update_help($route_name, RouteMatchInterface $route_match) { return $output; case 'update.status': - return '

' . t('Here you can find information about available updates for your installed modules and themes. Note that each module or theme is part of a "project", which may or may not have the same name, and might include multiple modules or themes within it.') . '

'; + return '

' . t('Here you can find information about available updates for your installed modules and themes. Note that each module or theme is part of a "project", which may or may not have the same name, and might include multiple modules or themes within it.') . '

' + . '

' . t('Projects covered by Drupal’s security advisory policy will have security advisories responsibly disclosed when vulnerabilities are reported to Drupal’s security team. Projects from Drupal.org that are not covered may have publicly disclosed vulnerabilities.') . '

'; case 'system.modules_list': if (_update_manager_access()) { diff --git a/core/modules/update/update.report.inc b/core/modules/update/update.report.inc index 7b14a05852..21f18c00e7 100644 --- a/core/modules/update/update.report.inc +++ b/core/modules/update/update.report.inc @@ -8,6 +8,8 @@ use Drupal\Component\Utility\Unicode; use Drupal\Core\Template\Attribute; use Drupal\Core\Url; +use Drupal\update\UpdateFetcherInterface; +use Drupal\update\UpdateManagerInterface; /** * Prepares variables for project status report templates. @@ -39,45 +41,38 @@ 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 UpdateFetcherInterface::UNKNOWN: + case UpdateFetcherInterface::FETCH_PENDING: + case UpdateFetcherInterface::NOT_FETCHED: + 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 +85,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 +122,7 @@ function template_preprocess_update_project_status(&$variables) { $versions_inner = []; $security_class = []; $version_class = []; + if (isset($project['recommended'])) { if ($project['status'] != UPDATE_CURRENT || $project['existing_version'] !== $project['recommended']) { @@ -159,7 +155,7 @@ function template_preprocess_update_project_status(&$variables) { $versions_inner[] = [ '#theme' => 'update_version', '#version' => $project['releases'][$project['recommended']], - '#title' => t('Recommended version:'), + '#title' => t('Recommended update:'), '#attributes' => ['class' => $version_class], ]; } @@ -210,6 +206,16 @@ function template_preprocess_update_project_status(&$variables) { } } + // Currently installed version. + 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 (!empty($versions_inner)) { $variables['versions'] = $versions_inner; } diff --git a/core/themes/stable/css/update/update.admin.theme.css b/core/themes/stable/css/update/update.admin.theme.css index abf0a88243..19b4af2a25 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,19 @@ 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-bottom: 1px solid #bfbfbf; + padding: 0.5em 0; +} +.project-update__version--installed { + border-bottom: none; } .project-update__version-date { white-space: nowrap; @@ -51,13 +60,12 @@ } .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 { +.project-update__version--recommended-strong .project-update__version-title, +.version-security .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..2c3308afd0 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', @@ -81,24 +71,31 @@
{% endif %} {% set includes = includes|join(', ') %} - {% if disabled %} - {{ 'Includes:'|t }} -
    -
  • - {% trans %} - Enabled: {{ includes|placeholder }} - {% endtrans %} -
  • -
  • - {% set disabled = disabled|join(', ') %} - {% trans %} - Disabled: {{ disabled|placeholder }} - {% endtrans %} -
  • -
- {% else %} - {% trans %} - Includes: {{ includes|placeholder }} - {% endtrans %} - {% endif %}
+ +{% if versions %} + {% for version in versions %} + {{ version }} + {% endfor %} +{% endif %} + +{% if disabled %} + {{ 'Includes:'|t }} +
    +
  • + {% trans %} + Enabled: {{ includes|placeholder }} + {% endtrans %} +
  • +
  • + {% set disabled = disabled|join(', ') %} + {% trans %} + Disabled: {{ disabled|placeholder }} + {% endtrans %} +
  • +
+{% else %} + {% trans %} + Includes: {{ includes|placeholder }} + {% endtrans %} +{% 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..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 @@ #}
-
{{ title }}
-
+
{{ title }}
+
{{ version.version }} ({{ version.date|date('Y-M-d') }}) + {% if version.security_covered %} + {% trans %} + Covered by Drupal’s security advisory policy + {% endtrans %} + {% endif %}
- + {% if attributes.class != 'project-update__version--installed' %} +
+ +
+ {% endif %}