Изображения в виджетах Magento - PullRequest
7 голосов
/ 22 февраля 2011

Я занимаюсь разработкой сайта для модного клиента в Magento Community версии 1.4.2, и в рамках этого проекта мне нужно иметь несколько настраиваемых блоков продвижения домашней страницы для отображения определенных продуктов или категорий продуктов. Для этого я подумал, что напишу свой собственный виджет, и добился довольно хороших результатов в этом, за исключением того, как работать с изображениями. Мне нужно включить изображение в рамках продвижения. В моем файле определения виджета я включил следующий параметр

        <image>
            <label>Image</label>
            <description>Promotion image</description>
            <visible>1</visible>
            <type>image</type>
        </image>

Поначалу казалось, что это работает нормально, и при создании / редактировании виджета в админ-панели администратора поле загрузки файла включается в параметры виджета, однако при сохранении формы изображение не загружается или его детали сохраняются. в базе данных. У кого-нибудь еще есть опыт использования изображений в виджетах и ​​что я могу делать не так?

Ответы [ 6 ]

25 голосов
/ 28 марта 2012

Существует несколько причин, по которым изображение не сохраняется / не загружается:

  • Форма enctype должна быть "multipart/form-data" для загрузки файла на работу
  • Даже если вы измените форму enctype на "multipart/form-data", вы заметите, что если вы отслеживаете запросы на получение POST'а как "application/x-www-form-urlencoded", то это потому, что это выполняется через ajax и ajax отдельно. невозможно обработать загрузку файла, вам нужно обрабатывать их отдельно.

Я успешно реализовал кнопку «Вставить изображение», которая инициализирует диалоговое окно Media Library, где вы можете просматривать изображения и / или загружать изображения на сервер.

Как только пользователь нажимает «Вставить файл», он вставляет полный URL-адрес изображения в текстовое поле в виджете, чтобы он передавался в шаблон как обычное поле.

Вот как я этого добился:

В вашем widget.xml укажите новый узел:

<image translate="label">
    <label>Image</label>
    <visible>1</visible>
    <required>1</required>
    <type>label</type>
    <helper_block>
        <type>widgets/cms_wysiwyg_images_chooser</type>
        <data>
            <button translate="open">
                <open>Insert Image...</open>
            </button>
        </data>
    </helper_block>
</image>

Вспомогательный тип блока <type>widgets/cms_wysiwyg_images_chooser</type> является пользовательским классом, поэтому вы можете изменить его на любой, если хотите правильно создать класс / файлы.

<?php
class Stackoverflow_Widgets_Block_Cms_Wysiwyg_Images_Chooser extends Mage_Adminhtml_Block_Template
{
public function prepareElementHtml(Varien_Data_Form_Element_Abstract $element)
{
    $config = $this->getConfig();
    $chooseButton = $this->getLayout()->createBlock('adminhtml/widget_button')
        ->setType('button')
        ->setClass('scalable btn-chooser')
        ->setLabel($config['button']['open'])
        ->setOnclick('MediabrowserUtility.openDialog(\''.$this->getUrl('*/cms_wysiwyg_images/index', array('target_element_id' => $element->getName())).'\')')
        ->setDisabled($element->getReadonly());
    $text = new Varien_Data_Form_Element_Text();
    $text->setForm($element->getForm())
        ->setId($element->getName())
        ->setName($element->getName())
        ->setClass('widget-option input-text');
    if ($element->getRequired()) {
        $text->addClass('required-entry');
    }
    if ($element->getValue()) {
        $text->setValue($element->getValue());
    }
    $element->setData('after_element_html', $text->getElementHtml().$chooseButton->toHtml());
    return $element;
}
}
?>

И это все! Теперь у вас должно появиться новое поле в настройках вашего виджета под названием «Изображение» с текстовым полем и кнопкой, в которую вы можете вставить URL-адрес изображения на вашем сервере и отобразить его из вашего шаблона.

Краткое объяснение того, как это работает:

Создается кнопка, которая имеет функцию onclick, которая вызывает диалог Media Library, вызывая MediabrowserUtility.openDialog(), которому передается параметр target_element_id, который сообщает библиотеке мультимедиа, в какой элемент установить значение, когда пользователь щелкает «Insert File», поэтому мы просто передаем id нашего текстового поля в виджете, чтобы оно получило URL изображения, выбранного пользователем.

Надеюсь, это кому-нибудь поможет, так как я не смог найти там никаких ресурсов, объясняющих, как это сделать, поэтому я потратил довольно много времени, копаясь в Magento, чтобы решить все это:)

В будущем я хотел бы сделать так, чтобы оно отображало изображение после его выбора в виджете и сохраняло URL в скрытом поле, но привязка onchange не срабатывает, когда значение устанавливается на элемент из js/mage/adminhtml/browser.js в функции insert, поэтому без изменения основных файлов сделать это намного сложнее. Я думал о том, чтобы поиграться, когда форма снова сфокусируется после закрытия Media Library или таймера (довольно хитро, но сработает), но у меня есть другие вещи, к которым можно перейти, и я могу вернуться к нему позже!

UPDATE:

URL, которые генерирует Media Library, выглядят так:

http://www.yourwebsite.com/index.php/admin/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvd2lkZ2V0cy9iYW5uZXIvaG9tZXBhZ2UvZm9yZWdyb3VuZC9maXNoLXRhbmsucG5nIn19/key/e8167e3884e40b97d8985e7b84e7cbc7875f134e5f7e5946c9c2a482d0279762/

Кэшированное изображение, которое работает только в том случае, если пользователь является администратором. Глупый? Да. Если вы вставляете то же изображение на страницу CMS, когда HTML-файл генерируется для вывода, он преобразует его в исходный URL-адрес на сервере, доступном через /media/wysiwyg/path/to/file/photo.jpg. Нам нужно показать исходный URL-адрес пользователю, поэтому мы можем подключиться к функции, которая генерирует HTML-виджет (когда вы нажимаете «Вставить виджет»), и найдите /admin/cms_wysiwyg/directive/___directive/ и замените его исходным URL-адресом на изображение, как на странице CMS.

В вашем config.xml для ваших пользовательских виджетов:

<global>
    <models>
        <widget>
            <rewrite>
                <widget>Stackoverflow_Widgets_Model_Widget</widget>
            </rewrite>
        </widget>
    </models>
</global>

Затем создайте модель виджета code\local\Stackoverflow\Widgets\Model\Widget.php:

<?php
class Stackoverflow_Widgets_Model_Widget extends Mage_Widget_Model_Widget
{
    public function getWidgetDeclaration($type, $params = array(), $asIs = true)
    {
        foreach($params as $k => $v){
            if(strpos($v,'/admin/cms_wysiwyg/directive/___directive/') !== false){
                $parts = explode('/',parse_url($v, PHP_URL_PATH));
                $key = array_search('___directive', $parts);
                if($key !== false){
                    $directive = $parts[$key+1];
                    $src = Mage::getModel('core/email_template_filter')->filter(Mage::helper('core')->urlDecode($directive));
                    if(!empty($src)){
                        $params[$k] = parse_url($src, PHP_URL_PATH);
                    }
                }
            }
        }
        return parent::getWidgetDeclaration($type, $params, $asIs);
    }
}

, которая переопределяет функцию getWidgetDeclaration, которая вызывается каждый раз, когда вывод виджета создается для textarea / wysiwyg и просматривает все параметры, и если он находит изображение, связанное с кешем администратора, он обнаруживает Исходное изображение и перезаписать переменную в массиве и вызвать исходную функцию с параметрами.

Если кэшированное изображение не найдено, функция будет работать в обычном режиме.

ОБНОВЛЕНИЕ: 13.09.2012

Как отметил Джонатан Дэй, вы должны перезаписать Mage_Widget_Model_Widget_Instance также, если вы хотите, чтобы он работал в экземпляре виджета.

До сих пор у меня не было необходимости добавлять изображение в виджет через инстанс виджета, и я не мог понять, почему моя функция не работает, пока я не исследовал и не понял, что экземпляры "всплывающих" виджетов используют Mage_Widget_Model_Widget и экземпляры виджета, используемые на вкладке параметров виджета (без всплывающего окна), Mage_Widget_Model_Widget_Instance и не расширяют Mage_Widget_Model_Widget, поэтому не наследуют функциональность.

Чтобы добавить функциональность к Mage_Widget_Model_Widget_Instance, просто добавьте строку <widget_instance>Petbarn_Widgets_Model_Widget_Instance</widget_instance> к вашему config.xml, чтобы она выглядела так:

<global>
    <models>
        <widget>
            <rewrite>
                <widget>Stackoverflow_Widgets_Model_Widget</widget>
                <widget_instance>Stackoverflow_Widgets_Model_Widget_Instance</widget_instance>
            </rewrite>
        </widget>
    </models>
</global>

Затем создайте экземпляр модели code\local\Stackoverflow\Widgets\Model\Widget\Instance.php:

<?php
class Petbarn_Widgets_Model_Widget_Instance extends Mage_Widget_Model_Widget_Instance
{
    protected function _beforeSave()
    {
        if (is_array($this->getData('widget_parameters'))) {
            $params = $this->getData('widget_parameters');
            foreach($params as $k => $v){
                if(strpos($v,'/cms_wysiwyg/directive/___directive/') !== false){
                    $parts = explode('/',parse_url($v, PHP_URL_PATH));
                    $key = array_search('___directive', $parts);
                    if($key !== false){
                        $directive = $parts[$key+1];
                        $src = Mage::getModel('core/email_template_filter')->filter(Mage::helper('core')->urlDecode($directive));
                        if(!empty($src)){
                            $params[$k] = parse_url($src, PHP_URL_PATH);
                        }
                    }
                }
            }
            $this->setData('widget_parameters', $params);
        }
        return parent::_beforeSave();
    }
}

На этот раз мы модифицируем данные widget_parameters в начале функции _beforeSave(), чтобы она исправляла URL-адрес до его сохранения.

Вы также должны убедиться, что javascript-файл /js/mage/adminhtml/browser.js включен (в моем случае его не было), чтобы получить функциональность MediabrowserUtility.

Чтобы убедиться, что он включен, самый простой способ - включить его для всех администраторов (не тратя много времени на его настройку).

Создайте local.xml для макетов adminhtml (если у вас его еще нет): app\design\adminhtml\default\default\layout\local.xml

<?xml version="1.0"?>
<layout version="0.1.0">
    <default>
        <reference name="head">
            <action method="addJs"><script>mage/adminhtml/browser.js</script></action>
        </reference>
    </default>
</layout>

Это заставит Magento включать js/mage/adminhtml/browser.js на каждой странице администратора, поэтому MediabrowserUtility всегда будет доступен.

ПРИМЕЧАНИЕ: я использую Magento Enterprise 1.11.2.0, поэтому я не уверен, как он ведет себя в других версиях.

9 голосов
/ 16 сентября 2012

Я решил этот вариант использования, создав собственный тип поля для виджетов:

<image>
    <label>Image</label>
    <description>Promotion image</description>
    <visible>1</visible>
    <type>widgetimagechooser/chooser</type>
</image>

Я реализовал блок Aijko_WidgetImageChooser_Block_Chooser, который запускает стандартный элемент выбора изображений Magento.

Чтобы решить проблему с неясным URL-адресом файла изображения, я реализовал пользовательский контроллер Aijko_WidgetImageChooser_Adminhtml_Cms_Wysiwyg_Images_ChooserController, который обрабатывает возвращаемое значение из стандартного средства выбора изображений Magento.

Значение добавляется в текстовое поле в виджете. Этот относительный URL к изображению затем может использоваться для показа изображения во внешнем интерфейсе.

Не стесняйтесь попробовать расширение, доступное на Github или установить напрямую, используя Magento Connect .

2 голосов
/ 13 июля 2012

Спасибо за ответ!Я нашел лучший способ решить проблему с кэшированными URL-адресами изображений.Мне даже пришлось это сделать, потому что ваше решение перезаписи модели виджетов не работало с Magento 1.7.0.2.

Итак, я добавил добавление нового параметра GET use_file_url в URL, используемый дляБлок выбора:

$url    = $this->getUrl(
    '*/cms_wysiwyg_images/index',
    array(
        'target_element_id' => $element->getName(),
        'use_file_url' => 1
    )
);

Передает параметр GET в медиабраузер.Следующим шагом является передача этого параметра в onInsertAction из Mage_Adminhtml_Cms_Wysiwyg_ImagesController.Для этого необходимо переопределить функцию getOnInsertUrl() блока Mage_Adminhtml_Block_Cms_Wysiwyg_Images_Content:

public function getOnInsertUrl()
{
    $useFileUrl = (int)$this->getRequest()->getParam('use_file_url', 0);
    return $this->getUrl('*/*/onInsert', array('use_file_url' => $useFileUrl));
}

Затем необходимо обработать новый параметр в контроллере Mage_Adminhtml_Cms_Wysiwyg_ImagesController:

public function onInsertAction()
{
    $useFileUrl = (int)$this->getRequest()->getParam('use_file_url', 0) == 1 ? true : false;
    $helper     = Mage::helper('cms/wysiwyg_images');
    $storeId    = $this->getRequest()->getParam('store');
    $filename   = $this->getRequest()->getParam('filename');
    $filename   = $helper->idDecode($filename);
    $asIs       = $this->getRequest()->getParam('as_is');

    Mage::helper('catalog')->setStoreId($storeId);
    $helper->setStoreId($storeId);

    if ($useFileUrl == false) {
        $image = $helper->getImageHtmlDeclaration($filename, $asIs);
    } else {
        $image = $helper->getImageMediaUrl($filename);
    }

    $this->getResponse()->setBody($image);
}

Последний шаг - переопределить помощник Mage_Cms_Helper_Wysiwyg_Images и добавить функцию getImageMediaUrl():

public function getImageMediaUrl($filename)
{
    return $this->getCurrentUrl() . $filename;
}

Я думаю, что это довольно симпатичный подход, даже если вам придется переопределить 4 класса.Но передача параметра GET представляется более безопасной в будущем, чем анализ кэшированного URL.

1 голос
/ 15 ноября 2014

Пользовательские атрибуты изображения Magento обычно не отображаются на вкладке расширения, и вам придется перейти в Каталог> Продукт> Изображения, чтобы назначить этот атрибут. Но с помощью некоторого пользовательского кода вы можете достичь этого.

0 голосов
/ 28 июля 2015

Начиная с версии Magento 1.9.2.0, вам также необходимо добавить следующее в файл макета adminhtml:

lib/flex.js
lib/FABridge.js
mage/adminhtml/flexuploader.js
0 голосов
/ 24 февраля 2011

Нет файлов для загрузки виджетов.Чтобы решить эту проблему, вы можете использовать magento media browser и выбрать изображение как для wysiwyg editor, но есть другая проблема, media browser не возвращает чистый URL изображения.

...