views.install 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. <?php
  2. /**
  3. * @file
  4. * Contains install and update functions for Views.
  5. */
  6. /**
  7. * Implements hook_install().
  8. */
  9. function views_install() {
  10. module_set_weight('views', 10);
  11. }
  12. /**
  13. * Update views field plugins.
  14. */
  15. function views_update_8001(&$sandbox) {
  16. $config_factory = \Drupal::configFactory();
  17. $ids = [];
  18. $message = NULL;
  19. $ago_formats = [
  20. 'time ago',
  21. 'time hence',
  22. 'time span',
  23. 'raw time ago',
  24. 'raw time hence',
  25. 'raw time span',
  26. 'inverse time span',
  27. ];
  28. foreach ($config_factory->listAll('views.view.') as $view_config_name) {
  29. $view = $config_factory->getEditable($view_config_name);
  30. $displays = $view->get('display');
  31. foreach ($displays as $display_name => $display) {
  32. if (!empty($display['display_options']['fields'])) {
  33. foreach ($display['display_options']['fields'] as $field_name => $field) {
  34. if (isset($field['entity_type']) && $field['plugin_id'] === 'date') {
  35. $ids[] = $view->get('id');
  36. // Grab the settings we need to move to a different place in the
  37. // config schema.
  38. $date_format = !empty($field['date_format']) ? $field['date_format'] : 'medium';
  39. $custom_date_format = !empty($field['custom_date_format']) ? $field['custom_date_format'] : '';
  40. $timezone = !empty($field['timezone']) ? $field['timezone'] : '';
  41. // Save off the base part of the config path we are updating.
  42. $base = "display.$display_name.display_options.fields.$field_name";
  43. if (in_array($date_format, $ago_formats)) {
  44. // Update the field to use the Field API formatter.
  45. $view->set($base . '.plugin_id', 'field');
  46. $view->set($base . '.type', 'timestamp_ago');
  47. // Ensure the granularity is an integer, which is defined in the
  48. // field.formatter.settings.timestamp_ago schema.
  49. $granularity = is_numeric($custom_date_format) ? (int) $custom_date_format : 2;
  50. // Add the new settings.
  51. if ($date_format === 'time ago' || $date_format === 'time hence' || $date_format === 'time span') {
  52. $view->set($base . '.settings.future_format', '@interval hence');
  53. $view->set($base . '.settings.past_format', '@interval ago');
  54. $view->set($base . '.settings.granularity', $granularity);
  55. }
  56. elseif ($date_format === 'raw time ago' || $date_format === 'raw time hence') {
  57. $view->set($base . '.settings.future_format', '@interval');
  58. $view->set($base . '.settings.past_format', '@interval');
  59. $view->set($base . '.settings.granularity', $granularity);
  60. }
  61. elseif ($date_format === 'raw time span') {
  62. $view->set($base . '.settings.future_format', '@interval');
  63. $view->set($base . '.settings.past_format', '-@interval');
  64. $view->set($base . '.settings.granularity', $granularity);
  65. }
  66. elseif ($date_format === 'inverse time span') {
  67. $view->set($base . '.settings.future_format', '-@interval');
  68. $view->set($base . '.settings.past_format', '@interval');
  69. $view->set($base . '.settings.granularity', $granularity);
  70. }
  71. }
  72. else {
  73. // Update the field to use the Field API formatter.
  74. $view->set($base . '.plugin_id', 'field');
  75. $view->set($base . '.type', 'timestamp');
  76. // Add the new settings, and make sure everything is a string
  77. // to conform with the field.formatter.settings.timestamp schema.
  78. $view->set($base . '.settings.date_format', (string) $date_format);
  79. $view->set($base . '.settings.custom_date_format', (string) $custom_date_format);
  80. $view->set($base . '.settings.timezone', (string) $timezone);
  81. }
  82. // Remove the old settings.
  83. $view->clear($base . '.date_format');
  84. $view->clear($base . '.custom_date_format');
  85. $view->clear($base . '.timezone');
  86. }
  87. }
  88. }
  89. }
  90. $view->save(TRUE);
  91. }
  92. if (!empty($ids)) {
  93. $message = \Drupal::translation()->translate('Updated field plugins for views: @ids', ['@ids' => implode(', ', array_unique($ids))]);
  94. }
  95. return $message;
  96. }
  97. /**
  98. * Updates %1 and !1 tokens to argument tokens.
  99. */
  100. function views_update_8002() {
  101. $config_factory = \Drupal::configFactory();
  102. foreach ($config_factory->listAll('views.view.') as $view_config_name) {
  103. $view = $config_factory->getEditable($view_config_name);
  104. $displays = $view->get('display');
  105. $argument_map_per_display = _views_update_argument_map($displays);
  106. $changed = FALSE;
  107. // Update all the field settings, which support tokens.
  108. foreach ($displays as $display_name => &$display) {
  109. if (!empty($display['display_options']['fields'])) {
  110. $token_values = [
  111. 'path',
  112. 'alt',
  113. 'link_class',
  114. 'rel',
  115. 'target',
  116. 'query',
  117. 'fragment',
  118. 'prefix',
  119. 'suffix',
  120. 'more_link_text',
  121. 'more_link_path',
  122. 'link_attributes',
  123. 'text',
  124. ];
  125. foreach ($display['display_options']['fields'] as $field_name => &$field) {
  126. foreach ($token_values as $token_name) {
  127. if (!empty($field['alter'][$token_name])) {
  128. if (is_array($field['alter'][$token_name])) {
  129. foreach (array_keys($field['alter'][$token_name]) as $key) {
  130. $field['alter'][$token_name][$key] = _views_update_8002_token_update($field['alter'][$token_name][$key], $argument_map_per_display[$display_name]);
  131. $changed = TRUE;
  132. }
  133. }
  134. else {
  135. $field['alter'][$token_name] = _views_update_8002_token_update($field['alter'][$token_name], $argument_map_per_display[$display_name]);
  136. $changed = TRUE;
  137. }
  138. }
  139. }
  140. }
  141. }
  142. }
  143. // Update the area handlers with tokens.
  144. foreach ($displays as $display_name => &$display) {
  145. $area_types = ['header', 'footer', 'empty'];
  146. foreach ($area_types as $area_type) {
  147. if (!empty($display['display_options'][$area_type])) {
  148. foreach ($display['display_options'][$area_type] as &$area) {
  149. switch ($area['plugin_id']) {
  150. case 'title':
  151. $area['title'] = _views_update_8002_token_update($area['title'], $argument_map_per_display[$display_name]);
  152. $changed = TRUE;
  153. break;
  154. case 'result':
  155. $area['content'] = _views_update_8002_token_update($area['content'], $argument_map_per_display[$display_name]);
  156. $changed = TRUE;
  157. break;
  158. case 'text':
  159. $area['content']['value'] = _views_update_8002_token_update($area['content']['value'], $argument_map_per_display[$display_name]);
  160. $changed = TRUE;
  161. break;
  162. case 'text_custom':
  163. $area['content'] = _views_update_8002_token_update($area['content'], $argument_map_per_display[$display_name]);
  164. $changed = TRUE;
  165. break;
  166. case 'entity':
  167. $area['target'] = _views_update_8002_token_update($area['target'], $argument_map_per_display[$display_name]);
  168. $changed = TRUE;
  169. break;
  170. }
  171. }
  172. }
  173. }
  174. }
  175. // Update the argument title settings.
  176. foreach ($displays as $display_name => &$display) {
  177. if (!empty($display['display_options']['arguments'])) {
  178. foreach ($display['display_options']['arguments'] as &$argument) {
  179. if (isset($argument['exception']['title'])) {
  180. $argument['exception']['title'] = _views_update_8002_token_update($argument['exception']['title'], $argument_map_per_display[$display_name]);
  181. $changed = TRUE;
  182. }
  183. if (isset($argument['title'])) {
  184. $argument['title'] = _views_update_8002_token_update($argument['title'], $argument_map_per_display[$display_name]);
  185. $changed = TRUE;
  186. }
  187. }
  188. }
  189. }
  190. // Update the display title settings.
  191. // Update the more link text and more link URL.
  192. foreach ($displays as $display_name => &$display) {
  193. if (!empty($display['display_options']['title'])) {
  194. $display['display_options']['title'] = _views_update_8002_token_update($display['display_options']['title'], $argument_map_per_display[$display_name]);
  195. $changed = TRUE;
  196. }
  197. if (!empty($display['display_options']['use_more_text'])) {
  198. $display['display_options']['use_more_text'] = _views_update_8002_token_update($display['display_options']['use_more_text'], $argument_map_per_display[$display_name]);
  199. $changed = TRUE;
  200. }
  201. if (!empty($display['display_options']['link_url'])) {
  202. $display['display_options']['link_url'] = _views_update_8002_token_update($display['display_options']['link_url'], $argument_map_per_display[$display_name]);
  203. $changed = TRUE;
  204. }
  205. }
  206. // Update custom classes for row class + grid classes.
  207. // Update RSS description field.
  208. foreach ($displays as $display_name => &$display) {
  209. if (!empty($display['display_options']['style'])) {
  210. if (!empty($display['display_options']['style']['options']['row_class_custom'])) {
  211. $display['display_options']['style']['options']['row_class_custom'] = _views_update_8002_token_update($display['display_options']['style']['options']['row_class_custom'], $argument_map_per_display[$display_name]);
  212. $changed = TRUE;
  213. }
  214. if (!empty($display['display_options']['style']['options']['col_class_custom'])) {
  215. $display['display_options']['style']['options']['col_class_custom'] = _views_update_8002_token_update($display['display_options']['style']['options']['col_class_custom'], $argument_map_per_display[$display_name]);
  216. $changed = TRUE;
  217. }
  218. if (!empty($display['display_options']['style']['options']['description'])) {
  219. $display['display_options']['style']['options']['description'] = _views_update_8002_token_update($display['display_options']['style']['options']['description'], $argument_map_per_display[$display_name]);
  220. $changed = TRUE;
  221. }
  222. }
  223. }
  224. if ($changed) {
  225. $view->set('display', $displays);
  226. $view->save(TRUE);
  227. }
  228. }
  229. }
  230. /**
  231. * Updates a views configuration string from using %/! to twig tokens.
  232. *
  233. * @param string $text
  234. * Text in which to search for argument tokens and replace them with their
  235. * twig representation.
  236. * @param array $argument_map
  237. * A map of argument machine names keyed by their previous index.
  238. *
  239. * @return string
  240. * The updated token.
  241. */
  242. function _views_update_8002_token_update($text, array $argument_map) {
  243. $text = preg_replace_callback('/%(\d)/', function ($match) use ($argument_map) {
  244. return "{{ arguments.{$argument_map[$match[1]]} }}";
  245. }, $text);
  246. $text = preg_replace_callback('/!(\d)/', function ($match) use ($argument_map) {
  247. return "{{ raw_arguments.{$argument_map[$match[1]]} }}";
  248. }, $text);
  249. return $text;
  250. }
  251. /**
  252. * Builds an argument map for each Views display.
  253. *
  254. * @param array $displays
  255. * A list of Views displays.
  256. *
  257. * @return array
  258. * The argument map keyed by display id.
  259. */
  260. function _views_update_argument_map($displays) {
  261. $argument_map = [];
  262. foreach ($displays as $display_id => $display) {
  263. $argument_map[$display_id] = [];
  264. if (isset($display['display_options']['arguments'])) {
  265. foreach (array_keys($display['display_options']['arguments']) as $number => $name) {
  266. $argument_map[$display_id][$number + 1] = $name;
  267. }
  268. }
  269. elseif (isset($displays['default']['display_options']['arguments'])) {
  270. foreach (array_keys($displays['default']['display_options']['arguments']) as $number => $name) {
  271. $argument_map[$display_id][$number + 1] = $name;
  272. }
  273. }
  274. }
  275. return $argument_map;
  276. }
  277. /**
  278. * Clear caches to fix entity operations field.
  279. */
  280. function views_update_8003() {
  281. // Empty update to cause a cache flush so that views data is rebuilt. Entity
  282. // types that don't implement a list builder cannot have the entity operations
  283. // field.
  284. // Use hook_post_update_NAME() instead to clear the cache.The use
  285. // of hook_update_N to clear the cache has been deprecated see
  286. // https://www.drupal.org/node/2960601 for more details.
  287. }
  288. /**
  289. * Clear caches due to updated entity views data.
  290. */
  291. function views_update_8004() {
  292. // Empty update to cause a cache flush so that views data is rebuilt.
  293. // Use hook_post_update_NAME() instead to clear the cache.The use
  294. // of hook_update_N to clear the cache has been deprecated see
  295. // https://www.drupal.org/node/2960601 for more details.
  296. }
  297. /**
  298. * Clear views data cache.
  299. */
  300. function views_update_8005() {
  301. // Empty update function to rebuild the views data.
  302. // Use hook_post_update_NAME() instead to clear the cache.The use
  303. // of hook_update_N to clear the cache has been deprecated see
  304. // https://www.drupal.org/node/2960601 for more details.
  305. }
  306. /**
  307. * Clear caches due to updated entity views data.
  308. */
  309. function views_update_8100() {
  310. // Empty update to cause a cache flush so that views data is rebuilt.
  311. // Use hook_post_update_NAME() instead to clear the cache.The use
  312. // of hook_update_N to clear the cache has been deprecated see
  313. // https://www.drupal.org/node/2960601 for more details.
  314. }
  315. /**
  316. * Set default values for enabled/expanded flag on page displays.
  317. */
  318. function views_update_8101() {
  319. $config_factory = \Drupal::configFactory();
  320. foreach ($config_factory->listAll('views.view.') as $view_config_name) {
  321. $view = $config_factory->getEditable($view_config_name);
  322. $save = FALSE;
  323. foreach ($view->get('display') as $display_id => $display) {
  324. if ($display['display_plugin'] == 'page') {
  325. $display['display_options']['menu']['enabled'] = TRUE;
  326. $display['display_options']['menu']['expanded'] = FALSE;
  327. $view->set("display.$display_id", $display);
  328. $save = TRUE;
  329. }
  330. }
  331. if ($save) {
  332. $view->save();
  333. }
  334. }
  335. }
  336. /**
  337. * Rebuild the container to add a new container parameter.
  338. */
  339. function views_update_8200() {
  340. // Empty update to cause a cache rebuild so that the container is rebuilt.
  341. // Use hook_post_update_NAME() instead to clear the cache.The use
  342. // of hook_update_N to clear the cache has been deprecated see
  343. // https://www.drupal.org/node/2960601 for more details.
  344. }
  345. /**
  346. * Rebuild cache to refresh the views config schema.
  347. */
  348. function views_update_8201() {
  349. // Empty update to cause a cache rebuild so that config schema get refreshed.
  350. // Use hook_post_update_NAME() instead to clear the cache.The use
  351. // of hook_update_N to clear the cache has been deprecated see
  352. // https://www.drupal.org/node/2960601 for more details.
  353. }
  354. /**
  355. * Update field names for multi-value base fields.
  356. */
  357. function views_update_8500() {
  358. // This update has been replaced by
  359. // views_post_update_field_names_for_multivalue_fields().
  360. }