0

I want to remove product from wishlist from a custom button on detail. I did a plugin for the Magento\Wishlist\Controller\Index\Remove.php with an aroundExecute but for some reason I can't load/create products as magento does in the default Remove controller. I posted my file

 use Magento\Customer\Model\Session;
    use Magento\Framework\Controller\Result\JsonFactory;
    use Magento\Framework\Exception\NotFoundException;
    use Magento\Wishlist\Controller\WishlistProviderInterface;
    use Magento\Wishlist\Model\Item;
    use Magento\Wishlist\Model\Product\AttributeValueProvider;
    use Magento\Wishlist\Model\WishlistFactory;

/**
 * Class Remove
 * @package Codesicle\WishlistAjax\Plugin\Wishlist\Controller\Index
 */
class Remove
{
    /**
     * @var WishlistProviderInterface
     */
    protected $wishlistProvider;

    /**
     * @var AttributeValueProvider
     */
    private $attributeValueProvider;


    /**
     * @var Session
     */
    protected $customerSession;

    /**
     * @var JsonFactory
     */
    protected $jsonFactory;

    /**
     * @var WishlistFactory
     */
    protected $wishlistFactory;

    public function __construct(
        WishlistProviderInterface $wishlistProvider,
        AttributeValueProvider $attributeValueProvider = null,
        JsonFactory $jsonFactory,
        Session $customerSession,
        WishlistFactory $wishlistFactory
    )
    {
        $this->wishlistProvider = $wishlistProvider;
        $this->attributeValueProvider = $attributeValueProvider
            ?: \Magento\Framework\App\ObjectManager::getInstance()->get(AttributeValueProvider::class);
        $this->jsonFactory = $jsonFactory;
        $this->customerSession = $customerSession;
        $this->wishlistFactory = $wishlistFactory;
    }

    public function aroundExecute($subject, $proceed)
    {

        $id = (int)$this->getRequest()->getParam('item');

        $item = $subject->_objectManager->create(Item::class)->load($id);

        if (!$item->getId()) {
            throw new NotFoundException(__('Page not found.'));
        }
        $wishlist = $this->wishlistProvider->getWishlist($item->getWishlistId());
        if (!$wishlist) {
            throw new NotFoundException(__('Page not found.'));
        }
        try {
            $item->delete();
            $wishlist->save();
            $productName = $this->attributeValueProvider
                ->getRawAttributeValue($item->getProductId(), 'name');

            $response = [
                'errors' => false,
                'message' => __('%1 has been removed from your Wish List.', $productName)
            ];
        } catch (\Magento\Framework\Exception\LocalizedException $exception) {
            $response = [
                'errors' => true,
                'message' => __('We can\'t delete the item from Wish List right now because of an error: %1.', $exception->getMessage())
            ];
        } catch (\Exception $exception) {
            $response = [
                'errors' => true,
                'message' => __('We can\'t delete the item from the Wish List right now.')
            ];
        }
        $this->_objectManager->get(\Magento\Wishlist\Helper\Data::class)->calculate();

        $resultJson = $this->jsonFactory->create();
        return $resultJson->setData($response);
    }

What am I missing or what did I do wrong?

LE:

Looks like the getItem method from WishlistFactory is returning NULL and I can't get to find out why

4
  • Which error it show? Commented Aug 9, 2019 at 12:34
  • I get 500 error on the Post request. from some debugging the problem seems to be here or below $subject->_objectManager->create(Item::class)->load($id) but as I said this is how magento does it
    – Vlad Patru
    Commented Aug 9, 2019 at 12:36
  • Create _objectManager then use into your code. Commented Aug 9, 2019 at 12:41
  • @DhirenVasoya I did that and still not working I used $this->_objectManager = $context->getObjectManager(); in the constructor and still I get 500 error
    – Vlad Patru
    Commented Aug 9, 2019 at 13:17

4 Answers 4

0

I see that you pass parameter of class AttributeValueProvider with null default value. The problem should be caused by the way you pass this parameter in dependency injection. So that when you call $this->attributeValueProvider->getRawAttributeValue($item->getProductId(), 'name') PHP will throw fatal error, because the dependency injection does not pass the AttributeValueProvider instance.

Try removing the null default value while passing AttributeValueProvider instance by changing AttributeValueProvider $attributeValueProvider = null to AttributeValueProvider $attributeValueProvider.

If problem persists, try removing the generated interceptor of your class: rm generated/code/Codesicle/WishlistAjax/Plugin/Wishlist/Controller/Index/Remove/Interceptor.php, and retry deleting wishlist item.

1
  • that is not the problem, I tried your version but that was how magento-wishlist module gets the attributeValueProvider for some reason the getItem from the Wishlist model is returning NULL but I can't get to figure out why
    – Vlad Patru
    Commented Aug 12, 2019 at 8:22
0

so I changed the implementation a bit, there was a problem with the getItem() method and I went with the following

  1. get current customer ID $customerId = $this->_session->getCustomerId();

  2. get wishlist by customer ID $wishlist = $this->_wishlist->loadByCustomerId($customerId, true); I had to set create to true here otherwise the collection was not returning, only wishlist info like ID , name , etc.

  3. get item from that collection $item = $wishlist->getItem($id);

0

I would approach to this problem with a different way. When I create a plugin, I always try to focus on the purpose, rather than the result. There can be multiple ways to reach the expected result, but which one would serve the purpose the most?

The purpose here is to return a custom JSON response instead of a redirect. It is not to rewrite a core process to remove a wishlist item.

Here is a working example, giving the same result you are trying to achieve:

use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\Message\MessageInterface;
use Magento\Framework\View\LayoutFactory;
use Magento\Wishlist\Controller\Index\Remove as Subject;
use Magento\Framework\Controller\Result\JsonFactory;

/**
 * Class Remove
 */
class Remove
{
    /**
     * @var LayoutFactory
     */
    protected $layoutFactory;

    /**
     * @var ManagerInterface
     */
    protected $messageManager;

    /**
     * @var JsonFactory
     */
    protected $jsonFactory;

    /**
     * Remove constructor.
     * @param LayoutFactory $layoutFactory
     * @param ManagerInterface $messageManager
     * @param JsonFactory $jsonFactory
     */
    public function __construct(
        LayoutFactory $layoutFactory,
        ManagerInterface $messageManager,
        JsonFactory $jsonFactory
    ) {
        $this->layoutFactory = $layoutFactory;
        $this->messageManager = $messageManager;
        $this->jsonFactory = $jsonFactory;
    }

    /**
     * @param Subject $controller
     * @param \Magento\Framework\Controller\Result\Redirect $result
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function afterExecute(Subject $controller, $result)
    {
        $messages = $this->messageManager->getMessages(true);
        $messagesBlock = $this->layoutFactory->create()->getMessagesBlock();
        $messagesBlock->setMessages($messages);

        $resultJson = $this->jsonFactory->create();
        $resultJson->setData([
            'errors' => boolval($messages->getCountByType(MessageInterface::TYPE_ERROR)),
            'message' => trim(strip_tags($messagesBlock->getGroupedHtml()))
        ]);
        return $resultJson;
    }
}

NOTE: By using the code above, you will need to post form_key parameter too along with the item parameter, as it's validated on the default controller unlike your example code. It may make your job easier to remove that validation, but it is highly unadvised to do so.

0

Try this : Tested Code

Note :Just pass productId parameter in your ajax call & Logged User Id Automatically fetch from the Session

class WishlistRemoveItems extends \Magento\Framework\App\Action\Action
{
    protected $wishlist;

    public function __construct(
        \Magento\Wishlist\Model\Wishlist $wishlist,
        \Magento\Framework\App\Request\Http $request,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Framework\App\Action\Context $context
    ) {
        $this->wishlist = $wishlist;
        $this->request = $request;
        $this->customerSession = $customerSession;
        parent::__construct($context);
    }

    public function execute()
    {

        $customerId =  $this->customerSession->getCustomer()->getId();
        $productId = $this->request->getPostValue('productId');
        $wish = $this->wishlist->loadByCustomerId($customerId);
        $items = $wish->getItemCollection();

        /** @var \Magento\Wishlist\Model\Item $item */
        foreach ($items as $item) {
            if ($item->getProductId() == $productId) {
                $item->delete();
                $wish->save();
            }
        }
    }
}

hope it will help you, Thanks

Your Answer

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

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