本題に入る前に
WordPress の フィルター関数(add_filter
)を利用すれば、ウィジェットで表示されるコンテンツ(HTML)を事前に取得して目的に応じて一部を置換したり書き換えることができます。
例えば、テキストウィジェットが表示される前にコンテンツをチェックしたい場合は以下のようにします。
add_filter( 'widget_text', 'custom_filter_widget_text' ); function custom_filter_widget_text( $content ) { // テキストウィジェットの中身( $content )を書き換える処理 return $content; }
widget_text フィルターと wp_head アクションの実行順序
このアクションフィルターを利用して、テキストウィジェットのコンテンツ内に特定のタグや文字列がある場合は、その特定のコンテンツを表示するために head セクション内に必要な CSS や JavaScript などのリソースを挿入させるため、add_action
関数を利用して wp_head
アクションフックに処理を登録しようとしたところ、どうやら wp_head
アクションフックは widget_text
アクションフィルターよりも先に実行されるため、このフィルター内の処理として add_action( 'wp_head', 'my-function' )
のように wp_head
アクションフックを指定しても意味がないことがわかりました。
例えば、ページを AMP に対応するため、テキストウィジェット内に iframe タグが見つかった場合は、AMP タグ(amp-iframe)への自動変換と AMP での埋め込みタグに必要な各種専用モジュール(JavaScript)を head セクション内に自動挿入する場合、widget_text
アクションフィルターと wp_head
アクションフックを利用しても実現できません。
wp_head よりも先にウィジェットの中身を取得、判定
wp_head
アクションフックや header.php が処理される前に特定のウィジェットの表示コンテンツを取得し、その内容に応じて今回のように head セクション内に必要なタグを挿入するような場合は、wp_get_sidebars_widgets
という追加されているすべてのウィジェットを取得できる関数を利用します。
// すべてのウィジェットデータを取得 $all_widgets = wp_get_sidebars_widgets();
取得したすべてのウィジェットの中から、ウィジェットエリアの ID を指定して対象エリアを絞り込みます。
ウィジェットエリアの ID は、register_sidebar
関数で指定した id キーの値です。
// 対象のウィジェットエリア(widget-area-1, widget-area-2 の部分)のウィジェットデータのみを取得 $target_widgets[] = $all_widgets['widget-area-1']; $target_widgets[] = $all_widgets['widget-area-2'];
対象のウィジェットエリアを絞り込んで、そこにあるすべてのウィジェットを取得したら、後はそれらに任意のウィジェット(ここではテキストウィジェットとカスタムHTMLウィジェット)が存在する場合に必要な処理を実行させます。
// 取得した対象エリアにあるウィジェットを順にチェック foreach ( $target_widgets as $widgets ) { if ( !empty( $widgets ) ) { // 各ウィジェットのIDを順にチェック foreach ( $widgets as $widget_id ) { // カスタムHTMLウィジェットが見つかった場合 if ( strpos( $widget_id, 'custom_html-') !== false ) { // 対象のウィジェットのID(数値)のみを取得 $wid = (int)str_replace( 'custom_html-', '', $widget_id ); // すべてのカスタムHTMLウィジェットの取得 $content = get_option( 'widget_custom_html' ); if ( !empty($content) && is_array($content) ){ // すべてのカスタムHTMLウィジェットから対象ウィジェットのコンテンツのみを取得 $content = $content[$wid]['content']; // 以下に iframe が見つかったらコンテンツ($content)を書き換えたり wp_head アクションを実行したりする処理 } } // テキストウィジェットが見つかった場合 else if ( strpos( $widget_id, 'text-') !== false ) { // 対象のウィジェットのID(数値)のみを取得 $wid = (int)str_replace( 'text-', '', $widget_id ); // すべてのテキストウィジェットの取得 $content = get_option( 'widget_text' ); if ( !empty($content) && is_array($content) ){ // すべてのテキストウィジェットから対象ウィジェットのコンテンツのみを取得 $content = $content[$wid]['text']; // 以下に iframe が見つかったらコンテンツ($content)を書き換えたり wp_head アクションを実行したりする処理 } } } } }
これらの処理を関数にまとめておいて、wp_head
よりも先に実行されるアクションフィルターの処理として実行すればOKです。
ちなみに、add_action
で実行(do_action
)される各アクションフックの実行順序は、以下のようです。
dp_action
で実行されるアクションフックの実行順序の詳細については以下が参考になります。