Google Crisis Response(Google)
災害に関する情報源や、行方不明者情報の収集と検索を行う『パーソンファインダー』を初めとするツールの提供が行われています。

2007年2月18日 日曜日

EntryKeywords 0.5.0 公開しました

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

 『公開迫る』といいつつ、結局2週間も過ぎてしまいました。自作 WordPress プラグインの EntryKeywords 0.5.0 をやっと公開です。

 公開場所は、予定通り JSeries になりました。その中に専用のページを作り、リリース情報などを掲載するようにしています。

 また、このブログに専用のカテゴリーを新設しました。JSeries はコメントやトラックバックができませんので、必要な場合はカテゴリー内の記事にでもしていただければと思います。

Comments (2)

2007年2月15日 木曜日

WordPress プラグインのトラブル解決

Filed under: EntryKeywords,WordPress,ハック,プラグイン
時間:4時14分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

 フック admin_headdo_action を実行している直前で $wp_filter の中身をすべて表示させてみたところ、あっさり解決しました。
 関数名を検索してみるとしっかり登録されていたので登録内容を確認。フックのところを見たとき愕然としました。

 フック名は、「admin_head 」。後ろに余計なスペースが・・・。

 はい。単なる入力ミスです。こんなのに3日も悩んでたんですか。
 スペルを間違えないようにコピーしてきたときにスペースが入ってしまったのではないかと。本末転倒もいいところです(^^;

 フックは開発者が自由に決められる仕組みなので、スペルミスには注意が必要ですね。構文エラーなら PHP が面倒を見てくれますが、今回のような論理エラーは思い込みなどで気がつくのに時間がかかります。皆さんもご注意くださいませ。

Comments (0)

WordPress プラグインの仕組み

Filed under: EntryKeywords,WordPress,ハック,プラグイン
時間:3時25分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

 自作プラグイン EntryKeywords のオプション設定画面を CSS で装飾したくて作業中。

 マニュアルを見ていて add_action('admin_head ', '関数'); とすればいいはずと目星をつけていましたが、なぜか動いてくれません。2日以上悩み続けています。仕方がないので流れを追いかけてみることに。
 結局動くまでには至っていませんが、せっかくなので仕組みをメモ。

登録

 まず、関数 add_action でフックに対応する関数の登録を行います。2.0.7 では add_filter を呼び出すだけなので、実際の処理は 関数 add_filter を見ます。定義は、/wp-includes/functions.php にあります。

  1. function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
  2.     global $wp_filter;
  3.  
  4.     // check that we don't already have the same filter at the same priority
  5.     if ( isset($wp_filter[$tag]["$priority"]) ) {
  6.         foreach($wp_filter[$tag]["$priority"] as $filter) {
  7.             // uncomment if we want to match function AND accepted_args
  8.             // if ( $filter == array($function, $accepted_args) ) {
  9.             if ( $filter['function'] == $function_to_add ) {
  10.                 return true;
  11.             }
  12.         }
  13.     }
  14.  
  15.     // So the format is wp_filter['tag']['array of priorities']['array of ['array (functions, accepted_args)]']
  16.     $wp_filter[$tag]["$priority"][] = array('function'=>$function_to_add, 'accepted_args'=>$accepted_args);
  17.     return true;
  18. }

 フックの登録は、グローバル変数 $wp_filter に配列として登録されます。関数 add_filter の処理は大きく2つに分かれていて、登録処理は後半の部分で行います。前半は重複して登録しないためのチェックです。
 登録処理のコメントにもありますが、登録情報はフックと優先度で分類されています。また、関数にはオブジェクトのメンバー関数も登録できます。その場合は、array(オブジェクトインスタンス, 関数名) という配列を使います。オブジェクトインスタンスは参照渡しする必要があります。そのため、PHP 4 では変数の頭に & をつけて明示的に参照渡しにする必要があります。

実行

 登録した関数を実行するには、関数 do_action を使います。この定義も /wp-includes/functions.php にあります。

  1. function do_action($tag, $arg = '') {
  2.     global $wp_filter;
  3.     $extra_args = array_slice(func_get_args(), 2);
  4.     if ( is_array($arg) )
  5.         $args = array_merge($arg, $extra_args);
  6.     else
  7.         $args = array_merge(array($arg), $extra_args);
  8.  
  9.     merge_filters($tag);
  10.  
  11.     if ( !isset($wp_filter[$tag]) ) {
  12.         return;
  13.     }
  14.     foreach ($wp_filter[$tag] as $priority => $functions) {
  15.         if ( !is_null($functions) ) {
  16.             foreach($functions as $function) {
  17.  
  18.                 $function_name = $function['function'];
  19.                 $accepted_args = $function['accepted_args'];
  20.  
  21.                 if ( $accepted_args == 1 ) {
  22.                     if ( is_array($arg) )
  23.                         $the_args = $arg;
  24.                     else
  25.                         $the_args = array($arg);
  26.                 } elseif ( $accepted_args > 1 ) {
  27.                     $the_args = array_slice($args, 0, $accepted_args);
  28.                 } elseif ( $accepted_args == 0 ) {
  29.                     $the_args = NULL;
  30.                 } else {
  31.                     $the_args = $args;
  32.                 }
  33.  
  34.                 $string = call_user_func_array($function_name, $the_args);
  35.             }
  36.         }
  37.     }
  38. }

 前半は飛ばして、後半の foreach を見ます。
 特定のフックに対する登録情報を順に処理しています。情報を取り出し、引数の処理をし、最後に組み込み関数 call_user_func_array で関数をコールします。

どこまでは動いているのか

 調べた結果、少なくとも add_filter での重複チェックを通過していることはわかりました。最後の return の直前($wp_filter への登録直後)で $wp_filter[$tag]["$priority"] の値を表示させて確認しました。
 add_action を経由しないで直接登録した場合ではきちんと動作しましたので、何らかの理由により登録を削除されているのではないかと考えています。

Comments (1)

2007年2月11日 日曜日

WordPress ダッシュボードの構文エラーの修正

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

 WordPress ダッシュボードには、ブログ内のページにリンクを張っているサイトのリストが表示されています。Me の日本語リリースでは「リンク元」とタイトルがつけられているところです。

 このリストですが、リンク部分に構文エラーがありました。リンクの終了タグである </a> がありません。2.0.6 の時点でなっていました。2.0.7 でも直っていません。

 2.0.7 での修正方法は次のとおり。

 修正前。/wp-admin/index.php の28行目。

  1. <li><a href="<?php echo wp_filter_kses($item['link']); ?>">< ?php echo wptexturize(wp_specialchars(wpj_rss_convert($item['title']))); ?></a></li>

 修正後。行末の </li> の直前に終了タグを入れます。

  1. <li><a href="<?php echo wp_filter_kses($item['link']); ?>">< ?php echo wptexturize(wp_specialchars(wpj_rss_convert($item['title']))); ?></a></li>

 これで構文エラーはなくなりました。

 なお、ほかのバージョンで修正箇所を探す場合は、次のコードを目印にするといいかもしれません。タイトルの部分です。そこから5・6行下に修正箇所があると思います。

  1. < ?php _e('Incoming Links'); ?>
Comments (0)

2007年2月5日 月曜日

オリジナルプラグイン EntryKeywords の公開迫る

Filed under: EntryKeywords,WordPress,プラグイン
時間:1時49分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

 先月の中ごろから WordPress プラグインの作成に挑んできましたが、もうまもなく公開できると思います。名称は、EntryKeywords。

 機能としては、記事に対してキーワードを複数設定し、それをいろいろと利用しようというものです。再利用を重視している点でタグ系のプラグインとは違います。基本は文字列での表示ですが、配列や JSON で取得できるなど、プログラマ寄りになっています。
 公開場所は WordPress Plugins/JSeries の予定。発案者であるひろまささんには参加の申し込みをしてあるので、現在返事待ちです。

 まだドキュメントもなくベータ版状態ですが、よかったらいじってみてください。GPL ライセンスですので、変更もご自由に。

Comments (1)

2007年1月25日 木曜日

ダッシュボードの『その他の WordPress サイト』が更新されない

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

 ダッシュボードの『その他の WordPress サイト』が更新されていないことが最近多いです。RSS リーダー代わりに結構参照しているのですが、1日経っても同じままだとちょっとさびしいです。
 この部分ははてなのRSSサービスを利用していることがすでにわかっているので、ソースコードから探し出して直接見てみました。

 まったく違う内容でした。どこかにキャッシュされているんでしょうか。そのうちハックしてみます。

ダッシュボードについて

 WordPress を使った事のない方のために簡単に説明。
 ダッシュボードは、WordPress の管理画面の一番最初に表示されるページで、ニュース情報や最近のコメント・投稿した記事などが表示されます。

Comments (0)

2007年1月18日 木曜日

プラグインテスト用兼メモ

Filed under: EntryKeywords,WordPress,ハック,プラグイン
時間:0時38分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

 プラグイン製作に挑むことにしました。このページはそのテスト用です。
 普通の記事ページでもいいのですが、何かあったときの影響範囲を狭めるのと、個別に開くと人気度が変化してしまうために専用の記事を使うことにしました。

メモ

カスタムフィールド
キー
yo_keyword
値を得る

 指定の記事のカスタムフィールドの値を得る。

  1. get_post_meta($post->ID, 'yo_keyword', true);
$post->ID
記事ID
‘yo_keyword’
値がほしいキー
true
このキーが1つだけのときtrue。falseだとリストになる。

プラグインオプションの処理

Saving Plugin Data to the Database

get_option($option):値の取得
add_option($name, $value, $description, $autoload):新規追加
update_option($option_name, $newvalue):更新。ない場合は add_option() が呼ばれる
delete_option($name):オプションの削除

class を使う場合のオプションページ登録

 class を使っている場合(OOP)、add_options_page() の第5引数は次のようにする。

  1. array(&$this, 'function_name')

 この引数が、call_user_func_array() の第1引数になる。これをやらないと、「First argument is expected to be a valid callback」と警告が出る。

フォームの値

 フォームからの値はグローバル変数の $_POST$_GET で得られるが、WordPressはどちらも独自の方法でエスケープしている。(/wp-settings.php
 このエスケープは強制的に行われるため、フォームを使う場合は stripslashes によるアンエスケープが必要。

  1. // If already slashed, strip.
  2. if ( get_magic_quotes_gpc() ) {
  3.     $_GET    = stripslashes_deep($_GET   );
  4.     $_POST   = stripslashes_deep($_POST  );
  5.     $_COOKIE = stripslashes_deep($_COOKIE);
  6. }
  7.  
  8. // Escape with wpdb.
  9. $_GET    = add_magic_quotes($_GET   );
  10. $_POST   = add_magic_quotes($_POST  );
  11. $_COOKIE = add_magic_quotes($_COOKIE);
  12. $_SERVER = add_magic_quotes($_SERVER);

 エスケープ処理を行っている関数 add_magic_quotes() は、/wp-includes/functions.php で定義されている。
 再起処理により、階層の深い配列にも対応するようになっている。

  1. function add_magic_quotes($array) {
  2.     global $wpdb;
  3.  
  4.     foreach ($array as $k => $v) {
  5.         if ( is_array($v) ) {
  6.             $array[$k] = add_magic_quotes($v);
  7.         } else {
  8.             $array[$k] = $wpdb->escape($v);
  9.         }
  10.     }
  11.     return $array;
  12. }

 最終的なエスケープ処理をする $wpdb->escape() は、/wp-includes/wp-db.php で定義されている。$wpdb は クラス wpdb のインスタンス。

  1. // ====================================================================
  2.     //  Format a string correctly for safe insert under all PHP conditions
  3.    
  4.     function escape($string) {
  5.         return addslashes( $string ); // Disable rest for now, causing problems
  6.         if( !$this->dbh || version_compare( phpversion(), '4.3.0' ) == '-1' )
  7.             return mysql_escape_string( $string );
  8.         else
  9.             return mysql_real_escape_string( $string, $this->dbh );
  10.     }

進行具合

 デバッグ&テスト中。
 本番テストということで、アフィリエイト広告のキーワードとして使ってみています。
 記事のメタ情報を利用するため、記事ループの中でないと使えないことが判明。サイドバーのアフィリエイト広告に使いたかったのでちょっと残念。

管理画面スクリーンショット

TODO

  • オプションを保持している変数をクラスオブジェクトにする。
  • メソッドの引数によるオプションの上書き処理を、オプション用クラスのメソッドとして切り離す。
  • 管理画面のオプション設定画面の表示を専用クラスに切り離す。
  • キーワードをランダムに1つ選択するメソッドの実装。
  • オプション設定画面の整理。
  • カスタムフィールドに改行で区切って複数のキーワードが入れられるようにする。
  • キーワードを得る方法に、配列とJSONを追加。

参考資料

Comments (0)

2007年1月15日 月曜日

記事にキーワードをつけるアイディアのメモ

Filed under: EntryKeywords,アフィリエイト,プラグイン
時間:22時34分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

 ちょっと思いついたのでメモ。時間があればプラグインとして作ってみようと思いますが、今はただのメモ。

 実はもうある?ご存知の方ぜひ教えてください。面白そうだから作るよというのも大歓迎です。

アフィリエイト要に記事にキーワードを付ける

 Amazon.co.jp のライブリンクのように、ASP型のアフィリエイトサービスには、キーワードによって表示する商品を動的に決定することができるものがあります。お任せリンクではキーワードの抽出がどうなっているのかわからず曖昧になりがちですが、直接指定することで好きなように決めることができます。

 ブログでは、カテゴリーという概念があります。記事を大まかに分類するわけです。もう少し細かいものにタグがあります。これも一種のキーワードといえますが、アフィリエイト用としてはまだちょっと曖昧な気がします。細かくしすぎるとタグの意味がなくなってしまいますし。

キーワードを記事に紐付ける

 ということで、専用のキーワードという概念が必要であると私は結論付けました。そして、それを WordPress のカスタムフィールドでできないかと考えています。記事の ID と紐付けられた形でデータベースに記録されるようなので、記事 ID からたどって値(ここではキーワード)を取得することも可能なはずです。

 ここまでくればあとは簡単。アフィリエイトの広告表示コードを出力する関数を定義したプラグインを作るだけ。キーワードを URL エンコードして埋め込むようにしてやれば、投稿画面で設定したキーワードを広告表示コードに渡すことができるはずです。表示はテンプレートに関数を埋め込んでもらいます。

柔軟にする

 プラグインオプションの設定画面がほしいですね。
 広告コードを設定することができればいろいろ対応できますし、ほかにもいろいろオプションが必要になるかもしれません。

その他

 キーワードの設定がない場合はカテゴリーを使えばいいでしょうか。オプションで初期値を設定できるというのもありかも。

Comments (0)

2007年1月11日 木曜日

Popularity Contest 日本語版 を導入

Filed under: プラグイン
時間:19時20分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

 記事の人気度を表示する、Popularity Contest の日本語版を導入しました。

 インストールは一般的なプラグインと同じで、アップロードして有効にするだけ。記事本文の一番最後に、次のように人気度が自動的に挿入されます。

  1. <p class="akpc_pop">人気度: 20%</p>

 別の場所にしたいとか、デフォルトとは違うコードにしたい場合は、ファイルの上のほうにある変数(手元のファイルでは38行目)
$ak_show_popularity_with_post の値を1から0にします。
 プログラム上は1以外にすればいいと思いますが、次のように書かれているので一応0に。

  1. /* -- INSTALLATION --------------------- */
  2.  
  3. // Change this to "0" below if you don't want to show each post's popularity with the post content
  4.  
  5. $ak_show_popularity_with_post = 1;

 そして、挿入したいところに次のコードを入れます。ランク表示のテキストだけが出力されるので、好みのタグにすることができます。

  1. < ?php akpc_the_popularity(); ?>

 ランクはパーマリンクのクリックやトラックバックなど、さまざまなアクションの点数制によって決まります。アクションごとにどれくらい加算していくのかは、管理画面のオプション→人気度 で変更できます。
 また、ダッシュボード→人気記事一覧 から、詳細な人気記事のリストを見ることができます。

Comments (0)

2007年1月7日 日曜日

Akismet 有名ハックの解説と追加ハック

Filed under: ハック,プラグイン
時間:18時16分
投稿者:よしとも
AddClips 経由でソーシャルブックマークに登録

 Akismet de-spam view Hack と呼ばれるハック(プログラムの改造。不正アクセスではない)があります。

 WordPeress のスパムブロックプラグイン Akimet の捕獲したスパム一覧で、半角英数記号以外が含まれたスパム(以下、マルチバイトスパムと表記します)が含まれているものだけ表示するようにするというものです。

 大概のスパムは半角英数のみです。そして、多くの日本語サイトに届くスパムでないコメントやトラックバックは日本語によるものです。だったら、マルチバイトスパム以外を表示しなければすっきりするじゃないかというのが、このハックのコンセプトです。

 また、power source*さんによる、管理画面のダッシュボードにマルチバイトスパムの捕獲数を併記するハックがあります。

 今回、スパム対策の一環としてこの2つのハックを試してみました。効果抜群で、すっきりしたスパム一覧とマルチバイトスパムの捕獲数表示に喜んでおります。

 お二人への感謝と還元と自分への覚書として、この2つのハックの解説をしてみたいと思います。また、思いつきで追加ハックもしました。
 なお、ハックした WordPress のバージョンは2.04です。

Akismet de-spam view Hack

オリジナル

 ファイル /wp-content/plugins/akismet/akismet.php の267行目。

  1. $comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' ORDER BY comment_date DESC LIMIT 150");
ハック
  1. $comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' AND LENGTH(comment_content) <> CHAR_LENGTH(comment_content) ORDER BY comment_date DESC LIMIT 150");

 変更したのは、一覧に表示するデータを得る部分です。データベースサーバにスパム判定されたコメントのデータを要求しています。このハックでは、SQL の条件文(WHERE 節)にマルチバイトではないという条件を AND で加えています。

追加部分のコード
  1. AND LENGTH(comment_content) <> CHAR_LENGTH(comment_content)

 テーブル wp_comments のフィールド comment_content に格納されているコメントの本文に対し、関数 LENGTHCHAR_LENGTH の結果が一致していないというものです。LENGTH はバイト数を、CHAR_LENGTH は文字数を返します。マルチバイト文字は1文字が1バイトではないため、2つの結果は一致しません。

マルチバイトスパムの捕獲数をダッシュボードに併記するハック

Akismet ダッシュボードスクリーンショット

オリジナル

 ファイル /wp-content/plugins/akismet/akismet.php の323行目。関数 akismet_stats 付近。

  1. function akismet_stats() {
  2.     $count = get_option('akismet_spam_count');
  3.     if ( !$count )
  4.         return;
  5.     $path = plugin_basename(__FILE__);
  6.     echo '<h3>'.__('Spam').'</h3>';
  7.     echo '<p>'.sprintf(__('<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.'), 'http://akismet.com/', "edit.php?page=$path", number_format($count) ).'</p>';
  8. }
関数 akismet_stats のハック
  1. function akismet_stats() {
  2.     $count = get_option('akismet_spam_count');
  3. //  $count = ksd_spam_count();
  4.     $mbs_count = mb_spam_count();
  5.     if ( !$count )
  6.         return;
  7.     $path = plugin_basename(__FILE__);
  8.     echo '<h3>'.__('Spam').'</h3>';
  9.     echo '<p>'.sprintf(__('<a href="%1$s">Akismet</a> has protected your site from <a href="%2$s">%3$s spam comments</a>.'), 'http://akismet.com/', "edit.php?page=$path", number_format($count) ).'</p>';
  10.     if ( $mbs_count ) {
  11.         echo '<p><strong><a href="edit.php?page='.$path.'&amp;akismet_list=mb">要チェック</a></strong>: マルチバイト文字を含むものを '.$mbs_count.' 件捕獲中です。</p>';
  12.     } else {
  13.         echo '<p>この中にマルチバイト文字を含むものはありません。</p>';
  14.     }
  15. }

 マルチバイトスパムのカウントと表示を追加しています。4行目がマルチバイトスパムのカウント、10~14行目がダッシュボードに表示する部分です。
 もともとのハックではマルチバイトスパム以外も含めた捕獲数を捕獲中のものだけにしてありますが、私の好みで総数に戻してあります。捕獲中のものだけにしたい場合は、2行目のコメントアウトをはずし、3行目をコメントアウトするか削除してください。また、もとのハックではリスト表示にする変更をしてありますが、こちらも好みで段落にしてあります。

 4行目で呼び出している関数 mb_spam_count は、新たに定義したものです。関数 ksd_spam_count に、マルチバイトであることを条件に加えたものになっています。Akismet de-spam view Hack と同様の変更です。
 基本的にはどこに記述しても構いませんが、akismet_stats の近くが良いでしょう。私は akismet_stats の直後にしました。

mb_spam_count
  1. function mb_spam_count() { // マルチバイトスパムの件数
  2.     global $wpdb, $comments;
  3.     $count = $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND LENGTH(comment_content) <> CHAR_LENGTH(comment_content)");
  4.     return $count;
  5. }
ksd_spam_count

 ファイル /wp-content/plugins/akismet/akismet.php の195行目。

  1. function ksd_spam_count() {
  2.     global $wpdb, $comments;
  3.     $count = $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'");
  4.     return $count;
  5. }

追加ハック

 解説は以上ですが、思いつきで従来の一覧表示もできるようにしてみました。

267行目(Akismet de-spam view Hack の場所)

 引数を見て、どちらの表示にするか処理を分岐させています。引数の名前は被らなければなんでもいいのですが、とりあえず akismet_spam_list としました。値が mb ならマルチバイトスパムのみ、それ以外なら従来の表示になります。

  1. switch ($_GET['akismet_spam_list'])
  2. {
  3.     case 'mb':
  4.         $comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' AND LENGTH(comment_content) <> CHAR_LENGTH(comment_content) ORDER BY comment_date DESC LIMIT 150");
  5.         break;
  6.     default:
  7.         $comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' ORDER BY comment_date DESC LIMIT 150");
  8. }
関数 akismet_stats

 せっかくなので、ダッシュボードのリンクも変更します。マルチバイトスパムがあったときの表示をする行(ハックの11行目)を、次のようにします。

  1. echo '<p><strong><a href="edit.php?page='.$path.'&amp;akismet_spam_list=mb">要チェック</a></strong>: マルチバイト文字を含むものを '.$mbs_count.' 件捕獲中です。</p>';

 これで、要チェックのときはマルチバイトスパムだけの表示にでき、最近の傾向を見たいときなどでは従来の表示にすることができます。

参考情報

Function Reference/wpdb Class « WordPress Codex:
データベースアクセス用クラス
Database Description « WordPress Codex:
データベーステーブル
Comments (1)
Page 8 of 9« First...56789

HTML convert time: 0.589 sec. Powered by

Images is enhanced with WordPress Lightbox JS by Zeo