Skip to content

@Jonathonbyrd /CustomWidgetFile.php
Last active

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
EMPTY WIDGET Plugin code to create a single widget in wordpress.
<?php
/**
* @Author Jonathon byrd
* @link http://www.jonathonbyrd.com
* @Package Wordpress
* @SubPackage Widgets
* @copyright Proprietary Software, Copyright Byrd Incorporated. All Rights Reserved
* @Since 1.0.0
*
* Plugin Name: Master Widget
* Plugin URI: http://www.redrokk.com
* Description: <a href="http://redrokk.com" target="_blank">redrokk</a> Designs and develops software for WordPress, Drupal, Joomla, Cakephp, SugarCRM, Symfony and more!
* Version: 1.0.0
* Author: redrokk
* Author URI: http://www.redrokk.com
*
*
*/
defined('ABSPATH') or die("Cannot access pages directly.");
/**
* Register a New Master Widget
*
* The following is an array of settings for a single widget.
* All that you need to worry about is defining this array and the
* logic + administrative options for the widget is handled.
*
* The actual display of the widget is not handled by the Master
* Widget Class and requires that you provide a callback or a file that
* can be displayed when the widget is shown on the front end.
*
* A nice array of values is provided to you when displaying the widget
* UI, simply use extract($args) to retrieve three variables full of
* useful data.
*
* The following code should be placed within your theme/functions.php
*
* ************** ************* *************
//build an array of settings
$docWidget = array(
'id' => 'first-custom-widget', //make sure that this is unique
'title' => 'aaaFirst Widget',
'classname' => 'st-custom-wi',
'do_wrapper' => true,
'show_view' => 'document_widget_view',
'fields' => array(
array(
'name' => 'Title',
'desc' => '',
'id' => 'title',
'type' => 'text',
'std' => ''
),
array(
'name' => 'Textarea',
'desc' => 'Enter big text here',
'id' => 'textarea_id',
'type' => 'textarea',
'std' => 'Default value 2'
),
array(
'name' => 'Select box',
'id' => 'select_id',
'type' => 'select',
'options' => array( 'KEY1' => 'Value 1', 'KEY2' => 'Value 2', 'KEY3' => 'Value 3' )
),
array(
'name' => 'Radio',
'id' => 'radio_id',
'type' => 'radio',
'options' => array(
array('name' => 'Name 1', 'value' => 'Value 1'),
array('name' => 'Name 2', 'value' => 'Value 2')
)
),
array(
'name' => 'Checkbox',
'id' => 'checkbox_id',
'type' => 'checkbox'
),
)
);
//register this widget
register_master_widget($docWidget);
function document_widget_view( $args )
{
extract($args);
?>
the view for my widget
<?php
}
*/
/**
* Only display once
*
* This line of code will ensure that we only run the master widget class
* a single time. We don't need to be throwing errors.
*/
if (!class_exists('MasterWidgetClass')) :
/**
* Initializing
*
* The directory separator is different between linux and microsoft servers.
* Thankfully php sets the DIRECTORY_SEPARATOR constant so that we know what
* to use.
*/
defined("DS") or define("DS", DIRECTORY_SEPARATOR);
/**
* Actions and Filters
*
* Register any and all actions here. Nothing should actually be called
* directly, the entire system will be based on these actions and hooks.
*/
add_action( 'widgets_init', 'widgets_init_declare_registered', 1 );
/**
* Register a widget
*
* @param $widget
*/
function register_master_widget( $widget = null )
{
global $masterWidgets;
if (!isset($masterWidgets))
{
$masterWidgets = array();
}
if (!is_array($widget)) return false;
$defaults = array(
'id' => '1',
'title' => 'Generic Widget',
'classname' => $widget['id'],
'do_wrapper' => true,
'description' => '',
'width' => 200,
'height' => 200,
'fields' => array(),
);
$masterWidgets[$widget['id']] = wp_parse_args($widget, $defaults);
return true;
}
/**
* Get the registered widgets
*
* @return array
*/
function get_registered_masterwidgets()
{
global $masterWidgets;
if (!did_action('init_master_widgets'))
do_action('init_master_widgets');
return $masterWidgets;
}
/**
* Initialize the widgets
*
* @return boolean
*/
function widgets_init_declare_registered()
{
//initialziing variables
global $wp_widget_factory;
$widgets = get_registered_masterwidgets();
//reasons to fail
if (empty($widgets) || !is_array($widgets)) return false;
foreach ($widgets as $id => $widget)
{
$wp_widget_factory->widgets[$id] =& new MasterWidgetClass( $widget );
}
return false;
}
/**
* Multiple Widget Master Class
*
* This class allows us to easily create qidgets without having to deal with the
* mass of php code.
*
* @author byrd
* @since 1.3
*/
class MasterWidgetClass extends WP_Widget
{
/**
* Constructor.
*
* @param $widget
*/
function MasterWidgetClass( $widget )
{
$this->widget = apply_filters('master_widget_setup', $widget);
$widget_ops = array(
'classname' => $this->widget['classname'],
'description' => $this->widget['description']
);
$this->WP_Widget($this->widget['id'], $this->widget['title'], $widget_ops);
}
/**
* Display the Widget View
*
* @example extract the args within the view template
extract($args[1]);
* @param $args
* @param $instance
*/
function widget($sidebar, $instance)
{
//initializing variables
$widget = $this->widget;
$widget['number'] = $this->number;
$args = array(
'sidebar' => $sidebar,
'widget' => $widget,
'params' => $instance,
);
$show_view = apply_filters('master_widget_view', $this->widget['show_view'], $widget, $instance, $sidebar);
$title = apply_filters( 'master_widget_title', $instance['title'] );
if ( $widget['do_wrapper'] )
echo $sidebar['before_widget'];
if ( $title && $widget['do_wrapper'] )
echo $sidebar['before_title'] . $title . $sidebar['after_title'];
//give people an opportunity
do_action('master_widget_show_'.$widget['id']);
//load the file if it exists
if (file_exists($show_view))
require $show_view;
//call the function if it exists
elseif (is_callable($show_view))
call_user_func( $show_view, $args );
//echo if we can't figure it out
else echo $show_view;
if ($widget['do_wrapper'])
echo $sidebar['after_widget'];
}
/**
* Update from within the admin
*
* @param $new_instance
* @param $old_instance
*/
function update($new_instance, $old_instance)
{
//initializing variables
$new_instance = array_map('strip_tags', $new_instance);
$instance = wp_parse_args($new_instance, $old_instance);
return $instance;
}
/**
* Display the options form
*
* @param $instance
*/
function form($instance)
{
//reasons to fail
if (empty($this->widget['fields'])) return false;
$defaults = array(
'id' => '',
'name' => '',
'desc' => '',
'type' => '',
'options' => '',
'std' => '',
);
do_action('master_widget_before');
foreach ($this->widget['fields'] as $field)
{
//making sure we don't throw strict errors
$field = wp_parse_args($field, $defaults);
$meta = false;
if (isset($field['id']) && array_key_exists($field['id'], $instance))
@$meta = attribute_escape($instance[$field['id']]);
if ($field['type'] != 'custom' && $field['type'] != 'metabox')
{
echo '<p><label for="',$this->get_field_id($field['id']),'">';
}
if (isset($field['name']) && $field['name']) echo $field['name'],':';
switch ($field['type'])
{
case 'text':
echo '<input type="text" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '" value="', ($meta ? $meta : @$field['std']), '" class="vibe_text" />',
'<br/><span class="description">', @$field['desc'], '</span>';
break;
case 'textarea':
echo '<textarea class="vibe_textarea" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '" cols="60" rows="4" style="width:97%">', $meta ? $meta : @$field['std'], '</textarea>',
'<br/><span class="description">', @$field['desc'], '</span>';
break;
case 'select':
echo '<select class="vibe_select" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '">';
foreach ($field['options'] as $value => $option)
{
echo '<option', $value ? ' value="' . $value . '"' : '', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>';
}
echo '</select>',
'<br/><span class="description">', @$field['desc'], '</span>';
break;
case 'radio':
foreach ($field['options'] as $option)
{
echo '<input class="vibe_radio" type="radio" name="', $this->get_field_name($field['id']), '" value="', $option['value'], '"', $meta == $option['value'] ? ' checked="checked"' : '', ' />',
$option['name'];
}
echo '<br/><span class="description">', @$field['desc'], '</span>';
break;
case 'checkbox':
echo '<input type="hidden" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '" /> ',
'<input class="vibe_checkbox" type="checkbox" name="', $this->get_field_name($field['id']), '" id="', $this->get_field_id($field['id']), '"', $meta ? ' checked="checked"' : '', ' /> ',
'<br/><span class="description">', @$field['desc'], '</span>';
break;
case 'custom':
echo $field['std'];
break;
}
if ($field['type'] != 'custom' && $field['type'] != 'metabox')
{
echo '</label></p>';
}
}
do_action('master_widget_after');
return;
}
}// ends Master Widget Class
endif; //if !class_exists
<?php
/**
* @Author Jonathon byrd
* @link http://www.jonathonbyrd.com
* @Package Wordpress
* @SubPackage Widgets
* @copyright Proprietary Software, Copyright Byrd Incorporated. All Rights Reserved
* @Since 1.0.0
*
* Plugin Name: Document Widget
* Plugin URI: http://www.redrokk.com
* Description: <a href="http://redrokk.com" target="_blank">redrokk</a> Designs and develops software for WordPress, Drupal, Joomla, Cakephp, SugarCRM, Symfony and more!
* Version: 1.0.0
* Author: redrokk
* Author URI: http://www.redrokk.com
*
*
*/
defined('ABSPATH') or die("Cannot access pages directly.");
/**
* Initializing
*
* The directory separator is different between linux and microsoft servers.
* Thankfully php sets the DIRECTORY_SEPARATOR constant so that we know what
* to use.
*/
defined("DS") or define("DS", DIRECTORY_SEPARATOR);
/**
* Actions and Filters
*
* Register any and all actions here. Nothing should actually be called
* directly, the entire system will be based on these actions and hooks.
*/
add_action( 'widgets_init', create_function( '', 'register_widget("Document_Widget");' ) );
/**
*
* @author byrd
* Document Widget
*/
class Document_Widget extends WP_Widget
{
/**
* Constructor
*
* Registers the widget details with the parent class
*/
function Document_Widget()
{
// widget actual processes
parent::WP_Widget( $id = 'foo_widget', $name = get_class($this), $options = array( 'description' => 'A Foo Widget' ) );
}
function form($instance)
{
// outputs the options form on admin
?>
Form goes here
<?php
}
function update($new_instance, $old_instance)
{
// processes widget options to be saved
$instance = wp_parse_args($old_instance, $new_instance);
return $instance;
}
function widget($args, $instance)
{
// outputs the content of the widget
extract( $args );
$title = apply_filters( 'widget_title', $instance['title'] );
echo $before_widget;
if ( $title )
echo $before_title . $title . $after_title;
?>
Widget view to users goes here
<?php
}
}
@JulioRFA

GREAT job Jonathon, this is extremely useful to get things done at light speed.

I just want to add a little useful bit:

At lines 331 - 334 you have

foreach ($field['options'] as $option)
{
    echo '<option', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>';
}

I wanted values for the <option> in the select tag, so...

foreach ($field['options'] as $value => $option)
{
    echo '<option', $value ? ' value="' . $value . '"' : '', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>';
}

So I could...

array(
    'name'    => 'Select box',
    'id'      => 'select_id',
    'type'    => 'select',
    'options' => array( 'KEY1' => 'Value 1', 'KEY2' => 'Value 2', 'KEY3' => 'Value 3' )
)

Thanks, I really appreciate this.

@Jonathonbyrd

Done. :) Thanks for the contribution. Can you retest and let me know if there's a bug.

@JulioRFA

Cool.
Another one

Lines 207 - 215. The Widget constructor. I just added on my own:

function MasterWidgetClass( $widget )
{
    $this->widget = apply_filters('master_widget_setup', $widget);
    $widget_ops = array(
        'classname' => $this->widget['classname'], 
        'description' => $this->widget['description'] 
    );
    /* Added Widget Control Settings. */
    $control_ops = array(
        'width' => $this->widget['width'],
        'height' => $this->widget['height']
    );
    $this->WP_Widget($this->widget['id'], $this->widget['title'], $widget_ops, $control_ops);
}

Added the $control_ops array, to set the widget UI width and height

Here http://phpdoc.wordpress.org/trunk/WordPress/Widgets/WP_Widget.html#$control_options says:

array $control_options: Optional Passed to wp_register_widget_control()
width: required if more than 250px
height: currently not used but may be needed in the future

@JulioRFA

There's a bug if the <option> in the <select> tag has a value property. Saving the widget settings does not take effect and the select option don't show the actual selected value. The fix that works if <option> has or not a value:

foreach ($field['options'] as $value => $option)
{
    $selected_option = ( $value ) ? $value : $option;
    echo '<option', $value ? ' value="' . $value . '"' : '', ($meta == $selected_option) ? ' selected="selected"' : '', '>', $option, '</option>';
}

:)

@Jonathonbyrd
@Fed03

i can't succed in using the wp_parse_args function to update the widget option....

i have to do this

$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title']);
$instance['cat'] = strip_tags($new_instance['cat']);
$instance['thumb_width'] = strip_tags($new_instance['thumb_width']);
$instance['thumb_height'] = strip_tags($new_instance['thumb_height']);
return $instance;

any hint?

@Jonathonbyrd
@Fed03

Can you provide me an example?

@wphax

Just a note, the attribute_escape() function has been deprecated since WP 2.8 and has been replaced with esc_attr(). I made this change on the fork I made.

@Jonathonbyrd
@jcpeden

I have the same problem as Fed03. My settings do not update. I've tried swapping:

$instance = wp_parse_args($old_instance, $new_instance);

to

$instance = wp_parse_args($new_instance, $old_instance);

But it doesn't work. Everytime I click save, the widget admin panel reverts to the old settings.

Any thoughts?

@jcpeden

Actually, I can't even get Fed03's method to work...settings will not update at all for me

@nickdefelice

If your settings are not updating, try removing any spaces from the $id variable and see if that helps. Change the line under parent::WP_Widget

$id = $classname, (under parent::WP_Widget)

To

$id = str_replace(' ','',$classname),

Also, removing any capital letters from $id may help via source: http://www.zachgraeve.com/2010/07/28/wordpress-3-0-widget-bugs-widgets-not-saving/

@Jonathonbyrd

I just added sanitize_title to all of the $ids, that should help.

@Jonathonbyrd

@CHANGELOG 5/28/2012 : Added support for shortcodes.

The Empty Widget now creates a shortcode using the same name as the class. This way you can specify [Empty_Widget title="my shortcode title"] and pass any arguments that you specified in the widget['fields'] array. Also, the std (default) option within the fields array is set as the defaults for the widget params as well as the defaults for the shortcode params.

@humanshell

Quick question:

How do I create a checkbox field that's checked by default?

@Jonathonbyrd

This should do it:

    array(
        'name' => 'Checkbox',
        'desc' => '',
        'id' => 'checkbox_id',
        'type' => 'checkbox',
        'std' => false,
    ),
@humanshell

That doesn't work on my end. I tried with false and true. It's not a huge deal, I'm enabling it now with Jquery. I just thought it might be easy to do in the checkbox field itself. No worries.

Thank you for this Gist by the way, I'm rewriting a plugin at work and I wouldn't have gotten as much done in such a short period of time without it!

@Jonathonbyrd

@CHANGELOG 5/29/2012 : Adjusted the default value handling with wp-admin configurations

The system was using an old form field creation method. I've since updated my other plugins and now this class to use a new style form field creation method. This new method is quite a bit cleaner and handles the default field values in a much more stable manner. This new method will also allow us to expand on the default form functionality with ease.

@humanshell

The new form() method looks far more powerful. I'll update my plugin to use the new method tonight. I'll let you know how it goes.

@Jonathonbyrd

@CHANGELOG 5/29/2012.2 : Added Shortcode WYSIWYG button support

The Empty_Widget class now turns your widget into a shortcode with a supporting WYSIWYG custom button. Upon clicking the button you will see the same widget options available to you for sidebars. You also have the option to view a preview of what the widget will look like when creating the shortcode. Finally, upon hitting submit within the buttons popup, the shortcode string will be created and inserted into your post or page.

@Jonathonbyrd

@CHANGELOG 5/30/2012 : Added additional form fields

The additional fields are select boxes of the default wordpress data, such as: capabilities, categories, roles, users n more!

@kabadabra

Hi - this plugin looks epic!

I added the widget, but clicking save doesnt save the values, returns back to default. Using the latest WordPress version. Any ideas?

@Jonathonbyrd

Sorry, I've been making lots of changes. I'm working on it right now and should post an update within the hour.

@kabadabra

Ahh hehe thanks man! Awesome work - just post a notice when updated, working on a project as we speak and your widget is SUPER USEFUL and easy to understand and manage!!

@Jonathonbyrd

Alright! Should be good to go bro. I tested it in WP 3.3.2, worked great.

@kabadabra

Oh yeah! Works GREAT! Thanks so much man....perfect!!!

@kabadabra

Just something weird...

I use the function "dynamic_sidebar( 'Home Pane' )" to get the contents of my Widget's HTML on my Home Page, but it only gets the default values set in the Widget's php file, not the values from WordPress Widget itself...not sure why, any advice?

@Jonathonbyrd

Thanks for bug testin this with me today :) I just had to toggle lines 336 and 337.

 $field['args']['name'] = $element_name = $this->get_field_name($id);

is now above

 $id = $this->get_field_id($id);
@kabadabra

Hehe I'm trying :) it's now doing that no saving thing again....

The toggle makes the value show up correctly, but in the widget settings it doesnt return the value just keeps the default. However it does update the fields...

@Jonathonbyrd

Fixed!

            // grabbing the meta value
            if (array_key_exists($id, $instance))
                @$meta = attribute_escape($instance[$id]);
            else
                $meta = $default;

Had to move this above the if (!$shortcode) command

@kabadabra

Nice one bro! Working great!! Thank you very much for looking into this today, and the additions you implemented are epic! bows down

@humanshell

Johnathan,

The checkbox part of the updated form() method has been working perfectly for me, thanks. I just wanted to point out that according to the Codex, attribute_escape() (line 316 of the abstract class' form method) has been deprecated since 2.8.0. That should probably be changed to esc_attr()?

Thanks again for releasing this excellent code.

@Jonathonbyrd
@humanshell

Jonathan,

Just added a textarea to my plugin and thought you should know that the line break on line 349 of the abstract class' form method was inserting all that whitespace into the textarea when clicking save in the admin. I moved that line up so it doesn't break right in the "echo $meta" output. That fixed the issue. Not sure if anyone else is experiencing this issue, but I thought you'd want to know incase you wanted to update that section.

@Jonathonbyrd
Owner
@humanshell

You're welcome, looking forward to the updates. Don't forget about changing attribute_escape() to esc_attr() on line 316. :-)

@mrwweb

(Someday, I'll figure out github better to submit a real patch. Hopefully this is useful.)

Possible bug: If there are multiple checkboxes/radioes in a single field, clicking any label toggles the first checkbox or radio button because of the id/for attributes.

I fixed that with the following:
`<?php foreach ((array)$options as $_value => $_name): ?>

@mrwweb

Should've previewed that. Sorry. I can't get code to paste. Weird. Anyway...snippet is here: http://pastebin.com/wTxPhvTj

@mrwweb

(Sorry if this got submitted. I posted this and then it disappeared. Also, someday I'll learn github, but right now my priority is submitting this patch.)

When using multiple checkboxes or radio buttons in a single option, clicking on any label toggles the first box/button. This is because the id/for values of the input/label aren't unique. I changed that, and now they work. I also moved the linebreak into the foreach loop so that each box/button gets its own line.

Code here: http://pastebin.com/wTxPhvTj

@Jonathonbyrd
Owner

Thanks buddy, I don't think I ever received an email that you commented, but noticed it now and made the adjustment.

@foxpcteam

Hello, when ui try to activate this plugin i get error:
Fatal error: Class 'Empty_Widget_Abstract' not found in /plugins/123/CustomWidgetFile.php on line 28

why i get this error?

thanks for help.

@ozzysong

I'm using your code on some widgets and found a little problem using the "select_categories" field type.

On line 422:

<?php wp_dropdown_categories($args); ?>

You forgot to actually pass arguments to wp_dropdown_categories().

This is what I'm using and is working fine:

<?php wp_dropdown_categories( array( 'id' => $id, 'name' => $element_name, 'class' => $class, 'selected' => $meta ) ); ?>

Hope it helps :)

@Jonathonbyrd
Owner

Nice @ozzysong I'll get that added

@alessandrotesoro

I'm using your class and i've noticed that it doesn't allow widgets to be localized/translated. Anytime i try using __() to localize a string (widget title/fields names/desc/ etc), it returns an unexpected "(" error. Any idea how to fix it?

Update 21st November
This also seem to cause issues with WPML when trying to translate widgets fields/titles they are not being recognized.

@AndPicc

Hello!
First of all thanx for this code, it's very well made and I'm learning a lot by working with it.
I made a few experiments in the last year, and everything was working fine.

then I've noticed that on versions after wordpress 4.0 the tinymce popup is not working properly.

when you click to submit, it loads the homepage into the popup, and it doesn't close it, nor it adds the actual shortcode into the post content..

I've tried to search around and I found out that actually there have been some changes in tinymce popups, but I've not been able to figure out how to fix your code..

could you have a look at this issue please?

cheers!
and Merry Christmas!
Andrea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.