1

I Have created recently viewed product widget in backend category page sidebar. I have single store with multiple Currency setup when i view the product gets added to list perfectly.

My problem is when I change the currency the image gets removed. Again i need to view that product to sort that issue. So i need to overide below file to fix the issue..

I need to overide the below file

Magento\Catalog\Ui\DataProvider\Product\Listing\Collector\Image

I have tried using Preference but unfortunately it is not working.

$this->imageCodes returns an empty array. The value for this is set in

module-catalog/etc/di.xml.

around line 992

Could anyone suggest me a way to overide this class.

So far what i have done is

app/code/Vendor/Module/etc/di.xml

<preference for="Magento\Catalog\Ui\DataProvider\Product\Listing\Collector\Image" type="Vendor\Module\Plugin\Ui\DataProvider\Product\Listing\Collector\Image" />

Then app/code/Vendor/Module/Plugin/Ui/DataProvider/Product/Listing/Collector/Image.php

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

namespace Vendor\Module\Plugin\Ui\DataProvider\Product\Listing\Collector;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductRender\ImageInterface;
use Magento\Catalog\Api\Data\ProductRender\ImageInterfaceFactory;
use Magento\Catalog\Api\Data\ProductRenderInterface;
use Magento\Catalog\Helper\ImageFactory;
use Magento\Catalog\Model\Product\Image\NotLoadInfoImageException;
use Magento\Catalog\Ui\DataProvider\Product\ProductRenderCollectorInterface;
use Magento\Framework\App\State;
use Magento\Framework\View\Design\ThemeInterface;
use Magento\Framework\View\DesignInterface;
use Magento\Store\Model\StoreManager;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\View\DesignLoader;

/**
 * Collect enough information about image rendering on front
 * If you want to add new image, that should render on front you need
 * to configure this class in di.xml
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Image extends \Magento\Catalog\Ui\DataProvider\Product\Listing\Collector\Image
{

    /**
     * @var ImageFactory
     */
    private $imageFactory;

    /**
     * @var array
     */
    private $imageCodes;

    /**
     * @var State
     */
    private $state;

    /**
     * @var StoreManager
     */
    private $storeManager;

    /**
     * @var DesignInterface
     * @deprecated 103.0.1 DesignLoader is used for design theme loading
     */
    private $design;

    /**
     * @var ImageInterfaceFactory
     */
    private $imageRenderInfoFactory;

    /**
     * @var DesignLoader
     */
    private $designLoader;

    /**
     * Image constructor.
     * @param ImageFactory $imageFactory
     * @param State $state
     * @param StoreManager|StoreManagerInterface $storeManager
     * @param DesignInterface $design
     * @param ImageInterfaceFactory $imageRenderInfoFactory
     * @param array $imageCodes
     * @param DesignLoader $designLoader
     */
    public function __construct(
        ImageFactory $imageFactory,
        State $state,
        StoreManagerInterface $storeManager,
        DesignInterface $design,
        ImageInterfaceFactory $imageRenderInfoFactory,
        array $imageCodes = [],
        DesignLoader $designLoader = null
    ) {
        parent::__construct($imageFactory, $state, $storeManager, $design, $imageRenderInfoFactory, $imageCodes, $designLoader);
    }

    /**
     * In order to allow to use image generation using Services, we need to emulate area code and store code
     *
     * @inheritdoc
     */
    public function collect(ProductInterface $product, ProductRenderInterface $productRender)
    {
        $images = [];
        /** @var ThemeInterface $currentTheme */
        $currentTheme = $this->design->getDesignTheme();
        print_r($this->imageCodes);die;
        foreach ($this->imageCodes as $imageCode) {
            /** @var ImageInterface $image */
            $image = $this->imageRenderInfoFactory->create();
            /** @var \Magento\Catalog\Helper\Image $helper */
            $helper = $this->state
                ->emulateAreaCode(
                    'frontend',
                    [$this, "emulateImageCreating"],
                    [$product, $imageCode, (int) $productRender->getStoreId(), $image]
                );

            try {
                $resizedInfo = $helper->getResizedImageInfo();
            } catch (NotLoadInfoImageException $exception) {
                $resizedInfo = [$helper->getWidth(), $helper->getHeight()];
            }

            $image->setCode($imageCode);
            $image->setHeight($helper->getHeight());
            $image->setWidth($helper->getWidth());
            $image->setLabel($helper->getLabel());
            $image->setResizedHeight($resizedInfo[1]);
            $image->setResizedWidth($resizedInfo[0]);

            $images[] = $image;
        }

        $this->design->setDesignTheme($currentTheme);
        $productRender->setImages($images);
    }

    /**
     * Callback for emulating image creation
     *
     * Callback in which we emulate initialize default design theme, depends on current store, be settings store id
     * from render info
     *
     * @param ProductInterface $product
     * @param string $imageCode
     * @param int $storeId
     * @param ImageInterface $image
     * @return \Magento\Catalog\Helper\Image
     */
    public function emulateImageCreating(ProductInterface $product, $imageCode, $storeId, ImageInterface $image)
    {
        $this->storeManager->setCurrentStore($storeId);
        $this->designLoader->load();

        $imageHelper = $this->imageFactory->create();
        $imageHelper->init($product, $imageCode);
        $image->setUrl($imageHelper->getUrl());
        return $imageHelper;
    }
}

Kindly help!!!

5
  • Any how you solved it ?
    – anonymous
    Mar 19 '20 at 16:11
  • 1
    Yes i have solved it..
    – aravind
    Mar 20 '20 at 4:34
  • Great :) Would you mind to post answer so that I can check where I'm making mistake?
    – anonymous
    Mar 20 '20 at 6:47
  • Have you tired my code?
    – aravind
    Mar 20 '20 at 8:25
  • Yes buddy, I've tried your code, I forgot to add arguments for class, Why we need those imagecode as argument here ? like, Any idea?? Also I'm trying to override this because in recently viewed widget my imges are breaking randomly, I've to test more and see if this will solve my issue or not. Thanks
    – anonymous
    Mar 20 '20 at 12:50
1

Better use plugin for this case instead overwrite class

You can add intercept in public method collect or emulateImageCreating

You can use aroundCollect for full modify behavior method

<type name="Magento\Catalog\Ui\DataProvider\Product\Listing\Collector\Image">
    <plugin name="aroundCollectImage" type="Vendor\Module\Plugin\DataProvider\Product\Listing\Collector\Image" />
</type>

Create new class plugin

Vendor\Module\Plugin\DataProvider\Product\Listing\Collector\Image

No need extend origin class just add aroundCollect method

1
  • I will check now..
    – aravind
    Dec 16 '19 at 4:28
1

In vendor/Module/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
 <type name="Magento\Catalog\Ui\DataProvider\Product\Listing\Collector\Image">
        <plugin name="recently_viewed_image"
            type="Vendor\Module\Ui\DataProvider\Product\Listing\Collector\Image"
            sortOrder="10" disabled="false" />
    </type>
    <type name="Vendor\Module\Ui\DataProvider\Product\Listing\Collector\Image">
        <arguments>
            <argument name="imageCodes" xsi:type="array">
                <item name="widget_recently_viewed_grid" xsi:type="string">recently_viewed_products_grid_content_widget</item>
                <item name="widget_recently_viewed_list" xsi:type="string">recently_viewed_products_list_content_widget</item>
                <item name="widget_recently_viewed_sidebar" xsi:type="string">recently_viewed_products_images_names_widget</item>
                <item name="widget_recently_compared_grid" xsi:type="string">recently_compared_products_grid_content_widget</item>
                <item name="widget_recently_compared_list" xsi:type="string">recently_compared_products_list_content_widget</item>
                <item name="widget_recently_compared_sidebar" xsi:type="string">recently_compared_products_images_names_widget</item>
            </argument>
        </arguments>
    </type>
</config>

Then in plugin file Vendor\Module\Ui\DataProvider\Product\Listing\Collector\Image add below code,

<?php
namespace Vendor\Module\Ui\DataProvider\Product\Listing\Collector;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductRender\ImageInterface;
use Magento\Catalog\Api\Data\ProductRender\ImageInterfaceFactory;
use Magento\Catalog\Api\Data\ProductRenderInterface;
use Magento\Catalog\Helper\ImageFactory;
use Magento\Catalog\Model\Product\Image\NotLoadInfoImageException;
use Magento\Catalog\Ui\DataProvider\Product\ProductRenderCollectorInterface;
use Magento\Framework\App\State;
use Magento\Framework\View\Design\ThemeInterface;
use Magento\Framework\View\DesignInterface;
use Magento\Store\Model\StoreManager;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\View\DesignLoader;

class Image
{
    /** Key for image information access to, when render product */
    const KEY = "images";

    /**
     * @var ImageFactory
     */
    private $imageFactory;

    /**
     * @var array
     */
    private $imageCodes;

    /**
     * @var State
     */
    private $state;

    /**
     * @var StoreManager
     */
    private $storeManager;

    /**
     * @var DesignInterface
     * @deprecated 103.0.1 DesignLoader is used for design theme loading
     */
    private $design;

    /**
     * @var ImageInterfaceFactory
     */
    private $imageRenderInfoFactory;

    /**
     * @var DesignLoader
     */
    private $designLoader;

    /**
     * Image constructor.
     * @param ImageFactory $imageFactory
     * @param State $state
     * @param StoreManager|StoreManagerInterface $storeManager
     * @param DesignInterface $design
     * @param ImageInterfaceFactory $imageRenderInfoFactory
     * @param array $imageCodes
     * @param DesignLoader $designLoader
     */
    public function __construct(
        ImageFactory $imageFactory,
        State $state,
        StoreManagerInterface $storeManager,
        DesignInterface $design,
        ImageInterfaceFactory $imageRenderInfoFactory,
        array $imageCodes = [],
        DesignLoader $designLoader = null
    ) {
        $this->imageFactory = $imageFactory;
        $this->imageCodes = $imageCodes;
        $this->state = $state;
        $this->storeManager = $storeManager;
        $this->design = $design;
        $this->imageRenderInfoFactory = $imageRenderInfoFactory;
        $this->designLoader = $designLoader ?: \Magento\Framework\App\ObjectManager::getInstance()
            ->get(DesignLoader::class);
    }

    public function aroundCollect(
        \Magento\Catalog\Ui\DataProvider\Product\Listing\Collector\Image $subject,
        \Closure $proceed,
        ProductInterface $product,
        ProductRenderInterface $productRender
    ) {
        $images = [];
        /** @var ThemeInterface $currentTheme */
        $currentTheme = $this->design->getDesignTheme();
        $this->design->setDesignTheme($currentTheme);

        foreach ($this->imageCodes as $imageCode) {
            /** @var ImageInterface $image */
            $image = $this->imageRenderInfoFactory->create();
            /** @var \Magento\Catalog\Helper\Image $helper */
            $helper = $this->state
                ->emulateAreaCode(
                    'frontend',
                    [$this, "emulateImageCreating"],
                    [$product, $imageCode, (int) $productRender->getStoreId(), $image]
                );

            try {
                $resizedInfo = $helper->getResizedImageInfo();
            } catch (NotLoadInfoImageException $exception) {
                $resizedInfo = [$helper->getWidth(), $helper->getHeight()];
            }

            $image->setCode($imageCode);
            $image->setHeight($helper->getHeight());
            $image->setWidth($helper->getWidth());
            $image->setLabel($helper->getLabel());
            $image->setResizedHeight($resizedInfo[1]);
            $image->setResizedWidth($resizedInfo[0]);

            $images[] = $image;

        }

        $productRender->setImages($images);
    }

     /* Callback for emulating image creation
     *
     * Callback in which we emulate initialize default design theme, depends on current store, be settings store id
     * from render info
     *
     * @param ProductInterface $product
     * @param string $imageCode
     * @param int $storeId
     * @param ImageInterface $image
     * @return \Magento\Catalog\Helper\Image
     */
    public function emulateImageCreating(ProductInterface $product, $imageCode, $storeId, ImageInterface $image)
    {
        $this->storeManager->setCurrentStore($storeId);
        $this->designLoader->load();

        $imageHelper = $this->imageFactory->create();
        $imageHelper->init($product, $imageCode);
        $image->setUrl($imageHelper->getUrl());
        return $imageHelper;
    }
}

Hope it helps!!

0

I think issue is $imageCodes is Private Member.

In Your __construct define $this->imageCodes = $imageCodes;

after adding this code clear cache and check

1
  • I have checked but it is still not working..
    – aravind
    Dec 16 '19 at 4:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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