Cocoonの人気記事popular_listでタグ指定を可能にする方法

Cocoon

このサイトはWordPressのテーマ「Cocoon」を使っています。

人気記事表示機能popular_listでタグ指定での絞り込みを行えるようソースコード修正して対応したので、やり方を載せておきます。

対応すると下記ツイートの通り人気記事をタグで絞り込むことができます。

popular_listでタグ指定を可能にする方法

子テーマ側に既存関数を修正実装して実現します。
 親テーマ側に影響を与えないようにするため。

既存の実装は、popular_entries_shortcodeとgenerate_popular_entries_tagでショートコードから各属性の値を取り出し、get_access_ranking_recordsでWordPressデータベースから記事情報を取り出しています。

呼び出し構造はこんな感じ。

popular_entries_shortcode
 generate_popular_entries_tag
  get_access_ranking_records



↑の3関数は既に親テーマ側に実装されていますが、いずれも

if ( !function_exists( 'get_access_ranking_records' ) ):
function get_access_ranking_records(略

というように子テーマ側での関数カスタマイズが考慮済なので、
 ・親テーマから関数を子テーマのfunctions.phpにコピー
 ・必要部分を修正
というやり方が最も楽に対応できると思います。

実際にやってみた

ここから実際のコードを見ながら修正していきましょう。
※Cocoonは現在も更新がされていますが、それに伴いこれらのソースコードが修正されることがあります。この記事で紹介したコードと一致しない可能性があります。ご注意ください。



まずpopular_entries_shortcodeです。
差分はdiff -ruNっぽく +- で表示しています。
実際のソースコードには含めないので注意。

まあ簡単ですね。
cats属性と同様にtags属性を指定できるようにします。
catsとtags両方指定された場合はcats優先とします。

if ( !function_exists( 'popular_entries_shortcode' ) ):
function popular_entries_shortcode($atts) {
  extract(shortcode_atts(array(
    'days' => 'all',
    'count' => 5,
    'type' => 'default',
    'rank' => 0,
    'pv' => 0,
    'cats' => 'all',
    'children' => 0,
+    'tags' => 'all',
    'bold' => 0,
    'arrow' => 0,
    'class' => null,
  ), $atts, 'popular_list'));
  $cat_ids = array();
  if ($cats && $cats != 'all') {
    $cat_ids = explode(',', $cats);
  }
+  else if ($tags && $tags != 'all') {
+    $tag_ids = explode(',', $tags);
+  }
  $atts = array(
    'days' => $days,
    'entry_count' => $count,
    'entry_type' => $type,
    'ranking_visible' => $rank,
    'pv_visible' => $pv,
    'cat_ids' => $cat_ids,
    'children' => $children,
+    'tag_ids' => $tag_ids,
    'bold' => $bold,
    'arrow' => $arrow,
    'class' => $class,
  );
  ob_start();
  generate_popular_entries_tag($atts);
  //_v($atts);
  //generate_popular_entries_tag($days, $count, $type, $rank, $pv, $categories);
  $res = ob_get_clean();
  return $res;
}
endif;



お次はgenerate_popular_entries_tagです。
こちらも単純にtag_ids/exclude_tag_idsによるタグ指定を追加しただけ。

//人気ランキングリストの取得
if ( !function_exists( 'generate_popular_entries_tag' ) ):
function generate_popular_entries_tag($atts){
  extract(shortcode_atts(array(
    'days' => 'all',
    'entry_count' => 5,
    'entry_type' => ET_DEFAULT,
    'ranking_visible' => 0,
    'pv_visible' => 0,
    'cat_ids' => array(),
    'children' => 0,
+    'tag_ids' => array();
    'exclude_post_ids' => array(),
    'exclude_cat_ids' => array(),
+    'exclude_tag_ids' => array(),
    'bold' => 0,
    'arrow' => 0,
    'class' => null,
  ), $atts));

-  $records = get_access_ranking_records($days, $entry_count, $entry_type, $cat_ids, $exclude_post_ids, $exclude_cat_ids, $children);
+  $records = get_access_ranking_records($days, $entry_count, $entry_type, $cat_ids, $tag_ids, $exclude_post_ids, $exclude_cat_ids, $exclude_tag_ids, $children);
(略)



これで最後。
get_access_ranking_recordsを修正します。

//アクセスランキングを取得
if ( !function_exists( 'get_access_ranking_records' ) ):
-function get_access_ranking_records($days = 'all', $limit = 5, $type = 'post', $cat_ids = array(), $exclude_post_ids = array(), $exclude_cat_ids = array(), $children = 0){
+function get_access_ranking_records($days = 'all', $limit = 5, $type = 'post', $cat_ids = array(), $tag_ids = array(), $exclude_post_ids = array(), $exclude_cat_ids = array(), $exclude_tag_ids = array(), $children = 0){
(略)

  //アクセスキャッシュを有効にしている場合
  if (is_access_count_cache_enable()) {
(略)
    $expids = implode(',', $exclude_post_ids);
    $excats = implode(',', $exclude_cat_ids);
+    $extags = implode(',', $exclude_tag_ids);
    $type = get_accesses_post_type();
-    $transient_id = TRANSIENT_POPULAR_PREFIX.'?days='.$days.'&limit='.$limit.'&type='.$type.'&cats='.$cats.'&children='.$children.'&expids='.$expids.'&excats='.$excats;
+    $transient_id = TRANSIENT_POPULAR_PREFIX.'?days='.$days.'&limit='.$limit.'&type='.$type.'&cats='.$cats.'&tags='.$tags.'&children='.$children.'&expids='.$expids.'&excats='.$excats.'&extags='.$extags;
(略)
  //カテゴリを指定する場合
  if (is_ids_exist($cat_ids) || is_ids_exist($exclude_cat_ids)) {
(略)
+  //タグを指定する場合
+  else if (is_ids_exist($tag_ids) || is_ids_exist($exclude_tag_ids)) {
+    global $post;
+    $term_relationships = $wpdb->term_relationships;
+    $term_taxonomy = $wpdb->term_taxonomy;
+    $joined_table = 'terms_accesses';
+    //タグ指定
+    if (is_ids_exist($tag_ids)) {
+      $tag_ids = implode(',', $tag_ids);
+      //$where .= " AND {$term_relationships}.term_taxonomy_id IN ({$tag_ids}) ".PHP_EOL;
+      $where .= " AND {$term_taxonomy}.term_id IN ({$tag_ids}) ".PHP_EOL;
+    }
+    //除外タグ指定
+    if (is_ids_exist($exclude_cat_ids)) {
+      //空の配列を取り除く
+      $exclude_tag_ids = array_filter($exclude_tag_ids, "strlen");
+      //カンマ区切りにする
+      $ex_tag_ids = implode(',', $exclude_tag_ids);
+      $ex_tag_ids = preg_replace('/,$/', '', $ex_tag_ids);
+      $where .= " AND {$term_relationships}.term_taxonomy_id NOT IN ({$ex_tag_ids}) ".PHP_EOL;
+    }
+
+    $where .= " AND {$term_taxonomy}.taxonomy = 'post_tag' ".PHP_EOL;
+(略 - 前記カテゴリー指定時のコードと同じ)
  } else {
    $query = "
      SELECT {$access_table}.post_id, SUM({$access_table}.count) AS sum_count
        FROM {$access_table} $where
        GROUP BY {$access_table}.post_id
        ORDER BY sum_count DESC
    ";
    //1回のクエリで投稿データを取り出せるようにケーブル結合クエリを追加
    $query = wrap_joined_wp_posts_query($query, $limit);
  }



追加コードが長いですが、以下のようにコード修正しただけです。
 マジメに設計するのがだるかったので、手抜き。

修正前

//カテゴリを指定する場合
if (is_ids_exist($cat_ids) || is_ids_exist($exclude_cat_ids)) {
(カテゴリ指定時のコード)
} else {
(カテゴリ指定しない時のコード)
}


修正後

//カテゴリを指定する場合
if (is_ids_exist($cat_ids) || is_ids_exist($exclude_cat_ids)) {
(カテゴリ指定時のコード)
+else if (is_ids_exist($tag_ids) || is_ids_exist($exclude_tag_ids)) {
+ (タグ指定時のコード)

} else {
(カテゴリ、タグ指定しない時のコード)
}



taxonomy指定時にカテゴリの場合はcategoryとしますが、タグの場合はpost_tagとします。
こんな感じ。

$where .= " AND {$term_taxonomy}.taxonomy = 'post_tag' ".PHP_EOL;



WordPress記事は全てデータベースに入っていてPHPから中身を取り出せるようになっています。
詳細はこのページなどを見ていただくとわかります。



すべてうまく行っていれば、以下のようなショートコードでタグ指定ができます。

[popular_list count="2" type="border_square" tags="271"]



終わりに

いかがでしたか。

私の使い方ではどうしてもタグでの人気記事絞り込みをやりたかったので、実装しました。

この記事が役に立ったら嬉しいです!

この記事を書いた人
yatch

組込ソフト歴15年の外資系エンジニア。
前職で組込Linuxを使った商品設計/品質確保の業務に従事。
Raspberry Piが好き。
株式投資で年100万円を稼ぐ。
香港人妻と国際結婚。

Please follow me
CocoonWordpress
Please follow me
世界Linux新聞

Comments

タイトルとURLをコピーしました