Skip to content

Instantly share code, notes, and snippets.

@jonathonbyrdziak
Last active September 29, 2022 22:00
Show Gist options
  • Star 74 You must be signed in to star a gist
  • Fork 42 You must be signed in to fork a gist
  • Save jonathonbyrdziak/1229641 to your computer and use it in GitHub Desktop.
Save jonathonbyrdziak/1229641 to your computer and use it in GitHub Desktop.
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('Option 1', 'Option 2', 'Option 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 $option)
{
echo '<option', $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
}
}
@jonathonbyrdziak
Copy link
Author

@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
Copy link

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.

@jonathonbyrdziak
Copy link
Author

@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.

@jonathonbyrdziak
Copy link
Author

@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
Copy link

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?

@jonathonbyrdziak
Copy link
Author

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

@kabadabra
Copy link

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!!

@jonathonbyrdziak
Copy link
Author

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

@kabadabra
Copy link

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

@kabadabra
Copy link

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?

@jonathonbyrdziak
Copy link
Author

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
Copy link

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...

@jonathonbyrdziak
Copy link
Author

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
Copy link

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

@humanshell
Copy link

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.

@jonathonbyrdziak
Copy link
Author

jonathonbyrdziak commented Jun 28, 2012 via email

@humanshell
Copy link

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.

@jonathonbyrdziak
Copy link
Author

jonathonbyrdziak commented Jul 8, 2012 via email

@humanshell
Copy link

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

@mrwweb
Copy link

mrwweb commented Sep 27, 2012

(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:
` $_name): ?>
<input name="" id=""
value="" type=""

class="" />

<label class="<?php echo $element_name; ?>" for="<?php echo $id; ?>">
    <?php echo $_name; ?>
</label>
`

For some reason, using only <?php echo $_value; ?> as the id/for attribute didn't work. Also, I moved the <br /> tag inside the foreach so each checkbox/radio button gets its own line.

I love this thing. Thanks!

@mrwweb
Copy link

mrwweb commented Sep 27, 2012

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

@mrwweb
Copy link

mrwweb commented Sep 27, 2012

(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

@jonathonbyrdziak
Copy link
Author

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

@foxpcteam
Copy link

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.

@osirismqz
Copy link

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 :)

@jonathonbyrdziak
Copy link
Author

Nice @ozzysong I'll get that added

@alessandrotesoro
Copy link

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
Copy link

AndPicc commented Dec 24, 2014

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

@alexanderbiscajin
Copy link

Thanks for an amazing tutorial on how to create widgets. WordPress give a best drag and drop design option through widgets. This components allow users to add design and structure control elements through WordPress themes. Create Widget Plugin

@Adzetko
Copy link

Adzetko commented Nov 20, 2020

Careful! In widget.class.phpn at line 176, it shows

parent::WP_Widget(

which is deprecated. However, the fix is simple, simply replace WP_Widget( by __construct(.

This piece of code was so useful and makes the plugin developement so much streamlined, thanks alot ♥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment