File: /home/zeusxp5/zenoxpressalongside.net/wp-content/plugins/weforms/includes/class-notification.php
<?php
/**
* Email Notification Class
*/
class WeForms_Notification {
private $merge_tags = [];
private $args = [];
/**
* Init the class
*
* @param array $args
*/
public function __construct( $args = [] ) {
$defaults = [
'form_id' => 0,
'entry_id' => 0,
'page_id' => 0,
];
$this->args = wp_parse_args( $args, $defaults );
}
/**
* Send notifications
*
* @return void
*/
public function send_notifications() {
$notifications = $this->get_active_notifications();
if ( !$notifications ) {
return;
}
$this->set_merge_tags();
foreach ( $notifications as $notification ) {
if ( $this->meet_conditions( $notification ) ) {
if ( $notification['type'] == 'email' ) {
$this->send_notification( $notification );
} elseif ( $notification['type'] == 'sms' ) {
$this->send_sms( $notification );
}
}
}
}
/**
* Resend entry notifications
*
* @return void
*/
public function resend_entry_notifications( $notifications ) {
if ( !$notifications ) {
return;
}
$this->set_merge_tags();
foreach ( $notifications as $notification ) {
if ( $this->meet_conditions( $notification ) ) {
if ( $notification['type'] == 'email' ) {
$this->send_notification( $notification );
} elseif ( $notification['type'] == 'sms' ) {
$this->send_sms( $notification );
}
}
}
}
/**
* Send a single notification
*
* @param array $notification
*
* @return void
*/
public function send_notification( $notification ) {
$headers = [];
$to = $this->replace_tags( $notification['to'] );
$subject = $this->replace_tags( $notification['subject'] );
$subject = static::replace_name_tag( $subject, $this->args['entry_id'] );
$message = $this->replace_tags( $notification['message'] );
$message = static::replace_name_tag( $message, $this->args['entry_id'] );
$message = $this->replace_all_fields( $message );
$message = wpautop( $message );
$fromName = $this->replace_tags( $notification['fromName'] );
$fromName = static::replace_name_tag( $fromName, $this->args['entry_id'] );
$fromAddress = $this->replace_tags( $notification['fromAddress'] );
$replyTo = $this->replace_tags( $notification['replyTo'] );
$cc = $this->replace_tags( $notification['cc'] );
$bcc = $this->replace_tags( $notification['bcc'] );
if ( $fromName || $fromAddress ) {
$headers['from'] = [
'email' => $fromAddress,
'name' => $fromName,
];
}
if ( $cc ) {
$headers['cc'] = $cc;
}
if ( $bcc ) {
$headers['bcc'] = $bcc;
}
if ( $replyTo ) {
$headers['replyto'] = $replyTo;
}
// content type to text/html
$headers[] = 'Content-Type: text/html; charset=UTF-8';
$email_body = apply_filters( 'weforms_email_message', $this->get_formatted_body( $message ), $notification['message'], $headers );
/**
* Added the display style to the safe styles during wp_kses_post().
* WP kses post removes the display css property that we need when formatting the Checkbox and Multiple Choice Grids.
* This function will only run during the notification process.
*
* @since 1.6.17
*/
add_filter( 'safe_style_css', function( $styles ) {
$styles[] = 'display';
return $styles;
} );
/**
* Added the input tag to the allowed html during wp_kses_post().
* WP kses post removes the input tag that we need when formatting the Checkbox and Multiple Choice Grids.
* The $message variable is formatted during the entry creation process. The values from the form are sanitized to avoid
* any issues with malicious inputs.
*
* This function is only used during the notification process.
*
* @since 1.6.17
*/
add_filter( 'wp_kses_allowed_html', function( $html ) {
$html['input'] = array(
'class' => array(),
'name' => array(),
'type' => array(),
'value' => array(),
'checked' => array(),
'disabled' => array(),
);
return $html;
} );
weforms()->emailer->send( $to, $subject, wp_kses_post( htmlspecialchars_decode( $email_body ) ) , $headers );
}
/**
* Send a single sms notification
*
* @param array $notification
*
* @return void
*/
public function send_sms( $notification ) {
if ( !class_exists( 'WeForms_SMS_Notification' ) ) {
return;
}
$to = $this->replace_tags( $notification['smsTo'] );
$message = $this->replace_tags( $notification['smsText'] );
$message = static::replace_name_tag( $message, $this->args['entry_id'] );
$message = $this->replace_all_fields( $message );
$email_body = apply_filters( 'weforms_sms_message', $this->get_formatted_sms_body( $message ) );
weforms_sms()->send_sms( [ $to ], $message );
}
/**
* Check conditional logics
*
* @param array $notification
*
* @return bool
*/
public function meet_conditions( $notification ) {
$form = weforms()->form->get( $this->args['form_id'] );
$entry = $form->entries()->get( $this->args['entry_id'] );
$fields = $entry->get_fields();
$cond = !empty( $notification['weforms_cond'] ) ? $notification['weforms_cond'] : [];
if ( isset( $cond['condition_status'] ) && 'yes' === $cond['condition_status'] ) {
$cond_logic = !empty( $cond['cond_logic'] ) ? $cond['cond_logic'] : 'any';
if ( !empty( $cond['conditions'] ) && is_array( $cond['conditions'] ) ) {
$status = []; // going to store all condition result as boolean
foreach ( $cond['conditions'] as $k => $condition ) {
$field = $fields[$condition['name']];
$value = $field['value'];
$options = $field['options'];
$operator = $condition['operator'] == '=' ? true : false;
// probably from checkbox
if ( is_array( $value ) ) {
// search by value
if ( in_array( $condition['option'], $value ) ) {
$status[$k] = $operator ? true : false;
} else {
// search by key
foreach ( $value as $single_value ) {
if ( $condition['option'] == array_search( $single_value, $options ) ) {
$status[$k] = $operator ? true : false;
break;
}
}
}
if ( !isset( $status[$k] ) ) {
$status[$k] = $operator ? false : true;
}
} else {
if ( $condition['option'] == $value || $condition['option'] == array_search( $value, $options ) ) {
$status[$k] = $operator ? true : false;
} else {
$status[$k] = $operator ? false : true;
}
}
}
if ( $cond_logic == 'any' ) {
return in_array( true, $status ) ? true : false; // any true? then true
} elseif ( $cond_logic == 'all' ) {
return in_array( false, $status ) ? false : true; // any false? then false
}
}
}
return true;
}
/**
* Get active notifications of a form
*
* @param int $form_id
*
* @return array|bool
*/
public function get_active_notifications() {
$notifications = weforms()->form->get( $this->args['form_id'] )->get_notifications();
if ( $notifications ) {
$notifications = array_filter( $notifications, function ( $notification ) {
return $notification['active'] == true;
} );
return $notifications;
}
return false;
}
/**
* Get formatted HTML email
*
* @param string $message
*
* @return string
*/
public function get_formatted_body( $message ) {
$css = '';
$header = apply_filters( 'weforms_email_header', '' );
$footer = apply_filters( 'weforms_email_footer', '' );
if ( empty( $header ) ) {
ob_start();
include WEFORMS_INCLUDES . '/email/template/header.php';
$header = ob_get_clean();
}
if ( empty( $footer ) ) {
ob_start();
include WEFORMS_INCLUDES . '/email/template/footer.php';
$footer = ob_get_clean();
}
ob_start();
include WEFORMS_INCLUDES . '/email/template/styles.php';
$css = apply_filters( 'weforms_email_styles', ob_get_clean() );
$content = $header . $message . $footer;
if ( !class_exists( 'Emogrifier' ) ) {
require_once WEFORMS_INCLUDES . '/library/Emogrifier.php';
}
try {
// apply CSS styles inline for picky email clients
$emogrifier = new Emogrifier( $content, $css );
$content = $emogrifier->emogrify();
} catch ( Exception $e ) {
echo esc_html( $e->getMessage() );
}
return $content;
}
/**
* Get formatted HTML email
*
* @param string $message
*
* @return string
*/
public function get_formatted_sms_body( $message ) {
$message = strip_tags( $message );
if ( strlen( $message ) > apply_filters( 'wefroms_sms_char_length', 153 ) ) {
$message = substr( $message, 0, apply_filters( 'wefroms_sms_char_length', 153 ) );
$message .= __( '..', 'weforms' );
}
return $message;
}
/**
* Populate an key/value pair of search/replace array
*
* @return array
*/
public function set_merge_tags() {
// return early we had a previous array call
if ( $this->merge_tags ) {
return $this->merge_tags;
}
// populate the key/value array for the first time
$tags = weforms_get_merge_tags();
$replace_array = [];
foreach ( $tags as $section => $child ) {
if ( !$child['tags'] ) {
continue;
}
foreach ( $child['tags'] as $search_key => $label ) {
$replace_array[ '{' . $search_key . '}' ] = $this->get_merge_value( $search_key );
}
}
$this->merge_tags = $replace_array;
}
/**
* Get a merge tag value based on a tag
*
* @param string $tag
*
* @return string
*/
public function get_merge_value( $tag ) {
switch ( $tag ) {
case 'entry_id':
return $this->args['entry_id'];
break;
case 'form_id':
return $this->args['form_id'];
break;
case 'form_name':
return get_post_field( 'post_title', $this->args['form_id'] );
break;
case 'admin_email':
return get_option( 'admin_email' );
break;
case 'date':
return date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
break;
case 'site_name':
return get_bloginfo( 'name' );
break;
case 'site_url':
return site_url( '/' );
break;
case 'page_title':
return get_post_field( 'post_title', $this->args['page_id'] );
break;
case 'ip_address':
return weforms_get_client_ip();
break;
case 'user_id':
return get_current_user_id();
break;
case 'first_name':
return $this->get_user_prop( 'first_name' );
break;
case 'last_name':
return $this->get_user_prop( 'last_name' );
break;
case 'display_name':
return $this->get_user_prop( 'display_name' );
break;
case 'user_email':
return $this->get_user_prop( 'user_email' );
break;
case 'url_page':
return get_permalink( $this->args['page_id'] );
break;
case 'url_referer':
return isset( $_SERVER['HTTP_REFERER'] ) ? sanitize_url( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
break;
case 'url_login':
return wp_login_url();
break;
case 'url_logout':
return wp_logout_url();
break;
case 'url_register':
return wp_registration_url();
break;
case 'url_lost_password':
return wp_lostpassword_url();
break;
case 'personal_data_erase_confirm_url':
$action_type = 'remove_personal_data';
$email_address = weforms_get_entry_meta( $this->args['entry_id'], 'user_email_address', true );
$request_id = wp_create_user_request( $email_address, $action_type );
if ( !empty( $email_address ) ) {
$confirm_url = add_query_arg(
[
'action' => 'confirmaction',
'request_id' => $request_id,
'confirm_key' => wp_generate_user_request_key( $request_id ),
],
wp_login_url()
);
return make_clickable( $confirm_url );
}
break;
case 'personal_data_export_confirm_url':
$action_type = 'export_personal_data';
$email_address = weforms_get_entry_meta( $this->args['entry_id'], 'user_email_address', true );
$request_id = wp_create_user_request( $email_address, $action_type );
if ( !empty( $email_address ) ) {
$confirm_url = add_query_arg(
[
'action' => 'confirmaction',
'request_id' => $request_id,
'confirm_key' => wp_generate_user_request_key( $request_id ),
],
wp_login_url()
);
return make_clickable( $confirm_url );
}
break;
default:
return apply_filters( 'weforms_merge_tag_value', '', $tag, $this->args );
break;
}
}
/**
* Parse out the custom fields with options or values. Since the options are what is stored, options may need to be
* used to find the value from the field settings.
*
* For example, let's say we have the following options:
* DEPARTMENT / EMAIL
* Support / support@example.com
* Sales / sales@example.com
*
* Users need the ability to pass {field:department} and get "Support",
* and {value:department} to get support@email.com
*
* @param string $text The text to parse.
* @param int $entry_id The entry ID. Optional. Default null if tags to be replaced are on the frontend.
*
* @return string $text The parsed text.
*/
public static function replace_field_tags( $text, $entry_id = null ) {
// Validate data.
if ( empty( $text ) || !isset( $entry_id ) ) {
return;
}
// Users looking for {field:something} or {value:something}, determine which one.
$is_field = preg_match_all( '/{field:(\w*)}/', $text, $matches_field );
$is_value = preg_match_all( '/{value:(\w*)}/', $text, $matches_value );
if ( $is_field ) {
$meta_keys = $matches_field[1];
// Create an array of meta values to replace.
$meta_values = array();
foreach ( $meta_keys as $meta_key ) {
$meta_value = weforms_get_entry_meta( $entry_id, $meta_key, true );
// Add values to the array.
array_push( $meta_values, $meta_value );
if ( is_array( $meta_value ) ) {
$meta_value = implode( WeForms::$field_separator, $meta_value );
}
}
// $text may include HTML tags, only replace tag that was matched. Replace all matches.
$text = str_replace( $matches_field[0], $meta_values, $text );
}
if ( $is_value ) {
$meta_keys = $matches_value[1];
// Create an array of modified values to replace.
$modified_values = array();
foreach ( $meta_keys as $meta_key ) {
$form_field_values = WeForms_Form_Entry::get_form( $entry_id )->get_field_values()[ $meta_key ]['options'];
$meta_value = weforms_get_entry_meta( $entry_id, $meta_key, true );
$modified_value = array_search( $meta_value, $form_field_values );
// Add values to the array.
array_push( $modified_values, $modified_value );
if ( is_array( $modified_value ) ) {
$modified_value = implode( WeForms::$field_separator, $modified_value );
}
}
// $text may include HTML tags, only replace tag that was matched.
$text = str_replace( $matches_value[0], $modified_values, $text );
}
return $text;
}
/**
* Replace name tag with required value
*
* @param string $text
*
* @return string
*/
public static function replace_name_tag( $text, $entry_id ) {
$pattern = '/{name-(full|first|middle|last):(\w*)}/';
preg_match_all( $pattern, $text, $matches );
// bail out if nothing found to be replaced
if ( !$matches[0] ) {
return $text;
}
list( $search, $fields, $meta_key ) = $matches;
$meta_value = weforms_get_entry_meta( $entry_id, $meta_key[0], true );
$replace = explode( WeForms::$field_separator, $meta_value );
foreach ( $search as $index => $search_key ) {
if ( 'first' == $fields[ $index ] ) {
$text = str_replace( $search_key, $replace[0], $text );
} elseif ( 'middle' == $fields[ $index ] ) {
$text = str_replace( $search_key, $replace[1], $text );
} elseif ( 'last' == $fields[ $index ] ) {
$text = str_replace( $search_key, $replace[2], $text );
} else {
$text = str_replace( $search_key, implode( ' ', $replace ), $text );
}
}
return $text;
}
/**
* Replace image/file tag with Image URL
*
* @param string $text
*
* @return string
*/
public static function replace_file_tags( $text, $entry_id ) {
$pattern = '/{(?:image|file):(\w*)}/';
preg_match_all( $pattern, $text, $matches );
// bail out if nothing found to be replaced
if ( !$matches ) {
return $text;
}
foreach ( $matches[1] as $index => $meta_key ) {
$meta_value = weforms_get_entry_meta( $entry_id, $meta_key, true );
$files = [];
if ( is_array( $meta_value ) ) {
foreach ( $meta_value as $key => $attachment_id ) {
$file_url = wp_get_attachment_url( $attachment_id );
if ( $file_url ) {
$files[] = $file_url;
}
}
} else {
$file_url = wp_get_attachment_url( $attachment_id );
if ( $file_url ) {
$files[] = $file_url;
}
}
$files = implode( ' ', $files );
$text = str_replace( $matches[0][$index], $files, $text );
}
return $text;
}
/**
* Get property of a user object with failsafe check
*
* @param string $property
*
* @return string
*/
public function get_user_prop( $property ) {
$user = wp_get_current_user();
if ( $user->ID != 0 ) {
return $user->{$property};
}
return '';
}
/**
* Replace text with merge tags
*
* @param string $text
*
* @return text
*/
public function replace_tags( $text = '' ) {
$merge_keys = array_keys( $this->merge_tags );
$merge_values = array_values( $this->merge_tags );
$text = str_replace( $merge_keys, $merge_values, $text );
$text = static::replace_field_tags( $text, $this->args['entry_id'] );
$text = static::replace_file_tags( $text, $this->args['entry_id'] );
return $text;
}
/**
* Replace {all_fields} if found
*
* @param string $text
*
* @return string
*/
public function replace_all_fields( $text = '' ) {
// check if {all_fields} exists
if ( false === strpos( $text, '{all_fields}' ) ) {
return $text;
}
$form = weforms()->form->get( $this->args['form_id'] );
$entry = $form->entries()->get( $this->args['entry_id'] );
$fields = $entry->get_fields();
if ( !$fields ) {
return $text;
}
$table = '<table width="600" cellpadding="0" cellspacing="0">';
$table .= '<tbody>';
foreach ( $fields as $key => $value ) {
$field_value = isset( $value[ 'value' ] ) ? $value[ 'value' ] : '';
if ( !$field_value ) {
continue; // let's skip empty fields
}
$table .= '<tr class="field-label">';
$table .= '<td><strong>' . $value['label'] . '</strong></td>';
$table .= '</tr>';
$table .= '<tr class="field-value">';
$table .= '<td>';
if ( in_array( $value['type'], array( 'multiple_select', 'checkbox_field' ) ) ) {
$field_value = is_array( $field_value ) ? $field_value : [];
if ( $field_value ) {
$table .= '<ul>';
foreach ( $field_value as $value_key ) {
$table .= '<li>' . $value_key . '</li>';
}
$table .= '</ul>';
} else {
$table .= '—';
}
} elseif ( in_array( $value['type'], array( 'google_map' ) ) ) {
$table .= $field_value['address'];
} else {
$table .= $field_value;
}
$table .= '</td>';
$table .= '</tr>';
}
$table .= '</tbody>';
$table .= '</table>';
$text = str_replace( '{all_fields}', $table, $text );
return $text;
}
}