commerce_multi_payment-8.x-1.x-dev/modules/multi_payment_example/src/Plugin/Commerce/InlineForm/StoreCreditForm.php

modules/multi_payment_example/src/Plugin/Commerce/InlineForm/StoreCreditForm.php
<?php

namespace Drupal\commerce_multi_payment_example\Plugin\Commerce\InlineForm;

use Drupal\commerce\Plugin\Commerce\InlineForm\InlineFormBase;
use Drupal\commerce_multi_payment\MultiplePaymentManagerInterface;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_payment\Exception\DeclineException;
use Drupal\commerce_payment\Exception\HardDeclineException;
use Drupal\commerce_price\Price;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides an inline form for redeeming a coupon.
 *
 * @CommerceInlineForm(
 *   id = "commerce_multi_payment_example_storecredit_form",
 *   label = @Translation("Store credit example form"),
 * )
 */
class StoreCreditForm extends InlineFormBase {

  /**
   * @var \Drupal\commerce_multi_payment\MultiplePaymentManagerInterface
   */
  protected $multiPaymentManager;


  /**
   * Constructs a new CouponRedemption object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\commerce_multi_payment\MultiplePaymentManagerInterface $multi_payment_manager
   *   The multiple payments manager
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MultiplePaymentManagerInterface $multi_payment_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);

    $this->multiPaymentManager = $multi_payment_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('commerce_multi_payment.manager'),
      $container->get('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'order_id' => '',
      'payment_gateway_id' => '',
      'balance' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  protected function requiredConfiguration() {
    return ['order_id', 'payment_gateway_id', 'balance'];
  }

  /**
   * {@inheritdoc}
   */
  public function buildInlineForm(array $inline_form, FormStateInterface $form_state) {

    $inline_form = parent::buildInlineForm($inline_form, $form_state);

    $order = $this->multiPaymentManager->loadOrder($this->configuration['order_id']);
    if (!$order) {
      throw new \RuntimeException('Invalid order_id given to the store credit inline form.');
    }
    assert($order instanceof OrderInterface);

    $payment_gateway_plugin = $this->multiPaymentManager->loadPaymentGatewayPlugin($this->configuration['payment_gateway_id']);

    $staged_payment = NULL;

    $staged_payments = $this->multiPaymentManager->getStagedPaymentsFromOrder($order, $this->configuration['payment_gateway_id']);
    if (!empty($staged_payments)) {
      $staged_payment = reset($staged_payments);
      try {
        // Remove store credit if it is no longer valid.
        $balance = $payment_gateway_plugin->getBalance($staged_payment->getOrder()->getCustomerId());
        if ($balance->lessThan($staged_payment->getAmount())) {
          throw new HardDeclineException("Store credit balance is less than requested amount.");
        }
      }
      catch (DeclineException $e) {
        $order = $staged_payment->getOrder();
        $staged_payment->delete();
        $order->save();
        $staged_payment = NULL;
      }
    }

    $balance = $payment_gateway_plugin->getBalance($order->getCustomerId());
    if ($balance !== NULL && $balance->getNumber() > 0) {
      $inline_form = [
        '#tree' => TRUE,
        '#theme' => 'commerce_multi_payment_example_storecredit_form',
        '#configuration' => $this->getConfiguration(),
      ] + $inline_form;

      $balance = $this->configuration['balance'];
      $formatted_balance = [
        '#type' => 'inline_template',
        '#template' => '{{ price|commerce_price_format }}',
        '#context' => [
          'price' => $balance,
        ],
      ];


      $inline_form['store_credit'] = [
        '#type' => 'details',
        '#open' => !empty($staged_payment),
        '#title' => t('@label: @balance available', [
          '@label' => $payment_gateway_plugin->multiPaymentDisplayLabel(),
          '@balance' => \Drupal::service('renderer')->render($formatted_balance),
        ]),
      ];

      if (!empty($staged_payment)) {
        $default_amount = $staged_payment->getAmount();
      } else {
        if ($order->getTotalPrice()->compareTo($balance) <= 0) {
          $default_amount = $order->getTotalPrice();
        } else {
          $default_amount = $balance;
        }
      }

      $inline_form['#staged_payment_id'] = !empty($staged_payment) ? $staged_payment->id() : NULL;

      $inline_form['store_credit']['amount'] = [
        '#title' => t('Amount to apply to order'),
        '#type' => 'commerce_price',
        '#currency_code' => $balance->getCurrencyCode(),
        '#default_value' => $default_amount->toArray(),
      ];

      $inline_form['store_credit']['apply'] = [
        '#type' => 'submit',
        '#value' => t('Apply'),
        '#staged_payment_id' => !empty($staged_payment) ? $staged_payment->id() : NULL,
        '#name' => $this->configuration['payment_gateway_id'] . '_apply_store_credit_payment',
        '#limit_validation_errors' => [
          $inline_form['#parents'],
        ],
        '#submit' => [
          [get_called_class(), 'applyStoreCredit'],
        ],
        '#ajax' => [
          'callback' => [get_called_class(), 'ajaxRefreshForm'],
          'element' => $inline_form['#parents'],
        ],
        // Simplify ajaxRefresh() by having all triggering elements
        // on the same level.
        '#parents' => array_merge($inline_form['#parents'], [$this->configuration['payment_gateway_id'] . '_apply_store_credit_payment']),
      ];

      if (!empty($staged_payment)) {
        $element['store_credit']['remove'] = [
          '#type' => 'submit',
          '#value' => t('Remove'),
          '#name' => $this->configuration['payment_gateway_id'] . '_remove_store_credit_payment',
          '#limit_validation_errors' => [
            $inline_form['#parents'],
          ],
          '#submit' => [
            [get_called_class(), 'removeStoreCredit'],
          ],
          '#ajax' => [
            'callback' => [get_called_class(), 'ajaxRefreshForm'],
            'element' => $inline_form['#parents'],
          ],
          // Simplify ajaxRefresh() by having all triggering elements
          // on the same level.
          '#parents' => array_merge($inline_form['#parents'], [$this->configuration['payment_gateway_id'] . '_remove_store_credit_payment']),
        ];
      }
    }

    return $inline_form;
  }

  /**
   * @param string $payment_gateway_id
   * @param int $user_id
   *
   * @return \Drupal\commerce_price\Price
   *   the balance of the store credit
   */
  protected static function getBalance($payment_gateway_id, $uid) {
    /** @var \Drupal\commerce_multi_payment\MultiplePaymentManagerInterface $multi_payment_manager */
    $multi_payment_manager = \Drupal::service('commerce_multi_payment.manager');
    /** @var \Drupal\commerce_multi_payment_example\Plugin\Commerce\PaymentGateway\StoreCreditPaymentGatewayInterface $payment_gateway_plugin */
    $payment_gateway_plugin = $multi_payment_manager->loadPaymentGatewayPlugin($payment_gateway_id);
    return $payment_gateway_plugin->getBalance($uid);
  }

  /**
   * Validates the store credit redemption element.
   *
   * @param array $inline_form
   *   The form .
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function validateInlineForm(array &$inline_form, FormStateInterface $form_state) {
    parent::validateInlineForm($inline_form, $form_state);
    $triggering_element = $form_state->getTriggeringElement();
    if (in_array('multi_payment_apply', $triggering_element['#parents']) && in_array($this->configuration['payment_gateway_id'], $triggering_element['#parents'])) {

      if ($triggering_element['#name'] == $this->configuration['payment_gateway_id'] . '_apply_store_credit_payment') {
        $amount_parents = array_merge($inline_form['#parents'], [
          'store_credit',
          'amount',
        ]);
        $amount_path = implode('][', $amount_parents);
        $amount_array = $form_state->getValue($amount_parents);
        $amount = new Price($amount_array['number'], $amount_array['currency_code']);


        // Check to see if the gift card has already been added to the order.
        $order_storage = \Drupal::entityTypeManager()
          ->getStorage('commerce_order');
        /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
        $order = $order_storage->load($this->configuration['order_id']);

        // Check the store credit balance.
        try {
          $balance = static::getBalance($this->configuration['payment_gateway_id'], $order->getCustomerId());
          $element['#balance'] = $balance;

          if ($balance->lessThan($amount)) {
            $form_state->setErrorByName($amount_path, t('Applied amount is greater than store credit balance.'));
          }

        } catch (DeclineException $e) {
          $form_state->setErrorByName($amount_path, $e->getMessage());
        }
      }
    }
  }

  /**
   * Submit callback for the apply store credit button.
   */
  public static function applyStoreCredit(array $form, FormStateInterface $form_state) {
    /** @var \Drupal\commerce_multi_payment\MultiplePaymentManagerInterface $multi_payment_manager */
    $multi_payment_manager = \Drupal::service('commerce_multi_payment.manager');

    $triggering_element = $form_state->getTriggeringElement();
    $parents = array_slice($triggering_element['#parents'], 0, -1);
    $inline_form = NestedArray::getValue($form, $parents);
    $staged_payment_id = $inline_form['#staged_payment_id'];

    $amount_parents = array_merge($inline_form['#parents'], [
      'store_credit',
      'amount',
    ]);
    $amount_array = $form_state->getValue($amount_parents);
    $amount = new Price($amount_array['number'], $amount_array['currency_code']);

    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $multi_payment_manager->loadOrder($inline_form['#configuration']['order_id']);

    $append = FALSE;

    if (empty($staged_payment_id)) {
      $staged_payment = $multi_payment_manager->createStagedPayment([
        'order_id' => $inline_form['#configuration']['order_id'],
        'payment_gateway' => $inline_form['#configuration']['payment_gateway_id'],
      ]);
      $append = TRUE;
    }
    else {
      $staged_payment = $multi_payment_manager->loadStagedPayment($staged_payment_id);
      $staged_payment->setStatus(TRUE);
    }

    // Prevent the payment amount from being more than the total order price, with existing adjustments.
    $staged_payment->setAmount($amount);
    $amount = $multi_payment_manager->getAdjustedPaymentAmount($staged_payment);

    $staged_payment->setAmount($amount);
    $staged_payment->save();

    if ($append) {
      $order->get('staged_multi_payment')->appendItem($staged_payment);
    }
    $order->save();

    static::setUserInput($form_state, array_merge($parents, [
      'store_credit',
      'amount',
    ]), NULL);

    $form_state->setRebuild();
  }

  /**
   * Remove store credit submit callback.
   */
  public static function removeStoreCredit(array $form, FormStateInterface $form_state) {
    /** @var \Drupal\commerce_multi_payment\MultiplePaymentManagerInterface $multi_payment_manager */
    $multi_payment_manager = \Drupal::service('commerce_multi_payment.manager');
    $triggering_element = $form_state->getTriggeringElement();
    $staged_payment_id = $triggering_element['#staged_payment_id'];
    $parents = array_slice($triggering_element['#parents'], 0, -1);
    $inline_form = NestedArray::getValue($form, $parents);

    $staged_payment = $multi_payment_manager->loadStagedPayment($inline_form['#staged_payment_id']);
    $staged_payment->delete();

    $order = $multi_payment_manager->loadOrder($inline_form['#inline_form']->getConfiguration()['order_id']);
    $order->save();

    static::setUserInput($form_state, array_merge($parents, [
      'store_credit',
      'amount',
    ]), NULL);
    $form_state->setRebuild();
  }

  /**
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   * @param array $parents
   * @param mixed|null $value
   */
  public static function setUserInput(FormStateInterface &$form_state, array $parents, $value = NULL) {
    $user_input = &$form_state->getUserInput();
    NestedArray::setValue($user_input, $parents, $value);
  }

}

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

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