update.report.inc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <?php
  2. /**
  3. * @file
  4. * Code required only when rendering the available updates report.
  5. */
  6. use Drupal\Core\Template\Attribute;
  7. use Drupal\Core\Url;
  8. /**
  9. * Prepares variables for project status report templates.
  10. *
  11. * Default template: update-report.html.twig.
  12. *
  13. * @param array $variables
  14. * An associative array containing:
  15. * - data: An array of data about each project's status.
  16. */
  17. function template_preprocess_update_report(&$variables) {
  18. $data = $variables['data'];
  19. $last = \Drupal::state()->get('update.last_check') ?: 0;
  20. $variables['last_checked'] = [
  21. '#theme' => 'update_last_check',
  22. '#last' => $last,
  23. // Attach the library to a variable that gets printed always.
  24. '#attached' => [
  25. 'library' => [
  26. 'update/drupal.update.admin',
  27. ],
  28. ],
  29. ];
  30. // For no project update data, populate no data message.
  31. if (empty($data)) {
  32. $variables['no_updates_message'] = _update_no_data();
  33. }
  34. $rows = [];
  35. foreach ($data as $project) {
  36. $project_status = [
  37. '#theme' => 'update_project_status',
  38. '#project' => $project,
  39. ];
  40. // Build project rows.
  41. if (!isset($rows[$project['project_type']])) {
  42. $rows[$project['project_type']] = [
  43. '#type' => 'table',
  44. '#attributes' => ['class' => ['update']],
  45. ];
  46. }
  47. $row_key = !empty($project['title']) ? mb_strtolower($project['title']) : mb_strtolower($project['name']);
  48. // Add the project status row and details.
  49. $rows[$project['project_type']][$row_key]['status'] = $project_status;
  50. // Add project status class attribute to the table row.
  51. switch ($project['status']) {
  52. case UPDATE_CURRENT:
  53. $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-success']];
  54. break;
  55. case UPDATE_UNKNOWN:
  56. case UPDATE_FETCH_PENDING:
  57. case UPDATE_NOT_FETCHED:
  58. case UPDATE_NOT_SECURE:
  59. case UPDATE_REVOKED:
  60. case UPDATE_NOT_SUPPORTED:
  61. $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-error']];
  62. break;
  63. case UPDATE_NOT_CHECKED:
  64. case UPDATE_NOT_CURRENT:
  65. default:
  66. $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-warning']];
  67. break;
  68. }
  69. }
  70. $project_types = [
  71. 'core' => t('Drupal core'),
  72. 'module' => t('Modules'),
  73. 'theme' => t('Themes'),
  74. 'module-disabled' => t('Uninstalled modules'),
  75. 'theme-disabled' => t('Uninstalled themes'),
  76. ];
  77. $variables['project_types'] = [];
  78. foreach ($project_types as $type_name => $type_label) {
  79. if (!empty($rows[$type_name])) {
  80. ksort($rows[$type_name]);
  81. $variables['project_types'][] = [
  82. 'label' => $type_label,
  83. 'table' => $rows[$type_name],
  84. ];
  85. }
  86. }
  87. }
  88. /**
  89. * Prepares variables for update project status templates.
  90. *
  91. * Default template: update-project-status.html.twig.
  92. *
  93. * @param array $variables
  94. * An associative array containing:
  95. * - project: An array of information about the project.
  96. */
  97. function template_preprocess_update_project_status(&$variables) {
  98. // Storing by reference because we are sorting the project values.
  99. $project = &$variables['project'];
  100. // Set the project title and URL.
  101. $variables['title'] = (isset($project['title'])) ? $project['title'] : $project['name'];
  102. $variables['url'] = (isset($project['link'])) ? Url::fromUri($project['link'])->toString() : NULL;
  103. $variables['install_type'] = $project['install_type'];
  104. if ($project['install_type'] == 'dev' && !empty($project['datestamp'])) {
  105. $variables['datestamp'] = format_date($project['datestamp'], 'custom', 'Y-M-d');
  106. }
  107. $variables['existing_version'] = $project['existing_version'];
  108. $versions_inner = [];
  109. $security_class = [];
  110. $version_class = [];
  111. if (isset($project['recommended'])) {
  112. if ($project['status'] != UPDATE_CURRENT || $project['existing_version'] !== $project['recommended']) {
  113. // First, figure out what to recommend.
  114. // If there's only 1 security update and it has the same version we're
  115. // recommending, give it the same CSS class as if it was recommended,
  116. // but don't print out a separate "Recommended" line for this project.
  117. if (!empty($project['security updates'])
  118. && count($project['security updates']) == 1
  119. && $project['security updates'][0]['version'] === $project['recommended']
  120. ) {
  121. $security_class[] = 'project-update__version--recommended';
  122. $security_class[] = 'project-update__version---strong';
  123. }
  124. else {
  125. $version_class[] = 'project-update__version--recommended';
  126. // Apply an extra class if we're displaying both a recommended
  127. // version and anything else for an extra visual hint.
  128. if ($project['recommended'] !== $project['latest_version']
  129. || !empty($project['also'])
  130. || ($project['install_type'] == 'dev'
  131. && isset($project['dev_version'])
  132. && $project['latest_version'] !== $project['dev_version']
  133. && $project['recommended'] !== $project['dev_version'])
  134. || (isset($project['security updates'][0])
  135. && $project['recommended'] !== $project['security updates'][0])
  136. ) {
  137. $version_class[] = 'project-update__version--recommended-strong';
  138. }
  139. $versions_inner[] = [
  140. '#theme' => 'update_version',
  141. '#version' => $project['releases'][$project['recommended']],
  142. '#title' => t('Recommended version:'),
  143. '#attributes' => ['class' => $version_class],
  144. ];
  145. }
  146. // Now, print any security updates.
  147. if (!empty($project['security updates'])) {
  148. $security_class[] = 'version-security';
  149. foreach ($project['security updates'] as $security_update) {
  150. $versions_inner[] = [
  151. '#theme' => 'update_version',
  152. '#version' => $security_update,
  153. '#title' => t('Security update:'),
  154. '#attributes' => ['class' => $security_class],
  155. ];
  156. }
  157. }
  158. }
  159. if ($project['recommended'] !== $project['latest_version']) {
  160. $versions_inner[] = [
  161. '#theme' => 'update_version',
  162. '#version' => $project['releases'][$project['latest_version']],
  163. '#title' => t('Latest version:'),
  164. '#attributes' => ['class' => ['version-latest']],
  165. ];
  166. }
  167. if ($project['install_type'] == 'dev'
  168. && $project['status'] != UPDATE_CURRENT
  169. && isset($project['dev_version'])
  170. && $project['recommended'] !== $project['dev_version']) {
  171. $versions_inner[] = [
  172. '#theme' => 'update_version',
  173. '#version' => $project['releases'][$project['dev_version']],
  174. '#title' => t('Development version:'),
  175. '#attributes' => ['class' => ['version-latest']],
  176. ];
  177. }
  178. }
  179. if (isset($project['also'])) {
  180. foreach ($project['also'] as $also) {
  181. $versions_inner[] = [
  182. '#theme' => 'update_version',
  183. '#version' => $project['releases'][$also],
  184. '#title' => t('Also available:'),
  185. '#attributes' => ['class' => ['version-also-available']],
  186. ];
  187. }
  188. }
  189. if (!empty($versions_inner)) {
  190. $variables['versions'] = $versions_inner;
  191. }
  192. if (!empty($project['disabled'])) {
  193. sort($project['disabled']);
  194. $variables['disabled'] = $project['disabled'];
  195. }
  196. sort($project['includes']);
  197. $variables['includes'] = $project['includes'];
  198. $variables['extras'] = [];
  199. if (!empty($project['extra'])) {
  200. foreach ($project['extra'] as $value) {
  201. $extra_item = [];
  202. $extra_item['attributes'] = new Attribute();
  203. $extra_item['label'] = $value['label'];
  204. $extra_item['data'] = [
  205. '#prefix' => '<em>',
  206. '#markup' => $value['data'],
  207. '#suffix' => '</em>',
  208. ];
  209. $variables['extras'][] = $extra_item;
  210. }
  211. }
  212. // Set the project status details.
  213. $status_label = NULL;
  214. switch ($project['status']) {
  215. case UPDATE_NOT_SECURE:
  216. $status_label = t('Security update required!');
  217. break;
  218. case UPDATE_REVOKED:
  219. $status_label = t('Revoked!');
  220. break;
  221. case UPDATE_NOT_SUPPORTED:
  222. $status_label = t('Not supported!');
  223. break;
  224. case UPDATE_NOT_CURRENT:
  225. $status_label = t('Update available');
  226. break;
  227. case UPDATE_CURRENT:
  228. $status_label = t('Up to date');
  229. break;
  230. }
  231. $variables['status']['label'] = $status_label;
  232. $variables['status']['attributes'] = new Attribute();
  233. $variables['status']['reason'] = (isset($project['reason'])) ? $project['reason'] : NULL;
  234. switch ($project['status']) {
  235. case UPDATE_CURRENT:
  236. $uri = 'core/misc/icons/73b355/check.svg';
  237. $text = t('Ok');
  238. break;
  239. case UPDATE_UNKNOWN:
  240. case UPDATE_FETCH_PENDING:
  241. case UPDATE_NOT_FETCHED:
  242. $uri = 'core/misc/icons/e29700/warning.svg';
  243. $text = t('Warning');
  244. break;
  245. case UPDATE_NOT_SECURE:
  246. case UPDATE_REVOKED:
  247. case UPDATE_NOT_SUPPORTED:
  248. $uri = 'core/misc/icons/e32700/error.svg';
  249. $text = t('Error');
  250. break;
  251. case UPDATE_NOT_CHECKED:
  252. case UPDATE_NOT_CURRENT:
  253. default:
  254. $uri = 'core/misc/icons/e29700/warning.svg';
  255. $text = t('Warning');
  256. break;
  257. }
  258. $variables['status']['icon'] = [
  259. '#theme' => 'image',
  260. '#width' => 18,
  261. '#height' => 18,
  262. '#uri' => $uri,
  263. '#alt' => $text,
  264. '#title' => $text,
  265. ];
  266. }