Nic*_*tes 7 widget magento magento-1.4
我正在为Magento社区版本1.4.2中的时尚客户开发一个站点,作为该项目的一部分,我需要有一些定制的主页促销块来展示特定产品或产品类别.为此,我想我会编写自己的小部件,除了如何处理图像外,在这方面取得了很大的进步.我需要将图片作为促销的一部分.在我的小部件定义文件中,我包含以下参数
<image>
<label>Image</label>
<description>Promotion image</description>
<visible>1</visible>
<type>image</type>
</image>
Run Code Online (Sandbox Code Playgroud)
这似乎起初工作正常,当在管理员后端创建/编辑窗口小部件时,窗口小部件选项中包含文件上载字段,但是在保存窗体时,图像似乎不会上载,或者其详细信息保留在数据库中.有没有其他人有在小部件中使用图像的经验以及我可能做错了什么?
Kus*_*Kus 25
有几个原因导致它无法保存/上传图像:
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>
Run Code Online (Sandbox Code Playgroud)
辅助块类型<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;
}
}
?>
Run Code Online (Sandbox Code Playgroud)
就是这样!您现在应该在窗口小部件选项中有一个名为"Image"的新字段,其中包含一个文本框和一个按钮,您可以在其中将URL插入服务器上的图像并从模板中显示该图像.
快速解释它的工作原理:
创建一个按钮,其中包含一个onclick函数,Media Library通过调用MediabrowserUtility.openDialog()哪个函数来调用对话框,该参数target_element_id告诉媒体库,一旦用户点击" Insert File",就会在元素中设置值,因此我们只需将id小部件中的文本框传递给它接收用户选择的图像的URL.
希望这有助于某人,因为我找不到任何解释如何做的资源所以我花了很长时间挖掘Magento来全力以赴:)
我将来要做的是让它在小部件中选择它后显示图像,并将url存储在隐藏字段中,但是onchange当值设置为元素时不会触发绑定从js/mage/adminhtml/browser.js在insert功能,所以在不改变核心文件是很多更难做.关于在Media Library关闭或计时器之后表单再次聚焦时(我很笨拙但可以工作),我想过要玩,但是我还有其他的东西要继续前进,可能会在以后再回来!
更新:
Media Library生成的URL 如下所示:
http://www.yourwebsite.com/index.php/admin/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvd2lkZ2V0cy9iYW5uZXIvaG9tZXBhZ2UvZm9yZWdyb3VuZC9maXNoLXRhbmsucG5nIn19/key/e8167e3884e40b97d8985e7b84e7cbc7875f134e5f7e5946c9c2a482d0279762/
哪个是缓存图像,仅在用户是管理员时才有效.笨?是.如果在为输出生成html时将相同的图像插入CMS页面,则会将其转换为可通过服务器访问的服务器上的原始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>
Run Code Online (Sandbox Code Playgroud)
然后创建模型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);
}
}
Run Code Online (Sandbox Code Playgroud)
这会覆盖getWidgetDeclaration每次为textarea/wysiwyg生成窗口小部件输出时调用的函数,并查看所有参数,如果找到链接到管理缓存的图像,它将找出原始图像并覆盖变量在数组中并使用参数调用原始函数.
如果未找到缓存的图像,则该功能将正常工作.
更新:13/09/2012
正如Jonathan Day指出的那样,Mage_Widget_Model_Widget_Instance如果你想让它在Widget实例中工作,你也必须覆盖它.
到目前为止,我还没有必要通过Widget实例向窗口小部件添加图像,并且为什么我的函数无法工作而感到困惑,直到我调查并意识到"弹出窗口"窗口小部件实例的使用Mage_Widget_Model_Widget以及使用的窗口小部件实例在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>
Run Code Online (Sandbox Code Playgroud)
然后创建模型实例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();
}
}
Run Code Online (Sandbox Code Playgroud)
这次我们widget_parameters在_beforeSave()函数开始时修改数据,以便在保存之前修复url.
您还必须确保包含/js/mage/adminhtml/browser.jsjavascript文件(在我的情况下不是)以获取MediabrowserUtility功能.
为了确保包含它,最简单的方法是将其包含在所有管理员中(没有花费太多时间更好地定位它).
创建一个local.xmlfor 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>
Run Code Online (Sandbox Code Playgroud)
这将使Magento包含js/mage/adminhtml/browser.js在每个管理页面上,因此MediabrowserUtility将始终可用.
注意:我正在使用Magento Enterprise 1.11.2.0,所以我不确定它在其他版本上的表现如何.
我通过为小部件创建自定义字段类型来解决了这个用例:
<image>
<label>Image</label>
<description>Promotion image</description>
<visible>1</visible>
<type>widgetimagechooser/chooser</type>
</image>
Run Code Online (Sandbox Code Playgroud)
我实现了一个Aijko_WidgetImageChooser_Block_Chooser触发标准Magento图像选择器元素的块.
为了解决图像文件中非清除URL的问题,我实现了一个自定义控制器Aijko_WidgetImageChooser_Adminhtml_Cms_Wysiwyg_Images_ChooserController,它处理来自Magento标准图像选择器的返回值.
该值将添加到窗口小部件中的文本框中.然后,该图像的相对URL可用于显示前端中的图像.
您可以尝试在Github上使用扩展程序,也可以使用Magento Connect直接安装.