wp_get_document_title, title-tagが貧弱なので改造する|WordPress

WordPress 4.4 からwp_titleの代替として利用が可能となっているwp_get_document_title関数ですが、いまいち使い勝手が良くありません。

フィルターフックも用意されておらず、wptexturizeconvert_chars, esc_html, capital_P_dangitなどの変換関数は強制適用されてしまいます。

※ WordPress 5.8からフィルターフックに対応しました。

他にも、区切り文字の両端に空白が強制挿入されてしまうという問題があります。

全角区切りPageTitle|BlogNamePageTitle | BlogNameになってしまう

wp_get_document_titleの実装を調査してみましたが、これは仕様上どうにもならないようなので、同機能を独自実装をすることにしました。

駄目だこいつ…早くなんとか改良しないと……。

というわけで分解改造してみました。

そもそもWordPress 5.8以降のバージョンであればフィルターフック名document_titleにてフィルターの除去が可能となっています(例:remove_filter('document_title', 'capital_P_dangit');)。
セパレーターの両端に空白が強制挿入されてしまう問題は依然として残っていますが、document_titleに文字列置換用のフィルターを追加するなりして対処することは可能となっています。
add_filter('document_title_separator', function () { return '###### document_title_separator ######'; }); add_filter('document_title', function ($s) { return str_replace(' ###### document_title_separator ###### ', '|', $s); });

どうしてもwp_get_document_titleを自作したい場合は以下の冒涜的なコードを参考にしてください。

function mc_get_document_title() {
  if ($s = apply_filters('mc_pre_get_document_title', '')) { return $s; }
  $a = array('title' => '');
  
  /**/ if (is_404())    { $a['title'] = __('Page not found'); }
  else if (is_search()) { $a['title'] = sprintf(__('Search Results for “%s”'), get_search_query()); }
  else if (is_front_page()) { $a['title'] = get_bloginfo('name', 'display'); }
  else if (is_post_type_archive())     { $a['title'] = post_type_archive_title('', false); }
  else if (is_tax())                   { $a['title'] = single_term_title('', false); }
  else if (is_home() || is_singular()) { $a['title'] = single_post_title('', false); }
  else if (is_category() || is_tag())  { $a['title'] = single_term_title('', false); }
  else if (is_author() && $author = get_queried_object()) { $a['title'] = $author->display_name; }
  else if (is_year())  { $a['title'] = get_the_date(_x('Y', 'yearly archives date format')); }
  else if (is_month()) { $a['title'] = get_the_date(_x('F Y', 'monthly archives date format')); }
  else if (is_day())   { $a['title'] = get_the_date(); }
  
  global $page, $paged;
  if (($paged >= 2 || $page >= 2) && ! is_404()) { $a['page'] = sprintf(__('Page %s'), max($paged, $page)); }
  
  if (is_front_page()) { $a['tagline'] = get_bloginfo('description', 'display'); }
  else { $a['site'] = get_bloginfo('name', 'display'); }
  
  $sep = apply_filters('mc_document_title_separator', ' - ');
  $a = apply_filters('mc_document_title_parts', $a);
  $s = implode($sep, array_filter($a));
  return apply_filters('mc_get_document_title', $s);
}

add_filter('mc_get_document_title', 'wptexturize');
add_filter('mc_get_document_title', 'convert_chars');
add_filter('mc_get_document_title', 'esc_html');
add_filter('mc_get_document_title', 'capital_P_dangit');

利用時は以下のように不要なフィルターを除去して使います。

// 不要なフィルターを除去
remove_filter('mc_get_document_title', 'wptexturize');
remove_filter('mc_get_document_title', 'convert_chars');
remove_filter('mc_get_document_title', 'esc_html');
remove_filter('mc_get_document_title', 'capital_P_dangit');
// セパレーターを全角文字にする
add_filter('mc_document_title_separator', function () { return '|'; });

add_theme_support('title-tag')の時のようにタイトルを自動表示したい場合には、wp_headにアクションを追加することで同等の機能を実現します。

add_action('wp_head', function () {
  echo '<title>' . mc_get_document_title() . '</title>' . "\n";
}, 1);
広告
広告