datetime_range.module 7.25 KB
Newer Older
1 2 3 4 5 6 7
<?php

/**
 * @file
 * Field hooks to implement a datetime field that stores a start and end date.
 */

8
use Drupal\Core\Url;
9
use Drupal\Core\Routing\RouteMatchInterface;
10 11
use Drupal\views\Views;
use Drupal\views\ViewEntityInterface;
12 13 14 15 16 17 18 19 20

/**
 * Implements hook_help().
 */
function datetime_range_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.datetime_range':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
21
      $output .= '<p>' . t('The Datetime Range module provides a Date field that stores start dates and times, as well as end dates and times. See the <a href=":field">Field module help</a> and the <a href=":field_ui">Field UI module help</a> pages for general information on fields and how to create and manage them. For more information, see the <a href=":datetime_do">online documentation for the Datetime Range module</a>.', [':field' => Url::fromRoute('help.page', ['name' => 'field'])->toString(), ':field_ui' => (\Drupal::moduleHandler()->moduleExists('field_ui')) ? Url::fromRoute('help.page', ['name' => 'field_ui'])->toString() : '#', ':datetime_do' => 'https://www.drupal.org/documentation/modules/datetime_range']) . '</p>';
22 23 24
      $output .= '<h3>' . t('Uses') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('Managing and displaying date fields') . '</dt>';
25
      $output .= '<dd>' . t('The <em>settings</em> and the <em>display</em> of the Date field can be configured separately. See the <a href=":field_ui">Field UI help</a> for more information on how to manage fields and their display.', [':field_ui' => (\Drupal::moduleHandler()->moduleExists('field_ui')) ? Url::fromRoute('help.page', ['name' => 'field_ui'])->toString() : '#']) . '</dd>';
26
      $output .= '<dt>' . t('Displaying dates') . '</dt>';
27
      $output .= '<dd>' . t('Dates can be displayed using the <em>Plain</em> or the <em>Default</em> formatter. The <em>Plain</em> formatter displays the date in the <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> format. If you choose the <em>Default</em> formatter, you can choose a format from a predefined list that can be managed on the <a href=":date_format_list">Date and time formats</a> page.', [':date_format_list' => Url::fromRoute('entity.date_format.collection')->toString()]) . '</dd>';
28 29 30 31
      $output .= '</dl>';
      return $output;
  }
}
32 33

/**
34
 * Implements hook_ENTITY_TYPE_presave().
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
 *
 * When a view is saved using the old string or standard plugin format for
 * Datetime Range filters or sorts, they will automatically be updated to
 * Datetime filters or sorts. Old plugins usage must to be considered
 * deprecated and must be converted before 9.0.0, when this updating layer will
 * be removed.
 *
 * @deprecated in Drupal 8.5.x and will be removed before 9.0.0.
 *
 * @see https://www.drupal.org/node/2857691
 */
function datetime_range_view_presave(ViewEntityInterface $view) {
  $config_factory = \Drupal::configFactory();
  $displays = $view->get('display');
  $changed = FALSE;

  foreach ($displays as $display_name => &$display) {

    // Update datetime_range filters.
    if (isset($display['display_options']['filters'])) {
      foreach ($display['display_options']['filters'] as $field_name => &$filter) {
        if ($filter['plugin_id'] === 'string') {
57 58 59 60
          $table_data = Views::viewsData()->get($filter['table']);
          if (!$table_data) {
            continue;
          }
61 62

          // Get field config.
63
          $filter_views_data = $table_data[$filter['field']]['filter'];
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
          if (!isset($filter_views_data['entity_type']) || !isset($filter_views_data['field_name'])) {
            continue;
          }
          $field_storage_name = 'field.storage.' . $filter_views_data['entity_type'] . '.' . $filter_views_data['field_name'];
          $field_configuration = $config_factory->get($field_storage_name);

          if ($field_configuration->get('type') === 'daterange') {

            // Set entity_type if missing.
            if (!isset($filter['entity_type'])) {
              $filter['entity_type'] = $filter_views_data['entity_type'];
            }

            // Set datetime plugin_id.
            $filter['plugin_id'] = 'datetime';

            // Create datetime value array.
            $datetime_value = [
              'min' => '',
              'max' => '',
              'value' => $filter['value'],
              'type' => 'date',
            ];

            // Map string operator/value to numeric equivalent.
            switch ($filter['operator']) {
              case '=':
              case 'empty':
              case 'not empty':
                $operator = $filter['operator'];
                break;

              case '!=':
              case 'not':
                $operator = '!=';
                break;

              case 'starts':
                $operator = 'regular_expression';
                $datetime_value['value'] = '^' . preg_quote($datetime_value['value']);
                break;

              case 'ends':
                $operator = 'regular_expression';
                $datetime_value['value'] = preg_quote($datetime_value['value']) . '$';
                break;

              default:
                $operator = 'regular_expression';
                // Add .* to prevent blank regexes.
                if (empty($datetime_value['value'])) {
                  $datetime_value['value'] = '.*';
                }
                else {
                  $datetime_value['value'] = preg_quote($datetime_value['value']);
                }
            }

            // Set value and operator.
            $filter['value'] = $datetime_value;
            $filter['operator'] = $operator;
            $changed = TRUE;
            @trigger_error('Use of string filters for datetime_range fields is deprecated. Use the datetime filters instead. See https://www.drupal.org/node/2857691', E_USER_DEPRECATED);
          }
        }
      }
    }

    // Update datetime_range sort handlers.
    if (isset($display['display_options']['sorts'])) {
      foreach ($display['display_options']['sorts'] as $field_name => &$sort) {
        if ($sort['plugin_id'] === 'standard') {
136 137 138 139
          $table_data = Views::viewsData()->get($sort['table']);
          if (!$table_data) {
            continue;
          }
140 141

          // Get field config.
142
          $sort_views_data = $table_data[$sort['field']]['sort'];
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
          if (!isset($sort_views_data['entity_type']) || !isset($sort_views_data['field_name'])) {
            continue;
          }
          $field_storage_name = 'field.storage.' . $sort_views_data['entity_type'] . '.' . $sort_views_data['field_name'];
          $field_configuration = $config_factory->get($field_storage_name);

          if ($field_configuration->get('type') === 'daterange') {

            // Set entity_type if missing.
            if (!isset($sort['entity_type'])) {
              $sort['entity_type'] = $sort_views_data['entity_type'];
            }

            // Set datetime plugin_id.
            $sort['plugin_id'] = 'datetime';
            $changed = TRUE;
            @trigger_error('Use of standard sort handlers for datetime_range fields is deprecated. Use the datetime sort handlers instead. See https://www.drupal.org/node/2857691', E_USER_DEPRECATED);
          }
        }
      }
    }
  }

  if ($changed) {
    $view->set('display', $displays);
  }
}