Magento小部件中的图像

时间:2011-02-22 11:54:45

标签: magento widget magento-1.4

我正在为Magento社区版本1.4.2中的时尚客户开发一个网站,作为该项目的一部分,我需要有一些自定义主页推广块来展示特定产品或产品类别。为此,我想我会编写自己的小部件,除了如何处理图像外,在这方面取得了很大的进步。我需要将图片作为促销的一部分。在我的小部件定义文件中,我包含以下参数

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

这似乎起初工作正常,当在管理员后端创建/编辑窗口小部件时,窗口小部件选项中包含文件上载字段,但是在保存表单时,图像似乎没有上载,或者其详细信息保留在数据库中。有没有其他人有在小部件中使用图像的经验以及我可能做错了什么?

6 个答案:

答案 0 :(得分:25)

有几个原因导致它无法保存/上传图像:

  • 表单enctype需要为“multipart/form-data”才能上传文件
  • 即使您将表单enctype更改为“multipart/form-data”,您也会注意到,如果您监控它被POST为“application/x-www-form-urlencoded”的请求,这是因为它已完成通过ajax和ajax本身无法处理文件上传,您需要单独处理它们。

我已成功实施“插入图片”按钮,该按钮初始化Media Library对话框,您可以在其中浏览服务器以查找图像和/或上传图像。

用户点击“插入文件”后,会将完整的图片网址插入到窗口小部件的文本框中,以便将其像普通字段一样传递到模板中。

这就是我实现它的方式:

在您的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;
}
}
?>

就是这样!您现在应该在窗口小部件选项中有一个名为“Image”的新字段,其中包含一个文本框和一个按钮,您可以在其中将URL插入服务器上的图像并从模板中显示它。

快速解释其工作原理:

创建一个具有onclick功能的按钮,通过调用Media Library来调用MediabrowserUtility.openDialog()对话,并传递参数target_element_id,该参数告诉媒体库在用户点击“Insert File”后设置该值,以便我们只是传递小部件中文本框的id,以便接收用户选择的图像的网址。

希望这有助于某人,因为我找不到任何解释如何做的资源所以我花了很长时间挖掘Magento来全力以赴:)

我将来要做的是让它在小部件中选择后显示图像,并将url存储在隐藏字段中,但不会触发onchange绑定当值设置为js/mage/adminhtml/browser.js函数中insert的元素时,因此不更改核心文件就更难了。在Media Library关闭或计时器(相当笨拙但可以工作)之后,我想到了表单再次聚焦的时候,但是我还有其他事情可以继续下去,可能会在以后再回来!

<强>更新

Media Library生成的网址如下:

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

哪些是缓存图片,仅在用户是管理员时才有效。笨?是。如果在为输出生成html时将同一图像插入CMS页面,则会将其转换为可通过/media/wysiwyg/path/to/file/photo.jpg访问的服务器上的原始URL。我们需要向用户显示原始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);
    }
}

覆盖每次为textarea / wysiwyg生成窗口小部件输出时调用的getWidgetDeclaration函数,并查看所有参数,如果找到链接到管理缓存的图像,它将查找取出原始图像并覆盖数组中的变量,并使用参数调用原始函数。

如果找不到缓存的图像,该功能将正常工作。

更新日期:13/09/2012

正如Jonathan Day指出的那样,如果你想让它在Widget实例中工作,你也必须覆盖Mage_Widget_Model_Widget_Instance

到目前为止,我还没有必要通过Widget实例向窗口小部件添加图像,并且为什么我的函数不起作用而感到困惑,直到我调查并意识到“弹出窗口”窗口小部件实例使用{{1}在Widget选项选项卡(没有弹出窗口)上使用的窗口小部件实例是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

然后创建模型Instance <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() javascript文件(在我的情况下不是),以获得/js/mage/adminhtml/browser.js功能。

为了确保包含它,最简单的方法是将其包含在所有管理员中(没有花太多时间更好地定位它)。

为adminhtml布局创建MediabrowserUtility(如果您还没有):local.xml

app\design\adminhtml\default\default\layout\local.xml

这将使Magento在管理员的每个页面上都包含<?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> ,因此js/mage/adminhtml/browser.js始终可用。

注意:我正在使用Magento Enterprise 1.11.2.0,所以我不确定它在其他版本上的表现。

答案 1 :(得分:9)

我通过为小部件创建自定义字段类型来解决此用例:

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

我实现了一个触发标准Magento图像选择器元素的块Aijko_WidgetImageChooser_Block_Chooser

为了解决图像文件的非清除URL的问题,我实现了一个自定义控制器Aijko_WidgetImageChooser_Adminhtml_Cms_Wysiwyg_Images_ChooserController,它处理来自Magento标准图像选择器的返回值。

该值将添加到窗口小部件的文本框中。然后,该图像的相对URL可用于在前端显示图像。

您可以尝试Github上提供的扩展程序,也可以使用Magento Connect直接安装。

答案 2 :(得分:2)

谢谢你的回答!我找到了一种更好的方法来解决缓存图像URL的问题。我甚至不得不这样做,因为覆盖Widget模型的解决方案不适用于Magento 1.7.0.2。

所以我所做的是在用于Chooser Block的URL中添加一个新的GET参数use_file_url

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

这会将GET参数传递给媒体浏览器。下一步是将此参数传递给onInsertAction的{​​{1}}。这样做,您必须覆盖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()

我认为这是一个非常漂亮的方法,即使你必须完成4个类。但是,传递GET参数似乎比解析缓存的URL更安全。

答案 3 :(得分:1)

Magento的图片自定义属性通常不会出现在扩展标签中,您必须转到目录&gt;产品&gt;要分配此属性的图像。但是通过一些自定义编码,您可以实现这一目标。

答案 4 :(得分:0)

小部件没有文件上传。要解决这个问题你可以使用magento媒体浏览器并选择图像为wysiwyg编辑器,但还有其他问题,媒体浏览器不会返回清晰的图像URL。

答案 5 :(得分:0)

从Magento 1.9.2.0开始,您还需要将以下内容添加到您的adminhtml布局文件中:

lib/flex.js
lib/FABridge.js
mage/adminhtml/flexuploader.js