有馬総一郎のブログ

(彼氏の事情)

2020年10月26日 22:02:26 JST - 3 minute read - Comments - PHP

WordPress Contact Form 7で自動で日付を設定するチェックボックスを追加する独自タグを実装

WordPressを弄ることがあって、そこでは問い合わせフォームで参加日付を選択させるためにチェックボックスを追加している。

コンタクトフォームの編集ページ、フォーム欄で

[checkbox checkbox-143 use_label_element exclusive "05/14""05/28""06/11"]

このようにしていた。しかし、毎回、手動で参加日付を更新するのは手間ということで自動化させてみた。

参考にしたのは以下のサイト

初め、こんなに長い行書かないと駄目なの?と挫けそうになったが、実はそんなに修正するところは多くない。foreachで回す配列と、チェックボックスの値、ラベルをどう設定するか位である。 functions.php の最後に追記すれば良い。ハイライトした所以外はコピペである。

プラグインエディターで追記しようとしたら、上手く行かなかったので、sftpでファイル毎上書きした。動作環境は以下。

  • WordPress バージョン 5.2.7
  • Contact Form 7 バージョン 5.1.3

/wp-content/plugins/contact-form-7/includes/functions.php1

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// 独自タグ[visit_days]追記
add_action( 'wpcf7_init', 'wpcf7_add_form_tag_visitdays' );

// 独自タグ[visit_days]を定義(末尾*は必須項目用)
function wpcf7_add_form_tag_visitdays() {
    wpcf7_add_form_tag( array( 'visit_days', 'visit_days*' ),
        'wpcf7_pagelist_form_tag_handler', // 関数名
        array(
            'name-attr' => true,
            'selectable-values' => true,
            'multiple-controls-container' => true,
        )
    );
}

// 独自タグの内容を定義する関数
function wpcf7_pagelist_form_tag_handler( $tag ) {
    if ( empty( $tag->name ) ) {
        return '';
    }

    $validation_error = wpcf7_get_validation_error( $tag->name );
    $class = wpcf7_form_controls_class( $tag->type );

    if ( $validation_error ) {
        $class .= ' wpcf7-not-valid';
    }

    // オプションの設定
    $label_first        = $tag->has_option( 'label_first' );
    $use_label_element  = $tag->has_option( 'use_label_element' );
    $exclusive          = $tag->has_option( 'exclusive' );
    $multiple           = false;

    if ( 'visit_days' == $tag->basetype ) {
        $multiple = ! $exclusive;
    }

    if ( $exclusive ) {
        $class .= ' wpcf7-exclusive-checkbox';
    }

    $atts = array();

    $atts['class']  = $tag->get_class_option( $class );
    $atts['id']     = $tag->get_id_option();

    $tabindex = $tag->get_option( 'tabindex', 'signed_int', true );

    if ( false !== $tabindex ) {
        $tabindex = (int) $tabindex;
    }

    // 参加日付を取得
    $now = strtotime('now');
    $secondThrs = strtotime("second thursday of this month");
    $day1 = date('m/d', strtotime("second wednesday of this month"));
    $day2 = date('m/d', strtotime("fourth wednesday of this month"));
    $day3 = date('m/d', strtotime("second wednesday of next month"));
    if ($now >= $secondThrs) {
        $day1 = date('m/d', strtotime("fourth wednesday of this month"));
        $day2 = date('m/d', strtotime("second wednesday of next month"));
        $day3 = date('m/d', strtotime("fourth wednesday of next month"));
    }
    $visitdays = array($day1, $day2, $day3, "その他");


    $html = '';
    $count = 0;

    $hangover = wpcf7_get_hangover( $tag->name, $multiple ? array() : '' );

    foreach($visitdays as $visitday) {
        $class = 'wpcf7-list-item';

        $checked    = false;
        $key        = $count;
        $value      = $visitday;
        $label      = $value;

        if ( $hangover ) {
            if ( $multiple ) {
                $checked = in_array( $value, (array) $hangover, true );
            } else {
                $checked = ( $hangover === $value );
            }
        } else {
            $checked = in_array( $count + 1, (array) $defaults );
        }

        $item_atts = array(
            'type'      => 'checkbox',
            'name'      => $tag -> name . ( $multiple ? '[]' : '' ),
            'value'     => $value,
            'checked'   => $checked ? 'checked' : '',
            'tabindex'  => false !== $tabindex ? $tabindex : '',
        );

        $item_atts = wpcf7_format_atts( $item_atts );

        if ( $label_first ) { // put label first, input last
            $item = sprintf(
                '<span class="wpcf7-list-item-label">%1$s</span><input %2$s />',
                esc_html( $label ), $item_atts );
        } else {
            $item = sprintf(
                '<input %2$s /><span class="wpcf7-list-item-label">%1$s</span>',
                esc_html( $label ), $item_atts );
        }

        if ( $use_label_element ) {
            $item = '<label>' . $item . '</label>';
        }

        if ( false !== $tabindex && 0 < $tabindex ) {
            $tabindex += 1;
        }

        $count += 1;

        if ( 1 == $count ) {
            $class .= ' first';
        }

        if ( count( $visitdays ) == $count ) { // last round
            $class .= ' last';
        }

        $item = '<span class="' . esc_attr( $class ) . '">' . $item . '</span>';
        $html .= $item;
    } // foreach

    $atts = wpcf7_format_atts( $atts );

    $html = sprintf(
        '<span class="wpcf7-form-control-wrap %1$s"><span %2$s>%3$s</span>%4$s</span>',
        sanitize_html_class( $tag->name ), $atts, $html, $validation_error );

    return $html;

}

// バリデートの設定
add_filter( 'wpcf7_validate_visit_days', 'wpcf7_visit_days_validation_filter', 10, 2 );
add_filter( 'wpcf7_validate_visit_days*', 'wpcf7_visit_days_validation_filter', 10, 2 );

function wpcf7_visit_days_validation_filter( $result, $tag ) {
    $type = $tag->type;
    $name = $tag->name;
    $is_required = $tag->is_required() || 'visit_days*' == $type; // 'visit_days*' は独自タグ
    $value = isset( $_POST[$name] ) ? (array) $_POST[$name] : array();

    if ( $is_required && empty( $value ) ) {
        $result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
    }

    return $result;
}

これでコンタクトフォームで

参加日付
[visit_days checkbox-143 use_label_element exclusive]

と記述することで

WordPress Contact Form 7
と表示される。

しかし、 PHP も便利だね。

strtotime("second thursday of this month")
strtotime("second wednesday of this month")
strtotime("second wednesday of next month")

とやれば、月の第2水曜、木曜、更に翌月まで取得できるんだね。 Java だともう少し面倒だな、いや自分が知らないだけか?


  1. 参考元のサイトだと function.php となっていたが、 functions.php が正しい。またcat_listの方は修正漏れか126行が定義されていない(参考元のままの)$childrenになっていた。 ↩︎