PluginProbe
weForms – Easy Drag & Drop Contact Form Builder For WordPress / 1.6.24
weForms – Easy Drag & Drop Contact Form Builder For WordPress v1.6.24
1.6.7 1.6.8 1.6.9 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.18 1.6.19 1.6.2 1.6.20 1.6.21 1.6.22 1.6.23 1.6.24 1.6.25 1.6.26 1.6.27 1.6.28 1.6.3 1.6.4 1.6.5 1.6.6 All 74 releases
weforms / includes / class-notification.php

class-notification.php in weForms – Easy Drag & Drop Contact Form Builder For WordPress 1.6.24, at includes/class-notification.php

747 lines 24.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Email Notification Class
5 */
6 class WeForms_Notification {
7
8 private $merge_tags = [];
9 private $args = [];
10
11 /**
12 * Init the class
13 *
14 * @param array $args
15 */
16 public function __construct( $args = [] ) {
17 $defaults = [
18 'form_id' => 0,
19 'entry_id' => 0,
20 'page_id' => 0,
21 ];
22
23 $this->args = wp_parse_args( $args, $defaults );
24 }
25
26 /**
27 * Send notifications
28 *
29 * @return void
30 */
31 public function send_notifications() {
32 $notifications = $this->get_active_notifications();
33
34 if ( !$notifications ) {
35 return;
36 }
37
38 $this->set_merge_tags();
39
40 foreach ( $notifications as $notification ) {
41 if ( $this->meet_conditions( $notification ) ) {
42 if ( $notification['type'] == 'email' ) {
43 $this->send_notification( $notification );
44 } elseif ( $notification['type'] == 'sms' ) {
45 $this->send_sms( $notification );
46 }
47 }
48 }
49 }
50
51 /**
52 * Resend entry notifications
53 *
54 * @return void
55 */
56 public function resend_entry_notifications( $notifications ) {
57 if ( !$notifications ) {
58 return;
59 }
60
61 $this->set_merge_tags();
62
63 foreach ( $notifications as $notification ) {
64 if ( $this->meet_conditions( $notification ) ) {
65 if ( $notification['type'] == 'email' ) {
66 $this->send_notification( $notification );
67 } elseif ( $notification['type'] == 'sms' ) {
68 $this->send_sms( $notification );
69 }
70 }
71 }
72 }
73
74 /**
75 * Send a single notification
76 *
77 * @param array $notification
78 *
79 * @return void
80 */
81 public function send_notification( $notification ) {
82 $headers = [];
83
84 $to = $this->replace_tags( $notification['to'] );
85
86 $subject = $this->replace_tags( $notification['subject'] );
87 $subject = static::replace_name_tag( $subject, $this->args['entry_id'] );
88
89 $message = $this->replace_tags( $notification['message'] );
90 $message = static::replace_name_tag( $message, $this->args['entry_id'] );
91 $message = $this->replace_all_fields( $message );
92 $message = wpautop( $message );
93
94 $fromName = $this->replace_tags( $notification['fromName'] );
95 $fromName = static::replace_name_tag( $fromName, $this->args['entry_id'] );
96 $fromAddress = $this->replace_tags( $notification['fromAddress'] );
97 $replyTo = $this->replace_tags( $notification['replyTo'] );
98 $cc = $this->replace_tags( $notification['cc'] );
99 $bcc = $this->replace_tags( $notification['bcc'] );
100
101 if ( $fromName || $fromAddress ) {
102 $headers['from'] = [
103 'email' => $fromAddress,
104 'name' => $fromName,
105 ];
106 }
107
108 if ( $cc ) {
109 $headers['cc'] = $cc;
110 }
111
112 if ( $bcc ) {
113 $headers['bcc'] = $bcc;
114 }
115
116 if ( $replyTo ) {
117 $headers['replyto'] = $replyTo;
118 }
119
120 // content type to text/html
121 $headers[] = 'Content-Type: text/html; charset=UTF-8';
122 $email_body = apply_filters( 'weforms_email_message', $this->get_formatted_body( $message ), $notification['message'], $headers );
123
124 /**
125 * Added the display style to the safe styles during wp_kses_post().
126 * WP kses post removes the display css property that we need when formatting the Checkbox and Multiple Choice Grids.
127 * This function will only run during the notification process.
128 *
129 * @since 1.6.17
130 */
131 add_filter( 'safe_style_css', function( $styles ) {
132 $styles[] = 'display';
133 return $styles;
134 } );
135
136 /**
137 * Added the input tag to the allowed html during wp_kses_post().
138 * WP kses post removes the input tag that we need when formatting the Checkbox and Multiple Choice Grids.
139 * The $message variable is formatted during the entry creation process. The values from the form are sanitized to avoid
140 * any issues with malicious inputs.
141 *
142 * This function is only used during the notification process.
143 *
144 * @since 1.6.17
145 */
146 add_filter( 'wp_kses_allowed_html', function( $html ) {
147 $html['input'] = array(
148 'class' => array(),
149 'name' => array(),
150 'type' => array(),
151 'value' => array(),
152 'checked' => array(),
153 'disabled' => array(),
154 );
155 return $html;
156 } );
157 weforms()->emailer->send( $to, $subject, wp_kses_post( htmlspecialchars_decode( $email_body ) ) , $headers );
158 }
159
160 /**
161 * Send a single sms notification
162 *
163 * @param array $notification
164 *
165 * @return void
166 */
167 public function send_sms( $notification ) {
168 if ( !class_exists( 'WeForms_SMS_Notification' ) ) {
169 return;
170 }
171
172 $to = $this->replace_tags( $notification['smsTo'] );
173 $message = $this->replace_tags( $notification['smsText'] );
174 $message = static::replace_name_tag( $message, $this->args['entry_id'] );
175 $message = $this->replace_all_fields( $message );
176
177 $email_body = apply_filters( 'weforms_sms_message', $this->get_formatted_sms_body( $message ) );
178
179 weforms_sms()->send_sms( [ $to ], $message );
180 }
181
182 /**
183 * Check conditional logics
184 *
185 * @param array $notification
186 *
187 * @return bool
188 */
189 public function meet_conditions( $notification ) {
190 $form = weforms()->form->get( $this->args['form_id'] );
191 $entry = $form->entries()->get( $this->args['entry_id'] );
192 $fields = $entry->get_fields();
193
194 $cond = !empty( $notification['weforms_cond'] ) ? $notification['weforms_cond'] : [];
195
196 if ( isset( $cond['condition_status'] ) && 'yes' === $cond['condition_status'] ) {
197 $cond_logic = !empty( $cond['cond_logic'] ) ? $cond['cond_logic'] : 'any';
198
199 if ( !empty( $cond['conditions'] ) && is_array( $cond['conditions'] ) ) {
200 $status = []; // going to store all condition result as boolean
201
202 foreach ( $cond['conditions'] as $k => $condition ) {
203 $field = $fields[$condition['name']];
204 $value = $field['value'];
205 $options = $field['options'];
206 $operator = $condition['operator'] == '=' ? true : false;
207
208 // probably from checkbox
209 if ( is_array( $value ) ) {
210
211 // search by value
212 if ( in_array( $condition['option'], $value ) ) {
213 $status[$k] = $operator ? true : false;
214 } else {
215
216 // search by key
217 foreach ( $value as $single_value ) {
218 if ( $condition['option'] == array_search( $single_value, $options ) ) {
219 $status[$k] = $operator ? true : false;
220
221 break;
222 }
223 }
224 }
225
226 if ( !isset( $status[$k] ) ) {
227 $status[$k] = $operator ? false : true;
228 }
229 } else {
230 if ( $condition['option'] == $value || $condition['option'] == array_search( $value, $options ) ) {
231 $status[$k] = $operator ? true : false;
232 } else {
233 $status[$k] = $operator ? false : true;
234 }
235 }
236 }
237
238 if ( $cond_logic == 'any' ) {
239 return in_array( true, $status ) ? true : false; // any true? then true
240 } elseif ( $cond_logic == 'all' ) {
241 return in_array( false, $status ) ? false : true; // any false? then false
242 }
243 }
244 }
245
246 return true;
247 }
248
249 /**
250 * Get active notifications of a form
251 *
252 * @param int $form_id
253 *
254 * @return array|bool
255 */
256 public function get_active_notifications() {
257 $notifications = weforms()->form->get( $this->args['form_id'] )->get_notifications();
258
259 if ( $notifications ) {
260 $notifications = array_filter( $notifications, function ( $notification ) {
261 return $notification['active'] == true;
262 } );
263
264 return $notifications;
265 }
266
267 return false;
268 }
269
270 /**
271 * Get formatted HTML email
272 *
273 * @param string $message
274 *
275 * @return string
276 */
277 public function get_formatted_body( $message ) {
278 $css = '';
279 $header = apply_filters( 'weforms_email_header', '' );
280 $footer = apply_filters( 'weforms_email_footer', '' );
281
282 if ( empty( $header ) ) {
283 ob_start();
284 include WEFORMS_INCLUDES . '/email/template/header.php';
285 $header = ob_get_clean();
286 }
287
288 if ( empty( $footer ) ) {
289 ob_start();
290 include WEFORMS_INCLUDES . '/email/template/footer.php';
291 $footer = ob_get_clean();
292 }
293
294 ob_start();
295 include WEFORMS_INCLUDES . '/email/template/styles.php';
296 $css = apply_filters( 'weforms_email_styles', ob_get_clean() );
297
298 $content = $header . $message . $footer;
299
300 if ( !class_exists( 'Emogrifier' ) ) {
301 require_once WEFORMS_INCLUDES . '/library/Emogrifier.php';
302 }
303
304 try {
305
306 // apply CSS styles inline for picky email clients
307 $emogrifier = new Emogrifier( $content, $css );
308 $content = $emogrifier->emogrify();
309 } catch ( Exception $e ) {
310 echo esc_html( $e->getMessage() );
311 }
312
313 return $content;
314 }
315
316 /**
317 * Get formatted HTML email
318 *
319 * @param string $message
320 *
321 * @return string
322 */
323 public function get_formatted_sms_body( $message ) {
324 $message = strip_tags( $message );
325
326 if ( strlen( $message ) > apply_filters( 'wefroms_sms_char_length', 153 ) ) {
327 $message = substr( $message, 0, apply_filters( 'wefroms_sms_char_length', 153 ) );
328 $message .= __( '..', 'weforms' );
329 }
330
331 return $message;
332 }
333
334 /**
335 * Populate an key/value pair of search/replace array
336 *
337 * @return array
338 */
339 public function set_merge_tags() {
340
341 // return early we had a previous array call
342 if ( $this->merge_tags ) {
343 return $this->merge_tags;
344 }
345
346 // populate the key/value array for the first time
347 $tags = weforms_get_merge_tags();
348 $replace_array = [];
349
350 foreach ( $tags as $section => $child ) {
351 if ( !$child['tags'] ) {
352 continue;
353 }
354
355 foreach ( $child['tags'] as $search_key => $label ) {
356 $replace_array[ '{' . $search_key . '}' ] = $this->get_merge_value( $search_key );
357 }
358 }
359
360 $this->merge_tags = $replace_array;
361 }
362
363 /**
364 * Get a merge tag value based on a tag
365 *
366 * @param string $tag
367 *
368 * @return string
369 */
370 public function get_merge_value( $tag ) {
371 switch ( $tag ) {
372 case 'entry_id':
373 return $this->args['entry_id'];
374 break;
375
376 case 'form_id':
377 return $this->args['form_id'];
378 break;
379
380 case 'form_name':
381 return get_post_field( 'post_title', $this->args['form_id'] );
382 break;
383
384 case 'admin_email':
385 return get_option( 'admin_email' );
386 break;
387
388 case 'date':
389 return date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
390 break;
391
392 case 'site_name':
393 return get_bloginfo( 'name' );
394 break;
395
396 case 'site_url':
397 return site_url( '/' );
398 break;
399
400 case 'page_title':
401 return get_post_field( 'post_title', $this->args['page_id'] );
402 break;
403
404 case 'ip_address':
405 return weforms_get_client_ip();
406 break;
407
408 case 'user_id':
409 return get_current_user_id();
410 break;
411
412 case 'first_name':
413 return $this->get_user_prop( 'first_name' );
414 break;
415
416 case 'last_name':
417 return $this->get_user_prop( 'last_name' );
418 break;
419
420 case 'display_name':
421 return $this->get_user_prop( 'display_name' );
422 break;
423
424 case 'user_email':
425 return $this->get_user_prop( 'user_email' );
426 break;
427
428 case 'url_page':
429 return get_permalink( $this->args['page_id'] );
430 break;
431
432 case 'url_referer':
433 return isset( $_SERVER['HTTP_REFERER'] ) ? sanitize_url( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
434 break;
435
436 case 'url_login':
437 return wp_login_url();
438 break;
439
440 case 'url_logout':
441 return wp_logout_url();
442 break;
443
444 case 'url_register':
445 return wp_registration_url();
446 break;
447
448 case 'url_lost_password':
449 return wp_lostpassword_url();
450 break;
451
452 case 'personal_data_erase_confirm_url':
453 $action_type = 'remove_personal_data';
454 $email_address = weforms_get_entry_meta( $this->args['entry_id'], 'user_email_address', true );
455 $request_id = wp_create_user_request( $email_address, $action_type );
456
457 if ( !empty( $email_address ) ) {
458 $confirm_url = add_query_arg(
459 [
460 'action' => 'confirmaction',
461 'request_id' => $request_id,
462 'confirm_key' => wp_generate_user_request_key( $request_id ),
463 ],
464 wp_login_url()
465 );
466
467 return make_clickable( $confirm_url );
468 }
469
470 break;
471
472 case 'personal_data_export_confirm_url':
473 $action_type = 'export_personal_data';
474 $email_address = weforms_get_entry_meta( $this->args['entry_id'], 'user_email_address', true );
475 $request_id = wp_create_user_request( $email_address, $action_type );
476
477 if ( !empty( $email_address ) ) {
478 $confirm_url = add_query_arg(
479 [
480 'action' => 'confirmaction',
481 'request_id' => $request_id,
482 'confirm_key' => wp_generate_user_request_key( $request_id ),
483 ],
484 wp_login_url()
485 );
486
487 return make_clickable( $confirm_url );
488 }
489
490 break;
491
492 default:
493 return apply_filters( 'weforms_merge_tag_value', '', $tag, $this->args );
494 break;
495 }
496 }
497
498 /**
499 * Parse out the custom fields with options or values. Since the options are what is stored, options may need to be
500 * used to find the value from the field settings.
501 *
502 * For example, let's say we have the following options:
503 * DEPARTMENT / EMAIL
504 * Support / support@example.com
505 * Sales / sales@example.com
506 *
507 * Users need the ability to pass {field:department} and get "Support",
508 * and {value:department} to get support@email.com
509 *
510 * @param string $text The text to parse.
511 * @param int $entry_id The entry ID. Optional. Default null if tags to be replaced are on the frontend.
512 *
513 * @return string $text The parsed text.
514 */
515 public static function replace_field_tags( $text, $entry_id = null ) {
516 // Validate data.
517 if ( empty( $text ) || !isset( $entry_id ) ) {
518 return;
519 }
520
521 // Users looking for {field:something} or {value:something}, determine which one.
522 $is_field = preg_match_all( '/{field:(\w*)}/', $text, $matches_field );
523 $is_value = preg_match_all( '/{value:(\w*)}/', $text, $matches_value );
524
525 if ( $is_field ) {
526 $meta_keys = $matches_field[1];
527 // Create an array of meta values to replace.
528 $meta_values = array();
529 foreach ( $meta_keys as $meta_key ) {
530 $meta_value = weforms_get_entry_meta( $entry_id, $meta_key, true );
531 // Add values to the array.
532 array_push( $meta_values, $meta_value );
533 if ( is_array( $meta_value ) ) {
534 $meta_value = implode( WeForms::$field_separator, $meta_value );
535 }
536 }
537 // $text may include HTML tags, only replace tag that was matched. Replace all matches.
538 $text = str_replace( $matches_field[0], $meta_values, $text );
539 }
540 if ( $is_value ) {
541 $meta_keys = $matches_value[1];
542 // Create an array of modified values to replace.
543 $modified_values = array();
544 foreach ( $meta_keys as $meta_key ) {
545 $form_field_values = WeForms_Form_Entry::get_form( $entry_id )->get_field_values()[ $meta_key ]['options'];
546 $meta_value = weforms_get_entry_meta( $entry_id, $meta_key, true );
547 $modified_value = array_search( $meta_value, $form_field_values );
548 // Add values to the array.
549 array_push( $modified_values, $modified_value );
550 if ( is_array( $modified_value ) ) {
551 $modified_value = implode( WeForms::$field_separator, $modified_value );
552 }
553 }
554 // $text may include HTML tags, only replace tag that was matched.
555 $text = str_replace( $matches_value[0], $modified_values, $text );
556 }
557 return $text;
558 }
559
560 /**
561 * Replace name tag with required value
562 *
563 * @param string $text
564 *
565 * @return string
566 */
567 public static function replace_name_tag( $text, $entry_id ) {
568 $pattern = '/{name-(full|first|middle|last):(\w*)}/';
569
570 preg_match_all( $pattern, $text, $matches );
571
572 // bail out if nothing found to be replaced
573 if ( !$matches[0] ) {
574 return $text;
575 }
576
577 list( $search, $fields, $meta_key ) = $matches;
578
579 $meta_value = weforms_get_entry_meta( $entry_id, $meta_key[0], true );
580 $replace = explode( WeForms::$field_separator, $meta_value );
581
582 foreach ( $search as $index => $search_key ) {
583 if ( 'first' == $fields[ $index ] ) {
584 $text = str_replace( $search_key, $replace[0], $text );
585 } elseif ( 'middle' == $fields[ $index ] ) {
586 $text = str_replace( $search_key, $replace[1], $text );
587 } elseif ( 'last' == $fields[ $index ] ) {
588 $text = str_replace( $search_key, $replace[2], $text );
589 } else {
590 $text = str_replace( $search_key, implode( ' ', $replace ), $text );
591 }
592 }
593
594 return $text;
595 }
596
597 /**
598 * Replace image/file tag with Image URL
599 *
600 * @param string $text
601 *
602 * @return string
603 */
604 public static function replace_file_tags( $text, $entry_id ) {
605 $pattern = '/{(?:image|file):(\w*)}/';
606
607 preg_match_all( $pattern, $text, $matches );
608
609 // bail out if nothing found to be replaced
610 if ( !$matches ) {
611 return $text;
612 }
613
614 foreach ( $matches[1] as $index => $meta_key ) {
615 $meta_value = weforms_get_entry_meta( $entry_id, $meta_key, true );
616
617 $files = [];
618
619 if ( is_array( $meta_value ) ) {
620 foreach ( $meta_value as $key => $attachment_id ) {
621 $file_url = wp_get_attachment_url( $attachment_id );
622
623 if ( $file_url ) {
624 $files[] = $file_url;
625 }
626 }
627 } else {
628 $file_url = wp_get_attachment_url( $attachment_id );
629
630 if ( $file_url ) {
631 $files[] = $file_url;
632 }
633 }
634
635 $files = implode( ' ', $files );
636
637 $text = str_replace( $matches[0][$index], $files, $text );
638 }
639
640 return $text;
641 }
642
643 /**
644 * Get property of a user object with failsafe check
645 *
646 * @param string $property
647 *
648 * @return string
649 */
650 public function get_user_prop( $property ) {
651 $user = wp_get_current_user();
652
653 if ( $user->ID != 0 ) {
654 return $user->{$property};
655 }
656
657 return '';
658 }
659
660 /**
661 * Replace text with merge tags
662 *
663 * @param string $text
664 *
665 * @return text
666 */
667 public function replace_tags( $text = '' ) {
668 $merge_keys = array_keys( $this->merge_tags );
669 $merge_values = array_values( $this->merge_tags );
670
671 $text = str_replace( $merge_keys, $merge_values, $text );
672 $text = static::replace_field_tags( $text, $this->args['entry_id'] );
673 $text = static::replace_file_tags( $text, $this->args['entry_id'] );
674
675 return $text;
676 }
677
678 /**
679 * Replace {all_fields} if found
680 *
681 * @param string $text
682 *
683 * @return string
684 */
685 public function replace_all_fields( $text = '' ) {
686
687 // check if {all_fields} exists
688 if ( false === strpos( $text, '{all_fields}' ) ) {
689 return $text;
690 }
691
692 $form = weforms()->form->get( $this->args['form_id'] );
693 $entry = $form->entries()->get( $this->args['entry_id'] );
694 $fields = $entry->get_fields();
695
696 if ( !$fields ) {
697 return $text;
698 }
699
700 $table = '<table width="600" cellpadding="0" cellspacing="0">';
701 $table .= '<tbody>';
702
703 foreach ( $fields as $key => $value ) {
704 $field_value = isset( $value[ 'value' ] ) ? $value[ 'value' ] : '';
705
706 if ( !$field_value ) {
707 continue; // let's skip empty fields
708 }
709
710 $table .= '<tr class="field-label">';
711 $table .= '<td><strong>' . $value['label'] . '</strong></td>';
712 $table .= '</tr>';
713 $table .= '<tr class="field-value">';
714 $table .= '<td>';
715
716 if ( in_array( $value['type'], array( 'multiple_select', 'checkbox_field' ) ) ) {
717 $field_value = is_array( $field_value ) ? $field_value : [];
718
719 if ( $field_value ) {
720 $table .= '<ul>';
721
722 foreach ( $field_value as $value_key ) {
723 $table .= '<li>' . $value_key . '</li>';
724 }
725 $table .= '</ul>';
726 } else {
727 $table .= '&mdash;';
728 }
729 } elseif ( in_array( $value['type'], array( 'google_map' ) ) ) {
730 $table .= $field_value['address'];
731 } else {
732 $table .= $field_value;
733 }
734
735 $table .= '</td>';
736 $table .= '</tr>';
737 }
738
739 $table .= '</tbody>';
740 $table .= '</table>';
741
742 $text = str_replace( '{all_fields}', $table, $text );
743
744 return $text;
745 }
746 }
747