| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 | <?php/** * @file * Contains install and update functions for Views. */use Drupal\Core\Config\Schema\ArrayElement;use Drupal\views\Views;/** * Implements hook_install(). */function views_install() {  module_set_weight('views', 10);}/** * Update views field plugins. */function views_update_8001(&$sandbox) {  $config_factory = \Drupal::configFactory();  $ids = [];  $message = NULL;  $ago_formats = [    'time ago',    'time hence',    'time span',    'raw time ago',    'raw time hence',    'raw time span',    'inverse time span',  ];  foreach ($config_factory->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.}/** * Update field names for multi-value base fields. */function views_update_8500() {  // Find all multi-value base fields for content entities.  $entity_type_manager = \Drupal::entityTypeManager();  $entity_field_manager = \Drupal::service('entity_field.manager');  $table_update_info = [];  foreach ($entity_type_manager->getDefinitions() as $entity_type_id => $entity_type) {    if ($entity_type->hasHandlerClass('views_data')) {      $base_field_definitions = $entity_field_manager->getBaseFieldDefinitions($entity_type_id);      $entity_storage = $entity_type_manager->getStorage($entity_type_id);      $table_mapping = $entity_storage->getTableMapping($base_field_definitions);      foreach ($base_field_definitions as $field_name => $base_field_definition) {        $base_field_storage_definition = $base_field_definition->getFieldStorageDefinition();        // Skip single value and custom storage base fields.        if (!$base_field_storage_definition->isMultiple() || $base_field_storage_definition->hasCustomStorage()) {          continue;        }        // Get the actual table, as well as the column for the main property        // name so we can perform an update later on the views.        $table_name = $table_mapping->getFieldTableName($field_name);        $main_property_name = $base_field_storage_definition->getMainPropertyName();        $table_update_info[$table_name][$field_name] = $table_mapping->getFieldColumnName($base_field_storage_definition, $main_property_name);      }    }  }  if (empty($table_update_info)) {    return;  }  $config_factory = \Drupal::configFactory();  /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */  $typed_config_manager = \Drupal::service('config.typed');  $views_data = Views::viewsData();  $handler_types = ['field', 'argument', 'sort', 'relationship', 'filter'];  $required_cleanup_handlers = [];  foreach ($config_factory->listAll('views.view.') as $id) {    $view = $config_factory->getEditable($id);    $changed = FALSE;    foreach ($view->get('display') as $display_id => &$display) {      foreach ($handler_types as $handler_type_singular) {        $handler_type_plural = $handler_type_singular . 's';        $handler_data = $view->get("display.$display_id.display_options.$handler_type_plural");        if (empty($handler_data)) {          continue;        }        foreach ($handler_data as $key => $data) {          // If this handler has a table we're interested in, update the field          // name.          $table = $data['table'];          if (isset($table_update_info[$table])) {            $path_to_handler = "display.$display_id.display_options.$handler_type_plural.$key";            $path_field = "{$path_to_handler}.field";            $path_plugin_id = "{$path_to_handler}.plugin_id";            $original_field_name = $view->get($path_field);            // Only if the wrong field name is set do we change the field. It            // could already be using the correct field. Like            // user__roles/roles_target_id.            if (isset($table_update_info[$table][$original_field_name])) {              $required_cleanup_handlers[$id][] = $path_to_handler;              // Set both the new table field as well as new 'plugin_id' field.              $view->set($path_field, $table_update_info[$table][$original_field_name]);              $view->set($path_plugin_id, $views_data->get($table)[$table_update_info[$table][$original_field_name]][$handler_type_singular]['id']);              $changed = TRUE;            }          }        }      }    }    if ($changed) {      $view->save(TRUE);    }  }  // Beside of updating the field and plugin ID we also need to truncate orphan  // keys so he configuration applies to the config schema.  // We cannot do that inline in the other code, due to caching issues with  // typed configuration.  foreach ($required_cleanup_handlers as $id => $paths_to_handlers) {    $changed = FALSE;    $typed_view = $typed_config_manager->get($id);    $view = $config_factory->getEditable($id);    foreach ($paths_to_handlers as $path_to_handler) {      /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_view */      /** @var \Drupal\Core\Config\Schema\ArrayElement $typed_config */      $typed_config = $typed_view->get($path_to_handler);      $config = $typed_config->getValue();      // Filter values we want to convert from a string to an array.      if (strpos($path_to_handler, 'filters') !== FALSE && $typed_config->get('value') instanceof ArrayElement && is_string($config['value'])) {        // An empty string casted to an array is an array with one        // element.        if ($config['value'] === '') {          $config['value'] = [];        }        else {          $config['value'] = (array) $config['value'];        }      }      // For all the other fields we try to determine the fields using      // config schema and remove everything which is not needed.      foreach (array_keys($config) as $config_key) {        if (!isset($typed_config->getDataDefinition()['mapping'][$config_key])) {          unset($config[$config_key]);          $changed = TRUE;        }      }      $typed_config->setValue($config);      $view->set($path_to_handler, $typed_config->getValue());    }    if ($changed) {      $view->save();    }  }}
 |