WordPress Twenty Twenty 子テーマ作成。カスタマイザーで設定されていなければテーマデフォルトのサイトアイコンを表示する。去年のコードを根底から書き直し。

はじめに

  • サイトアイコン、つまりファビコンを設定するために去年書いた別の子テーマのコードをコピペした。
  • 初めて実施した WordPress コーディングスタイルチェックに引っ掛かり、コードを根底から見直すことにした。

今までのコードを捨て、書き直しに至った経緯

https://github.com/oki2a24/oki2a24com-twentynineteen-child/blob/master/functions.php#L67-L86 をコピペし、パスを整えたり整形したりしました。そして次のコードを書き、動くことを確認しました。

diff --git a/functions.php b/functions.php
index b63fee8..d1761e4 100644
--- a/functions.php
+++ b/functions.php
@@ -29,3 +29,22 @@ function remove_more_link_scroll( $link ) {
        return $link;
 }
 add_filter( 'the_content_more_link', 'remove_more_link_scroll' );
+
+/**
+ * デフォルトのサイトアイコンを設定します。
+ * カスタマイザーで設定された場合はそちらを使用します。
+ */
+function filter_site_icon_meta_tags() {
+       if ( has_site_icon() ) {
+                       return;
+       }
+               $url = get_stylesheet_directory_uri();
+               // 出力される HTML ソースコードを見やすくするめに、最後に空白行を設置
+               echo <<<EOT
+<link rel="icon" href="{$url}/assets/images/cropped-site_icon-32x32.jpg" sizes="32x32" />
+<link rel="icon" href="{$url}/assets/images/cropped-site_icon-192x192.jpg" sizes="192x192" />
+<link rel="apple-touch-icon-precomposed" href="{$url}/assets/images/cropped-site_icon-180x180.jpg" />
+<meta name="msapplication-TileImage" content="{$url}/assets/images/cropped-site_icon-270x270.jpg" />
+EOT;
+}
+add_filter( 'wp_head', 'filter_site_icon_meta_tags' );

次に composer checkcs を実行しました。そうしましたら、残念ながら次のチェックに引っ掛かってしまいました><。

$ composer checkcs
> @php ./vendor/squizlabs/php_codesniffer/bin/phpcs --runtime-set testVersion 5.6-
E 1 / 1 (100%)

FILE: functions.php
----------------------------------------------------------------------
FOUND 5 ERRORS AND 1 WARNING AFFECTING 6 LINES
----------------------------------------------------------------------
 42 | ERROR   | Inline comments must end in full-stops, exclamation
    |         | marks, or question marks
    |         | (Squiz.Commenting.InlineComment.InvalidEndChar)
 43 | WARNING | All output should be run through an escaping function
    |         | (see the Security sections in the WordPress Developer
    |         | Handbooks), found '<<<EOT
    |         | '.
    |         | (WordPress.Security.EscapeOutput.OutputNotEscaped)
 44 | ERROR   | Code for favicon found. Favicons are handled by the
    |         | "Site Icon" setting in the customizer since WP
    |         | version 4.3.
    |         | (WPThemeReview.CoreFunctionality.NoFavicon.NoFavicon)
 45 | ERROR   | Code for favicon found. Favicons are handled by the
    |         | "Site Icon" setting in the customizer since WP
    |         | version 4.3.
    |         | (WPThemeReview.CoreFunctionality.NoFavicon.NoFavicon)
 46 | ERROR   | Code for favicon found. Favicons are handled by the
    |         | "Site Icon" setting in the customizer since WP
    |         | version 4.3.
    |         | (WPThemeReview.CoreFunctionality.NoFavicon.NoFavicon)
 47 | ERROR   | Code for favicon found. Favicons are handled by the
    |         | "Site Icon" setting in the customizer since WP
    |         | version 4.3.
    |         | (WPThemeReview.CoreFunctionality.NoFavicon.NoFavicon)
----------------------------------------------------------------------

Time: 116ms; Memory: 12MB

Script @php ./vendor/squizlabs/php_codesniffer/bin/phpcs --runtime-set testVersion 5.6- handling the checkcs event returned with error code 1

$

特に次の内容が辛いです。

Code for favicon found. Favicons are handled by the "Site Icon" setting in the customizer since WP version 4.3. (WPThemeReview.CoreFunctionality.NoFavicon.NoFavicon)

ファビコンはカスタマイザーの "サイトアイコン" 設定から操作するべきで、 HTML コードを出力するべきではない、そんな内容です。

考え方

小手先の修正ではなく、根本から考え直す必要がありました。 つまり、 <link><meta>echo などで出力する方法は一切使えません。

代わりに、元々これらを出力する箇所を特定し、その部分のさらにサイトアイコン URL を出力する部分を見つけ、その出力内容を変更すれば良さそうです。

wp_site_icon() | Function | WordPress Developer Resources がファビコンを HTML 出力する関数です。

そして、この関数の get_site_icon_url() がサイトアイコン URL を返す関数です。

get_site_icon_url() はありがたいことに、最後に URL を return する際に、外部から介入できるよう、フィルターフックをかませるように作られています。

return apply_filters( 'get_site_icon_url', $url, $size, $blog_id );

ですので、 get_site_icon_url フィルターフックを利用する関数を ./functions.php に定義し、そこでカスタマイザーでサイトアイコン未設定ならばデフォルトのサイトアイコン URL を返すようにしてやれば良さそうです♪

apply_filters と add_filter についてのお勉強

勉強の仕方

参考ページ

を読んで、よくわからない、疲れているからかな? となったあと、寝て起きて、もう一度いろいろ読み、公式ページ翻訳

も読んだり、ログ出力したりして理解しました。

apply_filters の情報から add_filter を使うまでの道筋

get_site_icon_url() | Function | WordPress Developer Resources からソースコードの次に注目します。

return apply_filters( 'get_site_icon_url', $url, $size, $blog_id );

これは次を意味しています。

  • get_site_icon_url フックの関数をここで実行する。
  • フックの関数に渡す引数は、最大 3 つで $url, $size, $blog_id 。

では実際にフックの関数を定義し、介入します。自作の子テーマの ./functions.php です。

まずは、介入できることだけ確認します。次のコードで確認できるはずです (実際にはこのコードを実行はしていません。解説用に書きました) 。

function sample( $url, $size ) {
    error_log('sample $url: ' . $url . ', $size: ' . $size);
    return $url
}
add_filter( 'get_site_icon_url', 'sample', 10, 2 );

add_filter で介入する関数についての情報を定義して渡しています。つまり、次を意味しています。

  • get_site_icon_urlapply_filters 時に実行する関数名は sample です。
  • sample 関数の実行優先順はデフォルトの 10 です。これは定義しなくてもよい不要な情報ですけれども、これがないと定義したい次の引数が定義できないのでデフォルト値を定義しています。
  • 2 は、 sample 関数へ渡す引数の数です。 apply_filters でフック関数へ最大 $url, $size, $blog_id の 3 つの引数を渡すことが可能です。今回は、 $url と $size が欲しいですので、 2 を設定しました。

あとは、 sample 関数が実行されたことを確かめます。

  • error_log で sample 関数の引数が渡ってきたことを確認しています。
  • return $url で介入した sample 関数で何もしなかった場合の結果を返しています。フックした関数で何もしなかった場合は介入しない場合と同じ結果を得体ですので、ここは重要です。

ここまでできればあと少しです。特に難しいことはなく、ただやりたいことを書くだけです。

カスタマイザーでサイトアイコン未設定ならばデフォルトのサイトアイコン URL を返すようにするコード

子テーマの ./functions.php に次のように書きました。

/**
 * デフォルトのサイトアイコンを設定します。
 * カスタマイザーで設定された場合はそちらを使用します。
 *
 * @param string $url サイトアイコン URL .
 * @param int    $size サイトアイコンサイズ .
 * @return string $url
 */
function get_default_site_icon_url( $url, $size ) {
        if ( $url ) {
                return $url;
        }
        $default_url = get_stylesheet_directory_uri() . '/assets/images/cropped-site_icon-' . $size . 'x' . $size . '.jpg';
        return $default_url;
}
add_filter( 'get_site_icon_url', 'get_default_site_icon_url', 10, 2 );

ポイントです。

  • カスタマイザーでサイトアイコン設定済みの場合、 get_site_icon_url() の apply_filters の実行前に $url に文字列が設定されています。未設定なら設定されていません。ですので $url を判定して、未設定なら子テーマデフォルトの URL を設定します。
  • サイトアイコンのために最終的に次の 4 つの HTML を出力したいです。これら 4 つの HTML 出力は別のところでやってくれるので、 href 部分のみを介入する関数で組み立てて返せばよいです。違いはサイズのみで、 32, 192, 180, 270 。これらが介入関数の $size としてやってきます。それを利用するだけです。
<link rel="icon" href="http://localhost:8080/wp-content/themes/oki2a24com-twentytwenty-child/assets/images/cropped-site_icon-32x32.jpg" sizes="32x32" />
<link rel="icon" href="http://localhost:8080/wp-content/themes/oki2a24com-twentytwenty-child/assets/images/cropped-site_icon-192x192.jpg" sizes="192x192" />
<link rel="apple-touch-icon-precomposed" href="http://localhost:8080/wp-content/themes/oki2a24com-twentytwenty-child/assets/images/cropped-site_icon-180x180.jpg" />
<meta name="msapplication-TileImage" content="http://localhost:8080/wp-content/themes/oki2a24com-twentytwenty-child/assets/images/cropped-site_icon-270x270.jpg" />

補足。デバッグの仕方

確認したい変数の中身を、 error_log($variable) で出力し、 docker-compose logs -f で内容を確認しました。

ですので、そもそも開発環境として、本番環境は使わず、 Docker の環境を使用しています。

おわりに

前回までは、WordPress コーディングスタイルは適用の仕方がわからなかったということもあり使用していませんでした。今回は、親テーマがやっているように composer.json を作ればコーディングスタイルの適用ができたので、積極的に使うことにしました。

その結果、根底からコードを見直さなければならなくなったので、ノートいたしました。

以上です。

コメントを残す

コメントを残す