listAll('views.view.') as $view_config_name) { $view = $config_factory->getEditable($view_config_name); $displays = $view->get('display'); foreach ($displays as $display_name => $display) { if (!empty($display['display_options']['fields'])) { foreach ($display['display_options']['fields'] as $field_name => $field) { if (isset($field['entity_type']) && $field['plugin_id'] === 'date') { $ids[] = $view->get('id'); // Grab the settings we need to move to a different place in the // config schema. $date_format = !empty($field['date_format']) ? $field['date_format'] : 'medium'; $custom_date_format = !empty($field['custom_date_format']) ? $field['custom_date_format'] : ''; $timezone = !empty($field['timezone']) ? $field['timezone'] : ''; // Save off the base part of the config path we are updating. $base = "display.$display_name.display_options.fields.$field_name"; if (in_array($date_format, $ago_formats)) { // Update the field to use the Field API formatter. $view->set($base . '.plugin_id', 'field'); $view->set($base . '.type', 'timestamp_ago'); // Ensure the granularity is an integer, which is defined in the // field.formatter.settings.timestamp_ago schema. $granularity = is_numeric($custom_date_format) ? (int) $custom_date_format : 2; // Add the new settings. if ($date_format === 'time ago' || $date_format === 'time hence' || $date_format === 'time span') { $view->set($base . '.settings.future_format', '@interval hence'); $view->set($base . '.settings.past_format', '@interval ago'); $view->set($base . '.settings.granularity', $granularity); } elseif ($date_format === 'raw time ago' || $date_format === 'raw time hence') { $view->set($base . '.settings.future_format', '@interval'); $view->set($base . '.settings.past_format', '@interval'); $view->set($base . '.settings.granularity', $granularity); } elseif ($date_format === 'raw time span') { $view->set($base . '.settings.future_format', '@interval'); $view->set($base . '.settings.past_format', '-@interval'); $view->set($base . '.settings.granularity', $granularity); } elseif ($date_format === 'inverse time span') { $view->set($base . '.settings.future_format', '-@interval'); $view->set($base . '.settings.past_format', '@interval'); $view->set($base . '.settings.granularity', $granularity); } } else { // Update the field to use the Field API formatter. $view->set($base . '.plugin_id', 'field'); $view->set($base . '.type', 'timestamp'); // Add the new settings, and make sure everything is a string // to conform with the field.formatter.settings.timestamp schema. $view->set($base . '.settings.date_format', (string) $date_format); $view->set($base . '.settings.custom_date_format', (string) $custom_date_format); $view->set($base . '.settings.timezone', (string) $timezone); } // Remove the old settings. $view->clear($base . '.date_format'); $view->clear($base . '.custom_date_format'); $view->clear($base . '.timezone'); } } } } $view->save(TRUE); } if (!empty($ids)) { $message = \Drupal::translation()->translate('Updated field plugins for views: @ids', ['@ids' => implode(', ', array_unique($ids))]); } return $message; } /** * Updates %1 and !1 tokens to argument tokens. */ function views_update_8002() { $config_factory = \Drupal::configFactory(); foreach ($config_factory->listAll('views.view.') as $view_config_name) { $view = $config_factory->getEditable($view_config_name); $displays = $view->get('display'); $argument_map_per_display = _views_update_argument_map($displays); $changed = FALSE; // Update all the field settings, which support tokens. foreach ($displays as $display_name => &$display) { if (!empty($display['display_options']['fields'])) { $token_values = [ 'path', 'alt', 'link_class', 'rel', 'target', 'query', 'fragment', 'prefix', 'suffix', 'more_link_text', 'more_link_path', 'link_attributes', 'text', ]; foreach ($display['display_options']['fields'] as $field_name => &$field) { foreach ($token_values as $token_name) { if (!empty($field['alter'][$token_name])) { if (is_array($field['alter'][$token_name])) { foreach (array_keys($field['alter'][$token_name]) as $key) { $field['alter'][$token_name][$key] = _views_update_8002_token_update($field['alter'][$token_name][$key], $argument_map_per_display[$display_name]); $changed = TRUE; } } else { $field['alter'][$token_name] = _views_update_8002_token_update($field['alter'][$token_name], $argument_map_per_display[$display_name]); $changed = TRUE; } } } } } } // Update the area handlers with tokens. foreach ($displays as $display_name => &$display) { $area_types = ['header', 'footer', 'empty']; foreach ($area_types as $area_type) { if (!empty($display['display_options'][$area_type])) { foreach ($display['display_options'][$area_type] as &$area) { switch ($area['plugin_id']) { case 'title': $area['title'] = _views_update_8002_token_update($area['title'], $argument_map_per_display[$display_name]); $changed = TRUE; break; case 'result': $area['content'] = _views_update_8002_token_update($area['content'], $argument_map_per_display[$display_name]); $changed = TRUE; break; case 'text': $area['content']['value'] = _views_update_8002_token_update($area['content']['value'], $argument_map_per_display[$display_name]); $changed = TRUE; break; case 'text_custom': $area['content'] = _views_update_8002_token_update($area['content'], $argument_map_per_display[$display_name]); $changed = TRUE; break; case 'entity': $area['target'] = _views_update_8002_token_update($area['target'], $argument_map_per_display[$display_name]); $changed = TRUE; break; } } } } } // Update the argument title settings. foreach ($displays as $display_name => &$display) { if (!empty($display['display_options']['arguments'])) { foreach ($display['display_options']['arguments'] as &$argument) { if (isset($argument['exception']['title'])) { $argument['exception']['title'] = _views_update_8002_token_update($argument['exception']['title'], $argument_map_per_display[$display_name]); $changed = TRUE; } if (isset($argument['title'])) { $argument['title'] = _views_update_8002_token_update($argument['title'], $argument_map_per_display[$display_name]); $changed = TRUE; } } } } // Update the display title settings. // Update the more link text and more link URL. foreach ($displays as $display_name => &$display) { if (!empty($display['display_options']['title'])) { $display['display_options']['title'] = _views_update_8002_token_update($display['display_options']['title'], $argument_map_per_display[$display_name]); $changed = TRUE; } if (!empty($display['display_options']['use_more_text'])) { $display['display_options']['use_more_text'] = _views_update_8002_token_update($display['display_options']['use_more_text'], $argument_map_per_display[$display_name]); $changed = TRUE; } if (!empty($display['display_options']['link_url'])) { $display['display_options']['link_url'] = _views_update_8002_token_update($display['display_options']['link_url'], $argument_map_per_display[$display_name]); $changed = TRUE; } } // Update custom classes for row class + grid classes. // Update RSS description field. foreach ($displays as $display_name => &$display) { if (!empty($display['display_options']['style'])) { if (!empty($display['display_options']['style']['options']['row_class_custom'])) { $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]); $changed = TRUE; } if (!empty($display['display_options']['style']['options']['col_class_custom'])) { $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]); $changed = TRUE; } if (!empty($display['display_options']['style']['options']['description'])) { $display['display_options']['style']['options']['description'] = _views_update_8002_token_update($display['display_options']['style']['options']['description'], $argument_map_per_display[$display_name]); $changed = TRUE; } } } if ($changed) { $view->set('display', $displays); $view->save(TRUE); } } } /** * Updates a views configuration string from using %/! to twig tokens. * * @param string $text * Text in which to search for argument tokens and replace them with their * twig representation. * @param array $argument_map * A map of argument machine names keyed by their previous index. * * @return string * The updated token. */ function _views_update_8002_token_update($text, array $argument_map) { $text = preg_replace_callback('/%(\d)/', function ($match) use ($argument_map) { return "{{ arguments.{$argument_map[$match[1]]} }}"; }, $text); $text = preg_replace_callback('/!(\d)/', function ($match) use ($argument_map) { return "{{ raw_arguments.{$argument_map[$match[1]]} }}"; }, $text); return $text; } /** * Builds an argument map for each Views display. * * @param array $displays * A list of Views displays. * * @return array * The argument map keyed by display id. */ function _views_update_argument_map($displays) { $argument_map = []; foreach ($displays as $display_id => $display) { $argument_map[$display_id] = []; if (isset($display['display_options']['arguments'])) { foreach (array_keys($display['display_options']['arguments']) as $number => $name) { $argument_map[$display_id][$number + 1] = $name; } } elseif (isset($displays['default']['display_options']['arguments'])) { foreach (array_keys($displays['default']['display_options']['arguments']) as $number => $name) { $argument_map[$display_id][$number + 1] = $name; } } } return $argument_map; } /** * Clear caches to fix entity operations field. */ function views_update_8003() { // Empty update to cause a cache flush so that views data is rebuilt. Entity // types that don't implement a list builder cannot have the entity operations // field. } /** * Clear caches due to updated entity views data. */ function views_update_8004() { // Empty update to cause a cache flush so that views data is rebuilt. } /** * Clear views data cache. */ function views_update_8005() { // Empty update function to rebuild the views data. } /** * Clear caches due to updated entity views data. */ function views_update_8100() { // Empty update to cause a cache flush so that views data is rebuilt. } /** * Set default values for enabled/expanded flag on page displays. */ function views_update_8101() { $config_factory = \Drupal::configFactory(); foreach ($config_factory->listAll('views.view.') as $view_config_name) { $view = $config_factory->getEditable($view_config_name); $save = FALSE; foreach ($view->get('display') as $display_id => $display) { if ($display['display_plugin'] == 'page') { $display['display_options']['menu']['enabled'] = TRUE; $display['display_options']['menu']['expanded'] = FALSE; $view->set("display.$display_id", $display); $save = TRUE; } } if ($save) { $view->save(); } } } /** * Rebuild the container to add a new container parameter. */ function views_update_8200() { // Empty update to cause a cache rebuild so that the container is rebuilt. } /** * Rebuild cache to refresh the views config schema. */ function views_update_8201() { // Empty update to cause a cache rebuild so that config schema get refreshed. }