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.
https://www.magepal.com/google-tag-manager.html
259 stars 89 forks source link

Disabled child of configurable product issue #64

Closed TommyChausson closed 4 years ago

TommyChausson commented 4 years ago

Hi,

I've noticed a bug in a specific case that i will describe below :

Magento version #:

Magento CE 2.3.2

Edition (EE, CE, OS, etc):

CE

Expected behavior:

Display a cart page even if i've disabled products inside

Actual behavior:

Throw fatal error

`Call to a member function getName() on null in /var/www/htdocs/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php:1000 Stack trace:

0 /var/www/htdocs/vendor/magepal/magento2-googletagmanager/Helper/DataLayerItem.php(159): Magento\ConfigurableProduct\Model\Product\Type\Configurable->getOrderOptions(Object(Magento\Catalog\Model\Product\Interceptor))

1 /var/www/htdocs/vendor/magepal/magento2-googletagmanager/Model/Cart.php(111): MagePal\GoogleTagManager\Helper\DataLayerItem->getItemVariant(Object(Magento\Quote\Model\Quote\Item\Interceptor))

2 /var/www/htdocs/vendor/magepal/magento2-googletagmanager/Block/Data/Cart.php(58): MagePal\GoogleTagManager\Model\Cart->getCart()

3 /var/www/htdocs/vendor/magento/framework/View/Element/AbstractBlock.php(283): MagePal\GoogleTagManager\Block\Data\Cart->_prepareLayout()

4 /var/www/htdocs/vendor/magento/framework/View/Layout/Generator/Block.php(149): Magento\Framework\View\Element\AbstractBlock->setLayout(Object(Magento\Framework in /var/www/htdocs/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php on line 1000`

Steps to reproduce:

I've Updated to the last module version.

Can you confirm the Issue ?

Regards,

sipy commented 4 years ago

Hello, exact same error here in Magento CE 2.3.3. The configurable product is not even disabled and the error is thrown anyway:

PHP Fatal error: Uncaught Error: Call to a member function getName() on null in /path_to_magento/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php:992 Stack trace:

0 /path_to_magento/generated/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Interceptor.php(310):

Magento\\ConfigurableProduct\\Model\\Product\\Type\\Configurable->getOrderOptions(Object(Magento\\Catalog\\Model\\Product\\Interceptor))

1 /path_to_magento/vendor/magepal/magento2-googletagmanager/Helper/DataLayerItem.php(159):

Magento\\ConfigurableProduct\\Model\\Product\\Type\\Configurable\\Interceptor->getOrderOptions(Object(Magento\\Catalog\\Model\\Product\\Interceptor))

2 /path_to_magento/vendor/magepal/magento2-googletagmanager/Model/Cart.php(103):

MagePal\\GoogleTagManager\\Helper\\DataLayerItem->getItemVariant(Object(Magento\\Quote\\Model\\Quote\\Item\\Interceptor))

Please help

srenon commented 4 years ago

I will look into a different way to implement this to bypass this issue, but this is technically a bug in Magento where they assume the product will always exist, our extension just highlights this issue.

So you can either disable the variant feature in our admin configuration or patch to the core issue until I revisit this logic and find a workaround.

A quick fix would be to apply a patch to https://github.com/magento/magento2/blob/2.3/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php#L992

From

public function getOrderOptions($product)
{
    $options = parent::getOrderOptions($product);
    $options['attributes_info'] = $this->getSelectedAttributesInfo($product);
    if ($simpleOption = $product->getCustomOption('simple_product')) {
        $options['simple_name'] = $simpleOption->getProduct()->getName();
        $options['simple_sku'] = $simpleOption->getProduct()->getSku();
    }

To

public function getOrderOptions($product)
{
    $options = parent::getOrderOptions($product);
    $options['attributes_info'] = $this->getSelectedAttributesInfo($product);
    if ($simpleOption = $product->getCustomOption('simple_product')) {
        if ($simpleOption->getProduct()) {
             $options['simple_name'] = $simpleOption->getProduct()->getName();
             $options['simple_sku'] = $simpleOption->getProduct()->getSku();
       }
    }