WordPress Embed と内部ブログカード

WordPress は標準の機能で、ブログや YouTube の動画、ツイート、音楽などの様々なコンテンツを、簡単にそして安全に埋め込むことができます。

一般的に 「Embed」といわれている機能です。ブログなどでは「ブログカード」などとも言われています。

oEmbed

埋め込みできるコンテンツのほとんどは、oEmbed によって提供されています。oEmbed とは埋め込み用のコンテンツを取得するためのプロトコルです。

はてなブログや YouTube、Twitter も、oEmbed プロバイダー(埋め込まれる側)に対応しているため、埋め込むことができるわけです。

WordPress 自体も oEmbed プロバイダーに対応(バージョン 4.4 以降)しているので、外部の WordPress サイトもサイト内でも埋め込むことができます。

コンテンツを埋め込むには、Embed ショートコードまたは、単に URL(独立した行)を記述するだけです。

内部ブログカード

便利な機能ではあるのですが、埋め込みに失敗して URL だけが表示されることがよくあります。なぜ、そうなるかはここでは置いておくとして、外部サイトが失敗するのは仕方がないとしても、サイト内の埋め込みが失敗するのは避けたいところです。その為に、ブログカードを表示するプラグインを使用するのもいいかもしれませんが、既存の記事を変更しないといけなかったりするので、ここでは手軽な方法として、記事の変更をすることなくサイト内の記事のみを対象に、独自のブログカード(以降「内部ブログカード」と表記)を表示する方法とします。

処理としては、Embed ショートコードで指定された URL が、サイト内の記事の場合のみ内部ブログカードを出力し、それ以外は標準の埋め込みコードとします。URL の記述も、内部的には Embed ショートコードに変換されているので対象となります。

方法はとっても簡単です。embed_oembed_html フィルタフックで埋め込みコードを変更することができるので、ここで URL がサイト内の記事の場合のみ、内部ブログカードへ変更します。

コードは下記の通りです。functions.php 等に追記してください。

/**
 * Generates excerpts for Blog Card from content.
 *
 * @param WP_Post $post Post object.
 * @return string The excerpt.
 */
function get_excerpt_for_blog_card( $post ) {
	$excerpt = trim( $post->post_excerpt );
	if ( ! $excerpt ) {
		$excerpt = apply_filters( 'the_content', strip_shortcodes( $post->post_content ) );
		$excerpt = str_replace( ']]>', ']]>', $excerpt );
	}
	$excerpt = wp_trim_words( $excerpt, 55, ' …' );
	return $excerpt;
}

/**
 * Generates Blog Card HTML.
 *
 * @param int $post_id The post ID.
 * @param string|array $size Optional. Image size to use. Accepts any valid image size, or an array of width and height values in pixels (in that order). Default array( 150, 150 ).
 * @return string Blog Card HTML.
 */
function get_blog_card( $post_id, $size = array( 150, 150 ) ) {
	$html = '';

	$post_query = new WP_Query( array(
		'p' => $post_id,
		'post_type' => 'any',
		'posts_per_page' => 1,
	) );
	if ( $post_query->have_posts() ) {
		while ( $post_query->have_posts() ) {
			$post_query->the_post();

			$permalink = get_permalink();

			$html .= '<div class="blog-card">';
			$html .= ( has_post_thumbnail() ? '<div class="blog-card-thumbnail"><a href="' . $permalink . '">' . get_the_post_thumbnail( null, $size ) . '</a></div>' : '' );
			$html .= '<div class="blog-card-content">';
			$html .= '<div class="blog-card-title"><a href="' .  $permalink . '">' . get_the_title() . '</a></div>';
			$html .= '<div class="blog-card-excerpt">' . get_excerpt_for_blog_card( $post_query->post ) . '</div>';
			$html .= '<div class="blog-card-footer"><span class="blog-card-more"><a href="' . $permalink . '">' . __( '記事を読む' ) . '</a></span></div>';
			$html .= '</div>';
			$html .= '</div>';
		}
		wp_reset_postdata();
	}

	return $html;
}

/**
 * embed_oembed_html wraps the filter.
 */
function blog_card_site_oembed_html( $html, $url ) {
	$post_id = url_to_postid( $url );
	if ( $post_id && ! is_admin() ) {
		$html = get_blog_card( $post_id );
	}
	return $html;
}

add_filter( 'embed_oembed_html', 'blog_card_site_oembed_html', 100, 2 );

スタイル(CSS)のサンプルは下記の通りです。

/*
Blog Card
*/
.blog-card {
	margin-bottom: 10px;
	padding: 15px;
	border: 1px solid #ccc;
	border-radius: 3px;
}
.blog-card:after {
	content: " "; 
	display: block;
	clear: both;
}
.blog-card-thumbnail {
	float: left;
	margin-right: 15px;
}
.blog-card-thumbnail img {
	object-fit: cover;
	width: 150px;
}
.blog-card-title {
	line-height: 1.4;
	margin: 0 0 0.75em;
	padding: 0;
	color: #333;
	font-size: 1.4rem;
	font-weight: 800;
}
.blog-card-title a {
	color: #333;
	text-decoration: none;
}
.blog-card-title a:visited {
	color: #444;
}
.blog-card-footer {
	margin-top: 0.25em
}

エディタ内

なお、上記のコードは、エディタ内では内部ブログカードでも標準の埋め込みコードを表示するようにしています。エディタ内においても、内部ブログカードを表示する場合は、下記のように変更してください。

変更前:

function blog_card_site_oembed_html( $html, $url ) {
	$post_id = url_to_postid( $url );
	if ( $post_id && ! is_admin() ) {
		$html = get_blog_card( $post_id );
	}
	return $html;
}

変更後:

function blog_card_site_oembed_html( $html, $url ) {
	$post_id = url_to_postid( $url );
	if ( $post_id ) {
		$html = get_blog_card( $post_id );
	}
	return $html;
}

また、エディタ用スタイルシート(editor-style.css)にも、スタイルを追記してください。

コメントを残す

メールアドレスが公開されることはありません。

日本語でコメントを入力してください。