diff --git a/core/modules/update/css/update.admin.css b/core/modules/update/css/update.admin.css index a3816af..7e00e60 100644 --- a/core/modules/update/css/update.admin.css +++ b/core/modules/update/css/update.admin.css @@ -7,7 +7,7 @@ font-weight: bold; font-size: 110%; padding-left: .25em; /* LTR */ - height: 22px; + min-height: 22px; } [dir="rtl"] .update .project { padding-right: .25em; @@ -80,55 +80,72 @@ } table.update, -.update table.version { +.update .version { width: 100%; margin-top: .5em; border: none; } -.update table.version tbody { - border: none; +.versions{ + margin:0; + padding: 1em; + list-style-type:none; +} + +.versions:after{ + content:""; + display:table; + clear:both; } -.update table.version tr, -.update table.version td { +.update .version { line-height: .9em; padding: 0; margin: 0; border: none; background: none; + clear: both; +} +.update .version > * { + padding-bottom:0.3em; } -.update table.version .version-title { - padding-left: 1em; /* LTR */ +.update li.version .version-title { width: 14em; -} -[dir="rtl"] .update table.version .version-title { - padding-left: 1em; + float:left; } -.update table.version .version-details { +.update li.version .version-details { padding-right: .5em; /* LTR */ + float:left; } -[dir="rtl"] .update table.version .version-details { +[dir="rtl"] .update .version .version-details { padding-left: .5em; direction: ltr; } -.update table.version .version-links { +.update .version .version-links { + float: right; /* LTR */ text-align: right; /* LTR */ - padding-right: 1em; /* LTR */ } -[dir="rtl"] .update table.version .version-links { + +.update .version .version-links .links { + list-style-type: none; + margin-top: 0; + padding-left: 0; + margin-left: 0.5em; +} + +[dir="rtl"] .update li.version .version-links { + float:left; text-align: left; - padding-left: 1em; } -.update table.version-security .version-title { +.update .version-security .version-title { color: #970f00; } -.update table.version-recommended-strong .version-title { +.update .version-recommended-strong .version-title { font-weight: bold; } diff --git a/core/modules/update/templates/update-report.html.twig b/core/modules/update/templates/update-report.html.twig new file mode 100644 index 0000000..3bc4489 --- /dev/null +++ b/core/modules/update/templates/update-report.html.twig @@ -0,0 +1,115 @@ +{# +/** + * @file + * Default theme implementation for the project status report. + * + * Available variables: + * - last_checked: A flag indicating whether the site checked for updates. + * - time: The time the site last checked for updates. + * - link: A link to check for updates manually. + * - project_types: A list of project types. + * - label: The project type label. + * - projects: Data about each project's status. + * - title: The project tile. + * - attributes: HTML attributes for the project row. + * - status_label: The project status label. + * - reason: The reason you should update the project. + * - icon: The project status version indicator icon. + * - existing_version: The version of the installed project. + * - versions: The available versions of the project. + * - install_type: The type of project (i.e. dev). + * - datestamp: The date/time of a project versions release. + * - extra: HTML attributes and additional information about the project. + * - attributes: HTML attributes for the extra item. + * - label: The label for an extra item. + * - data: The data about an extra item. + * - includes: The projects within project. + * - base_themes: The base theme declared for the project. + * - sub_themes: The sub themes declared for the project. + * + * @see template_preprocess_update_report() + * + * @ingroup themeable + */ +#} +
+ {% if last_checked %} + {{ 'Last checked: @time ago'|t({'@time': time}) }} + {% else %} + {{ 'Last checked: never'|t }} + {% endif %} + ({{ link }}) +
+ +{% for project_type in project_types %} +

{{ project_type.label }}

+ + + {% for project in project_type.projects %} + + + + {% endfor %} + +
+ {% spaceless %} +
+ {%- if project.status_label -%} + {{ project.status_label|t }} + {%- else -%} + {{ project.reason }} + {%- endif -%} + {{ project.icon }} +
+ {% endspaceless %} + +
{{ project.title }} {{ project.existing_version }} + {% if project.install_type == 'dev' and project.datestamp %} + ({{ project.datestamp }}) + {% endif %} +
+ + {% if project.versions %} +
    + {% for version in project.versions %} + {{ version }} + {% endfor %} +
+ {% endif %} + +
+ {% if project.extra %} +
+ {% for extra in project.extra %} + + {{ extra.label }}: {{ extra.data }} +
+ {% endfor %} +
+ {% endif %} +
+ {% if project.disabled %} + {{ 'Includes:'|t }} +
    +
  • {{ 'Enabled: %includes'|t({'%includes': project.includes|join(', ')}) }}
  • +
  • {{ 'Disabled: %disabled'|t({'%disabled': project.disabled|join(', ')}) }}
  • +
+ {% else %} + {{ 'Includes: %includes'|t({'%includes': project.includes|join(', ')}) }} + {% endif %} +
+ + {% if project.base_themes %} +
+ {{ 'Depends on: !basethemes'|t({'!basethemes': project.base_themes|join(', ')}) }} +
+ {% endif %} + + {% if project.sub_themes %} +
+ {{ 'Required by: %subthemes'|t({'%subthemes': project.sub_themes|join(', ')}) }} +
+ {% endif %} + +
+{% endfor %} diff --git a/core/modules/update/templates/update-version.html.twig b/core/modules/update/templates/update-version.html.twig new file mode 100644 index 0000000..dc51dc7 --- /dev/null +++ b/core/modules/update/templates/update-version.html.twig @@ -0,0 +1,27 @@ +{# +/** + * @file + * Default theme implementation for the version display of a project. + * + * Available variables: + * - attributes: HTML attributes for the update versions element. + * - version_link: Link to this version's release notes on drupal.org. + * - version_date: The date of the release. + * - version_links: Links to download this version and to this version's release notes. + * - tag: The title of the project. + * + * @see template_preprocess_update_version() + * + * @ingroup themeable + */ +#} + +
{{ tag }}
+
+ {{ version_link }} + ({{ version_date }}) +
+ + diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc index e411c2f..a706464 100644 --- a/core/modules/update/update.manager.inc +++ b/core/modules/update/update.manager.inc @@ -279,27 +279,6 @@ function update_manager_update_form($form, $form_state = array(), $context) { } /** - * Returns HTML for the first page in the process of updating projects. - * - * @param $variables - * An associative array containing: - * - form: A render element representing the form. - * - * @ingroup themeable - */ -function theme_update_manager_update_form($variables) { - $form = $variables['form']; - $last = \Drupal::state()->get('update.last_check') ?: 0; - $update_last_check = array( - '#theme' => 'update_last_check', - '#last' => $last, - ); - $output = drupal_render($update_last_check); - $output .= drupal_render_children($form); - return $output; -} - -/** * Form validation handler for update_manager_update_form(). * * Ensures that at least one project is selected. diff --git a/core/modules/update/update.module b/core/modules/update/update.module index 4cf9c0d..8381ffe 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -181,24 +181,15 @@ function update_manager_access() { */ function update_theme() { return array( - 'update_manager_update_form' => array( - 'render element' => 'form', - 'file' => 'update.manager.inc', - ), - 'update_last_check' => array( - 'variables' => array('last' => NULL), - ), 'update_report' => array( 'variables' => array('data' => NULL), 'file' => 'update.report.inc', + 'template' => 'update-report', ), 'update_version' => array( 'variables' => array('version' => NULL, 'tag' => NULL, 'class' => array()), 'file' => 'update.report.inc', - ), - 'update_status_label' => array( - 'variables' => array('status' => NULL), - 'file' => 'update.report.inc', + 'template' => 'update-version', ), ); } @@ -538,30 +529,6 @@ function _update_project_status_sort($a, $b) { } /** - * Returns HTML for the last time we checked for update data. - * - * In addition to properly formatting the given timestamp, this function also - * provides a "Check manually" link that refreshes the available update and - * redirects back to the same page. - * - * @param $variables - * An associative array containing: - * - last: The timestamp when the site last checked for available updates. - * - * @see theme_update_report() - * @see theme_update_available_updates_form() - * @ingroup themeable - */ -function theme_update_last_check($variables) { - $last = $variables['last']; - $output = '
'; - $output .= $last ? t('Last checked: @time ago', array('@time' => format_interval(REQUEST_TIME - $last))) : t('Last checked: never'); - $output .= ' (' . l(t('Check manually'), 'admin/reports/updates/check', array('query' => drupal_get_destination())) . ')'; - $output .= "
\n"; - return $output; -} - -/** * Implements hook_verify_update_archive(). * * First, we ensure that the archive isn't a copy of Drupal core, which the diff --git a/core/modules/update/update.report.inc b/core/modules/update/update.report.inc index 4c5264e..640fdb1 100644 --- a/core/modules/update/update.report.inc +++ b/core/modules/update/update.report.inc @@ -5,8 +5,12 @@ * Code required only when rendering the available updates report. */ +use Drupal\Core\Template\Attribute; + /** - * Returns HTML for the project status report. + * Prepares variables for project status report templates. + * + * Default template: update-report.html.twig. * * @param array $variables * An associative array containing: @@ -14,26 +18,17 @@ * * @ingroup themeable */ -function theme_update_report($variables) { +function template_preprocess_update_report(&$variables) { $data = $variables['data']; + $notification_level = \Drupal::config('update.settings')->get('notification.threshold'); $last = \Drupal::state()->get('update.last_check') ?: 0; - $update_last_check = array( - '#theme' => 'update_last_check', - '#last' => $last, - ); - $output = drupal_render($update_last_check); + $variables['last_checked'] = ($last != NULL); + $variables['time'] = format_interval(REQUEST_TIME - $last); + $variables['link'] = l(t('Check manually'), 'admin/reports/updates/check', array('query' => drupal_get_destination())); - if (!is_array($data)) { - $output .= '

' . $data . '

'; - return $output; - } - - $header = array(); $rows = array(); - $notification_level = \Drupal::config('update.settings')->get('notification.threshold'); - // Create an array of status values keyed by module or theme name, since // we'll need this while generating the report if we have to cross reference // anything (e.g. subthemes which have base themes missing an update). @@ -82,32 +77,63 @@ function theme_update_report($variables) { '#title' => $text, ); - $row = '
'; - $update_status_label = array('#theme' => 'update_status_label', '#status' => $project['status']); - $status_label = drupal_render($update_status_label); - $row .= !empty($status_label) ? $status_label : check_plain($project['reason']); - $row .= '' . drupal_render($icon) . ''; - $row .= "
\n"; + // Used to collect the project values. + $row = array(); + $row['attributes'] = new Attribute(array('class' => $class)); + $row['icon'] = $icon; + + $row['status_attributes'] = new Attribute(array('class' => array())); + switch ($project['status']) { + case UPDATE_NOT_SECURE: + $row['status_attributes']['class'] = 'security-error'; + $row['status_label'] = 'Security update required!'; + break; + case UPDATE_REVOKED: + $row['status_attributes']['class'] = 'revoked'; + $row['status_label'] = 'Revoked!'; + break; + case UPDATE_NOT_SUPPORTED: + $row['status_attributes']['class'] = 'not-supported'; + $row['status_label'] = 'Not supported!'; + break; + case UPDATE_NOT_CURRENT: + $row['status_attributes']['class'] = 'not-current'; + $row['status_label'] = 'Update available'; + break; + case UPDATE_CURRENT: + $row['status_attributes']['class'] = 'current'; + $row['status_label'] = 'Up to date'; + break; + } + + if (!empty($project['reason'])) { + $row['reason'] = check_plain($project['reason']); + } + else { + $row['reason'] = ''; + } - $row .= '
'; + // Set the project title. if (isset($project['title'])) { if (isset($project['link'])) { - $row .= l($project['title'], $project['link']); + $row['title'] = l($project['title'], $project['link']); } else { - $row .= check_plain($project['title']); + $row['title'] = check_plain($project['title']); } } else { - $row .= check_plain($project['name']); + $row['title'] = check_plain($project['name']); } - $row .= ' ' . check_plain($project['existing_version']); + + // Clean up the version for twig. + $row['existing_version'] = check_plain($project['existing_version']); + if ($project['install_type'] == 'dev' && !empty($project['datestamp'])) { - $row .= ' (' . format_date($project['datestamp'], 'custom', 'Y-M-d') . ')'; + $row['datestamp'] = format_date($project['datestamp'], 'custom', 'Y-M-d'); } - $row .= "
\n"; - $versions_inner = ''; + $versions_inner = array(); $security_class = array(); $version_class = array(); if (isset($project['recommended'])) { @@ -117,7 +143,10 @@ function theme_update_report($variables) { // If there's only 1 security update and it has the same version we're // recommending, give it the same CSS class as if it was recommended, // but don't print out a separate "Recommended" line for this project. - if (!empty($project['security updates']) && count($project['security updates']) == 1 && $project['security updates'][0]['version'] === $project['recommended']) { + if (!empty($project['security updates']) + && count($project['security updates']) == 1 + && $project['security updates'][0]['version'] === $project['recommended'] + ) { $security_class[] = 'version-recommended'; $security_class[] = 'version-recommended-strong'; } @@ -136,141 +165,128 @@ function theme_update_report($variables) { ) { $version_class[] = 'version-recommended-strong'; } - $update_version = array( + $versions_inner[] = array( '#theme' => 'update_version', '#version' => $project['releases'][$project['recommended']], '#tag' => t('Recommended version:'), '#class' => $version_class, ); - $versions_inner .= drupal_render($update_version); } // Now, print any security updates. if (!empty($project['security updates'])) { $security_class[] = 'version-security'; foreach ($project['security updates'] as $security_update) { - $update_version = array( + $versions_inner[] = array( '#theme' => 'update_version', '#version' => $security_update, '#tag' => t('Security update:'), '#class' => $security_class, ); - $versions_inner .= drupal_render($update_version); } } } if ($project['recommended'] !== $project['latest_version']) { - $update_version = array( + $versions_inner[] = array( '#theme' => 'update_version', '#version' => $project['releases'][$project['latest_version']], '#tag' => t('Latest version:'), '#class' => array('version-latest'), ); - $versions_inner .= drupal_render($update_version); } if ($project['install_type'] == 'dev' && $project['status'] != UPDATE_CURRENT && isset($project['dev_version']) && $project['recommended'] !== $project['dev_version']) { - $update_version = array( + $versions_inner[] = array( '#theme' => 'update_version', '#version' => $project['releases'][$project['dev_version']], '#tag' => t('Development version:'), '#class' => array('version-latest'), ); - $versions_inner .= drupal_render($update_version); } } if (isset($project['also'])) { foreach ($project['also'] as $also) { - $update_version = array( + $versions_inner[] = array( '#theme' => 'update_version', '#version' => $project['releases'][$also], '#tag' => t('Also available:'), '#class' => array('version-also-available'), ); - $versions_inner .= drupal_render($update_version); } } if (!empty($versions_inner)) { - $row .= "
\n" . $versions_inner . "
\n"; + $row['versions'] = $versions_inner; } - $row .= "
\n"; + + $row['extra'] = array(); if (!empty($project['extra'])) { - $row .= '
' . "\n"; foreach ($project['extra'] as $key => $value) { - $row .= '
'; - $row .= check_plain($value['label']) . ': '; - $row .= drupal_placeholder($value['data']); - $row .= "
\n"; + $extra_item = array(); + $extra_item['attributes'] = new Attribute(array('class' => $value['class'])); + $extra_item['label'] = check_plain($value['label']); + $extra_item['data'] = drupal_placeholder($value['data']); + $row['extra'][$key] = $extra_item; } - $row .= "
\n"; // extra div. } - $row .= '
'; - sort($project['includes']); + // Make sure we start with a clean slate for each project in the report. + $row['disabled'] = array(); + $row['includes'] = array(); if (!empty($project['disabled'])) { sort($project['disabled']); - // Make sure we start with a clean slate for each project in the report. - $includes_items = array(); - $row .= t('Includes:'); - $includes_items[] = t('Enabled: %includes', array('%includes' => implode(', ', $project['includes']))); - $includes_items[] = t('Disabled: %disabled', array('%disabled' => implode(', ', $project['disabled']))); - $item_list = array( - '#theme' => 'item_list', - '#items' => $includes_items, - ); - $row .= drupal_render($item_list); - } - else { - $row .= t('Includes: %includes', array('%includes' => implode(', ', $project['includes']))); + $row['disabled'] = $project['disabled']; } - $row .= "
\n"; + + sort($project['includes']); + $row['includes'] = $project['includes']; if (!empty($project['base_themes'])) { - $row .= '
'; asort($project['base_themes']); $base_themes = array(); foreach ($project['base_themes'] as $base_key => $base_theme) { - $update_status_label = array( - '#theme' => 'update_status_label', - '#status' => $status[$base_key], - ); switch ($status[$base_key]) { case UPDATE_NOT_SECURE: + $status_label = t('Security update required!'); + break; case UPDATE_REVOKED: + $status_label = t('Revoked!'); + break; case UPDATE_NOT_SUPPORTED: - $base_themes[] = t('%base_theme (!base_label)', array('%base_theme' => $base_theme, '!base_label' => drupal_render($update_status_label))); + $status_label = t('Not supported!'); break; - default: - $base_themes[] = drupal_placeholder($base_theme); + $status_label = ''; + } + + if ($status_label) { + $base_themes[] = t('%base_theme (!base_label)', array( + '%base_theme' => $base_theme, + '!base_label' => $status_label, + )); + } + else { + $base_themes[] = drupal_placeholder($base_theme); } } - $row .= t('Depends on: !basethemes', array('!basethemes' => implode(', ', $base_themes))); - $row .= "
\n"; + $row['base_themes'] = $base_themes; } if (!empty($project['sub_themes'])) { - $row .= '
'; sort($project['sub_themes']); - $row .= t('Required by: %subthemes', array('%subthemes' => implode(', ', $project['sub_themes']))); - $row .= "
\n"; + $row['sub_themes'] = $project['sub_themes']; } - $row .= "
\n"; // info div. - + // Build project rows. if (!isset($rows[$project['project_type']])) { $rows[$project['project_type']] = array(); } - $row_key = isset($project['title']) ? drupal_strtolower($project['title']) : drupal_strtolower($project['name']); - $rows[$project['project_type']][$row_key] = array( - 'class' => array($class), - 'data' => array($row), - ); + $row_key = !empty($project['title']) ? drupal_strtolower($project['title']) : drupal_strtolower($project['name']); + $rows[$project['project_type']][$row_key] = $row; } $project_types = array( @@ -280,57 +296,23 @@ function theme_update_report($variables) { 'module-disabled' => t('Disabled modules'), 'theme-disabled' => t('Disabled themes'), ); + $variables['project_types'] = array(); foreach ($project_types as $type_name => $type_label) { if (!empty($rows[$type_name])) { ksort($rows[$type_name]); - $output .= "\n

" . $type_label . "

\n"; - $table = array( - '#theme' => 'table', - '#header' => $header, - '#rows' => $rows[$type_name], - '#attributes' => array( - 'class' => array('update'), - ), + $variables['project_types'][] = array( + 'label' => $type_label, + 'projects' => $rows[$type_name], ); - $output .= drupal_render($table); } } drupal_add_css(drupal_get_path('module', 'update') . '/css/update.admin.css'); - return $output; } /** - * Returns HTML for a label to display for a project's update status. + * Prepare variables for the version display of a project. * - * @param array $variables - * An associative array containing: - * - status: The integer code for a project's current update status. - * - * @see update_calculate_project_data() - * @ingroup themeable - */ -function theme_update_status_label($variables) { - switch ($variables['status']) { - case UPDATE_NOT_SECURE: - return '' . t('Security update required!') . ''; - - case UPDATE_REVOKED: - return '' . t('Revoked!') . ''; - - case UPDATE_NOT_SUPPORTED: - return '' . t('Not supported!') . ''; - - case UPDATE_NOT_CURRENT: - return '' . t('Update available') . ''; - - case UPDATE_CURRENT: - return '' . t('Up to date') . ''; - - } -} - -/** - * Returns HTML for the version display of a project. + * Default template: update-version.html.twig. * * @param array $variables * An associative array containing: @@ -340,40 +322,28 @@ function theme_update_status_label($variables) { * - date: The date of the release. * - download_link: The URL for the downloadable file. * - tag: The title of the project. - * - class: A string containing extra classes for the wrapping table. - * - * @ingroup themeable + * - class: A array containing extra classes for the wrapping table. */ -function theme_update_version($variables) { +function template_preprocess_update_version(&$variables) { $version = $variables['version']; - $tag = $variables['tag']; - $class = implode(' ', $variables['class']); - - $output = ''; - $output .= ''; - $output .= ''; - $output .= '\n"; - $output .= '\n"; - $output .= ''; - $output .= ''; - $output .= "
' . $tag . "'; - $output .= l($version['version'], $version['release_link']); - $output .= ' (' . format_date($version['date'], 'custom', 'Y-M-d') . ')'; - $output .= "
\n"; - return $output; }