Contact Form 7 - Version 4.9

Version Description

  • Supports subscribers_only setting
  • Changes the default value of WPCF7_VERIFY_NONCE to false
  • WPCF7_FormTagsManager::collect_tag_types() supports invert option
  • New filter hooks: wpcf7_verify_nonce, wpcf7_subscribers_only_notice, wpcf7_remote_ip_addr, and wpcf7_submission_is_blacklisted
  • Fixed: Form-tag's tabindex option did not accept 0 or negative integer values
  • Shows a validation error when no option in a radio buttons group is checked
  • Config validator: Adds a validation rule against the use of deprecated settings (on_sent_ok and on_submit)
  • Allows to pass the skip_mail option through the WPCF7_ContactForm::submit() and WPCF7_Submission::get_instance() function parameters.
  • Triggers wpcf7beforesubmit custom DOM event. You can manipulate the formData object through an event handler.
Download this release

Release Info

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

Code changes from version 4.8.1 to 4.9

admin/admin.php CHANGED
@@ -301,9 +301,11 @@ function wpcf7_admin_enqueue_scripts( $hook_suffix ) {
301
 
302
  $args = array(
303
  'apiSettings' => array(
304
- 'root' => esc_url_raw( get_rest_url() ),
 
305
  'nonce' => ( wp_installing() && ! is_multisite() )
306
- ? '' : wp_create_nonce( 'wp_rest' ) ),
 
307
  'pluginUrl' => wpcf7_plugin_url(),
308
  'saveAlert' => __(
309
  "The changes you made will be lost if you navigate away from this page.",
301
 
302
  $args = array(
303
  'apiSettings' => array(
304
+ 'root' => esc_url_raw( rest_url( 'contact-form-7/v1' ) ),
305
+ 'namespace' => 'contact-form-7/v1',
306
  'nonce' => ( wp_installing() && ! is_multisite() )
307
+ ? '' : wp_create_nonce( 'wp_rest' ),
308
+ ),
309
  'pluginUrl' => wpcf7_plugin_url(),
310
  'saveAlert' => __(
311
  "The changes you made will be lost if you navigate away from this page.",
admin/js/scripts.js CHANGED
@@ -39,15 +39,17 @@
39
  'visibility', 'hidden' );
40
  } );
41
 
 
 
42
  $( 'input:checkbox.toggle-form-table' ).click( function( event ) {
43
- $( this ).wpcf7ToggleFormTable();
44
- } ).wpcf7ToggleFormTable();
45
 
46
- if ( '' == $( '#title' ).val() ) {
47
  $( '#title' ).focus();
48
  }
49
 
50
- $.wpcf7TitleHint();
51
 
52
  $( '.contact-form-editor-box-mail span.mailtag' ).click( function( event ) {
53
  var range = document.createRange();
@@ -55,7 +57,7 @@
55
  window.getSelection().addRange( range );
56
  } );
57
 
58
- $.wpcf7UpdateConfigErrors();
59
 
60
  $( '[data-config-field]' ).change( function() {
61
  var postId = $( '#post_ID' ).val();
@@ -70,22 +72,21 @@
70
  data.push( {
71
  'name': $( this ).attr( 'name' ).replace( /^wpcf7-/, '' ).replace( /-/g, '_' ),
72
  'value': $( this ).val()
73
- });
74
- });
75
 
76
  data.push( { 'name': 'context', 'value': 'dry-run' } );
77
 
78
  $.ajax( {
79
  method: 'POST',
80
- url: wpcf7.apiSettings.root +
81
- 'contact-form-7/v1/contact-forms/' + postId,
82
  beforeSend: function( xhr ) {
83
  xhr.setRequestHeader( 'X-WP-Nonce', wpcf7.apiSettings.nonce );
84
  },
85
  data: data
86
  } ).done( function( response ) {
87
  wpcf7.configValidator.errors = response.config_errors;
88
- $.wpcf7UpdateConfigErrors();
89
  } );
90
  } );
91
 
@@ -102,7 +103,7 @@
102
  if ( this.defaultSelected != $( this ).is( ':selected' ) ) {
103
  changed = true;
104
  }
105
- });
106
  } else {
107
  if ( this.defaultValue != $( this ).val() ) {
108
  changed = true;
@@ -127,23 +128,21 @@
127
  } );
128
  } );
129
 
130
- $.fn.wpcf7ToggleFormTable = function() {
131
- return this.each( function() {
132
- var formtable = $( this ).closest( '.contact-form-editor-box-mail' ).find( 'fieldset' );
 
133
 
134
- if ( $( this ).is( ':checked' ) ) {
135
- formtable.removeClass( 'hidden' );
136
- } else {
137
- formtable.addClass( 'hidden' );
138
- }
139
- } );
140
  };
141
 
142
- $.wpcf7UpdateConfigErrors = function() {
143
  var errors = wpcf7.configValidator.errors;
144
- var errorCount = {
145
- total: 0,
146
- };
147
 
148
  $( '[data-config-field]' ).each( function() {
149
  $( this ).removeAttr( 'aria-invalid' );
@@ -221,8 +220,7 @@
221
  }
222
  } );
223
 
224
- $( '#misc-publishing-actions .misc-pub-section.config-error' )
225
- .remove();
226
 
227
  if ( errorCount.total ) {
228
  var $warning = $( '<div></div>' )
@@ -248,34 +246,44 @@
248
 
249
  $( '#misc-publishing-actions' ).append( $warning );
250
  }
251
- }
252
 
253
  /**
254
  * Copied from wptitlehint() in wp-admin/js/post.js
255
  */
256
- $.wpcf7TitleHint = function() {
257
- var title = $( '#title' );
258
- var titleprompt = $( '#title-prompt-text' );
259
 
260
- if ( '' == title.val() ) {
261
- titleprompt.removeClass( 'screen-reader-text' );
262
  }
263
 
264
- titleprompt.click( function() {
265
  $( this ).addClass( 'screen-reader-text' );
266
- title.focus();
267
  } );
268
 
269
- title.blur( function() {
270
- if ( '' == $(this).val() ) {
271
- titleprompt.removeClass( 'screen-reader-text' );
272
  }
273
  } ).focus( function() {
274
- titleprompt.addClass( 'screen-reader-text' );
275
  } ).keydown( function( e ) {
276
- titleprompt.addClass( 'screen-reader-text' );
277
  $( this ).unbind( e );
278
  } );
279
  };
280
 
 
 
 
 
 
 
 
 
 
 
281
  } )( jQuery );
39
  'visibility', 'hidden' );
40
  } );
41
 
42
+ wpcf7.toggleMail2( 'input:checkbox.toggle-form-table' );
43
+
44
  $( 'input:checkbox.toggle-form-table' ).click( function( event ) {
45
+ wpcf7.toggleMail2( this );
46
+ } );
47
 
48
+ if ( '' === $( '#title' ).val() ) {
49
  $( '#title' ).focus();
50
  }
51
 
52
+ wpcf7.titleHint();
53
 
54
  $( '.contact-form-editor-box-mail span.mailtag' ).click( function( event ) {
55
  var range = document.createRange();
57
  window.getSelection().addRange( range );
58
  } );
59
 
60
+ wpcf7.updateConfigErrors();
61
 
62
  $( '[data-config-field]' ).change( function() {
63
  var postId = $( '#post_ID' ).val();
72
  data.push( {
73
  'name': $( this ).attr( 'name' ).replace( /^wpcf7-/, '' ).replace( /-/g, '_' ),
74
  'value': $( this ).val()
75
+ } );
76
+ } );
77
 
78
  data.push( { 'name': 'context', 'value': 'dry-run' } );
79
 
80
  $.ajax( {
81
  method: 'POST',
82
+ url: wpcf7.apiSettings.getRoute( '/contact-forms/' + postId ),
 
83
  beforeSend: function( xhr ) {
84
  xhr.setRequestHeader( 'X-WP-Nonce', wpcf7.apiSettings.nonce );
85
  },
86
  data: data
87
  } ).done( function( response ) {
88
  wpcf7.configValidator.errors = response.config_errors;
89
+ wpcf7.updateConfigErrors();
90
  } );
91
  } );
92
 
103
  if ( this.defaultSelected != $( this ).is( ':selected' ) ) {
104
  changed = true;
105
  }
106
+ } );
107
  } else {
108
  if ( this.defaultValue != $( this ).val() ) {
109
  changed = true;
128
  } );
129
  } );
130
 
131
+ wpcf7.toggleMail2 = function( checkbox ) {
132
+ var $checkbox = $( checkbox );
133
+ var $fieldset = $( 'fieldset',
134
+ $checkbox.closest( '.contact-form-editor-box-mail' ) );
135
 
136
+ if ( $checkbox.is( ':checked' ) ) {
137
+ $fieldset.removeClass( 'hidden' );
138
+ } else {
139
+ $fieldset.addClass( 'hidden' );
140
+ }
 
141
  };
142
 
143
+ wpcf7.updateConfigErrors = function() {
144
  var errors = wpcf7.configValidator.errors;
145
+ var errorCount = { total: 0 };
 
 
146
 
147
  $( '[data-config-field]' ).each( function() {
148
  $( this ).removeAttr( 'aria-invalid' );
220
  }
221
  } );
222
 
223
+ $( '#misc-publishing-actions .misc-pub-section.config-error' ).remove();
 
224
 
225
  if ( errorCount.total ) {
226
  var $warning = $( '<div></div>' )
246
 
247
  $( '#misc-publishing-actions' ).append( $warning );
248
  }
249
+ };
250
 
251
  /**
252
  * Copied from wptitlehint() in wp-admin/js/post.js
253
  */
254
+ wpcf7.titleHint = function() {
255
+ var $title = $( '#title' );
256
+ var $titleprompt = $( '#title-prompt-text' );
257
 
258
+ if ( '' === $title.val() ) {
259
+ $titleprompt.removeClass( 'screen-reader-text' );
260
  }
261
 
262
+ $titleprompt.click( function() {
263
  $( this ).addClass( 'screen-reader-text' );
264
+ $title.focus();
265
  } );
266
 
267
+ $title.blur( function() {
268
+ if ( '' === $(this).val() ) {
269
+ $titleprompt.removeClass( 'screen-reader-text' );
270
  }
271
  } ).focus( function() {
272
+ $titleprompt.addClass( 'screen-reader-text' );
273
  } ).keydown( function( e ) {
274
+ $titleprompt.addClass( 'screen-reader-text' );
275
  $( this ).unbind( e );
276
  } );
277
  };
278
 
279
+ wpcf7.apiSettings.getRoute = function( path ) {
280
+ var url = wpcf7.apiSettings.root;
281
+
282
+ url = url.replace(
283
+ wpcf7.apiSettings.namespace,
284
+ wpcf7.apiSettings.namespace + path );
285
+
286
+ return url;
287
+ };
288
+
289
  } )( jQuery );
includes/capabilities.php CHANGED
@@ -9,6 +9,7 @@ function wpcf7_map_meta_cap( $caps, $cap, $user_id, $args ) {
9
  'wpcf7_read_contact_forms' => WPCF7_ADMIN_READ_CAPABILITY,
10
  'wpcf7_delete_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
11
  'wpcf7_manage_integration' => 'manage_options',
 
12
  );
13
 
14
  $meta_caps = apply_filters( 'wpcf7_map_meta_cap', $meta_caps );
9
  'wpcf7_read_contact_forms' => WPCF7_ADMIN_READ_CAPABILITY,
10
  'wpcf7_delete_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
11
  'wpcf7_manage_integration' => 'manage_options',
12
+ 'wpcf7_submit' => 'read',
13
  );
14
 
15
  $meta_caps = apply_filters( 'wpcf7_map_meta_cap', $meta_caps );
includes/config-validator.php CHANGED
@@ -11,6 +11,7 @@ class WPCF7_ConfigValidator {
11
  const error_file_not_found = 106;
12
  const error_unavailable_names = 107;
13
  const error_invalid_mail_header = 108;
 
14
 
15
  public static function get_doc_link( $error_code = '' ) {
16
  $url = __( 'https://contactform7.com/configuration-errors/',
@@ -139,6 +140,8 @@ class WPCF7_ConfigValidator {
139
  return __( "Multiple form controls are in a single label element.", 'contact-form-7' );
140
  case self::error_invalid_mail_header:
141
  return __( "There are invalid mail header fields.", 'contact-form-7' );
 
 
142
  default:
143
  return '';
144
  }
@@ -178,6 +181,7 @@ class WPCF7_ConfigValidator {
178
  $this->validate_mail( 'mail' );
179
  $this->validate_mail( 'mail_2' );
180
  $this->validate_messages();
 
181
 
182
  do_action( 'wpcf7_config_validator_validate', $this );
183
 
@@ -576,4 +580,20 @@ class WPCF7_ConfigValidator {
576
 
577
  return false;
578
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
  }
11
  const error_file_not_found = 106;
12
  const error_unavailable_names = 107;
13
  const error_invalid_mail_header = 108;
14
+ const error_deprecated_settings = 109;
15
 
16
  public static function get_doc_link( $error_code = '' ) {
17
  $url = __( 'https://contactform7.com/configuration-errors/',
140
  return __( "Multiple form controls are in a single label element.", 'contact-form-7' );
141
  case self::error_invalid_mail_header:
142
  return __( "There are invalid mail header fields.", 'contact-form-7' );
143
+ case self::error_deprecated_settings:
144
+ return __( "Deprecated settings are used.", 'contact-form-7' );
145
  default:
146
  return '';
147
  }
181
  $this->validate_mail( 'mail' );
182
  $this->validate_mail( 'mail_2' );
183
  $this->validate_messages();
184
+ $this->validate_additional_settings();
185
 
186
  do_action( 'wpcf7_config_validator_validate', $this );
187
 
580
 
581
  return false;
582
  }
583
+
584
+ public function validate_additional_settings() {
585
+ $deprecated_settings_used =
586
+ $this->contact_form->additional_setting( 'on_sent_ok' ) ||
587
+ $this->contact_form->additional_setting( 'on_submit' );
588
+
589
+ if ( $deprecated_settings_used ) {
590
+ return $this->add_error( 'additional_settings.body',
591
+ self::error_deprecated_settings,
592
+ array(
593
+ 'link' => self::get_doc_link( 'deprecated_settings' ),
594
+ )
595
+ );
596
+ }
597
+ }
598
+
599
  }
includes/contact-form.php CHANGED
@@ -289,6 +289,18 @@ class WPCF7_ContactForm {
289
  . esc_html( $this->prop( 'form' ) ) . '</code></pre>';
290
  }
291
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  $this->unit_tag = self::get_unit_tag( $this->id );
293
 
294
  $lang_tag = str_replace( '_', '-', $this->locale );
@@ -409,8 +421,8 @@ class WPCF7_ContactForm {
409
  $hidden_fields['_wpcf7_container_post'] = (int) get_the_ID();
410
  }
411
 
412
- if ( WPCF7_VERIFY_NONCE ) {
413
- $hidden_fields['_wpcf7_nonce'] = wpcf7_create_nonce( $this->id );
414
  }
415
 
416
  $hidden_fields += (array) apply_filters(
@@ -616,7 +628,7 @@ class WPCF7_ContactForm {
616
 
617
  $mailtags = array_unique( array_filter( $mailtags ) );
618
 
619
- return apply_filters( 'wpcf7_collect_mail_tags', $mailtags );
620
  }
621
 
622
  public function suggest_mail_tags( $for = 'mail' ) {
@@ -648,8 +660,27 @@ class WPCF7_ContactForm {
648
  }
649
  }
650
 
651
- public function submit() {
652
- $submission = WPCF7_Submission::get_instance( $this );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
653
 
654
  $result = array(
655
  'contact_form_id' => $this->id(),
@@ -739,6 +770,16 @@ class WPCF7_ContactForm {
739
  return $this->is_true( 'demo_mode' );
740
  }
741
 
 
 
 
 
 
 
 
 
 
 
742
  /* Upgrade */
743
 
744
  private function upgrade() {
289
  . esc_html( $this->prop( 'form' ) ) . '</code></pre>';
290
  }
291
 
292
+ if ( $this->is_true( 'subscribers_only' )
293
+ && ! current_user_can( 'wpcf7_submit', $this->id() ) ) {
294
+ $notice = __(
295
+ "This contact form is available only for logged in users.",
296
+ 'contact-form-7' );
297
+ $notice = sprintf(
298
+ '<p class="wpcf7-subscribers-only">%s</p>',
299
+ esc_html( $notice ) );
300
+
301
+ return apply_filters( 'wpcf7_subscribers_only_notice', $notice, $this );
302
+ }
303
+
304
  $this->unit_tag = self::get_unit_tag( $this->id );
305
 
306
  $lang_tag = str_replace( '_', '-', $this->locale );
421
  $hidden_fields['_wpcf7_container_post'] = (int) get_the_ID();
422
  }
423
 
424
+ if ( $this->nonce_is_active() ) {
425
+ $hidden_fields['_wpnonce'] = wpcf7_create_nonce();
426
  }
427
 
428
  $hidden_fields += (array) apply_filters(
628
 
629
  $mailtags = array_unique( array_filter( $mailtags ) );
630
 
631
+ return apply_filters( 'wpcf7_collect_mail_tags', $mailtags, $args, $this );
632
  }
633
 
634
  public function suggest_mail_tags( $for = 'mail' ) {
660
  }
661
  }
662
 
663
+ public function submit( $args = '' ) {
664
+ $args = wp_parse_args( $args, array(
665
+ 'skip_mail' => $this->in_demo_mode() || ! empty( $this->skip_mail ),
666
+ ) );
667
+
668
+ if ( $this->is_true( 'subscribers_only' )
669
+ && ! current_user_can( 'wpcf7_submit', $this->id() ) ) {
670
+ $result = array(
671
+ 'contact_form_id' => $this->id(),
672
+ 'status' => 'error',
673
+ 'message' => __(
674
+ "This contact form is available only for logged in users.",
675
+ 'contact-form-7' ),
676
+ );
677
+
678
+ return $result;
679
+ }
680
+
681
+ $submission = WPCF7_Submission::get_instance( $this, array(
682
+ 'skip_mail' => $args['skip_mail'],
683
+ ) );
684
 
685
  $result = array(
686
  'contact_form_id' => $this->id(),
770
  return $this->is_true( 'demo_mode' );
771
  }
772
 
773
+ public function nonce_is_active() {
774
+ $is_active = WPCF7_VERIFY_NONCE;
775
+
776
+ if ( $this->is_true( 'subscribers_only' ) ) {
777
+ $is_active = true;
778
+ }
779
+
780
+ return (bool) apply_filters( 'wpcf7_verify_nonce', $is_active, $this );
781
+ }
782
+
783
  /* Upgrade */
784
 
785
  private function upgrade() {
includes/controller.php CHANGED
@@ -1,10 +1,9 @@
1
  <?php
2
 
3
- add_action( 'wp_loaded', 'wpcf7_control_init' );
4
 
5
  function wpcf7_control_init() {
6
- if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] )
7
- && 'XMLHttpRequest' == $_SERVER['HTTP_X_REQUESTED_WITH'] ) {
8
  return;
9
  }
10
 
1
  <?php
2
 
3
+ add_action( 'parse_request', 'wpcf7_control_init', 20 );
4
 
5
  function wpcf7_control_init() {
6
+ if ( WPCF7_Submission::is_restful() ) {
 
7
  return;
8
  }
9
 
includes/form-tags-manager.php CHANGED
@@ -96,7 +96,7 @@ class WPCF7_FormTagsManager {
96
  return false;
97
  }
98
 
99
- public function collect_tag_types( $feature = null ) {
100
  $tag_types = array_keys( $this->tag_types );
101
 
102
  if ( empty( $feature ) ) {
@@ -106,7 +106,8 @@ class WPCF7_FormTagsManager {
106
  $output = array();
107
 
108
  foreach ( $tag_types as $tag ) {
109
- if ( $this->tag_type_supports( $tag, $feature ) ) {
 
110
  $output[] = $tag;
111
  }
112
  }
96
  return false;
97
  }
98
 
99
+ public function collect_tag_types( $feature = null, $invert = false ) {
100
  $tag_types = array_keys( $this->tag_types );
101
 
102
  if ( empty( $feature ) ) {
106
  $output = array();
107
 
108
  foreach ( $tag_types as $tag ) {
109
+ if ( ! $invert && $this->tag_type_supports( $tag, $feature )
110
+ || $invert && ! $this->tag_type_supports( $tag, $feature ) ) {
111
  $output[] = $tag;
112
  }
113
  }
includes/functions.php CHANGED
@@ -19,7 +19,8 @@ function wpcf7_upload_dir( $type = false ) {
19
 
20
  $uploads = apply_filters( 'wpcf7_upload_dir', array(
21
  'dir' => $uploads['basedir'],
22
- 'url' => $uploads['baseurl'] ) );
 
23
 
24
  if ( 'dir' == $type ) {
25
  return $uploads['dir'];
@@ -30,16 +31,12 @@ function wpcf7_upload_dir( $type = false ) {
30
  return $uploads;
31
  }
32
 
33
- function wpcf7_verify_nonce( $nonce, $action = -1 ) {
34
- if ( substr( wp_hash( $action, 'nonce' ), -12, 10 ) == $nonce ) {
35
- return true;
36
- }
37
-
38
- return false;
39
  }
40
 
41
- function wpcf7_create_nonce( $action = -1 ) {
42
- return substr( wp_hash( $action, 'nonce' ), -12, 10 );
43
  }
44
 
45
  function wpcf7_blacklist_check( $target ) {
19
 
20
  $uploads = apply_filters( 'wpcf7_upload_dir', array(
21
  'dir' => $uploads['basedir'],
22
+ 'url' => $uploads['baseurl'],
23
+ ) );
24
 
25
  if ( 'dir' == $type ) {
26
  return $uploads['dir'];
31
  return $uploads;
32
  }
33
 
34
+ function wpcf7_verify_nonce( $nonce, $action = 'wp_rest' ) {
35
+ return wp_verify_nonce( $nonce, $action );
 
 
 
 
36
  }
37
 
38
+ function wpcf7_create_nonce( $action = 'wp_rest' ) {
39
+ return wp_create_nonce( $action );
40
  }
41
 
42
  function wpcf7_blacklist_check( $target ) {
includes/js/scripts.js CHANGED
@@ -169,11 +169,13 @@
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
  }
@@ -183,51 +185,58 @@
183
  };
184
 
185
  wpcf7.submit = function( form ) {
 
 
 
 
186
  var $form = $( form );
187
 
 
 
188
  $( '[placeholder].placeheld', $form ).each( function( i, n ) {
189
  $( n ).val( '' );
190
  } );
191
 
192
  wpcf7.clearResponse( $form );
193
- $( '.ajax-loader', $form ).addClass( 'is-active' );
194
-
195
- if ( typeof window.FormData !== 'function' ) {
196
- return;
197
- }
198
 
199
  var formData = new FormData( $form.get( 0 ) );
200
 
201
- var ajaxSuccess = function( data, status, xhr, $form ) {
202
- var detail = {
203
- id: $( data.into ).attr( 'id' ),
204
- status: data.status,
205
- inputs: []
206
- };
207
 
208
- $.each( $form.serializeArray(), function( i, field ) {
209
- if ( '_wpcf7' == field.name ) {
210
- detail.contactFormId = field.value;
211
- } else if ( '_wpcf7_version' == field.name ) {
212
- detail.pluginVersion = field.value;
213
- } else if ( '_wpcf7_locale' == field.name ) {
214
- detail.contactFormLocale = field.value;
215
- } else if ( '_wpcf7_unit_tag' == field.name ) {
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 {
228
- detail.inputs.push( field );
229
- }
230
- } );
 
 
 
 
 
 
231
 
232
  var $message = $( '.wpcf7-response-output', $form );
233
 
169
  } );
170
  } );
171
 
172
+ // URL Input Correction
173
  $form.on( 'change', '.wpcf7-validates-as-url', function() {
174
  var val = $.trim( $( this ).val() );
175
 
176
+ if ( val
177
+ && ! val.match( /^[a-z][a-z0-9.+-]*:/i )
178
+ && -1 !== val.indexOf( '.' ) ) {
179
  val = val.replace( /^\/+/, '' );
180
  val = 'http://' + val;
181
  }
185
  };
186
 
187
  wpcf7.submit = function( form ) {
188
+ if ( typeof window.FormData !== 'function' ) {
189
+ return;
190
+ }
191
+
192
  var $form = $( form );
193
 
194
+ $( '.ajax-loader', $form ).addClass( 'is-active' );
195
+
196
  $( '[placeholder].placeheld', $form ).each( function( i, n ) {
197
  $( n ).val( '' );
198
  } );
199
 
200
  wpcf7.clearResponse( $form );
 
 
 
 
 
201
 
202
  var formData = new FormData( $form.get( 0 ) );
203
 
204
+ var detail = {
205
+ id: $form.closest( 'div.wpcf7' ).attr( 'id' ),
206
+ status: 'init',
207
+ inputs: [],
208
+ formData: formData
209
+ };
210
 
211
+ $.each( $form.serializeArray(), function( i, field ) {
212
+ if ( '_wpcf7' == field.name ) {
213
+ detail.contactFormId = field.value;
214
+ } else if ( '_wpcf7_version' == field.name ) {
215
+ detail.pluginVersion = field.value;
216
+ } else if ( '_wpcf7_locale' == field.name ) {
217
+ detail.contactFormLocale = field.value;
218
+ } else if ( '_wpcf7_unit_tag' == field.name ) {
219
+ detail.unitTag = field.value;
220
+ } else if ( '_wpcf7_container_post' == field.name ) {
221
+ detail.containerPostId = field.value;
222
+ } else if ( field.name.match( /^_wpcf7_\w+_free_text_/ ) ) {
223
+ var owner = field.name.replace( /^_wpcf7_\w+_free_text_/, '' );
224
+ detail.inputs.push( {
225
+ name: owner + '-free-text',
226
+ value: field.value
227
+ } );
228
+ } else if ( field.name.match( /^_/ ) ) {
229
+ // do nothing
230
+ } else {
231
+ detail.inputs.push( field );
232
+ }
233
+ } );
234
+
235
+ wpcf7.triggerEvent( $form.closest( 'div.wpcf7' ), 'beforesubmit', detail );
236
+
237
+ var ajaxSuccess = function( data, status, xhr, $form ) {
238
+ detail.id = $( data.into ).attr( 'id' );
239
+ detail.status = data.status;
240
 
241
  var $message = $( '.wpcf7-response-output', $form );
242
 
includes/submission.php CHANGED
@@ -15,7 +15,11 @@ class WPCF7_Submission {
15
 
16
  private function __construct() {}
17
 
18
- public static function get_instance( WPCF7_ContactForm $contact_form = null ) {
 
 
 
 
19
  if ( empty( self::$instance ) ) {
20
  if ( null == $contact_form ) {
21
  return null;
@@ -23,7 +27,7 @@ class WPCF7_Submission {
23
 
24
  self::$instance = new self;
25
  self::$instance->contact_form = $contact_form;
26
- self::$instance->skip_mail = $contact_form->in_demo_mode();
27
  self::$instance->setup_posted_data();
28
  self::$instance->submit();
29
  } elseif ( null != $contact_form ) {
@@ -33,6 +37,10 @@ class WPCF7_Submission {
33
  return self::$instance;
34
  }
35
 
 
 
 
 
36
  public function get_status() {
37
  return $this->status;
38
  }
@@ -71,8 +79,7 @@ class WPCF7_Submission {
71
 
72
  private function setup_posted_data() {
73
  $posted_data = (array) $_POST;
74
- $posted_data = array_diff_key(
75
- $posted_data, array( '_wpcf7_nonce' => '' ) );
76
  $posted_data = $this->sanitize_posted_data( $posted_data );
77
 
78
  $tags = $this->contact_form->scan_form_tags();
@@ -176,19 +183,20 @@ class WPCF7_Submission {
176
  }
177
 
178
  private function get_remote_ip_addr() {
 
 
179
  if ( isset( $_SERVER['REMOTE_ADDR'] )
180
  && WP_Http::is_ip_address( $_SERVER['REMOTE_ADDR'] ) ) {
181
- return $_SERVER['REMOTE_ADDR'];
182
  }
183
 
184
- return '';
185
  }
186
 
187
  private function get_request_url() {
188
  $home_url = untrailingslashit( home_url() );
189
 
190
- if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] )
191
- && 'XMLHttpRequest' == $_SERVER['HTTP_X_REQUESTED_WITH'] ) {
192
  $referer = isset( $_SERVER['HTTP_REFERER'] )
193
  ? trim( $_SERVER['HTTP_REFERER'] ) : '';
194
 
@@ -232,17 +240,22 @@ class WPCF7_Submission {
232
  private function spam() {
233
  $spam = false;
234
 
 
 
 
 
 
235
  $user_agent = (string) $this->get_meta( 'user_agent' );
236
 
237
  if ( strlen( $user_agent ) < 2 ) {
238
  $spam = true;
239
  }
240
 
241
- if ( WPCF7_VERIFY_NONCE && ! $this->verify_nonce() ) {
242
  $spam = true;
243
  }
244
 
245
- if ( $this->blacklist_check() ) {
246
  $spam = true;
247
  }
248
 
@@ -250,18 +263,21 @@ class WPCF7_Submission {
250
  }
251
 
252
  private function verify_nonce() {
253
- return wpcf7_verify_nonce(
254
- $_POST['_wpcf7_nonce'], $this->contact_form->id() );
 
 
 
255
  }
256
 
257
- private function blacklist_check() {
258
  $target = wpcf7_array_flatten( $this->posted_data );
259
  $target[] = $this->get_meta( 'remote_ip' );
260
  $target[] = $this->get_meta( 'user_agent' );
261
-
262
  $target = implode( "\n", $target );
263
 
264
- return wpcf7_blacklist_check( $target );
 
265
  }
266
 
267
  /* Mail */
@@ -271,8 +287,7 @@ class WPCF7_Submission {
271
 
272
  do_action( 'wpcf7_before_send_mail', $contact_form );
273
 
274
- $skip_mail = $this->skip_mail || ! empty( $contact_form->skip_mail );
275
- $skip_mail = apply_filters( 'wpcf7_skip_mail', $skip_mail, $contact_form );
276
 
277
  if ( $skip_mail ) {
278
  return true;
15
 
16
  private function __construct() {}
17
 
18
+ public static function get_instance( WPCF7_ContactForm $contact_form = null, $args = '' ) {
19
+ $args = wp_parse_args( $args, array(
20
+ 'skip_mail' => false,
21
+ ) );
22
+
23
  if ( empty( self::$instance ) ) {
24
  if ( null == $contact_form ) {
25
  return null;
27
 
28
  self::$instance = new self;
29
  self::$instance->contact_form = $contact_form;
30
+ self::$instance->skip_mail = (bool) $args['skip_mail'];
31
  self::$instance->setup_posted_data();
32
  self::$instance->submit();
33
  } elseif ( null != $contact_form ) {
37
  return self::$instance;
38
  }
39
 
40
+ public static function is_restful() {
41
+ return defined( 'REST_REQUEST' ) && REST_REQUEST;
42
+ }
43
+
44
  public function get_status() {
45
  return $this->status;
46
  }
79
 
80
  private function setup_posted_data() {
81
  $posted_data = (array) $_POST;
82
+ $posted_data = array_diff_key( $posted_data, array( '_wpnonce' => '' ) );
 
83
  $posted_data = $this->sanitize_posted_data( $posted_data );
84
 
85
  $tags = $this->contact_form->scan_form_tags();
183
  }
184
 
185
  private function get_remote_ip_addr() {
186
+ $ip_addr = '';
187
+
188
  if ( isset( $_SERVER['REMOTE_ADDR'] )
189
  && WP_Http::is_ip_address( $_SERVER['REMOTE_ADDR'] ) ) {
190
+ $ip_addr = $_SERVER['REMOTE_ADDR'];
191
  }
192
 
193
+ return apply_filters( 'wpcf7_remote_ip_addr', $ip_addr );
194
  }
195
 
196
  private function get_request_url() {
197
  $home_url = untrailingslashit( home_url() );
198
 
199
+ if ( self::is_restful() ) {
 
200
  $referer = isset( $_SERVER['HTTP_REFERER'] )
201
  ? trim( $_SERVER['HTTP_REFERER'] ) : '';
202
 
240
  private function spam() {
241
  $spam = false;
242
 
243
+ if ( $this->contact_form->is_true( 'subscribers_only' )
244
+ && current_user_can( 'wpcf7_submit', $this->contact_form->id() ) ) {
245
+ return $spam;
246
+ }
247
+
248
  $user_agent = (string) $this->get_meta( 'user_agent' );
249
 
250
  if ( strlen( $user_agent ) < 2 ) {
251
  $spam = true;
252
  }
253
 
254
+ if ( ! $this->verify_nonce() ) {
255
  $spam = true;
256
  }
257
 
258
+ if ( $this->is_blacklisted() ) {
259
  $spam = true;
260
  }
261
 
263
  }
264
 
265
  private function verify_nonce() {
266
+ if ( ! $this->contact_form->nonce_is_active() ) {
267
+ return true;
268
+ }
269
+
270
+ return wpcf7_verify_nonce( $_POST['_wpnonce'] );
271
  }
272
 
273
+ private function is_blacklisted() {
274
  $target = wpcf7_array_flatten( $this->posted_data );
275
  $target[] = $this->get_meta( 'remote_ip' );
276
  $target[] = $this->get_meta( 'user_agent' );
 
277
  $target = implode( "\n", $target );
278
 
279
+ return (bool) apply_filters( 'wpcf7_submission_is_blacklisted',
280
+ wpcf7_blacklist_check( $target ), $this );
281
  }
282
 
283
  /* Mail */
287
 
288
  do_action( 'wpcf7_before_send_mail', $contact_form );
289
 
290
+ $skip_mail = apply_filters( 'wpcf7_skip_mail', $this->skip_mail, $contact_form );
 
291
 
292
  if ( $skip_mail ) {
293
  return true;
modules/acceptance.php CHANGED
@@ -38,7 +38,7 @@ function wpcf7_acceptance_form_tag_handler( $tag ) {
38
 
39
  $atts['class'] = $tag->get_class_option( $class );
40
  $atts['id'] = $tag->get_id_option();
41
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
42
 
43
  if ( $tag->has_option( 'default:on' ) ) {
44
  $atts['checked'] = 'checked';
38
 
39
  $atts['class'] = $tag->get_class_option( $class );
40
  $atts['id'] = $tag->get_id_option();
41
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
42
 
43
  if ( $tag->has_option( 'default:on' ) ) {
44
  $atts['checked'] = 'checked';
modules/akismet.php CHANGED
@@ -74,7 +74,7 @@ function wpcf7_akismet_submitted_params() {
74
  $has_akismet_option = false;
75
 
76
  foreach ( (array) $_POST as $key => $val ) {
77
- if ( '_wpcf7' == substr( $key, 0, 6 ) ) {
78
  continue;
79
  }
80
 
74
  $has_akismet_option = false;
75
 
76
  foreach ( (array) $_POST as $key => $val ) {
77
+ if ( '_wpcf7' == substr( $key, 0, 6 ) || '_wpnonce' == $key ) {
78
  continue;
79
  }
80
 
modules/checkbox.php CHANGED
@@ -52,10 +52,10 @@ function wpcf7_checkbox_form_tag_handler( $tag ) {
52
  $atts['class'] = $tag->get_class_option( $class );
53
  $atts['id'] = $tag->get_id_option();
54
 
55
- $tabindex = $tag->get_option( 'tabindex', 'int', true );
56
 
57
  if ( false !== $tabindex ) {
58
- $tabindex = absint( $tabindex );
59
  }
60
 
61
  $html = '';
@@ -126,7 +126,7 @@ function wpcf7_checkbox_form_tag_handler( $tag ) {
126
  'name' => $tag->name . ( $multiple ? '[]' : '' ),
127
  'value' => $value,
128
  'checked' => $checked ? 'checked' : '',
129
- 'tabindex' => $tabindex ? $tabindex : '',
130
  );
131
 
132
  $item_atts = wpcf7_format_atts( $item_atts );
@@ -145,7 +145,7 @@ function wpcf7_checkbox_form_tag_handler( $tag ) {
145
  $item = '<label>' . $item . '</label>';
146
  }
147
 
148
- if ( false !== $tabindex ) {
149
  $tabindex += 1;
150
  }
151
 
@@ -165,7 +165,7 @@ function wpcf7_checkbox_form_tag_handler( $tag ) {
165
  $free_text_atts = array(
166
  'name' => $free_text_name,
167
  'class' => 'wpcf7-free-text',
168
- 'tabindex' => $tabindex ? $tabindex : '',
169
  );
170
 
171
  if ( wpcf7_is_posted() && isset( $_POST[$free_text_name] ) ) {
@@ -202,12 +202,11 @@ add_filter( 'wpcf7_validate_checkbox*', 'wpcf7_checkbox_validation_filter', 10,
202
  add_filter( 'wpcf7_validate_radio', 'wpcf7_checkbox_validation_filter', 10, 2 );
203
 
204
  function wpcf7_checkbox_validation_filter( $result, $tag ) {
205
- $type = $tag->type;
206
  $name = $tag->name;
207
-
208
  $value = isset( $_POST[$name] ) ? (array) $_POST[$name] : array();
209
 
210
- if ( $tag->is_required() && empty( $value ) ) {
211
  $result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
212
  }
213
 
52
  $atts['class'] = $tag->get_class_option( $class );
53
  $atts['id'] = $tag->get_id_option();
54
 
55
+ $tabindex = $tag->get_option( 'tabindex', 'signed_int', true );
56
 
57
  if ( false !== $tabindex ) {
58
+ $tabindex = (int) $tabindex;
59
  }
60
 
61
  $html = '';
126
  'name' => $tag->name . ( $multiple ? '[]' : '' ),
127
  'value' => $value,
128
  'checked' => $checked ? 'checked' : '',
129
+ 'tabindex' => false !== $tabindex ? $tabindex : '',
130
  );
131
 
132
  $item_atts = wpcf7_format_atts( $item_atts );
145
  $item = '<label>' . $item . '</label>';
146
  }
147
 
148
+ if ( false !== $tabindex && 0 < $tabindex ) {
149
  $tabindex += 1;
150
  }
151
 
165
  $free_text_atts = array(
166
  'name' => $free_text_name,
167
  'class' => 'wpcf7-free-text',
168
+ 'tabindex' => false !== $tabindex ? $tabindex : '',
169
  );
170
 
171
  if ( wpcf7_is_posted() && isset( $_POST[$free_text_name] ) ) {
202
  add_filter( 'wpcf7_validate_radio', 'wpcf7_checkbox_validation_filter', 10, 2 );
203
 
204
  function wpcf7_checkbox_validation_filter( $result, $tag ) {
 
205
  $name = $tag->name;
206
+ $is_required = $tag->is_required() || 'radio' == $tag->type;
207
  $value = isset( $_POST[$name] ) ? (array) $_POST[$name] : array();
208
 
209
+ if ( $is_required && empty( $value ) ) {
210
  $result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
211
  }
212
 
modules/date.php CHANGED
@@ -32,7 +32,7 @@ function wpcf7_date_form_tag_handler( $tag ) {
32
 
33
  $atts['class'] = $tag->get_class_option( $class );
34
  $atts['id'] = $tag->get_id_option();
35
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
36
  $atts['min'] = $tag->get_date_option( 'min' );
37
  $atts['max'] = $tag->get_date_option( 'max' );
38
  $atts['step'] = $tag->get_option( 'step', 'int', true );
32
 
33
  $atts['class'] = $tag->get_class_option( $class );
34
  $atts['id'] = $tag->get_id_option();
35
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
36
  $atts['min'] = $tag->get_date_option( 'min' );
37
  $atts['max'] = $tag->get_date_option( 'max' );
38
  $atts['step'] = $tag->get_option( 'step', 'int', true );
modules/file.php CHANGED
@@ -30,7 +30,7 @@ function wpcf7_file_form_tag_handler( $tag ) {
30
  $atts['size'] = $tag->get_size_option( '40' );
31
  $atts['class'] = $tag->get_class_option( $class );
32
  $atts['id'] = $tag->get_id_option();
33
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
34
 
35
  if ( $tag->is_required() ) {
36
  $atts['aria-required'] = 'true';
30
  $atts['size'] = $tag->get_size_option( '40' );
31
  $atts['class'] = $tag->get_class_option( $class );
32
  $atts['id'] = $tag->get_id_option();
33
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
34
 
35
  if ( $tag->is_required() ) {
36
  $atts['aria-required'] = 'true';
modules/number.php CHANGED
@@ -33,7 +33,7 @@ function wpcf7_number_form_tag_handler( $tag ) {
33
 
34
  $atts['class'] = $tag->get_class_option( $class );
35
  $atts['id'] = $tag->get_id_option();
36
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
37
  $atts['min'] = $tag->get_option( 'min', 'signed_int', true );
38
  $atts['max'] = $tag->get_option( 'max', 'signed_int', true );
39
  $atts['step'] = $tag->get_option( 'step', 'int', true );
33
 
34
  $atts['class'] = $tag->get_class_option( $class );
35
  $atts['id'] = $tag->get_id_option();
36
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
37
  $atts['min'] = $tag->get_option( 'min', 'signed_int', true );
38
  $atts['max'] = $tag->get_option( 'max', 'signed_int', true );
39
  $atts['step'] = $tag->get_option( 'step', 'int', true );
modules/quiz.php CHANGED
@@ -42,7 +42,7 @@ function wpcf7_quiz_form_tag_handler( $tag ) {
42
 
43
  $atts['class'] = $tag->get_class_option( $class );
44
  $atts['id'] = $tag->get_id_option();
45
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
46
  $atts['autocomplete'] = 'off';
47
  $atts['aria-required'] = 'true';
48
  $atts['aria-invalid'] = $validation_error ? 'true' : 'false';
42
 
43
  $atts['class'] = $tag->get_class_option( $class );
44
  $atts['id'] = $tag->get_id_option();
45
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
46
  $atts['autocomplete'] = 'off';
47
  $atts['aria-required'] = 'true';
48
  $atts['aria-invalid'] = $validation_error ? 'true' : 'false';
modules/really-simple-captcha.php CHANGED
@@ -107,7 +107,7 @@ function wpcf7_captchar_form_tag_handler( $tag ) {
107
 
108
  $atts['class'] = $tag->get_class_option( $class );
109
  $atts['id'] = $tag->get_id_option();
110
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
111
  $atts['autocomplete'] = 'off';
112
  $atts['aria-invalid'] = $validation_error ? 'true' : 'false';
113
 
107
 
108
  $atts['class'] = $tag->get_class_option( $class );
109
  $atts['id'] = $tag->get_id_option();
110
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
111
  $atts['autocomplete'] = 'off';
112
  $atts['aria-invalid'] = $validation_error ? 'true' : 'false';
113
 
modules/recaptcha.php CHANGED
@@ -296,7 +296,7 @@ var recaptchaCallback = function() {
296
  }
297
  }
298
  }
299
- }
300
 
301
  document.addEventListener( 'wpcf7submit', function( event ) {
302
  switch ( event.detail.status ) {
@@ -340,7 +340,7 @@ function wpcf7_recaptcha_form_tag_handler( $tag ) {
340
  $atts['data-theme'] = $tag->get_option( 'theme', '(dark|light)', true );
341
  $atts['data-badge'] = $tag->get_option(
342
  'badge', '(bottomright|bottomleft|inline)', true );
343
- $atts['data-tabindex'] = $tag->get_option( 'tabindex', 'int', true );
344
  $atts['data-callback'] = $tag->get_option( 'callback', '', true );
345
  $atts['data-expired-callback'] =
346
  $tag->get_option( 'expired_callback', '', true );
296
  }
297
  }
298
  }
299
+ };
300
 
301
  document.addEventListener( 'wpcf7submit', function( event ) {
302
  switch ( event.detail.status ) {
340
  $atts['data-theme'] = $tag->get_option( 'theme', '(dark|light)', true );
341
  $atts['data-badge'] = $tag->get_option(
342
  'badge', '(bottomright|bottomleft|inline)', true );
343
+ $atts['data-tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
344
  $atts['data-callback'] = $tag->get_option( 'callback', '', true );
345
  $atts['data-expired-callback'] =
346
  $tag->get_option( 'expired_callback', '', true );
modules/select.php CHANGED
@@ -34,7 +34,7 @@ function wpcf7_select_form_tag_handler( $tag ) {
34
 
35
  $atts['class'] = $tag->get_class_option( $class );
36
  $atts['id'] = $tag->get_id_option();
37
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
38
 
39
  if ( $tag->is_required() ) {
40
  $atts['aria-required'] = 'true';
34
 
35
  $atts['class'] = $tag->get_class_option( $class );
36
  $atts['id'] = $tag->get_id_option();
37
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
38
 
39
  if ( $tag->is_required() ) {
40
  $atts['aria-required'] = 'true';
modules/submit.php CHANGED
@@ -18,7 +18,7 @@ function wpcf7_submit_form_tag_handler( $tag ) {
18
 
19
  $atts['class'] = $tag->get_class_option( $class );
20
  $atts['id'] = $tag->get_id_option();
21
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
22
 
23
  $value = isset( $tag->values[0] ) ? $tag->values[0] : '';
24
 
18
 
19
  $atts['class'] = $tag->get_class_option( $class );
20
  $atts['id'] = $tag->get_id_option();
21
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
22
 
23
  $value = isset( $tag->values[0] ) ? $tag->values[0] : '';
24
 
modules/text.php CHANGED
@@ -47,7 +47,7 @@ function wpcf7_text_form_tag_handler( $tag ) {
47
 
48
  $atts['class'] = $tag->get_class_option( $class );
49
  $atts['id'] = $tag->get_id_option();
50
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
51
 
52
  $atts['autocomplete'] = $tag->get_option( 'autocomplete',
53
  '[-0-9a-zA-Z]+', true );
47
 
48
  $atts['class'] = $tag->get_class_option( $class );
49
  $atts['id'] = $tag->get_id_option();
50
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
51
 
52
  $atts['autocomplete'] = $tag->get_option( 'autocomplete',
53
  '[-0-9a-zA-Z]+', true );
modules/textarea.php CHANGED
@@ -38,7 +38,7 @@ function wpcf7_textarea_form_tag_handler( $tag ) {
38
 
39
  $atts['class'] = $tag->get_class_option( $class );
40
  $atts['id'] = $tag->get_id_option();
41
- $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
42
 
43
  $atts['autocomplete'] = $tag->get_option( 'autocomplete',
44
  '[-0-9a-zA-Z]+', true );
38
 
39
  $atts['class'] = $tag->get_class_option( $class );
40
  $atts['id'] = $tag->get_id_option();
41
+ $atts['tabindex'] = $tag->get_option( 'tabindex', 'signed_int', true );
42
 
43
  $atts['autocomplete'] = $tag->get_option( 'autocomplete',
44
  '[-0-9a-zA-Z]+', true );
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: takayukister
3
  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.1
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -62,6 +62,18 @@ 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.1 =
66
 
67
  * wpcf7.initForm JavaScript function added to isolate form initialization process.
3
  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.1
7
+ Stable tag: 4.9
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.9 =
66
+
67
+ * Supports subscribers_only setting
68
+ * Changes the default value of WPCF7_VERIFY_NONCE to false
69
+ * WPCF7_FormTagsManager::collect_tag_types() supports invert option
70
+ * New filter hooks: wpcf7_verify_nonce, wpcf7_subscribers_only_notice, wpcf7_remote_ip_addr, and wpcf7_submission_is_blacklisted
71
+ * Fixed: Form-tag's tabindex option did not accept 0 or negative integer values
72
+ * Shows a validation error when no option in a radio buttons group is checked
73
+ * Config validator: Adds a validation rule against the use of deprecated settings (on_sent_ok and on_submit)
74
+ * Allows to pass the skip_mail option through the WPCF7_ContactForm::submit() and WPCF7_Submission::get_instance() function parameters.
75
+ * Triggers wpcf7beforesubmit custom DOM event. You can manipulate the formData object through an event handler.
76
+
77
  = 4.8.1 =
78
 
79
  * wpcf7.initForm JavaScript function added to isolate form initialization process.
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.1
11
  */
12
 
13
- define( 'WPCF7_VERSION', '4.8.1' );
14
 
15
  define( 'WPCF7_REQUIRED_WP_VERSION', '4.7' );
16
 
@@ -49,7 +49,7 @@ if ( ! defined( 'WPCF7_ADMIN_READ_WRITE_CAPABILITY' ) ) {
49
  }
50
 
51
  if ( ! defined( 'WPCF7_VERIFY_NONCE' ) ) {
52
- define( 'WPCF7_VERIFY_NONCE', true );
53
  }
54
 
55
  if ( ! defined( 'WPCF7_USE_REALLY_SIMPLE_CAPTCHA' ) ) {
7
  Author URI: https://ideasilo.wordpress.com/
8
  Text Domain: contact-form-7
9
  Domain Path: /languages/
10
+ Version: 4.9
11
  */
12
 
13
+ define( 'WPCF7_VERSION', '4.9' );
14
 
15
  define( 'WPCF7_REQUIRED_WP_VERSION', '4.7' );
16
 
49
  }
50
 
51
  if ( ! defined( 'WPCF7_VERIFY_NONCE' ) ) {
52
+ define( 'WPCF7_VERIFY_NONCE', false );
53
  }
54
 
55
  if ( ! defined( 'WPCF7_USE_REALLY_SIMPLE_CAPTCHA' ) ) {