Magento小部件中的图像 [英] Images in Magento widgets

查看:53
本文介绍了Magento小部件中的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为Magento社区1.4.2版中的时尚客户开发一个网站,并且作为该项目的一部分,我需要具有一些自定义的首页促销模块,以展示特定产品或产品类别.为此,我认为我将编写自己的小部件,并且在如何处理图像方面取得了相当不错的进展.我需要在推广中添加一张图片.在我的小部件定义文件中,我包含了以下参数

I am developing a site for a fashion client in Magento Community version 1.4.2 and as part of this project I need to have some customized home page promotion blocks to feature specific products or categories of products. For this I thought I would write my own widget and have made pretty good progress in this with the exception of how to deal with images. I need to include an image as part of the promotion. In my widget definition file I included the following parameter

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

乍一看似乎可以正常工作,并且在admin后端中创建/编辑窗口小部件时,窗口小部件选项中包含文件上载字段,但是在保存表单时,图像似乎未上载,或者图像的详细信息已保留在数据库中.其他人是否有在小部件中使用图像的经验,我可能做错了什么?

This seemed at first to work fine and when creating/editing a widget in the admin back end a file upload field is included in the widget options however on saving the form the image does not appear to be uploaded, or its details retained in the database. Does anyone else have experience of using images in widgets and what I may be doing wrong?

推荐答案

它不保存/上传图像的原因有两个:

There are a couple reason why it doesn't save/upload the image:

  • enctype的格式必须为"multipart/form-data",才能使文件上传正常工作
  • 即使将格式enctype更改为"multipart/form-data",您也会注意到,如果监视请求以POST形式发送为"application/x-www-form-urlencoded"的请求,这是因为它是通过ajax和ajax本身完成的无法处理文件上传,您需要分别处理.
  • The form enctype needs to be "multipart/form-data" for a file upload to work
  • Even if you change the form enctype to "multipart/form-data" you will notice if you monitor the requests that it gets POST'ed as "application/x-www-form-urlencoded" this is because it is done through ajax and ajax by itself can't process a file upload, you need to process them separately.

我已经成功实现了一个插入图像"按钮,该按钮初始化了Media Library对话框,您可以在其中浏览服务器中的图像和/或上传图像.

I have successfully implemented a "Insert Image" button which initialises the Media Library dialogue where you can browse your server for images and/or upload images.

一旦用户单击插入文件",它将把完整的图像URL插入到小部件中的文本框中,以便像普通字段一样传递到模板中.

Once the user clicks "Insert File" it inserts the full image url into a textbox in the widget so it's passed along like a normal field to your template.

这是我实现的方式:

在您的widget.xml中指定一个新节点:

In your widget.xml specify a new node:

<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>是自定义类,因此只要正确创建类/文件,您就可以将其更改为所需的任何内容.

The helper block type <type>widgets/cms_wysiwyg_images_chooser</type> is a custom class, so you can change it to anything you want as long as you create the class/files correctly.

<?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插入服务器上的图像并从模板中显示它.

And that is it! You should now have a new field in your widget options called "Image" with a textbox and a button in which you can insert the url to an image on your server and display it from your template.

其工作原理的简短说明:

A quick explanation of how it works:

创建一个具有onclick功能的按钮,该功能通过调用MediabrowserUtility.openDialog()来调用Media Library对话框,该参数还随同一起传递了参数target_element_id,该参数告诉媒体库用户单击后将在哪个元素中设置值"Insert File",因此我们只需在小部件中传递文本框的id即可接收用户选择的图像的网址.

A button is created that has an onclick function that calls the Media Library dialogue by calling MediabrowserUtility.openDialog() which along is passed the parameter target_element_id which tells media library what element to set the value in once they user clicks "Insert File" so we simply pass along the id of our textbox in the widget for it to receive the url of the image that the user selected.

希望这对某人有帮助,因为我在那里找不到任何资源来解释如何做到这一点,所以我花了相当长的时间浏览Magento来解决所有问题:)

Hope this helps someone as I couldn't find any resources out there that explained how to do it so I spent quite a while digging through Magento to work it all out :)

我将来想要做的是拥有它,以便在您在小部件中选择它后显示该图像,并将该URL存储在一个隐藏字段中,但是当绑定不被触发时,在insert函数的js/mage/adminhtml/browser.js中将值设置为js/mage/adminhtml/browser.js的元素,因此不更改核心文件就很难做.我曾考虑过要在Media Library关闭或计时器之后再次获得焦点时进行操作(虽然很容易躲闪,但是可以使用),但是我还有其他事情要做,以后可能会再回来!

What I would like to do in the future is have it so it displays the image after you select it in the widget, and it stores the url in a hidden field, but having an onchange bind is not fired when the value is set to the element from js/mage/adminhtml/browser.js in the insert function, so without changing the core files it is a lot harder to do. I thought about playing around with when the form gets focus again after the Media Library closes or a timer (pretty dodgey but would work), but I have other things to move on to and may come back to it later!

更新:

Media Library生成的URL如下:

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

这是一个缓存的图像,仅当用户是管理员时才起作用.愚蠢的?是的.如果在生成html输出时将同一图像插入CMS页面,则会将其转换为可通过/media/wysiwyg/path/to/file/photo.jpg访问的服务器上的原始URL.我们需要将原始网址显示给用户,因此我们可以做的就是挂接到生成窗口小部件html的函数中(当您单击插入窗口小部件"时),然后查找/admin/cms_wysiwyg/directive/___directive/并将其替换为原始URL.图片,就像CMS页面一样.

Which are a cached image, and only work if the user is an admin. Stupid? Yes. If you insert the same image in to a CMS page when the html is generated for output it converts it to the original url on the server accessible via /media/wysiwyg/path/to/file/photo.jpg. We need the original url to show to the user, so what we can do is hook into the function that generates the widget html (when you click "Insert Widget") and look for /admin/cms_wysiwyg/directive/___directive/ and replace it with the original URL to the image as the CMS page does.

config.xml中用于自定义窗口小部件:

In your config.xml for your custom widgets:

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

然后创建模型Widget code\local\Stackoverflow\Widgets\Model\Widget.php:

Then create the model Widget 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生成窗口小部件输出时调用,并浏览所有参数,如果找到链接到管理缓存的图像,它将查找原始图像并覆盖数组中的变量,然后使用参数调用原始函数.

Which overrides the getWidgetDeclaration function which is called every time a the widget output is produced for a textarea/wysiwyg and looks through all the parameters and if it finds an image that is linked to the admin cache it will find out the original image and overwrite the variable in the array and call the original function with the parameters.

如果找不到缓存的图像,该功能将正常运行.

If the cached image is not found the function will work as normal.

更新:2012年9月13日

正如乔纳森·戴(Jonathan Day)指出的那样,如果您希望Mage_Widget_Model_Widget_Instance在窗口小部件实例中运行,也必须覆盖它.

As Jonathan Day pointed out you have to overwrite Mage_Widget_Model_Widget_Instance also if you want it to work in a Widget Instance.

直到现在,我还不需要通过Widget实例将图像添加到Widget,并且一直困惑为什么我的功能无法正常工作,直到我调查并意识到弹出"窗口小部件实例使用Mage_Widget_Model_Widget并在窗口小部件选项"选项卡上使用的窗口小部件实例(无弹出窗口)为Mage_Widget_Model_Widget_Instance并且不扩展Mage_Widget_Model_Widget,因此请勿继承该功能.

I haven't had the need to add an image to a widget through a Widget Instance until now and was confused why my function didn't work, until I investigated and realised the "popup" widget instances use Mage_Widget_Model_Widget and the widget instances that are used on a Widget options tab (no popup) are Mage_Widget_Model_Widget_Instance and do not extend Mage_Widget_Model_Widget so do not inherit the functionality.

要将功能添加到Mage_Widget_Model_Widget_Instance中,只需将<widget_instance>Petbarn_Widgets_Model_Widget_Instance</widget_instance>行添加到config.xml中,使其看起来像:

To add the functionality to Mage_Widget_Model_Widget_Instance simply add the line <widget_instance>Petbarn_Widgets_Model_Widget_Instance</widget_instance> to your config.xml so it will look like:

<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();
    }
}

这一次,我们在_beforeSave()函数的开头修改了widget_parameters数据,因此它在保存URL之前先对其进行修复.

This time we are modifying the widget_parameters data at the start of the _beforeSave() function so it fixes up the url before it saves it.

您还必须确保包含/js/mage/adminhtml/browser.js javascript文件(在我的情况下不是),以获取MediabrowserUtility功能.

You also have to ensure the /js/mage/adminhtml/browser.js javascript file is included (in my case it wasn't) to get the MediabrowserUtility functionality.

要确保将其包含在内,最简单的方法是为所有管理员添加它(没有花很多时间更好地针对它).

To ensure it is included, the easiest way is to include it for all of admin (didn't spend much time targeting it better).

为adminhtml布局创建local.xml(如果您还没有):app\design\adminhtml\default\default\layout\local.xml

Create a local.xml for adminhtml layouts (if you don't already have one): 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将始终可用.

This will make Magento include js/mage/adminhtml/browser.js on every page of admin so MediabrowserUtility will always be available.

注意:我使用的是Magento Enterprise 1.11.2.0,因此我不确定它在其他版本上的行为.

这篇关于Magento小部件中的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆