array( 'href' => array(), 'title' => array(), ), 'br' => array(), 'em' => array(), 'span' => array(), 'strong' => array(), 'small' => array(), ); public function __construct() { $this->cpath = untrailingslashit( plugin_dir_path( __FILE__ ) ); add_action( 'awsm_application_form_init', array( $this, 'application_form' ) ); add_action( 'awsm_application_form_field_init', array( $this, 'form_field_init' ) ); add_action( 'awsm_application_form_field_init', array( $this, 'form_language_field' ), 100 ); add_action( 'awsm_job_application_submitting', array( $this, 'set_form_language' ) ); add_action( 'before_awsm_job_details', array( $this, 'insert_application' ) ); add_action( 'wp_ajax_awsm_applicant_form_submission', array( $this, 'ajax_handle' ) ); add_action( 'wp_ajax_nopriv_awsm_applicant_form_submission', array( $this, 'ajax_handle' ) ); add_filter( 'wp_check_filetype_and_ext', array( $this, 'check_filetype_and_ext' ), 10, 5 ); } public static function init() { if ( is_null( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } public static function get_allowed_html() { /** * Filters the allowed HTML elements and attributes for the form. * * @since 3.0.0 * * @param array|string $allowed_html An array of allowed HTML elements and attributes or a context name. */ return apply_filters( 'awsm_application_form_allowed_html', self::$allowed_html ); } public function dynamic_form_fields( $form_attrs ) { $allowed_file_types = get_option( 'awsm_jobs_admin_upload_file_ext' ); $allowed_file_content = ''; if ( is_array( $allowed_file_types ) && ! empty( $allowed_file_types ) ) { $allowed_file_types = '.' . join( ', .', $allowed_file_types ); /* translators: %1$s: comma-separated list of allowed file types */ $allowed_file_content = '' . sprintf( esc_html__( 'Allowed Type(s): %1$s', 'wp-job-openings' ), $allowed_file_types ) . ''; } $default_form_fields = array( 'awsm_applicant_name' => array( 'label' => __( 'Full Name', 'wp-job-openings' ), 'id' => 'awsm-applicant-name', 'class' => array( 'awsm-job-form-control' ), ), 'awsm_applicant_email' => array( 'label' => __( 'Email', 'wp-job-openings' ), 'field_type' => array( 'tag' => 'input', 'type' => 'email', ), 'id' => 'awsm-applicant-email', 'class' => array( 'awsm-job-form-control' ), 'error' => array( 'error_rule' => 'email', 'error_msg' => __( 'Please enter a valid email address.', 'wp-job-openings' ), ), ), 'awsm_applicant_phone' => array( 'label' => __( 'Phone', 'wp-job-openings' ), 'field_type' => array( 'tag' => 'input', 'type' => 'tel', ), 'id' => 'awsm-applicant-phone', 'class' => array( 'awsm-job-form-control' ), 'error' => array( 'error_msg' => __( 'Please enter a valid phone number.', 'wp-job-openings' ), ), ), 'awsm_applicant_letter' => array( 'label' => __( 'Cover Letter', 'wp-job-openings' ), 'field_type' => array( 'tag' => 'textarea', ), 'id' => 'awsm-cover-letter', 'class' => array( 'awsm-job-form-control' ), ), 'awsm_file' => array( 'label' => __( 'Upload CV/Resume', 'wp-job-openings' ), 'field_type' => array( 'tag' => 'input', 'type' => 'file', 'accept' => $allowed_file_types, ), 'id' => 'awsm-application-file', 'class' => array( 'awsm-resume-file-control', 'awsm-job-form-control', 'awsm-form-file-control' ), 'content' => $allowed_file_content, ), ); /** * Filters the job application form fields. * * @since 1.0.0 * @since 2.2.1 The `$form_attrs` parameter was added. * * @param array $form_fields Form fields array. * @param array $form_attrs Attributes array for the form. */ $form_fields = apply_filters( 'awsm_application_form_fields', $default_form_fields, $form_attrs ); return $form_fields; } public function display_dynamic_fields( $form_attrs ) { $dynamic_form_fields = $this->dynamic_form_fields( $form_attrs ); if ( ! empty( $dynamic_form_fields ) ) { $ordered_form_fields = array(); /** * Filters the job application form fields order. * * @since 1.2.0 * @since 2.2.1 The `$form_attrs` parameter was added. * * @param array $form_fields_order Form fields array. * @param array $form_attrs Attributes array for the form. */ $form_fields_order = apply_filters( 'awsm_application_form_fields_order', $this->form_fields_order, $form_attrs ); foreach ( $form_fields_order as $form_field_order ) { $ordered_form_fields[ $form_field_order ] = $dynamic_form_fields[ $form_field_order ]; } $dynamic_form_fields = $ordered_form_fields; $allowed_html = self::get_allowed_html(); $required_msg = esc_attr__( 'This field is required.', 'wp-job-openings' ); $form_output = ''; foreach ( $dynamic_form_fields as $field_name => $field_args ) { $show_field = ( isset( $field_args['show_field'] ) ) ? $field_args['show_field'] : true; if ( $show_field ) { $label = ( isset( $field_args['label'] ) ) ? $field_args['label'] : ''; $tag = ( isset( $field_args['field_type'] ) ) ? ( ( isset( $field_args['field_type']['tag'] ) ) ? $field_args['field_type']['tag'] : 'input' ) : 'input'; $input_type = ( isset( $field_args['field_type'] ) ) ? ( ( isset( $field_args['field_type']['type'] ) ) ? $field_args['field_type']['type'] : 'text' ) : 'text'; $field_id = ( isset( $field_args['id'] ) ) ? $field_args['id'] : $field_name; $field_class = 'awsm-job-form-field'; $field_class = ( isset( $field_args['class'] ) && is_array( $field_args['class'] ) ) ? $field_class . ' ' . join( ' ', $field_args['class'] ) : $field_class; $required = ( isset( $field_args['required'] ) ) ? $field_args['required'] : true; $required_attr = ( $required ) ? ' required' : ''; $data_required = ( $required ) ? ' data-msg-required="' . $required_msg . '"' : ''; $required_label = ( $required ) ? ' *' : ''; $form_group_class = 'awsm-job-form-group'; $form_group_class = ( isset( $field_args['label_inline'] ) ) ? $form_group_class . ' awsm-job-inline-group' : $form_group_class; $extra_content = ( isset( $field_args['content'] ) ) ? $field_args['content'] : ''; // Validation $data_error_msg = ( isset( $field_args['error'] ) && ! empty( $field_args['error'] ) ) ? ( ( isset( $field_args['error']['error_msg'], $field_args['error']['error_rule'] ) && ! empty( $field_args['error']['error_msg'] ) && ! empty( $field_args['error']['error_rule'] ) ) ? ( ' data-rule-' . $field_args['error']['error_rule'] . '="true" data-msg-' . $field_args['error']['error_rule'] . '="' . esc_attr( $field_args['error']['error_msg'] ) . '"' ) : '' ) : ''; // Common attributes for tags $common_attrs = sprintf( 'name="%1$s" class="%2$s" id="%3$s"%4$s', esc_attr( $field_name ), esc_attr( $field_class ), esc_attr( $field_id ), $required_attr . $data_required . $data_error_msg ); if ( $input_type === 'file' ) { $common_attrs .= isset( $field_args['field_type']['accept'] ) ? sprintf( ' accept="%s"', esc_attr( $field_args['field_type']['accept'] ) ) : ''; } else { if ( $tag !== 'textarea' && $tag !== 'select' ) { $common_attrs .= isset( $field_args['field_type']['value'] ) ? sprintf( ' value="%s"', esc_attr( $field_args['field_type']['value'] ) ) : ''; } } $field_content = $label_content = ''; // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found if ( ! empty( $label ) ) { $label_content = sprintf( '', wp_kses( $label, $allowed_html ) . $required_label, esc_attr( $field_id ) ); } if ( $tag === 'input' || $tag === 'select' ) { if ( $tag === 'select' || $input_type === 'checkbox' || $input_type === 'radio' ) { $options = isset( $field_args['field_type']['options'] ) ? $field_args['field_type']['options'] : ''; if ( ! empty( $options ) && is_array( $options ) ) { $options_content = ''; if ( $tag === 'select' ) { if ( ! $required ) { $options_content .= sprintf( '', esc_html__( '--Please Choose an Option--', 'wp-job-openings' ) ); } foreach ( $options as $option ) { $options_content .= sprintf( '', esc_attr( $option ), esc_html( $option ) ); } $field_content .= sprintf( '', $options_content, $common_attrs ); } else { $id_suffix = 1; foreach ( $options as $option ) { $name_suffix = ( $input_type === 'checkbox' ) ? '[]' : ''; $current_field_id = esc_attr( $field_id . '_' . $id_suffix ); $common_attrs = sprintf( 'name="%1$s" class="%2$s" id="%3$s"%4$s', esc_attr( $field_name . $name_suffix ), esc_attr( $field_class ), $current_field_id, $required_attr . $data_required . $data_error_msg ); $options_content .= sprintf( ' ', esc_attr( $input_type ), esc_attr( $option ), $common_attrs, $current_field_id, esc_html( $option ) ); $id_suffix ++; } $field_content .= sprintf( '
%s
', $options_content ); } } } else { $field_content .= sprintf( '', esc_attr( $input_type ), $common_attrs ); } } elseif ( $tag === 'textarea' ) { $field_content .= sprintf( '', $common_attrs ); } if ( isset( $field_args['label_inline'] ) && $field_args['label_inline'] === 'right' ) { $field_content .= $label_content; } else { $field_content = $label_content . $field_content; } $field_type = $tag === 'input' ? $input_type : $tag; /** * Filters the field content of a specific field type of the job application form. * * @since 2.0.0 * @since 2.2.1 The `$form_attrs` parameter was added. * * @param string $field_content The content. * @param array $field_args Form field options. * @param array $form_attrs Attributes array for the form. */ $field_content = apply_filters( "awsm_application_dynamic_form_{$field_type}_field_content", $field_content, $field_args, $form_attrs ); $field_output = sprintf( '
%1$s
', $field_content . wp_kses( $extra_content, $allowed_html ), esc_attr( $form_group_class ) ); /** * Filters the form field content of the job application form. * * @since 2.0.0 * @since 2.2.1 The `$form_attrs` parameter was added. * * @param string $field_output The content. * @param string $field_type The field type. * @param array $field_args Form field options. * @param array $form_attrs Attributes array for the form. */ $form_output .= apply_filters( 'awsm_application_dynamic_form_field_content', $field_output, $field_type, $field_args, $form_attrs ); } } /** * Filters the dynamic form fields content of the job application form. * * @since 1.3.0 * @since 2.2.1 The `$form_attrs` parameter was added. * * @param string $form_output The content. * @param array $dynamic_form_fields Dynamic form fields. * @param array $form_attrs Attributes array for the form. */ echo apply_filters( 'awsm_application_dynamic_form_fields_content', $form_output, $dynamic_form_fields, $form_attrs ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } public function get_gdpr_field_label() { $gdpr_enable = get_option( 'awsm_enable_gdpr_cb' ); $gdpr_cb_text = get_option( 'awsm_gdpr_cb_text' ); if ( ! empty( $gdpr_enable ) && ! empty( $gdpr_cb_text ) ) { return $gdpr_cb_text; } else { return false; } } public function display_gdpr_field( $form_attrs ) { $label = $this->get_gdpr_field_label(); if ( ! empty( $label ) ) { $field_id = $form_attrs['single_form'] ? 'awsm_form_privacy_policy' : esc_attr( 'awsm_form_privacy_policy-' . $form_attrs['job_id'] ); $field_content = sprintf( '
', esc_attr( $field_id ), wp_kses( $label, self::get_allowed_html() ), esc_attr__( 'This field is required.', 'wp-job-openings' ) ); /** * Filters the privacy policy checkbox field content. * * @since 3.0.0 * * @param string $field_content Field HTML content. * @param array $form_attrs Attributes array for the form. */ echo apply_filters( 'awsm_application_form_gdpr_field_content', $field_content, $form_attrs ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } public function display_recaptcha_field( $form_attrs ) { if ( $this->is_recaptcha_set() ) : /** * Filters the reCAPTCHA visibility in the application form. * * @since 2.2.0 * @since 2.2.1 The `$form_attrs` parameter was added. * * @param bool $is_visible Whether the reCAPTCHA is visible or not in the form. * @param array $form_attrs Attributes array for the form. */ $is_visible = apply_filters( 'awsm_application_form_is_recaptcha_visible', true, $form_attrs ); if ( $is_visible ) : $site_key = get_option( 'awsm_jobs_recaptcha_site_key' ); $fallback_url = add_query_arg( 'k', $site_key, 'https://www.google.com/recaptcha/api/fallback' ); ?>
true, 'job_id' => get_the_ID(), ); include AWSM_Job_Openings::get_template_path( 'form.php', 'single-job' ); } public function form_field_init( $form_attrs ) { $this->display_dynamic_fields( $form_attrs ); $this->display_gdpr_field( $form_attrs ); $this->display_recaptcha_field( $form_attrs ); } public function check_filetype_and_ext( $wp_filetype, $file, $filename, $mimes, $real_mime = '' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( ! empty( $real_mime ) && isset( $_POST['action'] ) && $_POST['action'] === 'awsm_applicant_form_submission' && empty( $wp_filetype['type'] ) && ! empty( $mimes ) ) { $filetype = wp_check_filetype( $filename, $mimes ); // fix issue with application/vnd.openxmlformats-officedocument.* mime types in some PHP versions. $extensions = array( 'docx', 'dotx', 'xlsx', 'xltx', 'pptx', 'ppsx', 'potx', 'sldx' ); if ( $filetype['ext'] && in_array( $filetype['ext'], $extensions, true ) && $real_mime === $filetype['type'] . $filetype['type'] ) { $wp_filetype['ext'] = $filetype['ext']; $wp_filetype['type'] = $filetype['type']; } } return $wp_filetype; } public function upload_dir( $param ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( isset( $_POST['action'] ) && $_POST['action'] === 'awsm_applicant_form_submission' ) { $subdir = '/' . AWSM_JOBS_UPLOAD_DIR_NAME; if ( empty( $param['subdir'] ) ) { $param['path'] = $param['path'] . $subdir; $param['url'] = $param['url'] . $subdir; $param['subdir'] = $subdir; } else { $subdir .= $param['subdir']; $param['path'] = str_replace( $param['subdir'], $subdir, $param['path'] ); $param['url'] = str_replace( $param['subdir'], $subdir, $param['url'] ); $param['subdir'] = str_replace( $param['subdir'], $subdir, $param['subdir'] ); } } return $param; } public function hashed_file_name( $dir, $name, $ext ) { $file_name = hash( 'sha1', ( $name . uniqid( (string) rand(), true ) ) ) . time(); return sanitize_file_name( $file_name . $ext ); } public function form_language_field() { $current_lang = AWSM_Job_Openings::get_current_language(); if ( ! empty( $current_lang ) ) { printf( '', esc_attr( $current_lang ) ); } } public function set_form_language() { // phpcs:disable WordPress.Security.NonceVerification.Missing if ( isset( $_POST['lang'] ) ) { AWSM_Job_Openings::set_current_language( $_POST['lang'] ); } // phpcs:enable } public function insert_application() { // phpcs:disable WordPress.Security.NonceVerification.Missing global $awsm_response; $awsm_response = array( 'success' => array(), 'error' => array(), ); if ( $_SERVER['REQUEST_METHOD'] === 'POST' && ! empty( $_POST['action'] ) && $_POST['action'] === 'awsm_applicant_form_submission' ) { $job_id = intval( $_POST['awsm_job_id'] ); $applicant_name = sanitize_text_field( wp_unslash( $_POST['awsm_applicant_name'] ) ); $applicant_email = sanitize_email( wp_unslash( $_POST['awsm_applicant_email'] ) ); $applicant_phone = sanitize_text_field( wp_unslash( $_POST['awsm_applicant_phone'] ) ); $applicant_letter = awsm_jobs_sanitize_textarea( wp_unslash( $_POST['awsm_applicant_letter'] ) ); $attachment = isset( $_FILES['awsm_file'] ) ? $_FILES['awsm_file'] : ''; $agree_privacy_policy = false; $generic_err_msg = esc_html__( 'Error in submitting your application. Please refresh the page and retry.', 'wp-job-openings' ); if ( $this->is_recaptcha_set() ) { $is_human = false; if ( isset( $_POST['g-recaptcha-response'] ) ) { $is_human = $this->validate_captcha_field( $_POST['g-recaptcha-response'] ); } if ( ! $is_human ) { $awsm_response['error'][] = esc_html__( 'Please verify that you are not a robot.', 'wp-job-openings' ); } } if ( $this->get_gdpr_field_label() !== false ) { if ( ! isset( $_POST['awsm_form_privacy_policy'] ) || $_POST['awsm_form_privacy_policy'] !== 'yes' ) { $awsm_response['error'][] = esc_html__( 'Please agree to our privacy policy.', 'wp-job-openings' ); } else { $agree_privacy_policy = sanitize_text_field( $_POST['awsm_form_privacy_policy'] ); } } if ( get_post_type( $job_id ) !== 'awsm_job_openings' ) { $awsm_response['error'][] = esc_html__( 'Error occurred: Invalid Job.', 'wp-job-openings' ); } if ( get_post_status( $job_id ) === 'expired' ) { $awsm_response['error'][] = esc_html__( 'Sorry! This job has expired.', 'wp-job-openings' ); } if ( empty( $applicant_name ) ) { $awsm_response['error'][] = esc_html__( 'Name is required.', 'wp-job-openings' ); } if ( empty( $applicant_email ) ) { $awsm_response['error'][] = esc_html__( 'Email is required.', 'wp-job-openings' ); } else { if ( ! filter_var( $applicant_email, FILTER_VALIDATE_EMAIL ) ) { $awsm_response['error'][] = esc_html__( 'Invalid email format.', 'wp-job-openings' ); } } if ( empty( $applicant_phone ) ) { $awsm_response['error'][] = esc_html__( 'Contact number is required.', 'wp-job-openings' ); } else { if ( ! preg_match( '%^[+]?[0-9()/ -]*$%', trim( $applicant_phone ) ) ) { $awsm_response['error'][] = esc_html__( 'Invalid phone number.', 'wp-job-openings' ); } } if ( empty( $applicant_letter ) ) { $awsm_response['error'][] = esc_html__( 'Cover Letter cannot be empty.', 'wp-job-openings' ); } if ( empty( $attachment ) || ! isset( $attachment['error'] ) || $attachment['error'] > 0 ) { $awsm_response['error'][] = esc_html__( 'Please select your cv/resume.', 'wp-job-openings' ); } /** * Fires before job application submission * * @since 1.2 */ do_action( 'awsm_job_application_submitting' ); if ( count( $awsm_response['error'] ) === 0 ) { if ( ! function_exists( 'wp_handle_upload' ) ) { include ABSPATH . 'wp-admin/includes/file.php'; } if ( ! function_exists( 'wp_crop_image' ) ) { include ABSPATH . 'wp-admin/includes/image.php'; } $mimes = array(); $allowed_mime_types = get_allowed_mime_types(); $alowed_types = get_option( 'awsm_jobs_admin_upload_file_ext' ); foreach ( $alowed_types as $allowed_type ) { if ( isset( $allowed_mime_types[ $allowed_type ] ) ) { $mimes[ $allowed_type ] = $allowed_mime_types[ $allowed_type ]; } } $override = array( 'test_form' => false, 'mimes' => $mimes, 'unique_filename_callback' => array( $this, 'hashed_file_name' ), ); add_filter( 'upload_dir', array( $this, 'upload_dir' ) ); $movefile = wp_handle_upload( $attachment, $override ); remove_filter( 'upload_dir', array( $this, 'upload_dir' ) ); if ( $movefile && ! isset( $movefile['error'] ) ) { $post_base_data = array( 'post_title' => $applicant_name, 'post_content' => '', 'post_status' => 'publish', 'comment_status' => 'closed', ); $application_data = array_merge( $post_base_data, array( 'post_type' => 'awsm_job_application', 'post_parent' => $job_id, ) ); $application_id = wp_insert_post( $application_data, true ); if ( ! is_wp_error( $application_id ) ) { $attachment_data = array_merge( $post_base_data, array( 'post_mime_type' => $movefile['type'], 'guid' => $movefile['url'], ) ); $attach_id = wp_insert_attachment( $attachment_data, $movefile['file'], $application_id, true ); if ( ! is_wp_error( $attach_id ) ) { $attach_data = wp_generate_attachment_metadata( $attach_id, $movefile['file'] ); wp_update_attachment_metadata( $attach_id, $attach_data ); $applicant_details = array( 'awsm_job_id' => $job_id, 'awsm_apply_for' => esc_html( get_the_title( $job_id ) ), 'awsm_applicant_ip' => isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : '', 'awsm_applicant_name' => $applicant_name, 'awsm_applicant_email' => $applicant_email, 'awsm_applicant_phone' => $applicant_phone, 'awsm_applicant_letter' => $applicant_letter, 'awsm_attachment_id' => $attach_id, ); if ( ! empty( $agree_privacy_policy ) ) { $applicant_details['awsm_agree_privacy_policy'] = $agree_privacy_policy; } foreach ( $applicant_details as $meta_key => $meta_value ) { update_post_meta( $application_id, $meta_key, $meta_value ); } // Now, send notification email $applicant_details['application_id'] = $application_id; $this->notification_email( $applicant_details ); $awsm_response['success'][] = esc_html__( 'Your application has been submitted.', 'wp-job-openings' ); /** * Fires after successful job application submission * * @since 1.2 * * @param int $application_id Application ID */ do_action( 'awsm_job_application_submitted', $application_id ); } else { AWSM_Job_Openings::log( $attach_id ); $awsm_response['error'][] = $generic_err_msg; } } else { AWSM_Job_Openings::log( $application_id ); $awsm_response['error'][] = $generic_err_msg; } } else { AWSM_Job_Openings::log( $movefile ); $awsm_response['error'][] = $movefile['error']; } } add_action( 'awsm_application_form_notices', array( $this, 'awsm_form_submit_notices' ) ); } return $awsm_response; // phpcs:enable } public function is_recaptcha_set() { $is_set = false; $enable_recaptcha = get_option( 'awsm_jobs_enable_recaptcha' ); $site_key = get_option( 'awsm_jobs_recaptcha_site_key' ); $secret_key = get_option( 'awsm_jobs_recaptcha_secret_key' ); if ( $enable_recaptcha === 'enable' && ! empty( $site_key ) && ! empty( $secret_key ) ) { $is_set = true; } return $is_set; } public function get_recaptcha_response( $token ) { $result = array(); $secret_key = get_option( 'awsm_jobs_recaptcha_secret_key' ); $response = wp_safe_remote_post( 'https://www.google.com/recaptcha/api/siteverify', array( 'body' => array( 'secret' => $secret_key, 'response' => $token, 'remoteip' => $_SERVER['REMOTE_ADDR'], ), ) ); if ( ! is_wp_error( $response ) ) { $response_body = wp_remote_retrieve_body( $response ); if ( '' !== $response_body ) { if ( wp_remote_retrieve_response_code( $response ) === 200 ) { $result = json_decode( $response_body, true ); } } } return $result; } public function validate_captcha_field( $token ) { $is_valid = false; if ( ! empty( $token ) ) { $result = $this->get_recaptcha_response( $token ); if ( ! empty( $result ) ) { $is_valid = isset( $result['success'] ) && $result['success'] === true; } } return $is_valid; } public function ajax_handle() { $response = $this->insert_application(); wp_send_json( $response ); } public function awsm_form_submit_notices() { global $awsm_response; $msg_array = array(); $class_name = 'awsm-default-message'; $content = ''; if ( ! empty( $awsm_response['success'] ) ) { $msg_array = $awsm_response['success']; $class_name = 'awsm-success-message'; } else { if ( ! empty( $awsm_response['error'] ) ) { $msg_array = $awsm_response['error']; $class_name = 'awsm-error-message'; $content .= '

' . esc_html__( 'The following errors have occurred:', 'wp-job-openings' ) . '

'; } } foreach ( $msg_array as $msg ) { $content .= '
  • ' . esc_html( $msg ) . '
  • '; } printf( '', esc_attr( $class_name ), $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } public function get_mail_template_tags( $applicant_details, $options = array() ) { $job_expiry = get_post_meta( $applicant_details['awsm_job_id'], 'awsm_job_expiry', true ); $job_expiry = ( ! empty( $job_expiry ) ) ? date_i18n( get_awsm_jobs_date_format( 'expiry-mail' ), strtotime( $job_expiry ) ) : ''; $attachment_url = isset( $applicant_details['awsm_attachment_id'] ) ? wp_get_attachment_url( $applicant_details['awsm_attachment_id'] ) : ''; if ( ! empty( $attachment_url ) && get_option( 'awsm_hide_uploaded_files' ) === 'hide_files' ) { $attachment_url = AWSM_Job_Openings::get_application_edit_link( $applicant_details['application_id'] ); } $tags = array( '{applicant}' => $applicant_details['awsm_applicant_name'], '{application-id}' => $applicant_details['application_id'], '{applicant-email}' => $applicant_details['awsm_applicant_email'], '{applicant-phone}' => isset( $applicant_details['awsm_applicant_phone'] ) ? $applicant_details['awsm_applicant_phone'] : '', '{job-id}' => $applicant_details['awsm_job_id'], '{job-expiry}' => $job_expiry, '{job-title}' => $applicant_details['awsm_apply_for'], '{applicant-cover}' => isset( $applicant_details['awsm_applicant_letter'] ) ? nl2br( $applicant_details['awsm_applicant_letter'] ) : '', '{applicant-resume}' => ( ! empty( $attachment_url ) ) ? esc_url( $attachment_url ) : '', ); $tags = array_merge( $tags, AWSM_Job_Openings::get_mail_generic_template_tags( $options ) ); /** * Filters the mail template tags. * * @since 1.4 * * @param array $tags Mail template tags * @param array $applicant_details Applicant Details * @param array $options Settings values */ return apply_filters( 'awsm_jobs_mail_template_tags', $tags, $applicant_details, $options ); } /** * Get the notification options. * * @since 3.0.0 * * @param string $type Notification type - applicant or admin * @return array */ public static function get_notification_options( $type ) { $options = array(); $admin_email = get_option( 'admin_email' ); $hr_email = get_option( 'awsm_hr_email_address' ); if ( $type === 'applicant' ) { $options = array( 'acknowledgement' => get_option( 'awsm_jobs_acknowledgement' ), 'from' => get_option( 'awsm_jobs_from_email_notification', $admin_email ), 'reply_to' => get_option( 'awsm_jobs_reply_to_notification' ), 'cc' => get_option( 'awsm_jobs_hr_notification', $hr_email ), 'subject' => get_option( 'awsm_jobs_notification_subject', '' ), 'content' => get_option( 'awsm_jobs_notification_content', '' ), 'html_template' => get_option( 'awsm_jobs_notification_mail_template' ), ); } elseif ( $type === 'admin' ) { $options = array( 'enable' => get_option( 'awsm_jobs_enable_admin_notification' ), 'from' => get_option( 'awsm_jobs_admin_from_email_notification', $admin_email ), 'reply_to' => get_option( 'awsm_jobs_admin_reply_to_notification', '{applicant-email}' ), 'to' => get_option( 'awsm_jobs_admin_to_notification', $hr_email ), 'cc' => get_option( 'awsm_jobs_admin_hr_notification' ), 'subject' => get_option( 'awsm_jobs_admin_notification_subject', '' ), 'content' => get_option( 'awsm_jobs_admin_notification_content', '' ), 'html_template' => get_option( 'awsm_jobs_notification_admin_mail_template' ), ); } return $options; } /** * Handle applicant and admin notification emails. * * @since 3.0.0 The `$data` parameter was added. * * @param array $applicant_details Applicant details. * @param array $data Notification data if provided will override the default. */ protected function notification_email( $applicant_details, $data = array() ) { /** * Filters the default notifications types - applicant or admin. * * @since 3.2.0 * * @param array $types Notification types. * @param array $applicant_details Applicant details. * @param array $data Notification data. */ $types = apply_filters( 'awsm_jobs_default_notifications_types', array( 'applicant', 'admin' ), $applicant_details, $data ); foreach ( $types as $type ) { if ( ! isset( $data[ $type ] ) ) { $data[ $type ] = self::get_notification_options( $type ); } $options = $data[ $type ]; // Check if the notification is enabled or not. $enable = false; if ( $type === 'applicant' ) { $enable = $options['acknowledgement'] === 'acknowledgement'; } elseif ( $type === 'admin' ) { $enable = $options['enable'] === 'enable'; } if ( $enable ) { $admin_email = get_option( 'admin_email' ); $hr_mail = get_option( 'awsm_hr_email_address' ); $applicant_email = $applicant_details['awsm_applicant_email']; $company_name = get_option( 'awsm_job_company_name' ); $from = ( ! empty( $company_name ) ) ? $company_name : get_option( 'blogname' ); $tags = $this->get_mail_template_tags( $applicant_details, array( 'admin_email' => $admin_email, 'hr_email' => $hr_mail, 'company_name' => $company_name, ) ); $tag_names = array_keys( $tags ); $tag_values = array_values( $tags ); $email_tag_names = array( '{admin-email}', '{hr-email}', '{applicant-email}' ); $email_tag_values = array( $admin_email, $hr_mail, $applicant_email ); if ( ! empty( $options['subject'] ) && ! empty( $options['content'] ) ) { $subject = str_replace( $tag_names, $tag_values, $options['subject'] ); $reply_to = str_replace( $email_tag_names, $email_tag_values, $options['reply_to'] ); $cc = str_replace( $email_tag_names, $email_tag_values, $options['cc'] ); /** * Filters the applicant or admin notification mail headers. * * @since 1.4 * * @param array $headers Additional headers. * @param array $applicant_details Applicant details. */ $headers = apply_filters( "awsm_jobs_{$type}_notification_mail_headers", array( 'content_type' => 'Content-Type: text/html; charset=UTF-8', 'from' => sprintf( 'From: %1$s <%2$s>', $from, $options['from'] ), 'reply_to' => 'Reply-To: ' . $reply_to, 'cc' => 'Cc: ' . $cc, ), $applicant_details ); $reply_to = trim( str_replace( 'Reply-To:', '', $headers['reply_to'] ) ); if ( empty( $reply_to ) ) { unset( $headers['reply_to'] ); } $mail_cc = trim( str_replace( 'Cc:', '', $headers['cc'] ) ); if ( empty( $mail_cc ) ) { unset( $headers['cc'] ); } /** * Filters the applicant or admin notification mail attachments. * * @since 1.4 * * @param array $attachments Mail attachments. * @param array $applicant_details Applicant details. */ $attachments = apply_filters( "awsm_jobs_{$type}_notification_mail_attachments", array(), $applicant_details ); $admin_attachments = $attachments; if ( $type === 'admin' ) { $attachments = ! empty( $attachments ) ? wp_list_pluck( $attachments, 'file' ) : array(); } $mail_content = nl2br( AWSM_Job_Openings_Mail_Customizer::sanitize_content( $options['content'] ) ); if ( $options['html_template'] === 'enable' ) { // Header mail template. ob_start(); include AWSM_Job_Openings::get_template_path( 'header.php', 'mail' ); $header_template = ob_get_clean(); $header_template .= '
    '; // Footer mail template. ob_start(); include AWSM_Job_Openings::get_template_path( 'footer.php', 'mail' ); $footer_template = ob_get_clean(); $footer_template = '
    ' . $footer_template; $template = $header_template . $mail_content . $footer_template; /** * Filters the applicant or admin notification mail template. * * @since 2.0.0 * * @param string $template Mail template. * @param array $template_data Mail template data. * @param array $applicant_details Applicant details. */ $mail_content = apply_filters( "awsm_jobs_{$type}_notification_mail_template", $template, array( 'header' => $header_template, 'main' => $mail_content, 'footer' => $footer_template, ), $applicant_details ); } else { // Basic mail template. ob_start(); include AWSM_Job_Openings::get_template_path( 'basic.php', 'mail' ); $basic_template = ob_get_clean(); $mail_content = str_replace( '{mail-content}', $mail_content, $basic_template ); } $tag_names[] = '{mail-subject}'; $tag_values[] = $subject; $mail_content = str_replace( $tag_names, $tag_values, $mail_content ); $to = $applicant_email; if ( $type !== 'applicant' ) { $to = str_replace( $email_tag_names, $email_tag_values, $options['to'] ); } AWSM_Job_Openings::log( array( 'to' => $to, 'subject' => $subject, 'mail_content' => $mail_content, 'headers' => $headers, 'attachments' => $attachments, ) ); add_filter( 'wp_mail_content_type', 'awsm_jobs_mail_content_type' ); // Now, send the mail. $is_mail_send = wp_mail( $to, $subject, $mail_content, array_values( $headers ), $attachments ); remove_filter( 'wp_mail_content_type', 'awsm_jobs_mail_content_type' ); if ( $is_mail_send ) { if ( $type === 'applicant' ) { // Save the applicant notification details. $current_time = current_time( 'mysql' ); $mails_data = array( array( 'send_by' => 0, 'mail_date' => $current_time, 'cc' => $cc, 'subject' => $subject, 'mail_content' => str_replace( $tag_names, $tag_values, nl2br( $options['content'] ) ), ), ); update_post_meta( $applicant_details['application_id'], 'awsm_application_mails', $mails_data ); } elseif ( $type === 'admin' ) { // Remove the admin notification attachments after the mail is sent (requires a specific structure for each attachment). if ( ! empty( $admin_attachments ) ) { foreach ( $admin_attachments as $admin_attachment ) { if ( isset( $admin_attachment['temp'] ) && $admin_attachment['temp'] === true ) { unlink( $admin_attachment['file'] ); } } } } /** * Fires when applicant or admin notification mail is successfully sent. * * @since 1.4 * * @param array $applicant_details Applicant details. */ do_action( "awsm_job_{$type}_mail_sent", $applicant_details ); } else { /** * Fires when applicant or admin notification mail is failed to send. * * @since 1.4 * * @param array $applicant_details Applicant details. */ do_action( "awsm_job_{$type}_mail_failed", $applicant_details ); } } } } } }