【WordPress】Popular Postsの出力をカスタマイズして任意の場所に表示する

人気記事をランキング表示するためのプラグインWordPress Popular Posts。大変便利なのですが、リスト表示時にサムネイル画像を出力すると、画像にリンク<a><img></a>が設定されてしまいます。

スマホからの操作を考えると、<a>タグをブロックにした<li><a>….画像、タイトル….</a></li>としたいところです。

以下、Popular Postsの<li>タグ内を自由にカスタイマイズする方法です。

環境
PHP
5.5
WordPress
4.2
Popular Posts
3.2.2

フィルターフックを利用したカスタマイズ

<li>タグ内の表示をカスタマイズするのでwpp_postをフックし、表示の定義をしていきます。

functions.php
add_filter('wpp_post', function($post_html, $p, $instance)
{
    // サムネイルのアタッチメント情報のIDを取得
    $thumb_id   = get_post_thumbnail_id($p->id);

    // サムネイルのHTMLテキストを取得
    // imgタグをカスタマイズしたいときは、wp_get_attachment_image_src($thumb_id, 'thumbnail'); 配列でsrc、sizeなどが返ってくる。
    $thumb_link = wp_get_attachment_image($thumb_id, 'post-thumbnail');

    // パーマリンク取得
    $perma_link = get_the_permalink($p->id);

    // タイトル取得
    $title      = $p->title;

    // 日付取得
    $date       = date(get_option('date_format'), strtotime($p->date));

    // 任意のカスタマイズ
    $format = '<li>
                    <a href="%s" title="%s">
                        <div class="thumbnail">
                            %s
                        </div>
                        <div class="content">
                            <p class="title">%s</p>
                            <p class="meta">%s</p>
                        </div>
                    </a>
                </li>';

    return sprintf($format, $perma_link, esc_attr($title), $thumb_link, $title, $date);
}, 10, 3);

以上でリスト表示のカスタイマイズは完了です。ただ、このままだと管理画面でも同様に反映されてしまいます。今回は$p->pageviewsでview数を取得していないので、管理画面でview数が確認できません。管理画面で従来通りに表示するために、上記のコードを修正します。

functions.php 修正
add_filter('wpp_post', function($post_html, $p, $instance)
{
    // 管理画面はカスタマイズしない
    if (is_admin()) {
        return $post_html;
    }

    // 以下、先ほどのコード
    ...............
}

これで、管理画面では従来通りのシンプルなリスト、Blog上ではカスタマイズしたリストが表示されるようになりました。

ユーザー定義関数でテンプレート内に表示

続いて、サイドバーやフッターなど、任意の場所に表示させるための関数を書いていきます。

Popular Posts を関数化する

先ほどカスタマイズしたリストを簡単に呼び出す関数を定義します。

functions.php
function get_my_popular_posts($limit = 5, $range = 'all')
{
    if (function_exists('wpp_get_mostpopular')) {
        wpp_get_mostpopular([
            'limit' => $limit,
            'range' => $range,
            'order_by' => 'views',
            'post_type' => 'post',
            'wpp_start' => '<section class="popular-posts"><h1 class="title">Popular posts</h1><ol class="popular-posts-list">',
            'wpp_end' => '</ol></section>'
        ]);
    }
}

関数の呼び出し

表示したいテンプレート内で以下のコードを書くことで、任意の場所に表示できるようになります。

index.php など
get_my_popular_posts(3, 'day');

// 定義したコードが展開される
<section class="popular-posts">
    <h1 class="title">Popular posts</h1>
    <ol class="popular-posts-list">
        <li>.........<li>
        <li>.........<li>
        <li>.........<li>
    </ol>
</section>

wp-adminフォルダをアクセス制限していると、カウントされない

集計に/wp-admin/admin-ajax.phpを使用しているので、wp-adminフォルダに.htaccessでアクセス制限している場合、うまくカウントされません。/wp-admin/.htaccessを以下のようにすることで正常にカウントがされます。

admin-ajax.phpにアクセス制限をかけない
Order deny,allow
Deny from all
Allow from 許可IP

<Files ~ "admin-ajax\.php">
    Order allow,deny
    Allow from all
</Files>

wpp_get_mostpopular だけでカスタマイズ可

この記事の公開後、プラグインをよく見てみると{thumb_img}というimgタグのみ出力するタグを発見しました。wpp_postをフックしなくても、wpp_get_mostpopular()だけでカスタイマイズが可能です。

function get_my_popular_posts($limit = 5, $range = 'all', $thumbnail_size = 150)
{
    if (function_exists('wpp_get_mostpopular')) {
        wpp_get_mostpopular([
            'limit' => $limit,
            'range' => $range,
            'order_by' => 'views',
            'post_type' => 'post',
            'stats_comments' => 0,
            'stats_author' => 0,
            'stats_date' => 0,
            'stats_views' => 0,
            'stats_date_format' => 'y.m.d',
            'thumbnail_width' => $thumbnail_size,
            'thumbnail_height' => $thumbnail_size,
            'wpp_start' => '<section class="popular-posts"><h1 class="title">Popular posts</h1><ol class="popular-posts-list">',
            'wpp_end' => '</ol></section>',
            'post_html' =>
            '<li>
                <a href="{url}" title="{text_title}">
                    <div class="thumbnail">
                        {thumb_img}
                    </div>
                    <div class="content">
                        <p class="title">{text_title}</p>
                        <p class="meta">{date}</p>
                    </div>
                </a>
            </li>'
        ]);
    }
}