PluginProbe ʕ •ᴥ•ʔ
Contact Form 7 / 5.6.1
Contact Form 7 v5.6.1
6.1.6 5.0.2 5.0.3 5.0.4 5.0.5 5.1 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.2 5.2.1 5.2.2 5.3 5.3.1 5.3.2 5.4 5.4.1 5.4.2 5.5 5.5.1 5.5.2 5.5.3 5.5.4 5.5.5 5.5.6 5.5.6.1 5.6 5.6.1 5.6.2 5.6.3 5.6.4 5.7 5.7.1 5.7.2 5.7.3 5.7.4 5.7.5 5.7.5.1 5.7.6 5.7.7 5.8 5.8.1 5.8.2 5.8.3 5.8.4 5.8.5 5.8.6 5.8.7 5.9 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 6.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 trunk 1.1 1.10 1.10.0.1 1.10.1 1.2 1.3 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.6 1.6.1 1.7 1.7.1 1.7.2 1.7.4 1.7.5 1.7.6 1.7.6.1 1.7.7 1.7.7.1 1.7.8 1.8 1.8.0.1 1.8.0.2 1.8.0.3 1.8.0.4 1.8.1 1.8.1.1 1.9 1.9.1 1.9.2 1.9.2.1 1.9.2.2 1.9.3 1.9.4 1.9.5 1.9.5.1 2.0 2.0-beta 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1 2.1.1 2.1.2 2.2 2.2.1 2.3 2.3.1 2.4 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 3.0 3.0-beta 3.0.1 3.0.2 3.0.2.1 3.1 3.1.1 3.1.2 3.2 3.2.1 3.3 3.3.1 3.3.2 3.3.3 3.4 3.4.1 3.4.2 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.6 3.7 3.7.1 3.7.2 3.8 3.8.1 3.9 3.9-beta 3.9.1 3.9.2 3.9.3 4.0 4.0.1 4.0.2 4.0.3 4.1 4.1-beta 4.1.1 4.1.2 4.2 4.2-beta 4.2.1 4.2.2 4.3 4.3.1 4.4 4.4.1 4.4.2 4.5 4.5.1 4.6 4.6.1 4.7 4.8 4.8.1 4.9 4.9.1 4.9.2 5.0 5.0.1
contact-form-7 / includes / submission.php
contact-form-7 / includes Last commit date
block-editor 4 years ago css 4 years ago js 3 years ago swv 3 years ago capabilities.php 7 years ago config-validator.php 3 years ago contact-form-functions.php 3 years ago contact-form-template.php 4 years ago contact-form.php 3 years ago controller.php 5 years ago file.php 4 years ago form-tag.php 3 years ago form-tags-manager.php 3 years ago formatting.php 3 years ago functions.php 3 years ago integration.php 4 years ago l10n.php 5 years ago mail.php 4 years ago pipe.php 4 years ago rest-api.php 4 years ago shortcodes.php 3 years ago special-mail-tags.php 5 years ago submission.php 4 years ago upgrade.php 7 years ago validation-functions.php 3 years ago validation.php 3 years ago
submission.php
833 lines
1 <?php
2
3 class WPCF7_Submission {
4
5 private static $instance;
6
7 private $contact_form;
8 private $status = 'init';
9 private $posted_data = array();
10 private $posted_data_hash = null;
11 private $skip_spam_check = false;
12 private $uploaded_files = array();
13 private $extra_attachments = array();
14 private $skip_mail = false;
15 private $response = '';
16 private $invalid_fields = array();
17 private $meta = array();
18 private $consent = array();
19 private $spam_log = array();
20 private $result_props = array();
21
22
23 public static function get_instance( $contact_form = null, $args = '' ) {
24 if ( $contact_form instanceof WPCF7_ContactForm ) {
25 if ( empty( self::$instance ) ) {
26 self::$instance = new self( $contact_form, $args );
27 self::$instance->proceed();
28 return self::$instance;
29 } else {
30 return null;
31 }
32 } else {
33 if ( empty( self::$instance ) ) {
34 return null;
35 } else {
36 return self::$instance;
37 }
38 }
39 }
40
41
42 public static function is_restful() {
43 return defined( 'REST_REQUEST' ) && REST_REQUEST;
44 }
45
46
47 private function __construct( WPCF7_ContactForm $contact_form, $args = '' ) {
48 $args = wp_parse_args( $args, array(
49 'skip_mail' => false,
50 ) );
51
52 $this->contact_form = $contact_form;
53 $this->skip_mail = (bool) $args['skip_mail'];
54 }
55
56
57 private function proceed() {
58 $contact_form = $this->contact_form;
59
60 switch_to_locale( $contact_form->locale() );
61
62 $this->setup_meta_data();
63 $this->setup_posted_data();
64
65 if ( $this->is( 'init' ) and ! $this->validate() ) {
66 $this->set_status( 'validation_failed' );
67 $this->set_response( $contact_form->message( 'validation_error' ) );
68 }
69
70 if ( $this->is( 'init' ) and ! $this->accepted() ) {
71 $this->set_status( 'acceptance_missing' );
72 $this->set_response( $contact_form->message( 'accept_terms' ) );
73 }
74
75 if ( $this->is( 'init' ) and $this->spam() ) {
76 $this->set_status( 'spam' );
77 $this->set_response( $contact_form->message( 'spam' ) );
78 }
79
80 if ( $this->is( 'init' ) and ! $this->unship_uploaded_files() ) {
81 $this->set_status( 'validation_failed' );
82 $this->set_response( $contact_form->message( 'validation_error' ) );
83 }
84
85 if ( $this->is( 'init' ) ) {
86 $abort = ! $this->before_send_mail();
87
88 if ( $abort ) {
89 if ( $this->is( 'init' ) ) {
90 $this->set_status( 'aborted' );
91 }
92
93 if ( '' === $this->get_response() ) {
94 $this->set_response( $contact_form->filter_message(
95 __( "Sending mail has been aborted.", 'contact-form-7' ) )
96 );
97 }
98 } elseif ( $this->mail() ) {
99 $this->set_status( 'mail_sent' );
100 $this->set_response( $contact_form->message( 'mail_sent_ok' ) );
101
102 do_action( 'wpcf7_mail_sent', $contact_form );
103 } else {
104 $this->set_status( 'mail_failed' );
105 $this->set_response( $contact_form->message( 'mail_sent_ng' ) );
106
107 do_action( 'wpcf7_mail_failed', $contact_form );
108 }
109 }
110
111 restore_previous_locale();
112
113 $this->remove_uploaded_files();
114 }
115
116
117 public function get_status() {
118 return $this->status;
119 }
120
121
122 public function set_status( $status ) {
123 if ( preg_match( '/^[a-z][0-9a-z_]+$/', $status ) ) {
124 $this->status = $status;
125 return true;
126 }
127
128 return false;
129 }
130
131
132 public function is( $status ) {
133 return $this->status == $status;
134 }
135
136
137 /**
138 * Returns an associative array of submission result properties.
139 *
140 * @return array Submission result properties.
141 */
142 public function get_result() {
143 $result = array_merge( $this->result_props, array(
144 'status' => $this->get_status(),
145 'message' => $this->get_response(),
146 ) );
147
148 if ( $this->is( 'validation_failed' ) ) {
149 $result['invalid_fields'] = $this->get_invalid_fields();
150 }
151
152 switch ( $this->get_status() ) {
153 case 'init':
154 case 'validation_failed':
155 case 'acceptance_missing':
156 case 'spam':
157 $result['posted_data_hash'] = '';
158 break;
159 default:
160 $result['posted_data_hash'] = $this->get_posted_data_hash();
161 break;
162 }
163
164 $result = apply_filters( 'wpcf7_submission_result', $result, $this );
165
166 return $result;
167 }
168
169
170 /**
171 * Adds items to the array of submission result properties.
172 *
173 * @param string|array|object $args Value to add to result properties.
174 * @return array Added result properties.
175 */
176 public function add_result_props( $args = '' ) {
177 $args = wp_parse_args( $args, array() );
178
179 $this->result_props = array_merge( $this->result_props, $args );
180
181 return $args;
182 }
183
184
185 public function get_response() {
186 return $this->response;
187 }
188
189
190 public function set_response( $response ) {
191 $this->response = $response;
192 return true;
193 }
194
195
196 public function get_contact_form() {
197 return $this->contact_form;
198 }
199
200
201 public function get_invalid_field( $name ) {
202 if ( isset( $this->invalid_fields[$name] ) ) {
203 return $this->invalid_fields[$name];
204 } else {
205 return false;
206 }
207 }
208
209
210 public function get_invalid_fields() {
211 return $this->invalid_fields;
212 }
213
214
215 public function get_meta( $name ) {
216 if ( isset( $this->meta[$name] ) ) {
217 return $this->meta[$name];
218 }
219 }
220
221
222 private function setup_meta_data() {
223 $timestamp = time();
224
225 $remote_ip = $this->get_remote_ip_addr();
226
227 $remote_port = isset( $_SERVER['REMOTE_PORT'] )
228 ? (int) $_SERVER['REMOTE_PORT'] : '';
229
230 $user_agent = isset( $_SERVER['HTTP_USER_AGENT'] )
231 ? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : '';
232
233 $url = $this->get_request_url();
234
235 $unit_tag = isset( $_POST['_wpcf7_unit_tag'] )
236 ? wpcf7_sanitize_unit_tag( $_POST['_wpcf7_unit_tag'] ) : '';
237
238 $container_post_id = isset( $_POST['_wpcf7_container_post'] )
239 ? (int) $_POST['_wpcf7_container_post'] : 0;
240
241 $current_user_id = get_current_user_id();
242
243 $do_not_store = $this->contact_form->is_true( 'do_not_store' );
244
245 $this->meta = array(
246 'timestamp' => $timestamp,
247 'remote_ip' => $remote_ip,
248 'remote_port' => $remote_port,
249 'user_agent' => $user_agent,
250 'url' => $url,
251 'unit_tag' => $unit_tag,
252 'container_post_id' => $container_post_id,
253 'current_user_id' => $current_user_id,
254 'do_not_store' => $do_not_store,
255 );
256
257 return $this->meta;
258 }
259
260
261 public function get_posted_data( $name = '' ) {
262 if ( ! empty( $name ) ) {
263 if ( isset( $this->posted_data[$name] ) ) {
264 return $this->posted_data[$name];
265 } else {
266 return null;
267 }
268 }
269
270 return $this->posted_data;
271 }
272
273
274 public function get_posted_string( $name ) {
275 $data = $this->get_posted_data( $name );
276 $data = wpcf7_array_flatten( $data );
277
278 if ( empty( $data ) ) {
279 return '';
280 }
281
282 // Returns the first array item.
283 return trim( reset( $data ) );
284 }
285
286
287 private function setup_posted_data() {
288 $posted_data = array_filter( (array) $_POST, function( $key ) {
289 return '_' !== substr( $key, 0, 1 );
290 }, ARRAY_FILTER_USE_KEY );
291
292 $posted_data = wp_unslash( $posted_data );
293 $posted_data = $this->sanitize_posted_data( $posted_data );
294
295 $tags = $this->contact_form->scan_form_tags();
296
297 foreach ( (array) $tags as $tag ) {
298 if ( empty( $tag->name ) ) {
299 continue;
300 }
301
302 $type = $tag->type;
303 $name = $tag->name;
304 $pipes = $tag->pipes;
305
306 if ( wpcf7_form_tag_supports( $type, 'do-not-store' ) ) {
307 unset( $posted_data[$name] );
308 continue;
309 }
310
311 $value_orig = $value = '';
312
313 if ( isset( $posted_data[$name] ) ) {
314 $value_orig = $value = $posted_data[$name];
315 }
316
317 if ( WPCF7_USE_PIPE
318 and $pipes instanceof WPCF7_Pipes
319 and ! $pipes->zero() ) {
320 if ( is_array( $value_orig ) ) {
321 $value = array();
322
323 foreach ( $value_orig as $v ) {
324 $value[] = $pipes->do_pipe( $v );
325 }
326 } else {
327 $value = $pipes->do_pipe( $value_orig );
328 }
329 }
330
331 if ( wpcf7_form_tag_supports( $type, 'selectable-values' ) ) {
332 $value = (array) $value;
333
334 if ( $tag->has_option( 'free_text' )
335 and isset( $posted_data[$name . '_free_text'] ) ) {
336 $last_val = array_pop( $value );
337
338 list( $tied_item ) = array_slice(
339 WPCF7_USE_PIPE ? $tag->pipes->collect_afters() : $tag->values,
340 -1, 1
341 );
342
343 list( $last_val, $tied_item ) = array_map(
344 function ( $item ) {
345 return wpcf7_canonicalize( $item, array(
346 'strto' => 'as-is',
347 ) );
348 },
349 array( $last_val, $tied_item )
350 );
351
352 if ( $last_val === $tied_item ) {
353 $value[] = sprintf( '%s %s',
354 $last_val,
355 $posted_data[$name . '_free_text']
356 );
357 } else {
358 $value[] = $last_val;
359 }
360
361 unset( $posted_data[$name . '_free_text'] );
362 }
363 }
364
365 $value = apply_filters( "wpcf7_posted_data_{$type}", $value,
366 $value_orig, $tag );
367
368 $posted_data[$name] = $value;
369
370 if ( $tag->has_option( 'consent_for:storage' )
371 and empty( $posted_data[$name] ) ) {
372 $this->meta['do_not_store'] = true;
373 }
374 }
375
376 $this->posted_data = apply_filters( 'wpcf7_posted_data', $posted_data );
377
378 $this->posted_data_hash = $this->create_posted_data_hash();
379
380 return $this->posted_data;
381 }
382
383
384 private function sanitize_posted_data( $value ) {
385 if ( is_array( $value ) ) {
386 $value = array_map( array( $this, 'sanitize_posted_data' ), $value );
387 } elseif ( is_string( $value ) ) {
388 $value = wp_check_invalid_utf8( $value );
389 $value = wp_kses_no_null( $value );
390 }
391
392 return $value;
393 }
394
395
396 /**
397 * Returns the time-dependent variable for hash creation.
398 *
399 * @return float Float value rounded up to the next highest integer.
400 */
401 private function posted_data_hash_tick() {
402 return ceil( time() / ( HOUR_IN_SECONDS / 2 ) );
403 }
404
405
406 /**
407 * Creates a hash string based on posted data, the remote IP address,
408 * contact form location, and window of time.
409 *
410 * @param string $tick Optional. If not specified, result of
411 * posted_data_hash_tick() will be used.
412 * @return string The hash.
413 */
414 private function create_posted_data_hash( $tick = '' ) {
415 if ( '' === $tick ) {
416 $tick = $this->posted_data_hash_tick();
417 }
418
419 $hash = wp_hash(
420 wpcf7_flat_join( array_merge(
421 array(
422 $tick,
423 $this->get_meta( 'remote_ip' ),
424 $this->get_meta( 'unit_tag' ),
425 ),
426 $this->posted_data
427 ) ),
428 'wpcf7_submission'
429 );
430
431 return $hash;
432 }
433
434
435 /**
436 * Returns the hash string created for this submission.
437 *
438 * @return string The current hash for the submission.
439 */
440 public function get_posted_data_hash() {
441 return $this->posted_data_hash;
442 }
443
444
445 /**
446 * Verifies that the given string is equivalent to the posted data hash.
447 *
448 * @param string $hash Optional. This value will be compared to the
449 * current posted data hash for the submission. If not
450 * specified, the value of $_POST['_wpcf7_posted_data_hash']
451 * will be used.
452 * @return int|bool 1 if $hash is created 0-30 minutes ago,
453 * 2 if $hash is created 30-60 minutes ago,
454 * false if $hash is invalid.
455 */
456 public function verify_posted_data_hash( $hash = '' ) {
457 if ( '' === $hash and ! empty( $_POST['_wpcf7_posted_data_hash'] ) ) {
458 $hash = trim( $_POST['_wpcf7_posted_data_hash'] );
459 }
460
461 if ( '' === $hash ) {
462 return false;
463 }
464
465 $tick = $this->posted_data_hash_tick();
466
467 // Hash created 0-30 minutes ago.
468 $expected_1 = $this->create_posted_data_hash( $tick );
469
470 if ( hash_equals( $expected_1, $hash ) ) {
471 return 1;
472 }
473
474 // Hash created 30-60 minutes ago.
475 $expected_2 = $this->create_posted_data_hash( $tick - 1 );
476
477 if ( hash_equals( $expected_2, $hash ) ) {
478 return 2;
479 }
480
481 return false;
482 }
483
484
485 private function get_remote_ip_addr() {
486 $ip_addr = '';
487
488 if ( isset( $_SERVER['REMOTE_ADDR'] )
489 and WP_Http::is_ip_address( $_SERVER['REMOTE_ADDR'] ) ) {
490 $ip_addr = $_SERVER['REMOTE_ADDR'];
491 }
492
493 return apply_filters( 'wpcf7_remote_ip_addr', $ip_addr );
494 }
495
496
497 private function get_request_url() {
498 $home_url = untrailingslashit( home_url() );
499
500 if ( self::is_restful() ) {
501 $referer = isset( $_SERVER['HTTP_REFERER'] )
502 ? trim( $_SERVER['HTTP_REFERER'] ) : '';
503
504 if ( $referer
505 and 0 === strpos( $referer, $home_url ) ) {
506 return esc_url_raw( $referer );
507 }
508 }
509
510 $url = preg_replace( '%(?<!:|/)/.*$%', '', $home_url )
511 . wpcf7_get_request_uri();
512
513 return $url;
514 }
515
516
517 private function validate() {
518 if ( $this->invalid_fields ) {
519 return false;
520 }
521
522 $result = new WPCF7_Validation();
523
524 $this->contact_form->validate_schema(
525 array(
526 'text' => true,
527 'file' => false,
528 'field' => array(),
529 ),
530 $result
531 );
532
533 $tags = $this->contact_form->scan_form_tags( array(
534 'feature' => '! file-uploading',
535 ) );
536
537 foreach ( $tags as $tag ) {
538 $type = $tag->type;
539 $result = apply_filters( "wpcf7_validate_{$type}", $result, $tag );
540 }
541
542 $result = apply_filters( 'wpcf7_validate', $result, $tags );
543
544 $this->invalid_fields = $result->get_invalid_fields();
545
546 return $result->is_valid();
547 }
548
549
550 private function accepted() {
551 return apply_filters( 'wpcf7_acceptance', true, $this );
552 }
553
554
555 public function add_consent( $name, $conditions ) {
556 $this->consent[$name] = $conditions;
557 return true;
558 }
559
560
561 public function collect_consent() {
562 return (array) $this->consent;
563 }
564
565
566 private function spam() {
567 $spam = false;
568
569 $skip_spam_check = apply_filters( 'wpcf7_skip_spam_check',
570 $this->skip_spam_check,
571 $this
572 );
573
574 if ( $skip_spam_check ) {
575 return $spam;
576 }
577
578 if ( $this->contact_form->is_true( 'subscribers_only' )
579 and current_user_can( 'wpcf7_submit', $this->contact_form->id() ) ) {
580 return $spam;
581 }
582
583 $user_agent = (string) $this->get_meta( 'user_agent' );
584
585 if ( strlen( $user_agent ) < 2 ) {
586 $spam = true;
587
588 $this->add_spam_log( array(
589 'agent' => 'wpcf7',
590 'reason' => __( "User-Agent string is unnaturally short.", 'contact-form-7' ),
591 ) );
592 }
593
594 if ( ! $this->verify_nonce() ) {
595 $spam = true;
596
597 $this->add_spam_log( array(
598 'agent' => 'wpcf7',
599 'reason' => __( "Submitted nonce is invalid.", 'contact-form-7' ),
600 ) );
601 }
602
603 return apply_filters( 'wpcf7_spam', $spam, $this );
604 }
605
606
607 public function add_spam_log( $args = '' ) {
608 $args = wp_parse_args( $args, array(
609 'agent' => '',
610 'reason' => '',
611 ) );
612
613 $this->spam_log[] = $args;
614 }
615
616
617 public function get_spam_log() {
618 return $this->spam_log;
619 }
620
621
622 private function verify_nonce() {
623 if ( ! $this->contact_form->nonce_is_active() or ! is_user_logged_in() ) {
624 return true;
625 }
626
627 $nonce = isset( $_POST['_wpnonce'] ) ? $_POST['_wpnonce'] : '';
628
629 return wpcf7_verify_nonce( $nonce );
630 }
631
632
633 /* Mail */
634
635 private function before_send_mail() {
636 $abort = false;
637
638 do_action_ref_array( 'wpcf7_before_send_mail', array(
639 $this->contact_form,
640 &$abort,
641 $this,
642 ) );
643
644 return ! $abort;
645 }
646
647
648 private function mail() {
649 $contact_form = $this->contact_form;
650
651 $skip_mail = apply_filters( 'wpcf7_skip_mail',
652 $this->skip_mail, $contact_form
653 );
654
655 if ( $skip_mail ) {
656 return true;
657 }
658
659 $result = WPCF7_Mail::send( $contact_form->prop( 'mail' ), 'mail' );
660
661 if ( $result ) {
662 $additional_mail = array();
663
664 if ( $mail_2 = $contact_form->prop( 'mail_2' )
665 and $mail_2['active'] ) {
666 $additional_mail['mail_2'] = $mail_2;
667 }
668
669 $additional_mail = apply_filters( 'wpcf7_additional_mail',
670 $additional_mail, $contact_form
671 );
672
673 foreach ( $additional_mail as $name => $template ) {
674 WPCF7_Mail::send( $template, $name );
675 }
676
677 return true;
678 }
679
680 return false;
681 }
682
683
684 public function uploaded_files() {
685 return $this->uploaded_files;
686 }
687
688
689 private function add_uploaded_file( $name, $file_path ) {
690 if ( ! wpcf7_is_name( $name ) ) {
691 return false;
692 }
693
694 $paths = (array) $file_path;
695 $uploaded_files = array();
696 $hash_strings = array();
697
698 foreach ( $paths as $path ) {
699 if ( @is_file( $path ) and @is_readable( $path ) ) {
700 $uploaded_files[] = $path;
701 $hash_strings[] = md5_file( $path );
702 }
703 }
704
705 $this->uploaded_files[$name] = $uploaded_files;
706
707 if ( empty( $this->posted_data[$name] ) ) {
708 $this->posted_data[$name] = implode( ' ', $hash_strings );
709 }
710 }
711
712
713 private function remove_uploaded_files() {
714 foreach ( (array) $this->uploaded_files as $file_path ) {
715 $paths = (array) $file_path;
716
717 foreach ( $paths as $path ) {
718 wpcf7_rmdir_p( $path );
719
720 if ( $dir = dirname( $path )
721 and false !== ( $files = scandir( $dir ) )
722 and ! array_diff( $files, array( '.', '..' ) ) ) {
723 // remove parent dir if it's empty.
724 rmdir( $dir );
725 }
726 }
727 }
728 }
729
730
731 private function unship_uploaded_files() {
732 $result = new WPCF7_Validation();
733
734 $tags = $this->contact_form->scan_form_tags( array(
735 'feature' => 'file-uploading',
736 ) );
737
738 foreach ( $tags as $tag ) {
739 if ( empty( $_FILES[$tag->name] ) ) {
740 continue;
741 }
742
743 $file = $_FILES[$tag->name];
744
745 $args = array(
746 'tag' => $tag,
747 'name' => $tag->name,
748 'required' => $tag->is_required(),
749 'filetypes' => $tag->get_option( 'filetypes' ),
750 'limit' => $tag->get_limit_option(),
751 'schema' => $this->contact_form->get_schema(),
752 );
753
754 $new_files = wpcf7_unship_uploaded_file( $file, $args );
755
756 if ( is_wp_error( $new_files ) ) {
757 $result->invalidate( $tag, $new_files );
758 } else {
759 $this->add_uploaded_file( $tag->name, $new_files );
760 }
761
762 $result = apply_filters(
763 "wpcf7_validate_{$tag->type}",
764 $result, $tag,
765 array(
766 'uploaded_files' => $new_files,
767 )
768 );
769 }
770
771 $this->invalid_fields = $result->get_invalid_fields();
772
773 return $result->is_valid();
774 }
775
776
777 /**
778 * Adds extra email attachment files that are independent from form fields.
779 *
780 * @param string|array $file_path A file path or an array of file paths.
781 * @param string $template Optional. The name of the template to which
782 * the files are attached.
783 * @return bool True if it succeeds to attach a file at least,
784 * or false otherwise.
785 */
786 public function add_extra_attachments( $file_path, $template = 'mail' ) {
787 if ( ! did_action( 'wpcf7_before_send_mail' ) ) {
788 return false;
789 }
790
791 $extra_attachments = array();
792
793 foreach ( (array) $file_path as $path ) {
794 $path = path_join( WP_CONTENT_DIR, $path );
795
796 if ( file_exists( $path ) ) {
797 $extra_attachments[] = $path;
798 }
799 }
800
801 if ( empty( $extra_attachments ) ) {
802 return false;
803 }
804
805 if ( ! isset( $this->extra_attachments[$template] ) ) {
806 $this->extra_attachments[$template] = array();
807 }
808
809 $this->extra_attachments[$template] = array_merge(
810 $this->extra_attachments[$template],
811 $extra_attachments
812 );
813
814 return true;
815 }
816
817
818 /**
819 * Returns extra email attachment files.
820 *
821 * @param string $template An email template name.
822 * @return array Array of file paths.
823 */
824 public function extra_attachments( $template ) {
825 if ( isset( $this->extra_attachments[$template] ) ) {
826 return (array) $this->extra_attachments[$template];
827 }
828
829 return array();
830 }
831
832 }
833