diff --git a/src/Element/PaymentLineItemsInput.php b/src/Element/PaymentLineItemsInput.php index 26f9765b..18f20f9b 100644 --- a/src/Element/PaymentLineItemsInput.php +++ b/src/Element/PaymentLineItemsInput.php @@ -9,7 +9,6 @@ use Drupal\Core\Ajax\RemoveCommand; use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\Render\Element; use Drupal\Core\Render\Element\FormElement; use Drupal\Core\Render\RendererInterface; use Drupal\Core\StringTranslation\TranslationInterface; @@ -187,6 +186,8 @@ class PaymentLineItemsInput extends FormElement implements ContainerFactoryPlugi '#submit' => array(array(get_class($this), 'deleteSubmit')), '#type' => 'submit', '#value' => $this->t('Delete'), + // Fixes https://www.drupal.org/project/drupal/issues/2546700. + '#name' => 'delete_' . implode('-', $element['#parents']) . '_' . $line_item->getName(), ); } @@ -218,15 +219,11 @@ class PaymentLineItemsInput extends FormElement implements ContainerFactoryPlugi '#limit_validation_errors' => array( array_merge($element['#parents'], array('add_more', 'type')), ), - '#submit' => array(function(array $form, FormStateInterface $form_state) use ($plugin_id) { - /** @var \Drupal\Component\Plugin\PluginManagerInterface $element_info_manager */ - $element_info_manager = \Drupal::service('plugin.manager.element_info'); - /** @var \Drupal\payment\Element\PaymentLineItemsInput $element_plugin */ - $element_plugin = $element_info_manager->createInstance($plugin_id); - $element_plugin->addMoreSubmit($form, $form_state); - }), + '#submit' => [[get_class($this), 'addMoreSubmit']], '#type' => 'submit', '#value' => $this->t('Add and configure a new line item'), + // Fixes https://www.drupal.org/project/drupal/issues/2546700. + '#name' => 'add_' . implode('-', $element['#parents']), ); return $element; @@ -258,13 +255,13 @@ class PaymentLineItemsInput extends FormElement implements ContainerFactoryPlugi /** * Implements form #submit callback. */ - public function addMoreSubmit(array &$form, FormStateInterface $form_state) { + public static function addMoreSubmit(array &$form, FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); $parents = array_slice($triggering_element['#array_parents'], 0, -2); $root_element = NestedArray::getValue($form, $parents); $values = $form_state->getValues(); $values = NestedArray::getValue($values, array_slice($triggering_element['#parents'], 0, -2)); - $line_item = $this->paymentLineItemManager->createInstance($values['add_more']['type']); + $line_item = \Drupal::service('plugin.manager.payment.line_item')->createInstance($values['add_more']['type']); $line_item->setName(static::createLineItemName($root_element, $form_state, $values['add_more']['type'])); $line_items = static::getLineItems($root_element, $form_state); $line_items[] = $line_item; @@ -275,14 +272,11 @@ class PaymentLineItemsInput extends FormElement implements ContainerFactoryPlugi /** * Implements form AJAX callback. */ - public function ajaxAddMoreSubmit(array &$form, FormStateInterface $form_state) { + public static function ajaxAddMoreSubmit(array &$form, FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); $parents = array_slice($triggering_element['#array_parents'], 0, -2); - $root_element = NestedArray::getValue($form, $parents); - $response = new AjaxResponse(); - $response->addCommand(new ReplaceCommand('#' . $root_element['#id'], $this->renderer->render($root_element))); - - return $response; + $element = NestedArray::getValue($form, $parents); + return $element; } /** @@ -290,7 +284,7 @@ class PaymentLineItemsInput extends FormElement implements ContainerFactoryPlugi */ public static function deleteSubmit(array &$form, FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); - $root_element_parents = array_slice($triggering_element['#array_parents'], 0, -3); + $root_element_parents = array_slice($triggering_element['#array_parents'], 0, -3); $root_element = NestedArray::getValue($form, $root_element_parents); $parents = $triggering_element['#array_parents']; $line_item_name = $parents[count($parents) - 2]; @@ -310,7 +304,7 @@ class PaymentLineItemsInput extends FormElement implements ContainerFactoryPlugi */ public static function ajaxDeleteSubmit(array &$form, FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); - $root_element_parents = array_slice($triggering_element['#array_parents'], 0, -3); + $root_element_parents = array_slice($triggering_element['#array_parents'], 0, -3); $root_element = NestedArray::getValue($form, $root_element_parents); $parents = $triggering_element['#array_parents']; $line_item_name = $parents[count($parents) - 2]; @@ -391,13 +385,7 @@ class PaymentLineItemsInput extends FormElement implements ContainerFactoryPlugi * @return string */ protected static function getElementId(array $element, FormStateInterface $form_state) { - $key = 'payment.element.payment_line_items_input.id.' . $element['#name']; - - if (!$form_state->has($key)) { - $form_state->set($key, Html::getUniqueId('payment-element-payment_line_items_input')); - } - - return $form_state->get($key); + return Html::getId('payment-element-payment_line_items_input--' . implode('-', $element['#parents'])); } /** @@ -418,6 +406,7 @@ class PaymentLineItemsInput extends FormElement implements ContainerFactoryPlugi * {@inheritdoc} */ public static function valueCallback(&$element, $input, FormStateInterface $form_state) { + static::initializeLineItems($element, $form_state); return static::getLineItems($element, $form_state); } diff --git a/tests/src/Unit/Element/PaymentLineItemsInputTest.php b/tests/src/Unit/Element/PaymentLineItemsInputTest.php index 365746bb..7712ecf1 100644 --- a/tests/src/Unit/Element/PaymentLineItemsInputTest.php +++ b/tests/src/Unit/Element/PaymentLineItemsInputTest.php @@ -117,6 +117,7 @@ namespace Drupal\Tests\payment\Unit\Element { '#cardinality' => 1, '#default_value' => $line_items, '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $form_state = $this->getMock(FormStateInterface::class); $form = []; @@ -137,6 +138,7 @@ namespace Drupal\Tests\payment\Unit\Element { '#cardinality' => PaymentLineItemsInput::CARDINALITY_UNLIMITED, '#default_value' => $line_items, '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $form_state = $this->getMock(FormStateInterface::class); $form = []; @@ -197,7 +199,7 @@ namespace Drupal\Tests\payment\Unit\Element { '#cardinality' => PaymentLineItemsInput::CARDINALITY_UNLIMITED, '#default_value' => $line_items, '#name' => $this->randomMachineName(), - '#parents' => [], + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $element = $this->sut->process($element, $form_state, $form); @@ -224,6 +226,7 @@ namespace Drupal\Tests\payment\Unit\Element { $element = array( '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $form_state = new FormState(); @@ -251,6 +254,7 @@ namespace Drupal\Tests\payment\Unit\Element { $element = array( '#name' => $this->randomMachineName(), '#default_value' => $line_items, + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $form_state = new FormState(); @@ -281,6 +285,7 @@ namespace Drupal\Tests\payment\Unit\Element { $element = array( '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $form_state = new FormState(); @@ -314,6 +319,7 @@ namespace Drupal\Tests\payment\Unit\Element { $element = array( '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $form_state = new FormState(); @@ -350,6 +356,7 @@ namespace Drupal\Tests\payment\Unit\Element { $element = array( '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $form_state = new FormState(); @@ -391,6 +398,7 @@ namespace Drupal\Tests\payment\Unit\Element { $form_build = array( 'foo' => array( '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), 'add_more' => array( 'add' => array( '#array_parents' => array('foo', 'add_more', 'add'), @@ -419,6 +427,7 @@ namespace Drupal\Tests\payment\Unit\Element { 'foo' => array( '#id' => $this->randomMachineName(), '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), 'add_more' => array( 'add' => array( '#array_parents' => array('foo', 'add_more', 'add'), @@ -458,6 +467,7 @@ namespace Drupal\Tests\payment\Unit\Element { $form_build = array( 'foo' => array( '#name' => $root_element_name, + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), 'line_items' => array( $line_item_name => array( 'delete' => array( @@ -468,6 +478,7 @@ namespace Drupal\Tests\payment\Unit\Element { ), ), ); + $form_build['foo']['line_items'][$line_item_name]['delete']['#name'] = 'delete_' . implode('-', $form_build['foo']['#parents']); $form_state = new FormState(); $form_state->set('payment.element.payment_line_items_input.configured.' . $root_element_name, array($line_item_a, $line_item_b, $line_item_c)); @@ -493,6 +504,7 @@ namespace Drupal\Tests\payment\Unit\Element { 'foo' => array( '#id' => $this->randomMachineName(), '#name' => $root_element_name, + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), 'line_items' => array( $line_item_name => array( 'delete' => array( @@ -503,6 +515,7 @@ namespace Drupal\Tests\payment\Unit\Element { ), ), ); + $form_build['foo']['line_items'][$line_item_name]['delete']['#name'] = 'delete_' . implode('-', $form_build['foo']['#parents']); $form_state = new FormState(); $form_state->setTriggeringElement($form_build['foo']['line_items'][$line_item_name]['delete']); @@ -518,6 +531,7 @@ namespace Drupal\Tests\payment\Unit\Element { public function testGetElementId() { $element_build = array( '#name' => $this->randomMachineName(), + '#parents' => array($this->randomMachineName(), $this->randomMachineName()), ); $id_prefix = Html::getId('payment-element-payment_line_items_input');