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!!!

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

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

I think issue is $imageCodes is Private Member.

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

after adding this code clear cache and check

  • 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.