AddressFinder / addressfinder-magento

AddressFinder extension for Magento 2
Other
7 stars 7 forks source link

Fixes an issue with multiple payment methods introduced in code refactor #65

Closed bencorlett closed 4 years ago

bencorlett commented 4 years ago

This PR fixes an issue where multiple payment methods would attach forms to AddressFinder reusing the same ID which would cause an exception to be thrown:

Exception #0 (Exception): Item (Magento\Framework\DataObject) with the same ID "frontend.checkout.billing.address" already exists.
<pre>#1 AddressFinder\AddressFinder\Observer\FormConfig\Frontend\AddCheckoutBillingAddress->addForm() called at [app/code/AddressFinder/AddressFinder/Observer/FormConfig/Base.php:64]
#2 AddressFinder\AddressFinder\Observer\FormConfig\Base->execute() called at [vendor/magento/framework/Event/Invoker/InvokerDefault.php:88]
#3 Magento\Framework\Event\Invoker\InvokerDefault->_callObserverMethod() called at [vendor/magento/framework/Event/Invoker/InvokerDefault.php:74]
#4 Magento\Framework\Event\Invoker\InvokerDefault->dispatch() called at [vendor/magento/framework/Event/Manager.php:66]
#5 Magento\Framework\Event\Manager->dispatch() called at [generated/code/Magento/Framework/Event/Manager/Proxy.php:95]
#6 Magento\Framework\Event\Manager\Proxy->dispatch() called at [app/code/AddressFinder/AddressFinder/Model/FormConfigProvider.php:91]
#7 AddressFinder\AddressFinder\Model\FormConfigProvider->get() called at [app/code/AddressFinder/AddressFinder/Block/Plugin.php:71]
#8 AddressFinder\AddressFinder\Block\Plugin->getFormsConfig() called at [app/code/AddressFinder/AddressFinder/view/frontend/templates/plugin.phtml:12]

A new internal code feature that was introduced to assist with debugging was to provide a form ID to each form. This would make it easier to trace down issues particularly if there are multiple forms on the same page. An example of how we configure this is here:

<?php

$forms->addItem(new DataObject([
    'id' => self::FORM_ID,
    // ...
]);

Each ID must be unique, and this is where the problem is introduced. Magento duplicates the billing form for every payment method, which means we must also perform this duplication:

<?php

foreach ($this->getActivePaymentMethodCodes() as $code) {
    $forms->addItem(new DataObject([
        'id' => self::FORM_ID,
        // ...
   ]);
}

The problem here is, if there's more than one payment method, we're adding multiple forms with the same ID. As with all of the other fields in these forms, we need to integrate the payment method's code into the form ID so that it is always unique. Payment method codes must also be unique (this is enforced internally by Magento).

So that's what we've done.

After enabling a second payment method in the test environment, prior to the fix, the following error is produced (in developer mode) or the plugin is silenced (in production mode):

Screen Shot 2020-05-14 at 5 22 41 am

After the fix, everything works as expected (across both shipping and billing sections of the checkout):

Screen Shot 2020-05-14 at 5 24 16 am