创建自定义Widget 并通过添加图片选择器插入图片
自定义widget
-
先在模块的etc 配置文件中创建
widget.xml
配置文件例如:在
HomeCategoryLis
t模块中创建widget
文件位置:\Rokanthemes\HomeCategoryList\etc\widget.xml
代码内容:
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Magento/Widget/etc/widget.xsd"> <widget id="custom_homepage_category_title" class="Rokanthemes\HomeCategoryList\Block\HomeCategoryTitle" is_email_compatible="true" placeholder_image="Magento_CatalogWidget::images/products_list.png" ttl="86400"> <label translate="true">Custom Homepage Category Title</label> <description translate="true">Custom Homepage Category Title</description> <parameters> <parameter name="title" xsi:type="text" required="true" visible="true"> <label translate="true">Title</label> </parameter> <parameter name="short_desc" xsi:type="text" required="false" visible="true"> <label translate="true">Short Desc</label> </parameter> </parameters> </widget> </widgets>
-
在block中创建对应的类
上面配置中
<widget>
标签中的class
值为当前widget
所对应的class
类,所以要在对应位置创建HomeCategoryTitle.php
文件位置为:
Rokanthemes\HomeCategoryList\Block\HomeCategoryTitle
代码内容示例:<?php namespace Rokanthemes\HomeCategoryList\Block; class HomeCategoryTitle extends \Magento\Catalog\Block\Product\AbstractProduct implements \Magento\Widget\Block\BlockInterface { protected $httpContext; protected $_catalogProductVisibility; protected $productCollectionFactory; protected $sqlBuilder; protected $rule; protected $conditionsHelper; protected $_categoryFactory; protected $productFactory; protected $_scopeConfig; public function __construct( \Magento\Catalog\Block\Product\Context $context, \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory, \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility, \Magento\Framework\App\Http\Context $httpContext, \Magento\Rule\Model\Condition\Sql\Builder $sqlBuilder, \Magento\CatalogWidget\Model\Rule $rule, \Magento\Widget\Helper\Conditions $conditionsHelper, \Magento\Catalog\Model\CategoryFactory $categoryFactory, array $data = [] ) { $this->productCollectionFactory = $productCollectionFactory; $this->_catalogProductVisibility = $catalogProductVisibility; $this->httpContext = $httpContext; $this->sqlBuilder = $sqlBuilder; $this->rule = $rule; $this->conditionsHelper = $conditionsHelper; $this->_categoryFactory = $categoryFactory; $this->_scopeConfig = $context->getScopeConfig(); parent::__construct( $context, $data ); $this->_isScopePrivate = true; } /** * {@inheritdoc} */ protected function _construct() { parent::_construct(); $this->setTemplate('widget/home_category_title.phtml'); } public function getTitle() { return $this->getData('title'); } public function getCategoryId() { $categoryIdLink = explode('/',$this->getData('category_id')); return end($categoryIdLink); } public function getLeftBigImage(){ return $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA).$this->getData('left_big_image'); } public function getLeftBigImageLink(){ return $this->getData('left_big_image_link'); } public function getBaseUrl() { return $this->_storeManager->getStore()->getBaseUrl(); } } ?>
-
创建widget对应的template文件
在上面block创建的方法中有以下代码段:
protected function _construct(){ parent::_construct(); $this->setTemplate('widget/home_category_title.phtml'); }
其实这里就是设置
widget
对应的.phtml
文件所以我们需要在Rokanthemes\HomeCategoryList\view\frontend\templates\widget\
位置创建对应的home_category_title.phtml
文件。代码内容:
<div class="rokan-product-heading rokan-featured-heading"> <h2><?php echo $block->getTitle(); ?></h2> <?php if ($block->getShortDescData()): ?> <div class="short_desc"><p><?php echo $this->getShortDescData(); ?></p></div> <?php endif; ?> </div>
-
命令行清除缓存重新生成静态
清除缓存:
php bin/magento cache:clean
重新安装di
php bin/magento setup:di:compile
生成静态
php bin/magento setup:static-content:deploy
自定义widget中添加图片选择器插入图片
widget.xml
中添加图片选择器parameter
<parameter name="below_image" xsi:type="block" required="true" visible="true">
<label translate="true">Below Image</label>
<description translate="true">Select Insert photo</description>
<block class="Rokanthemes\HomeCategoryList\Block\Adminhtml\Widget\ImageChooser">
<data>
<item name="button" xsi:type="array">
<item name="open" xsi:type="string">Choose Image...</item>
</item>
</data>
</block>
</parameter>
模块block
中添加ImageChooser.php
文件
文件位置:Rokanthemes\HomeCategoryList\Block\Adminhtml\Widget\
代码:
<?php
namespace Rokanthemes\HomeCategoryList\Block\Adminhtml\Widget;
use Magento\Framework\Data\Form\Element\AbstractElement as Element;
use Magento\Backend\Block\Template\Context as TemplateContext;
use Magento\Framework\Data\Form\Element\Factory as FormElementFactory;
use Magento\Backend\Block\Template;
class ImageChooser extends Template
{
/**
* @var \Magento\Framework\Data\Form\Element\Factory
*/
protected $elementFactory;
/**
* @param TemplateContext $context
* @param FormElementFactory $elementFactory
* @param array $data
*/
public function __construct(
TemplateContext $context,
FormElementFactory $elementFactory,
$data = []
) {
$this->elementFactory = $elementFactory;
parent::__construct($context, $data);
}
/**
* Prepare chooser element HTML
*
* @param Element $element
* @return Element
*/
public function prepareElementHtml(Element $element)
{
$config = $this->_getData('config');
$sourceUrl = $this->getUrl('cms/wysiwyg_images/index',
['target_element_id' => $element->getId(), 'type' => 'file']);
/** @var \Magento\Backend\Block\Widget\Button $chooser */
$chooser = $this->getLayout()->createBlock('Magento\Backend\Block\Widget\Button')
->setType('button')
->setClass('btn-chooser')
->setLabel($config['button']['open'])
// ->setOnClick( "MediabrowserUtility.openDialog( '$sourceUrl', null, null, '".$this->escapeQuote(__('Choose Image...'),true)."', (opt = new Object(), opt.closed = false, opt) )" )
->setOnClick('MediabrowserUtility.openDialog(\''. $sourceUrl .'\')')
->setDisabled($element->getReadonly());
/** @var \Magento\Framework\Data\Form\Element\Text $input */
$input = $this->elementFactory->create("text", ['data' => $element->getData()]);
$input->setId($element->getId());
$input->setForm($element->getForm());
$input->setClass("widget-option input-text admin__control-text");
if ($element->getRequired()) {
$input->addClass('required-entry');
}
$element->setData('after_element_html', $input->getElementHtml() . $chooser->toHtml());
return $element;
}
}
创建拦截器对插入图片地址进行处理
因为是在widget中插入图片,默认会插入带有'{{','}}'的引用方式,会与widget的引用造成冲突从而使图片无法正常显示。所以需要在插入动作之后对图片地址进行处理
创建一个新的插件(拦截器) Rokanthemes/HomeCategoryList/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Magento\Widget\Model\Widget">
<plugin name="insert_picture_before" type="Rokanthemes\HomeCategoryList\Model\Widget" sortOrder="1" disabled="false"/>
</type>
</config>
然后创建拦截器逻辑,需要使用before方法,这样就可以改变传递给\Magento\Widget\Model\Widget
方法getWidgetDeclaration
的参数,getWidgetDeclaration
。
文件位置:Rokanthemes\HomeCategoryList\Model\
文件名:Widget.php
代码内容:
<?php
/**
* Created by PhpStorm.
* User: Hankin.Peng
* Date: 2018/7/20
* Time: 16:03
*/
namespace Rokanthemes\HomeCategoryList\Model;
use \Magento\Widget\Model\Widget as BaseWidget;
class Widget
{
public function beforeGetWidgetDeclaration(BaseWidget $subject, $type, $params = [], $asIs = true)
{
// I rather do a check for a specific parameters
$str='Rokanthemes\HomeCategoryList\Block\HomeCategory';
$pictureStr='Picture';
if(strstr($type,$str) && stristr($type,$pictureStr)) {
foreach ($params as $paramKey => $value) {
$url = $params[$paramKey];
if (strpos($url, '/directive/___directive/') !== false) {
$parts = explode('/', $url);
$key = array_search("___directive", $parts);
if ($key !== false) {
$url = $parts[$key + 1];
$url = base64_decode(strtr($url, '-_,', '+/='));
$parts = explode('"', $url);
$key = array_search("{{media url=", $parts);
$url = $parts[$key + 1];
$params[$paramKey] = $url;
}
}
}
}
return array($type, $params, $asIs);
}
}