subjects ?? '[]', true) ?: []; if (empty($subject_ids)) return []; $disciplines = []; foreach ($subject_ids as $sid) { if (!is_numeric($sid)) continue; $terms = wp_get_post_terms((int) $sid, 'discipline'); if (!is_wp_error($terms) && !empty($terms)) { foreach ($terms as $t) { $order_val = get_field('order', $t); if ($order_val === false || $order_val === null) { $order_val = get_term_meta($t->term_id, 'order', true); } if (!isset($disciplines[$t->term_id])) { $disciplines[$t->term_id] = [ 'term' => $t, 'order' => (int) $order_val ]; } } } } if (empty($disciplines)) return []; uasort($disciplines, function ($a, $b) { return $a['order'] <=> $b['order']; }); $top_disciplines = array_slice($disciplines, 0, 3, true); $questions_to_show = []; foreach ($top_disciplines as $term_id => $data) { $term = $data['term']; $q_posts = get_posts([ 'post_type' => 'interview_question', 'posts_per_page' => -1, 'tax_query' => [ [ 'taxonomy' => 'discipline', 'field' => 'term_id', 'terms' => $term_id ] ], 'fields' => 'ids' ]); if (!empty($q_posts)) { $random_q_id = $q_posts[array_rand($q_posts)]; $gallery = get_field('content', $random_q_id); $images = []; if (is_array($gallery)) { foreach ($gallery as $img) { if (is_string($img)) { $images[] = $img; } elseif (is_array($img) && !empty($img['url'])) { $images[] = $img['url']; } } } if (!empty($images)) { $q_items = []; foreach ($images as $url) { $q_items[] = ['type' => 'image', 'url' => $url]; } $questions_to_show[$term->name] = $q_items; } } } return $questions_to_show; } /* ============================================================ Interview CSS (output once) ============================================================ */ function im_enqueue_interview_styles() { static $done = false; if ($done) return; $done = true; echo ''; echo ''; } /* ============================================================ AJAX: Video Upload Handler ============================================================ */ add_action('wp_ajax_im_interview_upload', 'im_ajax_interview_upload'); add_action('wp_ajax_nopriv_im_interview_upload', 'im_ajax_interview_upload'); function im_ajax_interview_upload() { $token_str = sanitize_text_field($_POST['im_token'] ?? ''); $token_row = $token_str ? IM_Token::validate($token_str) : null; if (!$token_row) { wp_send_json_error(['message' => 'Invalid or expired interview link. Please refresh the page.']); } $candidate = IM_Candidate::get($token_row->candidate_id); if (!$candidate) { wp_send_json_error(['message' => 'Candidate not found.']); } if (!wp_verify_nonce($_POST['im_nonce'] ?? '', 'im_interview_' . $token_row->token)) { wp_send_json_error(['message' => 'Security verification failed. Please refresh and try again.']); } $file = $_FILES['im_video'] ?? null; if (!$file || $file['error'] !== UPLOAD_ERR_OK) { wp_send_json_error(['message' => 'Video upload failed. Please check the file size (max 500MB) and try again.']); } $allowed = [ 'video/mp4', 'video/quicktime', 'video/x-msvideo', 'video/avi', 'video/webm', 'video/x-ms-wmv', 'application/zip', 'application/x-zip-compressed', 'application/x-rar-compressed', 'application/vnd.rar', 'application/x-7z-compressed', 'application/gzip', 'application/x-tar' ]; $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = finfo_file($finfo, $file['tmp_name']); finfo_close($finfo); if (!in_array($mime, $allowed, true)) { wp_send_json_error(['message' => 'Supported formats: mp4, mov, avi, webm, wmv, zip, rar, 7z.']); } if ($file['size'] > IM_MAX_VIDEO_SIZE) { wp_send_json_error(['message' => 'Video file cannot exceed 500MB. Please compress and try again.']); } $upload_dir = wp_upload_dir(); $save_dir = $upload_dir['basedir'] . '/interviews/' . $candidate->id; wp_mkdir_p($save_dir); file_put_contents($save_dir . '/index.html', ''); $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); $filename = 'interview_' . $token_row->id . '_' . time() . '.' . $ext; $dest = $save_dir . '/' . $filename; if (!move_uploaded_file($file['tmp_name'], $dest)) { wp_send_json_error(['message' => 'File save failed. Please contact the administrator.']); } IM_Token::mark_used($token_row->id, $dest, $filename); IM_Candidate::update_status($candidate->id, 'completed'); $name = esc_html($candidate->preferred_name ?: $candidate->first_name); wp_send_json_success(['message' => 'ok', 'name' => $name]); } /* ============================================================ Shortcode: [im_interview] ============================================================ */ add_shortcode('im_interview', function () { im_enqueue_interview_styles(); ob_start(); $token_str = sanitize_text_field($_GET['im_token'] ?? ''); // No token if (!$token_str): ?>
!

Link Expired

This link has expired. Please fill out the Join Us form again, and we’ll send you a new application link shortly.

is_used): ?>

Already Submitted

You have already submitted your interview video. No further action is needed.

Thank you for your participation!

!

Link Expired

This interview link has expired. Please contact us if you need a new one.

opened_at)) { IM_Token::mark_opened($token_row->id); $token_row = IM_Token::validate($token_str); } $candidate = IM_Candidate::get($token_row->candidate_id); $questions = im_get_questions($candidate); $name = esc_html($candidate->preferred_name ?: $candidate->first_name); $nonce = wp_create_nonce('im_interview_' . $token_row->token); $expires_dt = new DateTimeImmutable($token_row->expires_at, wp_timezone()); $expires_ms = $expires_dt->getTimestamp() * 1000; $q_html = ''; foreach ($questions as $subject => $qs) { $q_html .= '

' . esc_html($subject) . ' Exam question

'; } if (!$q_html) $q_html = '

No questions available. Please contact the recruitment team.

'; ?>

Video Interview

Welcome,

Please review the questions below, record your responses, and upload your video.

Time remaining:

Interview Questions

Please answer all questions in one video, in order. Only one upload is allowed.

Please record your responses in English.

Walk us through your thinking as if you’re teaching a student — we’d love to see how you explain and communicate your ideas. Most candidates spend around 5–10 minutes per question, but there’s no strict time limit. Don’t worry about having perfect answers — we’re much more interested in how you think and how you teach.

Upload Interview Video

Supported formats: mp4, mov, avi, webm, wmv, zip, rar, 7z  |  Max 500MB

Click to select a video or archive file, or drag and drop here