WordPressはとても簡単にコンテンツをWebページに埋め込めます。たとえば、YouTubeに掲載されている動画のURLを投稿エディターに入力すれば、動画が投稿内に自動的に埋め込まれます。これを実現しているのは、埋め込み用データの取得方法を定めるオープン規格oEmbedです。
oEmbedによって、WordPressは埋め込み用URLをキャッチして表示しています。WordPressでは以前からYouTubeのようなoEmbedプロバイダーに対応していましたが、WordPress 4.4とWP-APIによって、いまやWordPress自身がoEmbedプロバイダーとして機能するようになりました。どういうことかというと、WordPressのコンテンツの一部をYouTubeの動画と同じくらい簡単に投稿内に埋め込めるようになったのです。
oEmbedプロバイダー機能は、WP-APIを使い、JSONまたはXMLによる埋め込みデータをoEmbedコンシューマー(編注:URLを入力してコンテンツを埋め込むサイト)に戻し、ページに埋め込むために必要な情報を提供します。WordPressの他の機能と同様、oEmbedプロバイダー機能はアクションやフィルターを通じて簡単に修正できます。これらのフックを使って、カスタム投稿タイプを埋め込む方法を説明しましょう。
何を作るのか
この記事では「status-update」というカスタム投稿タイプを登録する単純なプラグイン「Status Update」を作成します。Status Updateカスタム投稿タイプは、投稿エディター内のタイトル入力欄を削除し、FacebookやTwitterの近況アップデートのような機能に変えたものです。このページのoEmbed出力をカスタマイズし、ページのユーザー名とアバター画像を表示します。最終版についてはGitHubのリポジトリを参照してください。
プラグインの設定
wp-content内のpluginsフォルダーを開き、sp-status-updateという名前でフォルダーを作成してください。そのディレクトリ内でsp-status-update.phpという名前でファイルを作成します。このファイルがプラグインのメインクラスの作成場所になります。プラグインヘッダーをファイル上部につけてください。
/**
* Plugin Name: Status Update
* Plugin URI: https://github.com/mAAdhaTTah/sitepoint-status-update
* Description: Post your own Facebook-like status updates
* Version: 1.0.0
* Author: James DiGioia for SitePoint
* Author URI: http://jamesdigioia.com
* Text Domain: wp-status-update
* Languages: /languages
*/
プラグインを作成するメインのプラグインシングルトンを設定します。
class SP_Status_Update {
/**
* Plugin instance.
*
* @var static
*/
protected static $instance;
/**
* Retrieve the plugin instance.
*
* @return static
*/
public static instance() {
if (null === static::$instance) {
static::$instance = new static;
}
return static::$instance;
}
/**
* Plugin constructor.
*/
protected function __construct() {
// Add actions/filters here
}
}
最後にファイル下部でプラグインを開始してください。
SP_Status_Update::instance();
コメント欄に書いたように、フックとフィルターをコンストラクターに加えます。
カスタム投稿タイプの登録
GenerateWPを使えば、カスタム投稿タイプを簡単にカスタマイズ・登録できます。WordPressに登録しておきましょう。
add_action( 'init', array( $this, 'register_post_type' ), 0 );
そして自分のクラスにこの登録方法を加えておきます。
/**
* Register the Status Update custom post type.
*/
public function register_post_type() {
$labels = array(
'name' => _x( 'Status Updates', 'Post Type General Name', 'sp-status-update' ),
'singular_name' => _x( 'Status Update', 'Post Type Singular Name', 'sp-status-update' ),
'menu_name' => __( 'Status Update', 'sp-status-update' ),
'name_admin_bar' => __( 'Status Update', 'sp-status-update' ),
'archives' => __( 'Satus Update Archives', 'sp-status-update' ),
'parent_item_colon' => __( 'Parent Update:', 'sp-status-update' ),
'all_items' => __( 'All Updates', 'sp-status-update' ),
'add_new_item' => __( 'Add New Status Update', 'sp-status-update' ),
'add_new' => __( 'Add New', 'sp-status-update' ),
'new_item' => __( 'New Status Update', 'sp-status-update' ),
'edit_item' => __( 'Edit Status Update', 'sp-status-update' ),
'update_item' => __( 'Update Status Update', 'sp-status-update' ),
'view_item' => __( 'View Status Update', 'sp-status-update' ),
'search_items' => __( 'Search Status Updates', 'sp-status-update' ),
'not_found' => __( 'Not found', 'sp-status-update' ),
'not_found_in_trash' => __( 'Not found in Trash', 'sp-status-update' ),
'featured_image' => __( 'Featured Image', 'sp-status-update' ),
'set_featured_image' => __( 'Set featured image', 'sp-status-update' ),
'remove_featured_image' => __( 'Remove featured image', 'sp-status-update' ),
'use_featured_image' => __( 'Use as featured image', 'sp-status-update' ),
'insert_into_item' => __( '
INSERT INTO Status Update', 'sp-status-update' ),
'uploaded_to_this_item' => __( 'Uploaded to this Status Update', 'sp-status-update' ),
'items_list' => __( 'Status Updates list', 'sp-status-update' ),
'items_list_navigation' => __( 'Status Updates list navigation', 'sp-status-update' ),
'filter_items_list' => __( 'Filter Status Updates list', 'sp-status-update' ),
);
$args = array(
'label' => __( 'Status Update', 'sp-status-update' ),
'description' => __( 'Simple Status Update', 'sp-status-update' ),
'labels' => $labels,
'supports' => array( 'editor', 'author', ),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 5,
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'page',
);
register_post_type( 'sp_status_update', $args );
}
それでは、oEmbedアウトプットのカスタマイズを始めましょう。
始める前に:oEmbedの仕組みとは?
ビジュアルエディターにリンクを貼り付けると、ビジュアルエディターはURLをどのように認識しているのでしょうか。
最初は「発見」です。oEmbedはプロバイダーに「既存の(X)HTMLドキュメントのheadに要素を加えてoEmbedサポートを見つけやすくするように」求めています。head要素はoEmbedコンシューマーをAPIのエンドポイントへと誘導し、埋め込み後の表示を用意します。oEmbedはJSON、XMLのどちらのフォーマットにも対応しています。
WordPressも、両方のフォーマットをサポートしています。wp_headに登録されている[wp_oembed_add_discovery_links]関数が適切な<head>タグを組み込む役割を持っていて、oembed_discovery_linksフィルターを使ってカスタマイズできます。
エディターはそこからAPIエンドポイントの構造化されたバージョンをキャッチします。JSONはこのようになります。
{
"version": "1.0",
"provider_name": "Website Name",
"provider_url": "http://example.com",
"author_name": "admin",
"author_url": "http://example.com/author/admin/",
"title": "",
"type": "rich",
"width": 600,
"height": 338,
"html": "long string of html"
}
XMLも同様で、WordPressは両方をサポートしています。XMLには特殊な処理が必要ですが、WordPressはWP-APIによってJSONとXMLがフォーマット通りに動くようにします。
エディターはこの動きを利用してhtmlキーをサニタイズし、ページ内に投入します。WordPressではoEmbed HTMLに投稿タイトルとiframeメッセージを安全かつ正しく操作するための<script>タグ、そしてサンドボックス化されたiframeと一緒にblockquoteが含まれています。このHTMLは[get_post_embed_html]を使って取得、embed_htmlでフィルタリングできます。
iframe URLを使うと「魔法」がかかり始めます。初期設定ではもともと埋め込まれているテンプレートをインポートしますが、完全に上書きして自分の埋め込みテンプレートを使うこともできます。embed_templateフィルターを使い、自分のテンプレートファイルに取り替えてしまいましょう。
add_filter( 'embed_template', 'my_embed_template' );
function my_embed_template( $template ) {
if ( 'custom_post_type' === get_post_type() ) {
return '/path/to/custom-embed-template.php';
}
return $template;
}
ほとんどの場合、上で紹介したフィルターをカスタマイズする必要はありませんが、oEmbedプロバイダーをもっと効率的に活用するためには、内部をよく知っておくと便利です。利用可能なフックやフィルターを使い、ビルトインテンプレートを修正していきます。
oEmbedタイトルをカスタマイズする
今回のプラグインは近況アップデート情報を埋め込むためのものなので、最初にoEmbedのアウトプットからタイトルを取り除きましょう。the_titleフィルターを呼び出します。
add_filter( 'the_title', array( $this, 'remove_embed_title' ), 10, 2 );
remove_embed_titleではヘルプ機能、is_embedが供給されます。この機能はoEmbedコンテクスト使用時にはtrueとなり、oEmbedアウトプットでカスタマイズできます。
以下のようにしてタイトルを取り除きます。
/**
* Remove the title from the Status Update oembed.
*
* @param string $title Post title.
* @param int $id Post ID.
*
* @return string
*/
public function remove_embed_title( $title, $id ) {
$post = get_post( $id );
if ( is_embed() && 'sp_status_update' === $post->post_type ) {
return '';
}
return $title;
}
これでタイトルがoEmbedから削除されます。もっと完全な方法でこのプラグインを作成していたら、is_oembedチェックを含める必要はないかもしれません。他の場所で削除することになるからです。しかし、この方法ならどのようにoEmbedアウトプットのタイトルにアプローチし、カスタマイズするかが分かります。
oEmbed Excerptをカスタマイズする
Status Updateの多くは短い文章で成り立つことが多いので、投稿全体の引用は避けます。the_excerpt_embedフックをフィルタリングし、引用する対象を修正できます。
add_filter( 'the_excerpt_embed', array( $this, 'get_excerpt_embed' ) );
現在の投稿タイプがカスタム投稿タイプになっているか確認します。OKであればすべてのコンテンツのアウトプットを戻します。
/**
* Returns the custom excerpt for the custom post type.
*
* @param string $output Default embed output.
* @return string Customize embed output.
*/
public function get_excerpt_embed( $output ) {
if ( 'sp_status_update' === get_post_type() ) {
return get_the_content();
}
return $output;
}
引用部分が常にStatus Updateの全投稿コンテンツになります。iframe内で、引用部分はwp-embed-excerptクラスとともにdiv内に出力され、カスタムスタイルを適用できます。カレンダーイベントのようなもっと複雑な操作をしたければ、div内でカスタムコンテンツを出力するか、embed_contentアクションで独自コンテンツを追加できます。
oEmbedにコンテンツを追加する
oembed_contentアクションは引用部分が出力されるとすぐに実行され、引用部分とフッターの間に指定区域を挿入し、カスタムHTMLを出力します。Status Updateプラグインは著者名とアバターを出力します。このアクションを追加します。
add_action( 'embed_content', array( $this, 'embed_author' ) );
カスタムHTMLを反映させるには、このアクションフックを使います。
/**
* Add the author div to the embed iframe.
*/
public function embed_author() {
if ( 'sp_status_update' !== get_post_type() ) {
return;
}
$output = '<div class="wp-embed-author">';
$output .= '— ';
$output .= get_the_author();
$output .= get_avatar( get_the_author_meta( 'ID' ), 20 );
$output .= '</div>';
echo $output;
}
シンプルなemダッシュ、著者名そして著者のアバターがあります。先にも書きましたが、もっと広範囲のカスタマイズをする場合でも、このアクションを使えばどんな追加カスタムHTMLでもアウトプットできます。
カスタムスタイルとスクリプトをoEmbedに加える
oEmbedテンプレートには標準テンプレートページと同じようにヘッダーとフッターがあります。embed_headフックを使うとテンプレートのheadで独自スタイルのエンキューのロケーションが得られます。今までと同じようにこのメソッドをフックに加えましょう。
add_action( 'embed_head', array( $this, 'embed_styles' ) );
このフックは独自スタイルをwp_enqueue_style関数と組み合わせて、キューへ追加するのに使えます。あるいはそんなにたくさんのスタイルでなければ、headに直接書くこともできます。
/**
* Embed the plugin's custom styles
*/
public function embed_styles() {
echo <<<CSS
<style>
.wp-embed-excerpt, .wp-embed-author {
font-size: 24px;
line-height: 24px;
margin-bottom: 5px;
}
.wp-embed-author {
float: right;
}
</style>
CSS;
}
JavaScriptについても、JavaScriptファイルをキューへ追加するためのwp_enqueue_script関数など、embed_footerアクションを使って同じように操作できます。またはインラインでも直接記述できます。
最後に
この記事で紹介したのは、oEmbedによって埋め込む内容を好きなように変更したいときに試してほしい、フックの基本です。記事にあるコードはすべてGitHubにあります。
もっとカスタマイズされた例を見たければ、WP-Gistpenの次バージョンをぜひ注目してください。WordPressのoEmbedプロバイダーを使い、シンタックスハイライトされたコードスニペットの埋め込みができるようになります。
(原文:Customizing WordPress oEmbed Content)
[翻訳:加藤由佳]
[編集:Livit]