問題:WordPressをアップデートしたらショートコードが動いてない
「なんか、サイトによくわからない英語が表示されてるんですが」
見てみると独自ショートコードが実行されずまんま出力されている
(あ・・これあかんやつや)
経験上このタイプのトラブルはWordPressの仕様変更などに起因していて、往々にして少しの修正では済まないし、場合によっては実質対応が不可能な場合さえある。
原因:ブロックテーマでは剥き出しのショートコードは動かなくなった
同じショートコードを使っていても、ブロックテーマではないサイトでは問題なく動いている、ブロックテーマのサイトでもWordPressのアップデートがまだのサイトでは動いている、WordPressのブロックテーマ周りの仕様変更がどうやら原因のようだ。
一部ショートコードが動かなくなったサイトでも、同じショートコードが動いているところもある、違いはどうやら、テンプレートエディタで直接設置されたブロックであるかどうかというところのようだ。
対応:テンプレートはテンプレートパーツを組み合わせて編集するルールに
調べたところ、テンプレートエディタに書かれた剥き出しのショートコードを動かないようにしたのはセキュリティ上の懸念があってのことということなので、無理矢理これを動かせるようにするのはあまりよろしくないようだ。
テンプレートパーツブロックに入れることでショートコードが実行されるようなので、テンプレートエディタで剥き出しになっているブロックをテンプレートパーツに入れてショートコードを動くようにした。テンプレート編集の際は、まずテンプレートパーツを作ってテンプレートはそれを組み合わせて作るというルールを徹底してもらうことにしてショートコードが実行されない問題は解決。
かと思った。
問題:まだ動かないショートコードがいる
とりあえずショートコードの実行自体はされるようになったようだとホッとしたのも束の間、意図しない出力をするやつ、出力がされないやつ、やっぱり実行されないやつがいる。見たところサーバーサイドレンダーを使っているものやループのコンテキストに依存したショートコードが動いていないようだ。
原因:ブロックテーマではdo_shortcodeの後にdo_blocksが実行される
ブロックテーマではdo_shortcodeがdo_blocksより先に実行される。これがどういうことを意味するかというと、ブロックがrender_callbackでショートコードを出力しても実行されないし、逆にrender_callbackが受け取るcontentsはすでにショートコードが実行されてしまっているということである。
$content = $wp_embed->run_shortcode( $_wp_current_template_content );
$content = $wp_embed->autoembed( $content );
$content = do_blocks( $content );
$content = wptexturize( $content );
$content = convert_smilies( $content );
$content = shortcode_unautop( $content );
$content = wp_filter_content_tags( $content, 'template' );
$content = do_shortcode( $content );
$content = str_replace( ']]>', ']]>', $content );
参照:get_the_block_template_html
ブロックテーマでなければ、do_blocksが全部終わった後に適用されるthe_contentフィルタフックのdo_shortcodeでまとめて実行されていた。なので、render_callbackでループを書いてcontents内のショートコードをグローバル変数を変えながら実行したり、あるいはショートコードを出力して、親ブロックのコンテキストでそのショートコードを実行するなんてことができていたのだが、これができなくなってしまった。
対応:独自ショートコードをWordPressのショートコードから独立して処理
とりあえず、原因特定まではそれほど時間が掛からなかったが、これはWordPressの処理を読み直さなければ適切に対処ができない、時間がかかる問題だということも同時にわかった。
なので一旦は応急処置でrender_callbackとショートコードを組み合わせて使わないブロックに置き換えた。見た目が少し変わってしまったところもあるものの、内容としては同じものが表示されている状態までは復旧できた。
表向きは問題は解決したわけが、ここからが本番。
フィルタフックでどうにかできないものかと、ブロックテーマでコンテンツがどのように出力されているのかWordPressのコードを追ってみたがこれはどうにもなりそうになかった、そもそもフィルタフックがほとんどなかった。
独自ショートコードの登録を遅らせるなども試みたが、ショートコードを実行したいタイミングの後でまたショートコードを実行したくないタイミングがあったりして断念した。
結局、独自ショートコードをWordPressのショートコードとして登録することはせず、独自ショートコードの実行を自前で実装してcore/template-part及びthe_contentのフィルタフックで処理するというおよそ力技な方法で対処した。
実のところ、hrefとかclassとかでショートコードが使えるようにhtmlの属性値内のショートコードを実行したい需要もあったので丁度良かった。
まとめ
今回のWordPress6.3のブロックテーマでのショートコードの扱いに関する変更への対応は、ブロックのrender_callbackでの入出力に絡んだところで問題が起きた場合は簡単な対処方法はないようだ。