WordPress Tips: extend the Text Widget allowing shortcodes and custom classes

What follows is a small tip to create an extension of the base “text” widget of WordPress, to allow the execution of shortcodes and to allow to specify one or more classes (space separated) per-widget.
In this way it will be really simple identify the widget in our CSS.

The class is really simple to manage and extend (if you know what this class does: if not, you can read more at http://codex.wordpress.org/Widgets_API).

To give it a try, just replace “Mytheme” and “mytheme” with your theme (or child theme) name and put the code into the function.php file.
You can alternatively create a simple plugin, but this is left as an exercise for the reader :P


/**
 * Advanced Text widget class
 */
class Mytheme_Widget_Text extends WP_Widget {

	function __construct() {
		parent::__construct(
			'mytheme_widget_text',
			__('Mytheme: Arbitrary Text/HTML and shortcodes.'),
			array( 'description' => __( 'Output an arbitrary text/HTML and/or shortcodes.', 'mytheme' ), ) 
		);
	}

	function widget( $args, $instance ) {
		extract($args);
		$title = apply_filters( 'mytheme_widget_text', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
		$text = apply_filters( 'mytheme_widget_text', empty( $instance['text'] ) ? '' : $instance['text'], $instance );
		$class = apply_filters( 'mytheme_widget_text', empty( $instance['class'] ) ? '' : $instance['class'], $instance );

		echo $before_widget;
		if ( !empty( $title ) ) { echo $before_title . $title . $after_title; } ?>
			<div class="mytheme-textwidget <?php echo $class; ?>"><?php echo !empty( $instance['filter'] ) ? wpautop( $text ) : $text; ?></div>
		<?php
		echo $after_widget;
	}

	function update( $new_instance, $old_instance ) {
		$instance = $old_instance;
		$instance['title'] = strip_tags($new_instance['title']);
		$instance['class'] = strip_tags($new_instance['class']);

		if ( current_user_can('unfiltered_html') )
			$instance['text'] =  $new_instance['text'];
		else
			$instance['text'] = stripslashes( wp_filter_post_kses( addslashes($new_instance['text']) ) ); // wp_filter_post_kses() expects slashed
		$instance['filter'] = isset($new_instance['filter']);

		return $instance;
	}

	function form( $instance ) {
		$instance = wp_parse_args( (array) $instance, array(
				'title' => '',
				'text' => '',
				'class' => ''
			)
		);
		$title = strip_tags($instance['title']);
		$text = esc_textarea($instance['text']);
		$class = esc_textarea($instance['class']);
	?>
		<p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
		<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($title); ?>" /></p>

		<p><label for="<?php echo $this->get_field_id('class'); ?>"><?php _e('Class:'); ?></label>
		<input class="widefat" id="<?php echo $this->get_field_id('class'); ?>" name="<?php echo $this->get_field_name('class'); ?>" type="text" value="<?php echo esc_attr($class); ?>" /></p>

		<textarea class="widefat" rows="16" cols="20" id="<?php echo $this->get_field_id('text'); ?>" name="<?php echo $this->get_field_name('text'); ?>">
		    <?php echo $text; ?>
		</textarea>

		<p><input id="<?php echo $this->get_field_id('filter'); ?>" name="<?php echo $this->get_field_name('filter'); ?>" type="checkbox" <?php checked(isset($instance['filter']) ? $instance['filter'] : 0); ?> />&nbsp;<label for="<?php echo $this->get_field_id('filter'); ?>"><?php _e('Automatically add paragraphs'); ?></label></p>
	<?php
	}
}


// Register and load the widget
function mytheme_load_widget() {
	register_widget( 'mytheme_widget_text' );

	// Allow to execute shortcodes on mytheme_widget_text
	add_filter('mytheme_widget_text', 'do_shortcode');
}
add_action( 'widgets_init', 'mytheme_load_widget' );

In order to use Disqus to comment out you have to accept the use of third-party cookies.