Why does my widget break other widgets?

So this widget i created is killing all other widgets registered in the same sidebar. Meaning, nothing renders after this widget does. No other widget markup makes it to the DOM. After hours of hair pulling, I’ve found that the culprit has something to do with the get_posts method found in _get_featured_posts(). It’s like calling that method stops all other widget processing. Here’s my widget code:

class Featured_newsroom_posts extends WP_Widget {
function __construct() {
    parent::__construct(
        'featured_newsroom_posts', // Base ID
        __('CUMC: Featured Newsroom Posts', 'text_domain'), // Name
        array( 'description' => __( 'Featured posts to show on the newsroom homepage ordered by publish date.', 'text_domain' ), ) // Args
    );
}

public function widget( $args, $instance ) {
    $title = apply_filters( 'widget_title', $instance['title'] );
    echo $args['before_widget'];
    if ( ! empty( $title ) ){
        echo $args['before_title'] . $title . $args['after_title'];
    }

    $featured_posts = $this->_get_featured_posts();
    if (!empty($featured_posts)) {
        $count = 1;
        foreach ($featured_posts as $inner) {
            echo '
                <article class="headline">
                    <a href="' . $inner->guid . '">
                        <strong class="headline-source">' . $inner->post_title . '</strong>
                    </a>
                </article>';
            if ($count === (int)$instance['count']) {
                break;
            }
            $count++;
        }
    } else {
        echo 'No recent posts found.';
    }
    echo $args['after_widget'];
}

public function form( $instance ) {
    if ( isset( $instance['title'] ) ) {
        $title = $instance['title'];
    }
    else {
        $title = __( 'Featured Posts', 'text_domain' );
    }
    ?>
    <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( 'count' ); ?>"><?php _e( 'Number of posts to display:' ); ?></label>
        <select name="<?php echo $this->get_field_name( 'count' ); ?>">
            <?php 
                for($i = 1; $i <= 8; $i++){
                    echo '<option value="' . $i . '" ' . ($i === (int)$instance[ 'count' ] ? 'selected' : '' ) . '>' . $i . '</option>';
                }
            ?>
        </select>
    </p>
    <?php 
}

public function update( $new_instance, $old_instance ) {
    $instance = array();
    $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
    $instance['count'] = $new_instance['count'];

    return $instance;
}

private function _get_featured_posts(){
    global $wpdb;
    //Get all the blog ids
    $sites = wp_get_sites(array('public' => 1, 'offset' => 1));

    $all_posts = array();
    foreach($sites as $site) {
        switch_to_blog($site['blog_id']);
        //Find posts that are marked for listing in the newsroom
        $posts = get_posts(array('meta_key' => 'list_in_newsroom', 'meta_value' => '1'));
        if($posts){
            $all_posts = array_merge($all_posts, $posts);
        }
    }
    restore_current_blog();
    return $all_posts;
}
}

function register_custom_widgets() {
register_widget( 'Featured_newsroom_posts' );
}
add_action( 'widgets_init', 'register_custom_widgets' );

Any help would be totally awesome! Thanks!

Related posts

1 comment

  1. I can already see a problem. It is your use of switch_to_blog(). You are potentially doing multiple switch_to_blog() calls; calling restore_current_blog() once at the end of the loop is meaningless. Please review the codex with examples – http://codex.wordpress.org/Function_Reference/switch_to_blog

    A quick fix is putting restore_current_blog() within the foreach loop. What happens if you do not use switch_to_blog() and restore_current_blog() correctly is that WP globals are disrupted and potentially break WP APIs called afterwards.

Comments are closed.