In dit artikel leg ik uit hoe de Recent Custom Posts widget is opgebouwd (Wordpress 3.0+, vereist wat voorkennis van Custom Posts en 1 of meer daadwerkelijk bestaande Custom Post types om te testen/gebruiken).
Sinds versie 2.8 beschikt Wordpress over een zogenaamde API, een Application Programming Interface. Een API is een verzameling definities op basis waarvan een computerprogramma kan communiceren met een ander programma of onderdeel. In dit geval gebeurt dat in de vorm van bibliotheken, zogenaamde 'classes'. Om precies te zijn: de class WP_Widget. Deze bibliotheek definieert alle basis-functionaliteiten van een widget, dat wil zeggen: de manier waarop een widget zich hoort te gedragen. Denk daarbij aan het verschijnen in je administrator panel, het weergegeven worden op je website aan de gebruikerskant etc. Dit is echter (nog) een holle schil. Wat de widget doet en hoe hij dit doet, wordt pas duidelijk wanneer je dit aan de API vertelt.
Hoe werkt de widget API? In principe kun je de werking van een widget uitbreiden door functies toe te voegen aan de class WP_Widget. Hoe de class WP_Widget er precies uitziet, daar gaan ik nu niet op in (en dat is ook niet relevant voor dit artikel). Deze bibliotheek beschikt over vier basis functies, ook wel functionaliteiten (in Wordpress aangeduid als 'functions'):
class Recent_Custom_Posts extends WP_Widget
{
"> function Recent_Custom_Posts() { }
function form($instance) { }
function update($new_instance, $old_instance) { }
function widget($args, $instance) {}
}
register_widget('Recent_Custom_Posts');
De functies van de widget Recent_Custom_Posts() is eigenlijk een kopie van de "WP_Widget_Recent_Posts"-widget (deze vindt je in wp-includes/default-widgets.php - bekijk deze eens om te vergelijken). Daaraan heb ik een string $custom toegevoegd. Deze string word door de gebruiker ingevoerd (het custom post type), daarop wordt vervolgens de WP_Query gedraaid. Alleen berichten van het ingevoerde post-type worden weergegeven, in plaats van het standaard post-type "the_post". Eigenlijk is dit erg voor de hand liggend, maar in mijn ogen nog niet eerder uitgevoerd (althans, ik kon het niet vinden).
Dit ziet er in de praktijk als volgt uit (voeg deze code toe onderaan het bestand functions.php binnen je actieve theme):
class Recent_Custom_Posts extends WP_Widget {
function Recent_Custom_Posts() {
$widget_ops = array('classname' => 'Recent_Custom_Posts', 'description' => __( "The most recent custom posts on your blog") );
$this->WP_Widget('recent-custom-posts', __('Recent Custom Posts'), $widget_ops);
$this->alt_option_name = 'Recent_Custom_Posts';
add_action( 'save_post', array(&$this, 'flush_widget_cache') );
add_action( 'deleted_post', array(&$this, 'flush_widget_cache') );
add_action( 'switch_theme', array(&$this, 'flush_widget_cache') );
}
function widget($args, $instance) {
$cache = wp_cache_get('Recent_Custom_Posts', 'widget');
if ( !is_array($cache) )
$cache = array();
if ( isset($cache[$args['widget_id']]) ) {
echo $cache[$args['widget_id']];
return;
}
ob_start();
extract($args);
<script src="/plugins/editors/tinymce/jscripts/tiny_mce/themes/advanced/langs/en.js" type="text/javascript"></script>
t;
$title = apply_filters('widget_title', empty($instance['title']) ? __('Recent Posts') : $instance['title']);
$custom = apply_filters('post_type', empty($instance['custom']) ? __('post') : $instance['custom']);
if ( !$number = (int) $instance['number'] )
$number = 10;
else if ( $number < 1 )
$number = 1;
else if ( $number > 15 )
$number = 15;
$r = new WP_Query(array('showposts' => $number, 'nopaging' => 0, 'post_status' => 'publish', 'caller_get_posts' => 1, 'post_type' => $custom));
if ($r->have_posts()) : ?>
<?php echo $before_widget; ?>
<?php if ( $title ) echo $before_title . $title . $after_title; ?>
<ul>
<?php while ($r->have_posts()) : $r->the_post(); ?>
<li><a href="/<?php the_permalink() ?>" title="<?php echo esc_attr(get_the_title() ? get_the_title() : get_the_ID()); ?>"><?php if ( get_the_title() ) the_title(); else the_ID(); ?> </a></li>
<?php endwhile; ?>
</ul>
<?php echo $after_widget; ?>
<?php
wp_reset_query(); // Restore global post data stomped by the_post().
endif;
$cache[$args['widget_id']] = ob_get_flush();
wp_cache_add('Recent_Custom_Posts', $cache, 'widget');
}
function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title']);
$instance['number'] = (int) $new_instance['number'];
$instance['custom'] = strip_tags($new_instance['custom']);
$this->flush_widget_cache();
$alloptions = wp_cache_get( 'alloptions', 'options' );
if ( isset($alloptions['Recent_Custom_Posts']) )
delete_option('Recent_Custom_Posts');
return $instance;
}
function flush_widget_cache() {
wp_cache_delete('Recent_Custom_Posts', 'widget');
}
function form( $instance ) {
$title = esc_attr($instance['title']);
if ( !$number = (int) $instance['number'] )
$number = 5;
$custom = esc_attr($instance['custom']);
?>
<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 $title; ?>" /></p>
<p><label for="<?php echo $this->get_field_id('custom'); ?>"><?php _e('Custom Post Type:'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('custom'); ?>" name="<?php echo $this->get_field_name('custom'); ?>" type="text" value="<?php echo $custom; ?>" /></p>
<p><label for="<?php echo $this->get_field_id('number'); ?>"><?php _e('Number of posts to show:'); ?></label>
<input id="<?php echo $this->get_field_id('number'); ?>" name="<?php echo $this->get_field_name('number'); ?>" type="text" value="<?php echo $number; ?>" size="3" /><br />
<small><?php _e('(at most 15)'); ?></small></p>
<?php
}
}
register_widget('Recent_Custom_Posts');
Binnenkort breid ik de werking van deze widget verder uit. Op het verlanglijstje staat nog:
- Een dropdown-menu met daarin de binnen het blog aanwezige custom post types i.p.v. het handmatig invoeren van custom post type;
- Meerdere custom post types weergeven in 1 widget;
- Een plug-in maken van deze widget.
Voel je vrij om aanpassingen en toevoegingen te mailen naar:
Dit e-mailadres is beschermd tegen spambots. U heeft Javascript nodig om het te kunnen zien.
Met vriendelijke groet,
Dick Jense