update.report.inc 11 KB

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