WordPressで記事内に特定のショートコードが入っているかを判定する関数がhas_shortcode。
if ( has_shortcode( $content, 'shortcode' ) ) {
// $content内にショートコード[shortcode]が入っているときにtrueになる
}
という感じで使うんだけど、どうも入っているショートコードが判定できていない。しかも本番環境だけ。
テスト環境では同じショートコードで意図通りの挙動になっていたので頭をひねるばかり。
##本番環境とテスト環境での $post->post_content の内容の違い
記事自体の内容をよくよく見直していると、テスト環境ではショートコードを記事に直に書いていたが、本番環境では作業効率化のためにショートコードをGutenbergの再利用可能ブロックとして登録していた。
has_shortcodeに渡していた内容が $post->post_content。この内容を見てみると、ショートコードを直に書いていた場合はショートコードがそのまま入っている状態=意図した内容がきちんと渡されていたが、再利用可能ブロック化した場合にここに入っているのが<!-- wp:block なんちゃら〜〜〜 /-->という形式のGutenbergのブロック要素。$post->post_contentの段階ではブロック要素が展開されてない、ってことだった。
##ブロック要素だけ展開する
ではこのブロック要素を展開するにはどうしたらいいのか。the_contentまでいってしまうとショートコードまで展開されてしまうので、その前段階のブロック要素のみを展開する方法はないだろうか。ヒントは wp-includes/default-filters.php に記載されていた。
add_filter( 'the_content', 'do_blocks', 9 );
名前的にドンピシャだしリファレンスみてもそのとおり。
https://developer.wordpress.org/reference/functions/do_blocks/
なのでhas_shortcodeにわたす$contentをこんな感じにして解決。
$content = do_blocks( $post->post_content );
今 has_shortcode を検索すると、 has_shortcode に渡す代表的なものに $post->post_contentって挙げられてるけど、 $post->post_content ではGutenbergのブロック要素が展開されていないから注意しようね、って話だったとさ。