commerce_donation_flow-1.0.x-dev/src/Plugin/Commerce/CheckoutPane/DonationItemPaneBase.php

src/Plugin/Commerce/CheckoutPane/DonationItemPaneBase.php
<?php

namespace Drupal\commerce_donation_flow\Plugin\Commerce\CheckoutPane;

use Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneBase;
use Drupal\commerce_donation_flow\Exception\MissingDonationItemException;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\Core\Form\FormStateInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Class DonationItemPaneBase holds common donation pane methods.
 *
 * This class is meant to be extended, and appropriate annotations added
 * in the extending class.
 *
 * @package Drupal\commerce_donation_flow\Plugin\Commerce\CheckoutPane
 */
class DonationItemPaneBase extends CheckoutPaneBase {

  /**
   * Injected service: Used to detect if Field Group module is installed.
   *
   * @var \Drupal\Core\Extension\ModuleHandler
   */
  protected $moduleHandler;

  /**
   * FormDisplay object for this pane.
   *
   * @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface
   */
  protected $formDisplay;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, CheckoutFlowInterface $checkout_flow = NULL) {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition, $checkout_flow);
    // Parent constructor populates $this->order.
    $instance->moduleHandler = $container->get('module_handler');
    return $instance;
  }

  /**
   * Method to retrieve the donation item from the order.
   *
   * @return \Drupal\commerce_order\Entity\OrderItemInterface|null
   *   Return the donation item or null if there are none.
   *
   * @throws \LengthException
   */
  protected function getDonationItem(): ?OrderItemInterface {
    // Guard for missing order in the pane. This plugin seems to occasionally
    // get instantiated early and then re-instantiated by Commerce.
    if (!($this->order instanceof OrderInterface)) {
      return NULL;
    }
    // Sift through order items to find donation bundles.
    $donations = array_filter($this->order->getItems(), function ($item) {
      return $item->bundle() == 'donation';
    });
    // Ensure we have only 1.
    $count = count($donations);
    if ($count > 1) {
      throw new \LengthException('An order may only contain a single donation item.');
    }
    elseif ($count === 1) {
      return reset($donations);
    }
    // Count must be 0.
    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function isVisible() {
    $item = $this->getDonationItem();
    return $item instanceof OrderItemInterface;
  }

  /**
   * Setter used in extending classes.
   *
   * @param string $displayMode
   *   The display mode id.
   */
  protected function setFormDisplay($displayMode = 'default') {
    $donationItem = $this->getDonationItem();
    if ($donationItem instanceof OrderItemInterface) {
      $this->formDisplay = EntityFormDisplay::collectRenderDisplay(
        $donationItem,
        $displayMode
      );
    }
  }

  /**
   * {@inheritdoc}
   */
  public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
    $donationItem = $this->getDonationItem();
    if (!($this->formDisplay instanceof EntityFormDisplayInterface)) {
      // Setting this conditionally so that extending classes can explicitly
      // set this service, but we can reliably depend on it being present.
      $this->setFormDisplay();
    }
    if ($donationItem instanceof OrderItemInterface) {
      // The purpose of this pane is to display an edit form on the donation
      // item entity.  This form should not be visible if there is not such
      // an entity, however multiple lines below will fail, so setting a
      // guard.
      $pane_form['#title_display'] = 'invisible';
      // Check for ajax build.
      $input = $form_state->getUserInput();
      if (isset($input[AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER])) {
        // Render any status messages:
        $pane_form['messages'] = [
          '#type' => 'status_messages',
          '#weight' => -90,
        ];
      }
      $this->formDisplay->buildForm($donationItem, $pane_form, $form_state);
    }
    return $pane_form;
  }

  /**
   * {@inheritdoc}
   */
  public function validatePaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
    // Our form comes from the entity form builder.
    $donationItem = $this->getDonationItem();
    if ($donationItem instanceof OrderItemInterface) {
      $form_state->cleanValues();
      $this->buildDonationItem($pane_form, $form_state, $donationItem);
      $this->formDisplay->validateFormValues($donationItem, $pane_form, $form_state);
      $form_state->set('donation_item', $donationItem);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitPaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
    $donationItem = $form_state->get('donation_item');
    if ($donationItem instanceof OrderItemInterface) {
      $donationItem->save();
    }
    else {
      // Allow extending panes to catch an Exception if desired to deal with
      // a missing donation OrderItem.
      throw new MissingDonationItemException('Instance of OrderItemInterface not stored as `donation_item` in FormState');
    }
  }

  /**
   * Builds an updated OrderItem object based upon the submitted form values.
   *
   * Based on \Drupal\inline_entity_form\Form\EntityInlineForm::buildEntity:
   *
   * @param array $paneForm
   *   The entity form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param \Drupal\commerce_order\Entity\OrderItemInterface $donationItem
   *   The donation item we are updating.
   *
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   * @throws \Drupal\Core\TypedData\Exception\ReadOnlyException
   */
  protected function buildDonationItem(array $paneForm, FormStateInterface $form_state, OrderItemInterface $donationItem) {
    if (!($this->formDisplay instanceof EntityFormDisplayInterface)) {
      // Setting this conditionally so that extending classes can explicitly
      // set this service, but we can reliably depend on it being present.
      $this->setFormDisplay();
    }
    $this->formDisplay->extractFormValues($donationItem, $paneForm, $form_state);
    if ($donationItem->hasField('field_donation_amount') && !$donationItem->field_donation_amount->isEmpty()) {
      $price = $donationItem->field_donation_amount->first()->toPrice();
      $donationItem->setUnitPrice($price, TRUE);
    }
    $donationTitle = $donationItem->getTitle();
    if ($donationItem->hasField('field_gift_type')) {
      $donationTitle .= ' - ';
      $donationTitle .= $donationItem->field_gift_type->value;
      $recurringValue = NULL;
      if ($donationItem->hasField('field_recurring_begins') && $donationItem->field_gift_type->value == 'recurring') {
        $timezone = date_default_timezone_get();
        $setTime = new DrupalDateTime('+1 month', $timezone);
        // Adjust the date for storage.
        $setTime->setTimezone(new \DateTimezone(DateTimeItemInterface::STORAGE_TIMEZONE));
        $recurringValue = $setTime->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
        $donationItem->field_recurring_begins->setValue(['value' => $recurringValue]);
      }
    }
    $donationItem->setTitle($donationTitle);
    // Invoke all specified builders for copying form values to entity fields.
    if (isset($paneForm['#entity_builders'])) {
      foreach ($paneForm['#entity_builders'] as $function) {
        call_user_func_array(
          $function,
          [
            $donationItem->getEntityTypeId(),
            $donationItem,
            &$paneForm,
            &$form_state,
          ]
        );
      }
    }
  }

  /**
   * Helper method to build the pane summary given a view mode.
   *
   * @param string $viewMode
   *   The view mode to build.
   *
   * @return array
   *   The render array.
   */
  protected function doSummaryBuild($viewMode) {
    $donationItem = $this->getDonationItem();
    if (!($donationItem instanceof OrderItemInterface)) {
      return [];
    }
    $viewBuilder = $this->entityTypeManager->getViewBuilder($donationItem->getEntityTypeId());
    $entityView = $viewBuilder->view($donationItem, $viewMode, $donationItem->language()
      ->getId());
    $renderArray = $viewBuilder->build($entityView);
    $build = [
      'summary' => [
        '#theme' => 'commerce_donation_flow_summary',
        '#content' => $renderArray,
        '#attributes' => [
          'class' => [
            'donation-summary--' . Html::cleanCssIdentifier(strtolower($this->getId())),
          ],
        ],
      ],
    ];
    return $build;
  }

}

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

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