内容が古くなっている可能性がありますのでご注意下さい。
以前開発した連載記事のページネーションのプラグインに、連載記事一覧を表示するウィジェットを追加した、Automatic Series Organizerプラグインを開発します。
仕様は極めて単純で、記事の投稿時に
series_idという決められた名前のカスタムフィールドを追加し、値の欄に連載名を記入しておくと、同じseries_idの値を持つ投稿を1つの連載記事としてまとめ、ページネーション
を表示するとともに、連載記事一覧をウィジェット
に表示するというものです。
プログラムの完全なリストは以下の通りです。
<?php /* Plugin Name: Automatic Series Organizer Plugin URI: http://midoriit.com/works/auto-series.html Description: Automaticallly organize pagination and widgets from series of posts. Version: 0.3 Author: Midori IT Office, LLC Author URI: http://midoriit.com/ License: GPLv2 or later Text Domain: auto-series Domain Path: /languages/ */ /* * Localization */ add_action( 'plugins_loaded', 'auto_series_loaded' ); function auto_series_loaded() { $ret = load_plugin_textdomain( 'auto-series', false, basename( dirname(__FILE__) ).'/languages/' ); } /* * List of Series Widget */ add_action( 'widgets_init', function() { register_widget("Series_Widget"); }); class Series_Widget extends WP_Widget { // Constructor function __construct() { parent::__construct( 'Series_Widget', __('Series List', 'auto-series'), array( 'description' => __( 'Show List of Series', 'auto-series' ), ) ); } // Widget option form function form($instance) { $title = esc_attr($instance['title']); echo '<p><label for="'.$this->get_field_id('title').'">'; echo __( 'Title:', 'auto-series' ); echo '<input class="widefat" id="'.$this->get_field_id('title').'" name="'. $this->get_field_name('title').'" type="text" value="'.$title.'" />'; echo '</label></p>'; } // Updaate widget option function update($new_instance, $old_instance) { $instance['title'] = strip_tags($new_instance['title']); return $instance; } // Output list of series function widget($args, $instance) { extract( $args ); echo $before_widget; if( $instance['title'] ) { echo $before_title.$instance['title'].$after_title; } else { echo $before_title.__( 'Series List', 'auto-series' ).$after_title; } $args = array( 'meta_key'=> 'series_id', 'orderby' => 'date', 'order' => 'ASC', 'nopaging' => true ); $series = array(); $posts = new WP_Query( $args ); if( $posts->found_posts > 1) { echo '<ul>'; while( $posts->have_posts() ) { $posts->the_post(); $series_id = get_post_meta(get_the_ID(), 'series_id', true); if( !in_array( $series_id, $series ) ) { echo '<li><a href="'.get_permalink().'">'.$series_id.'</a></li>'; array_push($series, $series_id); } } echo '</ul>'; } wp_reset_postdata(); echo $after_widget; } } /* * CSS for Pagination */ add_action( 'wp_print_styles', 'pagination_css' ); function pagination_css() { $css_file = plugins_url( 'auto-series.css', __FILE__ ); wp_enqueue_style( 'auto-series', $css_file ); } /* * Show Pagination */ function series_pagination() { global $post; $current = $post->ID; $meta_value = get_post_meta($current, 'series_id', true); if( $meta_value == '' ) { return; } $args = array( 'meta_key'=> 'series_id', 'meta_value' => $meta_value, 'orderby' => 'date', 'order' => 'ASC', 'nopaging' => true ); $pagination=''; $series = new WP_Query( $args ); if( $series->found_posts > 1) { $num = 1; $pagination = '<div class="series_pagination"><span>'.$meta_value.'</span> <span>'; while( $series->have_posts() ) { $series->the_post(); if( $current == get_the_ID() ) { if( $num > 9 ) { $pagination = $pagination.'<a class="current_post wide">'.$num.'</a>'; } else { $pagination = $pagination.'<a class="current_post">'.$num.'</a>'; } } else { $permalink = esc_url( apply_filters( 'the_permalink', get_permalink() ) ); if( $num > 9 ) { $pagination = $pagination.'<a class="wide" href="'.$permalink.'" title="'.get_the_title().'">'.$num.'</a>'; } else { $pagination = $pagination.'<a href="'.$permalink.'" title="'.get_the_title().'">'.$num.'</a>'; } } $num++; } $pagination = $pagination.'</span></div>'; } wp_reset_postdata(); echo $pagination; } ?>
まずは、一丁前にローカライゼーションをしています。
add_action( 'plugins_loaded', 'auto_series_loaded' ); function auto_series_loaded() { $ret = load_plugin_textdomain( 'auto-series', false, basename( dirname(__FILE__) ).'/languages/' ); }
日本語の言語リソース(auto-series-ja.po)は以下のように定義し、
msgid "Midori IT Office, LLC" msgstr "合同会社緑IT事務所" msgid "Title:" msgstr "タイトル:" msgid "Series List" msgstr "連載記事一覧" msgid "Show List of Series" msgstr "連載記事の一覧を表示します" msgid "Automaticallly organize pagination and widgets from series of posts." msgstr "連載記事のページネーションと連載一覧のウィジェットを自動的に構成します。"
以下のコマンドでバイナリファイル(auto-series-ja.mo)に変換します。
msgfmt -o auto-series-ja.mo auto-series-ja.po
msgfmtコマンドは、GetText for Windowsに含まれています。
次の
add_action( 'widgets_init', function() { register_widget("Series_Widget"); });
でウィジェットを登録します。ウィジェット本体は次のSeries_Widgetクラスです。ウィジェットのクラスは、WP_Widgetクラスを派生させて作ります。
コンストラクタ
function __construct() { parent::__construct( 'Series_Widget', __('Series List', 'auto-series'), array( 'description' => __( 'Show List of Series', 'auto-series' ), ) ); }
では、ウィジェット管理画面に表示される名前や説明を定義します。
次のform()メソッドは、ウィジェット管理画面でオプション設定をするためのフォームを表示します。
function form($instance) { $title = esc_attr($instance['title']); echo '<p><label for="'.$this->get_field_id('title').'">'; echo __( 'Title:', 'auto-series' ); echo '<input class="widefat" id="'.$this->get_field_id('title').'" name="'. $this->get_field_name('title').'" type="text" value="'.$title.'" />'; echo '</label></p>'; }
ここでは、ウィジェットのタイトルを設定できるようにしています。
次のupdate()メソッドで値を更新します。
function update($new_instance, $old_instance) { $instance['title'] = strip_tags($new_instance['title']); return $instance; }
HTMLのタグは取り除いています。
ウィジェットを表示するのはwidget()メソッドです。
function widget($args, $instance) { extract( $args ); echo $before_widget; if( $instance['title'] ) { echo $before_title.$instance['title'].$after_title; } else { echo $before_title.__( 'Series List', 'auto-series' ).$after_title; } $args = array( 'meta_key'=> 'series_id', 'orderby' => 'date', 'order' => 'ASC', 'nopaging' => true ); $series = array(); $posts = new WP_Query( $args ); if( $posts->found_posts > 1) { echo '<ul>'; while( $posts->have_posts() ) { $posts->the_post(); $series_id = get_post_meta(get_the_ID(), 'series_id', true); if( !in_array( $series_id, $series ) ) { echo '<li><a href="'.get_permalink().'">'.$series_id.'</a></li>'; array_push($series, $series_id); } } echo '</ul>'; } wp_reset_postdata(); echo $after_widget; }
ウィジェットの出力に先立ち$before_widgetを、最後に$after_widgetを出力しています。また、タイトルの前には$before_titleを、後には$after_titleを出力していますが、これらの変数はextract( $args );によって得られます。
WP_Query()でカスタムフィールドseries_idを持つ記事を検索し、series_idの値(つまり連載名)が、出力済み連載名を格納する配列$seriesに含まれていなければ、その記事へのリンク付きで連載名を出力し、連載名を配列$seriesに格納します。
記事の日付で昇順に検索しているため、連載名からリンクする記事は、その連載の最初の記事になります。また、古い連載から順に表示されます。
以降は、ページネーションのためのCSSの処理と、ページネーションを出力するseries_pagination()メソッドの定義です。これらは、以前開発した連載記事のページネーションのプラグインと基本的には同じです。但し、カスタムフィールドの名前がseries_idに変わっています。
今回作成したプラグインはGitHubからダウンロードできます。
https://github.com/midoriit/auto-series