Posted in WordPress

How to cache a WordPress widget

Use powerful WordPress Transients API for cache heavy piece of code.

// Block direct requests
if ( !defined('ABSPATH') ) {
	exit();
}

/**
 * Example Cache Widget
 *
 * @author 	LetaMotovilov <lehaqs@gmail.com>
 */
class Example_Cache_Widget extends WP_Widget {

	public $textdomain = 'textdomain';

	public function __construct() {
		$params = array(
			'name' 			=> __( 'Example Cache', $this->textdomain ),
			'description' 	=> __( 'Displays some elements.', $this->textdomain ),
		);
		parent::__construct( 'Example_Cache_Widget', '', $params );
		// If need, uncomment this.
		/*
			add_action( 'save_post', array( $this, 'delete_cache' ) );
			add_action( 'deleted_post', array( $this, 'delete_cache' ) );
			add_action( 'switch_theme', array( $this, 'delete_cache' ) );
		*/
	}

	public function widget( $args, $instance ) {
	    // Display html
		extract( $args );
	    echo $before_widget;

		if ( $instance['title'] ) {
			echo $before_title . $instance['title'] . $after_title;
		}

		$cached_code = get_transient( $this->id );
		// Check if code exist in cache.
		if( $cached_code === false ) {
			$elements = $this->get_elements( $instance['count'] );

			ob_start();
			$this->display_elements( $elements );
			$cached_code = ob_get_contents();
			ob_end_clean();

			// Add to cache for one day.
			set_transient( $this->id, $cached_code, DAY_IN_SECONDS );
		}
		echo $cached_code;

		echo $after_widget;
	}

	public function form( $instance ) {
		$defaults = $this->get_defaults();

		extract( wp_parse_args( $instance, $defaults ) );
		?>
		<p>
			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:', $this->textdomain ); ?></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 ); ?>">
			<span class="description"><?php _e('Widget title.', $this->textdomain); ?></span>
		</p>
		<p>
			<label for="<?php echo $this->get_field_id( 'count' ); ?>"><?php _e( 'Count:', $this->textdomain ); ?></label>
			<input type="number" class="widefat" id="<?php echo $this->get_field_id( 'count' ); ?>"  min="10" max="40" name="<?php echo $this->get_field_name( 'count' ); ?>" value="<?php echo esc_attr( $count ); ?>" />
            <span class="description"><?php _e('How many elements fetch (min 10 - max 40 posts)', $this->textdomain); ?></span>
		</p>
		<?php
	}

	public function update( $new_instance, $old_instance ) {
		$instance = $old_instance;

		$instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
		$instance['count'] = ( ! empty( $new_instance['title'] ) ) ? absint( strip_tags( $new_instance['title'] ) ): '';

		$this->delete_cache();

		return $instance;
	}

	private function get_elements ( $count ) {

		// Its super hard query
	    $args_query = array(
	    	'post_type' => 'post',
	    	'post_status' => 'publish',
	    	'posts_per_page' => $count
	    );

		return new WP_Query( $args_query );
	}

	private function display_elements ( $elements ) {
		// Do super hard stuff...
		// echo $element;
	}

	private function get_defaults() {
		$defaults = array(
			'title'			=> __('Some Title', $this->textdomain),
			'count'			=> 10,
		);

		return $defaults;
	}

	private function delete_cache() {
		delete_transient( $this->id );
	}
}

// Load the widget on widgets_init PHP 5.3+
add_action( 'widgets_init', function(){
    register_widget( 'Example_Cache_Widget' );
});

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s