WordPress のカスタム投稿タイプでツイートのような機能を持たせようと遊んでいて、投稿タイプの設定でタイトルを無効にしたのだが、自動で Auto Draft というタイトルが挿入されてしまう。これを投稿内容の先頭の何文字かをタイトルに充てるということをしたい。要は、特定の投稿タイプの記事タイトルを保存時に編集するということだ。
何が問題かというと、コメントのウィジェットなどで、うっかりタイトルが表示されてしまったりするので、そのための対応。
wp_insert_post_data フィルターフック
データベースに保存時の記事タイトルの変更は wp_insert_post_data
フィルターフックを使えば簡単にできる。一つ目のパラメーターが配列として渡され、その中の、post_title
を編集して、配列を返してあげれば良い。
その配列の中に post_type
という要素があるので、それで指定した投稿タイプのスラッグと一致するかをチェックすればやりたいことはできる。
渡される配列のストラクチャーはこんな感じ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[post_author] => (string, length: 1) 1 [post_date] => (string, length: 19) 2019-11-30 20:47:14 [post_date_gmt] => (string, length: 19) 0000-00-00 00:00:00 [post_content] => (string, length: 59) <!-- wp:paragraph --> <p>テストノート。</p> <!-- /wp:paragraph --> [post_content_filtered] => (string, length: 0) [post_title] => (string, length: 7) テストノート [post_excerpt] => (string, length: 0) [post_status] => (string, length: 5) draft [post_type] => (string, length: 4) note [comment_status] => (string, length: 4) open [ping_status] => (string, length: 6) closed [post_password] => (string, length: 0) [post_name] => (string, length: 0) [to_ping] => (string, length: 0) [pinged] => (string, length: 0) [post_modified] => (string, length: 19) 2019-11-30 20:47:14 [post_modified_gmt] => (string, length: 19) 2019-11-30 11:47:14 [post_parent] => (integer, length: 1) 0 [menu_order] => (integer, length: 1) 0 [post_mime_type] => (string, length: 0) [guid] => (string, length: 76) ..... |
で、今回、記事内容の一部をタイトルにするということで、日本語の場合、WordPress の関数 wp_trim_words()
はきちんと文字数を認識してくれないので、カスタム関数を書いて mbstring 系の関数を使って処理する必要がある。
コード
ささっと処理用のクラスを書いた。
クラス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
class PostTitleModifierOnSave { private $___bMBExtension = false; private $___sBlogEncoding = 'UTF-8'; private $___aPostTypeSlugs = array(); public function __construct( array $aPostTypeSlugs=array(), $sBlogEncoding='UTF-8' ) { $this->___bMBExtension = function_exists( 'mb_strlen' ); $this->___aPostTypeSlugs = $aPostTypeSlugs; $this->___sBlogEncoding = $this->___sBlogEncoding ? $this->___sBlogEncoding : 'UTF-8'; add_filter( 'wp_insert_post_data' , array( $this, 'replyToModifyPostTitle' ) , '99', 1 ); // Grabs the inserted post data so you can modify it. } public function replyToModifyPostTitle( $aData ) { if ( ! in_array( $aData[ 'post_type' ], $this->___aPostTypeSlugs ) ) { return $aData; } $aData[ 'post_title' ] = $this->getWordsTrimmed( $aData[ 'post_content' ] ); return $aData; } private function getWordsTrimmed( $sText='', $iCharacterLength=55, $sSuffix='…' ) { $sText = wp_strip_all_tags( $sText ); $sText = trim( preg_replace("/[\n\r\t ]+/", ' ', $sText ), ' ' ); if ( ! $this->___bMBExtension ) { return wp_trim_words( $sText, $iCharacterLength, $sSuffix ); } if ( mb_strlen( $sText, $this->___sBlogEncoding ) > $iCharacterLength ) { $sText = mb_substr( $sText, 0, $iCharacterLength, $this->___sBlogEncoding ) . $sSuffix; } return $sText; } } new PostTitleModifierOnSave( array( 'note' ), get_option( 'blog_charset', 'UTF-8' ) ); |
使い方
テーマの functions.php
に放り込むなどを想定している。 使い方は、クラスをインスタンス化するだけ。その時に、2つパラメーターを渡してあげる。
- ( array ) 目的の投稿タイプスラッグ e.g.
array( 'my_post_type', 'another_post_type' )
- ( string ) サイトで設定されているキャラクターエンコーディング e.g.
UTF-8
上の例では note
という投稿タイプスラッグの場合は、記事内容の最初の55文字だけ抜き取ってタイトルにしてあげてね、という感じ。
getWordsTrimmed()
メソッドで文字列を編集しているので、このメソッドを名称を変えるなどしてカスタマイズして使えば別の用途に応用できるだろう。
結果
結果はこんな感じになる。