custom_field-1.0.x-dev/src/Plugin/CustomField/FieldFormatter/DateTimeFormatterBase.php

src/Plugin/CustomField/FieldFormatter/DateTimeFormatterBase.php
<?php

declare(strict_types=1);

namespace Drupal\custom_field\Plugin\CustomField\FieldFormatter;

use Drupal\Component\Datetime\DateTimePlus;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Datetime\TimeZoneFormHelper;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\custom_field\Plugin\CustomField\FieldType\DateTimeType;
use Drupal\custom_field\Plugin\CustomField\FieldType\DateTimeTypeInterface;
use Drupal\custom_field\Plugin\CustomFieldFormatterBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Base class for 'DateTime custom field formatter' plugin implementations.
 */
abstract class DateTimeFormatterBase extends CustomFieldFormatterBase {

  /**
   * The entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected DateFormatterInterface $dateFormatter;

  /**
   * The date format entity storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected EntityStorageInterface $dateFormatStorage;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->entityTypeManager = $container->get('entity_type.manager');
    $instance->dateFormatter = $container->get('date.formatter');
    $instance->dateFormatStorage = $container->get('entity_type.manager')->getStorage('date_format');

    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings(): array {
    return [
      'timezone_override' => '',
      'timezone_stored' => FALSE,
      'display_timezone' => FALSE,
      'timezone_format' => 'abbreviation',
      'user_timezone' => FALSE,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state): array {
    $visibility_path = $form['#visibility_path'];
    $parents = $form['#field_parents'];
    $elements['timezone'] = [
      '#type' => 'details',
      '#title' => $this->t('Time zone'),
    ];
    $elements['timezone']['timezone_override'] = [
      '#type' => 'select',
      '#title' => $this->t('Time zone override'),
      '#description' => $this->t('The time zone selected here will always be used'),
      '#options' => TimeZoneFormHelper::getOptionsListByRegion(TRUE),
      '#default_value' => $this->getSetting('timezone_override'),
      '#parents' => [...$parents, 'timezone_override'],
    ];
    if ($this->customFieldDefinition->getDatetimeType() === DateTimeType::DATETIME_TYPE_DATETIME) {
      $elements['timezone']['timezone_stored'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Use stored time zone'),
        '#description' => $this->t('If checked, the time zone of the field will be used if available instead of the time zone of the user.'),
        '#default_value' => $this->getSetting('timezone_stored'),
        '#states' => [
          'visible' => [
            ':input[name="' . $visibility_path . '[timezone_override]"]' => ['value' => ''],
          ],
        ],
        '#parents' => [...$parents, 'timezone_stored'],
      ];
      $elements['timezone']['display_timezone'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Display time zone'),
        '#description' => $this->t('If checked, the time zone of the field will be displayed along with the date/time.'),
        '#default_value' => $this->getSetting('display_timezone'),
        '#parents' => [...$parents, 'display_timezone'],
      ];
      $elements['timezone']['timezone_format'] = [
        '#type' => 'select',
        '#title' => $this->t('Time zone format'),
        '#description' => $this->t('The format of the time zone to display.'),
        '#options' => [
          'name' => $this->t('Name'),
          'offset' => $this->t('Offset'),
          'abbreviation' => $this->t('Abbreviation'),
        ],
        '#default_value' => $this->getSetting('timezone_format'),
        '#states' => [
          'visible' => [
            ':input[name="' . $visibility_path . '[display_timezone]"]' => ['checked' => TRUE],
          ],
        ],
        '#parents' => [...$parents, 'timezone_format'],
      ];
      $elements['timezone']['user_timezone'] = [
        '#type' => 'checkbox',
        '#title' => $this->t("Append date/time in user's time zone"),
        '#description' => $this->t("If checked, the date/time in the user's time zone will also be displayed."),
        '#default_value' => $this->getSetting('user_timezone'),
        '#parents' => [...$parents, 'user_timezone'],
      ];
    }

    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  public function formatValue(FieldItemInterface $item, mixed $value): ?array {
    /** @var \Drupal\Core\Datetime\DrupalDateTime $date */
    $date = $value['date'];

    if ($date === NULL) {
      return NULL;
    }

    $timezone = $this->getSetting('timezone_stored') ? $value['timezone'] : NULL;
    if ($this->getSetting('timezone_override')) {
      $timezone = $this->getSetting('timezone_override');
    }

    if ($this->getSetting('user_timezone') && (!empty($timezone))) {
      return [
        '#theme' => 'item_list',
        '#list_type' => 'ul',
        '#items' => [
          $this->buildDateWithIsoAttribute($date, TRUE, $timezone),
          $this->buildDateWithIsoAttribute($date),
        ],
      ];
    }

    return $this->buildDateWithIsoAttribute($date, TRUE, $timezone);
  }

  /**
   * Creates a formatted date value as a string.
   *
   * @param \Drupal\Component\Datetime\DateTimePlus $date
   *   A DrupalDateTime object.
   * @param string|null $timezone
   *   The stored timezone.
   *
   * @return string
   *   A formatted date string using the chosen format.
   */
  abstract protected function formatDate(DateTimePlus $date, ?string $timezone): string;

  /**
   * Sets the proper time zone on a DrupalDateTime object for the current user.
   *
   * A DrupalDateTime object loaded from the database will have the UTC time
   * zone applied to it.  This method will apply the time zone for the current
   * user, based on system and user settings.
   *
   * @param \Drupal\Component\Datetime\DateTimePlus $date
   *   A DrupalDateTime object.
   * @param string|null $timezone
   *   The stored timezone.
   */
  protected function setTimeZone(DateTimePlus $date, ?string $timezone = NULL): void {
    $datetime_type = $this->customFieldDefinition->getDatetimeType();
    if ($datetime_type === DateTimeType::DATETIME_TYPE_DATE) {
      // A date without time has no timezone conversion.
      $timezone = DateTimeTypeInterface::STORAGE_TIMEZONE;
    }
    elseif (empty($timezone)) {
      $timezone = date_default_timezone_get();
    }

    $date->setTimezone(timezone_open($timezone));
  }

  /**
   * Creates a render array from a date object.
   *
   * @param \Drupal\Core\Datetime\DrupalDateTime $date
   *   A date object.
   * @param string|null $timezone
   *   The stored timezone.
   *
   * @return array<string, mixed>
   *   A render array.
   */
  protected function buildDate(DrupalDateTime $date, ?string $timezone = NULL): array {
    $datetime_type = $this->customFieldDefinition->getDatetimeType();
    $data_type = $this->customFieldDefinition->getDataType();
    $this->setTimeZone($date, $timezone);
    $formatted_date = $this->formatDate($date, $timezone);

    if ($data_type === 'datetime' && $datetime_type === DateTimeType::DATETIME_TYPE_DATETIME && $this->getSetting('display_timezone')) {
      $formatted_date .= ' ' . $this->formatTimezoneDisplay($date);
    }
    return [
      '#markup' => $formatted_date,
      '#cache' => [
        'contexts' => [
          'timezone',
        ],
      ],
    ];
  }

  /**
   * Creates a render array from a date object with ISO date attribute.
   *
   * @param \Drupal\Core\Datetime\DrupalDateTime $date
   *   A date object.
   * @param bool $format_timezone
   *   A boolean indicating whether to format and append the timezone.
   * @param string|null $timezone
   *   The stored timezone.
   *
   * @return array<string, mixed>
   *   A render array.
   */
  protected function buildDateWithIsoAttribute(DrupalDateTime $date, bool $format_timezone = TRUE, ?string $timezone = NULL): array {
    $datetime_type = $this->customFieldDefinition->getDatetimeType();
    // Create the ISO date in Universal Time.
    $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';

    $this->setTimeZone($date, $timezone);
    $formatted_date = $this->formatDate($date, $timezone);

    if ($format_timezone && $datetime_type === DateTimeType::DATETIME_TYPE_DATETIME && $this->getSetting('display_timezone')) {
      $formatted_date .= ' ' . $this->formatTimezoneDisplay($date);
    }

    return [
      '#theme' => 'time',
      '#text' => $formatted_date,
      '#attributes' => [
        'datetime' => $iso_date,
      ],
      '#cache' => [
        'contexts' => [
          'timezone',
        ],
      ],
    ];
  }

  /**
   * Formats timezone display based on settings.
   *
   * @param \Drupal\Core\Datetime\DrupalDateTime $date
   *   The date object.
   *
   * @return string
   *   The formatted timezone.
   */
  protected function formatTimezoneDisplay(DrupalDateTime $date): string {
    $format = $this->getSetting('timezone_format');
    $timezone_name = $date->getTimezone()->getName();

    switch ($format) {
      case 'name':
        return '(' . $timezone_name . ')';

      case 'offset':
        return '(' . $date->format('P') . ')';

      default:
        // Default to abbreviation.
        return '(' . $date->format('T') . ')';
    }
  }

}

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

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