WordPress: Kategorie-Links mit Anzahl neuer Posts

von

Da ich hier sehr selten poste, wollte ich dem geneigten Leser „neue“ Posts gesondert anzeigen. Posts, die jünger als ein Jahr sind…

In WordPress die Anzahl aller Posts in einer Kategorie auszugeben ist ja ganz einfach. Sollen allerdings nur die Posts gezählt werden, die jünger als X Tage sind, wird es schon schwieriger.

Im Template file functions.php klinkt man sich in die Klasse Walker_Nav_Menu ein und führt dort eine Hilfsfunktion aus, die per MySql nur diejenigen Posts auswählt, welcher nach dem jetzigen Zeitpunkt minus X Tagen erstellt wurden.

Bei Themes, die schon eine eigene Custom_Walker Subklasse haben, muß man ggf. den Aufruf der Hilfsfunktion in diese bereits vorhandene Subklasse einbauen.

/*  other function.php code goes here...     */
 
function my_custom_walker( $args ) {
    return array_merge( $args, array( 'walker' => new My_Custom_Walker() ) );
}
add_filter( 'wp_nav_menu_args', 'my_custom_walker' );
 
/*  class definition */
class My_Custom_Walker extends Walker_Nav_Menu {
 
    /*  wp function taken from http://codex.wordpress.org/Class_Reference/Walker_Nav_Menu */
    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
        $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
        $class_names = $value = '';
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;
        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
        $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
        $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
        $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
        $output .= $indent . '<li' . $id . $value . $class_names .'>';
        $atts = array();
        $atts['title']  = ! empty( $item->attr_title ) ? $item->attr_title : '';
        $atts['target'] = ! empty( $item->target )     ? $item->target     : '';
        $atts['rel']    = ! empty( $item->xfn )        ? $item->xfn        : '';
        $atts['href']   = ! empty( $item->url )        ? $item->url        : '';
        $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args );
        $attributes = '';
        foreach ( $atts as $attr => $value ) {
            if ( ! empty( $value ) ) {
                $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
                $attributes .= ' ' . $attr . '="' . $value . '"';
            }
        }
        $item_output = $args->before;
        $item_output .= '<a '. $attributes .'>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        /*  since this alters menus global, post count is only appended with category links
              this could also be adapted with post types or parent category ids */
        $item_output .= $item->object == 'category' ? my_count_posts($item->object_id, 14) . '</a>' : '</a>';
        $item_output .= $args->after;
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
 
}
 
/*  takes a category id and the amount of days counted posts are old */
function my_count_posts($catid, $days) {
    global $wpdb;
    $posts = $wpdb->get_results(
        "SELECT $wpdb->posts.*
        FROM $wpdb->posts
        INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)
        INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
        WHERE 1=1
        AND $wpdb->term_taxonomy.taxonomy = 'category'
        AND $wpdb->term_taxonomy.term_id IN ('" . $catid . "')
        AND $wpdb->posts.post_type = 'post'
        AND ($wpdb->posts.post_status = 'publish')
        AND DATE({$wpdb->posts}.post_date) > DATE( DATE_SUB( NOW(), INTERVAL " . $days . " DAY ) ) 
        GROUP BY $wpdb->posts.ID"
    );
    return count($posts) > 0 ? ' <span class="badge">' . count($posts) . '</span>' : FALSE;
}

Kommentieren