PluginProbe ʕ •ᴥ•ʔ
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More / 1.9.1.2
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More v1.9.1.2
1.10.1.1 1.10.1 1.10.0.5 trunk 1.1.4 1.1.4.2 1.1.5 1.1.5.1 1.1.6 1.1.6.1 1.1.7 1.1.7.1 1.1.7.2 1.1.8 1.1.8.1 1.1.8.2 1.1.8.3 1.1.8.4 1.10.0.1 1.10.0.2 1.10.0.3 1.10.0.4 1.2.0 1.2.0.1 1.2.1 1.2.2 1.2.2.1 1.2.2.2 1.2.3 1.2.3.1 1.2.3.2 1.2.4 1.2.4.1 1.2.5 1.2.5.1 1.2.6 1.2.7 1.2.8 1.2.8.1 1.2.9 1.3.0 1.3.1 1.3.1.1 1.3.1.2 1.3.2 1.3.3 1.3.5 1.3.6 1.3.6.1 1.3.6.2 1.3.7.2 1.3.7.3 1.3.7.4 1.3.8 1.3.9.1 1.4.0.1 1.4.1.1 1.4.2 1.4.2.1 1.4.2.2 1.4.3 1.4.4 1.4.4.1 1.4.5 1.4.5.1 1.4.5.2 1.4.5.3 1.4.6 1.4.7.1 1.4.7.2 1.4.8.1 1.4.9 1.5.0.1 1.5.0.3 1.5.0.4 1.5.1 1.5.1.1 1.5.1.3 1.5.2.1 1.5.2.2 1.5.2.3 1.5.3 1.5.3.1 1.5.4.1 1.5.4.2 1.5.5 1.5.5.1 1.5.6 1.5.6.2 1.5.7 1.5.8.2 1.5.9.1 1.5.9.4 1.5.9.5 1.6.0.1 1.6.0.2 1.6.1 1.6.2.2 1.6.2.3 1.6.3.1 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.7 1.6.7.1 1.6.7.2 1.6.7.3 1.6.8 1.6.8.1 1.6.9 1.7.0 1.7.1.1 1.7.1.2 1.7.2 1.7.2.1 1.7.3 1.7.4 1.7.4.1 1.7.4.2 1.7.5.1 1.7.5.2 1.7.5.3 1.7.5.5 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.7.9.1 1.8.0.1 1.8.0.2 1.8.1.1 1.8.1.2 1.8.1.3 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.3.1 1.8.4 1.8.4.1 1.8.5.2 1.8.5.3 1.8.5.4 1.8.6.2 1.8.6.3 1.8.6.4 1.8.7.2 1.8.8.2 1.8.8.3 1.8.9.1 1.8.9.2 1.8.9.4 1.8.9.5 1.8.9.6 1.9.0.1 1.9.0.2 1.9.0.3 1.9.0.4 1.9.1.1 1.9.1.2 1.9.1.3 1.9.1.4 1.9.1.5 1.9.1.6 1.9.2.1 1.9.2.2 1.9.2.3 1.9.3.1 1.9.3.2 1.9.4.1 1.9.4.2 1.9.5 1.9.5.1 1.9.5.2 1.9.6 1.9.6.1 1.9.6.2 1.9.7.1 1.9.7.2 1.9.7.3 1.9.8.1 1.9.8.2 1.9.8.4 1.9.8.7 1.9.9.2 1.9.9.3 1.9.9.4
wpforms-lite / includes / emails / class-emails.php
wpforms-lite / includes / emails Last commit date
templates 1 year ago class-emails.php 1 year ago
class-emails.php
882 lines
1 <?php
2
3 use WPForms\Helpers\Templates;
4 use WPForms\Tasks\Actions\EntryEmailsTask;
5
6 /**
7 * Emails.
8 *
9 * This class handles all (notification) emails sent by WPForms.
10 *
11 * Heavily influenced by the great AffiliateWP plugin by Pippin Williamson.
12 * https://github.com/AffiliateWP/AffiliateWP/blob/master/includes/emails/class-affwp-emails.php
13 *
14 * Note that this mailer class is no longer in active use and has been replaced with the "WPForms\Emails\Notifications" class.
15 * Please refer to the new mailer wrapper extension to extend or add further customizations.
16 *
17 * @deprecated 1.8.5
18 *
19 * @since 1.1.3
20 */
21 class WPForms_WP_Emails {
22
23 /**
24 * Store the from address.
25 *
26 * @since 1.1.3
27 *
28 * @var string
29 */
30 private $from_address;
31
32 /**
33 * Store the from name.
34 *
35 * @since 1.1.3
36 *
37 * @var string
38 */
39 private $from_name;
40
41 /**
42 * Store the reply-to address.
43 *
44 * @since 1.1.3
45 *
46 * @var bool|string
47 */
48 private $reply_to = false;
49
50 /**
51 * Store the reply-to name.
52 *
53 * @since 1.7.9
54 *
55 * @var bool|string
56 */
57 private $reply_to_name = false;
58
59 /**
60 * Store the carbon copy addresses.
61 *
62 * @since 1.3.1
63 *
64 * @var string
65 */
66 private $cc = false;
67
68 /**
69 * Store the email content type.
70 *
71 * @since 1.1.3
72 *
73 * @var string
74 */
75 private $content_type;
76
77 /**
78 * Store the email headers.
79 *
80 * @since 1.1.3
81 *
82 * @var string
83 */
84 private $headers;
85
86 /**
87 * Whether to send email in HTML.
88 *
89 * @since 1.1.3
90 *
91 * @var bool
92 */
93 private $html = true;
94
95 /**
96 * The email template to use.
97 *
98 * @since 1.1.3
99 *
100 * @var string
101 */
102 private $template;
103
104 /**
105 * Form data and settings.
106 *
107 * @since 1.1.3
108 *
109 * @var array
110 */
111 public $form_data = [];
112
113 /**
114 * Fields, formatted, and sanitized.
115 *
116 * @since 1.1.3
117 *
118 * @var array
119 */
120 public $fields = [];
121
122 /**
123 * Entry ID.
124 *
125 * @since 1.2.3
126 *
127 * @var int
128 */
129 public $entry_id = '';
130
131 /**
132 * Notification ID that is currently being processed.
133 *
134 * @since 1.5.7
135 *
136 * @var int
137 */
138 public $notification_id = '';
139
140 /**
141 * Get things going.
142 *
143 * @since 1.1.3
144 */
145 public function __construct() {
146
147 if ( 'none' === $this->get_template() ) {
148 $this->html = false;
149 }
150
151 add_action( 'wpforms_email_send_before', [ $this, 'send_before' ] );
152 add_action( 'wpforms_email_send_after', [ $this, 'send_after' ] );
153 }
154
155 /**
156 * Set a property.
157 *
158 * @since 1.1.3
159 *
160 * @param string $key Object property key.
161 * @param mixed $value Object property value.
162 */
163 public function __set( $key, $value ) {
164
165 $this->$key = $value;
166 }
167
168 /**
169 * Get the email from name.
170 *
171 * @since 1.1.3
172 *
173 * @return string The email from name
174 */
175 public function get_from_name() {
176
177 if ( ! empty( $this->from_name ) ) {
178 $this->from_name = $this->process_tag( $this->from_name );
179 } else {
180 $this->from_name = get_bloginfo( 'name' );
181 }
182
183 return apply_filters( 'wpforms_email_from_name', wpforms_decode_string( $this->from_name ), $this );
184 }
185
186 /**
187 * Get the email from address.
188 *
189 * @since 1.1.3
190 *
191 * @return string The email from address.
192 */
193 public function get_from_address() {
194
195 if ( ! empty( $this->from_address ) ) {
196 $this->from_address = $this->process_tag( $this->from_address );
197 } else {
198 $this->from_address = get_option( 'admin_email' );
199 }
200
201 return apply_filters( 'wpforms_email_from_address', wpforms_decode_string( $this->from_address ), $this );
202 }
203
204 /**
205 * Get the email reply-to.
206 *
207 * @since 1.1.3
208 *
209 * @return string The email reply-to address.
210 */
211 public function get_reply_to() {
212
213 if ( ! empty( $this->reply_to ) ) {
214
215 $email = $this->reply_to;
216
217 // Optional custom format with a Reply-to Name specified: John Doe <john@doe.com>
218 // - starts with anything,
219 // - followed by space,
220 // - ends with <anything> (expected to be an email, validated later).
221 $regex = '/^(.+) (<.+>)$/';
222 $matches = [];
223
224 if ( preg_match( $regex, $this->reply_to, $matches ) ) {
225 $this->reply_to_name = wpforms_decode_string( $this->process_tag( $matches[1] ) );
226 $email = trim( $matches[2], '<> ' );
227 }
228
229 $this->reply_to = $this->process_tag( $email );
230
231 if ( ! is_email( $this->reply_to ) ) {
232 $this->reply_to = false;
233 $this->reply_to_name = false;
234 }
235 }
236
237 return apply_filters( 'wpforms_email_reply_to', wpforms_decode_string( $this->reply_to ), $this );
238 }
239
240 /**
241 * Get the email carbon copy addresses.
242 *
243 * @since 1.3.1
244 *
245 * @return string The email reply-to address.
246 */
247 public function get_cc() {
248
249 if ( is_array( $this->cc ) ) {
250 $this->cc = implode( ',', $this->cc );
251 }
252
253 if ( ! empty( $this->cc ) ) {
254
255 $this->cc = $this->process_tag( $this->cc );
256
257 $addresses = array_map( 'trim', explode( ',', $this->cc ) );
258
259 foreach ( $addresses as $key => $address ) {
260 if ( ! is_email( $address ) ) {
261 unset( $addresses[ $key ] );
262 }
263 }
264
265 $this->cc = implode( ',', $addresses );
266 }
267
268 return apply_filters( 'wpforms_email_cc', wpforms_decode_string( $this->cc ), $this );
269 }
270
271 /**
272 * Get the email content type.
273 *
274 * @since 1.1.3
275 *
276 * @return string The email content type.
277 */
278 public function get_content_type() {
279
280 if ( ! $this->content_type && $this->html ) {
281 $this->content_type = apply_filters( 'wpforms_email_default_content_type', 'text/html', $this );
282 } elseif ( ! $this->html ) {
283 $this->content_type = 'text/plain';
284 }
285
286 return apply_filters( 'wpforms_email_content_type', $this->content_type, $this );
287 }
288
289 /**
290 * Get the email headers.
291 *
292 * @since 1.1.3
293 *
294 * @return string The email headers.
295 */
296 public function get_headers() {
297
298 if ( ! $this->headers ) {
299 $this->headers = "From: {$this->get_from_name()} <{$this->get_from_address()}>\r\n";
300
301 if ( $this->get_reply_to() ) {
302 $this->headers .= $this->reply_to_name ?
303 "Reply-To: {$this->reply_to_name} <{$this->get_reply_to()}>\r\n" :
304 "Reply-To: {$this->get_reply_to()}\r\n";
305 }
306
307 if ( $this->get_cc() ) {
308 $this->headers .= "Cc: {$this->get_cc()}\r\n";
309 }
310
311 $this->headers .= "Content-Type: {$this->get_content_type()}; charset=utf-8\r\n";
312 }
313
314 return apply_filters( 'wpforms_email_headers', $this->headers, $this );
315 }
316
317 /**
318 * Build the email.
319 *
320 * @since 1.1.3
321 *
322 * @param string $message The email message.
323 *
324 * @return string
325 */
326 public function build_email( $message ) {
327
328 // Plain text email shortcut.
329 if ( false === $this->html ) {
330 $message = $this->process_tag( $message );
331 $message = str_replace( '{all_fields}', $this->wpforms_html_field_value( false ), $message );
332
333 return apply_filters( 'wpforms_email_message', wpforms_decode_string( $message ), $this );
334 }
335
336 /*
337 * Generate an HTML email.
338 */
339
340 ob_start();
341
342 $this->get_template_part( 'header', $this->get_template(), true );
343
344 // Hooks into the email header.
345 do_action( 'wpforms_email_header', $this );
346
347 $this->get_template_part( 'body', $this->get_template(), true );
348
349 // Hooks into the email body.
350 do_action( 'wpforms_email_body', $this );
351
352 $this->get_template_part( 'footer', $this->get_template(), true );
353
354 // Hooks into the email footer.
355 do_action( 'wpforms_email_footer', $this );
356
357 $message = $this->process_tag( $message );
358 $message = nl2br( $message );
359
360 $body = ob_get_clean();
361
362 $message = str_replace( '{email}', $message, $body );
363 $message = str_replace( '{all_fields}', $this->wpforms_html_field_value( true ), $message );
364 $message = make_clickable( $message );
365
366 return apply_filters( 'wpforms_email_message', $message, $this );
367 }
368
369 /**
370 * Send the email.
371 *
372 * @since 1.1.3
373 *
374 * @param string $to The To address.
375 * @param string $subject The subject line of the email.
376 * @param string $message The body of the email.
377 * @param array $attachments Attachments to the email.
378 *
379 * @return bool
380 */
381 public function send( $to, $subject, $message, $attachments = [] ) {
382
383 if ( ! did_action( 'init' ) && ! did_action( 'admin_init' ) ) {
384 _doing_it_wrong( __FUNCTION__, esc_html__( 'You cannot send emails with WPForms_WP_Emails() until init/admin_init has been reached.', 'wpforms-lite' ), null );
385
386 return false;
387 }
388
389 // Don't send anything if emails have been disabled.
390 if ( $this->is_email_disabled() ) {
391 return false;
392 }
393
394 // Don't send if email address is invalid.
395 if ( ! is_email( $to ) ) {
396 return false;
397 }
398
399 // Hooks before email is sent.
400 do_action( 'wpforms_email_send_before', $this );
401
402 // Deprecated filter for $attachments.
403 $attachments = apply_filters_deprecated(
404 'wpforms_email_attachments',
405 [ $attachments, $this ],
406 '1.5.7 of the WPForms plugin',
407 'wpforms_emails_send_email_data'
408 );
409
410 /*
411 * Allow to filter data on per-email basis,
412 * useful for localizations based on recipient email address, form settings,
413 * or for specific notifications - whatever available in WPForms_WP_Emails class.
414 */
415 $data = apply_filters(
416 'wpforms_emails_send_email_data',
417 [
418 'to' => $to,
419 'subject' => $subject,
420 'message' => $message,
421 'headers' => $this->get_headers(),
422 'attachments' => $attachments,
423 ],
424 $this
425 );
426
427 $entry_obj = wpforms()->obj( 'entry' );
428
429 // phpcs:ignore WPForms.Comments.PHPDocHooks.RequiredHookDocumentation, WPForms.PHP.ValidateHooks.InvalidHookName
430 $send_same_process = apply_filters(
431 'wpforms_tasks_entry_emails_trigger_send_same_process',
432 false,
433 $this->fields,
434 $entry_obj ? $entry_obj->get( $this->entry_id ) : [],
435 $this->form_data,
436 $this->entry_id,
437 'entry'
438 );
439
440 if (
441 $send_same_process ||
442 ! empty( $this->form_data['settings']['disable_entries'] )
443 ) {
444 // Let's do this NOW.
445 $result = wp_mail(
446 $data['to'],
447 $this->get_prepared_subject( $data['subject'] ),
448 $this->build_email( $data['message'] ),
449 $data['headers'],
450 $data['attachments']
451 );
452 } else {
453 // Schedule the email.
454 $result = (bool) ( new EntryEmailsTask() )
455 ->params(
456 $data['to'],
457 $this->get_prepared_subject( $data['subject'] ),
458 $this->build_email( $data['message'] ),
459 $data['headers'],
460 $data['attachments']
461 )
462 ->register();
463 }
464
465 /**
466 * Hooks after the email is sent.
467 *
468 * @since 1.1.3
469 *
470 * @param WPForms_WP_Emails $this Current instance of this object.
471 */
472 do_action( 'wpforms_email_send_after', $this ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
473
474 return $result;
475 }
476
477 /**
478 * Add filters/actions before the email is sent.
479 *
480 * @since 1.1.3
481 */
482 public function send_before() {
483
484 add_filter( 'wp_mail_from', [ $this, 'get_from_address' ] );
485 add_filter( 'wp_mail_from_name', [ $this, 'get_from_name' ] );
486 add_filter( 'wp_mail_content_type', [ $this, 'get_content_type' ] );
487 }
488
489 /**
490 * Remove filters/actions after the email is sent.
491 *
492 * @since 1.1.3
493 */
494 public function send_after() {
495
496 remove_filter( 'wp_mail_from', [ $this, 'get_from_address' ] );
497 remove_filter( 'wp_mail_from_name', [ $this, 'get_from_name' ] );
498 remove_filter( 'wp_mail_content_type', [ $this, 'get_content_type' ] );
499 }
500
501 /**
502 * Convert text formatted HTML. This is primarily for turning line breaks
503 * into <p> and <br/> tags.
504 *
505 * @since 1.1.3
506 *
507 * @param string $message Text to convert.
508 *
509 * @return string
510 */
511 public function text_to_html( $message ) {
512
513 if ( 'text/html' === $this->content_type || true === $this->html ) {
514 $message = wpautop( $message );
515 }
516
517 return $message;
518 }
519
520 /**
521 * Process a smart tag.
522 * Decodes entities and sanitized (keeping line breaks) by default.
523 *
524 * @uses wpforms_decode_string()
525 *
526 * @since 1.1.3
527 * @since 1.6.0 Deprecated 2 params: $sanitize, $linebreaks.
528 *
529 * @param string $string String that may contain tags.
530 *
531 * @return string
532 */
533 public function process_tag( $string = '' ) {
534
535 return wpforms_process_smart_tags( $string, $this->form_data, $this->fields, $this->entry_id, 'email' );
536 }
537
538 /**
539 * Process the all fields smart tag if present.
540 *
541 * @since 1.1.3
542 *
543 * @param bool $is_html_email Toggle to use HTML or plaintext.
544 *
545 * @return string
546 */
547 public function wpforms_html_field_value( $is_html_email = true ) { // phpcs:ignore
548
549 if ( empty( $this->fields ) ) {
550 return '';
551 }
552
553 if ( empty( $this->form_data['fields'] ) ) {
554 $is_html_email = false;
555 }
556
557 $message = '';
558
559 if ( $is_html_email ) {
560 /*
561 * HTML emails.
562 */
563 ob_start();
564
565 // Hooks into the email field.
566 do_action( 'wpforms_email_field', $this );
567
568 $this->get_template_part( 'field', $this->get_template(), true );
569
570 $field_template = ob_get_clean();
571
572 // Check to see if user has added support for field type.
573 $other_fields = apply_filters( 'wpforms_email_display_other_fields', [], $this );
574
575 $x = 1;
576
577 foreach ( $this->form_data['fields'] as $field_id => $field ) {
578
579 $field_name = '';
580 $field_val = '';
581
582 // If the field exists in the form_data but not in the final
583 // field data, then it's a non-input based field, "other fields".
584 if ( empty( $this->fields[ $field_id ] ) ) {
585
586 // Check if the field type is in $other_fields, otherwise skip.
587 // Skip if the field is conditionally hidden.
588 if (
589 empty( $other_fields ) ||
590 ! in_array( $field['type'], $other_fields, true ) ||
591 (
592 wpforms()->is_pro() &&
593 wpforms_conditional_logic_fields()->field_is_hidden( $this->form_data, $field_id )
594 )
595 ) {
596 continue;
597 }
598
599 if ( $field['type'] === 'divider' ) {
600 $field_name = ! empty( $field['label'] ) ? str_repeat( '&mdash;', 3 ) . ' ' . $field['label'] . ' ' . str_repeat( '&mdash;', 3 ) : null;
601 $field_val = ! empty( $field['description'] ) ? $field['description'] : '';
602 } elseif ( $field['type'] === 'pagebreak' ) {
603 if ( ! empty( $field['position'] ) && $field['position'] === 'bottom' ) {
604 continue;
605 }
606 $title = ! empty( $field['title'] ) ? $field['title'] : esc_html__( 'Page Break', 'wpforms-lite' );
607 $field_name = str_repeat( '&mdash;', 6 ) . ' ' . $title . ' ' . str_repeat( '&mdash;', 6 );
608 } elseif ( $field['type'] === 'html' ) {
609
610 $field_name = ! empty( $field['name'] ) ? $field['name'] : esc_html__( 'HTML / Code Block', 'wpforms-lite' );
611 $field_val = $field['code'];
612 } elseif ( $field['type'] === 'content' ) {
613
614 $field_name = esc_html__( 'Content', 'wpforms-lite' );
615 $field_val = $field['content'];
616 }
617 } else {
618
619 if (
620 ! apply_filters( 'wpforms_email_display_empty_fields', false ) &&
621 ( ! isset( $this->fields[ $field_id ]['value'] ) || (string) $this->fields[ $field_id ]['value'] === '' )
622 ) {
623 continue;
624 }
625
626 if ( $field['type'] === 'payment-total' ) {
627
628 $field_name = isset( $this->fields[ $field_id ]['name'] ) ? $this->fields[ $field_id ]['name'] : '';
629
630 // Replace the payment total value if an order summary is enabled.
631 // Ideally, it could be done through the `wpforms_html_field_value` filter,
632 // but needed data is missed there, e.g. entry data ($this->fields).
633 if ( ! empty( $field['summary'] ) ) {
634 $field_val = $this->process_tag( '{order_summary}' );
635 } else {
636 $field_val = $this->fields[ $field_id ]['value'];
637 }
638 } else {
639 $field_name = isset( $this->fields[ $field_id ]['name'] ) ? $this->fields[ $field_id ]['name'] : '';
640 $field_val = empty( $this->fields[ $field_id ]['value'] ) && ! is_numeric( $this->fields[ $field_id ]['value'] ) ? '<em>' . esc_html__( '(empty)', 'wpforms-lite' ) . '</em>' : $this->fields[ $field_id ]['value'];
641 }
642 }
643
644 if ( empty( $field_name ) && null !== $field_name ) {
645 $field_name = sprintf( /* translators: %d - field ID. */
646 esc_html__( 'Field ID #%s', 'wpforms-lite' ),
647 wpforms_validate_field_id( $field['id'] )
648 );
649 }
650
651 $field_item = $field_template;
652
653 if ( 1 === $x ) {
654 $field_item = str_replace( 'border-top:1px solid #dddddd;', '', $field_item );
655 }
656
657 /**
658 * Filter the field name before it is added to the email message.
659 *
660 * @since 1.9.1
661 *
662 * @param string $field_name Field name.
663 * @param array $field Field data.
664 * @param array $form_data Form data and settings.
665 * @param string $context Context of the field name.
666 */
667 $field_name = apply_filters( // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
668 'wpforms_html_field_name',
669 $field_name,
670 $this->fields[ $field_id ] ?? $field,
671 $this->form_data,
672 'email-html'
673 );
674
675 $field_item = str_replace( '{field_name}', $field_name, $field_item );
676 $field_item = str_replace(
677 '{field_value}',
678 apply_filters(
679 'wpforms_html_field_value',
680 $field_val,
681 isset( $this->fields[ $field_id ] ) ? $this->fields[ $field_id ] : $field,
682 $this->form_data,
683 'email-html'
684 ),
685 $field_item
686 );
687
688 $message .= wpautop( $field_item );
689
690 $x ++;
691 }
692 } else {
693 /*
694 * Plain Text emails.
695 */
696 foreach ( $this->fields as $field ) {
697
698 if (
699 ! apply_filters( 'wpforms_email_display_empty_fields', false ) &&
700 ( ! isset( $field['value'] ) || (string) $field['value'] === '' )
701 ) {
702 continue;
703 }
704
705 $field_val = empty( $field['value'] ) && ! is_numeric( $field['value'] ) ? esc_html__( '(empty)', 'wpforms-lite' ) : $field['value'];
706 $field_name = $field['name'];
707
708 if ( empty( $field_name ) ) {
709 $field_name = sprintf( /* translators: %d - field ID. */
710 esc_html__( 'Field ID #%s', 'wpforms-lite' ),
711 wpforms_validate_field_id( $field['id'] )
712 );
713 }
714
715 $message .= '--- ' . $field_name . " ---\r\n\r\n";
716 $field_value = $field_val . "\r\n\r\n";
717 $message .= apply_filters( 'wpforms_plaintext_field_value', $field_value, $field, $this->form_data );
718 }
719 }
720
721 if ( empty( $message ) ) {
722 $empty_message = esc_html__( 'An empty form was submitted.', 'wpforms-lite' );
723 $message = $is_html_email ? wpautop( $empty_message ) : $empty_message;
724 }
725
726 return $message;
727 }
728
729 /**
730 * Email kill switch if needed.
731 *
732 * @since 1.1.3
733 *
734 * @return bool
735 */
736 public function is_email_disabled() {
737
738 return (bool) apply_filters( 'wpforms_disable_all_emails', false, $this );
739 }
740
741 /**
742 * Get the enabled email template.
743 *
744 * @since 1.1.3
745 *
746 * @return string When filtering return 'none' to switch to text/plain email.
747 */
748 public function get_template() {
749
750 if ( ! $this->template ) {
751 $this->template = wpforms_setting( 'email-template', 'default' );
752 }
753
754 return apply_filters( 'wpforms_email_template', $this->template );
755 }
756
757 /**
758 * Retrieve a template part. Taken from bbPress.
759 *
760 * @since 1.1.3
761 *
762 * @param string $slug Template file slug.
763 * @param string $name Optional. Default null.
764 * @param bool $load Maybe load.
765 *
766 * @return string
767 */
768 public function get_template_part( $slug, $name = null, $load = true ) {
769
770 // Setup possible parts.
771 $templates = [];
772
773 if ( isset( $name ) ) {
774 $templates[] = $slug . '-' . $name . '.php';
775 }
776
777 $templates[] = $slug . '.php';
778
779 // Return the part that is found.
780 return $this->locate_template( $templates, $load, false );
781 }
782
783 /**
784 * Retrieve the name of the highest priority template file that exists.
785 *
786 * Search in the STYLESHEETPATH before TEMPLATEPATH so that themes which
787 * inherit from a parent theme can just overload one file. If the template is
788 * not found in either of those, it looks in the theme-compat folder last.
789 *
790 * Taken from bbPress.
791 *
792 * @since 1.1.3
793 *
794 * @param string|array $template_names Template file(s) to search for, in order.
795 * @param bool $load If true the template file will be loaded if it is found.
796 * @param bool $require_once Whether to require_once or require. Default true.
797 * Has no effect if $load is false.
798 *
799 * @return string The template filename if one is located.
800 */
801 public function locate_template( $template_names, $load = false, $require_once = true ) {
802
803 // No file found yet.
804 $located = false;
805
806 // Try to find a template file.
807 foreach ( (array) $template_names as $template_name ) {
808
809 // Continue if template is empty.
810 if ( empty( $template_name ) ) {
811 continue;
812 }
813
814 // Trim off any slashes from the template name.
815 $template_name = ltrim( $template_name, '/' );
816
817 // Try locating this template file by looping through the template paths.
818 foreach ( $this->get_theme_template_paths() as $template_path ) {
819 $validated_path = Templates::validate_safe_path(
820 $template_path . $template_name,
821 [ 'theme', 'plugins' ]
822 );
823
824 if ( $validated_path ) {
825 $located = $validated_path;
826
827 break;
828 }
829 }
830 }
831
832 if ( ( true === $load ) && ! empty( $located ) ) {
833 load_template( $located, $require_once );
834 }
835
836 return $located;
837 }
838
839 /**
840 * Return a list of paths to check for template locations
841 *
842 * @since 1.1.3
843 *
844 * @return array
845 */
846 public function get_theme_template_paths() {
847
848 $template_dir = 'wpforms-email';
849
850 $file_paths = [
851 1 => trailingslashit( get_stylesheet_directory() ) . $template_dir,
852 10 => trailingslashit( get_template_directory() ) . $template_dir,
853 100 => WPFORMS_PLUGIN_DIR . 'includes/emails/templates',
854 ];
855
856 $file_paths = apply_filters( 'wpforms_email_template_paths', $file_paths );
857
858 // Sort the file paths based on priority.
859 ksort( $file_paths, SORT_NUMERIC );
860
861 return array_map( 'trailingslashit', $file_paths );
862 }
863
864 /**
865 * Perform email subject preparation: process tags, remove new lines, etc.
866 *
867 * @since 1.6.1
868 *
869 * @param string $subject Email subject to post-process.
870 *
871 * @return string
872 */
873 private function get_prepared_subject( $subject ) {
874
875 $subject = $this->process_tag( $subject );
876
877 $subject = trim( str_replace( [ "\r\n", "\r", "\n" ], ' ', $subject ) );
878
879 return wpforms_decode_string( $subject );
880 }
881 }
882