『東日本大震災』関連情報のまとめサイト

Google Crisis Response 東日本大震災(東北地方太平洋沖地震)(Google)
震災に関する情報源や、行方不明者情報の収集と検索を行う『パーソンファインダー』があります。Google Checkout による日本赤十字社への義援金もこちらから出来ます。
地震・津波災害に関する情報(Yahoo!Japan)
震災関連情報源へのリンク集。天気情報コンテンツの中にありますが、ライフライン、交通、震災関連の迷惑メール情報など多岐に渡っています。

2009年12月13日 日曜日

WordPressのアップグレードとユーザー権限

Filed under: WordPress,ハック
タグ:, , ,
時間:17時43分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

WordPress の自動アップグレードをしようとすると「このブログのプラグインを更新するための十分な権限がありません。」となってしまうので調査をしていたのですが、原因が判明しましたので記事にします。

まず、調査対象のバージョンは2.8.4です。2.6系から直接アップグレードしたもので、一番初めは2.0ME系でした。接頭辞は wp です。

権限がないといわれてしまう原因ですが、そのまま権限が与えられていないためです。管理者で作業しているので普通はそんなことはありえないのですが、どうやらアップグレード時に行われるデータベースの更新に問題があったようです。

権限情報の記録場所

権限の情報はオプションとしてデータベース上に記録されていて、次のSQLで見つけることができます。

SQL:
  1. SELECT `option_name`,`option_value` FROM `wp_options` WHERE `option_name` = 'wp_user_roles';

このオプションの値はPHPでシリアライズしたもので、管理者や編集者といったロール(役割)ごとに権限を配列の形で格納しています。wp-includes/capabilities.php の冒頭には、次のように書かれています。

PHP:
  1. * The role option is simple, the structure is organized by role name that store
  2.  * the name in value of the 'name' key. The capabilities are stored as an array
  3.  * in the value of the 'capability' key.
  4.  *
  5.  * <code>
  6.  * array (
  7.  *    'rolename' => array (
  8.  *      'name' => 'rolename',
  9.  *      'capabilities' => array()
  10.  *    )
  11.  * )
  12.  * </code>

権限の記録は20行目の配列で、権限名がキーでその権限があるかどうかを示す真偽値が値となります。

現状の確認

さて、ここまでを踏まえて実際にどのように権限情報が記録されているかを確認します。PHPで表示させるプログラムを書いてみてもいいのですが、面倒なのでもっと手っ取り早い方法を使いました。

前述したSQLでオプション値を取得し、それをテキストエディタ(私は秀丸エディタを使いました)に貼り付けます。このままではすべてが1行に繋がってわかりにくいので、{ と } と ; の後ろにテキスト置換で改行を入れました。
こうすると、権限名と真偽値が交互になってわかりやすくなります。

準備ができたら権限名を探します。自動アップグレードのアドレスから、きっかけとなるコードは wp-admin/update-core.php であることがわかりますので確認します。

冒頭の12行目に次のようにあります。

PHP:
  1. if ( ! current_user_can('update_plugins') )
  2.     wp_die(__('You do not have sufficient permissions to update plugins for this blog.'));

update_plugins という名前の権限を確認して、権限がなければメッセージを表示して終了するという処理ですね。早速この権限名を先ほど準備したテキストデータで探しますと、見当たりません。この名前をキーとする配列要素がないということになりますので、PHPでは真偽値は false となります。

念のため新規に同じバージョンのインストールをしてみた場合で確認したところ、しっかりとこの権限については true となっていました。

なぜこうなったのか

こうなると原因が気になります。アップグレードスクリプトの権限処理をするところを探してみました。アップグレードインストールをするときのファイル名を基点にしてたどってみたところ、wp-admin/includes/upgrade.php に定義されている upgrade_all() という関数の中で、WordPressデータベースのバージョンによってアップグレード用の関数を呼び出していることがわかりました。

PHP:
  1. /**
  2. * Functions to be called in install and upgrade scripts.
  3. *
  4. * {@internal Missing Long Description}}
  5. *
  6. * @since unknown
  7. */
  8. function upgrade_all() {
  9.     global $wp_current_db_version, $wp_db_version, $wp_rewrite;
  10.     $wp_current_db_version = __get_option('db_version');
  11.  
  12.     // We are up-to-date.  Nothing to do.
  13.     if ( $wp_db_version == $wp_current_db_version )
  14.         return;
  15.  
  16.     // If the version is not set in the DB, try to guess the version.
  17.     if ( empty($wp_current_db_version) ) {
  18.         $wp_current_db_version = 0;
  19.  
  20.         // If the template option exists, we have 1.5.
  21.         $template = __get_option('template');
  22.         if ( !empty($template) )
  23.             $wp_current_db_version = 2541;
  24.     }
  25.  
  26.     if ( $wp_current_db_version <6039 )
  27.         upgrade_230_options_table();
  28.  
  29.     populate_options();
  30.  
  31.     if ( $wp_current_db_version <2541 ) {
  32.         upgrade_100();
  33.         upgrade_101();
  34.         upgrade_110();
  35.         upgrade_130();
  36.     }
  37.  
  38.     if ( $wp_current_db_version <3308 )
  39.         upgrade_160();
  40.  
  41.     if ( $wp_current_db_version <4772 )
  42.         upgrade_210();
  43.  
  44.     if ( $wp_current_db_version <4351 )
  45.         upgrade_old_slugs();
  46.  
  47.     if ( $wp_current_db_version <5539 )
  48.         upgrade_230();
  49.  
  50.     if ( $wp_current_db_version <6124 )
  51.         upgrade_230_old_tables();
  52.  
  53.     if ( $wp_current_db_version <7499 )
  54.         upgrade_250();
  55.  
  56.     if ( $wp_current_db_version <7796 )
  57.         upgrade_251();
  58.  
  59.     if ( $wp_current_db_version <7935 )
  60.         upgrade_252();
  61.  
  62.     if ( $wp_current_db_version <8201 )
  63.         upgrade_260();
  64.  
  65.     if ( $wp_current_db_version <8989 )
  66.         upgrade_270();
  67.  
  68.     if ( $wp_current_db_version <10360 )
  69.         upgrade_280();
  70.  
  71.     maybe_disable_automattic_widgets();
  72.  
  73.     update_option( 'db_version', $wp_db_version );
  74.     update_option( 'db_upgraded', true );
  75. }

呼び出されている upgrade_***() という関数の中では、さらに必要に応じて populate_roles_***() という関数を呼び出しています。

この関数の定義は wp-admin/includes/schema.php にあり、そこではまさにロールごとに権限の追加を行っていました。

次のSQLでデータベースバージョンを確認して呼び出されるはずの関数の処理を確認してみました。

SQL:
  1. SELECT `option_name`,`option_value` FROM `wp_options` WHERE `option_name` = 'db_version';

2.6の新規インストール環境では8201となっていましたので、upgrade_all() の342~346行目が該当します。呼び出される関数の定義は次のとおり。

PHP:
  1. /**
  2. * Execute changes made in WordPress 2.7.
  3. *
  4. * @since 2.7.0
  5. */
  6. function upgrade_270() {
  7.     global $wpdb, $wp_current_db_version;
  8.  
  9.     if ( $wp_current_db_version <8980 )
  10.         populate_roles_270();
  11.  
  12.     // Update post_date for unpublished posts with empty timestamp
  13.     if ( $wp_current_db_version <8921 )
  14.         $wpdb->query( "UPDATE $wpdb->posts SET post_date = post_modified WHERE post_date = '0000-00-00 00:00:00'" );
  15. }
  16.  
  17. /**
  18. * Execute changes made in WordPress 2.8.
  19. *
  20. * @since 2.8.0
  21. */
  22. function upgrade_280() {
  23.     global $wp_current_db_version;
  24.  
  25.     if ( $wp_current_db_version <10360 )
  26.         populate_roles_280();
  27. }

PHP:
  1. /**
  2. * Create and modify WordPress roles for WordPress 2.7.
  3. *
  4. * @since 2.7.0
  5. */
  6. function populate_roles_270() {
  7.     $role =& get_role( 'administrator' );
  8.  
  9.     if ( !empty( $role ) ) {
  10.         $role->add_cap( 'install_plugins' );
  11.         $role->add_cap( 'update_themes' );
  12.     }
  13. }
  14.  
  15. /**
  16. * Create and modify WordPress roles for WordPress 2.8.
  17. *
  18. * @since 2.8.0
  19. */
  20. function populate_roles_280() {
  21.     $role =& get_role( 'administrator' );
  22.  
  23.     if ( !empty( $role ) ) {
  24.         $role->add_cap( 'install_themes' );
  25.     }
  26. }

populate_roles_***() で追加している権限を確認したところ、3つとも登録されていました。今度はさかのぼって確認してみると、populate_roles_260() で追加される2つの権限のみがありませんでした。しかもその1つは今回問題となっている update_plugins です。

どうやらここで失敗していたようです。

PHP:
  1. /**
  2. * Create and modify WordPress roles for WordPress 2.6.
  3. *
  4. * @since 2.6.0
  5. */
  6. function populate_roles_260() {
  7.     $role =& get_role( 'administrator' );
  8.  
  9.     if ( !empty( $role ) ) {
  10.         $role->add_cap( 'update_plugins' );
  11.         $role->add_cap( 'delete_plugins' );
  12.     }
  13. }

修復方法

原因まで判明したので、権限情報の修復を行います。直接書き換えてもいいのですが、間違えると面倒なので簡単なプログラムを作りました。

データを抽出して権限を追加し、再度シリアライズして表示するだけ。表示されたテキストデータをデータベース用の管理画面(ここのサーバーは phpMyAdmin が使えるのでそれを使いました)から直接反映させました。

このプログラムは自由に使っていただいてかまいませんが、何かあったときの補償はできませんので自己責任でお願いします。

PHP:
  1. <?php
  2. header('Content-type: text/plain;charset=UTF-8');
  3. $link = mysql_connect('データベースサーバー', 'ユーザー', 'パスワード');
  4.  
  5. if ( $link )
  6. {
  7.     mysql_set_charset('utf8');
  8.     if ( mysql_select_db('データベース') )
  9.     {
  10.         $sql = "SELECT `option_name`,`option_value` FROM `wp_options` WHERE `option_name` = 'wp_user_roles'";
  11.         if ( $res = mysql_query($sql) )
  12.         {
  13.             if ( $rows = mysql_fetch_assoc($res) )
  14.             {
  15.                 $rol_data = unserialize($rows['option_value']);
  16.                 $rol_data['administrator']['capabilities']['update_plugins'] = true;
  17.                 $rol_data['administrator']['capabilities']['delete_plugins'] = true;
  18.                 print serialize($rol_data);
  19.             }
  20.         }
  21.         else
  22.         {
  23.             print mysql_error();
  24.         }
  25.     }
  26.     else
  27.     {
  28.         print mysql_error();
  29.     }
  30. }
  31. else
  32. {
  33. }
  34. ?>

というわけで、無事自動アップグレードの画面を拝むことができました。

Comments (1)

2009年9月7日 月曜日

AmazonLink 2.0.0 beta2 リリース

Filed under: AmazonLink
タグ:,
時間:23時30分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

すでに昨夜の話になってしまいますが、AmazonLink 2.0.0 beta2 をリリースしました。ダウンロードは、いつものようにWordPress Plugins/JSeriesのサイトからどうぞ。

ページ投稿画面での検索フォーム追加や、AmazonLink コードの変更などをしています。また、アップグレードが進むとの予測から、急いで WordPress 2.8.4 での動作検証も行いました。2.8系は投稿画面の幅が狭くなっているため、ボタンなどのレイアウトも少し変えてあります。

AmazonLinkコードの変更ですが、商品ごとにテンプレートを変える機能を思いついたためです。テンプレートは複数行になる可能性が高いため、属性値とするには不向きです。そのため、コードに挟むことができるようにしました。

なお、内部で変換処理を行っているので、今までの形式も使用することはできます。

ASIN は Amazon Standard Item Number の略で、Amazon の商品コードです。

以前の形式
CODE:
  1. [amazon]ASIN[/amazon]

新しい形式
CODE:
  1. [amazon asin="ASIN"][/amazon]
  2. [amazon asin="ASIN" /]

現在は個別のテンプレートには対応できていませんが、TODOには入れておこうと思います。手を出しすぎると切りがないので、正式リリースまでは触らない予定です。

Comments (1)

2009年9月6日 日曜日

WordPress を最新版にアップグレードしてください

Filed under: WordPress
タグ:, , ,
時間:15時10分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

現在、WordPress 2.8.4 未満に存在するセキュリティーホールをターゲットとした不正アクセスが行われているようです。該当バージョンを使用している方はできるだけ早めにアップグレードを行ってください。当サイトも、先ほど作業を行いました。

不正アクセスが行われているかどうかの判別については、コリスさんがまとめてくださっています。

また、この記事に書かれている「WordPress Permalink & Rss problems」を、山本さくらさんが和訳した物を公開されています。

WordPress | 日本語 には、本家ブログの記事「How to Keep WordPress Secure」を訳したものが掲載されました。

これらの記事を参考に、不正アクセスが行われていないかどうかの確認と最新版へのアップグレードを行ってください。アップグレード済みであっても、念のため不正アクセスの有無の確認は行ってほうがいいと思います。

コリスさんの記事にもありますが、不正アクセスの形跡があった場合はデータベースも不正アクセスされている可能性があるとのこと。その場合はこのセキュリティホールが発見されるよりも十分古いバックアップに戻す以外は対策はなさそうです。
そうならないためにも、できるだけ早くアップグレードを行ってください。

2009年9月6日 15時40分 追記

それでもアップグレードを渋っている方には、Naoさんによる次の記事をどうぞ。

2009年8月7日 23時10分 追記

山本さくらさんが、攻撃内容について詳しく書かれています。

古いバージョンを使用しているところはすべてアウトと言うわけではないようですね。
とは言うものの、まだ見つかっていないセキュリティーホールによって条件がゆるくなる可能性は十分あります。残念ながら「バグのないプログラムはない」のです。

Comments (2)

2009年9月5日 土曜日

AmazonLink のテンプレート

Filed under: AmazonLink
タグ:, ,
時間:16時17分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

8月14日に公開となった AmazonLink 2.0.0 beta では、テンプレート機能によってある程度自由にデザインを作ることができるようになっています。

管理画面上の説明でどこまで伝わるのか自信がないので、現在このサイトで使用しているテンプレートを公開しようと思います。

CODE:
  1. <table class="amazonLink" width="468">
  2.     <tr>
  3.         <td colspan="2">
  4.             <strong><span class="itemName"><a href="[DETAIL_PAGE_URL]">[ITEM_NAME]</a></span>[IF_AUTHOR/] <span class="author">[AUTHOR]</span>[/IF_AUTHOR]</strong><br />
  5.             [IF_PUBLISHER/]発売:[PUBLISHER][IF_RELEASE_DATE/] [RELEASE_DATE][/IF_RELEASE_DATE] [/IF_PUBLISHER]
  6.             販売数ランク:[SALES_RANK]
  7.         </td>
  8.     </tr>
  9.     <tr>
  10.         <td rowspan="3" width="[MEDIUM_IMAGE_WIDTH]" valign="top">
  11.             <a href="[DETAIL_PAGE_URL]"><img src="[MEDIUM_IMAGE_URL]" width="[MEDIUM_IMAGE_WIDTH]" height="[MEDIUM_IMAGE_HEIGHT]" alt="『[ITEM_NAME]』の商品写真" /></a>
  12.         </td>
  13.         <td valign="top">
  14. [IF_CREATOR/]
  15.             <ul class="creator">
  16. [CREATOR/]        <li>[CREATOR_ROLE][CREATOR_NAME]</li>
  17. [/CREATOR]
  18.             </ul>
  19. [/IF_CREATOR]
  20.         </td>
  21.     </tr>
  22.         <td valign="top">
  23. [IF_REVIEW/]
  24. 平均評価:<img src="/wp-content/themes/custom01/images/evaluation_[AVERAGE_RATING].gif" width="59" height="11" alt="[AVERAGE_RATING]">
  25.             <ul class="evaluation">
  26. [REVIEW/]            <li><img src="/wp-content/themes/custom01/images/evaluation_[REVIEW_RATING].0.gif" width="59" height="11" alt="評価:[REVIEW_RATING]"> [REVIEW_SUMMARY]</li>
  27. [/REVIEW]
  28.             </ul>
  29. [/IF_REVIEW]
  30.         </td>
  31.     </tr>
  32.     <tr>
  33.         <td valign="bottom">
  34.             <span class="powerdBy">[POWERD_BY]</span>
  35.         </td>
  36.     </tr>
  37. </table>

テーブルの幅が固定であったりしますが、別のサイトにも流用可能かと思います。WordPress や プラグイン同様に GPL ライセンスとしますので、ご自由にお使いください。

Comments (2)

2009年8月14日 金曜日

AmazonLink 2.0.0 beta リリース

Filed under: AmazonLink,アフィリエイト
タグ:, ,
時間:18時33分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

JSeries サイトの更新はまだですが、先ほど AmazonLink 2.0.0 beta をリリースしました。
現在 SourceForge.JP の以下のアドレスからダウンロードができるようになっています。

http://sourceforge.jp/projects/wppluginsj/downloads/43119/AmazonLink-2.0.0beta.zip/

19時25分追記

Jseries サイトを更新しました。メジャーバージョンアップと言うことで、新規にページを作成してあります。
http://wppluginsj.sourceforge.jp/amazonlink2/

Comments (2)

2009年8月9日 日曜日

AmazonLink 2.0 beta もうすぐ・・・

Filed under: AmazonLink
タグ:, , , ,
時間:18時28分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

平日は忙しくてまったく時間はないわ、休日は平日できてないことをやってると終わってしまうわでほぼ停止状態でしたが、昨日と今日で AmazonLink を Amazon の Product Advertising API に対応させました。

ついでに WordPress 2.7 にも対応させたので、近いうちにベータ版として公開することができそうです。2.8 は未テストなので、対象外の予定です。

また、サイドバーでやってたアンケートの結果を元に、今回から動作環境条件として PHP 5.1 以上とします。これにより、Amazon とのやり取りの処理が PHP のネイティブ関数を使えるようになるので処理が早くできるはずです。PHP 4.x の環境しかない方はごめんなさい。

ベータ版として公開したあとの予定ですが、プログラムの整理と PHP 5.x らしい書き方への変更をしたいと思っています。一緒に WordPress 2.8 にも対応したいですね。

今後も使っていただけるという方は、Product Advertising API アカウントの取得をしておいてください。8月15日以降は、アカウントがないと投稿画面での検索ができなくなります。

Comments (0)

2009年6月14日 日曜日

ClickComments がサービス終了

Filed under: WordPress
タグ:,
時間:19時27分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

アイコンをクリックするだけで感想を投稿できる ClickComments というサービスを利用していましたら、いつの間にか終了してしまっていました。

専用の WordPress プラグインで記事の下に表示していたのですが、いつの間にか表示されない状態に。一時的な問題かと思って様子を見ていましたが、いつまでも直らないので調べてみたら表示のためにサービスサイトから読み込む JavaScript ファイルが Not found。

サービスサイトを見に行ってみると、長期のサービスをサービスを続ける余裕がないために無期限に終了するというメッセージが表示されていました。

Unfortunately, postreach ClickComments has been shut down indefinitely because we can no longer afford to keep it running.

クリックして下さる方もいらしたので残念ですが、プラグインを停止しました。
同じようなサービスをご存知でしたら、ぜひコメントをください。

Comments (0)

2009年5月10日 日曜日

”Amazon アソシエイト Web サービス”が”Product Advertising API”に

Filed under: AmazonLink,アフィリエイト,プログラミング
タグ:, , , , ,
時間:17時46分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録
Popularity: 22%
by Popularity Contest 日本語版

Amazon.co.jp からいろいろな情報を取得することができる”Amazon アソシエイト Web サービス”というサービスがありますが、”Product Advertising API”という名称に変わるとのことです。そして、情報のリクエストには署名による認証が必要になるとのこと。

拙作 WordPress プラグインの AmazonLink でもこのサービスを使用しているので他人事ではありません。

基本方式はほとんど変わらないとのことですが、認証で使用する電子署名の作成には、開発者登録をしたときに作成した Secret Access Key というものが必要になるようです。リクエスト時のデータによって変わるため、電子署名データだけをプログラムに埋め込んでおくことができません。また、Secret Access と言うくらいなのでこれを公開するのも駄目でしょう。

詳しい情報がまだ得られていないのでなんとも言えませんが、ただ使うだけの人にも開発者登録をしてもらわないと駄目になるかもしれません。

今のところは、たつをさんによる記事が一番詳しそう。

電子署名データの作成には RFC 2104-compliant HMAC with the SHA256 hash algorithm という変換処理のようなものが必要で、これを行うための関数である hash は PHP5 でないと標準では使用できません。PHP4 はすでに終了宣言が出ているのですが、まだ PHP5 が使用できないサーバーもあるので悩みどころです。

Comments (0)

2009年1月18日 日曜日

【重要】不正アクセスを受けました

Filed under: WordPress,重要
タグ:, ,
時間:23時40分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録
Popularity: 15%
by Popularity Contest 日本語版

不正アクセスを受けていたようです。現時点で判明している被害と行った対策は次のものです。

不正投稿

内容

先日、投稿した記憶のない記事がRSSに含まれていることに気がつきました。実際に過去の日付で投稿されており、不正アクセスをされたと結論付けました。

記事の内容は、違法またはセキュリティ的に危険な内容のサイトへの誘導と思われます。幸いタグが間違っているためにリンクにはなっておりませんでしたが、すぐに記事は削除いたしました。

対策

どのような形で投稿が行われたのかは不明ですが、WordPress を2.6系の最新バージョンへアップグレードいたしました。また、XML-RPC などの外部から投稿を可能にする機能は無効にしてあります。

テンプレートファイルの書き換え

内容

テンプレートファイルの footer.php に大量の隠しリンク(スタイルシートで非表示にしてありました)を記入されていました。本来4KBほどのサイズなのですが、記入されたファイルは1MB弱になっていました。

書き込まれた内容は、やはり外部サイトへのリンクでした。隠しリンクになっていましたので、検索エンジンロボットを対象としたものでしょう。
リンクの中には WordPress を使用したサイトと思われるものも多数ありましたので、WordPress を使用しているサイトが狙われている可能性があります。ユーザーの方は、書き換えが行われていないか確認することをお勧めします。

対策

追記された部分については、すでに削除してあり、そのほかのテンプレートに関しても確認を行いました。

また、管理画面から編集可能にするためファイル属性を666(誰でも書きこめる状態)にしてあったため、危険であると判断して644(ファイルの所有者のみが書きこめる状態)に変更しました。

Comments (0)

2008年11月29日 土曜日

WordPress 用プラグイン monthchunks のバグを修正

Filed under: WordPress,ハック,プラグイン
タグ:, , ,
時間:3時45分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録
Popularity: 26%
by Popularity Contest 日本語版

 このブログでは、月ごとアーカイブをコンパクトに表示してくれるプラグイン monthchunks を使用していますが、記事がないのに表示されている月があることが判明しました。

 問題の月は、2006年の9月。Google ウェブマスターツールのリンクエラー報告によると、76箇所で表示されているとのこと。さすがに数が多いので、本腰を入れて調べてみることにしました。久しぶりのプラグインハックです。

 何はともあれ、まずはプラグインのコードを読みます。使用しているバージョンは、最新の2.1。関数が1つ定義してあるだけでコメントを含めても154行と非常に短いので、初めてのハックにはお勧めかもしれません。

 大まかな流れは、SQL 文を生成して実行するだけ。オプションによって多少分岐がありますが、上から追いかけていけば大したことはありません。101行目からと114行目(110行目から始まる foreach の中)からの2箇所でデータベースにアクセスしています。1箇所目は記事のある年度の取得、2箇所目は各年度別に記事のある月の取得をしています。

PHP:
  1. // get an array of the years in which there are posts
  2.     $wpdb->query("SELECT DATE_FORMAT(post_date, '%Y') as post_year
  3.                   FROM $wpdb->posts
  4.                   WHERE post_status = 'publish'
  5.                   GROUP BY post_year
  6.                   HAVING post_year <> '0000'
  7.                   ORDER BY post_year $year_order");
  8.     $years = $wpdb->get_col();

PHP:
  1. // get an array of months for the current year without leading zero
  2.         // sort by month with leading zero
  3.         $months = $wpdb->get_results("SELECT DATE_FORMAT(post_date, '%c') as post_month,
  4.                                       $month_format AS display_month,
  5.                                       DATE_FORMAT(post_date, '%M') as post_month_name
  6.                                       FROM $wpdb->posts
  7.                                       WHERE DATE_FORMAT(post_date, '%Y') = $year
  8.                                       AND post_status = 'publish'
  9.                                       GROUP BY DATE_FORMAT(post_date, '%m')
  10.                                       ORDER BY post_date");

 今回問題になっているのは月の情報なので、2箇所目を詳しく見ていきます。PHP のコードと SQL が混在してわかりにくいので、最終的な SQL 文を記述してみます。オプションを特に指定しない場合は、次のようなものが出来上がります。(改行やインデントなどを加えてあります)

SQL:
  1. SELECT
  2.     DATE_FORMAT(`post_date`, '%c') AS `post_month`,
  3.     DATE_FORMAT(`post_date`, '%c') AS `display_month`,
  4.     DATE_FORMAT(`post_date`, '%M') AS `post_month_name`
  5. FROM `wp_posts`
  6. WHERE
  7.     DATE_FORMAT(`post_date`, '%Y') = 2006
  8.     AND post_status = 'publish'
  9. GROUP BY DATE_FORMAT(`post_date`, '%m')
  10. ORDER BY `post_date`;

 実際にこの SQL 文を手がかりに検索してみると、記事ではなく固定ページが見つかりました。記事と固定ページを区別していないため、固定ページしかない月も表示してしまっていたのです。

 ここまでわかればあとは簡単。検索条件に記事であることを加えればいいのです。記事の場合は post_type というフィールドの値が post となるので(WordPress 2.1以降)、post_type = 'post' を加えます。変更後は次のようになります。私は120行目に加えました。

PHP:
  1. // get an array of months for the current year without leading zero
  2.         // sort by month with leading zero
  3.         $months = $wpdb->get_results("SELECT DATE_FORMAT(post_date, '%c') as post_month,
  4.                                       $month_format AS display_month,
  5.                                       DATE_FORMAT(post_date, '%M') as post_month_name
  6.                                       FROM $wpdb->posts
  7.                                       WHERE DATE_FORMAT(post_date, '%Y') = $year
  8.                                       AND post_status = 'publish'
  9.                                       AND post_type = 'post'
  10.                                       GROUP BY DATE_FORMAT(post_date, '%m')
  11.                                       ORDER BY post_date");

 これにより、その年の公開されている記事という条件で絞り込むことができるようになりました。現在2006年の9月は表示されなくなっています。

2010年6月21日追記

prioさんからコメントをいただきましたので、年度の表示についても追記します。確認はしていませんので、参考程度にどうぞ。

100行目からの年度のコードを見ると、月の取得同様に固定ページも含むようになっています。SQLにしてみるとこんな感じ。

SQL:
  1. SELECT
  2.     DATE_FORMAT(post_date, '%Y') AS post_year
  3. FROM `wp_posts`
  4. WHERE
  5.     post_status = 'publish'
  6. GROUP BY post_year
  7. HAVING post_year <> '0000'
  8. ORDER BY post_year DESC

記事の投稿に限定する条件を加えると次のようになります。

PHP:
  1. // get an array of the years in which there are posts
  2.     $wpdb->query("SELECT DATE_FORMAT(post_date, '%Y') as post_year
  3.                   FROM $wpdb->posts
  4.                   WHERE post_status = 'publish'
  5.                   AND post_type = 'post'
  6.                   GROUP BY post_year
  7.                   HAVING post_year <> '0000'
  8.                   ORDER BY post_year $year_order");
  9.     $years = $wpdb->get_col();

104行目が追加した行です。意味については、月の場合と同じです。

Comments (2)
Page 2 of 2«12

HTML convert time: 1.033 sec. Powered by

Images is enhanced with WordPress Lightbox JS by Zeo