0

I am using Magento2.3.5-p2

I want to extend instead of overwriting a Magento class

The class that I want to extend is

vendor/magento/module-wishlist/Controller/Index/Cart.php

so to extend this I created a di.xml file here

app/code/MageBig/Ajaxwishlist/etc/di.xml

with content as below

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Wishlist\Controller\Index\Cart" type="MageBig\Ajaxwishlist\Controller\Wishlist\Cart"/>
</config>

the new file used to extends to that class is

MageBig\Ajaxwishlist\Controller\Wishlist\Cart

which the file path is located at

app/code/MageBig/Ajaxwishlist/Controller/Wishlist/Cart.php

So I copied the entire code from the vendor and extends it as necessary, put it in parent construct, the code is as below

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace MageBig\Ajaxwishlist\Controller\Wishlist;

use Magento\Catalog\Model\Product\Exception as ProductException;
use Magento\Framework\App\Action;
use Magento\Framework\Controller\ResultFactory;

/**
 * Add wishlist item to the shopping cart and remove from wishlist controller.
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Cart extends \Magento\Wishlist\Controller\Index\Cart
{
    private $optionFactory;
    
    public function __construct(
        Action\Context $context,
        \Magento\Wishlist\Controller\WishlistProviderInterface $wishlistProvider,
        \Magento\Wishlist\Model\LocaleQuantityProcessor $quantityProcessor,
        \Magento\Wishlist\Model\ItemFactory $itemFactory,
        \Magento\Checkout\Model\Cart $cart,
        \Magento\Wishlist\Model\Item\OptionFactory $optionFactory,
        \Magento\Catalog\Helper\Product $productHelper,
        \Magento\Framework\Escaper $escaper,
        \Magento\Wishlist\Helper\Data $helper,
        \Magento\Checkout\Helper\Cart $cartHelper,
        \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator,
        \Magento\Catalog\Model\ProductRepository $productRepository,
        \GShop\Product\Helper\EventData $eventData,
        \Magento\Customer\Model\Session $customerSession
    ) {
        parent::__construct($context,$wishlistProvider,$quantityProcessor,$itemFactory,$cart, $optionFactory, $productHelper, $escaper, $helper, $cartHelper, $formKeyValidator);
        $this->_productRepository = $productRepository;
        $this->eventData = $eventData;
        $this->customerSession = $customerSession;
    }

    /**
     * Add wishlist item to the shopping cart and remove from wishlist
     *
     * If Product has required options - item removed from wishlist and redirect
     * to product view page with a message about needed to be defined required options
     *
     * @return \Magento\Framework\Controller\ResultInterface
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function execute()
    {
        /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
        if (!$this->formKeyValidator->validate($this->getRequest())) {
            return $resultRedirect->setPath('*/*/');
        }

        $itemId = (int)$this->getRequest()->getParam('item');
        /* @var $item \Magento\Wishlist\Model\Item */
        $item = $this->itemFactory->create()->load($itemId);

        if (!$item->getId()) {
            $resultRedirect->setPath('*/*');
            return $resultRedirect;
        }
        $wishlist = $this->wishlistProvider->getWishlist($item->getWishlistId());
        if (!$wishlist) {
            $resultRedirect->setPath('*/*');
            return $resultRedirect;
        }

        // Set qty
        $qty = $this->getRequest()->getParam('qty');
        $postQty = $this->getRequest()->getPostValue('qty');
        if ($postQty !== null && $qty !== $postQty) {
            $qty = $postQty;
        }
        if (is_array($qty)) {
            if (isset($qty[$itemId])) {
                $qty = $qty[$itemId];
            } else {
                $qty = 1;
            }
        }
        $qty = $this->quantityProcessor->process($qty);
        if ($qty) {
            $item->setQty($qty);
        }

        $redirectUrl = $this->_url->getUrl('*/*');
        $configureUrl = $this->_url->getUrl(
            '*/*/configure/',
            [
                'id' => $item->getId(),
                'product_id' => $item->getProductId(),
            ]
        );

        try {
            /** @var \Magento\Wishlist\Model\ResourceModel\Item\Option\Collection $options */
            $options = $this->optionFactory->create()->getCollection()->addItemFilter([$itemId]);
            $item->setOptions($options->getOptionsByItem($itemId));

            $buyRequest = $this->productHelper->addParamsToBuyRequest(
                $this->getRequest()->getParams(),
                ['current_config' => $item->getBuyRequest()]
            );

            $item->mergeBuyRequest($buyRequest);
            $item->addToCart($this->cart, true);
            $this->cart->save()->getQuote()->collectTotals();
            $wishlist->save();

            // Start Gtm Event Get Event Of Wishlist Item Added To Cart
            $product_id = $item->getProductId();
            $product = $this->_productRepository->getById($product_id);

            $getEventData = $this->eventData->getGtmDataForAddToCart($product,$this->getRequest()->getParam('qty'));
            $this->customerSession->setGTMWishListItemAddedToCart($getEventData);
            // End Gtm Event Get Event Of Wishlist Item Added To Cart

            if (!$this->cart->getQuote()->getHasError()) {
                $message = __(
                    'You added %1 to your shopping cart.',
                    $this->escaper->escapeHtml($item->getProduct()->getName())
                );
                $this->messageManager->addSuccessMessage($message);
            }

            if ($this->cartHelper->getShouldRedirectToCart()) {
                $redirectUrl = $this->cartHelper->getCartUrl();
            } else {
                $refererUrl = $this->_redirect->getRefererUrl();
                if ($refererUrl && $refererUrl != $configureUrl) {
                    $redirectUrl = $refererUrl;
                }
            }
        } catch (ProductException $e) {
            $this->messageManager->addErrorMessage(__('This product(s) is out of stock.'));
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $this->messageManager->addNoticeMessage($e->getMessage());
            $redirectUrl = $configureUrl;
        } catch (\Exception $e) {
            $this->messageManager->addExceptionMessage($e, __('We can\'t add the item to the cart right now.'));
        }

        $this->helper->calculate();

        if ($this->getRequest()->isAjax()) {
            /** @var \Magento\Framework\Controller\Result\Json $resultJson */
            $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON);
            $resultJson->setData(['backUrl' => $redirectUrl]);
            return $resultJson;
        }

        $resultRedirect->setUrl($redirectUrl);
        return $resultRedirect;
    }
}

I have di:compile , cache clear and relogin user, and when I tried to "add to cart item from wishlist" error as below appear

Fatal error: Uncaught Error: Call to a member function create() on null in /var/www/project/app/code/MageBig/Ajaxwishlist/Controller/Wishlist/Cart.php:106 Stack trace: #0 /var/www/project/vendor/magento/framework/App/Action/Action.php(108): MageBig\Ajaxwishlist\Controller\Wishlist\Cart->execute() #1 /var/www/project/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\App\Action\Action->dispatch(Object(Magento\Framework\App\Request\Http)) #2 /var/www/project/vendor/magento/framework/Interception/Interceptor.php(138): MageBig\Ajaxwishlist\Controller\Wishlist\Cart\Interceptor->___callParent('dispatch', Array) #3 /var/www/project/app/code/Mageplaza/BetterProductReviews/Plugin/App/Action/Context.php(86): MageBig\Ajaxwishlist\Controller\Wishlist\Cart\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http)) #4 /var/www/project/vendor/magento/framework/Interception/Interceptor.php(135): Mageplaza\BetterProductReviews\Plugin\App\Action\ in /var/www/project/app/code/MageBig/Ajaxwishlist/Controller/Wishlist/Cart.php on line 106

The error is happening at line 106, which is here

$options = $this->optionFactory->create()->getCollection()->addItemFilter([$itemId]);

So I am assuming that the $option object returns a null value, I have tried declaring $optionFactory at the top of the code but it does not solve the problem

If anyone has any solution for this situation please help, any help is kindly appreciated

1

3 Answers 3

1

This is because optionfactory is private in parent class you need to inject it in child class.change constructor like this. and execute all commands.


    public function __construct(
        Action\Context $context,
        \Magento\Wishlist\Controller\WishlistProviderInterface $wishlistProvider,
        \Magento\Wishlist\Model\LocaleQuantityProcessor $quantityProcessor,
        \Magento\Wishlist\Model\ItemFactory $itemFactory,
        \Magento\Checkout\Model\Cart $cart,
        \Magento\Wishlist\Model\Item\OptionFactory $optionFactory,
        \Magento\Catalog\Helper\Product $productHelper,
        \Magento\Framework\Escaper $escaper,
        \Magento\Wishlist\Helper\Data $helper,
        \Magento\Checkout\Helper\Cart $cartHelper,
        \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator,
        \Magento\Catalog\Model\ProductRepository $productRepository,
        \GShop\Product\Helper\EventData $eventData,
        \Magento\Customer\Model\Session $customerSession
    ) {
        parent::__construct($context,$wishlistProvider,$quantityProcessor,$itemFactory,$cart, $optionFactory, $productHelper, $escaper, $helper, $cartHelper, $formKeyValidator);
        $this->_productRepository = $productRepository;
        $this->eventData = $eventData;
        $this->customerSession = $customerSession;
        $this->optionFactory = $optionFactory;
    }
2
  • Thank you finally able to fix the error Mar 24, 2022 at 8:07
  • Glad to know. please mark answer as accepted so it can help others.
    – Mehran
    Mar 24, 2022 at 8:08
0

I finally able to get the correct way to extends the class without copying the execute code from vendor, it is by putting own codes and then

return parent::execute();

below is the final code that works

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace MageBig\Ajaxwishlist\Controller\Wishlist;

use Magento\Catalog\Model\Product\Exception as ProductException;
use Magento\Framework\App\Action;
use Magento\Framework\Controller\ResultFactory;

class Cart extends \Magento\Wishlist\Controller\Index\Cart
{
    public $optionFactory;

    public function __construct(
        Action\Context $context,
        \Magento\Wishlist\Controller\WishlistProviderInterface $wishlistProvider,
        \Magento\Wishlist\Model\LocaleQuantityProcessor $quantityProcessor,
        \Magento\Wishlist\Model\ItemFactory $itemFactory,
        \Magento\Checkout\Model\Cart $cart,
        \Magento\Wishlist\Model\Item\OptionFactory $optionFactory,
        \Magento\Catalog\Helper\Product $productHelper,
        \Magento\Framework\Escaper $escaper,
        \Magento\Wishlist\Helper\Data $helper,
        \Magento\Checkout\Helper\Cart $cartHelper,
        \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator,
        \Magento\Catalog\Model\ProductRepository $productRepository,
        \GShop\Product\Helper\EventData $eventData,
        \Magento\Customer\Model\Session $customerSession
    ) {
        parent::__construct($context,$wishlistProvider,$quantityProcessor,$itemFactory,$cart, $optionFactory, $productHelper, $escaper, $helper, $cartHelper, $formKeyValidator);
        $this->_productRepository = $productRepository;
        $this->eventData = $eventData;
        $this->customerSession = $customerSession;
        $this->optionFactory = $optionFactory;
    }

    public function execute()
    {

        $itemId = (int)$this->getRequest()->getParam('item');
        $item = $this->itemFactory->create()->load($itemId);

        // Start Gtm Event Get Event Of Wishlist Item Added To Cart
        $product_id = $item->getProductId();
        $product = $this->_productRepository->getById($product_id);

        $getEventData = $this->eventData->getGtmDataForAddToCart($product,$this->getRequest()->getParam('qty'));
        $this->customerSession->setGTMWishListItemAddedToCart($getEventData);
        // End Gtm Event Get Event Of Wishlist Item Added To Cart

        return parent::execute();
    }
}
0

First, even if you extend the original class in your controller, if you use preference inside di.xml, then you override the class, which is really discouraged in M2. It should only be used as a last resort, because it makes the code hard to debug. Try to use plugin → observer → preference, in this order.

In this case, you have a public method, and you are doing something before the original method. This is a perfect use case for a before plugin.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.