Category: Tutorials
This article also touches on: Object-Oriented Programming
Blurbette Plugin: Widget
Creating a widget is very simple, because WordPress provides a WP_Widget class you can simply extend and define. Four methods are required:
- __construct(): the constructor which simply defines some strings and calls the parent method,
- form(): presents the draggable widget form in the admin panel,
- update(): operates when the form is updated,
- widget(): performs the output in the sidebar.
I’ll discuss each of the four methods one at a time:
<?php
class WPCX_Blurbette_Widget extends WP_Widget {
public function __construct() {
$widget_ops = array(
'classname' => 'wpcx_blurbettes',
'description' => __( 'Display a Blurbette', WPCX_Blurbette_Def::TEXT_DOMAIN )
);
parent::__construct(
'wpcx_blurbette_widget',
__( 'Blurbette', WPCX_Blurbette_Def::TEXT_DOMAIN ),
$widget_ops
);
}
The parent::__construct() method expects, in order: the Base ID, the displayed Title, and an array containing a unique classname and the description.
Next, the form() method:
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, array(
'title' => '',
'blurbette_id' => null
) );
$title = esc_attr( $instance['title'] );
$bbt_id = $instance['blurbette_id'];
$drop_ops = WPCX_Blurbette_Def::get_blurbettes_pairs( 'widget' );
?>
<p><label><?php
_e( 'Title:', WPCX_Blurbette_Def::TEXT_DOMAIN );
?><input class="widefat" type="text" id="<?php
echo $this->get_field_id( 'title' );
?>" name="<?php
echo $this->get_field_name( 'title' );
?>" value="<?php
echo $title;
?>" />
</label></p>
<p><label for="<?php
echo $this->get_field_id( 'blurbette_id' );
?>"><?php
_e( 'Blurbette:', WPCX_Blurbette_Def::TEXT_DOMAIN );
?></label>
<select id="<?php
echo $this->get_field_id( 'blurbette_id' );
?>" name="<?php
echo $this->get_field_name( 'blurbette_id' );
?>"><option value=""><?php
_e( 'Choose...', WPCX_Blurbette_Def::TEXT_DOMAIN );
?></option>
<?php foreach ( ( array ) $drop_ops['opts'] as $dop ): ?>
<option value="<?php
echo esc_attr( $dop['ID'] );
?>" <?php
echo selected( $dop['ID'], $bbt_id );
?>><?php
echo esc_html( substr( $dop['label'], 0, 50 ) );
?></option>
<?php endforeach; ?>
</select>
</p>
<?php
}
This outputs a simple two-element form, the title input text field, and a blurbette_id dropdown selector. The WP_Widget class adds other things like a Submit button, and Javascript controls for deleting, closing and dragging.
Also, it provides methods like get_field_id() and get_field_name() which I can use herein. They turn my basic name and id into unique ones, properly formatted for form processing.
Next, the update() method:
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags( $new_instance['title'] );
$instance['blurbette_id'] = $new_instance['blurbette_id'];
return $instance;
}
As you can see, the WP_Widget class makes this part very simple; I simply set elements for an $instance variable, corresponding to my form names above, and return it. Available are the $old_instance and $new_instance arrays for reference.
Lastly, the widget() method:
public function widget( $args, $instance ) {
if ( empty( $instance['blurbette_id'] ) ) return;
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
if ( WPCX_Blurbette_Def::check_availability( $instance['blurbette_id'], 'widget' ) ):
echo $args['before_widget'];
if ( ! empty( $title ) ):
echo $args['before_title'] . $title . $args['after_title'];
endif;
echo '<div class="textwidget blurbettewidget">', PHP_EOL;
echo do_shortcode( '[blurbette id="' . $instance['blurbette_id'] . '" context="widget"]' );
echo '</div>', PHP_EOL;
echo $args['after_widget'];
endif;
}
} // end class WPCX_Blurbette_Widget
WordPress calls the widget method on a custom class, when outputting the custom widget in a sidebar. It passes:
- $args, an array defined in a theme via the register_sidebar() function,
- $instance, an array containing the unique elements defined in form and update.
In this method, I’ve chosen to bail if for some reason the blurbette_id is blank. Also, only output if the WPCX_Blurbette_Def::check_availability() method (still just a placeholder) returns true. Even though the form() checks before making the Blurbette available in the dropdown, a user might later update a Blurbette’s availability without updating the widget.
Notice I’ve chosen to wrap in a <div> element with a textwidget class name, which is WordPress’ builtin class for text widgets; also an additional blurbettewidget class name. A theme is likely to define a stylesheet for a textwidget, so it makes sense to apply that definition here. Adding the additional blurbettewidget gives a designer a chance to customize further.
It’s worth pointing out: output is handled by invoking the shortcode, so any changes made in that class needn’t be re-coded here. Note also, I’ve made use of the extra context="widget" attribute of the shortcode, so output will obey that restriction if defined by the user.
Activating
All that’s left is to modify WPCX_Blurbette_Registry to activate the new widget. Activation is done with WordPress’ register_widget() function, which must be performed at the widgets_init action hook. So, define a new method within the WPCX_Blurbette_Registry class:
public function register_widget() {
register_widget( 'WPCX_Blurbette_Widget' );
}
… and hook it within WPCX_Blurbette_Registry’s __construct() method:
function __construct() {
spl_autoload_register( array( $this, 'class_autoloader' ) );
WPCX_Blurbette_Def::do_all_hooks();
WPCX_Blurbette_Shortcode::do_all_hooks();
add_action( 'widgets_init', array( $this, 'register_widget' ) );
add_action( 'plugins_loaded', array( $this, 'instantiate_the_rest' ) );
}
Recapping the code
Here’s the entire WPCX_Blurbette_Widget class:
<?php
class WPCX_Blurbette_Widget extends WP_Widget {
public function __construct() {
$widget_ops = array(
'classname' => 'wpcx_blurbettes',
'description' => __( 'Display a Blurbette', WPCX_Blurbette_Def::TEXT_DOMAIN )
);
parent::__construct(
'wpcx_blurbette_widget',
__( 'Blurbette', WPCX_Blurbette_Def::TEXT_DOMAIN ),
$widget_ops
);
}
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, array(
'title' => '',
'blurbette_id' => null
) );
$title = esc_attr( $instance['title'] );
$bbt_id = $instance['blurbette_id'];
$drop_ops = WPCX_Blurbette_Def::get_blurbettes_pairs( 'widget' );
?>
<p><label><?php
_e( 'Title:', WPCX_Blurbette_Def::TEXT_DOMAIN );
?><input class="widefat" type="text" id="<?php
echo $this->get_field_id( 'title' );
?>" name="<?php
echo $this->get_field_name( 'title' );
?>" value="<?php
echo $title;
?>" />
</label></p>
<p><label for="<?php
echo $this->get_field_id( 'blurbette_id' );
?>"><?php
_e( 'Blurbette:', WPCX_Blurbette_Def::TEXT_DOMAIN );
?></label>
<select id="<?php
echo $this->get_field_id( 'blurbette_id' );
?>" name="<?php
echo $this->get_field_name( 'blurbette_id' );
?>"><option value=""><?php
_e( 'Choose...', WPCX_Blurbette_Def::TEXT_DOMAIN );
?></option>
<?php foreach ( ( array ) $drop_ops['opts'] as $dop ): ?>
<option value="<?php
echo esc_attr( $dop['ID'] );
?>" <?php
echo selected( $dop['ID'], $bbt_id );
?>><?php
echo esc_html( substr( $dop['label'], 0, 50 ) );
?></option>
<?php endforeach; ?>
</select>
</p>
<?php
}
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags( $new_instance['title'] );
$instance['blurbette_id'] = $new_instance['blurbette_id'];
return $instance;
}
public function widget( $args, $instance ) {
if ( empty( $instance['blurbette_id'] ) ) return;
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
if ( WPCX_Blurbette_Def::check_availability( $instance['blurbette_id'], 'widget' ) ):
echo $args['before_widget'];
if ( ! empty( $title ) ):
echo $args['before_title'] . $title . $args['after_title'];
endif;
echo '<div class="textwidget blurbettewidget">', PHP_EOL;
echo do_shortcode( '[blurbette id="' . $instance['blurbette_id'] . '" context="widget"]' );
echo '</div>', PHP_EOL;
echo $args['after_widget'];
endif;
}
} // end WPCX_Blurbette_Widget