WordPress カスタマイザーのサニタイズ方法まとめ

最終更新日

Comments: 0

テーマを WordPress の公式ディレクトリに掲載させるためにはカスタマイザーのサニタイズが必須になります。
このチェック項目は Theme Check プラグインに組み込まれていて、全部正しくサニタイズがなされていないとテーマのアップロードすら出来ません。

必須: サニタイゼーションコールバック関数を使っていないカスタマイザー設定があります。add_setting() メソッドへのコールはすべてサニタイゼーションコールバック関数を通す必要があります。

っていうエラーが出ます。

サニタイズの役割

サニタイズとは一種のバリデーションチェックのようなものです。WordPress カスタマイザーでは指定されたコントロールタイプに対してユーザーの入力したデータが正しいかを検証し、正しくない場合はそのデータを破棄させたり、値の中で無効な文字列を削除したりします。これによりセキュリティ問題やコードのコンフリクトを防ぐことが出来ます。

例えばカラースキームの入力欄に "#zzzzzz" のように不正な文字列を入力すると、以下の画像のように入力欄が赤くなり、文字列が正しくないことを知らせます。この状態で「保存して公開」しても文字列は保存されません。

スポンサーリンク

サニタイズコールバックを呼び出す

サニタイズ用の関数を用意した上で add_settings の配列に sanitize_callback を追加することでコールバックが呼び出されます。
例:

$wp_customize->add_setting( 'link_color', array(
    'default'    => '#00619f',
    'sanitize_callback' => 'sanitize_hex_color',
));
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'link_color', array(
    'label'      => __( 'Link Color', 'coldbox' ),
    'section'    => 'colors',
    'settings'   => 'link_color',
)));

種類別サニタイズ手順

16進数のサニタイズはコアに関数が用意されています。
sanitize_hex_color を使用することが可能です。

テキスト

sanitize_text_field という関数が使えます。
ただしこの関数は、HTML タグをすべて消したり、> をエスケープしたり、無駄な空白や改行を削除したりとなんか色々強力なサニタイズをします。
そこまで強力なエスケープを必要としない場合や HTML を使用したい場合は、wp_filter_nohtml_kses (ただ HTML タグを抜くだけ) や、後述の wp_filter_post_kseswp_kses 等と使い分けましょう。

HTML

wp_filter_post_kses が使えます。
ただしこれだとほぼすべての HTML タグが使えてしまいますので、一部の HTML タグで十分な場合は、出力する段階で wp_kses 関数を使用し、使用できる HTML を制限するのがベターです。wp_kses を使う場合でもカスタマイザーへのサニタイズは必要になりますので、忘れずに sanitize_callback を指定しましょう。

wp_kses
この関数を使用することで使用できる HTML タグを制限することが出来ます。
例:

function czr_text() {
    $text = get_theme_mod( 'text', 'example' );
    $allowed_html = array(
        'a' => array( 'href' => array (), 'onclick' => array (), 'target' => array(), ),
        'br' => array(),
        'strong' => array(),
        'b' => array(),
    );
    return wp_kses( $text, $allowed_html );
}

この例では <a>, <br>, <strong>, <b> のみのタグが使用でき、それ以外は無視されるようになります。

Email

sanitize_email が使えます。メールアドレスには使用できない文字列をすべて排除する関数です。例えば、"example@exaple.com!" みたいなのが入力されると自動で "example@example.com" に変換されます。

URL

esc_url_raw が使えます。アンド記号やシングルクォーテーション等の記号がそれぞれエスケープされて保存されます。

チェックボックス

カスタマイザーでよく使われるチェックボックスですが、これはコアで用意されてないので自分で定義する必要があります。

function theme_slug_sanitize_checkbox( $checked ) {
    return ( ( isset( $checked ) && true == $checked ) ? true : false );
}

を定義し、 sanitize_callbacktheme_slug_sanitize_checkbox を使いましょう。

("theme_slug"部分は自分のテーマの slug と適意置き換えてください)

ラジオボタン・セレクトボックス

こちらもよく使われている印象がありますが、コアでの用意はありません。
radioselect は同一コードで対応できます。

function theme_slug_sanitize_select( $input, $setting ) {
    $input = sanitize_key( $input );
    $choices = $setting->manager->get_control($setting->id)->choices;
    return ( array_key_exists( $input, $choices ) ? $input : $setting->default );
}

数値

absint が使えます。absolute integer の略ですね。
負の数でない整数のみ通すようになります。

数値範囲付きの数値

'type' => 'number' では input_attrs に最小値と最大値を指定できます。数値を直接入力する場合はそれらを無視した数値が設定できてしまいますが、サニタイズコールバックを使用してそれを防ぐことが出来ます。

function theme_slug_sanitize_number_range( $number, $setting ) {
    $number = absint( $number );
    $atts = $setting->manager->get_control( $setting->id )->input_attrs;
    $min = ( isset( $atts['min'] ) ? $atts['min'] : $number );
    $max = ( isset( $atts['max'] ) ? $atts['max'] : $number );
    $step = ( isset( $atts['step'] ) ? $atts['step'] : 1 );
    return ( $min <= $number && $number <= $max && is_int( $number / $step ) ? $number : $setting->default );
}

サンプル:

function theme_slug_sanitize_number_range( $number, $setting ) {
    $number = absint( $number );
    $atts = $setting->manager->get_control( $setting->id )->input_attrs;
    $min = ( isset( $atts['min'] ) ? $atts['min'] : $number );
    $max = ( isset( $atts['max'] ) ? $atts['max'] : $number );
    $step = ( isset( $atts['step'] ) ? $atts['step'] : 1 );
    return ( $min <= $number && $number <= $max && is_int( $number / $step ) ? $number : $setting->default );
}
$wp_customize->add_setting( 'container_width', array(
    'default'  => '1140',
    'sanitize_callback' => 'theme_slug_sanitize_number_range',
));
$wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'container_width', array(
    'label'    =>  __( 'Site Max-Width', 'coldbox' ),
    'section'  => 'global',
    'type'     => 'number',
    'input_attrs' => array(
        'step'     => '1',
        'min'      => '800',
        'max'      => '1980',
    ),
)));

このサニタイズを使用する場合、最小値以上最大値以内かつ指定されたステップで割り切れる数以外 保存されなくなります (デフォルト値に戻されます)。
必ず最小値と最大値、ステップの数は近くに明記しておきましょう。

ファイルアップローダ

これもコアにはないので以下のような関数を使います。

function theme_slug_sanitize_image( $image, $setting ) {
    $mimes = array(
        'jpg|jpeg|jpe' => 'image/jpeg',
        'gif'          => 'image/gif',
        'png'          => 'image/png',
        'bmp'          => 'image/bmp',
        'tif|tiff'     => 'image/tiff',
        'ico'          => 'image/x-icon'
    );
    $file = wp_check_filetype( $image, $mimes );
    return ( $file['ext'] ? $image : $setting->default );
}

スポンサーリンク

正直カスタマイザーの中身にどんな内容が入っていようがただの自己責任じゃねえかとか、必須にするなら全部コアで関数用意しろよとか突っ込みどころは多いですが、やらなきゃいけないもんはやらなきゃいけないので黙ってやりましょう。

クレジット

一部コードは code-examples/sanitization-callbacks.php at master · WPTRT/code-examples から引用しました。感謝です。

参考リンク

ode-examples/sanitization-callbacks.php at master · WPTRT/code-examples
WordPress customizer sanitization examples | DivPusher - The WordPress Theme Club

フリーランスで WordPress, フロントエンド開発をするエンジニア (お仕事募集中)。最近は WordPress テーマの作成やレビュー、翻訳などやってます。フロントが好き。Twitter: @mirucons

スポンサーリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

コメントする

スパム対策の為、日本語が含まれない投稿は無視されますのでご注意ください。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください