Contact Form 7 - Version 4.8.1

Version Description

  • wpcf7.initForm JavaScript function added to isolate form initialization process.
  • Fix response message duplication caused by repeated click on submit button.
  • Clear $phpmailer->AltBody to avoid unintended inheritance from previous wp_mail() calls.
  • Fix incorrect character count of textarea input.
  • Akismet: Exclude the comment_author, comment_author_email, and comment_author_url values from the comment_content value.
  • REST API: More reliable approach to build route URLs.
  • Include free_text inputs into event.detail.inputs.
Download this release

Release Info

Developer takayukister
Plugin Icon 128x128 Contact Form 7
Version 4.8.1
Comparing to
See all releases

Code changes from version 4.8 to 4.8.1

includes/controller.php CHANGED
@@ -56,7 +56,7 @@ function wpcf7_enqueue_scripts() {
56
57
$wpcf7 = array(
58
'apiSettings' => array(
59
- 'root' => esc_url_raw( get_rest_url() ),
60
'namespace' => 'contact-form-7/v1',
61
),
62
'recaptcha' => array(
56
57
$wpcf7 = array(
58
'apiSettings' => array(
59
+ 'root' => esc_url_raw( rest_url( 'contact-form-7/v1' ) ),
60
'namespace' => 'contact-form-7/v1',
61
),
62
'recaptcha' => array(
includes/functions.php CHANGED
@@ -330,6 +330,7 @@ function wpcf7_count_code_units( $string ) {
330
}
331
332
$string = (string) $string;
333
334
$encoding = mb_detect_encoding( $string, mb_detect_order(), true );
335
330
}
331
332
$string = (string) $string;
333
+ $string = str_replace( "\r\n", "\n", $string );
334
335
$encoding = mb_detect_encoding( $string, mb_detect_order(), true );
336
includes/js/scripts.js CHANGED
@@ -30,151 +30,156 @@
30
31
$( 'div.wpcf7 > form' ).each( function() {
32
var $form = $( this );
33
34
- $form.submit( function( event ) {
35
- if ( typeof window.FormData !== 'function' ) {
36
- return;
37
- }
38
39
- wpcf7.submit( $form );
40
- event.preventDefault();
41
- } );
42
43
- $( '.wpcf7-submit', $form ).after( '<span class="ajax-loader"></span>' );
44
45
wpcf7.toggleSubmit( $form );
46
47
- $form.on( 'click', '.wpcf7-acceptance', function() {
48
- wpcf7.toggleSubmit( $form );
49
- } );
50
51
- // Exclusive Checkbox
52
- $( '.wpcf7-exclusive-checkbox', $form ).on( 'click', 'input:checkbox', function() {
53
- var name = $( this ).attr( 'name' );
54
- $form.find( 'input:checkbox[name="' + name + '"]' ).not( this ).prop( 'checked', false );
55
- } );
56
57
- // Free Text Option for Checkboxes and Radio Buttons
58
- $( '.wpcf7-list-item.has-free-text', $form ).each( function() {
59
- var $freetext = $( ':input.wpcf7-free-text', this );
60
- var $wrap = $( this ).closest( '.wpcf7-form-control' );
61
62
- if ( $( ':checkbox, :radio', this ).is( ':checked' ) ) {
63
- $freetext.prop( 'disabled', false );
64
} else {
65
$freetext.prop( 'disabled', true );
66
}
67
68
- $wrap.on( 'change', ':checkbox, :radio', function() {
69
- var $cb = $( '.has-free-text', $wrap ).find( ':checkbox, :radio' );
70
71
- if ( $cb.is( ':checked' ) ) {
72
- $freetext.prop( 'disabled', false ).focus();
73
- } else {
74
- $freetext.prop( 'disabled', true );
75
}
76
} );
77
- } );
78
-
79
- // Placeholder Fallback
80
- if ( ! wpcf7.supportHtml5.placeholder ) {
81
- $( '[placeholder]', $form ).each( function() {
82
- $( this ).val( $( this ).attr( 'placeholder' ) );
83
- $( this ).addClass( 'placeheld' );
84
85
- $( this ).focus( function() {
86
- if ( $( this ).hasClass( 'placeheld' ) ) {
87
- $( this ).val( '' ).removeClass( 'placeheld' );
88
- }
89
- } );
90
-
91
- $( this ).blur( function() {
92
- if ( '' === $( this ).val() ) {
93
- $( this ).val( $( this ).attr( 'placeholder' ) );
94
- $( this ).addClass( 'placeheld' );
95
- }
96
- } );
97
} );
98
- }
99
100
- if ( wpcf7.jqueryUi && ! wpcf7.supportHtml5.date ) {
101
- $form.find( 'input.wpcf7-date[type="date"]' ).each( function() {
102
- $( this ).datepicker( {
103
- dateFormat: 'yy-mm-dd',
104
- minDate: new Date( $( this ).attr( 'min' ) ),
105
- maxDate: new Date( $( this ).attr( 'max' ) )
106
- } );
107
} );
108
- }
109
110
- if ( wpcf7.jqueryUi && ! wpcf7.supportHtml5.number ) {
111
- $form.find( 'input.wpcf7-number[type="number"]' ).each( function() {
112
- $( this ).spinner( {
113
- min: $( this ).attr( 'min' ),
114
- max: $( this ).attr( 'max' ),
115
- step: $( this ).attr( 'step' )
116
- } );
117
} );
118
- }
119
120
- // Character Count
121
- $( '.wpcf7-character-count', $form ).each( function() {
122
- var $count = $( this );
123
- var name = $count.attr( 'data-target-name' );
124
- var down = $count.hasClass( 'down' );
125
- var starting = parseInt( $count.attr( 'data-starting-value' ), 10 );
126
- var maximum = parseInt( $count.attr( 'data-maximum-value' ), 10 );
127
- var minimum = parseInt( $count.attr( 'data-minimum-value' ), 10 );
128
-
129
- var updateCount = function( target ) {
130
- var $target = $( target );
131
- var length = $target.val().length;
132
- var count = down ? starting - length : length;
133
- $count.attr( 'data-current-value', count );
134
- $count.text( count );
135
-
136
- if ( maximum && maximum < length ) {
137
- $count.addClass( 'too-long' );
138
- } else {
139
- $count.removeClass( 'too-long' );
140
- }
141
142
- if ( minimum && length < minimum ) {
143
- $count.addClass( 'too-short' );
144
- } else {
145
- $count.removeClass( 'too-short' );
146
- }
147
- };
148
149
- $( ':input[name="' + name + '"]', $form ).each( function() {
150
- updateCount( this );
151
152
- $( this ).keyup( function() {
153
- updateCount( this );
154
- } );
155
} );
156
} );
157
158
- $form.on( 'change', '.wpcf7-validates-as-url', function() {
159
- var val = $.trim( $( this ).val() );
160
-
161
- // check the scheme part
162
- if ( val && ! val.match( /^[a-z][a-z0-9.+-]*:/i ) ) {
163
- val = val.replace( /^\/+/, '' );
164
- val = 'http://' + val;
165
- }
166
-
167
- $( this ).val( val );
168
- } );
169
170
- if ( wpcf7.cached ) {
171
- wpcf7.refill( $form );
172
}
173
- } );
174
- } );
175
176
- wpcf7.getId = function( form ) {
177
- return parseInt( $( 'input[name="_wpcf7"]', form ).val(), 10 );
178
};
179
180
wpcf7.submit = function( form ) {
@@ -211,6 +216,12 @@
211
detail.unitTag = field.value;
212
} else if ( '_wpcf7_container_post' == field.name ) {
213
detail.containerPostId = field.value;
214
} else if ( field.name.match( /^_/ ) ) {
215
// do nothing
216
} else {
@@ -285,7 +296,7 @@
285
$( n ).val( $( n ).attr( 'placeholder' ) );
286
} );
287
288
- $message.append( data.message ).slideDown( 'fast' );
289
$message.attr( 'role', 'alert' );
290
291
$( '.screen-reader-response', $form.closest( '.wpcf7' ) ).each( function() {
@@ -314,8 +325,8 @@
314
315
$.ajax( {
316
type: 'POST',
317
- url: wpcf7.apiSettings.root + wpcf7.apiSettings.namespace +
318
- '/contact-forms/' + wpcf7.getId( $form ) + '/feedback',
319
data: formData,
320
dataType: 'json',
321
processData: false,
@@ -384,7 +395,7 @@
384
}, 'fast', function() {
385
$( this ).css( { 'z-index': -100 } );
386
} );
387
- }
388
389
$target.on( 'mouseover', '.wpcf7-not-valid-tip', function() {
390
fadeOut( this );
@@ -394,7 +405,7 @@
394
fadeOut( $( '.wpcf7-not-valid-tip', $target ) );
395
} );
396
}
397
- }
398
399
wpcf7.refill = function( form, data ) {
400
var $form = $( form );
@@ -419,8 +430,8 @@
419
if ( typeof data === 'undefined' ) {
420
$.ajax( {
421
type: 'GET',
422
- url: wpcf7.apiSettings.root + wpcf7.apiSettings.namespace +
423
- '/contact-forms/' + wpcf7.getId( $form ) + '/refill',
424
dataType: 'json'
425
} ).done( function( data, status, xhr ) {
426
if ( data.captcha ) {
@@ -457,6 +468,16 @@
457
.removeClass( 'wpcf7-mail-sent-ok wpcf7-mail-sent-ng wpcf7-validation-errors wpcf7-spam-blocked' );
458
};
459
460
} )( jQuery );
461
462
/*
30
31
$( 'div.wpcf7 > form' ).each( function() {
32
var $form = $( this );
33
+ wpcf7.initForm( $form );
34
35
+ if ( wpcf7.cached ) {
36
+ wpcf7.refill( $form );
37
+ }
38
+ } );
39
+ } );
40
41
+ wpcf7.getId = function( form ) {
42
+ return parseInt( $( 'input[name="_wpcf7"]', form ).val(), 10 );
43
+ };
44
45
+ wpcf7.initForm = function( form ) {
46
+ var $form = $( form );
47
+
48
+ $form.submit( function( event ) {
49
+ if ( typeof window.FormData !== 'function' ) {
50
+ return;
51
+ }
52
+
53
+ wpcf7.submit( $form );
54
+ event.preventDefault();
55
+ } );
56
57
+ $( '.wpcf7-submit', $form ).after( '<span class="ajax-loader"></span>' );
58
+
59
+ wpcf7.toggleSubmit( $form );
60
+
61
+ $form.on( 'click', '.wpcf7-acceptance', function() {
62
wpcf7.toggleSubmit( $form );
63
+ } );
64
65
+ // Exclusive Checkbox
66
+ $( '.wpcf7-exclusive-checkbox', $form ).on( 'click', 'input:checkbox', function() {
67
+ var name = $( this ).attr( 'name' );
68
+ $form.find( 'input:checkbox[name="' + name + '"]' ).not( this ).prop( 'checked', false );
69
+ } );
70
71
+ // Free Text Option for Checkboxes and Radio Buttons
72
+ $( '.wpcf7-list-item.has-free-text', $form ).each( function() {
73
+ var $freetext = $( ':input.wpcf7-free-text', this );
74
+ var $wrap = $( this ).closest( '.wpcf7-form-control' );
75
76
+ if ( $( ':checkbox, :radio', this ).is( ':checked' ) ) {
77
+ $freetext.prop( 'disabled', false );
78
+ } else {
79
+ $freetext.prop( 'disabled', true );
80
+ }
81
82
+ $wrap.on( 'change', ':checkbox, :radio', function() {
83
+ var $cb = $( '.has-free-text', $wrap ).find( ':checkbox, :radio' );
84
+
85
+ if ( $cb.is( ':checked' ) ) {
86
+ $freetext.prop( 'disabled', false ).focus();
87
} else {
88
$freetext.prop( 'disabled', true );
89
}
90
+ } );
91
+ } );
92
93
+ // Placeholder Fallback
94
+ if ( ! wpcf7.supportHtml5.placeholder ) {
95
+ $( '[placeholder]', $form ).each( function() {
96
+ $( this ).val( $( this ).attr( 'placeholder' ) );
97
+ $( this ).addClass( 'placeheld' );
98
99
+ $( this ).focus( function() {
100
+ if ( $( this ).hasClass( 'placeheld' ) ) {
101
+ $( this ).val( '' ).removeClass( 'placeheld' );
102
}
103
} );
104
105
+ $( this ).blur( function() {
106
+ if ( '' === $( this ).val() ) {
107
+ $( this ).val( $( this ).attr( 'placeholder' ) );
108
+ $( this ).addClass( 'placeheld' );
109
+ }
110
} );
111
+ } );
112
+ }
113
114
+ if ( wpcf7.jqueryUi && ! wpcf7.supportHtml5.date ) {
115
+ $form.find( 'input.wpcf7-date[type="date"]' ).each( function() {
116
+ $( this ).datepicker( {
117
+ dateFormat: 'yy-mm-dd',
118
+ minDate: new Date( $( this ).attr( 'min' ) ),
119
+ maxDate: new Date( $( this ).attr( 'max' ) )
120
} );
121
+ } );
122
+ }
123
124
+ if ( wpcf7.jqueryUi && ! wpcf7.supportHtml5.number ) {
125
+ $form.find( 'input.wpcf7-number[type="number"]' ).each( function() {
126
+ $( this ).spinner( {
127
+ min: $( this ).attr( 'min' ),
128
+ max: $( this ).attr( 'max' ),
129
+ step: $( this ).attr( 'step' )
130
} );
131
+ } );
132
+ }
133
134
+ // Character Count
135
+ $( '.wpcf7-character-count', $form ).each( function() {
136
+ var $count = $( this );
137
+ var name = $count.attr( 'data-target-name' );
138
+ var down = $count.hasClass( 'down' );
139
+ var starting = parseInt( $count.attr( 'data-starting-value' ), 10 );
140
+ var maximum = parseInt( $count.attr( 'data-maximum-value' ), 10 );
141
+ var minimum = parseInt( $count.attr( 'data-minimum-value' ), 10 );
142
+
143
+ var updateCount = function( target ) {
144
+ var $target = $( target );
145
+ var length = $target.val().length;
146
+ var count = down ? starting - length : length;
147
+ $count.attr( 'data-current-value', count );
148
+ $count.text( count );
149
+
150
+ if ( maximum && maximum < length ) {
151
+ $count.addClass( 'too-long' );
152
+ } else {
153
+ $count.removeClass( 'too-long' );
154
+ }
155
156
+ if ( minimum && length < minimum ) {
157
+ $count.addClass( 'too-short' );
158
+ } else {
159
+ $count.removeClass( 'too-short' );
160
+ }
161
+ };
162
163
+ $( ':input[name="' + name + '"]', $form ).each( function() {
164
+ updateCount( this );
165
166
+ $( this ).keyup( function() {
167
+ updateCount( this );
168
} );
169
} );
170
+ } );
171
172
+ $form.on( 'change', '.wpcf7-validates-as-url', function() {
173
+ var val = $.trim( $( this ).val() );
174
175
+ // check the scheme part
176
+ if ( val && ! val.match( /^[a-z][a-z0-9.+-]*:/i ) ) {
177
+ val = val.replace( /^\/+/, '' );
178
+ val = 'http://' + val;
179
}
180
181
+ $( this ).val( val );
182
+ } );
183
};
184
185
wpcf7.submit = function( form ) {
216
detail.unitTag = field.value;
217
} else if ( '_wpcf7_container_post' == field.name ) {
218
detail.containerPostId = field.value;
219
+ } else if ( field.name.match( /^_wpcf7_\w+_free_text_/ ) ) {
220
+ var owner = field.name.replace( /^_wpcf7_\w+_free_text_/, '' );
221
+ detail.inputs.push( {
222
+ name: owner + '-free-text',
223
+ value: field.value
224
+ } );
225
} else if ( field.name.match( /^_/ ) ) {
226
// do nothing
227
} else {
296
$( n ).val( $( n ).attr( 'placeholder' ) );
297
} );
298
299
+ $message.html( '' ).append( data.message ).slideDown( 'fast' );
300
$message.attr( 'role', 'alert' );
301
302
$( '.screen-reader-response', $form.closest( '.wpcf7' ) ).each( function() {
325
326
$.ajax( {
327
type: 'POST',
328
+ url: wpcf7.apiSettings.getRoute(
329
+ '/contact-forms/' + wpcf7.getId( $form ) + '/feedback' ),
330
data: formData,
331
dataType: 'json',
332
processData: false,
395
}, 'fast', function() {
396
$( this ).css( { 'z-index': -100 } );
397
} );
398
+ };
399
400
$target.on( 'mouseover', '.wpcf7-not-valid-tip', function() {
401
fadeOut( this );
405
fadeOut( $( '.wpcf7-not-valid-tip', $target ) );
406
} );
407
}
408
+ };
409
410
wpcf7.refill = function( form, data ) {
411
var $form = $( form );
430
if ( typeof data === 'undefined' ) {
431
$.ajax( {
432
type: 'GET',
433
+ url: wpcf7.apiSettings.getRoute(
434
+ '/contact-forms/' + wpcf7.getId( $form ) + '/refill' ),
435
dataType: 'json'
436
} ).done( function( data, status, xhr ) {
437
if ( data.captcha ) {
468
.removeClass( 'wpcf7-mail-sent-ok wpcf7-mail-sent-ng wpcf7-validation-errors wpcf7-spam-blocked' );
469
};
470
471
+ wpcf7.apiSettings.getRoute = function( path ) {
472
+ var url = wpcf7.apiSettings.root;
473
+
474
+ url = url.replace(
475
+ wpcf7.apiSettings.namespace,
476
+ wpcf7.apiSettings.namespace + path );
477
+
478
+ return url;
479
+ };
480
+
481
} )( jQuery );
482
483
/*
includes/mail.php CHANGED
@@ -207,17 +207,25 @@ function wpcf7_mail_replace_tags( $content, $args = '' ) {
207
add_action( 'phpmailer_init', 'wpcf7_phpmailer_init' );
208
209
function wpcf7_phpmailer_init( $phpmailer ) {
210
$wpcf7_content_type = false;
211
212
- foreach ( (array) $phpmailer->getCustomHeaders() as $custom_header ) {
213
- if ( 'X-WPCF7-Content-Type' == $custom_header[0] ) {
214
- $wpcf7_content_type = trim( $custom_header[1] );
215
- break;
216
}
217
}
218
219
- if ( 'text/html' == $wpcf7_content_type ) {
220
$phpmailer->msgHTML( $phpmailer->Body );
221
}
222
}
223
207
add_action( 'phpmailer_init', 'wpcf7_phpmailer_init' );
208
209
function wpcf7_phpmailer_init( $phpmailer ) {
210
+ $custom_headers = $phpmailer->getCustomHeaders();
211
+ $phpmailer->clearCustomHeaders();
212
$wpcf7_content_type = false;
213
214
+ foreach ( (array) $custom_headers as $custom_header ) {
215
+ $name = $custom_header[0];
216
+ $value = $custom_header[1];
217
+
218
+ if ( 'X-WPCF7-Content-Type' === $name ) {
219
+ $wpcf7_content_type = trim( $value );
220
+ } else {
221
+ $phpmailer->addCustomHeader( $name, $value );
222
}
223
}
224
225
+ if ( 'text/html' === $wpcf7_content_type ) {
226
$phpmailer->msgHTML( $phpmailer->Body );
227
+ } elseif ( 'text/plain' === $wpcf7_content_type ) {
228
+ $phpmailer->AltBody = '';
229
}
230
}
231
modules/akismet.php CHANGED
@@ -99,8 +99,10 @@ function wpcf7_akismet_submitted_params() {
99
100
if ( 'author' == $akismet ) {
101
$params[$akismet] = trim( $params[$akismet] . ' ' . $val );
102
} elseif ( '' == $params[$akismet] ) {
103
$params[$akismet] = $val;
104
}
105
}
106
}
99
100
if ( 'author' == $akismet ) {
101
$params[$akismet] = trim( $params[$akismet] . ' ' . $val );
102
+ continue;
103
} elseif ( '' == $params[$akismet] ) {
104
$params[$akismet] = $val;
105
+ continue;
106
}
107
}
108
}
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://contactform7.com/donate/
4
Tags: contact, form, contact form, feedback, email, ajax, captcha, akismet, multilingual
5
Requires at least: 4.7
6
Tested up to: 4.8
7
- Stable tag: 4.8
8
License: GPLv2 or later
9
License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
@@ -62,6 +62,16 @@ Do you have questions or issues with Contact Form 7? Use these support channels
62
63
For more information, see [Releases](https://contactform7.com/category/releases/).
64
65
= 4.8 =
66
67
* Stopped using jquery.form.js.
@@ -71,12 +81,3 @@ For more information, see [Releases](https://contactform7.com/category/releases/
71
* New form-tag features: do-not-store, display-block, and display-hidden
72
* Removed inappropriate content from h1 headings.
73
* Added the support of size:invisible option to the reCAPTCHA form-tag.
74
-
75
- = 4.7 =
76
-
77
- * Added REST API custom endpoints to manipulate contact form data.
78
- * Config Validator: Added test items for field names and attachment file paths.
79
- * Added custom DOM events: `wpcf7invalid`, `wpcf7spam`, `wpcf7mailsent`, `wpcf7mailfailed` and `wpcf7submit`.
80
- * New action hook: `wpcf7_after_flamingo`.
81
- * Added `size` option to `select` and `select*` form-tag types.
82
- * Made it possible to use the 3rd parameter of `wpcf7_add_form_tag()` to specify "features" of the form-tag type.
4
Tags: contact, form, contact form, feedback, email, ajax, captcha, akismet, multilingual
5
Requires at least: 4.7
6
Tested up to: 4.8
7
+ Stable tag: 4.8.1
8
License: GPLv2 or later
9
License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
62
63
For more information, see [Releases](https://contactform7.com/category/releases/).
64
65
+ = 4.8.1 =
66
+
67
+ * wpcf7.initForm JavaScript function added to isolate form initialization process.
68
+ * Fix response message duplication caused by repeated click on submit button.
69
+ * Clear $phpmailer->AltBody to avoid unintended inheritance from previous wp_mail() calls.
70
+ * Fix incorrect character count of textarea input.
71
+ * Akismet: Exclude the comment_author, comment_author_email, and comment_author_url values from the comment_content value.
72
+ * REST API: More reliable approach to build route URLs.
73
+ * Include free_text inputs into event.detail.inputs.
74
+
75
= 4.8 =
76
77
* Stopped using jquery.form.js.
81
* New form-tag features: do-not-store, display-block, and display-hidden
82
* Removed inappropriate content from h1 headings.
83
* Added the support of size:invisible option to the reCAPTCHA form-tag.
wp-contact-form-7.php CHANGED
@@ -7,10 +7,10 @@ Author: Takayuki Miyoshi
7
Author URI: https://ideasilo.wordpress.com/
8
Text Domain: contact-form-7
9
Domain Path: /languages/
10
- Version: 4.8
11
*/
12
13
- define( 'WPCF7_VERSION', '4.8' );
14
15
define( 'WPCF7_REQUIRED_WP_VERSION', '4.7' );
16
7
Author URI: https://ideasilo.wordpress.com/
8
Text Domain: contact-form-7
9
Domain Path: /languages/
10
+ Version: 4.8.1
11
*/
12
13
+ define( 'WPCF7_VERSION', '4.8.1' );
14
15
define( 'WPCF7_REQUIRED_WP_VERSION', '4.7' );
16