RPeraltaJr
10/10/2019 - 2:55 PM

File Uploads with validations

This snippet was used in a WordPress theme.

<?php 

// * Job Apply 
function submit_apply_form() 
{
    global $wpdb;

    $response = (object) [
        "error" => false,
        "status"  => "",
        "message" => "",
    ];
    $post = get_post(((int) $_POST["post_id"]));

    $post_fields = [
        "first_name" => (object) [
            "label" => "First Name",
            "required" => true,
        ],
        "last_name" => (object) [
            "label" => "Last Name",
            "required" => true,
        ],
        "email" => (object) [
            "label" => "Email",
            "required" => true,
        ],
        "subject" => (object) [
            "label" => "Subject",
            "required" => false,
        ],
        "cover_letter" => (object) [
            "label" => "Cover Letter",
            "required" => true,
        ],
    ];

    $role = ucwords(sanitize_text_field($_POST['role']));
    $table_data = [
        "ip_address" => sanitize_text_field($_SERVER["REMOTE_ADDR"]),
        "form_url" => sanitize_text_field($_POST["form_url"]),
        "role" => $post->post_title,
    ];

    foreach ($post_fields as $post_field => $post_info) {
        if ($post_info->required === true) {
            if (empty($_POST[$post_field]) || strlen($_POST[$post_field]) < 1) {
                $response->error = true;
                $response->message = "Please fill in all inputs marked with *";
            }
        }

        $$post_field = filter_var($_POST[$post_field], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH);

        switch ($post_field) {
            case "email":
                $$post_field = filter_var($$post_field, FILTER_SANITIZE_EMAIL);
                if (!filter_var($$post_field, FILTER_VALIDATE_EMAIL)) {
                    $response->error = true;
                    $response->message = "Please check your email is valid";
                }
                break;
            case "cover_letter":
                break;
            default:
                $$post_field = ucwords(strtolower($$post_field));
        }

        $table_data[$post_field] = $$post_field;
    }

    // _ resume handling
    if (file_exists($_FILES["resume"]["tmp_name"]) || is_uploaded_file($_FILES["resume"]["tmp_name"])) {
        // * Check filesize < 2MB
        // documentation: http://www.cheatsheeting.com/show.html?sheet=mb-to-b-conversions
        if ($_FILES["resume"]["size"] > 1048576):
            $response->error = true;
            $response->message[] = "Resume needs to be less than 1MB.";
        endif;
        // * Check file extension(s)
        $allowedExts = [
            "pdf",
            "doc",
            "docx",
        ];
        $temp = explode(".", $_FILES["resume"]["name"]);
        $extension = end($temp);
        if (!in_array($extension, $allowedExts)):
            $response->error = true;
            $response->message[] = "Please check resume is an allowed file type.";
        endif;
        // * Check filetype
        $allowed_types = [
            "application/pdf",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "application/msword",
            // "application/rtf",
        ];
        if (!in_array($_FILES["resume"]["type"], $allowed_types)):
            $response->error = true;
            $response->message[] = "Please check resume is an allowed file type.";
        endif;
        
        // * File Renaming
        $timestamp = date('Y-m-d');
        $random = mt_rand();
        $filename = "{$timestamp}-{$random}.{$extension}";
    }

    // * captcha validation
    $captcha = (object) [
        "url" => "https://www.google.com/recaptcha/api/siteverify",
        "secret" => "6Lcpi6kUAAAAACLfsnIiZ1IZr7EHA_WtqKoY8nwi",
        "token" => filter_var($_POST["captcha"], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH),
    ];
    $captcha_response = file_get_contents($captcha->url . '?secret=' . $captcha->secret . '&response=' . $captcha->token);
    $captcha_response = json_decode($captcha_response);

    if (!empty($captcha_response->score) && $captcha_response->score < 0.5) {
        $response->error = true;
        $response->message = "There was an issue with your submission. Please try again.";
    }

    // * if no errors then save to database and send admin email
    if ($response->error === false) {
        $attachment = [];
        if (!empty($_FILES["resume"]["tmp_name"])) {
            $file_location = $_SERVER["DOCUMENT_ROOT"] . "/apply-resumes/" . $filename;
            $file_location = str_replace("/public_html", "", $file_location);
            $attachment[] = $file_location;
            move_uploaded_file($_FILES["resume"]["tmp_name"], $file_location);
        }

        $wpdb->insert("job_submissions", $table_data);

        $mail_subject = "New job submission for " . $post->post_title;
        $mail_applicant =
            '<b>Submission Info:</b><br>' .
            '<table style="border-collapse: collapse;">';
        foreach ($post_fields as $post_field => $post_info) {
            $mail_applicant .=
                '<tr>' .
                '<th style="text-align: left; border: 1px solid black; padding: 5px;">' .
                    $post_info->label .
                '</th>' .
                '<td style="border: 1px solid black; padding: 5px;">' .
                    $$post_field .
                '</td>' .
                '</tr>';
        }
        $mail_applicant .= '</table><br><br>';
        $mail_applicant .= '==========================<br>Sent from: ' . get_the_permalink($post->ID);

        $to = [
            "admin@mail.com"
        ];
        if ($last_name == "Testerson") {
            $to = [
                "developers@mail.com"
            ];
        }
        // message
        $message = "<html><head></head><body>$mail_applicant</body></html>";
        $headers = array(
            "Content-Type: text/html; charset=UTF-8",
            "From: No-reply <no-reply@mail.com>",
        );
        $sent = wp_mail($to, $mail_subject, $message, $headers, $attachment);
        if ($sent) {
            unlink($file_location);
        }
    }

    wp_send_json($response);
    wp_die();
}
add_action('wp_ajax_submit_apply_form', 'submit_apply_form');
add_action('wp_ajax_nopriv_submit_apply_form', 'submit_apply_form');
<form action="" method="POST" id="aply-form" class="form" autocomplete="off" data-form="apply" enctype="multipart/form-data">
  <!-- Form message goes here -->
  <div id="contact-form-message" class="form-group" data-form-message>
  </div>
  <div class="form-group">
      <div class="group">
          <label for="first_name">First Name <span>*</span></label>
          <input type="text" name="first_name" id="first_name" title="Letters and spaces only" pattern="[a-zA-Z\s]+" required>
      </div>
      <div class="group">
          <label for="last_name">Last Name <span>*</span></label>
          <input type="text" name="last_name" id="last_name" title="Letters and spaces only" pattern="[a-zA-Z\s]+" required>
      </div>
  </div>
  <div class="form-group">
      <label for="email">Email <span>*</span></label>
      <input type="email" name="email" id="email" required>
  </div>
  <div class="form-group">
      <label for="subject">Subject</label>
      <input type="text" name="subject" id="subject" maxlength="70">
  </div>
  <div class="form-group">
      <label for="message">We’d really like to know what interested you in our company and Employer Brand. Please tell us a little about why this might be a fit for you? <span>*</span></label>
      <textarea name="cover_letter" id="cover_letter" cols="30" rows="10" required></textarea>
  </div>
  <div class="form-group">
      <label for="form-job-resume">Resume (less than 2MB and PDF/DOC/DOCX)</label>
      <input type="file" name="resume" id="form-job-resume" accept="application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document">
  </div>
  <div class="form-group">
      <button type="submit" class="button button--outline button--arrow button--blue">Send Away!</button>
  </div>
  <input type="hidden" name="form_url" value="<?php echo sanitize_text_field($_SERVER["REQUEST_URI"]); ?>">
  <input type="hidden" name="post_id" value="<?php echo $post->ID; ?>">
  <input type="hidden" name="action" value="submit_apply_form">
  <input type="hidden" name="captcha" data-recaptcha>
</form>