custom_field-1.0.x-dev/src/Element/DatetimeBase.php

src/Element/DatetimeBase.php
<?php

declare(strict_types=1);

namespace Drupal\custom_field\Element;

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Datetime\Element\Datetime;
use Drupal\Core\Datetime\Entity\DateFormat;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a base class for custom field date elements.
 */
abstract class DatetimeBase extends Datetime {

  /**
   * {@inheritdoc}
   */
  public function getInfo(): array {
    $info = parent::getInfo();
    $info['#theme_wrappers'] = [];
    $info['#theme'] = NULL;
    $info['#timezone_element'] = FALSE;
    $info['#show_seconds'] = TRUE;
    $info['#field_parents'] = [];

    return $info;
  }

  /**
   * {@inheritdoc}
   */
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
    $element += ['#date_timezone' => date_default_timezone_get()];
    if ($input !== FALSE) {
      if ($element['#date_date_element'] === 'datetime-local' && !empty($input['date'])) {
        // With a datetime-local input, the date value is always normalized to
        // the format Y-m-d\TH:i.
        // @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local
        // 'html_datetime' is not a valid format to pass to
        // DrupalDateTime::createFromFormat()
        $date_parts = explode('T', $input['date']);
        $date_input = $date_parts[0];
        $time_input = $date_parts[1] ?? NULL;
        $date_format = DateFormat::load('html_date')->getPattern();
        $time_format = DateFormat::load('html_time')->getPattern();
      }
      else {
        $date_format = $element['#date_date_format'] != 'none' ? static::getHtml5DateFormat($element) : '';
        $time_format = $element['#date_time_element'] != 'none' ? static::getHtml5TimeFormat($element) : '';
        $same_day = $form_state->getValue([...$element['#field_parents'], 'same_day']);
        if ($input instanceof DrupalDateTime) {
          $values = [
            'date' => $input->format($date_format),
            'time' => $input->format($time_format),
          ];
          $input = $values;
        }
        // Modify input for same-day checkbox.
        elseif ($same_day && end($element['#parents']) === 'end_value') {
          $start_date = $form_state->getValue([...$element['#field_parents'], 'value']);
          if (empty($start_date['date'])) {
            $input['time'] = '';
          }
          else {
            $input['date'] = $start_date['date'];
          }
        }

        $date_input = $element['#date_date_element'] != 'none' && !empty($input['date']) ? $input['date'] : '';
        $time_input = $element['#date_time_element'] != 'none' && !empty($input['time']) ? $input['time'] : '';
      }

      // Seconds will be omitted in a post in case there's no entry.
      if (!empty($time_input) && strlen($time_input) == 5) {
        $time_input .= ':00';
      }

      try {
        $date_time_format = trim($date_format . ' ' . $time_format);
        $date_time_input = trim($date_input . ' ' . $time_input);
        $date = DrupalDateTime::createFromFormat($date_time_format, $date_time_input, $element['#date_timezone']);
      }
      catch (\Exception) {
        $date = NULL;
      }
      $input = [
        'date'   => $date_input,
        'time'   => $time_input,
        'object' => $date,
      ];
    }
    else {
      $date = $element['#default_value'] ?? NULL;
      if ($date instanceof DrupalDateTime && !$date->hasErrors()) {
        $date->setTimezone(new \DateTimeZone($element['#date_timezone']));
        $input = [
          'date'   => $date->format($element['#date_date_format']),
          'time'   => $date->format($element['#date_time_format']),
          'object' => $date,
        ];
      }
      else {
        $input = [
          'date'   => '',
          'time'   => '',
          'object' => NULL,
        ];
      }
    }

    return $input;
  }

  /**
   * {@inheritdoc}
   */
  protected static function getHtml5DateFormat($element) {
    switch ($element['#date_date_element']) {
      case 'date':
        return DateFormat::load('html_date')->getPattern();

      case 'datetime':
        return DateFormat::load('html_datetime')->getPattern();

      case 'datetime-local':
        return 'Y-m-d\TH:i';

      default:
        return $element['#date_date_format'];
    }
  }

  /**
   * {@inheritdoc}
   *
   * @return array<string, mixed>
   *   The processed element.
   */
  public static function processDatetime(&$element, FormStateInterface $form_state, &$complete_form): array {
    $element = parent::processDatetime($element, $form_state, $complete_form);
    $show_seconds = $element['#show_seconds'] ?? FALSE;
    if ($element['#date_date_element'] === 'datetime-local') {
      if ($show_seconds) {
        $element['date']['#attributes']['step'] = 1;
        $format = 'm/d/Y, h:i:s A';
      }
      else {
        $element['date']['#attributes']['step'] = 60;
        $format = 'm/d/Y, h:i A';
      }
      $element['date']['#attributes']['title'] = t('Enter a valid date and time - e.g. @format', [
        '@format' => (new \DateTime())->format($format),
      ]);
    }
    elseif ($element['#date_time_element'] !== 'none') {
      if ($show_seconds) {
        $element['time']['#attributes']['step'] = 1;
        $format = 'h:i:s A';
      }
      else {
        $element['time']['#attributes']['step'] = 60;
        $format = 'h:i A';
        // Remove the seconds from the time element.
        if (!empty($element['time']['#value'])) {
          $parts = explode(':', $element['time']['#value']);
          $parts = array_splice($parts, 0, 2);
          $element['time']['#value'] = implode(':', $parts);
        }
      }
      $element['time']['#attributes']['title'] = t('Enter a valid time - e.g. @format', [
        '@format' => (new \DateTime())->format($format),
      ]);
    }

    if ($element['#date_date_element'] != 'none') {
      // The value callback has populated the #value array.
      $same_day = $element['#same_day'] ?? FALSE;
      if ($same_day) {
        $element['date']['#type'] = 'hidden';
        $element['time']['#title'] = $element['#title'];
        $element['time']['#title_display'] = 'before';
      }
      $date = !empty($element['#value']['object']) ? $element['#value']['object'] : NULL;
      if (!$date instanceof DrupalDateTime) {
        $format_settings = [];
        $date_format = $element['#date_date_element'] != 'none' ? static::getHtml5DateFormat($element) : '';
        // With a datetime-local input, the date value is always normalized to
        // the format Y-m-d\TH:i.
        // @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local
        // 'html_datetime' returned by static::getHtml5DateFormat($element) is
        // not a valid format.
        // @see https://www.drupal.org/project/drupal/issues/3505318
        if ($element['#date_date_element'] === 'datetime-local') {
          $date_format = DateFormat::load('html_date')->getPattern() . '\T' . DateFormat::load('html_time')->getPattern();
        }
        $range = static::datetimeRangeYears($element['#date_year_range']);
        $html5_min = DrupalDateTime::createFromFormat(DrupalDateTime::FORMAT, $range[0] . '-01-01 00:00:00');
        $html5_max = DrupalDateTime::createFromFormat(DrupalDateTime::FORMAT, $range[1] . '-12-31 23:59:59');
        $element['date']['#attributes']['min'] = $html5_min->format($date_format, $format_settings);
        $element['date']['#attributes']['max'] = $html5_max->format($date_format, $format_settings);
      }
    }

    return $element;
  }

}

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

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