HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //var/www/html/bwcdev/wp-content/plugins/quiz-master-next/php/classes/class-qsm-emails.php
<?php
/**
 * Handles relevant functions for emails
 *
 * @package QSM
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * This class contains functions for loading, saving, and send quiz emails.
 *
 * @since 6.2.0
 */
class QSM_Emails {

	/**
	 * Sends the emails for the quiz.
	 *
	 * @since 6.2.0
	 * @param int $results_id result ID.
	 * @param array $quiz_settings Quiz Settings.
	 */
	public static function send_emails( $transient_id ) {
		global $mlwQuizMasterNext;

		$response_data = maybe_unserialize( get_transient( $transient_id ) );
		$emails = self::load_emails( $response_data['quiz_id'] );

		if ( ! is_array( $emails ) || empty( $emails ) ) {
			return;
		}

		add_filter( 'wp_mail_content_type', 'mlw_qmn_set_html_content_type' );
		$email_send = 0;
		$default_email_content = '';
		// Cycles through each possible email.
		foreach ( $emails as $index => $email ) {

			$email_subject = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $email['subject'], "quiz-email-subject-{$index}-{$response_data['quiz_id']}" );

			// kses converts ampersands to &amp; core.trac.wordpress.org/ticket/11311.
			$email_subject = str_replace( '&amp;', '&', $email_subject );

			$email_content = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $email['content'], "quiz-email-content-{$index}-{$response_data['quiz_id']}" );
			// Checks if any conditions are present. Else, send it always.
			if ( ! empty( $email['conditions'] ) ) {
				/**
				 * Since we have many conditions to test, we set this to true first.
				 * Then, we test each condition to see if it fails.
				 * If one condition fails, the value will be set to false.
				 * If all conditions pass, this will still be true and the email will
				 * be sent.
				 */
				$show = true;
				if ( isset( $email['default_mark'] ) && $index + 1 == $email['default_mark'] ) {
					$default_email_content = $email_content;
					$default_email_subject = $email_subject;
					$default_email_to = $email['to'];
					$default_email_reply_to = $email['replyTo'];
					$default_index = $index;
				}
				// Cycle through each condition to see if we should sent this email.
				foreach ( $email['conditions'] as $condition ) {
					$value    = $condition['value'];
					$main_condition = '';
					if ( isset($condition['category']) ) {
						$main_condition = $condition['category'];
					}
					if ( ! empty($condition['extra_condition']) && 'category' == $main_condition ) {
						$category = $condition['extra_condition'];
						if ( false !== strpos( $category, 'qsm-cat-') ) {
							$cat_id = intval( str_replace( 'qsm-cat-', '', $category ) );
							$term = get_term( $cat_id );
							if ( $term ) {
								$category = $term->name;
							}
						}
					}else {
						$category = $main_condition;
					}
					// First, determine which value we need to test.
					switch ( $condition['criteria'] ) {
						case 'score':
							if ( '' == $main_condition || 'quiz' == $main_condition ) {
								$test = $response_data['total_score'];
							} else {
								$test = apply_filters( 'mlw_qmn_template_variable_results_page', "%CATEGORY_SCORE_$category%", $response_data );
							}

							break;

						case 'points':
							if ( '' == $main_condition || 'quiz' == $main_condition ) {
								$test = $response_data['total_points'];
							} else {
								$test = apply_filters( 'mlw_qmn_template_variable_results_page', "%CATEGORY_POINTS_$category%", $response_data );
							}
							break;

						default:
							$test = 0;
							break;
					}

					// Then, determine how to test the vaue.
					switch ( $condition['operator'] ) {
						case 'greater-equal':
							if ( $test < $value ) {
								$show = false;
							}
							break;

						case 'greater':
							if ( $test <= $value ) {
								$show = false;
							}
							break;

						case 'less-equal':
							if ( $test > $value ) {
								$show = false;
							}
							break;

						case 'less':
							if ( $test >= $value ) {
								$show = false;
							}
							break;

						case 'not-equal':
							if ( $test == $value ) {
								$show = false;
							}
							break;

						case 'equal':
						default:
							if ( $test != $value ) {
								$show = false;
							}
							break;
					}

					/**
					 * Added custom criterias/operators to the email?
					 * Use this filter to check if the condition passed.
					 * If it fails your conditions, return false to prevent the
					 * email from sending.
					 * If it passes your condition or is not your custom criterias
					 * or operators, then return the value as-is.
					 * DO NOT RETURN TRUE IF IT PASSES THE CONDITION!!!
					 * The value may have been set to false when failing a previous condition.
					 */
					$show = apply_filters( 'qsm_email_condition_check', $show, $condition, $response_data );
					if ( ! $show ) {
						break;
					}
				}
				if ( $show ) {
					do_action( 'qsm_send_result_email_before', $response_data, $email['to'], $email_subject, $email_content, $email['replyTo'], $index );
					self::send_results_email( $response_data, $email['to'], $email_subject, $email_content, $email['replyTo'], $index );
					$email_send++;
				}
			} else {
				self::send_results_email( $response_data, $email['to'], $email_subject, $email_content, $email['replyTo'], $index );
				$email_send++;
			}
		}
		if ( 0 == $email_send && ! empty( $default_email_content ) ) {
			self::send_results_email( $response_data, $default_email_to, $default_email_subject, $default_email_content, $default_email_reply_to, $default_index );
		}

		remove_filter( 'wp_mail_content_type', 'mlw_qmn_set_html_content_type' );
	}

	/**
	 * Sends the results email.
	 *
	 * @since 6.2.0
	 * @param array  $response_data The data for the user's submission.
	 * @param string $to The email(s) to send to. Can be separated with commas.
	 * @param string $subject The subject of the email.
	 * @param string $content The body of the email.
	 * @param bool   $reply_to True if set user email as Reply To header.
	 */
	public static function send_results_email( $response_data, $to, $subject, $content, $reply_to, $index = 0 ) {

		do_action( 'qsm_start_sending_email', $response_data, $to, $subject );
		global $mlwQuizMasterNext;
		global $qmn_total_questions;
		$qmn_total_questions = 0;
		// Sets up our to email addresses.
		$user_email = sanitize_email( $response_data['user_email'] );
		$count      = 0;
		if ( is_email( $user_email ) ) {
			$to = str_replace( '%USER_EMAIL%', $response_data['user_email'], $to, $count );
		} else {
			$to = str_replace( '%USER_EMAIL%', '', $to );
		}
		$to       = apply_filters( 'qsm_send_results_email_addresses', $to, $response_data );
		$to_array = explode( ',', $to );
		$to_array = array_unique( $to_array );
		if ( empty( $to_array ) ) {
			return;
		}
		// Prepares our subject.
		$subject = apply_filters( 'mlw_qmn_template_variable_results_page', $subject, $response_data );
		// Prepares our content.
		$content                               = htmlspecialchars_decode( $content, ENT_QUOTES );
		$response_data['email_template_array'] = true;
		$content                               = apply_filters( 'mlw_qmn_template_variable_results_page', $content, $response_data );
		$content                               = apply_filters( 'qmn_email_template_variable_results', $content, $response_data );
		// convert css classes to inline.
		$content                               = apply_filters( 'qsm_results_css_inliner', $content, $response_data, $index );
		$content                               = $mlwQuizMasterNext->pluginHelper->qsm_results_css_inliner( $content );
		$content                               = html_entity_decode( $content );

		// Prepares our from name and email.
		$settings   = (array) get_option( 'qmn-settings' );
		$from_email = get_option( 'admin_email', 'a@example.com' );
		$from_name  = get_bloginfo( 'name' );
		if ( ! isset( $settings['from_email'] ) && ! isset( $settings['from_name'] ) ) {
			$options    = $mlwQuizMasterNext->quiz_settings->get_quiz_options();
			$from_array = maybe_unserialize( $options->email_from_text );
			if ( isset( $from_array['from_email'] ) ) {
				$from_email = $from_array['from_email'];
				$from_name  = $from_array['from_name'];

				// Updates option with this quiz's from values.
				$settings['from_email'] = $from_email;
				$settings['from_name']  = $from_name;
				update_option( 'qmn-settings', $settings );
			}
		} else {
			if ( isset( $settings['from_email'] ) ) {
				$from_email = $settings['from_email'];
			}
			if ( isset( $settings['from_name'] ) ) {
				$from_name = $settings['from_name'];
			}
		}

		// Prepares our headers.
		$headers = array();
		if ( is_email( $from_email ) ) {
			$headers[] = 'From: ' . $from_name . ' <' . $from_email . '>';
		}
		if ( is_email( $user_email ) && true === $reply_to ) {
			$name      = sanitize_text_field( $response_data['user_name'] );
			$headers[] = 'Reply-To: ' . html_entity_decode( $name ). ' <' . $user_email . '>';
		}
		/**
		 * Filter to modify email headers.
		 */
		$headers = apply_filters( 'qsm_send_results_email_headers', $headers, $response_data );

		// Prepares our attachments. If %USER_EMAIL% was in the $to, then use the user email attachment filter.
		$attachments = array();
		if ( 0 < intval( $count ) ) {
			$attachments = apply_filters( 'qsm_user_email_attachments', $attachments, $response_data );
		} else {
			$attachments = apply_filters( 'qsm_admin_email_attachments', $attachments, $response_data );
		}

		// Cycle through each to email address and send the email.
		foreach ( $to_array as $to_email ) {
			if ( is_email( $to_email ) ) {
				$mailResult = wp_mail( $to_email, $subject, $content, $headers, $attachments );
				if ( $mailResult ) {
					do_action( 'qsm_after_sending_email', $response_data, $to_email, $subject );
				}else {
					$mlwQuizMasterNext->log_manager->add( 'There has been an error in wp_mail. Please check SMTP details mail not sending. Error Code: 0001', 0, 'error' );
				}
			}
		}
	}

	/**
	 * Loads the emails for a single quiz.
	 *
	 * @since 6.2.0
	 * @param int $quiz_id The ID for the quiz.
	 * @return bool|array The array of emails or false.
	 */
	public static function load_emails( $quiz_id ) {
		$emails  = array();
		$quiz_id = intval( $quiz_id );

		// If the parameter supplied turns to 0 after intval, returns false.
		if ( 0 === $quiz_id ) {
			return false;
		}

		global $wpdb;
		$data = $wpdb->get_var( $wpdb->prepare( "SELECT user_email_template FROM {$wpdb->prefix}mlw_quizzes WHERE quiz_id = %d", $quiz_id ) );

		$data = maybe_unserialize( $data );
		// Checks if the emails is an array.
		if ( is_array( $data ) ) {
			// Checks if the emails array is not the newer version.
			if ( ! empty( $data ) && ! isset( $data[0]['conditions'] ) ) {
				$emails = self::convert_to_new_system( $quiz_id );
			} else {
				$emails = $data;
			}
		} else {
			$emails = self::convert_to_new_system( $quiz_id );
		}

		return $emails;
	}

	/**
	 * Loads and converts emails from the old system to new system
	 *
	 * @since 6.2.0
	 * @param int $quiz_id The ID for the quiz.
	 * @return array The combined newer versions of the emails.
	 */
	public static function convert_to_new_system( $quiz_id ) {
		$emails  = array();
		$quiz_id = intval( $quiz_id );

		// If the parameter supplied turns to 0 after intval, returns empty array.
		if ( 0 === $quiz_id ) {
			return $emails;
		}

		/**
		 * Loads the old user and admin emails. Checks if they are enabled and converts them.
		 */
		global $wpdb;
		global $mlwQuizMasterNext;
		$data   = $wpdb->get_row( $wpdb->prepare( "SELECT send_user_email, user_email_template, send_admin_email, admin_email_template, email_from_text, admin_email FROM {$wpdb->prefix}mlw_quizzes WHERE quiz_id = %d", $quiz_id ), ARRAY_A );
		$system = $mlwQuizMasterNext->pluginHelper->get_section_setting( 'quiz_options', 'system', 0 );
		if ( 0 === intval( $data['send_user_email'] ) ) {
			$emails = array_merge( $emails, self::convert_emails( $system, $data['user_email_template'] ) );
		}
		if ( 0 === intval( $data['send_admin_email'] ) ) {
			$from_email_array = maybe_unserialize( $data['email_from_text'] );
			if ( ! is_array( $from_email_array ) || ! isset( $from_email_array['reply_to'] ) ) {
				$from_email_array = array(
					'reply_to' => 1,
				);
			}
			$emails = array_merge( $emails, self::convert_emails( $system, $data['admin_email_template'], $data['admin_email'], $from_email_array['reply_to'] ) );
		}

		// Updates the database with new array to prevent running this step next time.
		$wpdb->update(
			$wpdb->prefix . 'mlw_quizzes',
			array( 'user_email_template' => maybe_serialize( $emails ) ),
			array( 'quiz_id' => $quiz_id ),
			array( '%s' ),
			array( '%d' )
		);

		return $emails;
	}

	/**
	 * Converts emails to new system.
	 *
	 * @since 6.2.0
	 * @param int    $system The grading system of the quiz.
	 * @param array  $emails The emails to convert.
	 * @param string $admin_emails The emails to send admin emails to, separated by comma.
	 * @param int    $reply_to Whether to add user email as Reply-To header (0 is enabled).
	 * @return array The emails that have been converted.
	 */
	public static function convert_emails( $system, $emails, $admin_emails = false, $reply_to = false ) {
		$new_emails = array();
		$emails     = maybe_unserialize( $emails );

		// Checks if emails is an array to cycle through.
		if ( is_array( $emails ) ) {

			// Cycles through the emails.
			foreach ( $emails as $email ) {

				// Because I didn't appreciate consistency as a young developer...
				if ( isset( $email['subject'] ) ) {
					$subject = $email['subject'];
					$message = $email['message'];
					$begin   = $email['begin_score'];
					$end     = $email['end_score'];
				} else {
					$subject = $email[3];
					$message = $email[2];
					$begin   = $email[0];
					$end     = $email[1];
				}

				// Sets up our basic email.
				$new_email = array(
					'conditions' => array(),
					'subject'    => $subject,
					'content'    => $message,
					'replyTo'    => false,
				);

				// Prepares the to email.
				if ( false === $admin_emails ) {
					$new_email['to'] = '%USER_EMAIL%';
				} elseif ( is_string( $admin_emails ) ) {
					$new_email['to'] = $admin_emails;
				} else {
					$new_email['to'] = get_option( 'admin_email ', 'test@example.com' );
				}

				// Sets reply to option to True if was enabled previously.
				if ( false !== $reply_to ) {
					if ( 0 === intval( $reply_to ) ) {
						$new_email['replyTo'] = true;
					}
				}

				// Checks to see if the email is not the older version's default page.
				if ( 0 !== intval( $begin ) || 0 !== intval( $end ) ) {

					// Checks if the system is points.
					if ( 1 === intval( $system ) ) {
						$new_email['conditions'][] = array(
							'criteria' => 'points',
							'operator' => 'greater-equal',
							'value'    => $begin,
						);
						$new_email['conditions'][] = array(
							'criteria' => 'points',
							'operator' => 'less-equal',
							'value'    => $end,
						);
					} else {
						$new_email['conditions'][] = array(
							'criteria' => 'score',
							'operator' => 'greater-equal',
							'value'    => $begin,
						);
						$new_email['conditions'][] = array(
							'criteria' => 'score',
							'operator' => 'less-equal',
							'value'    => $end,
						);
					}
				}

				$new_emails[] = $new_email;
			}
		} else {
			$new_emails[] = array(
				'conditions' => array(),
				'content'    => $emails,
				'subject'    => 'Quiz results for %QUIZ_NAME%',
				'replyTo'    => false,
			);

			// Prepares the to email.
			if ( false === $admin_emails ) {
				$new_emails[0]['to'] = '%USER_EMAIL%';
			} elseif ( is_string( $admin_emails ) ) {
				$new_emails[0]['to'] = $admin_emails;
			} else {
				$new_emails[0]['to'] = get_option( 'admin_email ', 'test@example.com' );
			}
		}
		return $new_emails;
	}

	/**
	 * Saves the emails for a quiz.
	 *
	 * @since 6.2.0
	 * @param int   $quiz_id The ID for the quiz.
	 * @param array $emails The emails to be saved.
	 * @return bool True or false depending on success.
	 */
	public static function save_emails( $quiz_id, $emails ) {
		global $wpdb, $mlwQuizMasterNext;
		if ( ! is_array( $emails ) ) {
			return false;
		}

		$quiz_id = intval( $quiz_id );
		if ( 0 === $quiz_id ) {
			return false;
		}

		// Sanitizes data in emails.
		$total = count( $emails );
		for ( $i = 0; $i < $total; $i++ ) {
			$emails[ $i ]['to']           = sanitize_text_field( $emails[ $i ]['to'] );
			$emails[ $i ]['subject']      = sanitize_text_field( $emails[ $i ]['subject'] );
			$emails[ $i ]['default_mark'] = sanitize_text_field( $emails[ $i ]['default_mark'] );

			/**
			 * The jQuery AJAX function won't send the conditions key
			 * if it's empty. So, check if it's set. If set, sanitize
			 * data. If not set, set to empty array.
			 */
			if ( isset( $emails[ $i ]['conditions'] ) ) {
				// Sanitizes the conditions.
				$total_conditions = count( $emails[ $i ]['conditions'] );
				for ( $j = 0; $j < $total_conditions; $j++ ) {
					$emails[ $i ]['conditions'][ $j ]['value'] = sanitize_text_field( $emails[ $i ]['conditions'][ $j ]['value'] );
				}
			} else {
				$emails[ $i ]['conditions'] = array();
			}

			if ( 'true' === $emails[ $i ]['replyTo'] || true === $emails[ $i ]['replyTo'] ) {
				$emails[ $i ]['replyTo'] = true;
			} else {
				$emails[ $i ]['replyTo'] = false;
			}
			if ( isset( $emails[ $i ]['content'] ) ) {
				$emails[ $i ]['content'] = preg_replace_callback(
					'/<qsmvariabletag>([^<]+)<\/qsmvariabletag>/u',
						function( $matches ) {
							return '%' . wp_strip_all_tags( preg_replace('/^\s+|\s+$/u', '', $matches[1] ) ) . '%';
						},
						$emails[ $i ]['content']
				);
				$emails[ $i ]['content'] = wp_kses_post( $emails[ $i ]['content'] );
			}
			$mlwQuizMasterNext->pluginHelper->qsm_register_language_support( $emails[ $i ]['subject'], "quiz-email-subject-{$i}-{$quiz_id}" );
			$mlwQuizMasterNext->pluginHelper->qsm_register_language_support( $emails[ $i ]['content'], "quiz-email-content-{$i}-{$quiz_id}" );
		}

		$results = $wpdb->update(
			$wpdb->prefix . 'mlw_quizzes',
			array( 'user_email_template' => maybe_serialize( $emails ) ),
			array( 'quiz_id' => $quiz_id ),
			array( '%s' ),
			array( '%d' )
		);
		if ( false !== $results ) {
			return true;
		} else {
			return false;
		}
	}
}