update.report.inc 9.2 KB

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