In order to apply some changes to the default Recent Posts Widget I have copied and modified it to my needs. It is included and registered in my template’s functions.php and when loading the widget-section in the admin panel its constructor is run.
The problem is that it does not appear in the list of available widgets and thus can not be used. The problem also occurs when I try the minimal example from http://www.darrenhoyt.com/2009/12/22/creating-custom-wordpress-widgets/, so I think I missed something important, but don’t know what.
- Until now my theme is a modified clone of https://wordpress.org/extend/themes/toolbox.
This explains the many occurrences oftoolbox_in the code. - Following are code excerpts from
functions.phpand
inc/widgets.php. I can provide more code if needed. Please let me
know in the comments.
Code:
<?php
// BEGIN functions.php
if ( ! function_exists( 'toolbox_setup' ) ):
/**
* Sets up theme defaults and registers support for various WordPress features.
*
* Note that this function is hooked into the after_setup_theme hook, which runs
* before the init hook. The init hook is too late for some features, such as indicating
* support post thumbnails.
*
* To override toolbox_setup() in a child theme, add your own toolbox_setup to your child theme's
* functions.php file.
*/
function toolbox_setup() {
// [...]
require( get_template_directory() . '/inc/widgets.php' );
// [...]
}
endif; // toolbox_setup
/**
* Tell WordPress to run toolbox_setup() when the 'after_setup_theme' hook is run.
*/
add_action( 'after_setup_theme', 'toolbox_setup' );
/**
* Register widgetized area and update sidebar with default widgets
*/
function toolbox_widgets_init() {
register_widget("My_Widget_Recent_Posts");
register_sidebar( array(
'name' => __( 'Sidebar 1', 'toolbox' ),
'id' => 'sidebar-1',
'before_widget' => '<aside id="%1$s" class="widget %2$s">',
'after_widget' => "</aside>",
'before_title' => '<h1 class="widget-title small">',
'after_title' => '</h1>',
) );
}
add_action( 'init', 'toolbox_widgets_init' );
// END functions.php
?>
<?php
// BEGIN inc/widgets.php
/**
* Recent_Posts widget class
*
* @since 2.8.0
*/
class My_Widget_Recent_Posts extends WP_Widget {
function __construct() {
$widget_ops = array('classname' => 'my_widget_recent_entries', 'description' => __( "The most recent posts on your site (modified)") );
parent::__construct('my-recent-posts', __('Recent Posts (modified)'), $widget_ops);
$this->alt_option_name = 'my_widget_recent_entries';
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('my_widget_recent_posts', 'widget');
if ( !is_array($cache) )
$cache = array();
if ( ! isset( $args['widget_id'] ) )
$args['widget_id'] = $this->id;
if ( isset( $cache[ $args['widget_id'] ] ) ) {
echo $cache[ $args['widget_id'] ];
return;
}
ob_start();
extract($args);
$title = apply_filters('widget_title', empty($instance['title']) ? __('Recent Posts') : $instance['title'], $instance, $this->id_base);
if ( empty( $instance['number'] ) || ! $number = absint( $instance['number'] ) )
$number = 10;
$r = new WP_Query( apply_filters( 'widget_posts_args', array( 'posts_per_page' => $number, 'no_found_rows' => true, 'post_status' => 'publish', 'ignore_sticky_posts' => true ) ) );
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>
<?php the_content(); ?></li>
<?php endwhile; ?>
</ul>
<?php echo $after_widget; ?>
<?php
// Reset the global $the_post as this query will have stomped on it
wp_reset_postdata();
endif;
$cache[$args['widget_id']] = ob_get_flush();
wp_cache_set('my_widget_recent_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'];
$this->flush_widget_cache();
$alloptions = wp_cache_get( 'alloptions', 'options' );
if ( isset($alloptions['my_widget_recent_entries']) )
delete_option('my_widget_recent_entries');
return $instance;
}
function flush_widget_cache() {
wp_cache_delete('my_widget_recent_posts', 'widget');
}
function form( $instance ) {
$title = isset($instance['title']) ? esc_attr($instance['title']) : '';
$number = isset($instance['number']) ? absint($instance['number']) : 5;
?>
<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('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" /></p>
<?php
}
}
// END inc/widgets.php
?>
Registering the widget as follows solved the problem for me, but is not very elegant in my opinion. Right behind the class definition I inserted the line
And removed the registration from
toolbox_widgets_init()where I think it belongs.In case somebody can explain why it has to be this way round or what I could change so that it would work like I intended to do it before I would highly appreciate comments. But for now the actual problem is solved.