Adding custom images to the product media gallery.

August 28, 2019

Recently needed to add custom images to the media gallery, and below are the two approaches I investigated.

First of all, lets look how to do this in Javascript, as this seemed like a good way of going about it. By modifying the media gallery widget we can update the gallery images fairly easily:

<script>
    require(['jquery'], function ($) {
        var gallerySelector = '[data-gallery-role=gallery-placeholder]';
        $(gallerySelector).on('gallery:loaded', function () {
            var gallery = $(gallerySelector).data('gallery');
            var images = gallery.returnCurrentImages();
            images.push({
                img: 'image1.jpg',
                thumb: 'thumb1.jpg',
                full: 'full1.jpg',
                caption: 'caption',
                position: 100
            });
            gallery.updateData(images);
        });
    });
</script>

This works quite nicely. But to be honest, I’d prefer the images to be added to the gallery in PHP code rather than in JS, because it’ll have less of a performance impact.

So let’s take a look at my second, and final approach:

I used a plugin after getGalleryImages is called on the Gallery block class: Magento\Catalog\Block\Product\View\Gallery. All we’ll need to do is add our image data to the collection that getGalleryImages returns. Simple as that.

File: 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\Block\Product\View\Gallery">
        <plugin name="add_images_to_gallery" type="VENDOR\MODULE\Plugin\AddImagesToGalleryBlock" />
    </type>
</config>

File: Plugin/AddImagesToGalleryBlock.php

<?php
namespace VENDOR\MODULE\Plugin;

use Magento\Catalog\Helper\Image;
use Magento\Catalog\Model\Product;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Catalog\Block\Product\View\Gallery;

class AddImagesToGalleryBlock
{
    protected $dataCollectionFactory;
    protected $filesystem;
    protected $mediaConfig;
    protected $imageHelper;
    protected $dataCollectionFactory;

    public function __construct(
        \Magento\Framework\Data\CollectionFactory $dataCollectionFactory,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\Catalog\Model\Product\Media\Config $mediaConfig,
        Image $imageHelper,
        \Magento\Framework\Data\CollectionFactory $dataCollectionFactory
)
    {
        $this->dataCollectionFactory = $dataCollectionFactory;
        $this->filesystem = $filesystem;
        $this->mediaConfig = $mediaConfig;
        $this->imageHelper = $imageHelper;
        $this->dataCollectionFactory = $dataCollectionFactory;
    }

    /**
     * @param Gallery $subject
     * @param \Magento\Framework\Data\Collection|null $images
     * @return \Magento\Framework\Data\Collection|null
     */
    public function afterGetGalleryImages(Gallery $subject, $images) {
        $product = $subject->getProduct();
        if (!$images instanceof  \Magento\Framework\Data\Collection) {
            $images = $this->dataCollectionFactory->create();
        }

       
        $myCustomImages = $product->getExtensionAttributes()->getCustomImages();
        if (empty($myCustomImages)) {
            return $images;
        }

        $directory = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA);

        $imageId = uniqid();
        $imageCount = $images->getSize();
        $myCustomImage = '/s/o/some_image.jpg';
        $file = $myCustomImage;
        $smallImage = $this->imageHelper->init($product, 'product_page_image_small')
            ->setImageFile($file)
            ->getUrl();
        $mediumImage = $this->imageHelper->init($product, 'product_page_image_medium')
            ->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false)
            ->setImageFile($file)
            ->getUrl();
        $largeImage = $this->imageHelper->init($product, 'product_page_image_large')
            ->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false)
            ->setImageFile($file)
            ->getUrl();
            
        $image = [
            'file' => $file,
            'media_type' => 'image',
            'value_id' => $imageId, // unique value
            'row_id' => $imageId, // unique value
            'label' => 'some image',
            'label_default' => 'some image',
            'position' => 100,
            'position_default' => 100,
            'disabled' => 0,
            'url'  => $this->mediaConfig->getMediaUrl($file),
            'path' => $directory->getAbsolutePath($this->mediaConfig->getMediaPath($file)),
            'small_image_url' => $smallImage,
            'medium_image_url' => $mediumImage,
            'large_image_url' => $largeImage
        ];
        $images->addItem(new \Magento\Framework\DataObject($image));

        return $images;
    }
}

Side note: you can see I used the product image helper ($this->imageHelper) to fetch the small, medium and large images. This is because the images I’m using are actually stored in the product media (pub/media/catalog/product) directory, and it seemed like a good idea to stick to Magento’s image resizing without any additional customisations.

I hope this article points you in the right direction to adding images to the media gallery!