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?

1
  • Did you try changing module="Magento_Catalog" to module="Esites_SEO" ? Commented Mar 24, 2016 at 10:57

4 Answers 4

9

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

3
  • 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
    Commented Jul 5, 2017 at 10:11
  • That's the right solution. Thanks heaps for that Yaroslav.
    – medina
    Commented Dec 4, 2017 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. Commented Nov 20, 2018 at 22:37
2

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.

1
  • Beware, that solution works only if you have $realPath as argument in SchemaLocator. Depends on Magento 2 version. Commented Jun 7, 2019 at 13:36
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.

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

6
  • thx 7ochem, It's my first real post.
    – JROCA22
    Commented Feb 18, 2017 at 11:32
  • This solution does not work as Magento is actively validating the XSD
    – barbazul
    Commented May 23, 2017 at 18:51
  • @barbazul that's only if you're in developer mode if I recall correctly..
    – Erfan
    Commented Jul 6, 2017 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
    Commented Jul 6, 2017 at 15:17
  • Maybe it's not the best practice but it worked for me
    – JROCA22
    Commented Jan 20, 2018 at 15:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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