magepal / magento2-google-tag-manager

Google Tag Manager is a user-friendly, yet powerful and cost-effective solution that is a must-have integration for every Magento store. It simplifies the process of adding and managing third-party JavaScript tags. With dozens of custom events and hundreds of data points our extensions the #1 GTM solution for Magento.

Home Page:https://www.magepal.com/google-tag-manager.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Provider with numeric indices appends instead of replace

Serializator opened this issue · comments

I was trying to use the MagePal\GoogleTagManager\DataLayer\OrderData\OrderProvider through DI to add my own provider to the $orderProviders argument, which by itself works.

I want to add a key to each element inside the "transactionProducts" sub-array from the "gtm.orderCompleted" event, but it appended two new elements onto the "transactionProducts" sub-array rather than override the elements at the specified indices.

Because MagePal\GoogleTagManager\DataLayer\OrderData\OrderProvider uses array_replace_recursive, it appends instead of replace numeric indices.

PHP Docs
_array_merge_recursive() merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.

If the input arrays have the same string keys, then the values for these keys are merged together into an array, and this is done recursively, so that if one of the values is an array itself, the function will merge it with a corresponding entry in another array too. If, however, the arrays have the same numeric key, the later value will not overwrite the original value, but will be appended._

Using "array_replace_recursive" resolves the issue, but I'm not certain about backward compatibility.

Magento version #: 2.3.2

Edition (EE, CE, OS, etc): EE

Expected behavior:

...
"transactionProducts" => [
    [
        "name" => "A Product",
        "foobar" => "I'm foobar"
    ]
]
...

Actual behavior:

...
"transactionProducts" => [
    [
        "name" => "A Product"
    ],
    [
        "foobar" => "I'm foobar"
    ]
]
...

Steps to reproduce:

  • Write a order provider using the MagePal\GoogleTagManager\DataLayer\OrderData\OrderAbstract class
  • Add the order provider to orderProviders in MagePal\GoogleTagManager\DataLayer\OrderData\OrderProvider using DI
  •   public function getData()
      {
          return ["transactionProducts" => [
              0 => [
                  "foobar" => "I'm foobar"
              ]
          ]];  
      }

@Serializator ... this is kinda limitation in the design, originally I was using array_merge_recursive and switch to array_merge in the latest version because if you tried to merge any layer that has 'event' then you would stop the events from triggering and cause a lot more issues.

You can easily accomplish this using OrderItemProvider
MagePal\GoogleTagManager\DataLayer\OrderData\OrderItemProvider

Eg

/**
 * @package MagePal\DataLayer\Data\OrderData
 */
class OrderItemProvider extends OrderItemAbstract
{
    /**
     * @var Product
     */
    private $productHelper;

    /**
     * ItemProvider constructor.
     * @param  Product  $productHelper
     */
    public function __construct(
        Product $productHelper
    ) {
        $this->productHelper = $productHelper;
    }

    /**
     * @return array
     */
    public function getData()
    {
        $product = $this->getItem()->getProduct();

        return [
            'url' => $product->getProductUrl(),
            'image_url' => $this->productHelper->getImageUrl($product)
        ];
    }
}

Hi @srenon,

Thank you for the quick help, I didn't notice the MagePal\GoogleTagManager\DataLayer\OrderData\OrderItemProvider, this would indeed do exactly what I want.