Bogoでアーカイブの投稿数のカウントを言語毎に行う

前記事の通りカテゴリーについては言語毎の投稿数カウントが出来るようになったのでアーカイブリストについても同じように考えてみた。カテゴリーで wp_list_categories をフックしたように wp_get_archives をフックすれば良いのかと思ったが、どう言うわけか add_filter (‘wp_get_archives’) は効かないようだった。Bogo使用者はカテゴリー同様の問題を抱えている筈だが残念ながら検索してもアーカイブ記事数についての解決策は見つからない。ウィジェットのソースコードを直接いじる等方法を考えてソースを開いて見たがどうも自分の手に負えるものではない。

そもそも任意のフィルタの掛けられない wp_get_archives を使わず、自由度の高い WP_Query を最初から使ってアーカイブリストを自作した方が早いのではと考え始め色々検索してみると、「特定カテゴリーのアーカイブリストを作りたい」という動機からwp_get_archivesを使わない自作アーカイブリストのソースを共有している方が何人も見つかった。プルダウンリストにするのは難しいのではと思ったがそれすらも意外に簡単なコードで実現できるようだ。コードのシンプルさと説明のわかりやすさを理由に、こちらのブログを選び手法をコピーさせてもらうことにする。https://oz-style.com/train/941/

通常のアーカイブウィジェット同様にサイドバーに表示したいので、テキストウィジェットに PHP コードを書く。当サイトでは functions.php に以下のコードを追加してウィジェットでphpが動く様にしてある。

// ウィジェットでphpコードを実行させる。
function widget_text_exec_php( $widget_text ) {
if( strpos( $widget_text, '<' . '?' ) !== false ) {
ob_start();
eval( '?>' . $widget_text );
$widget_text = ob_get_contents();
ob_end_clean();
}
return $widget_text;
}
add_filter( 'widget_text', 'widget_text_exec_php', 99 );

(追記:2024-10-02: このコードを使うと warning がずっと出てエラーログが一杯になっていた。画面上は問題無く動いているように見える。eval 内で使用している $post が未定義のため、という。global $post; を eval( 文の前の行に追記すると warning は出なくなるようだ。しかし ChatGPT によると「ウィジェット内でPHPコードを実行させるためのコードとして、eval()を使用する方法はありますが、これは非常にリスクが高いため、推奨されません。」とのことで、そもそもこういった手法はリスクがあるらしい。代わりに PHP Code Widget 等のプラグインを使った方がよいと。しかしこのプラグインも2年半もアップデートされておらず躊躇する。他にJIG作者Firsh氏お勧めの Code Snippets プラグインもあるのでそちらを試したところ、なんと!サイト全体が落ちるほど致命的なエラーが。評判の良いプラグインだし当方固有の原因があるのだと思うが、あまりに被害が大きかったのでもう一度試す気になれない。考えてみると当サイトではショートコードでPHPが動くようにしてあるので、テキストウィジェットにショートコードを書いて、下のPHPコードは別途 テーマフォルダに保存して呼び出すようにした。これによって eval の使用を回避できた。)

オリジナルのコードは特定カテゴリーの月毎アーカイブを作成するものなので、カテゴリー関係の記述は全て削除し、代わりに言語コードを指定する 'lang' => $lang というパラメータを入れて WP_Query で検索する。クリックした際に飛ぶ、月毎アーカイブのURL はパーマリンク構造別に変えなければならないとのこと。当サイトの場合は投稿名を使っているので、URLは https://www.1wishyouwerehere.com/2024/9 の様になるように書き換える。試行錯誤した結果、以下のようなコードで純正アーカイブウィジェットと同じように動いてくれている。

<?php
$lang = get_locale();
$args = array(
'lang' => $lang,
'posts_per_page' => -1 //現在の言語の記事を全部出力
);
$the_query = new WP_Query( $args ); //上記アーカイブクエリを実行
?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<?php
global $post;
$archive_list[ get_the_time( 'Y/n', $post->ID ) ][] = $post->post_title;//年月ごとに記事情報を格納
?>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>

<?php if( $archive_list ) : ?>
<select id="hoge"><!-- hogeは任意の名前:後述のJavaScriptで必要です -->
<option>月を選択</option>
<?php foreach( $archive_list as $year_month => $archive ) :
$year_month_arr = explode( '/', $year_month );
?>
<option value="<?php echo esc_url( home_url( ''.$year_month) ) ?>">
<!-- 現在の言語のアーカイブのURLを value に格納 -->
<?php echo $year_month_arr[0].'年'.$year_month_arr[1].'月' ?> [<?php echo count( $archive ) ?>]
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>


<?php
echo "
<script>
jQuery(function($) {
$('#hoge').change(function() {
if ($(this).val() != '') {
window.location.href = $(this).val();
}
});
});
</script>";
?>

実現出来たウィジェットの見た目はこの通り。英語翻訳のある月も投稿数表示は [1] となって正しく日本語の記事のみをカウントしている。

タイトルや日付表示が日本語なのでこのままでは英語ページでは使用出来ない。コードをコピーしてもう一つ別の英語用のテキストウィジェットを作りタイトルを英語に書き換え、Bogoのオプションにて日本語ページと英語ページそれぞれで別のウィジェットを表示させる。月表示は英語の場合 2024/8 だけだと味気ないのでこちらのサイトを参考に https://www.php.cn/ja/faq/717862.html 数字を英語の月名に書き換えている。

<?php
$lang = get_locale();
$args = array(
'lang' => $lang,
'posts_per_page' => -1 //現在の言語の記事を全部出力
);
$the_query = new WP_Query( $args ); //上記アーカイブクエリを実行
?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<?php $archive_list[ get_the_time( 'Y/n', $post->ID ) ][] = $post->post_title;//年月ごとに記事情報を格納
?>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>

<?php if( $archive_list ) : ?>
<select id="hoge"><!-- hogeは任意の名前:後述のJavaScriptで必要です -->
<option>Select Month</option>
<?php foreach( $archive_list as $year_month => $archive ) :
$year_month_arr = explode( '/', $year_month );
?>
<option value="<?php echo esc_url( home_url( $year_month ) ) ?>">
<?php $month_name = date('F', strtotime("1-$year_month_arr[1]-2022"));?>
<?php echo $year_month_arr[0].'-'.$month_name.' ' ?> [<?php echo count( $archive ) ?>]
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>

<?php
echo "
<script>
jQuery(function($) {
$('#hoge').change(function() {
if ($(this).val() != '') {
window.location.href = $(this).val();
}
});
});
</script>";
?>

英語版の見た目を示す。2021年9月のように日本語版の記事しか無い月は表示されておらずカウントが正しい事が確認出来る。

このように思ったよりも簡単なコードでプルダウン式のアーカイブリストをサイドバーに表示することが出来た。純正アーカイブウィジェットではどうしてあれだけ複雑なコードが必要なのか逆に不思議であるが、おそらくこちらの手法だと重い等、別の問題があるのだろう。今回も複数のプログラマの方のアイデアと知恵をお借りしてやりたいことが実現出来た。いつもながら感謝である。

コメント

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