8月17日に「私立・プログラミングキャンプ 2014」に行ってきましたので、その時の作業ログをTwitterでのつぶやきを基本にまとめてみました。
この投稿はほぼ自分のメモを公開するだけなので、成果物の報告とかは別で投稿します。
※つぶやきだけ見てると何をしているのかがさっぱりわからないと思うのですが、「Jetpack Sharing Source Pack」というWordPressプラグインを開発して、Jetpackの共有メニューにFeedlyやはてなブックマークのボタンを追加してみる。ということをやっています。
10:30 作業開始。
#upcamp 到着。そろそろ作業開始 (@ 愛宕グリーンヒルズMORIタワー in 港区, 東京都) https://t.co/079wmI1sGy
— D.Takahashi.cpp14 (@yaemonsan) August 17, 2014
10:50: 作業内容決定。
今日のメインはWordPressプラグイン @jetpack の機能拡張用のプラグイン開発。共有先にFeedlyを追加するところまでを第一目標点に。 #upcamp
— D.Takahashi.cpp14 (@yaemonsan) August 17, 2014
まずはplugins_loadedアクションでJetpackの存在を確認。
add_action( 'plugins_loaded', array( $this, 'is_jetpack_active' ) ); function is_jetpack_active() { if ( class_exists( 'Jetpack' ) ) { // Jetpack is active } else { // Jetpack is NOT active } }
sharedaddyモジュールが有効かどうかを確認するには、jetpack_modules_loadedアクションでJetpackクラスの関数をコールして確認。
add_action( 'jetpack_modules_loaded', array( $this, 'is_sharedaddy_modules_active' ) ); function is_sharedaddy_modules_active() { if ( Jetpack::is_module_active( 'sharedaddy' ) ) { // sharedaddy is active } else { // sharedaddy is NOT active } }
sharing_servicesフィルターで$services[‘feedly’]が存在しなければ、クラス名を文字列として追加。
add_filter( 'sharing_services', array( $this, 'add_sharing_services' ) ); function sharing_services( $services ) { require_once( dirname( __FILE__ ) . '/class.sharing-sources.php' ); if ( ! array_key_exists( 'feedly', $services ) ) { $services['feedly'] = 'Share_Feedly'; } }
sharing_global_optionsアクションでoptions-general.php?page=sharingの設定項目追加。
保存時に複雑な処理が必要な場合は特に、保存処理だけをsharing_admin_updateアクションに分けて記述する。
add_action( 'sharing_global_options', array( $this, 'add_sharing_options_init' ) ); function add_sharing_options_init() { ?> <tr> <th scope="row"> <label><?php esc_html_e( 'WordPress.com Likes are', 'jetpack' ); ?></label> </th> <td> <div> <label> <input type="radio" name="wpl_default" value="on" <?php checked( $this->is_enabled_sitewide(), true ); ?> /> <?php esc_html_e( 'On for all posts', 'jetpack' ); ?> </label> </div> <div> <label> <input type="radio" name="wpl_default" value="off" <?php checked( $this->is_enabled_sitewide(), false ); ?> /> <?php esc_html_e( 'Turned on per post', 'jetpack' ); ?> </label> <div> </td> </tr> <?php }
add_action( 'sharing_admin_update', array( $this, 'add_sharing_options_callback' ) ); function add_sharing_options_callback() { $new_state = ( ! empty( $_POST['wpl_default'] ) ) ? $_POST['wpl_default'] : 'on'; switch( $new_state ) { case 'off' : update_option( 'disabled_likes', 1 ); break; case 'on' : default: delete_option( 'disabled_likes' ); break; } }
実際の共有先の定義はSharing_Sourceクラスを継承して作る。
class Share_Facebook extends Sharing_Source { var $shortname = 'facebook'; private $share_type = 'default'; public function __construct( $id, array $settings ) { parent::__construct( $id, $settings ); if ( isset( $settings['share_type'] ) ) $this->share_type = $settings['share_type']; if ( 'official' == $this->button_style ) $this->smart = true; else $this->smart = false; } public function get_name() { return __( 'Facebook', 'jetpack' ); } public function display_header() { } public function get_display( $post ) { $share_url = $this->get_share_url( $post->ID ); if ( $this->smart ) { $url = $this->http() . '://www.facebook.com/plugins/like.php?href=' . rawurlencode( $share_url ) . '&layout=button_count&show_faces=false&action=like&colorscheme=light&height=21'; // Default widths to suit English $inner_w = 90; $widths = 100; $widths = apply_filters( 'sharing_facebook_like_widths', $widths ); $url .= '&width='.$inner_w; return '<div class="like_button"><iframe src="'.$url.'" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:'.( $inner_w + 6 ).'px; height:21px;" allowTransparency="true"></iframe></div>'; } if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'facebook' ) ) { sharing_register_post_for_share_counts( $post->ID ); } return $this->get_link( get_permalink( $post->ID ), _x( 'Facebook', 'share to', 'jetpack' ), __( 'Share on Facebook', 'jetpack' ), 'share=facebook', 'sharing-facebook-' . $post->ID ); } public function process_request( $post, array $post_data ) { $fb_url = $this->http() . '://www.facebook.com/sharer.php?u=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&t=' . rawurlencode( $this->get_share_title( $post->ID ) ); // Record stats parent::process_request( $post, $post_data ); // Redirect to Facebook wp_redirect( $fb_url ); die(); } public function display_footer() { $this->js_dialog( $this->shortname ); } }
11:48: WordPressの構造を見ていたらふと思った。
そもそもマジックメソッドでクラスのメンバ変数を取り出すとかいう野蛮な行為はやめた方がいいw
— D.Takahashi.cpp14 (@yaemonsan) August 17, 2014
12:17: おにぎりを食べながら、宣言してみた
今日、仕事した結果は https://t.co/1aj84Y5TuX に数時間に一回アップします。 #upcamp
— D.Takahashi.cpp14 (@yaemonsan) August 17, 2014
16:13: 共有ボタンの表示にはおおむね成功。
とりあえず、動いたので今日中には0.1.0-devから0.1.0-alphaか-betaにバンプできる予定。 #upcamp https://t.co/ILfRGMOWjn
— D.Takahashi.cpp14 (@yaemonsan) August 17, 2014
自分のサイト上でテストしていたせいでバグにより何回かサイトが落ちたとか、落ちなかったとか。
自分のサイトにおいてみた。 http://t.co/6ybpMMJ1K5
FacebookやTwitterでの拡散数表示と同様にFeedlyでの購読者数の表示にも対応予定。#upcamp— D.Takahashi.cpp14 (@yaemonsan) August 17, 2014
17:41: 決定的な問題に直面。
これにより、17日中の完成は不可能なことが確定…。
FeedlyのAPIがJSONPに対応していなくて泣きそう…
— D.Takahashi.cpp14 (@yaemonsan) August 17, 2014
ここから、WordPress関係のサイトを調べまくって思いついた解決方法がAPIの中継という方法。
仕組みは簡単で、
- [JS]出力用のURLをコール
- [PHP]FeedlyのAPIを叩く
- [PHP]WordPressのtransient APIに結果を取っておく
- [PHP]前後にごにょごにょ付けてJSONをJSONPに変換して出力
- [JS]以後、jQueryで通常通り
といった感じ。リバースプロキシ的な何か。
そのしばらく後、見事にRewrite APIの謎仕様の数々に苦戦するも、立食<のため #upcamp 会場での作業終了のため中断。
18:45: 食事・LT
オプティム、ゲヒルン、ありがとう!!!!! #upcamp
— うみさま (@umisama) August 17, 2014
ということで、会場提供や食事提供をしてくださった株式会社オプティム様とゲヒルン株式会社様、ありがとうございます!