contacts_events-8.x-1.x-dev/src/Plugin/Field/FieldWidget/BookingWindowsWidget.php

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

namespace Drupal\contacts_events\Plugin\Field\FieldWidget;

use Drupal\contacts_events\Plugin\Field\FieldType\BookingWindowsItemList;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Security\TrustedCallbackInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Plugin implementation of the 'booking_windows' widget.
 *
 * @FieldWidget(
 *   id = "booking_windows",
 *   label = @Translation("Booking windows"),
 *   field_types = {
 *     "booking_windows"
 *   }
 * )
 */
class BookingWindowsWidget extends WidgetBase implements TrustedCallbackInterface {

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

  /**
   * The element info manager.
   *
   * @var \Drupal\Core\Render\ElementInfoManagerInterface
   */
  protected $elementInfo;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $widget = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $widget->dateStorage = $container->get('entity_type.manager')->getStorage('date_format');
    $widget->elementInfo = $container->get('plugin.manager.element_info');
    return $widget;
  }

  /**
   * {@inheritdoc}
   */
  public static function trustedCallbacks() {
    return ['preRenderWrapConfirmed'];
  }

  /**
   * {@inheritdoc}
   */
  protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
    $elements = parent::formMultipleElements($items, $form, $form_state);
    // Don't show the additional element by default.
    unset($elements[$elements['#max_delta']]);
    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element['#process'][] = [static::class, 'processElement'];
    $element['#pre_render'][] = [static::class, 'preRenderWrapConfirmed'];
    $element['#element_validate'][] = [static::class, 'validateElement'];

    $element['label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Label'),
      '#default_value' => $items[$delta]->label ?? NULL,
      '#size' => $this->getSetting('size'),
      '#placeholder' => $this->getSetting('placeholder'),
      '#maxlength' => $this->getFieldSetting('max_length'),
      '#attributes' => ['class' => ['js-text-full', 'text-full']],
      '#weight' => 0,
    ];

    $element['id'] = [
      '#type' => 'machine_name',
      '#default_value' => $items[$delta]->id ?? NULL,
      '#machine_name' => [
        'exists' => BookingWindowsItemList::class . '::checkUnique',
      ],
      '#disabled' => isset($items[$delta]->id),
    ];

    $date_base = [
      '#type' => 'datetime',
      '#required' => FALSE,
      '#default_value' => NULL,
      '#date_increment' => 1,
      '#date_date_callbacks' => [],
      '#date_time_callbacks' => [],
    ];

    // Identify the type of date and time elements to use.
    switch ($this->getFieldSetting('datetime_type')) {
      case DateTimeItem::DATETIME_TYPE_DATE:
        $date_base['#date_timezone'] = DateTimeItemInterface::STORAGE_TIMEZONE;
        $date_base['#date_date_element'] = 'date';
        $date_base['#date_time_element'] = 'none';
        $date_base['#date_date_format'] = $this->dateStorage->load('html_date')->getPattern();
        $date_base['#date_time_format'] = '';
        break;

      default:
        $date_base['#date_timezone'] = date_default_timezone_get();
        $date_base['#date_date_element'] = 'date';
        $date_base['#date_time_element'] = 'time';
        $date_base['#date_date_format'] = $this->dateStorage->load('html_date')->getPattern();
        $date_base['#date_time_format'] = $this->dateStorage->load('html_time')->getPattern();
        break;
    }

    $element['cut_off'] = [
      '#title' => $this->t('Paid in full by'),
      '#description' => $this->t('This booking window will be locked if the item is paid in full by this date.'),
      '#weight' => 1,
    ] + $date_base;
    if (isset($items[$delta]->date)) {
      $element['cut_off']['#default_value'] = $this->createDefaultValue($items[$delta]->date, $element['cut_off']['#date_timezone']);
    }

    $element['use_confirmed'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Require confirmation by an earlier date'),
      '#default_value' => $items[$delta]->cut_off !== $items[$delta]->cut_off_confirmed,
      '#weight' => 2,
    ];

    $element['cut_off_confirmed'] = [
      '#title' => $this->t('Confirmed by'),
      '#description' => $this->t('This booking window will be locked if the item is confirmed by this date and paid in full by the above date.'),
      '#weight' => 3,
    ] + $date_base;
    if (isset($items[$delta]->date_confirmed)) {
      $element['cut_off_confirmed']['#default_value'] = $this->createDefaultValue($items[$delta]->date_confirmed, $element['cut_off_confirmed']['#date_timezone']);
    }

    return $element;
  }

  /**
   * Processes the element to set up the correct source for the ID.
   *
   * @param array $element
   *   The form element to process.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param array $complete_form
   *   The complete form structure.
   *
   * @return array
   *   The processed element.
   */
  public static function processElement(array &$element, FormStateInterface $form_state, array &$complete_form) {
    $element['id']['#machine_name']['source'] = $element['#array_parents'];
    $element['id']['#machine_name']['source'][] = 'label';
    return $element;
  }

  /**
   * Pre render the element to set up the correct states.
   *
   * @param array $element
   *   The form element to process.
   */
  public static function preRenderWrapConfirmed(array $element) {
    $checkbox_parents = $element['#parents'];
    $checkbox_parents[] = 'use_confirmed';
    $checkbox_name = array_shift($checkbox_parents);
    if ($checkbox_parents) {
      $checkbox_name .= '[' . implode('][', $checkbox_parents) . ']';
    }

    $element['cut_off_confirmed'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => 'js-form-wrapper',
      ],
      '#weight' => $element['cut_off_confirmed']['#weight'],
      '#states' => [
        'visible' => [':input[name="' . $checkbox_name . '"]' => ['checked' => TRUE]],
      ],
      'element' => $element['cut_off_confirmed'],
    ];

    return $element;
  }

  /**
   * Form validation handler for widget elements.
   *
   * @param array $element
   *   The form element.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public static function validateElement(array $element, FormStateInterface $form_state) {
    if (!empty($element['use_confirmed']['#value'])) {
      if (empty($element['cut_off_confirmed']['#value']['date'])) {
        $form_state->setError(
          $element['cut_off_confirmed'],
          new TranslatableMarkup('%window %confirmed is required.', [
            '%window' => $element['label']['#value'],
            '%confirmed' => $element['cut_off_confirmed']['#title'],
          ])
        );
      }
      elseif ($element['cut_off_confirmed']['#value']['date'] >= $element['cut_off']['#value']['date']) {
        $form_state->setError(
          $element['cut_off_confirmed'],
          new TranslatableMarkup('%window %confirmed must be before %paid.', [
            '%window' => $element['label']['#value'],
            '%paid' => $element['cut_off']['#title'],
            '%confirmed' => $element['cut_off_confirmed']['#title'],
          ])
        );
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    // The widget form element type has transformed the value to a
    // DrupalDateTime object at this point. We need to convert it back to the
    // storage timezone and format.
    switch ($this->getFieldSetting('datetime_type')) {
      case DateTimeItem::DATETIME_TYPE_DATE:
        $format = DateTimeItemInterface::DATE_STORAGE_FORMAT;
        break;

      default:
        $format = DateTimeItemInterface::DATETIME_STORAGE_FORMAT;
        break;
    }

    foreach ($values as &$item) {
      if (!empty($item['cut_off']) && $item['cut_off'] instanceof DrupalDateTime) {
        $date = $item['cut_off'];
        // Adjust the date for storage.
        $date->setTimezone(new \DateTimezone(DateTimeItemInterface::STORAGE_TIMEZONE));
        $item['cut_off'] = $date->format($format);
      }

      if (empty($item['use_confirmed'])) {
        $item['cut_off_confirmed'] = $item['cut_off'];
      }
      elseif (!empty($item['cut_off_confirmed']) && $item['cut_off_confirmed'] instanceof DrupalDateTime) {
        $date = $item['cut_off_confirmed'];
        // Adjust the date for storage.
        $date->setTimezone(new \DateTimezone(DateTimeItemInterface::STORAGE_TIMEZONE));
        $item['cut_off_confirmed'] = $date->format($format);
      }
    }
    return $values;
  }

  /**
   * Creates a date object for use as a default value.
   *
   * This will take a default value, apply the proper timezone for display in
   * a widget, and set the default time for date-only fields.
   *
   * @param \Drupal\Core\Datetime\DrupalDateTime $date
   *   The UTC default date.
   * @param string $timezone
   *   The timezone to apply.
   *
   * @return \Drupal\Core\Datetime\DrupalDateTime
   *   A date object for use as a default value in a field widget.
   */
  protected function createDefaultValue(DrupalDateTime $date, $timezone): DrupalDateTime {
    // The date was created and verified during field_load(), so it is safe to
    // use without further inspection.
    if ($this->getFieldSetting('datetime_type') === DateTimeItem::DATETIME_TYPE_DATE) {
      $date->setDefaultDateTime();
    }
    $date->setTimezone(new \DateTimeZone($timezone));
    return $date;
  }

}

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

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