Commit 2bb50de2 authored by bojanz's avatar bojanz Committed by bojanz

Issue #3003121 by bojanz, alexpott, mglaman: Add an InlineForm API, stop using...

Issue #3003121 by bojanz, alexpott, mglaman: Add an InlineForm API, stop using complex form elements
parent f9b3442b
......@@ -68,3 +68,7 @@ services:
plugin.manager.commerce_entity_trait:
class: Drupal\commerce\EntityTraitManager
arguments: ['@container.namespaces', '@cache.discovery', '@module_handler', '@commerce.configurable_field_manager']
plugin.manager.commerce_inline_form:
class: Drupal\commerce\InlineFormManager
arguments: ['@container.namespaces', '@cache.discovery', '@module_handler']
......@@ -2,7 +2,11 @@
namespace Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane;
use Drupal\commerce\InlineFormManager;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides the billing information pane.
......@@ -16,14 +20,57 @@ use Drupal\Core\Form\FormStateInterface;
*/
class BillingInformation extends CheckoutPaneBase implements CheckoutPaneInterface {
/**
* The inline form manager.
*
* @var \Drupal\commerce\InlineFormManager
*/
protected $inlineFormManager;
/**
* Constructs a new BillingInformation 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_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface $checkout_flow
* The parent checkout flow.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\commerce\InlineFormManager $inline_form_manager
* The inline form manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, CheckoutFlowInterface $checkout_flow, EntityTypeManagerInterface $entity_type_manager, InlineFormManager $inline_form_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $checkout_flow, $entity_type_manager);
$this->inlineFormManager = $inline_form_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, CheckoutFlowInterface $checkout_flow = NULL) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$checkout_flow,
$container->get('entity_type.manager'),
$container->get('plugin.manager.commerce_inline_form')
);
}
/**
* {@inheritdoc}
*/
public function buildPaneSummary() {
$summary = [];
if ($billing_profile = $this->order->getBillingProfile()) {
if ($profile = $this->order->getBillingProfile()) {
$profile_view_builder = $this->entityTypeManager->getViewBuilder('profile');
$summary = $profile_view_builder->view($billing_profile, 'default');
$summary = $profile_view_builder->view($profile, 'default');
}
return $summary;
}
......@@ -33,30 +80,47 @@ class BillingInformation extends CheckoutPaneBase implements CheckoutPaneInterfa
*/
public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
$store = $this->order->getStore();
$billing_profile = $this->order->getBillingProfile();
if (!$billing_profile) {
$profile = $this->order->getBillingProfile();
if (!$profile) {
$profile_storage = $this->entityTypeManager->getStorage('profile');
$billing_profile = $profile_storage->create([
$profile = $profile_storage->create([
'type' => 'customer',
'uid' => $this->order->getCustomerId(),
]);
}
$inline_form = $this->inlineFormManager->createInstance('customer_profile', [
'default_country' => $store->getAddress()->getCountryCode(),
'available_countries' => $store->getBillingCountries(),
], $profile);
$pane_form['profile'] = [
'#type' => 'commerce_profile_select',
'#default_value' => $billing_profile,
'#default_country' => $store->getAddress()->getCountryCode(),
'#available_countries' => $store->getBillingCountries(),
'#parents' => array_merge($pane_form['#parents'], ['profile']),
'#inline_form' => $inline_form,
];
$pane_form['profile'] = $inline_form->buildInlineForm($pane_form['profile'], $form_state);
return $pane_form;
}
/**
* {@inheritdoc}
*/
public function validatePaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $pane_form['profile']['#inline_form'];
$inline_form->validateInlineForm($pane_form['profile'], $form_state);
}
/**
* {@inheritdoc}
*/
public function submitPaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
$this->order->setBillingProfile($pane_form['profile']['#profile']);
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $pane_form['profile']['#inline_form'];
$inline_form->submitInlineForm($pane_form['profile'], $form_state);
/** @var \Drupal\profile\Entity\ProfileInterface $profile */
$profile = $inline_form->getEntity();
$this->order->setBillingProfile($profile);
}
}
......@@ -3,14 +3,17 @@
namespace Drupal\commerce_order\Element;
use Drupal\commerce\Element\CommerceElementTrait;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\RenderElement;
use Drupal\profile\Entity\ProfileInterface;
@trigger_error('The ' . __NAMESPACE__ . '\ProfileSelect is deprecated. Instead, use the customer_profile inline form. See https://www.drupal.org/node/3015309.', E_USER_DEPRECATED);
/**
* Provides a form element for selecting a customer profile.
*
* @deprecated Use the customer_profile inline form instead.
*
* Usage example:
* @code
* $form['billing_profile'] = [
......@@ -85,29 +88,16 @@ class ProfileSelect extends RenderElement {
if (!is_array($element['#available_countries'])) {
throw new \InvalidArgumentException('The commerce_profile_select #available_countries property must be an array.');
}
// Make sure that the specified default country is available.
if (!empty($element['#default_country']) && !empty($element['#available_countries'])) {
if (!in_array($element['#default_country'], $element['#available_countries'])) {
$element['#default_country'] = NULL;
}
}
$element['#profile'] = $element['#default_value'];
$form_display = EntityFormDisplay::collectRenderDisplay($element['#profile'], 'default');
$form_display->buildForm($element['#profile'], $element, $form_state);
if (!empty($element['address']['widget'][0])) {
$widget_element = &$element['address']['widget'][0];
// Remove the details wrapper from the address widget.
$widget_element['#type'] = 'container';
// Provide a default country.
if (!empty($element['#default_country']) && empty($widget_element['address']['#default_value']['country_code'])) {
$widget_element['address']['#default_value']['country_code'] = $element['#default_country'];
}
// Limit the available countries.
if (!empty($element['#available_countries'])) {
$widget_element['address']['#available_countries'] = $element['#available_countries'];
}
}
/** @var \Drupal\commerce\InlineFormManager $inline_form_manager */
$inline_form_manager = \Drupal::service('plugin.manager.commerce_inline_form');
$inline_form = $inline_form_manager->createInstance('customer_profile', [
'default_country' => $element['#default_country'],
'available_countries' => $element['#available_countries'],
], $element['#default_value']);
$element['#inline_form'] = $inline_form;
$element = $inline_form->buildInlineForm($element, $form_state);
return $element;
}
......@@ -119,15 +109,12 @@ class ProfileSelect extends RenderElement {
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @throws \Exception
* Thrown if button-level #validate handlers are detected on the parent
* form, as a protection against buggy behavior.
*/
public static function validateForm(array &$element, FormStateInterface $form_state) {
$form_display = EntityFormDisplay::collectRenderDisplay($element['#profile'], 'default');
$form_display->extractFormValues($element['#profile'], $element, $form_state);
$form_display->validateFormValues($element['#profile'], $element, $form_state);
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $element['#inline_form'];
$inline_form->validateInlineForm($element, $form_state);
$element['#profile'] = $inline_form->getEntity();
}
/**
......@@ -139,9 +126,10 @@ class ProfileSelect extends RenderElement {
* The current state of the form.
*/
public static function submitForm(array &$element, FormStateInterface $form_state) {
$form_display = EntityFormDisplay::collectRenderDisplay($element['#profile'], 'default');
$form_display->extractFormValues($element['#profile'], $element, $form_state);
$element['#profile']->save();
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $element['#inline_form'];
$inline_form->submitInlineForm($element, $form_state);
$element['#profile'] = $inline_form->getEntity();
}
}
<?php
namespace Drupal\commerce_order\Plugin\Commerce\InlineForm;
use Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormBase;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Form\FormStateInterface;
use Drupal\profile\Entity\ProfileInterface;
/**
* Provides a form element for managing a customer profile.
*
* @CommerceInlineForm(
* id = "customer_profile",
* label = @Translation("Customer profile"),
* )
*/
class CustomerProfile extends EntityInlineFormBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
// The country to select if the address widget doesn't have a default.
'default_country' => NULL,
// If empty, all countries will be available.
'available_countries' => [],
];
}
/**
* {@inheritdoc}
*/
protected function validateConfiguration() {
parent::validateConfiguration();
if (!is_array($this->configuration['available_countries'])) {
throw new \RuntimeException('The available_countries configuration value must be an array.');
}
// Make sure that the specified default country is available.
if (!empty($this->configuration['default_country']) && !empty($this->configuration['available_countries'])) {
if (!in_array($this->configuration['default_country'], $this->configuration['available_countries'])) {
$this->configuration['default_country'] = NULL;
}
}
}
/**
* {@inheritdoc}
*/
public function buildInlineForm(array $inline_form, FormStateInterface $form_state) {
$inline_form = parent::buildInlineForm($inline_form, $form_state);
assert($this->entity instanceof ProfileInterface);
$form_display = EntityFormDisplay::collectRenderDisplay($this->entity, 'default');
$form_display->buildForm($this->entity, $inline_form, $form_state);
if (!empty($inline_form['address']['widget'][0])) {
$widget_element = &$inline_form['address']['widget'][0];
// Remove the details wrapper from the address widget.
$widget_element['#type'] = 'container';
// Provide a default country.
$default_country = $this->configuration['default_country'];
if ($default_country && empty($widget_element['address']['#default_value']['country_code'])) {
$widget_element['address']['#default_value']['country_code'] = $default_country;
}
// Limit the available countries.
$available_countries = $this->configuration['available_countries'];
if ($available_countries) {
$widget_element['address']['#available_countries'] = $available_countries;
}
}
return $inline_form;
}
/**
* {@inheritdoc}
*/
public function validateInlineForm(array &$inline_form, FormStateInterface $form_state) {
parent::validateInlineForm($inline_form, $form_state);
assert($this->entity instanceof ProfileInterface);
$form_display = EntityFormDisplay::collectRenderDisplay($this->entity, 'default');
$form_display->extractFormValues($this->entity, $inline_form, $form_state);
$form_display->validateFormValues($this->entity, $inline_form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitInlineForm(array &$inline_form, FormStateInterface $form_state) {
parent::submitInlineForm($inline_form, $form_state);
assert($this->entity instanceof ProfileInterface);
$form_display = EntityFormDisplay::collectRenderDisplay($this->entity, 'default');
$form_display->extractFormValues($this->entity, $inline_form, $form_state);
$this->entity->save();
}
}
......@@ -2,6 +2,8 @@
namespace Drupal\commerce_order\Plugin\Field\FieldWidget;
use Drupal\commerce\Element\CommerceElementTrait;
use Drupal\commerce\InlineFormManager;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
......@@ -31,6 +33,13 @@ class BillingProfileWidget extends WidgetBase implements ContainerFactoryPluginI
*/
protected $entityTypeManager;
/**
* The inline form manager.
*
* @var \Drupal\commerce\InlineFormManager
*/
protected $inlineFormManager;
/**
* Constructs a new BillingProfileWidget object.
*
......@@ -46,11 +55,14 @@ class BillingProfileWidget extends WidgetBase implements ContainerFactoryPluginI
* Any third party settings.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\commerce\InlineFormManager $inline_form_manager
* The inline form manager.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager) {
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, InlineFormManager $inline_form_manager) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->entityTypeManager = $entity_type_manager;
$this->inlineFormManager = $inline_form_manager;
}
/**
......@@ -63,7 +75,8 @@ class BillingProfileWidget extends WidgetBase implements ContainerFactoryPluginI
$configuration['field_definition'],
$configuration['settings'],
$configuration['third_party_settings'],
$container->get('entity_type.manager')
$container->get('entity_type.manager'),
$container->get('plugin.manager.commerce_inline_form')
);
}
......@@ -74,7 +87,6 @@ class BillingProfileWidget extends WidgetBase implements ContainerFactoryPluginI
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $items[$delta]->getEntity();
$store = $order->getStore();
if (!$items[$delta]->isEmpty() && $items[$delta]->entity) {
$profile = $items[$delta]->entity;
}
......@@ -84,14 +96,21 @@ class BillingProfileWidget extends WidgetBase implements ContainerFactoryPluginI
'uid' => $order->getCustomer(),
]);
}
$inline_form = $this->inlineFormManager->createInstance('customer_profile', [
'default_country' => $store->getAddress()->getCountryCode(),
'available_countries' => $store->getBillingCountries(),
], $profile);
$element['#type'] = 'fieldset';
$element['profile'] = [
'#type' => 'commerce_profile_select',
'#default_value' => $profile,
'#default_country' => $store->getAddress()->getCountryCode(),
'#available_countries' => $store->getBillingCountries(),
'#parents' => array_merge($element['#field_parents'], [$items->getName(), $delta, 'profile']),
'#inline_form' => $inline_form,
];
$element['profile'] = $inline_form->buildInlineForm($element['profile'], $form_state);
// Workaround for widgets not having validate/submit callbacks.
CommerceElementTrait::attachElementSubmit($element, $form_state, $form);
$element['#element_validate'][] = [get_class($this), 'validateElement'];
$element['#commerce_element_submit'][] = [get_class($this), 'submitElement'];
// Workaround for massageFormValues() not getting $element.
$element['array_parents'] = [
'#type' => 'value',
......@@ -101,6 +120,34 @@ class BillingProfileWidget extends WidgetBase implements ContainerFactoryPluginI
return $element;
}
/**
* Validates the element.
*
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public static function validateElement(array $element, FormStateInterface $form_state) {
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $element['profile']['#inline_form'];
$inline_form->validateInlineForm($element['profile'], $form_state);
}
/**
* Submits the element.
*
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public static function submitElement(array $element, FormStateInterface $form_state) {
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $element['profile']['#inline_form'];
$inline_form->submitInlineForm($element['profile'], $form_state);
}
/**
* {@inheritdoc}
*/
......@@ -108,7 +155,9 @@ class BillingProfileWidget extends WidgetBase implements ContainerFactoryPluginI
$new_values = [];
foreach ($values as $delta => $value) {
$element = NestedArray::getValue($form, $value['array_parents']);
$new_values[$delta]['entity'] = $element['profile']['#profile'];
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $element['profile']['#inline_form'];
$new_values[$delta]['entity'] = $inline_form->getEntity();
}
return $new_values;
}
......
......@@ -3,15 +3,17 @@
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;
@trigger_error('The ' . __NAMESPACE__ . '\PaymentGatewayForm is deprecated. Instead, use the payment_gateway_form inline form. See https://www.drupal.org/node/3015309.', E_USER_DEPRECATED);
/**
* Provides a form element for embedding the payment gateway forms.
*
* @deprecated Use the payment_gateway_form inline form instead.
*
* Usage example:
* @code
* $form['payment_method'] = [
......@@ -72,8 +74,6 @@ class PaymentGatewayForm extends RenderElement {
* @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.
......@@ -88,27 +88,17 @@ class PaymentGatewayForm extends RenderElement {
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;
}
}
/** @var \Drupal\commerce\InlineFormManager $inline_form_manager */
$inline_form_manager = \Drupal::service('plugin.manager.commerce_inline_form');
$inline_form = $inline_form_manager->createInstance('payment_gateway_form', [
'operation' => $element['#operation'],
'exception_url' => $element['#exception_url'],
'exception_message' => $element['#exception_message'],
], $element['#default_value']);
$element['#inline_form'] = $inline_form;
$element = $inline_form->buildInlineForm($element, $form_state);
return $element;
}
......@@ -122,15 +112,9 @@ class PaymentGatewayForm extends RenderElement {
* 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());
}
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $element['#inline_form'];
$inline_form->validateInlineForm($element, $form_state);
}
/**
......@@ -142,38 +126,10 @@ class PaymentGatewayForm extends RenderElement {
* 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;
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $element['#inline_form'];
$inline_form->submitInlineForm($element, $form_state);
$form_state->setValueForElement($element, $inline_form->getEntity());
}
}
......@@ -3,6 +3,7 @@
namespace Drupal\commerce_payment\Form;
use Drupal\commerce\EntityHelper;
use Drupal\commerce\InlineFormManager;
use Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\OffsitePaymentGatewayInterface;
use Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\SupportsStoredPaymentMethodsInterface;
use Drupal\Component\Utility\Html;
......@@ -26,6 +27,13 @@ class PaymentAddForm extends FormBase implements ContainerInjectionInterface {
*/
protected $entityTypeManager;
/**
* The inline form manager.
*
* @var \Drupal\commerce\InlineFormManager
*/
protected $inlineFormManager;
/**
* The current order.
*
......@@ -38,11 +46,14 @@ class PaymentAddForm extends FormBase implements ContainerInjectionInterface {
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\commerce\InlineFormManager $inline_form_manager
* The inline form manager.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, RouteMatchInterface $route_match) {
public function __construct(EntityTypeManagerInterface $entity_type_manager, InlineFormManager $inline_form_manager, RouteMatchInterface $route_match) {
$this->entityTypeManager = $entity_type_manager;
$this->inlineFormManager = $inline_form_manager;
$this->order = $route_match->getParameter('commerce_order');
}
......@@ -52,6 +63,7 @@ class PaymentAddForm extends FormBase implements ContainerInjectionInterface {
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager'),
$container->get('plugin.manager.commerce_inline_form'),
$container->get('current_route_match')
);
}
......@@ -221,12 +233,15 @@ class PaymentAddForm extends FormBase implements ContainerInjectionInterface {
}
$payment_storage = $this->entityTypeManager->getStorage('commerce_payment');
$payment = $payment_storage->create($values);
$inline_form = $this->inlineFormManager->createInstance('payment_gateway_form', [
'operation' => 'add-payment',
], $payment);
$form['payment'] = [
'#type' => 'commerce_payment_gateway_form',
'#operation' => 'add-payment',
'#default_value' => $payment,
'#parents' => ['payment'],
'#inline_form' => $inline_form,
];
$form['payment'] = $inline_form->buildInlineForm($form['payment'], $form_state);
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Add payment'),
......@@ -236,6 +251,18 @@ class PaymentAddForm extends FormBase implements ContainerInjectionInterface {
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$step = $form_state->get('step');
if ($step == 'payment') {
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $form['payment']['#inline_form'];
$inline_form->validateInlineForm($form['payment'], $form_state);
}
}
/**
* {@inheritdoc}
*/
......@@ -246,10 +273,12 @@ class PaymentAddForm extends FormBase implements ContainerInjectionInterface {
$form_state->setRebuild(TRUE);
}
elseif ($step == 'payment') {
/** @var \Drupal\commerce_payment\Entity\PaymentInterface $payment */
$payment = $form_state->getValue('payment');
/** @var \Drupal\commerce\Plugin\Commerce\InlineForm\EntityInlineFormInterface $inline_form */
$inline_form = $form['payment']['#inline_form'];
$inline_form->submitInlineForm($form['payment'], $form_state);
$this->messenger()->addMessage($this->t('Payment saved.'));
$form_state->setRedirect('entity.commerce_payment.collection', ['commerce_order' => $payment->getOrderId()]);
$form_state->setRedirect('entity.commerce_payment.collection', ['commerce_order' => $this->order->id()]);
}
}
......
......@@ -2,6 +2,7 @@
namespace Drupal\commerce_payment\Form;
use Drupal\commerce\InlineFormManager;
use Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\SupportsStoredPaymentMethodsInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
......@@ -23,14 +24,24 @@ class PaymentMethodAddForm extends FormBase implements ContainerInjectionInterfa
*/
protected $entityTypeManager;
/**
* The inline form manager.
*
* @var \Drupal\commerce\InlineFormManager
*/
protected $inlineFormManager;
/**