22

The goal of a module I'm currently developing is to add a custom image type called "opengraph_image". I added a new EAV attribute though my InstallData.php script which works fine. When I now login into the Magento2 backend and alter a product I can choose the image type "opengraph_image" while uploading or editing product images.

However, on the frontend I would like to display this image. Therefore I created a etc/view.xml file in my module with the following content:

<?xml version="1.0"?>
<view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Esites_SEO:etc/custom.xsd">
    <media>
        <images module="Magento_Catalog">
            <image id="opengraph_image" type="opengraph_image">
                <width>265</width>
                <height>265</height>
            </image>
        </images>
    </media>
</view>

But now I get the following error:

Invalid XML in file /var/www/html/vhosts/magento2/app/code/Esites/SEO/etc/view.xml:
Element 'image', attribute 'type': [facet 'enumeration'] The value 'opengraph_image' is not an element of the set {'thumbnail', 'small_image', 'image', 'swatch_image', 'swatch_thumb'}.
Line: 5

Element 'image', attribute 'type': 'opengraph_image' is not a valid value of the local atomic type.
Line: 5

The reason is it doesn't seem to load my custom.xsd located in: app/code/Esites/SEO/etc/custom.xsd where I define the opengraph_image. Instead it seems to just load it's default XSD file: vendor/magento/framework/Config/etc/view.xsd

The content of my custom.xsd is a copy (for testing purposes) of this original view.xsd where I added the following on line 75:

 <xs:enumeration value="opengraph_image"/>

The frontend does work without errors if I include the line above in the original view.xsd file. I followed the documentation on: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/build/XSD-XML-validation.html and my paths are build according to the information on that page. Cache is cleared multiple times.

What am I missing?

8

Magento2 loads default view.xsd because ConfigView Reader using lib/internal/Magento/Framework/Config/SchemaLocator.php and it returns default view.xsd

$this->schema = $urnResolver
    ->getRealPath('urn:magento:framework:Config/etc/view.xsd');`

I was able to override it by follow steps below:

  • Create new extension for example Magento_SampleMinimal
  • Create the plugin definition in {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\Framework\Config\SchemaLocator">
            <plugin name="SampleMinimal_SchemaLocator" type="Magento\SampleMinimal\Model\Plugin\SchemaLocator" sortOrder="1"/>
        </type>
    </config>
    
  • Create plugin in {MODULE}/Model/Plugin/SchemaLocator.php

    <?php
    namespace Magento\SampleMinimal\Model\Plugin;
    
    use Magento\TestFramework\ObjectManager;
    
    class SchemaLocator
    {
        /**
         * After Get Schema
         *
         * @param \Magento\Framework\Config\SchemaLocator $schemaLocator
         * @param string $result
         * @return array
         */
        public function afterGetSchema(\Magento\Framework\Config\SchemaLocator $schemaLocator, $result)
        {
            $result = sprintf(realpath(__DIR__ . '/../../etc/view.xsd'));
            return $result;
        }
    }
    

    Update For Magento 2.0. version

  • Copy lib/internal/Magento/Framework/Config/etc/view.xsd to {MODULE}/etc/view.xsd

For Magento 2.1. version, Copy Vendor/Magento/Framework/Config/etc/view.xsd to {MODULE}/etc/view.xsd * Edit {MODULE}/etc/view.xsd and add new type of media_attribute

  • Are you serious.. Is this the only way? Seems overkill, and probably ridiculous that you can't add your own image without overwriting core XSD – Erfan Jul 5 '17 at 10:11
  • That's the right solution. Thanks heaps for that Yaroslav. – medina Dec 4 '17 at 22:51
  • This is great thank you! However, I would recommend writing the Plugin around Magento\Framework\Config\Dom\UrnResolver as there are places that use it directly instead of going through SchemaLocator. – quickshiftin Nov 20 '18 at 22:37
0

This seems to be a design flaw, in combination with a Magento 2 bug. I've created a bug report here: https://github.com/magento/magento2/issues/10161

If you're using the image builder directly in a template to output the opengraph_image, a better solution is to pass in custom attributes (using Magento\Catalog\Block\Product\ImageBuilder::setAttributes, or the third parameter of Magento\Catalog\Block\Product\View::getImage).

However, that won't work (given my bugreport), so you'll still have to override the ImageBuilder's create method to pass in those attributes to the Catalog Image Helper.

0

There is a simpler way than Yaroslav's answer. It is possible to change the constructor parameters to SchemaLocator in your module's di.xml. Like:

<type name="Magento\Framework\Config\SchemaLocator" >
    <arguments>
        <argument name="realPath" xsi:type="string">urn:magento:module:VendorName_ModuleName:etc/view.xsd</argument>
    </arguments>
</type>

No need for a Plugin.

  • Beware, that solution works only if you have $realPath as argument in SchemaLocator. Depends on Magento 2 version. – Pol Ravalitera Jun 7 at 13:36
-1

You don't need to modify or override view.xsd, this file is just for validation.
I've recently implemented a my solution by doing the following: Create an image catalog attribute (let's say that the new attribute ID 162). Once you created the attribute you'll be able to apply it on any catalog image. Now you must apply to it the right model and front end visibility. You can do it programmatically or following this guide.

  1. Open your database with phpMyAdmin or MySQL and try to mirror any system attribute like small_image

    use magento2_database_name;
    SELECT * FROM  `eav_attribute`;
    UPDATE `magento2_database_name`.`eav_attribute` SET `frontend_model` = 'Magento\\Catalog\\Model\\Product\\Attribute\\Frontend\\Image' WHERE  `eav_attribute`.`attribute_id` =162;
    SELECT * FROM  `catalog_eav_attribute`;
    UPDATE `magento2_database_name`.`catalog_eav_attribute` SET `is_visible` = '1', 'using_in_product_listing' = '1' WHERE `catalog_eav_attribute`.`attribute_id` =162;
    
  2. Go to www_root/magento2_root/app/design/frontend/Theme/package/etc/view.xml and add your new image type:

        <image id="opengraph_image" type="opengraph_image">
            <width>265</width>
            <height>265</height>
        </image>
    
  3. Update template files by adding the new image type on www_root/magento2_root/app/design/frontend/Theme/package/Magento_Catalog/templates/product/
  4. Clean your cache and you'll see it on front end.

It worked for me for a hover image on category product listing, hope this help.

  • thx 7ochem, It's my first real post. – JROCA22 Feb 18 '17 at 11:32
  • This solution does not work as Magento is actively validating the XSD – barbazul May 23 '17 at 18:51
  • @barbazul that's only if you're in developer mode if I recall correctly.. – Erfan Jul 6 '17 at 5:37
  • @Erfan It could be. I haven't checked, honestly. But still, it is a sign that it's not how you are supposed to do it or that there is something wrong in that particular XSD – barbazul Jul 6 '17 at 15:17
  • Maybe it's not the best practice but it worked for me – JROCA22 Jan 20 '18 at 15:00

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.