| Drupal | PHP Cross Reference | Content Management Systems |
1 <?php 2 3 /** 4 * @file 5 * Code required only when rendering the available updates report. 6 */ 7 8 /** 9 * Page callback: Generates a page about the update status of projects. 10 * 11 * @see update_menu() 12 */ 13 function update_status() { 14 if ($available = update_get_available(TRUE)) { 15 module_load_include('inc', 'update', 'update.compare'); 16 $data = update_calculate_project_data($available); 17 return theme('update_report', array('data' => $data)); 18 } 19 else { 20 return theme('update_report', array('data' => _update_no_data())); 21 } 22 } 23 24 /** 25 * Returns HTML for the project status report. 26 * 27 * @param array $variables 28 * An associative array containing: 29 * - data: An array of data about each project's status. 30 * 31 * @ingroup themeable 32 */ 33 function theme_update_report($variables) { 34 $data = $variables['data']; 35 36 $last = variable_get('update_last_check', 0); 37 $output = theme('update_last_check', array('last' => $last)); 38 39 if (!is_array($data)) { 40 $output .= '<p>' . $data . '</p>'; 41 return $output; 42 } 43 44 $header = array(); 45 $rows = array(); 46 47 $notification_level = variable_get('update_notification_threshold', 'all'); 48 49 // Create an array of status values keyed by module or theme name, since 50 // we'll need this while generating the report if we have to cross reference 51 // anything (e.g. subthemes which have base themes missing an update). 52 foreach ($data as $project) { 53 foreach ($project['includes'] as $key => $name) { 54 $status[$key] = $project['status']; 55 } 56 } 57 58 foreach ($data as $project) { 59 switch ($project['status']) { 60 case UPDATE_CURRENT: 61 $class = 'ok'; 62 $icon = theme('image', array('path' => 'misc/watchdog-ok.png', 'width' => 18, 'height' => 18, 'alt' => t('ok'), 'title' => t('ok'))); 63 break; 64 case UPDATE_UNKNOWN: 65 case UPDATE_FETCH_PENDING: 66 case UPDATE_NOT_FETCHED: 67 $class = 'unknown'; 68 $icon = theme('image', array('path' => 'misc/watchdog-warning.png', 'width' => 18, 'height' => 18, 'alt' => t('warning'), 'title' => t('warning'))); 69 break; 70 case UPDATE_NOT_SECURE: 71 case UPDATE_REVOKED: 72 case UPDATE_NOT_SUPPORTED: 73 $class = 'error'; 74 $icon = theme('image', array('path' => 'misc/watchdog-error.png', 'width' => 18, 'height' => 18, 'alt' => t('error'), 'title' => t('error'))); 75 break; 76 case UPDATE_NOT_CHECKED: 77 case UPDATE_NOT_CURRENT: 78 default: 79 $class = 'warning'; 80 $icon = theme('image', array('path' => 'misc/watchdog-warning.png', 'width' => 18, 'height' => 18, 'alt' => t('warning'), 'title' => t('warning'))); 81 break; 82 } 83 84 $row = '<div class="version-status">'; 85 $status_label = theme('update_status_label', array('status' => $project['status'])); 86 $row .= !empty($status_label) ? $status_label : check_plain($project['reason']); 87 $row .= '<span class="icon">' . $icon . '</span>'; 88 $row .= "</div>\n"; 89 90 $row .= '<div class="project">'; 91 if (isset($project['title'])) { 92 if (isset($project['link'])) { 93 $row .= l($project['title'], $project['link']); 94 } 95 else { 96 $row .= check_plain($project['title']); 97 } 98 } 99 else { 100 $row .= check_plain($project['name']); 101 } 102 $row .= ' ' . check_plain($project['existing_version']); 103 if ($project['install_type'] == 'dev' && !empty($project['datestamp'])) { 104 $row .= ' <span class="version-date">(' . format_date($project['datestamp'], 'custom', 'Y-M-d') . ')</span>'; 105 } 106 $row .= "</div>\n"; 107 108 $versions_inner = ''; 109 $security_class = array(); 110 $version_class = array(); 111 if (isset($project['recommended'])) { 112 if ($project['status'] != UPDATE_CURRENT || $project['existing_version'] !== $project['recommended']) { 113 114 // First, figure out what to recommend. 115 // If there's only 1 security update and it has the same version we're 116 // recommending, give it the same CSS class as if it was recommended, 117 // but don't print out a separate "Recommended" line for this project. 118 if (!empty($project['security updates']) && count($project['security updates']) == 1 && $project['security updates'][0]['version'] === $project['recommended']) { 119 $security_class[] = 'version-recommended'; 120 $security_class[] = 'version-recommended-strong'; 121 } 122 else { 123 $version_class[] = 'version-recommended'; 124 // Apply an extra class if we're displaying both a recommended 125 // version and anything else for an extra visual hint. 126 if ($project['recommended'] !== $project['latest_version'] 127 || !empty($project['also']) 128 || ($project['install_type'] == 'dev' 129 && isset($project['dev_version']) 130 && $project['latest_version'] !== $project['dev_version'] 131 && $project['recommended'] !== $project['dev_version']) 132 || (isset($project['security updates'][0]) 133 && $project['recommended'] !== $project['security updates'][0]) 134 ) { 135 $version_class[] = 'version-recommended-strong'; 136 } 137 $versions_inner .= theme('update_version', array('version' => $project['releases'][$project['recommended']], 'tag' => t('Recommended version:'), 'class' => $version_class)); 138 } 139 140 // Now, print any security updates. 141 if (!empty($project['security updates'])) { 142 $security_class[] = 'version-security'; 143 foreach ($project['security updates'] as $security_update) { 144 $versions_inner .= theme('update_version', array('version' => $security_update, 'tag' => t('Security update:'), 'class' => $security_class)); 145 } 146 } 147 } 148 149 if ($project['recommended'] !== $project['latest_version']) { 150 $versions_inner .= theme('update_version', array('version' => $project['releases'][$project['latest_version']], 'tag' => t('Latest version:'), 'class' => array('version-latest'))); 151 } 152 if ($project['install_type'] == 'dev' 153 && $project['status'] != UPDATE_CURRENT 154 && isset($project['dev_version']) 155 && $project['recommended'] !== $project['dev_version']) { 156 $versions_inner .= theme('update_version', array('version' => $project['releases'][$project['dev_version']], 'tag' => t('Development version:'), 'class' => array('version-latest'))); 157 } 158 } 159 160 if (isset($project['also'])) { 161 foreach ($project['also'] as $also) { 162 $versions_inner .= theme('update_version', array('version' => $project['releases'][$also], 'tag' => t('Also available:'), 'class' => array('version-also-available'))); 163 } 164 } 165 166 if (!empty($versions_inner)) { 167 $row .= "<div class=\"versions\">\n" . $versions_inner . "</div>\n"; 168 } 169 $row .= "<div class=\"info\">\n"; 170 if (!empty($project['extra'])) { 171 $row .= '<div class="extra">' . "\n"; 172 foreach ($project['extra'] as $key => $value) { 173 $row .= '<div class="' . implode(' ', $value['class']) . '">'; 174 $row .= check_plain($value['label']) . ': '; 175 $row .= drupal_placeholder($value['data']); 176 $row .= "</div>\n"; 177 } 178 $row .= "</div>\n"; // extra div. 179 } 180 181 $row .= '<div class="includes">'; 182 sort($project['includes']); 183 if (!empty($project['disabled'])) { 184 sort($project['disabled']); 185 // Make sure we start with a clean slate for each project in the report. 186 $includes_items = array(); 187 $row .= t('Includes:'); 188 $includes_items[] = t('Enabled: %includes', array('%includes' => implode(', ', $project['includes']))); 189 $includes_items[] = t('Disabled: %disabled', array('%disabled' => implode(', ', $project['disabled']))); 190 $row .= theme('item_list', array('items' => $includes_items)); 191 } 192 else { 193 $row .= t('Includes: %includes', array('%includes' => implode(', ', $project['includes']))); 194 } 195 $row .= "</div>\n"; 196 197 if (!empty($project['base_themes'])) { 198 $row .= '<div class="basethemes">'; 199 asort($project['base_themes']); 200 $base_themes = array(); 201 foreach ($project['base_themes'] as $base_key => $base_theme) { 202 switch ($status[$base_key]) { 203 case UPDATE_NOT_SECURE: 204 case UPDATE_REVOKED: 205 case UPDATE_NOT_SUPPORTED: 206 $base_themes[] = t('%base_theme (!base_label)', array('%base_theme' => $base_theme, '!base_label' => theme('update_status_label', array('status' => $status[$base_key])))); 207 break; 208 209 default: 210 $base_themes[] = drupal_placeholder($base_theme); 211 } 212 } 213 $row .= t('Depends on: !basethemes', array('!basethemes' => implode(', ', $base_themes))); 214 $row .= "</div>\n"; 215 } 216 217 if (!empty($project['sub_themes'])) { 218 $row .= '<div class="subthemes">'; 219 sort($project['sub_themes']); 220 $row .= t('Required by: %subthemes', array('%subthemes' => implode(', ', $project['sub_themes']))); 221 $row .= "</div>\n"; 222 } 223 224 $row .= "</div>\n"; // info div. 225 226 if (!isset($rows[$project['project_type']])) { 227 $rows[$project['project_type']] = array(); 228 } 229 $row_key = isset($project['title']) ? drupal_strtolower($project['title']) : drupal_strtolower($project['name']); 230 $rows[$project['project_type']][$row_key] = array( 231 'class' => array($class), 232 'data' => array($row), 233 ); 234 } 235 236 $project_types = array( 237 'core' => t('Drupal core'), 238 'module' => t('Modules'), 239 'theme' => t('Themes'), 240 'module-disabled' => t('Disabled modules'), 241 'theme-disabled' => t('Disabled themes'), 242 ); 243 foreach ($project_types as $type_name => $type_label) { 244 if (!empty($rows[$type_name])) { 245 ksort($rows[$type_name]); 246 $output .= "\n<h3>" . $type_label . "</h3>\n"; 247 $output .= theme('table', array('header' => $header, 'rows' => $rows[$type_name], 'attributes' => array('class' => array('update')))); 248 } 249 } 250 drupal_add_css(drupal_get_path('module', 'update') . '/update.css'); 251 return $output; 252 } 253 254 /** 255 * Returns HTML for a label to display for a project's update status. 256 * 257 * @param array $variables 258 * An associative array containing: 259 * - status: The integer code for a project's current update status. 260 * 261 * @see update_calculate_project_data() 262 * @ingroup themeable 263 */ 264 function theme_update_status_label($variables) { 265 switch ($variables['status']) { 266 case UPDATE_NOT_SECURE: 267 return '<span class="security-error">' . t('Security update required!') . '</span>'; 268 269 case UPDATE_REVOKED: 270 return '<span class="revoked">' . t('Revoked!') . '</span>'; 271 272 case UPDATE_NOT_SUPPORTED: 273 return '<span class="not-supported">' . t('Not supported!') . '</span>'; 274 275 case UPDATE_NOT_CURRENT: 276 return '<span class="not-current">' . t('Update available') . '</span>'; 277 278 case UPDATE_CURRENT: 279 return '<span class="current">' . t('Up to date') . '</span>'; 280 281 } 282 } 283 284 /** 285 * Returns HTML for the version display of a project. 286 * 287 * @param array $variables 288 * An associative array containing: 289 * - version: An array of data about the latest released version, containing: 290 * - version: The version number. 291 * - release_link: The URL for the release notes. 292 * - date: The date of the release. 293 * - download_link: The URL for the downloadable file. 294 * - tag: The title of the project. 295 * - class: A string containing extra classes for the wrapping table. 296 * 297 * @ingroup themeable 298 */ 299 function theme_update_version($variables) { 300 $version = $variables['version']; 301 $tag = $variables['tag']; 302 $class = implode(' ', $variables['class']); 303 304 $output = ''; 305 $output .= '<table class="version ' . $class . '">'; 306 $output .= '<tr>'; 307 $output .= '<td class="version-title">' . $tag . "</td>\n"; 308 $output .= '<td class="version-details">'; 309 $output .= l($version['version'], $version['release_link']); 310 $output .= ' <span class="version-date">(' . format_date($version['date'], 'custom', 'Y-M-d') . ')</span>'; 311 $output .= "</td>\n"; 312 $output .= '<td class="version-links">'; 313 $links = array(); 314 $links['update-download'] = array( 315 'title' => t('Download'), 316 'href' => $version['download_link'], 317 ); 318 $links['update-release-notes'] = array( 319 'title' => t('Release notes'), 320 'href' => $version['release_link'], 321 ); 322 $output .= theme('links__update_version', array('links' => $links)); 323 $output .= '</td>'; 324 $output .= '</tr>'; 325 $output .= "</table>\n"; 326 return $output; 327 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title