SVG Bilder in Magento Uploader erlauben

Wer die erlaubten Bilddatei-Typen für Produktbilder in Magento ändern will, wird feststellen, dass sie hart kodiert sind in Mage/Catalog/Model/Product/Attribute/Backend/Media.php und Mage/Adminhtml/controllers/Catalog/Product/GalleryController.php

Ich habe allerdings einen Observer gefunden, mit dem sie zusammen mit anderen Uploader-Konfigurationen angepasst werden können. Dieser Beitrag beschreibt, wie eine Extension für diesen Zweck erstellt werden kann, Grundlagen der Magento Extension-Programmierung werden vorausgesetzt.

Konfiguration in config.xml

<config>
    <adminhtml>
        <events>
            <catalog_product_gallery_prepare_layout>
                <observers>
                    <your_module>
                        <class>your_module/observer</class>
                        <method>setFlexUploaderConfig</method>
                        <type>singleton</type>
                    </your_module>
                </observers>
            </catalog_product_gallery_prepare_layout>
        </events>
    </adminhtml>
</config>

Dein Observer

class Your_Module_Model_Observer
{
    /**
     * Adds file types to allowed file types of file selector
     *
     * @see event catalog_product_gallery_prepare_layout
     * @see block Mage_Adminhtml_Block_Catalog_Product_Helper_Form_Gallery_Content
     * @param Varien_Event_Observer $observer
     */
    public function setFlexUploaderConfig(Varien_Event_Observer $observer)
    {
        /* @var $galleryBlock Mage_Adminhtml_Block_Catalog_Product_Helper_Form_Gallery_Content */
        $uploaderConfig = $observer->getBlock()->getUploader()->getConfig();
        $additionalExtensions = array('*.svg');
        $uploaderFileFilters = $uploaderConfig->getFilters();
        $uploaderFileFilters['vector_images'] = array(
                'label' => $this->__('Vector Images') . ' (' . join(', ', $additionalExtensions) . ')',
                'files' => $additionalExtensions
        );
        $uploaderConfig->setFilters($uploaderFileFilters);
    }
}

Anstatt einen neuen Filter hinzuzufügen, kann man hier auch den bestehenden Filter images ändern. Ich habe den Code von einem Modul übernommen, in dem ich Video-Uploads erlaube, da hat ein zusätzlicher Filter Sinn gemacht. Die Filter definieren die Dropdowns im “Datei öffnen” Dialog.

Für die servserseitige Validierung muss zusätzlich die gallery upload action überschrieben werden:

config.xml

<config>
    <admin>
        <routers>
            <adminhtml>
                <args>
                    <modules>
                        <Your_Module before="Mage_Adminhtml">Your_Module_Adminhtml</Your_Module>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>
</config>

Dein Controller:

class Your_Module_Adminhtml_Catalog_Product_GalleryController extends Mage_Adminhtml_Catalog_Product_GalleryController
{
    public static $allowedImageExtensions = array('jpg', 'jpeg', 'gif', 'png');
    public static $allowedVectorExtensions = array('svg');

    /**
     * Overridden to reconfigure the Uploader
     *
     * (non-PHPdoc)
     * @see Mage_Adminhtml_Catalog_Product_GalleryController::uploadAction()
     */
    public function uploadAction()
    {
        try {
            $uploader = new Mage_Core_Model_File_Uploader('image');


            // BEGIN change
            $uploader->setAllowedExtensions($this->_getAllowedExtensions());
            $uploader->addValidateCallback('catalog_product_image', $this, 'validateUploadImage');
            $uploader->addValidateCallback('svg_image', $this, 'validateUploadVector');
            // END change


            $uploader->setAllowRenameFiles(true);
            $uploader->setFilesDispersion(true);
            $result = $uploader->save(
                Mage::getSingleton('catalog/product_media_config')->getBaseTmpMediaPath()
            );

            Mage::dispatchEvent('catalog_product_gallery_upload_image_after', array(
                'result' => $result,
                'action' => $this
            ));

            /**
             * Workaround for prototype 1.7 methods "isJSON", "evalJSON" on Windows OS
             */
            $result['tmp_name'] = str_replace(DS, "/", $result['tmp_name']);
            $result['path'] = str_replace(DS, "/", $result['path']);

            $result['url'] = Mage::getSingleton('catalog/product_media_config')->getTmpMediaUrl($result['file']);
            $result['file'] = $result['file'] . '.tmp';
            $result['cookie'] = array(
                'name'     => session_name(),
                'value'    => $this->_getSession()->getSessionId(),
                'lifetime' => $this->_getSession()->getCookieLifetime(),
                'path'     => $this->_getSession()->getCookiePath(),
                'domain'   => $this->_getSession()->getCookieDomain()
            );

        } catch (Exception $e) {
            $result = array(
                'error' => $e->getMessage(),
                'errorcode' => $e->getCode());
        }

        $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
    }

    protected function _getAllowedExtensions()
    {
        return array_merge(self::$allowedImageExtensions, self::$allowedVectorExtensions);
    }
    public function validateUploadImage($file)
    {
        if (in_array(pathinfo($file, PATHINFO_EXTENSION), self::$allowedImageExtensions)) {
            return Mage::helper('catalog/image')->validateUploadFile($file);
        }
    }
    public function validateUploadVector($file)
    {
        if (in_array(pathinfo($file, PATHINFO_EXTENSION), self::$allowedVectorExtensions)) {
            //TODO throw exception if invalid file
            return;
        }
    }
}

Dieser Controller überschreibt uploadAction des originalen gallery controllers. Es ist notwendig, dass ich hier einen zweiten Validator hinzufüge und den Original-Validator aus Mage_Catalog_Helper_Image nur verwende, wenn das Bild einen der Dateitypen hat, der von der the GD extension unterstützt wird. In der validateUploadVector Methode ist Platz für zusätzliche Validierungen für SVG Dateien, es sollte eine Exception geworfen werden, wenn die Datei keine valide SVG ist.

Template Anpassungen

Zusätzlich müssen die Templates angepasst werden, um SVG Dateien korrekt darzustellen, also nicht die Methoden zur Thumbnail-Generierung zu nutzen, wenn die Datei ein SVG ist. Eine Alternative wäre ein Rewrite von Mage_Catalog_Helper_Image::resize(), um SVG-Dateien auszunehmen.

Frage und Antwort auf Magento StackExchange