WordPressアイキャッチをタイトルから自動生成

WordPressアイキャッチをタイトルから自動生成 制作ブログ

ワードプレスを使っていると、記事のアイキャッチがある方が、見た目やSEO的にも良いとされているのですが、記事を書くたびの画像を作るなどの手間があります。
そこで今回は、指定背景にタイトルを自動で載せるだけのアイキャッチを自動生成するボタンをWordPressの投稿一覧につけたいと思います。
メインの処理だけ見たい方は最後のコードを参考にしてください。

PHPのGDライブラリ or imagick

PHPなどで画像加工をする場合はGDライブラリを使うかimagickを利用するのが一般的です。
imagickはImageMagickのAPIをPHPで利用するモジュールで、サーバーにインストールされ使える環境が必要です。
GDライブラリは基本的なものはPHPをインストールする際に入ってあり、拡大縮小など基本的な機能はPHPが稼働している環境で利用できます。
しかし、今回は文字を書くためにGDライブラリではFreeType Support(–with-freetype-dir)が必要だったりPHPのインストール環境によって以外に面倒だったります。
対してimagickはWordPressを利用する前提としてサーバーに環境が整ってる場合が多いので今回はimagickを利用します。
処理そのものはGDライブラリのほうが軽いとされていますが、今回は一度に複数のアイキャッチを作成するのではなく、投稿一覧にボタンをつけて必要なものを1枚生成するだけなので、imagickで問題は対して無いと思われます。

投稿一覧にボタンをつける

WordPressの管理画面の投稿一覧にボタンを付けるために、manage_posts_custom_column にフックして$column_nameがthumbnailの時にボタンのhtmlを追加します。

▼function.phpやplugin.phpなど

add_action( 'manage_posts_custom_column', 'add_column', 10, 2 );
function add_column($column_name, $post_id) {
	if ( 'thumbnail' == $column_name) {
		echo '<span class="button makethumBtn">';
		echo __('Create');
		echo '</span>';
	}
}

 

WordPressの管理画面でjquaryのajax処理

まだまだjquaryとお別れできないので、コードの短縮もあり使っていきます。
コードシンプル化によりerrorや例外処理は省略しています。
まずadmin_enqueue_scriptsにフックして管理ページで読み込むjsを指定しておきます。

▼function.phpやplugin.phpなど

//管理ページでjavascriptを読み込む
add_action('admin_enqueue_scripts',function(){
	wp_enqueue_script( 'my-script', plugins_url( 'myscript.js', __FILE__ ), [ 'jquery' ], filemtime(plugin_dir_path( __FILE__ ).'/myscript.js'), false);
});

ボタンが押された時の処理をjquaryで実装します

▼myscript.js

(function($) {
$(function(){
	$('.makethumBtn').on('click',function(e){

		var button = $(this);
		var postID=$(this).parent('td').siblings('.post-id').text();

		jQuery.ajax({
			url: 'admin-ajax.php?action=myajaxfunc',
			type: 'post',
			data:{
				'mode':'makethumb',
				'postid': postID,
			},
			timeout: 5000,
			beforeSend: function(xhr, settings) {
				button.attr('disabled', true);
			},
			complete: function(xhr, textStatus) {
				button.attr('disabled', false);
			},
			success: function(result, textStatus, xhr) {
				window.location.reload();

			}
		});
	});
});
})(jQuery);

PHPでアイキャッチの生成をする

ここまではWordPressの投稿一覧でボタンを押してjavascriptのjquaryのajaxでPOSTするところまでの例ですので、各々実装方法は異なると思います。
まずは、WordPressのajax処理を追加登録します。
wp_ajax_〇〇〇〇として登録するとログインユーザー用。wp_ajax_nopriv_〇〇〇〇と登録すれば非ログインユーザー用となります。
今回は管理ページ内なのでログインユーザー前提ですので、wp_ajax_myajaxfuncとして登録しています。

▼function.phpやplugin.phpなど

add_action('wp_ajax_myajaxfunc', function() {
	require_once plugin_dir_path( __FILE__ ).'/myajaxfunc.php';
	die();
});

上記function内に直接記述してもかまいませんが、今回は別ファイルで読み込んでいます。
myajaxfunc.phpに対し投稿POSTIDだけPOSTしていますので後はいよいよメインの処理です。

▼myajaxfunc.php

if(isset($_POST['mode'])){$mode=$_POST['mode'];}
if($mode=='makethumb'){

	//プラグインフォルダから背景とフォントを読み込みます
	$baseImg= new Imagick(get_home_path().'wp-content/plugins/〇〇/thumb_bg.png');
	$draw=new ImagickDraw();
	$draw->setFont(get_home_path().'wp-content/plugins/〇〇/thumb_font.ttf');
	$draw->setFontSize( 40 );

	//imagickのカラー設定
	$pixel = new ImagickPixel();
	$pixel->setColor( "#696969" );
	$draw->setFillColor( $pixel );
	//投稿postIDからタイトルを取得
	$title=get_post($_POST['postid'])->post_title;
	$outtxt='';

	//16文字以上なら改行をいれる
	//改行をいれる箇所を正規表現でパターン分けしています
	if(mb_strlen($title)>16){
		$strlen=mb_strlen($title);
		//真ん中前後の接続詞後改行
		if(preg_match('/^(.{'.(intval($strlen/2)-3).','.(intval($strlen/2)+3).'}[を|に|の|で|から|へ])(.+)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		//真ん中前後の句読点削除後改行
		elseif(preg_match('/^(.{'.(intval($strlen/2)-3).','.(intval($strlen/2)+3).'})[,|.|:|、|。](.+)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		//真ん中前後の記号前改行
		elseif(preg_match('/^(.{'.(intval($strlen/2)-3).','.(intval($strlen/2)+3).'})([\(|(|【|「|\-|~].+)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		//真ん中前後の記号後改行
		elseif(preg_match('/^(.{'.(intval($strlen/2)-3).','.(intval($strlen/2)+3).'}[\)|)|】|」|\-|~][^\n]+)(.+)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		//真ん中前後のローマ字とそれ以外の区切りで改行		
		elseif(preg_match('/^(.{'.(intval($strlen/2)-4).','.(intval($strlen/2)+4).'}[a-zA-Z0-9]+)([^a-zA-Z0-9]+.+)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		elseif(preg_match('/^(.{'.(intval($strlen/2)-4).','.(intval($strlen/2)+4).'}[^a-zA-Z0-9]+)([a-zA-Z0-9]+.+)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		//上記の範囲を緩和
		elseif(preg_match('/^(.{'.(intval($strlen/2)-5).','.(intval($strlen/2)+5).'}[を|に|の|で|から|へ])(.*)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		elseif(preg_match('/^(.{'.(intval($strlen/2)-5).','.(intval($strlen/2)+5).'})[,|.|:|、|。](.*)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		elseif(preg_match('/^(.{'.(intval($strlen/2)-5).','.(intval($strlen/2)+5).'})([\(|(|【|「|\-|~][^\n]+)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		elseif(preg_match('/^(.{'.(intval($strlen/2)-5).','.(intval($strlen/2)+5).'}[\)|)|】|」|\-|~][^\n]+)(.*)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}		
		elseif(preg_match('/^(.{'.(intval($strlen/2)-8).','.(intval($strlen/2)+8).'}[a-zA-Z0-9]+)([^a-zA-Z0-9]+.*)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		elseif(preg_match('/^(.{'.(intval($strlen/2)-8).','.(intval($strlen/2)+8).'}[^a-zA-Z0-9]+)([a-zA-Z0-9]+.*)$/u', $title, $m)){$outtxt=$m[1]."\n".$m[2];}
		//半分で強制にわける
		else{$outtxt=mb_substr($title,0,intval($strlen/2))."\n".mb_substr($title,intval($strlen/2));}}
	}else{
		$outtxt=$title;
	}

	//テキストの情報を取得するためのもの
	$metrics = $baseImg->queryFontMetrics( $draw, $outtxt );
	//中央起点にする
	$draw->setTextAlignment(imagick::ALIGN_CENTER);
	//テキストを画像に貼り付けるフォントによって微調整が必要な場合も
	$draw->annotation( $baseImg->getImageWidth()/2, ($baseImg->getImageHeight()-$metrics['textHeight'])/2+$metrics['ascender'], $outtxt );
	$baseImg->drawImage( $draw );
	//ここからはWordPressのフォルダを取得~保存名、保存先
	$wp_upload_dir = wp_upload_dir();
	$thumbname = 'thumb_' . $_POST['postid'] . '.png';
	$thumbpath = $wp_upload_dir['path'] . '/' . $thumbname;
	$thumburl = site_url().'/wp-content/uploads/' . $thumbname;
	
	if($attach_id=attachment_url_to_postid( $thumburl )) {//すでにメディアに登録されている場合、画像だけ更新してアイキャッチに登録して終わる
		$baseImg->writeImage($thumbpath);
		$baseImg->destroy();
		set_post_thumbnail($_POST['postid'], $attach_id);
	}else{
		$baseImg->writeImage($thumbpath);
		$baseImg->destroy();

		//メディアのライブラリに登録する処理
		$wp_filetype = wp_check_filetype($thumbpath, null );
		$attachment = array(
			'post_mime_type' => $wp_filetype['type'],
			'post_title' => sanitize_file_name( $thumbname ),
			'post_content' => '',
			'post_status' => 'inherit'
		);
		$attach_id = wp_insert_attachment( $attachment, $thumbpath);
		
		require_once(ABSPATH . 'wp-admin/includes/image.php');
		$attach_data = wp_generate_attachment_metadata( $attach_id, $thumbname );
		wp_update_attachment_metadata( $attach_id,  $attach_data );

		//アイキャッチに登録
		set_post_thumbnail($_POST['postid'], $attach_id);
	}
	echo 'OK';
	die;
}

終わりに

以上でアイキャッチを自動生成して適応させるボタンの完成です。
文字を中央に描画する所の処理が、GDライブラリでよりも少し楽といったところでしょうか。