You are here

public function PaymentOptionsBuilder::buildOptions in Commerce Core 8.2

Builds the payment options for the given order's payment gateways.

The payment options will be derived from the given payment gateways in the following order: 1) The customer's stored payment methods. 2) The order's payment method (if not added in the previous step). 3) Options to create new payment methods of valid types. 4) Options for the remaining gateways (off-site, manual, etc).

Parameters

\Drupal\commerce_order\Entity\OrderInterface $order: The order.

\Drupal\commerce_payment\Entity\PaymentGatewayInterface[] $payment_gateways: The payment gateways. When empty, defaults to all available gateways.

Return value

\Drupal\commerce_payment\PaymentOption[] The payment options, keyed by option ID.

Overrides PaymentOptionsBuilderInterface::buildOptions

File

modules/payment/src/PaymentOptionsBuilder.php, line 39

Class

PaymentOptionsBuilder

Namespace

Drupal\commerce_payment

Code

public function buildOptions(OrderInterface $order, array $payment_gateways = []) {
  if (empty($payment_gateways)) {

    /** @var \Drupal\commerce_payment\PaymentGatewayStorageInterface $payment_gateway_storage */
    $payment_gateway_storage = $this->entityTypeManager
      ->getStorage('commerce_payment_gateway');
    $payment_gateways = $payment_gateway_storage
      ->loadMultipleForOrder($order);
  }

  /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface[] $payment_gateways_with_payment_methods */
  $payment_gateways_with_payment_methods = array_filter($payment_gateways, function ($payment_gateway) {

    /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $payment_gateway */
    return $payment_gateway
      ->getPlugin() instanceof SupportsStoredPaymentMethodsInterface;
  });
  $options = [];

  // 1) Add options to reuse stored payment methods for known customers.
  $customer = $order
    ->getCustomer();
  if ($customer
    ->isAuthenticated()) {
    $billing_countries = $order
      ->getStore()
      ->getBillingCountries();

    /** @var \Drupal\commerce_payment\PaymentMethodStorageInterface $payment_method_storage */
    $payment_method_storage = $this->entityTypeManager
      ->getStorage('commerce_payment_method');
    foreach ($payment_gateways_with_payment_methods as $payment_gateway) {
      $payment_methods = $payment_method_storage
        ->loadReusable($customer, $payment_gateway, $billing_countries);
      foreach ($payment_methods as $payment_method_id => $payment_method) {
        $options[$payment_method_id] = new PaymentOption([
          'id' => $payment_method_id,
          'label' => $payment_method
            ->label(),
          'payment_gateway_id' => $payment_gateway
            ->id(),
          'payment_method_id' => $payment_method_id,
        ]);
      }
    }
  }

  // 2) Add the order's payment method if it was not included above.

  /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $order_payment_method */
  $order_payment_method = $order
    ->get('payment_method')->entity;
  if ($order_payment_method) {
    $order_payment_method_id = $order_payment_method
      ->id();

    // Make sure that the payment method's gateway is still available.
    $payment_gateway_id = $order_payment_method
      ->getPaymentGatewayId();
    $payment_gateway_ids = EntityHelper::extractIds($payment_gateways_with_payment_methods);
    if (in_array($payment_gateway_id, $payment_gateway_ids) && !isset($options[$order_payment_method_id])) {
      $options[$order_payment_method_id] = new PaymentOption([
        'id' => $order_payment_method_id,
        'label' => $order_payment_method
          ->label(),
        'payment_gateway_id' => $order_payment_method
          ->getPaymentGatewayId(),
        'payment_method_id' => $order_payment_method_id,
      ]);
    }
  }

  // 3) Add options to create new stored payment methods of supported types.
  $payment_method_type_counts = [];

  // Count how many new payment method options will be built per gateway.
  foreach ($payment_gateways_with_payment_methods as $payment_gateway) {
    $payment_method_types = $payment_gateway
      ->getPlugin()
      ->getPaymentMethodTypes();
    foreach ($payment_method_types as $payment_method_type_id => $payment_method_type) {
      if (!isset($payment_method_type_counts[$payment_method_type_id])) {
        $payment_method_type_counts[$payment_method_type_id] = 1;
      }
      else {
        $payment_method_type_counts[$payment_method_type_id]++;
      }
    }
  }
  foreach ($payment_gateways_with_payment_methods as $payment_gateway) {
    $payment_gateway_plugin = $payment_gateway
      ->getPlugin();
    $payment_method_types = $payment_gateway_plugin
      ->getPaymentMethodTypes();
    foreach ($payment_method_types as $payment_method_type_id => $payment_method_type) {
      $option_id = 'new--' . $payment_method_type_id . '--' . $payment_gateway
        ->id();
      $option_label = $payment_method_type
        ->getCreateLabel();

      // If there is more than one option for this payment method type,
      // append the payment gateway label to avoid duplicate option labels.
      if ($payment_method_type_counts[$payment_method_type_id] > 1) {
        $option_label = $this
          ->t('@payment_method_label (@payment_gateway_label)', [
          '@payment_method_label' => $payment_method_type
            ->getCreateLabel(),
          '@payment_gateway_label' => $payment_gateway_plugin
            ->getDisplayLabel(),
        ]);
      }
      $options[$option_id] = new PaymentOption([
        'id' => $option_id,
        'label' => $option_label,
        'payment_gateway_id' => $payment_gateway
          ->id(),
        'payment_method_type_id' => $payment_method_type_id,
      ]);
    }
  }

  // 4) Add options for the remaining gateways.

  /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface[] $other_payment_gateways */
  $other_payment_gateways = array_diff_key($payment_gateways, $payment_gateways_with_payment_methods);
  foreach ($other_payment_gateways as $payment_gateway) {
    $payment_gateway_id = $payment_gateway
      ->id();
    $options[$payment_gateway_id] = new PaymentOption([
      'id' => $payment_gateway_id,
      'label' => $payment_gateway
        ->getPlugin()
        ->getDisplayLabel(),
      'payment_gateway_id' => $payment_gateway_id,
    ]);
  }
  return $options;
}