workflow-8.x-1.x-dev/src/Plugin/Field/FieldWidget/WorkflowDateTimeZoneWidget.php

src/Plugin/Field/FieldWidget/WorkflowDateTimeZoneWidget.php
<?php

namespace Drupal\workflow\Plugin\Field\FieldWidget;

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Datetime\Plugin\Field\FieldWidget\TimestampDatetimeWidget;
use Drupal\Core\Datetime\TimeZoneFormHelper;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\workflow\Controller\WorkflowTransitionFormController;

/**
 * Plugin implementation of the 'datetime_timezone' widget.
 *
 * @FieldWidget(
 *   id = "workflow_datetime_timestamp_timezone",
 *   label = @Translation("Datetime Timestamp Timezone"),
 *   field_types = {
 *     "created",
 *   }
 * )
 */
class WorkflowDateTimeZoneWidget extends TimestampDatetimeWidget {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    // Parent sets $element['value']['#type' => 'datetime',] etc.
    $element = parent::formElement($items, $delta, $element, $form, $form_state);

    if ($change_datetime = FALSE) {
      // Avoid error in Drupal\Core\Datetime\Element/DateTime::validateDateTime().
      // and valueCallback().
      // @see https://www.drupal.org/files/issues/2025-07-02/2648950-295.patch
      // The following is taken from Drupal\Core\Datetime\Element/DateTime.
      $date = $element['value']['#default_value'] ?? NULL;
      if ($date instanceof DrupalDateTime && !$date->hasErrors()) {
        // $element['value']['#date_date_format'] = 'Y-m-d'; // DateTime::getHtml5DateFormat($element);
        // $element['value']['#date_time_format'] = 'H:i:s'; // DateTime::getHtml5TimeFormat($element);
        // @todo Fix TimeZone.
        // $date->setTimezone(new \DateTimeZone($element['#date_timezone']));
        $input = [
          // 'date' => $date->format($element['value']['#date_date_format']),
          // 'time' => $date->format($element['value']['#date_time_format']),
          'date' => $date->format('Y-m-d'),
          'time' => $date->format('H:i:s'),
          'object' => $date,
        ];
      }
      // $element['value']['#default_value'] = $input;
      $element['#value'] = $input;
    }

    // From DateTimeWidgetBase:use the same timezone as for storage.
    // $element['value']['#date_timezone'] = DateTimeItemInterface::STORAGE_TIMEZONE;
    // #date_timezone: defaults to value from date_default_timezone_get().
    // #date_increment: A multiple of 60 will hide the "seconds"-component.
    $element['value']['#date_increment'] = 60;
    // $element['value']['#prefix'] = t('At') . ' ';
    // Move datetime into sub-element.
    // $element = ['datetime' => $element];
    // $element['value']['#element_validate'] = [];

    // Workflow might be empty on Action/VBO configuration.
    /** @var \Drupal\workflow\Entity\WorkflowTransitionInterface $transition */
    $transition = $items->getEntity();
    $workflow_settings = $transition?->getWorkflow()?->getSettings();
    if ($workflow_settings['schedule_timezone']) {
      // @todo Remove setting, use form display.
      $user = workflow_current_user();
      $timezone = $items[$delta]->timezone ?? $user->getTimeZone();
      if (empty($timezone)) {
        $timezone = \Drupal::config('system.date')->get('timezone.default');
      }
      // Use TimeZoneFormHelper::getOptionsList() in version >=D10.1.
      $timezone_options = method_exists(
        '\Drupal\Core\Datetime\TimeZoneFormHelper',
        'getOptionsListByRegion'
        )
        ? TimeZoneFormHelper::getOptionsListByRegion()
        : array_combine(timezone_identifiers_list(), timezone_identifiers_list());
      // Hide, not remove, element if needed.
      $controller = WorkflowTransitionFormController::create($transition);
      $add_schedule = $controller->isSchedulingAllowed();

      $element['timezone'] = [
        '#type' => 'select',
        '#title' => $this->t('Timezone'),
        '#description' => $this->t('Select the timezone in which the date should be stored and displayed.'),
        '#default_value' => $timezone,
        '#options' => $timezone_options,
        '#access' => $add_schedule,
      ];
    }

    // @todo Add wrapper to get date, time and timezone next to each other.
    // @todo Adding 'container-inline' does not work.
    // $element = [
    // '#type' => 'container',
    // '#attributes' => ['class' => ['container-inline', 'details-wrapper']],
    // 'scheduled_datetime' => $element,
    // ];

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
    if ($input ?? FALSE) {
      $value = $element['#default_value'];
    }
    else {
      $value = $element['#default_value'];
    }
    return $value;
  }

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    foreach ($values as $delta => $value) {
      if (!$timezone = $value['timezone'] ?? NULL) {
        continue;
      }

      $timestamp = $value['value'];
      // N.B. keep aligned: WorkflowTransition::getTimestamp()
      // and Workflow DateTimeZoneWidget::massageFormValues.
      if ($timestamp instanceof DrupalDateTime) {
        // We now override the value with the entered value converted into the
        // selected timezone, and then DateTimeWidgetBase converts this value
        // into UTC for storage.
        $values[$delta]['value'] = new DrupalDateTime(
          $timestamp->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT),
          new \DateTimezone($timezone));
      }
    }

    $value = parent::massageFormValues($values, $form, $form_state);
    return $value[0]['value'];
  }

}

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

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