contacts_events-8.x-1.x-dev/src/Entity/EventClass.php

src/Entity/EventClass.php
<?php

namespace Drupal\contacts_events\Entity;

use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\Component\Datetime\DateTimePlus;
use Drupal\Core\Config\Entity\ConfigEntityBase;

/**
 * Defines the Class entity.
 *
 * @ConfigEntityType(
 *   id = "contacts_events_class",
 *   label = @Translation("Class"),
 *   handlers = {
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "list_builder" = "Drupal\contacts_events\EventClassListBuilder",
 *     "form" = {
 *       "add" = "Drupal\contacts_events\Form\EventClassForm",
 *       "edit" = "Drupal\contacts_events\Form\EventClassForm",
 *       "delete" = "Drupal\contacts_events\Form\EventClassDeleteForm"
 *     },
 *     "route_provider" = {
 *       "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
 *     },
 *   },
 *   config_prefix = "contacts_events_class",
 *   admin_permission = "administer site configuration",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label",
 *     "uuid" = "uuid",
 *     "weight" = "weight"
 *   },
 *   config_export = {
 *     "id",
 *     "label",
 *     "type",
 *     "weight",
 *     "selectable",
 *     "min_age",
 *     "max_age",
 *     "bypass_age_check_on_empty_dob"
 *   },
 *   links = {
 *     "canonical" = "/admin/structure/event-classes/{contacts_events_class}",
 *     "add-form" = "/admin/structure/event-classes/add",
 *     "edit-form" = "/admin/structure/event-classes/{contacts_events_class}/edit",
 *     "delete-form" = "/admin/structure/event-classes/{contacts_events_class}/delete",
 *     "collection" = "/admin/structure/event-classes"
 *   }
 * )
 */
class EventClass extends ConfigEntityBase implements EventClassInterface {

  /**
   * The unique ID of the event class.
   *
   * @var string
   */
  protected $id;

  /**
   * The label of the event class.
   *
   * @var string
   */
  protected $label;

  /**
   * The type this class is for.
   *
   * @var string
   */
  protected $type;

  /**
   * The weight of this class.
   *
   * @var int
   */
  protected $weight;

  /**
   * Whether this class is selectable.
   *
   * @var bool
   */
  protected $selectable;

  /**
   * Minimum age for calculation (inclusive).
   *
   * @var bool
   */
  protected $min_age;

  /**
   * Maximum age for calculation (inclusive).
   *
   * @var bool
   */
  protected $max_age;

  /**
   * Bypass the age check when date of birth is empty.
   *
   * @var bool
   */
  protected $bypass_age_check_on_empty_dob;

  /**
   * {@inheritdoc}
   */
  public function evaluate(OrderItemInterface $order_item) {
    // Check that we are using the right order type.
    if ($this->type != 'global' && $this->type != $order_item->bundle()) {
      return FALSE;
    }

    $implementations = \Drupal::moduleHandler()
      ->getImplementations('contacts_events_class_evaluate');

    foreach ($implementations as $module) {
      $function = $module . '_contacts_events_class_evaluate';
      $result = $function($order_item, $this);
      if ($result === TRUE || $result === FALSE) {
        return $result;
      }
    }

    if ($this->type == 'contacts_ticket') {
      return $this->evaluateTicketHolderAge($order_item);
    }

    return TRUE;
  }

  /**
   * Evaluates whether the event class applies based on age calculation.
   *
   * @param \Drupal\commerce_order\Entity\OrderItemInterface $order_item
   *   The current order item.
   *
   * @return bool
   *   True if the ticketholder is within the class's age range, otherwise
   *   False.
   */
  protected function evaluateTicketHolderAge(OrderItemInterface $order_item) : bool {
    // If no min/max age specified, immediately allow.
    if ($this->min_age === NULL && $this->max_age === NULL) {
      return TRUE;
    }

    /** @var \Drupal\contacts_events\Entity\Ticket $ticket */
    // Don't use $order_item->getPurchasedEntity() or it can end up with a
    // cached version of the ticket, rather than the updated version.
    $ticket = $order_item->get('purchased_entity')->entity;

    if (!$ticket) {
      throw new \Exception("Order item {$order_item->id()} has no ticket.");
    }

    /** @var \Drupal\contacts_events\Entity\Event $event */
    $event = $ticket->getEvent();

    /** @var \Drupal\Core\Datetime\DrupalDateTime $comparison_date */
    $comparison_date = NULL;

    // If the event has a class_calculation_date, use that.
    if ($event->hasField('class_calculation_date')) {
      if (!$event->get('class_calculation_date')->isEmpty()) {
        $comparison_date = $event->get('class_calculation_date')->date;
      }
    }

    // Otherwise use the event start date.
    if ($comparison_date === NULL) {
      $comparison_date = $event->get('date')->start_date;
    }

    // Check the ticket holder has a DOB.
    $dob = $ticket->get('date_of_birth')->date;

    if (!$dob) {
      if ($this->bypass_age_check_on_empty_dob) {
        return TRUE;
      }

      return FALSE;
    }

    // Calculate age as of the comparison date.
    $age = static::calculateAge($dob, $comparison_date);

    // Only do the min age comparison if it's been specified.
    // Age range is inclusive.
    if ($this->min_age !== NULL && $age < $this->min_age) {
      return FALSE;
    }

    // Only do the max age comparison if it's been specified.
    // Age range is inclusive.
    if ($this->max_age !== NULL && $age > $this->max_age) {
      return FALSE;
    }

    return TRUE;
  }

  /**
   * Calculates age.
   *
   * @param \Drupal\Component\Datetime\DateTimePlus $dob
   *   Date of birth.
   * @param \Drupal\Component\Datetime\DateTimePlus $comparison_date
   *   Date to calculate age at.
   *
   * @return int
   *   Age in integer years.
   */
  public static function calculateAge(DateTimePlus $dob, DateTimePlus $comparison_date): int {
    // Clone the dates so we don't modify the originals as DateTimePlus
    // uses \DateTime rather than \DateTimeImmutable under the covers.
    $dob = clone $dob;
    $comparison_date = clone $comparison_date;

    // Set both times to midday.
    $dob->setDefaultDateTime();
    $comparison_date->setDefaultDateTime();

    $diff = $dob->diff($comparison_date);
    return $diff->y;
  }

  /**
   * Find the appropriate class for an order item.
   *
   * @param \Drupal\contacts_events\Entity\EventClassInterface[] $classes
   *   An array of classes.
   * @param \Drupal\commerce_order\Entity\OrderItemInterface $order_item
   *   The order item to check.
   *
   * @return \Drupal\contacts_events\Entity\EventClassInterface|null
   *   The matching class or NULL if there is no match.
   */
  public static function findClass(array $classes, OrderItemInterface $order_item) {
    // Ensure our items are sorted.
    uasort($classes, [static::class, 'sort']);

    // Loop over until we find a match.
    foreach ($classes as $class) {
      if ($class->evaluate($order_item)) {
        return $class;
      }
    }
  }

}

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

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