commerce-8.x-2.8/modules/payment/src/Element/PaymentGatewayForm.php
modules/payment/src/Element/PaymentGatewayForm.php
<?php
namespace Drupal\commerce_payment\Element;
use Drupal\commerce\Element\CommerceElementTrait;
use Drupal\commerce\Response\NeedsRedirectException;
use Drupal\commerce_payment\Entity\EntityWithPaymentGatewayInterface;
use Drupal\commerce_payment\Exception\PaymentGatewayException;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\RenderElement;
/**
* Provides a form element for embedding the payment gateway forms.
*
* Usage example:
* @code
* $form['payment_method'] = [
* '#type' => 'commerce_payment_gateway_form',
* '#operation' => 'add-payment-method',
* // A payment or payment method entity, depending on the operation.
* // On submit, the payment method will be created remotely, and the
* // entity updated, for access via $form_state->getValue('payment_method')
* '#default_value' => $payment_method,
* ];
* @endcode
*
* @RenderElement("commerce_payment_gateway_form")
*/
class PaymentGatewayForm extends RenderElement {
use CommerceElementTrait;
/**
* {@inheritdoc}
*/
public function getInfo() {
$class = get_class($this);
return [
'#operation' => '',
// The entity operated on. Instance of EntityWithPaymentGatewayInterface.
'#default_value' => NULL,
// The url to which the user will be redirected if an exception is thrown
// while building the form. If empty, the error will be shown inline.
'#exception_url' => '',
'#exception_message' => t('An error occurred while contacting the gateway. Please try again later.'),
'#process' => [
[$class, 'attachElementSubmit'],
[$class, 'processForm'],
],
'#element_validate' => [
[$class, 'validateElementSubmit'],
[$class, 'validateForm'],
],
'#commerce_element_submit' => [
[$class, 'submitForm'],
],
'#theme_wrappers' => ['container'],
];
}
/**
* Builds the payment gateway form.
*
* @param array $element
* The form element being processed.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param array $complete_form
* The complete form structure.
*
* @throws \InvalidArgumentException
* Thrown when the #operation or #default_value properties are empty, or
* when the #default_value property is not a valid entity.
* @throws \Drupal\commerce\Response\NeedsRedirectException
* Thrown if an exception was caught, and $element['#exception_url'] is not empty.
*
* @return array
* The processed form element.
*/
public static function processForm(array $element, FormStateInterface $form_state, array &$complete_form) {
if (empty($element['#operation'])) {
throw new \InvalidArgumentException('The commerce_payment_gateway_form element requires the #operation property.');
}
if (empty($element['#default_value'])) {
throw new \InvalidArgumentException('The commerce_payment_gateway_form element requires the #default_value property.');
}
elseif (isset($element['#default_value']) && !($element['#default_value'] instanceof EntityWithPaymentGatewayInterface)) {
throw new \InvalidArgumentException('The commerce_payment_gateway_form #default_value property must be a payment or a payment method entity.');
}
$plugin_form = static::createPluginForm($element);
try {
$element = $plugin_form->buildConfigurationForm($element, $form_state);
// Allow the plugin form to override the page title.
if (isset($element['#page_title'])) {
$complete_form['#title'] = $element['#page_title'];
}
}
catch (PaymentGatewayException $e) {
\Drupal::logger('commerce_payment')->error($e->getMessage());
if (!empty($element['#exception_url'])) {
\Drupal::messenger()->addError($element['#exception_message']);
throw new NeedsRedirectException($element['#exception_url']);
}
else {
$element['error'] = [
'#markup' => $element['#exception_message'],
];
$complete_form['actions']['#access'] = FALSE;
}
}
return $element;
}
/**
* Validates the payment gateway form.
*
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public static function validateForm(array &$element, FormStateInterface $form_state) {
$plugin_form = self::createPluginForm($element);
try {
$plugin_form->validateConfigurationForm($element, $form_state);
}
catch (PaymentGatewayException $e) {
$error_element = $plugin_form->getErrorElement($element, $form_state);
$form_state->setError($error_element, $e->getMessage());
}
}
/**
* Submits the payment gateway form.
*
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public static function submitForm(array &$element, FormStateInterface $form_state) {
$plugin_form = self::createPluginForm($element);
try {
$plugin_form->submitConfigurationForm($element, $form_state);
$form_state->setValueForElement($element, $plugin_form->getEntity());
}
catch (PaymentGatewayException $e) {
$error_element = $plugin_form->getErrorElement($element, $form_state);
$form_state->setError($error_element, $e->getMessage());
}
}
/**
* Creates an instance of the plugin form.
*
* @param array $element
* The form element.
*
* @return \Drupal\commerce_payment\PluginForm\PaymentGatewayFormInterface
* The plugin form.
*/
public static function createPluginForm(array $element) {
/** @var \Drupal\Core\Plugin\PluginFormFactoryInterface $plugin_form_factory */
$plugin_form_factory = \Drupal::service('plugin_form.factory');
/** @var \Drupal\commerce_payment\Entity\EntityWithPaymentGatewayInterface $entity */
$entity = $element['#default_value'];
$plugin = $entity->getPaymentGateway()->getPlugin();
/** @var \Drupal\commerce_payment\PluginForm\PaymentGatewayFormInterface $plugin_form */
$plugin_form = $plugin_form_factory->createInstance($plugin, $element['#operation']);
$plugin_form->setEntity($entity);
return $plugin_form;
}
}
