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

src/Entity/Ticket.php
<?php

namespace Drupal\contacts_events\Entity;

use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\commerce_price\Price;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\contacts_events\Event\TicketContactAcquisitionEvent;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Link;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
use Drupal\decoupled_auth\AcquisitionService;
use Drupal\user\UserInterface;

/**
 * Defines the Ticket entity.
 *
 * @ContentEntityType(
 *   id = "contacts_ticket",
 *   label = @Translation("Ticket"),
 *   bundle_label = @Translation("Ticket type"),
 *   handlers = {
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "list_builder" = "Drupal\contacts_events\TicketListBuilder",
 *     "views_data" = "Drupal\contacts_events\Entity\TicketViewsData",
 *     "form" = {
 *       "default" = "Drupal\contacts_events\Form\TicketForm",
 *       "add" = "Drupal\contacts_events\Form\TicketForm",
 *       "edit" = "Drupal\contacts_events\Form\TicketForm",
 *       "delete" = "Drupal\contacts_events\Form\TicketDeleteForm",
 *       "transfer" = "Drupal\contacts_events\Form\TransferForm",
 *     },
 *     "access" = "Drupal\contacts_events\TicketAccessControlHandler",
 *     "route_provider" = {
 *       "html" = "Drupal\contacts_events\TicketHtmlRouteProvider",
 *     },
 *     "inline_form" = "Drupal\contacts_events\Form\TicketInlineForm"
 *   },
 *   base_table = "contacts_ticket",
 *   admin_permission = "administer contacts_ticket entities",
 *   entity_keys = {
 *     "id" = "id",
 *     "bundle" = "type",
 *     "uuid" = "uuid",
 *     "uid" = "creator",
 *   },
 *   links = {
 *     "canonical" = "/admin/content/tickets/{contacts_ticket}",
 *     "add-page" = "/admin/content/tickets/add",
 *     "add-form" = "/admin/content/tickets/{contacts_ticket_type}/add",
 *     "edit-form" = "/admin/content/tickets/{contacts_ticket}/edit",
 *     "transfer-form" = "/admin/content/tickets/{contacts_ticket}/transfer",
 *     "delete-form" = "/admin/content/tickets/{contacts_ticket}/delete",
 *     "collection" = "/admin/content/tickets",
 *   },
 *   bundle_entity_type = "contacts_ticket_type",
 *   field_ui_base_route = "entity.contacts_ticket_type.edit_form"
 * )
 */
class Ticket extends ContentEntityBase implements TicketInterface {

  use EntityChangedTrait;
  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public static function preCreate(EntityStorageInterface $storage_controller, array &$values) {
    parent::preCreate($storage_controller, $values);
    $values += [
      'creator' => \Drupal::currentUser()->id(),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function label() {
    $name = $this->getName();
    $event = $this->getEvent();
    $booking = $this->getBooking();
    $booking_replacement = $booking ? new FormattableMarkup(' [@booking]', ['@booking' => $this->getBooking()->label()]) : '';

    if ($name && $event) {
      return new TranslatableMarkup('Ticket for @name at @event@booking', [
        '@name' => $name,
        '@event' => $event->label(),
        '@booking' => $booking_replacement,
      ]);
    }
    elseif ($event || $name) {
      return new TranslatableMarkup('Ticket for @descriptor@booking', [
        '@descriptor' => $event ? $event->label() : $name,
        '@booking' => $booking_replacement,
      ]);
    }
    else {
      return $this->t('Unknown ticket@booking', ['@booking' => $booking_replacement]);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getName($type = 'default') {
    $name = $this->get('name');
    if (!$name->isEmpty()) {
      // @todo Replace this with the new service once a tagged release is made
      // available: https://www.drupal.org/project/name/issues/2949574
      $format = name_get_format_by_machine_name('default');
      $parser = \Drupal::service('name.format_parser');
      $name = $parser->parse($this->get('name')->get(0)->getValue(), $format, [
        'object' => $this,
        'type' => $this->getEntityTypeId(),
        'markup' => FALSE,
      ]);
      return _name_value_sanitize($name, NULL, $type);
    }
  }

  /**
   * Get the name, as a link to the contact if applicable, from the order item.
   *
   * @param \Drupal\commerce_order\Entity\OrderItemInterface $order_item
   *   The order item.
   *
   * @return string
   *   The name, as a link if the ticket is linked to a Contact and the current
   *   user has permission to access the contact dashboard.
   */
  public static function getNameLinkFromOrderItem(OrderItemInterface $order_item) {
    if ($order_item->bundle() != 'contacts_ticket') {
      throw new \InvalidArgumentException('Order item must be of the contacts_ticket bundle.');
    }

    /** @var \Drupal\contacts_events\Entity\TicketInterface $ticket */
    $ticket = $order_item->getPurchasedEntity();
    if (!$ticket) {
      throw new \InvalidArgumentException('Order item must have a ticket.');
    }

    $uid = $ticket->get('contact')->target_id;
    $name = $ticket->getName();
    if (!$uid || !\Drupal::currentUser()->hasPermission('view contacts')) {
      return $name;
    }

    return Link::createFromRoute($name,
      'contacts.contact',
      ['user' => $uid],
    )->toString();
  }

  /**
   * {@inheritdoc}
   */
  public function getOrderItem() {
    return $this->get('order_item')->entity;
  }

  /**
   * {@inheritdoc}
   */
  public function setOrderItem(OrderItemInterface $order_item) {
    return $this->set('order_item', $order_item);
  }

  /**
   * {@inheritdoc}
   */
  public function getBooking() {
    $order_item = $this->getOrderItem();
    return $order_item ? $order_item->getOrder() : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getEvent() {
    return $this->get('event')->entity;
  }

  /**
   * {@inheritdoc}
   */
  public function onChange($name) {
    parent::onChange($name);

    // Update the event if the booking changes.
    if ($name == 'order_item') {
      $event = $this->get('order_item')->entity
        ->getOrder()
        ->get('event')->target_id;
      $this->set('event', $event);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function preSave(EntityStorageInterface $storage) {
    // Run acquisitions prior to the ticket being saved.
    // Only perform acquisition if an email is specified.
    if (!empty($this->get('email')->value)) {

      // If the email has changed, we need to re-acquire.
      /** @var \Drupal\contacts_events\Entity\Ticket $original */
      $original = !empty($this->id()) ? $storage->loadUnchanged($this->id()) : NULL;

      if (!empty($this->get('contact')->target_id) && isset($original)) {
        $new_email = $this->get('email')->value;
        $original_email = $original->get('email')->value;

        if (($new_email xor $original_email) || $new_email != $original_email) {
          $this->set('contact', NULL);
        }
      }

      $this->acquire();
    }

    // Ensure the ticket has the latest mapped price from the order item, if
    // one exists.
    $order_item = $this->getOrderItem();
    if ($order_item && !$order_item->get('mapped_price')->isEmpty()) {
      $this->setMappedPrice($order_item->get('mapped_price')->first()->getValue());
    }

    parent::preSave($storage);
  }

  /**
   * {@inheritdoc}
   */
  public function acquire($early = FALSE) {
    /** @var \Drupal\Core\Entity\EntityInterface $contact */
    // Ensure any linked contact exists.
    if (!empty($this->get('contact')->target_id)) {
      $acquisition_method = 'update';
      $contact = $this->get('contact')->entity;
      if (!$contact) {
        $this->set('contact', NULL);
      }
    }

    // If we don't have a contact, look for one.
    if (empty($this->get('contact')->target_id)) {
      $values = [];

      if (!empty($this->get('email')->value)) {
        $values['mail'] = $this->get('email')->value;
      }

      $context = [
        'name' => 'contacts_events_ticket',
        'ticket' => $this,
        // Always prefer coupled and allow acquiring protected roles.
        'behavior' => AcquisitionService::BEHAVIOR_PREFER_COUPLED | AcquisitionService::BEHAVIOR_INCLUDE_PROTECTED_ROLES,
      ];

      // In early acquisitions, we don't want to create a contact.
      if (!$early) {
        $context['behavior'] = $context['behavior'] | AcquisitionService::BEHAVIOR_CREATE;
      }

      // Use the global config for first behavior.
      if (\Drupal::config('decoupled_auth.settings')->get('acquisitions.behavior_first')) {
        $context['behavior'] = $context['behavior'] | AcquisitionService::BEHAVIOR_FIRST;
      }

      /** @var \Drupal\decoupled_auth\AcquisitionService $service */
      $service = \Drupal::service('decoupled_auth.acquisition');
      $contact = $service->acquire($values, $context, $acquisition_method);
    }

    // If we have no contact, there is nothing further to do.
    if (empty($contact)) {
      return;
    }

    // In early acquitions, we don't want to update details.
    if ($early) {
      $this->set('contact', $contact);
      return;
    }

    // If creating, we need to save before updating details.
    if ($acquisition_method == 'create') {
      // Save the new contact so we have an ID available to pass to the event.
      $contact->save();
    }

    // Raise an event to allow subscribers to attach profiles to the new entity.
    // By default we have a single subscriber that creates the Individual
    // profile.
    /* @see \Drupal\contacts_events\EventSubscriber\CreateIndividualProfileOnTicketAcquisition */
    /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher*/
    $dispatcher = \Drupal::service('event_dispatcher');
    $event = new TicketContactAcquisitionEvent($this, $contact, $acquisition_method);
    $dispatcher->dispatch(TicketContactAcquisitionEvent::NAME,
      $event);

    // Save any profiles that were attached to the user.
    foreach ($event->entitiesToSave as $entity) {
      $entity->save();
    }

    $this->set('contact', $contact);
  }

  /**
   * {@inheritdoc}
   */
  public function getCreatedTime() {
    return $this->get('created')->value;
  }

  /**
   * {@inheritdoc}
   */
  public function setCreatedTime($timestamp) {
    $this->set('created', $timestamp);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getTicketHolder() : ?UserInterface {
    return $this->get('contact')->entity;
  }

  /**
   * {@inheritdoc}
   */
  public function getTicketHolderId() : ?int {
    return $this->get('contact')->target_id;
  }

  /**
   * {@inheritdoc}
   */
  public function setTicketHolderId($uid) {
    $this->set('contact', $uid);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setTicketHolder(UserInterface $account) {
    $this->set('contact', $account->id());
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getStores() {
    $storage = \Drupal::entityTypeManager()->getStorage('commerce_store');
    $id = \Drupal::config('contacts_events.booking_settings')->get('store_id');
    return $storage->loadMultiple([$id]);
  }

  /**
   * {@inheritdoc}
   */
  public function getOrderItemTypeId() {
    return 'contacts_ticket';
  }

  /**
   * {@inheritdoc}
   */
  public function getOrderItemTitle() {
    // In the context of a booking, we only want the name.
    if ($name = $this->getName('raw')) {
      return 'Ticket for ' . $name;
    }
    else {
      return 'Ticket';
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getPrice() {
    return $this->getPriceOverride() ?? $this->getCalculatedPrice();
  }

  /**
   * {@inheritdoc}
   */
  public function getMappedPrice() {
    $items = $this->get('mapped_price');
    return $items->count() ? $items->first()->getValue() : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function setMappedPrice(array $mapped_price) {
    $this->set('mapped_price', $mapped_price);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getPriceOverride() {
    if (!$this->get('price_override')->isEmpty()) {
      return $this->get('price_override')->first()->toPrice();
    }
    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getCalculatedPrice() {
    if (!$this->get('price')->isEmpty()) {
      return $this->get('price')->first()->toPrice();
    }

    return new Price(0, $this->getDefaultCurrencyCode());
  }

  /**
   * {@inheritdoc}
   */
  public function setCalculatedPrice(Price $price = NULL) {
    $this->set('price', $price->toArray());
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getStatus() {
    $order_item = $this->getOrderItem();
    return $order_item ? $order_item->get('state')->value : 'pending';
  }

  /**
   * {@inheritdoc}
   */
  public function getConfirmedDate() {
    $order_item = $this->getOrderItem();
    return $order_item ? $order_item->get('confirmed')->value : NULL;
  }

  /**
   * Get the default currency code.
   *
   * @return string
   *   The default currency code.
   */
  protected function getDefaultCurrencyCode() {
    $stores = $this->getStores();
    $store = reset($stores);
    return $store->getDefaultCurrencyCode();
  }

  /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);

    $fields['contact'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Contact'))
      ->setDescription(t('The contact this ticket is for.'))
      ->setRevisionable(TRUE)
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->addConstraint('UniqueFieldValueForEventTicket', [
        'groupingField' => 'event',
        'message' => 'A @entity_type with @field_name %value_label already exists for this event.',
      ])
      ->setDisplayOptions('form', [
        'type' => 'entity_reference_autocomplete',
        'settings' => [
          'match_operator' => 'CONTAINS',
          'size' => '60',
          'placeholder' => '',
        ],
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['order_item'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Order item'))
      ->setDescription(t('The order item this ticket is on.'))
      ->setSetting('target_type', 'commerce_order_item')
      ->setSetting('handler_settings', ['target_bundles' => ['contacts_ticket']])
      ->setSetting('handler', 'default')
      ->setDisplayOptions('form', ['region' => 'hidden'])
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['event'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Event'))
      ->setDescription(t('The event this ticket is for.'))
      ->setRequired(TRUE)
      ->setRevisionable(TRUE)
      ->setSetting('target_type', 'contacts_event')
      ->setSetting('handler', 'default')
      ->setDisplayOptions('form', ['region' => 'hidden'])
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['price_override'] = BaseFieldDefinition::create('commerce_price')
      ->setLabel(t('Price override'))
      ->setDescription(t('The manual price override for this ticket.'))
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'commerce_price_default',
      ])
      ->setDisplayOptions('form', [
        'type' => 'commerce_price_default',
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['price'] = BaseFieldDefinition::create('commerce_price')
      ->setLabel(t('Price'))
      ->setDescription(t('The calculated price for this ticket.'))
      ->setRequired(TRUE)
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'commerce_price_default',
      ])
      ->setDisplayOptions('form', ['region' => 'hidden'])
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['mapped_price'] = BaseFieldDefinition::create('mapped_price_data')
      ->setLabel(new TranslatableMarkup('Mapped price'))
      ->setRequired(TRUE)
      ->setDisplayOptions('view', [
        'label' => 'hidden',
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['creator'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Added by'))
      ->setDescription(t('The user who added this ticket.'))
      ->setRequired(TRUE)
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->setDisplayOptions('form', ['region' => 'hidden'])
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['created'] = BaseFieldDefinition::create('created')
      ->setLabel(t('Created'))
      ->setDescription(t('The time that the entity was created.'))
      ->setDisplayOptions('form', ['region' => 'hidden'])
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE);
    ;

    $fields['changed'] = BaseFieldDefinition::create('changed')
      ->setLabel(t('Changed'))
      ->setDescription(t('The time that the entity was last edited.'))
      ->setDisplayOptions('form', ['region' => 'hidden'])
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['name'] = BaseFieldDefinition::create('name')
      ->setLabel(t('Name'))
      ->setDescription(t("Ticket holder's name."))
      ->setRequired(TRUE)
      ->setSetting('components', [
        'title' => TRUE,
        'given' => TRUE,
        'middle' => FALSE,
        'family' => TRUE,
        'generational' => FALSE,
        'credentials' => FALSE,
      ])
      ->setSetting('labels', [
        'title' => new TranslatableMarkup('Title'),
        'given' => new TranslatableMarkup('First name'),
        'family' => new TranslatableMarkup('Surname'),
      ])
      ->setSetting('show_component_required_marker', TRUE)
      ->setSetting('title_display', [
        'title' => 'title',
        'given' => 'title',
        'family' => 'title',
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['email'] = BaseFieldDefinition::create('email')
      ->setLabel(t('Email'))
      ->setDescription(t("Ticket holder's email address."))
      ->addConstraint('UniqueFieldValueForEventTicket', [
        'groupingField' => 'event',
        'message' => 'A @entity_type with @field_name %value already exists for this event.',
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['date_of_birth'] = BaseFieldDefinition::create('datetime')
      ->setLabel(t('Date of birth'))
      ->setDescription(t("Ticket holder's date of birth."))
      ->setSetting('datetime_type', DateTimeItem::DATETIME_TYPE_DATE)
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    return $fields;
  }

}

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

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