fullcalendar-8.x-2.x-dev/fullcalendar.views_execution.inc

fullcalendar.views_execution.inc
<?php

/**
 * @file
 * Contains Views module runtime hooks.
 */

use Drupal\Component\Utility\Html;
use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\Plugin\views\query\Sql;
use Drupal\views\ViewExecutable;

/**
 * Implements hook_views_pre_view().
 *
 * Add an argument that provides the current date for each date field present.
 */
function fullcalendar_views_pre_view(ViewExecutable $view, string $display_id, array $args): void {
  $style = $view->display_handler->getOption('style');

  if ($style['type'] !== 'fullcalendar') {
    return;
  }

  // Get the current view settings.
  $view->initStyle();
  /** @var \Drupal\fullcalendar\Plugin\views\style\FullCalendar $view_style */
  $view_style = $view->style_plugin;

  $settings = $view->style_plugin->options;

  foreach ($view_style->getPlugins() as $plugin) {
    $plugin->preView($settings);
  }

  if (empty($view->display_handler->getOption('use_ajax'))) {
    $view->style_plugin->options = $settings;
    return;
  }

  $settings['fullcalendar_fields_count'] = 0;
  $exposed_input = $view->getExposedInput();

  /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */
  $field_manager = \Drupal::service('entity_field.manager');

  $entity_type = $view->getBaseEntityType();
  $entity_type_id = $entity_type->id();

  $field_storages = $field_manager->getFieldStorageDefinitions($entity_type_id);

  // Loop through each date field and provide an argument for it.
  foreach ($view->display_handler->getHandlers('field') as $field) {
    /** @var \Drupal\views\Plugin\views\field\EntityField $field */
    if (!fullcalendar_field_is_date($field)) {
      continue;
    }

    $field_storage = $field_storages[$field->definition['field_name']];

    // Default table name for the field.
    $field_table = $field_storage->getTargetEntityTypeId() . '__' . $field_storage->getName();

    // If the field is a DateRecur field, need to apply table prefix.
    if ($field_storage->getType() === 'date_recur') {
      $field_table = 'date_recur__' . $field_table;
    }

    $field_value = $field_storage->getName() . '_value';

    // @todo The next 24 lines are a duplicate of
    //   \Drupal\fullcalendar\Plugin\views\style\FullCalendar::getExposedDates
    //   Lines 509ff.
    // Min and Max dates for exposed filter.
    $dateMin = new DateTime();
    $dateMax = new DateTime();

    // First, we try to set initial Min and Max date values based on the
    // exposed form values.
    // @todo These offsets don't seem to be possible.
    if (isset($exposed_input[$field_value]['min'], $exposed_input[$field_value]['max'])) {
      $dateMin->setTimestamp(strtotime($exposed_input[$field_value]['min']));
      $dateMax->setTimestamp(strtotime($exposed_input[$field_value]['max']));
    }
    // @todo if $settings['nav']['initialDate'] has a value, use that.
    // Use default 1 month date-range.
    else {
      $dateMin->modify('first day of this month');
      $dateMax->modify('first day of next month');
    }

    $options = [
      'exposed'   => TRUE,
      'form_type' => 'date_select',
      'operator'  => 'between',
      'value'     => [
        'type' => 'date',
        'min'  => $dateMin->format('Y-m-d'),
        'max'  => $dateMax->format('Y-m-d'),
      ],
      'group'     => 'fullcalendar',
    ];

    if (!empty($field->options['relationship'])) {
      $options['relationship'] = $field->options['relationship'];
    }

    $option_id = $view->addHandler($display_id, 'filter', $field_table, $field_value, $options);

    $settings['fullcalendar_fields'][$option_id] = Html::getClass($option_id);
    $settings['fullcalendar_fields_count']++;

    $view->setHandlerOption($display_id, 'filter', $option_id, 'expose', [
      'identifier' => $option_id,
      'operator'   => $option_id . '_op',
    ]);
  }

  // Needs for JavaScript.
  $settings['ajax'] = $view->display_handler->getOption('use_ajax');

  $view->style_plugin->options = $settings;
}

/**
 * Implements hook_views_query_alter().
 */
function fullcalendar_views_query_alter(ViewExecutable $view, QueryPluginBase $query): void {
  $style = $view->display_handler->getOption('style');

  if ($style['type'] !== 'fullcalendar') {
    return;
  }

  if (!$query instanceof Sql) {
    return;
  }

  // Force the query to be distinct.
  $query->distinct = TRUE;

  // Try to add additional condition to the query.
  foreach ($query->where as $group => &$condition_group) {
    if ($group !== 'fullcalendar') {
      continue;
    }

    // Prepare array for extracted query data.
    $data = [
      'field_min' => NULL,
      'field_max' => NULL,
      'date_min'  => NULL,
      'date_max'  => NULL,
    ];

    foreach ($condition_group['conditions'] as $condition) {
      // Try to extract field names from the current condition.
      $parts = explode(' BETWEEN ', $condition['field']);
      if (count($parts) !== 2) {
        continue;
      }

      $data['field_min'] = $parts[0];
      $data['field_max'] = $parts[1];

      // Try to extract dates from the current condition.
      $parts = explode(' AND ', $parts[1]);
      if (count($parts) !== 2) {
        continue;
      }

      $data['date_min'] = $parts[0];
      $data['date_max'] = $parts[1];
    }

    // If 'date_max' exists, then all required values exist, so we can add our
    // custom conditions.
    if (!empty($data['date_max'])) {
      // Change condition group type to 'OR'.
      $condition_group['type'] = 'OR';

      $or_conditions = [];

      // If event starts before and ends after the first day of the calendar.
      // 'event_start' <= 'calendar_start' AND 'event_end' >= 'calendar_start'.
      $or_conditions[] = $data['field_min'] . ' <= ' . $data['date_min'] . ' AND ' . $data['field_max'] . ' >= ' . $data['date_min'];

      // Add additional condition to the group.
      $condition_group['conditions'][] = [
        'field'    => '(' . implode(') OR (', $or_conditions) . ')',
        'value'    => [],
        'operator' => 'formula',
      ];
    }
  }
}

/**
 * Implements hook_views_ajax_data_alter().
 */
function fullcalendar_views_ajax_data_alter(array &$commands, ViewExecutable $view): void {
  // @todo This hook doesn't seem to exist, does it?
  $style = $view->display_handler->getOption('style');

  if ($style['type'] !== 'fullcalendar') {
    $commands = [];
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc