Introduction
We've already learned how to create a simple widget (i.e. create a module, define widgets and create frontend blocks). Now we are going to try to go deeper into the available widget configuration options to see what makes Magento widgets so beneficial to both the store owners and extension developers.
Learn available widget configuration options, types and definitions
Let's look into an abstract widget.xml file:
<?xml version="1.0"?>
<widgets>
<some_unique_widget_name type="block_group/block_path" translate="name description" module="modulename">
<name>Widget name</name>
<description>Short widget description</description>
<!-- Additional javascript files to be loaded
on the widget configuration edit form if needed. -->
<js>mage/adminhtml/first.js,mage/adminhtml/second.js</js>
<!--
It should contain comma separated list
of javascript files paths under the /js directory.
This tag is optional.
-->
<parameters>
<first_option translate="label">
<!-- General option properties -->
<!-- Defines if the option is allowed to be empty -->
<required>1</required>
<!-- Defines if the option is visible in the edit form -->
<visible>1</visible>
<!--
In case if you need some hidden input
in the widget configuration form,
set 'visible' to 0
-->
<!-- Label for the edit form -->
<label>Option name</label>
<!-- Option type -->
<type>select</type>
<!--
It can be either one of the simple form element types, e.g.:
<type>text</type>
<type>select</type>
<type>multiselect</type>
<type>label</type>
...
or it can define a renderer which will be used to create
this configuration field in the edit form.
Renderer is supposed to be a block reference
in 'block_group/block_path' format, e.g.:
<type>mymodule/some_custom_block</type>
-->
<!-- Source values for drop-downs and multiselects -->
<!--
There are two possible ways to define a set of available values.
The first way is to specify the list of available values right here:
-->
<values>
<value_one translate="label">
<value>1</value>
<label>One</label>
</none>
<two translate="label">
<value>2</value>
<label>Two</label>
</two>
<three translate="label">
<value>3</value>
<label>Three</label>
</three>
</values>
<!--
The second way is to specify the source model,
which must have toOptionArray() public method available.
The method should return an array of values and labels
in the following format:
array(
array('value' => 'value1', 'label' => 'Label 1'),
array('value' => 'value2', 'label' => 'Label 2'),
array('value' => 'value2', 'label' => 'Label 3'),
);
Source model name is specified in usual
'model_group/model_path' format, e.g.:
-->
<source_model>adminhtml/system_config_source_yesno</source_model>
<!-- Additional helper block to be created on the edit form page, optional -->
<helper_block>
<!-- Helper block reference in regular 'block_group/block_path' format -->
<type>module/block_type</type>
<!-- Arguments for the block constructor, optional -->
<data>
<value1>Value1</value1>
<value2>Value1</value2>
<value3>
<one>One</one>
<two>Two</two>
</value3>
</data>
</helper_block>
<!--
Here is the full example of helper block definition
from catalog module widgets:
<helper_block>
<type>adminhtml/catalog_product_widget_chooser</type>
<data>
<button translate="open">
<open>Select Product...</open>
</button>
</data>
</helper_block>
-->
</first_option>
<!--
...
any number of other widget configuration options goes here
...
-->
</parameters>
</some_unique_widget_name>
<!--
...
other widgets declarations go here
...
-->
</widgets>
Create a module
Let's create a module directory structure and necessary files
Declare a widget
app/code/local/Sample/WidgetTwo/etc/widget.xml:
<?xml version="1.0"?>
<widgets>
<widgettwo_list type="widgettwo/list" translate="name description" module="widgettwo">
<name>Social Bookmarking Links</name>
<description>Adds a simple list of social bookmarking links</description>
<parameters>
<enabled_services>
<label>Enabled Services</label>
<visible>1</visible>
<required>1</required>
<type>multiselect</type>
<source_model>widgettwo/services</source_model>
</enabled_services>
<template translate="label">
<label>Frontend Template</label>
<visible>1</visible>
<required>1</required>
<type>select</type>
<values>
<text translate="label">
<value>widgettwo/text.phtml</value>
<label>Text Links</label>
</text>
<icons translate="label">
<value>widgettwo/icons.phtml</value>
<label>Icon Links</label>
</icons>
</values>
</template>
</parameters>
</widgettwo_list>
</widgets>
Create a source model to use it with service multiselect in widget configuration
app/code/local/Sample/WidgetTwo/Model/Services.php:
<?php
class Sample_WidgetTwo_Model_Services
{
/**
* Provide available options as a value/label array
*
* @return array
*/
public function toOptionArray()
{
return array(
array('value' => 'digg', 'label' => 'Digg'),
array('value' => 'delicious', 'label' => 'Delicious'),
array('value' => 'twitter', 'label' => 'Twitter'),
);
}
}
Create a frontend widget block
app/code/local/Sample/WidgetTwo/Block/List.php:
<?php
class Sample_WidgetTwo_Block_List
extends Mage_Core_Block_Template
implements Mage_Widget_Block_Interface
{
/**
* A model to serialize attributes
* @var Varien_Object
*/
protected $_serializer = null;
/**
* Initialization
*/
protected function _construct()
{
$this->_serializer = new Varien_Object();
parent::_construct();
}
/**
* Produce links list rendered as html
*
* @return string
*/
protected function _toHtml()
{
$html = '';
$config = $this->getData('enabled_services');
if (empty($config)) {
return $html;
}
$services = explode(',', $config);
$list = array();
foreach ($services as $service) {
$item = $this->_generateServiceLink($service);
if ($item) {
$list[] = $item;
}
}
$this->assign('list', $list);
return parent::_toHtml();
}
/**
* Generate link attributes
*
* The method returns an array, containing any number of link attributes,
* All values are optional
* array(
* 'href' => '...',
* 'title' => '...',
* '_target' => '...',
* 'onclick' => '...',
* )
*
* @param string $service
* @return array
*/
protected function _generateServiceLink($service)
{
/**
* Page title
*/
$pageTitle = '';
$headBlock = $this->getLayout()->getBlock('head');
if ($headBlock) {
$pageTitle = $headBlock->getTitle();
}
/**
* Current URL
*/
$currentUrl = $this->getUrl('*/*/*', array('_current' => true, '_use_rewrite' => true));
/**
* Link HTML
*/
$attributes = array();
$icon = '';
switch ($service) {
case 'digg':
$attributes = array(
'href' => 'http://www.digg.com/submit?url=' . rawurlencode($currentUrl) . '&phase=2',
'title' => 'You Digg?',
);
$icon = 'digg.gif';
break;
case 'delicious':
$attributes = array(
'href' => 'http://del.icio.us/post?url=' . rawurlencode($currentUrl),
'title' => 'Add to del.icio.us',
'onclick' => 'window.open('http://del.icio.us/post?v=4&noui&jump=close&url='
. rawurlencode($currentUrl) . "&title=" . rawurlencode($pageTitle)
. "','delicious', 'toolbar=no,width=700,height=400'); return false;",
);
$icon = 'delicious.gif';
break;
case 'twitter':