date_recur-8.x-2.2/src/Plugin/Field/FieldType/DateRecurFieldItemList.php

src/Plugin/Field/FieldType/DateRecurFieldItemList.php
<?php

declare(strict_types=1);

namespace Drupal\date_recur\Plugin\Field\FieldType;

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Datetime\TimeZoneFormHelper;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Form\FormStateInterface;
use Drupal\date_recur\DateRecurPartGrid;
use Drupal\date_recur\Event\DateRecurEvents;
use Drupal\date_recur\Event\DateRecurValueEvent;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\datetime_range\Plugin\Field\FieldType\DateRangeFieldItemList;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * Recurring date field item list.
 */
class DateRecurFieldItemList extends DateRangeFieldItemList {

  /**
   * Value for 'default_time_zone_source' to get time zone from a fixed string.
   */
  public const DEFAULT_TIME_ZONE_SOURCE_FIXED = 'fixed';

  /**
   * Value for 'default_time_zone_source' to get current users time zone.
   */
  public const DEFAULT_TIME_ZONE_SOURCE_CURRENT_USER = 'current_user';

  /**
   * An event dispatcher, primarily for unit testing purposes.
   *
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|null
   */
  protected ?EventDispatcherInterface $eventDispatcher = NULL;

  /**
   * {@inheritdoc}
   */
  public function postSave($update): bool {
    parent::postSave($update);
    $event = new DateRecurValueEvent($this, !$update);
    $this->getDispatcher()->dispatch($event, DateRecurEvents::FIELD_VALUE_SAVE);
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function delete(): void {
    parent::delete();
    $event = new DateRecurValueEvent($this, FALSE);
    $this->getDispatcher()->dispatch($event, DateRecurEvents::FIELD_ENTITY_DELETE);
  }

  /**
   * {@inheritdoc}
   */
  public function deleteRevision(): void {
    parent::deleteRevision();
    $event = new DateRecurValueEvent($this, FALSE);
    $this->getDispatcher()->dispatch($event, DateRecurEvents::FIELD_REVISION_DELETE);
  }

  /**
   * Get the event dispatcher.
   *
   * @return \Symfony\Component\EventDispatcher\EventDispatcherInterface
   *   The event dispatcher.
   */
  protected function getDispatcher(): EventDispatcherInterface {
    if (isset($this->eventDispatcher)) {
      return $this->eventDispatcher;
    }
    return \Drupal::service('event_dispatcher');
  }

  /**
   * {@inheritdoc}
   */
  public function defaultValuesForm(array &$form, FormStateInterface $form_state): array {
    $element = parent::defaultValuesForm($form, $form_state);

    $defaultValue = $this->getFieldDefinition()->getDefaultValueLiteral();

    $element['default_date_time_zone'] = [
      '#type' => 'select',
      '#title' => $this->t('Start and end date time zone'),
      '#description' => $this->t('Time zone is required if a default start date or end date is provided.'),
      '#options' => $this->getTimeZoneOptions(),
      '#default_value' => $defaultValue[0]['default_date_time_zone'] ?? '',
      '#states' => [
        // Show the field if either start or end is set.
        'invisible' => [
          [
            ':input[name="default_value_input[default_date_type]"]' => ['value' => ''],
            ':input[name="default_value_input[default_end_date_type]"]' => ['value' => ''],
          ],
        ],
      ],
    ];

    $defaultTimeZoneSource = $defaultValue[0]['default_time_zone_source'] ?? NULL;
    $defaultTimeZone = $defaultTimeZoneSource === 'current_user'
      ? 'current_user'
      : $defaultValue[0]['default_time_zone'] ?? '';

    $element['default_time_zone'] = [
      '#type' => 'select',
      '#title' => $this->t('Time zone'),
      '#description' => $this->t('Default time zone.'),
      '#options' => [
        'current_user' => $this->t('- Current user time zone -'),
      ] + $this->getTimeZoneOptions(),
      '#default_value' => $defaultTimeZone,
      '#empty_option' => $this->t('- None -'),
    ];

    $element['default_rrule'] = [
      '#type' => 'textarea',
      '#title' => $this->t('RRULE'),
      '#default_value' => $defaultValue[0]['default_rrule'] ?? '',
    ];

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultValuesFormValidate(array $element, array &$form, FormStateInterface $form_state): void {
    /** @var string|null $defaultDateTimeZone */
    $defaultDateTimeZone = $form_state->getValue(['default_value_input', 'default_date_time_zone']);
    if ($defaultDateTimeZone === NULL || strlen($defaultDateTimeZone) === '') {
      /** @var string|null $defaultStartType */
      $defaultStartType = $form_state->getValue(['default_value_input', 'default_date_type']);
      if ($defaultStartType !== NULL && strlen($defaultStartType) > 0) {
        $form_state->setErrorByName('default_value_input][default_date_time_zone', (string) $this->t('Time zone must be provided if a default start date is provided.'));
      }

      /** @var string|null $defaultEndType */
      $defaultEndType = $form_state->getValue(['default_value_input', 'default_end_date_type']);
      if ($defaultEndType !== NULL && strlen($defaultEndType) > 0) {
        $form_state->setErrorByName('default_value_input][default_date_time_zone', (string) $this->t('Time zone must be provided if a default end date is provided.'));
      }
    }

    parent::defaultValuesFormValidate($element, $form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function defaultValuesFormSubmit(array $element, array &$form, FormStateInterface $form_state): array {
    $values = parent::defaultValuesFormSubmit($element, $form, $form_state);

    /** @var string|null $rrule */
    $rrule = $form_state->getValue(['default_value_input', 'default_rrule']);
    if ($rrule !== NULL && strlen($rrule) > 0) {
      $values[0]['default_rrule'] = $rrule;
    }

    /** @var string|null $defaultDateTimeZone */
    $defaultDateTimeZone = $form_state->getValue(['default_value_input', 'default_date_time_zone']);
    if ($defaultDateTimeZone !== NULL && strlen($defaultDateTimeZone) > 0) {
      $values[0]['default_date_time_zone'] = $defaultDateTimeZone;
    }

    /** @var string|null $defaultTimeZone */
    $defaultTimeZone = $form_state->getValue(['default_value_input', 'default_time_zone']);
    if ($defaultTimeZone !== NULL && strlen($defaultTimeZone) > 0) {
      if ($defaultTimeZone === 'current_user') {
        $values[0]['default_time_zone_source'] = 'current_user';
      }
      else {
        $values[0]['default_time_zone_source'] = 'fixed';
        $values[0]['default_time_zone'] = $defaultTimeZone;
      }
    }

    return $values;
  }

  /**
   * {@inheritdoc}
   */
  public static function processDefaultValue($default_value, FieldableEntityInterface $entity, FieldDefinitionInterface $definition): array {
    assert(is_array($default_value));
    $defaultDateTimeZone = $default_value[0]['default_date_time_zone'] ?? NULL;

    $defaultValue = FieldItemList::processDefaultValue($default_value, $entity, $definition);

    $defaultValues = [[]];

    $hasDefaultStartDateType = isset($defaultValue[0]['default_date_type']) && is_string($defaultValue[0]['default_date_type']) && strlen($defaultValue[0]['default_date_type']) > 0;
    $hasDefaultEndDateType = isset($defaultValue[0]['default_end_date_type']) && is_string($defaultValue[0]['default_end_date_type']) && strlen($defaultValue[0]['default_end_date_type']) > 0;
    $hasDefaultDateTimeZone = is_string($defaultDateTimeZone) && strlen($defaultDateTimeZone) > 0;
    if ($hasDefaultDateTimeZone && ($hasDefaultStartDateType || $hasDefaultEndDateType)) {
      $storageFormat = $definition->getSetting('datetime_type') == DateRecurItem::DATETIME_TYPE_DATE ? DateRecurItem::DATE_STORAGE_FORMAT : DateRecurItem::DATETIME_STORAGE_FORMAT;

      // Instruct 'value' and 'end_value' to convert from the localized time
      // zone to UTC.
      $formatSettings = ['timezone' => DateTimeItemInterface::STORAGE_TIMEZONE];

      if ($hasDefaultStartDateType) {
        $start_date = new DrupalDateTime($defaultValue[0]['default_date'], $defaultDateTimeZone);
        $start_value = $start_date->format($storageFormat, $formatSettings);
        $defaultValues[0]['value'] = $start_value;
        $defaultValues[0]['start_date'] = $start_date;
      }

      if ($hasDefaultEndDateType) {
        $end_date = new DrupalDateTime($defaultValue[0]['default_end_date'], $defaultDateTimeZone);
        $end_value = $end_date->format($storageFormat, $formatSettings);
        $defaultValues[0]['end_value'] = $end_value;
        $defaultValues[0]['end_date'] = $end_date;
      }

      $defaultValue = $defaultValues;
    }

    $rrule = $default_value[0]['default_rrule'] ?? NULL;
    if (is_string($rrule) && strlen($rrule) > 0) {
      $defaultValue[0]['rrule'] = $rrule;
    }

    $timeZoneSource = $default_value[0]['default_time_zone_source'] ?? NULL;
    if ($timeZoneSource === static::DEFAULT_TIME_ZONE_SOURCE_FIXED) {
      $defaultValue[0]['timezone'] = $default_value[0]['default_time_zone'];
    }
    elseif ($timeZoneSource === static::DEFAULT_TIME_ZONE_SOURCE_CURRENT_USER) {
      $timeZone = \date_default_timezone_get();
      if (strlen($timeZone) === 0) {
        throw new \Exception('Something went wrong. User has no time zone.');
      }
      $defaultValue[0]['timezone'] = $timeZone;
    }

    unset($defaultValue[0]['default_time_zone']);
    unset($defaultValue[0]['default_time_zone_source']);
    unset($defaultValue[0]['default_rrule']);
    return $defaultValue;
  }

  /**
   * Get a list of time zones suitable for a select field.
   *
   * @return array
   *   A list of time zones where keys are PHP time zone codes, and values are
   *   human readable and translatable labels.
   */
  protected function getTimeZoneOptions(): array {
    return TimeZoneFormHelper::getOptionsListByRegion(TRUE);
  }

  /**
   * Set the event dispatcher.
   *
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
   *   The event dispatcher.
   */
  public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void {
    $this->eventDispatcher = $eventDispatcher;
  }

  /**
   * Get the parts grid for this field.
   *
   * @return \Drupal\date_recur\DateRecurPartGrid
   *   The parts grid for this field.
   */
  public function getPartGrid(): DateRecurPartGrid {
    /** @var array{all: bool, frequencies: array<mixed>}|null $partSettings */
    $partSettings = $this->getFieldDefinition()->getSetting('parts');
    // Existing field configs may not have a parts setting yet.
    $partSettings ??= [];
    return DateRecurPartGrid::configSettingsToGrid($partSettings);
  }

  /**
   * {@inheritdoc}
   */
  public function onChange($delta): void {
    foreach ($this->list as $item) {
      assert($item instanceof DateRecurItem);
      $item->resetHelper();
    }
    parent::onChange($delta);
  }

}

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

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