Loading modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentInformation.php +67 −10 Original line number Diff line number Diff line Loading @@ -159,6 +159,7 @@ class PaymentInformation extends CheckoutPaneBase { $payment_gateway_storage = $this->entityTypeManager->getStorage('commerce_payment_gateway'); // Load the payment gateways. This fires an event for filtering the // available gateways, and then evaluates conditions on all remaining ones. /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface[] $payment_gateways */ $payment_gateways = $payment_gateway_storage->loadMultipleForOrder($this->order); // Can't proceed without any payment gateways. if (empty($payment_gateways)) { Loading @@ -178,6 +179,17 @@ class PaymentInformation extends CheckoutPaneBase { $option_labels = array_map(function (PaymentOption $option) { return $option->getLabel(); }, $options); $stored_options = $new_options = []; // Separate the stored payment options from the new ones. foreach ($options as $id => $option) { if (!empty($option->getPaymentMethodId())) { $stored_options[$id] = $option; } else { $new_options[$id] = $option; } } // Try to get a payment method from user input. $parents = array_merge($pane_form['#parents'], ['payment_method']); $default_option_id = NestedArray::getValue($form_state->getUserInput(), $parents); if ($default_option_id && isset($options[$default_option_id])) { Loading @@ -186,26 +198,62 @@ class PaymentInformation extends CheckoutPaneBase { else { $default_option = $this->paymentOptionsBuilder->selectDefaultOption($this->order, $options); } $pane_form['#after_build'][] = [get_class($this), 'clearValues']; $pane_form['payment_method'] = [ // First build the stored payment method options if any. if (!empty($stored_options)) { $pane_form['stored_payment_method'] = [ '#type' => 'radios', '#title' => $this->t('Your payment methods'), '#parents' => $parents, '#options' => array_intersect_key($option_labels, $stored_options), '#default_value' => isset($stored_options[$default_option->getId()]) ? $default_option->getId() : NULL, '#ajax' => [ 'callback' => [static::class, 'ajaxRefresh'], 'wrapper' => $pane_form['#id'], ], // Because we reuse the same "name" for the stored payment method // and new payment method form elements, Drupal gets confused during // validation, so we have to pretend the element is already validated. // Note that we have our own validation in validatePaneForm(). '#validated' => TRUE, ]; // Add a class to each individual radio, to help themers. foreach ($stored_options as $option) { $pane_form['stored_payment_method'][$option->getId()]['#attributes']['class'][] = "payment-method--stored"; } } $pane_form['new_payment_method'] = [ '#type' => 'radios', '#title' => $this->t('Payment method'), '#options' => $option_labels, '#default_value' => $default_option->getId(), '#title' => empty($stored_options) ? $this->t('Select a payment method') : $this->t('Add a new payment method'), '#options' => array_intersect_key($option_labels, $new_options), '#default_value' => isset($new_options[$default_option->getId()]) ? $default_option->getId() : NULL, '#parents' => $parents, '#ajax' => [ 'callback' => [get_class($this), 'ajaxRefresh'], 'callback' => [static::class, 'ajaxRefresh'], 'wrapper' => $pane_form['#id'], ], '#access' => count($options) > 1, // Only show the new payment method options if there are more than one or // if there are stored options available. '#access' => count($new_options) > 1 || count($stored_options) > 0, // Because we reuse the same "name" for the stored payment method // and new payment method form elements, Drupal gets confused during // validation, so we have to pretend the element is already validated. // Note that we have our own validation in validatePaneForm(). '#validated' => TRUE, ]; // Add a class to each individual radio, to help themers. foreach ($options as $option) { $class_name = $option->getPaymentMethodId() ? 'stored' : 'new'; $pane_form['payment_method'][$option->getId()]['#attributes']['class'][] = "payment-method--$class_name"; foreach ($new_options as $option) { $pane_form['new_payment_method'][$option->getId()]['#attributes']['class'][] = "payment-method--new"; } // Store the options for submitPaneForm(). $pane_form['#payment_options'] = $options; // Store the default payment option for validatePaneForm(). $pane_form['#default_option'] = $default_option; // If this is an existing payment method, return the pane form. // Editing payment methods at checkout is not supported. Loading Loading @@ -347,6 +395,15 @@ class PaymentInformation extends CheckoutPaneBase { if (!isset($values['payment_method'])) { $form_state->setError($complete_form, $this->noPaymentGatewayErrorMessage()); } // Because we disabled Drupal's default validation, we have to perform // our own, to ensure the selected payment method is a valid option. elseif (!isset($pane_form['#payment_options'][$values['payment_method']])) { if (isset($pane_form['#default_option'])) { $values['payment_method'] = $pane_form['#default_option']->getId(); $form_state->setValue($pane_form['#parents'], $values); } $form_state->setError($complete_form, $this->t('An illegal choice has been detected. Please contact the site administrator.')); } } /** Loading Loading
modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentInformation.php +67 −10 Original line number Diff line number Diff line Loading @@ -159,6 +159,7 @@ class PaymentInformation extends CheckoutPaneBase { $payment_gateway_storage = $this->entityTypeManager->getStorage('commerce_payment_gateway'); // Load the payment gateways. This fires an event for filtering the // available gateways, and then evaluates conditions on all remaining ones. /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface[] $payment_gateways */ $payment_gateways = $payment_gateway_storage->loadMultipleForOrder($this->order); // Can't proceed without any payment gateways. if (empty($payment_gateways)) { Loading @@ -178,6 +179,17 @@ class PaymentInformation extends CheckoutPaneBase { $option_labels = array_map(function (PaymentOption $option) { return $option->getLabel(); }, $options); $stored_options = $new_options = []; // Separate the stored payment options from the new ones. foreach ($options as $id => $option) { if (!empty($option->getPaymentMethodId())) { $stored_options[$id] = $option; } else { $new_options[$id] = $option; } } // Try to get a payment method from user input. $parents = array_merge($pane_form['#parents'], ['payment_method']); $default_option_id = NestedArray::getValue($form_state->getUserInput(), $parents); if ($default_option_id && isset($options[$default_option_id])) { Loading @@ -186,26 +198,62 @@ class PaymentInformation extends CheckoutPaneBase { else { $default_option = $this->paymentOptionsBuilder->selectDefaultOption($this->order, $options); } $pane_form['#after_build'][] = [get_class($this), 'clearValues']; $pane_form['payment_method'] = [ // First build the stored payment method options if any. if (!empty($stored_options)) { $pane_form['stored_payment_method'] = [ '#type' => 'radios', '#title' => $this->t('Your payment methods'), '#parents' => $parents, '#options' => array_intersect_key($option_labels, $stored_options), '#default_value' => isset($stored_options[$default_option->getId()]) ? $default_option->getId() : NULL, '#ajax' => [ 'callback' => [static::class, 'ajaxRefresh'], 'wrapper' => $pane_form['#id'], ], // Because we reuse the same "name" for the stored payment method // and new payment method form elements, Drupal gets confused during // validation, so we have to pretend the element is already validated. // Note that we have our own validation in validatePaneForm(). '#validated' => TRUE, ]; // Add a class to each individual radio, to help themers. foreach ($stored_options as $option) { $pane_form['stored_payment_method'][$option->getId()]['#attributes']['class'][] = "payment-method--stored"; } } $pane_form['new_payment_method'] = [ '#type' => 'radios', '#title' => $this->t('Payment method'), '#options' => $option_labels, '#default_value' => $default_option->getId(), '#title' => empty($stored_options) ? $this->t('Select a payment method') : $this->t('Add a new payment method'), '#options' => array_intersect_key($option_labels, $new_options), '#default_value' => isset($new_options[$default_option->getId()]) ? $default_option->getId() : NULL, '#parents' => $parents, '#ajax' => [ 'callback' => [get_class($this), 'ajaxRefresh'], 'callback' => [static::class, 'ajaxRefresh'], 'wrapper' => $pane_form['#id'], ], '#access' => count($options) > 1, // Only show the new payment method options if there are more than one or // if there are stored options available. '#access' => count($new_options) > 1 || count($stored_options) > 0, // Because we reuse the same "name" for the stored payment method // and new payment method form elements, Drupal gets confused during // validation, so we have to pretend the element is already validated. // Note that we have our own validation in validatePaneForm(). '#validated' => TRUE, ]; // Add a class to each individual radio, to help themers. foreach ($options as $option) { $class_name = $option->getPaymentMethodId() ? 'stored' : 'new'; $pane_form['payment_method'][$option->getId()]['#attributes']['class'][] = "payment-method--$class_name"; foreach ($new_options as $option) { $pane_form['new_payment_method'][$option->getId()]['#attributes']['class'][] = "payment-method--new"; } // Store the options for submitPaneForm(). $pane_form['#payment_options'] = $options; // Store the default payment option for validatePaneForm(). $pane_form['#default_option'] = $default_option; // If this is an existing payment method, return the pane form. // Editing payment methods at checkout is not supported. Loading Loading @@ -347,6 +395,15 @@ class PaymentInformation extends CheckoutPaneBase { if (!isset($values['payment_method'])) { $form_state->setError($complete_form, $this->noPaymentGatewayErrorMessage()); } // Because we disabled Drupal's default validation, we have to perform // our own, to ensure the selected payment method is a valid option. elseif (!isset($pane_form['#payment_options'][$values['payment_method']])) { if (isset($pane_form['#default_option'])) { $values['payment_method'] = $pane_form['#default_option']->getId(); $form_state->setValue($pane_form['#parents'], $values); } $form_state->setError($complete_form, $this->t('An illegal choice has been detected. Please contact the site administrator.')); } } /** Loading