contacts_events-8.x-1.x-dev/src/Plugin/Field/FieldType/BookingWindowsItemList.php

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

namespace Drupal\contacts_events\Plugin\Field\FieldType;

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Form\FormStateInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;

/**
 * Represents the booking windows field.
 */
class BookingWindowsItemList extends FieldItemList {

  /**
   * {@inheritdoc}
   *
   * @var \Drupal\contacts_events\Plugin\Field\FieldType\BookingWindowsItem[]
   */
  protected $list = [];

  /**
   * {@inheritdoc}
   */
  public function getConstraints() {
    $constraints = parent::getConstraints();

    $constraints[] = $this->getTypedDataManager()
      ->getValidationConstraintManager()
      ->create('BookingWindowsUnique', []);

    return $constraints;
  }

  /**
   * {@inheritdoc}
   */
  public function preSave() {
    parent::preSave();
    usort($this->list, [$this, 'sortItems']);
  }

  /**
   * Sorting callback for booking windows.
   *
   * Will sort by cut off confirmed ascending, cut off ascending, with NULL cut
   * offs last.
   *
   * @param \Drupal\contacts_events\Plugin\Field\FieldType\BookingWindowsItem $a
   *   The first booking window.
   * @param \Drupal\contacts_events\Plugin\Field\FieldType\BookingWindowsItem $b
   *   The second booking window.
   *
   * @return int
   *   The sort comparison result.
   */
  public static function sortItems(BookingWindowsItem $a, BookingWindowsItem $b) {
    // Start by comparing the confirmed cut off (the earlier).
    $a_cut_off_confirmed = $a->cut_off_confirmed ?? 'A';
    $b_cut_off_confirmed = $b->cut_off_confirmed ?? 'A';
    if ($a_cut_off_confirmed !== $b_cut_off_confirmed) {
      return $a_cut_off_confirmed <=> $b_cut_off_confirmed;
    }

    // Then compare the paid in full cut off.
    $a_cut_off = $a->cut_off ?? 'A';
    $b_cut_off = $b->cut_off ?? 'A';
    return $a_cut_off <=> $b_cut_off;
  }

  /**
   * A machine name callback for checking the uniqueness of IDs.
   *
   * @param string $value
   *   The ID being checked.
   * @param array $element
   *   The element array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return bool
   *   Whether the ID is unique.
   */
  public static function checkUnique($value, array $element, FormStateInterface $form_state) {
    $parents = $element['#parents'];
    array_pop($parents);
    $delta_checking = array_pop($parents);

    $submitted_values = $form_state->getValue($parents);
    foreach ($submitted_values as $delta => $values) {
      if (in_array($delta, [$delta_checking, 'add_more'])) {
        continue;
      }

      if ($values['id'] == $value) {
        return TRUE;
      }
    }

    return FALSE;
  }

  /**
   * Find the appropriate window for a specific date.
   *
   * @param \Drupal\Core\Datetime\DrupalDateTime|null $confirmed_date
   *   The date the item was confirmed, or NULL if it's not.
   * @param \Drupal\Core\Datetime\DrupalDateTime|null $comparison_date
   *   The date to check against, or NULL to use now.
   *
   * @return \Drupal\contacts_events\Plugin\Field\FieldType\BookingWindowsItem|null
   *   The booking window item, or NULL if none is found.
   */
  public function findWindow(?DrupalDateTime $confirmed_date, DrupalDateTime $comparison_date = NULL): ?BookingWindowsItem {
    if ($this->isEmpty()) {
      return NULL;
    }

    if (!isset($comparison_date)) {
      $comparison_date = new DrupalDateTime();
    }

    // If the ticket is not yet confirmed, treat it as though it is confirmed
    // on the comparison date.
    if (!isset($confirmed_date)) {
      $confirmed_date = $comparison_date;
    }

    // If our precision is by day, set our time to 00:00:00.
    if ($this->getSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) {
      $comparison_date->setTime(0, 0, 0);
      $confirmed_date->setTime(0, 0, 0);
    }

    // Ensure booking windows are sorted.
    usort($this->list, [$this, 'sortItems']);

    // Loop through until we find our match.
    foreach ($this->list as $window) {
      // If we have a paid in full date, ensure we are not past that.
      if ($window->cut_off && $window->date < $comparison_date) {
        continue;
      }

      // Ensure the item was confirmed in time.
      if ($window->cut_off_confirmed && $window->date_confirmed < $confirmed_date) {
        continue;
      }

      // Otherwise we have a match, so return the window.
      return $window;
    }

    return NULL;
  }

}

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

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