15

preview in backend

preview in backend 2

I need to display few images of product in frontend based on condition: use for virtual mirror should be checked.

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

namespace Dcw\Vm\Observer;

use Magento\Framework\Event\ObserverInterface;

class ChangeTemplateObserver extends \Magento\ProductVideo\Observer\ChangeTemplateObserver
{
    /**
     * @param mixed $observer
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     * @return void
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $observer->getBlock()->setTemplate('Dcw_Vm::helper/gallery.phtml');
    }
}

Template:

<div class="admin__field field-image-vm">
    <div class="admin__field-control">
        <div class="admin__field admin__field-option">
            <input type="checkbox"
                   id="use-for-vm"
                   data-role="vm-save"
                   data-form-part="<?php /* @escapeNotVerified */ echo $formName ?>"
                   value="1"
                   class="admin__control-checkbox"
                   name="<?php /* @escapeNotVerified */ echo $elementName ?>[<%- data.file_id %>][vm]"
            <% if (data.useforvm == 1) { %>checked="checked"<% } %> />

            <label for="use-for-vm" class="admin__field-label">
                <?php /* @escapeNotVerified */ echo __('Use for Virutal Mirror')?>
            </label>
        </div>
    </div>
</div>

Install script:

<?php

namespace Dcw\Vm\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Catalog\Model\ResourceModel\Product\Gallery;

class InstallSchema implements InstallSchemaInterface {

    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) {
        $setup->startSetup();

        $setup->getConnection()->addColumn(
                $setup->getTable(Gallery::GALLERY_TABLE), 'vm', [
            'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            'unsigned' => true,
            'nullable' => false,
            'default' => 0,
            'comment' => 'use for Vm'                ]
        );

        $setup->endSetup();
    }

}

How to save checked images state in backend? And how to filter those images in frontend? Can you help me on this?

UPDATE:

following observer (on event catalog_product_save_after) for existing images is working, but for new images not working.

<?php

namespace Dcw\Vm\Observer;

use Magento\Framework\Event\ObserverInterface;

class Productsaveafter implements ObserverInterface {

    protected $request;
    protected $resource;

    /**
     * 
     * @param \Magento\Framework\App\RequestInterface $request
     * @param \Magento\Framework\App\ResourceConnection $resource\
     */
    public function __construct(
    \Magento\Framework\App\RequestInterface $request, \Magento\Framework\App\ResourceConnection $resource
    ) {
        $this->request = $request;
        $this->resource = $resource;
    }

    public function execute(\Magento\Framework\Event\Observer $observer) {

        $vm = array();
        $data = $this->request->getPostValue();

        if (isset($data['product']['media_gallery']['images'])) {
            $images = $data['product']['media_gallery']['images'];

            foreach ($images as $image) {
                if (isset($image['vm']) && $image['vm'] == 1) {
                    $vm[$image['value_id']] = 1;
                } else {
                    $vm[$image['value_id']] = 0;
                }
            }
   // print_r($images);exit;
            $connection = $this->resource->getConnection();
            $tableName = 'catalog_product_entity_media_gallery'; //gives table name with prefix
            $product = $observer->getProduct();
            $mediaGallery = $product->getMediaGallery();

            if (isset($mediaGallery['images'])) {
                foreach ($mediaGallery['images'] as $image) {
                    if (isset($vm[$image['value_id']])) {
                        //Update Data into table
                        $sql = "Update " . $tableName . " Set vm = " . $vm[$image['value_id']] . " where value_id = " . $image['value_id'];
                        $connection->query($sql);
                    }
                }
            }
        }
    }

}
6
  • Which event you observe? I will try to reproduce it and to check why it's not working. Jun 14, 2017 at 5:52
  • catalog_product_save_after,if image is new value id will be null,so first time not working. Jun 14, 2017 at 5:55
  • And which event you are using for the ChangeTemplateObserver? Jun 14, 2017 at 6:24
  • <preference for="Magento\ProductVideo\Observer\ChangeTemplateObserver" type="Dcw\Vm\Observer\ChangeTemplateObserver" /> Jun 14, 2017 at 6:32
  • Does my answer helped you? Jun 18, 2017 at 20:23

2 Answers 2

12
+200

In your observer there is a lot of unnecessary code. You can change it like:

<?php

namespace Dcw\Vm\Observer;

use Magento\Framework\Event\ObserverInterface;

class ProductSaveAfter implements ObserverInterface {

    protected $request;
    protected $resource;

    /**
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @param \Magento\Framework\App\ResourceConnection $resource\
     */
    public function __construct(
        \Magento\Framework\App\RequestInterface $request, \Magento\Framework\App\ResourceConnection $resource
    ) {
        $this->request = $request;
        $this->resource = $resource;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $data = $this->request->getPostValue();

        if (isset($data['product']['media_gallery']['images'])) {
            // print_r($images);exit;
            $connection = $this->resource->getConnection();
            $tableName = 'catalog_product_entity_media_gallery'; //gives table name with prefix
            $product = $observer->getProduct();
            $mediaGallery = $product->getMediaGallery();

            if (isset($mediaGallery['images'])) {
                foreach ($mediaGallery['images'] as $image) {
                        //Update Data into table
                    $vmValue = !empty($image['vm']) ? (int)$image['vm'] : 0;
                        $sql = "UPDATE " . $tableName . " SET vm = " . $vmValue . " WHERE value_id = " . $image['value_id'];
                        $connection->query($sql);
                }
            }
        }
    }

}

Because you don't need to store data from a request, as it has no value_id in newly created images, therefore your data didn't remain when adding the new image.

To get data in other places I wrote a plugin. It's adding the column vm to media gallery select:

app/code/Dcw/Vm/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\Model\ResourceModel\Product\Gallery">
        <plugin name="afterCreateBatchBaseSelect" type="Dcw\Vm\Plugin\Product\Gallery" sortOrder="10" disabled="false"/>
    </type>
</config>

Code:

<?php

namespace Dcw\Vm\Plugin\Product;

class Gallery
{
    public function afterCreateBatchBaseSelect(
        \Magento\Catalog\Model\ResourceModel\Product\Gallery $subject,
        \Magento\Framework\DB\Select $select
    ) {
        $select->columns('vm');

        return $select;
    }
}

So now your custom attribute vm should always exists in the products media data.

To hide the vm-images on the frontend you can write plugin:

app/code/Dcw/Vm/etc/frontend/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\Model\Product">
        <plugin name="afterGetMediaGalleryImages" type="Dcw\Vm\Plugin\Product" sortOrder="10" disabled="false"/>
    </type>
</config>

Code:

<?php

namespace Dcw\Vm\Plugin;

class Product
{
    /**
     * @param \Magento\Catalog\Model\Product $subject
     * @param \Magento\Framework\Data\Collection $result
     * @return mixed
     */
    public function afterGetMediaGalleryImages(\Magento\Catalog\Model\Product $subject, $result)
    {
        foreach ($result as $key => $image) {
            if ($image['vm']) {
                $result->removeItemByKey($key);
            }
        }

        return $result;
    }
}

To obtain the vm-images from the product, use code writen by @Marius (without a plugin that deletes this images):

$images = []; 
foreach ($product->getMediaGalleryImages() as $image) {
    if ($image->getVm()) {
        $images[] = $image;
    }
}
4
  • @SivaKumarKoduru I'm glad to help you Jun 14, 2017 at 11:05
  • Hello, @Siarhey Uchukhlebau I have to Implement your code at backend side.but when I upload multiple images then I got only one image data with VM, Like this actually I need all images selected value into post data. Aug 10, 2019 at 17:21
  • @SiarheyUchukhlebau Thanks for this i think i'm nearly there: attributes save for me however the values are not showing in product edit form? Wondering if you have time you could see what I did wrong? The question mentions data.useforvm to pull values however that doesn't seem referenced anywhere, is there a step i'm missing? magento.stackexchange.com/questions/301685/…
    – harri
    Jan 20, 2020 at 14:37
  • I saved the new field to a column in catalog_product_entity_media_gallery_value table. $product->getColumn() is not working. Do you know how can I make that work?
    – mysterious
    Jun 22, 2021 at 18:49
4

Retrieving in frontend:

Let's say that the product for which you want to display the virtual mirror is $product.
You can get the images that are marked with your custom attribute like this:

$images = []; 
foreach ($product->getMediaGalleryImages() as $image) {
    if ($image->getVm()) {
        $images[] = $image;
    }
}

Then you can loop through the $images array and display them where you need.

To save the value of that checkbox in the backend I think you need to write an after plugin for the method \Magento\Catalog\Model\Product\Attribute\Backend\Media\ImageEntryConverter::convertFrom where you attach the value you get from post in the $entryArray.

4
  • in $image there is no property with vm, but in db that field existed.so its returning empty array. Jun 13, 2017 at 9:15
  • Ok. I'll dig further.
    – Marius
    Jun 13, 2017 at 9:15
  • any help on this,really its something difficult managing js in magento2. Jun 13, 2017 at 12:33
  • Sorry I didn't find anything useful. I will try to see if I can get something after work.
    – Marius
    Jun 13, 2017 at 13:07

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.