(function ($) {
function fixElementorTimeField() {
const field = document.querySelector('[name="form_fields[field_0d60bf7]"]');
if (!field) return;
// Elementor already initialized flatpickr → destroy it
if (field._flatpickr) {
field._flatpickr.destroy();
}
// Re-init with AM/PM display
flatpickr(field, {
enableTime: true,
noCalendar: true,
time_24hr: false,
altInput: true,
altFormat: "h K", // ✅ 8 PM, 9 PM
dateFormat: "H:i", // backend safe
allowInput: true
});
}
// Elementor frontend hook
$(window).on('elementor/frontend/init', function () {
elementorFrontend.hooks.addAction(
'frontend/element_ready/form.default',
function () {
setTimeout(fixElementorTimeField, 300);
}
);
});
})(jQuery);
add_action( 'template_redirect', 'tiki_madman_force_login_before_checkout' );
function tiki_madman_force_login_before_checkout() {
if ( is_page( wc_get_page_id( 'checkout' ) ) && ! is_user_logged_in() ) {
// Optional notice (may not show if your login page doesn't support WooCommerce notices)
wc_add_notice( 'You must be logged in to checkout. Please login or register first.', 'error' );
// Redirect to your custom login page
wp_redirect( 'https://asonvincent.webworkscraft.com/?page_id=1097' );
exit;
}
}
// === 1. Output product name and quantity (normal) ===
// Move "Remove" button to the subtotal/price column (after price)
add_filter('woocommerce_checkout_cart_item_quantity', function ($quantity_html, $cart_item, $cart_item_key) {
if (is_checkout()) {
$product_name = $cart_item['data']->get_name();
$product_qty = $cart_item['quantity'];
return esc_html($product_name) . ' × ' . $product_qty . '';
}
return $quantity_html;
}, 10, 3);
// === 2. Add Remove Button After Price in Checkout Row ===
add_filter('woocommerce_cart_item_subtotal', function ($subtotal, $cart_item, $cart_item_key) {
if (is_checkout()) {
$remove_button = '';
return $subtotal . $remove_button;
}
return $subtotal;
}, 10, 3);
// === 3. Handle AJAX Request to Remove Cart Item ===
add_action('wp_ajax_remove_checkout_item', 'ajax_remove_checkout_item');
add_action('wp_ajax_nopriv_remove_checkout_item', 'ajax_remove_checkout_item');
function ajax_remove_checkout_item() {
if (empty($_POST['cart_key'])) {
wp_send_json_error('Missing cart key.');
}
$cart_key = sanitize_text_field($_POST['cart_key']);
if (WC()->cart->remove_cart_item($cart_key)) {
WC()->cart->calculate_totals();
wp_send_json_success('Item removed.');
} else {
wp_send_json_error('Failed to remove item.');
}
}
// === 4. Enqueue Inline JS for AJAX Remove ===
add_action('wp_enqueue_scripts', function () {
if (is_checkout()) {
wp_add_inline_script('woocommerce', <<
// Add Dashboard Widget
function custom_dashboard_widget() {
wp_add_dashboard_widget('custom_dashboard_widget', 'Manage PDF Shortcodes', 'custom_dashboard_widget_display');
}
add_action('wp_dashboard_setup', 'custom_dashboard_widget');
// Display Dashboard Widget Form
function custom_dashboard_widget_display() {
$pdf_shortcodes = get_option('custom_pdf_shortcodes', []);
// Handle form submission for adding/editing shortcodes
if (isset($_POST['submit_pdf_shortcode']) && check_admin_referer('pdf_shortcode_nonce')) {
$index = isset($_POST['index']) ? intval($_POST['index']) : -1;
$action = sanitize_text_field($_POST['pdf_action']);
$title = sanitize_text_field($_POST['pdf_title']);
$meta_field = sanitize_text_field($_POST['pdf_meta_field']);
$shortcode_name = $action . '_' . $meta_field;
$shortcode_data = ['action' => $action, 'title' => $title, 'meta_field' => $meta_field, 'shortcode_name' => $shortcode_name];
if ($index >= 0 && isset($pdf_shortcodes[$index])) {
$pdf_shortcodes[$index] = $shortcode_data;
} else {
array_unshift($pdf_shortcodes, $shortcode_data);
}
update_option('custom_pdf_shortcodes', $pdf_shortcodes);
}
// Handle remove requests
if (isset($_POST['remove_pdf_shortcode']) && check_admin_referer('pdf_shortcode_nonce')) {
$index = isset($_POST['index']) ? intval($_POST['index']) : -1;
if ($index >= 0 && isset($pdf_shortcodes[$index])) {
array_splice($pdf_shortcodes, $index, 1);
update_option('custom_pdf_shortcodes', $pdf_shortcodes);
}
}
// Handle edit requests
$edit_index = -1;
if (isset($_POST['edit_pdf_shortcode'])) {
$edit_index = isset($_POST['index']) ? intval($_POST['index']) : -1;
}
// Display form for adding a new shortcode or editing an existing one
$current_action = $edit_index >= 0 ? $pdf_shortcodes[$edit_index]['action'] : '';
$current_title = $edit_index >= 0 ? $pdf_shortcodes[$edit_index]['title'] : '';
$current_meta_field = $edit_index >= 0 ? $pdf_shortcodes[$edit_index]['meta_field'] : '';
custom_pdf_shortcode_form($current_action, $current_title, $current_meta_field, $edit_index);
// Display existing shortcodes
echo 'Existing Shortcodes:
';
echo ' ';
foreach ($pdf_shortcodes as $index => $shortcode) {
echo '- ';
echo ($index + 1) . '. Title: ' . esc_html($shortcode['title']) . ', Meta Field: ' . esc_html($shortcode['meta_field']) . '
';
echo 'Shortcode: [' . esc_attr($shortcode['shortcode_name']) . ']';
echo '';
echo ' ';
}
echo '
';
// Display CSS class information
echo '';
echo 'For styling, use the shortcode name as the CSS class.
';
echo 'Example: If the shortcode is [view_download_pdf], use .view_download_pdf as the CSS class.';
echo '';
}
// Form for adding/editing a shortcode
function custom_pdf_shortcode_form($action = '', $title = '', $meta_field = '', $index = -1) {
?>
$link_text";
}
/* Style for Download PDF link */
.Your Custom Class {
color: #ffffff;
font-size: 12px;
font-weight: 600;
text-decoration: none;
background-color: #1D5D7C;
border-radius: 8px;
padding: 10px 20px;
display: inline-block;
transition: background-color 0.3s ease;
}
.Your Custom Class:hover {
background-color: #C47A39;
color: #ffffff;
}
/* Style for View PDF link */
.Your Custom Class {
color: #ffffff;
font-size: 12px;
font-weight: 600;
text-decoration: none;
background-color: #C47A39;
border-radius: 08px;
padding: 10px 20px;
display: inline-block;
transition: background-color 0.3s ease;
}
.Your Custom Class:hover {
background-color: #1D5D7C;
color: #ffffff;
}
/**
* ===================================================================
* LCP & HEAD OPTIMIZATION SNIPPET
* ===================================================================
* 1. Preloads LCP elements (hero image or font).
* 2. Excludes the first 2 images from lazy-loading (helps LCP).
* 3. Removes unnecessary junk from wp_head (improves TTFB).
*/
// 1. Preload Your LCP Element
add_action('wp_head', 'my_preload_lcp_elements');
function my_preload_lcp_elements() {
// --- IF YOUR LCP IS AN IMAGE ---
// ❗ IMPORTANT: Change this to your real LCP image path
// You can use if ( is_front_page() ) { ... } to run only on the homepage.
echo '';
// --- IF YOUR LCP IS TEXT (H1, etc.) ---
// ❗ IMPORTANT: Uncomment (remove //) and change this if your LCP is text
// echo '';
}
// 2. Exclude Your LCP Image from Lazy Loading
add_filter('wp_omit_loading_attr_threshold', 'my_omit_lcp_lazy_load');
function my_omit_lcp_lazy_load($threshold) {
// This skips lazy-loading for the first 2 images on the page.
// 1 is the default. Change 2 to 1 if you only need to skip the first image.
return 2;
}
// 3. Remove Unnecessary "Junk" from wp_head
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');
remove_action('admin_print_scripts', 'print_emoji_detection_script');
remove_action('admin_print_styles', 'print_emoji_styles');
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'wp_shortlink_wp_head');
/**
* Add "Enable Minimum Quantity" toggle and "Minimum Quantity Value" field in Product Edit page
*/
add_action('woocommerce_product_options_general_product_data', function() {
echo '';
// Enable toggle
woocommerce_wp_checkbox([
'id' => '_enable_min_qty',
'label' => __('Enable Minimum Quantity', 'custom'),
'description' => __('Enable custom minimum quantity for this product.', 'custom'),
]);
// Minimum Quantity field
woocommerce_wp_text_input([
'id' => '_min_qty_value',
'label' => __('Minimum Quantity Value', 'custom'),
'description' => __('Set minimum quantity (e.g. 5, 10, etc.)', 'custom'),
'type' => 'number',
'custom_attributes' => [
'min' => '1',
'step' => '1'
]
]);
echo '';
});
/**
* Save the custom product fields
*/
add_action('woocommerce_process_product_meta', function($post_id) {
$enable_min_qty = isset($_POST['_enable_min_qty']) ? 'yes' : 'no';
update_post_meta($post_id, '_enable_min_qty', $enable_min_qty);
if (isset($_POST['_min_qty_value'])) {
update_post_meta($post_id, '_min_qty_value', absint($_POST['_min_qty_value']));
}
});
/**
* Set default quantity and increment steps on single product page
*/
add_filter('woocommerce_quantity_input_args', function($args, $product) {
$enable = get_post_meta($product->get_id(), '_enable_min_qty', true);
$min_qty = (int) get_post_meta($product->get_id(), '_min_qty_value', true);
if ($enable === 'yes' && $min_qty > 0) {
$args['input_value'] = $min_qty; // Default quantity
$args['min_value'] = $min_qty; // Minimum allowed
$args['step'] = $min_qty; // Increment step
}
return $args;
}, 10, 2);
/**
* Enforce minimum quantity in cart
*/
add_action('woocommerce_before_calculate_totals', function($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
foreach ($cart->get_cart() as $cart_item) {
$product_id = $cart_item['product_id'];
$enable = get_post_meta($product_id, '_enable_min_qty', true);
$min_qty = (int) get_post_meta($product_id, '_min_qty_value', true);
if ($enable === 'yes' && $min_qty > 0) {
$qty = $cart_item['quantity'];
$new_qty = max($min_qty, ceil($qty / $min_qty) * $min_qty);
if ($qty !== $new_qty) {
$cart_item['quantity'] = $new_qty;
}
}
}
});
/**
* Auto update price dynamically on frontend when quantity changes (AJAX)
*/
add_action('wp_footer', function() {
if (!is_product()) return;
?>
/**
* Add "Enable Minimum Quantity" toggle and "Minimum Quantity Value" field in Product Edit page
*/
add_action('woocommerce_product_options_general_product_data', function() {
echo '';
// Enable toggle
woocommerce_wp_checkbox([
'id' => '_enable_min_qty',
'label' => __('Enable Minimum Quantity', 'custom'),
'description' => __('Enable custom minimum quantity for this product.', 'custom'),
]);
// Minimum Quantity field
woocommerce_wp_text_input([
'id' => '_min_qty_value',
'label' => __('Minimum Quantity Value', 'custom'),
'description' => __('Set minimum quantity (e.g. 5, 10, etc.)', 'custom'),
'type' => 'number',
'custom_attributes' => [
'min' => '1',
'step' => '1'
]
]);
echo '';
});
/**
* Save the custom product fields
*/
add_action('woocommerce_process_product_meta', function($post_id) {
$enable_min_qty = isset($_POST['_enable_min_qty']) ? 'yes' : 'no';
update_post_meta($post_id, '_enable_min_qty', $enable_min_qty);
if (isset($_POST['_min_qty_value'])) {
update_post_meta($post_id, '_min_qty_value', absint($_POST['_min_qty_value']));
}
});
/**
* Set default quantity and increment steps on single product page
*/
add_filter('woocommerce_quantity_input_args', function($args, $product) {
$enable = get_post_meta($product->get_id(), '_enable_min_qty', true);
$min_qty = (int) get_post_meta($product->get_id(), '_min_qty_value', true);
if ($enable === 'yes' && $min_qty > 0) {
$args['input_value'] = $min_qty; // Default quantity
$args['min_value'] = $min_qty; // Minimum allowed
$args['step'] = $min_qty; // Increment step
}
return $args;
}, 10, 2);
/**
* Enforce minimum quantity in cart
*/
add_action('woocommerce_before_calculate_totals', function($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
foreach ($cart->get_cart() as $cart_item) {
$product_id = $cart_item['product_id'];
$enable = get_post_meta($product_id, '_enable_min_qty', true);
$min_qty = (int) get_post_meta($product_id, '_min_qty_value', true);
if ($enable === 'yes' && $min_qty > 0) {
$qty = $cart_item['quantity'];
$new_qty = max($min_qty, ceil($qty / $min_qty) * $min_qty);
if ($qty !== $new_qty) {
$cart_item['quantity'] = $new_qty;
}
}
}
});
/**
* Auto update price dynamically on frontend when quantity changes (AJAX)
*/
add_action('wp_footer', function() {
if (!is_product()) return;
?>
/**
* Add "Enable Minimum Quantity" toggle and "Minimum Quantity Value" field in Product Edit page
*/
add_action('woocommerce_product_options_general_product_data', function() {
echo '';
// Enable toggle
woocommerce_wp_checkbox([
'id' => '_enable_min_qty',
'label' => __('Enable Minimum Quantity', 'custom'),
'description' => __('Enable custom minimum quantity for this product.', 'custom'),
]);
// Minimum Quantity field
woocommerce_wp_text_input([
'id' => '_min_qty_value',
'label' => __('Minimum Quantity Value', 'custom'),
'description' => __('Set minimum quantity (e.g. 5, 10, etc.)', 'custom'),
'type' => 'number',
'custom_attributes' => [
'min' => '1',
'step' => '1'
]
]);
echo '';
});
/**
* Save the custom product fields
*/
add_action('woocommerce_process_product_meta', function($post_id) {
$enable_min_qty = isset($_POST['_enable_min_qty']) ? 'yes' : 'no';
update_post_meta($post_id, '_enable_min_qty', $enable_min_qty);
if (isset($_POST['_min_qty_value'])) {
update_post_meta($post_id, '_min_qty_value', absint($_POST['_min_qty_value']));
}
});
/**
* Set default quantity and increment steps on single product page
*/
add_filter('woocommerce_quantity_input_args', function($args, $product) {
$enable = get_post_meta($product->get_id(), '_enable_min_qty', true);
$min_qty = (int) get_post_meta($product->get_id(), '_min_qty_value', true);
if ($enable === 'yes' && $min_qty > 0) {
$args['input_value'] = $min_qty; // Default quantity
$args['min_value'] = $min_qty; // Minimum allowed
$args['step'] = $min_qty; // Increment step
}
return $args;
}, 10, 2);
/**
* Enforce minimum quantity in cart
*/
add_action('woocommerce_before_calculate_totals', function($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
foreach ($cart->get_cart() as $cart_item) {
$product_id = $cart_item['product_id'];
$enable = get_post_meta($product_id, '_enable_min_qty', true);
$min_qty = (int) get_post_meta($product_id, '_min_qty_value', true);
if ($enable === 'yes' && $min_qty > 0) {
$qty = $cart_item['quantity'];
$new_qty = max($min_qty, ceil($qty / $min_qty) * $min_qty);
if ($qty !== $new_qty) {
$cart_item['quantity'] = $new_qty;
}
}
}
});
/**
* Auto update price dynamically on frontend when quantity changes (AJAX)
*/
add_action('wp_footer', function() {
if (!is_product()) return;
?>
(function ($) {
function fixElementorTimeField() {
const field = document.querySelector('[name="form_fields[field_0d60bf7]"]');
if (!field) return;
// Elementor already initialized flatpickr → destroy it
if (field._flatpickr) {
field._flatpickr.destroy();
}
// Re-init with AM/PM display
flatpickr(field, {
enableTime: true,
noCalendar: true,
time_24hr: false,
altInput: true,
altFormat: "h K", // ✅ 8 PM, 9 PM
dateFormat: "H:i", // backend safe
allowInput: true
});
}
// Elementor frontend hook
$(window).on('elementor/frontend/init', function () {
elementorFrontend.hooks.addAction(
'frontend/element_ready/form.default',
function () {
setTimeout(fixElementorTimeField, 300);
}
);
});
})(jQuery);
(function ($) {
function fixElementorDateField() {
const field = document.querySelector('[name="form_fields[field_26149d6]"]');
if (!field) return;
// Destroy existing flatpickr (Elementor default)
if (field._flatpickr) {
field._flatpickr.destroy();
}
flatpickr(field, {
dateFormat: "Y-m-d", // backend format (keep safe)
altInput: true,
altFormat: "d M Y", // ✅ 20 Jan 2026
allowInput: true
});
}
$(window).on('elementor/frontend/init', function () {
elementorFrontend.hooks.addAction(
'frontend/element_ready/form.default',
function () {
setTimeout(fixElementorDateField, 300);
}
);
});
})(jQuery);
/**
* Plugin Name: MCQ Master System V46.0
* Description: Advanced MCQ Quiz System with Full Elementor Styling Controls
* Version: 46.0
* Author: MCQ Master
*/
if (!defined('ABSPATH')) exit;
/**
* MCQ Master System: Extreme Customization V46.0
* Features: Full Typography, Border, Margin, Padding, Hover Effects, Popup Input Styling
* Security: Nonce verification, sanitization, capability checks
*/
// ============================================================================
// 1. REGISTER CUSTOM POST TYPES & TAXONOMIES
// ============================================================================
add_action('init', function() {
// Quiz CPT
register_post_type('quiz', array(
'public' => true,
'label' => 'ALL MCQ',
'labels' => array(
'name' => 'ALL MCQ',
'singular_name' => 'MCQ Quiz',
'add_new' => 'ADD NEW MCQ',
'all_items' => 'ALL MCQ',
'edit_item' => 'Edit Quiz',
'view_item' => 'View Quiz'
),
'supports' => array('title'),
'menu_icon' => 'dashicons-welcome-learn-more',
'has_archive' => true,
'taxonomies' => array('mcq_category', 'mcq_tag'),
'capability_type' => 'post',
'query_var' => true,
'show_in_rest' => false,
));
// Taxonomies
register_taxonomy('mcq_category', 'quiz', array(
'label' => 'MCQ Category',
'hierarchical' => true,
'show_ui' => true,
'show_admin_column' => true,
'rewrite' => array('slug' => 'mcq-category')
));
register_taxonomy('mcq_tag', 'quiz', array(
'label' => 'MCQ Tags',
'hierarchical' => false,
'show_ui' => true,
'rewrite' => array('slug' => 'mcq-tag')
));
// Settings CPT
register_post_type('mcq_setting', array(
'public' => false,
'show_ui' => true,
'show_in_menu' => 'edit.php?post_type=quiz',
'label' => 'MCQ Settings',
'supports' => array('title'),
'capability_type' => 'post',
));
// Leads CPT
register_post_type('quiz_leads', array(
'public' => false,
'show_ui' => true,
'show_in_menu' => 'edit.php?post_type=quiz',
'label' => 'Student Leads',
'supports' => array('title'),
'capability_type' => 'post',
));
// Submissions CPT
register_post_type('quiz_submission', array(
'public' => false,
'show_ui' => true,
'show_in_menu' => 'edit.php?post_type=quiz',
'label' => 'Quiz Results',
'supports' => array('title'),
'capability_type' => 'post',
));
}, 1);
// ============================================================================
// 2. ADMIN COLUMNS & REPORTING UI
// ============================================================================
add_filter('manage_quiz_leads_posts_columns', function($cols) {
$new_cols = array();
$new_cols['cb'] = $cols['cb'];
$new_cols['title'] = 'Student Name';
$new_cols['lead_details'] = 'Contact & Info';
$new_cols['final_score'] = 'Quiz Score';
$new_cols['action_btn'] = 'Action';
$new_cols['date'] = $cols['date'];
return $new_cols;
});
add_action('manage_quiz_leads_posts_custom_column', function($col, $id) {
$info = get_post_meta($id, '_user_data', true) ?: array();
$sub_id = get_post_meta($id, '_related_submission_id', true);
if ($col === 'lead_details') {
foreach($info as $key => $val) {
if($key != 'name') {
echo ''.esc_html(ucfirst($key)).': '.esc_html($val).'
';
}
}
}
if ($col === 'final_score' && $sub_id) {
echo '' .
esc_html(get_post_meta($sub_id, '_submission_score', true)) . '';
}
if ($col === 'action_btn' && $sub_id) {
echo '';
}
}, 10, 2);
add_filter('manage_quiz_submission_posts_columns', function($cols) {
$new_cols = array();
$new_cols['cb'] = $cols['cb'];
$new_cols['title'] = 'Submission User';
$new_cols['score_display'] = 'Score';
$new_cols['action_inline'] = 'Detailed Report';
$new_cols['date'] = $cols['date'];
return $new_cols;
});
add_action('manage_quiz_submission_posts_custom_column', function($col, $id) {
if ($col === 'score_display') {
echo '' .
esc_html(get_post_meta($id, '_submission_score', true) ?: 'N/A') . '';
}
if ($col === 'action_inline') {
echo '';
}
}, 10, 2);
add_action('admin_footer', function() {
?>
×
Loading...
Quiz Analysis (Score: '.$score.')';
echo ' ';
echo 'Question User Answer Correct Answer Status ';
echo '';
if (is_array($details)) {
foreach($details as $d) {
$status_style = $d['ok'] ? 'color:#059669; font-weight:bold;' : 'color:#dc2626; font-weight:bold;';
$status_text = $d['ok'] ? '✔ Correct' : '✘ Wrong';
echo "";
echo "" . esc_html($d['q']) . " ";
echo "" . esc_html(strtoupper($d['u'])) . " ";
echo "" . esc_html(strtoupper($d['c'])) . " ";
echo "$status_text ";
echo " ";
}
} else {
echo "No data available ";
}
echo '
';
wp_die();
});
// ============================================================================
// 3. META BOXES & SETTINGS
// ============================================================================
add_action('add_meta_boxes', function() {
add_meta_box('quiz_settings_box', 'Quiz General Settings', 'render_quiz_settings_v46', 'quiz', 'normal', 'high');
add_meta_box('quiz_repeater_box', 'Question Builder', 'render_quiz_repeater_v46', 'quiz', 'normal', 'high');
add_meta_box('mcq_redir_box', 'Redirect URL Configuration', 'render_mcq_redir_v46', 'mcq_setting', 'normal', 'high');
});
function render_mcq_redir_v46($post) {
$redir_url = get_post_meta($post->ID, '_mcq_redirect_url', true);
wp_nonce_field('save_mcq_meta_v46', 'mcq_nonce_v46');
echo '';
echo '';
echo '';
echo 'After quiz completion, users will be redirected to this URL
';
echo '';
}
function render_quiz_settings_v46($post) {
$timer = get_post_meta($post->ID, '_quiz_timer', true) ?: 10;
$is_req = get_post_meta($post->ID, '_is_required', true);
$expiry = get_post_meta($post->ID, '_quiz_expiry', true);
$selected_setting = get_post_meta($post->ID, '_linked_setting_id', true);
$fields = get_post_meta($post->ID, '_enabled_fields', true) ?: array();
$settings_posts = get_posts(array('post_type' => 'mcq_setting', 'numberposts' => -1));
wp_nonce_field('save_mcq_meta_v46', 'mcq_nonce_v46');
?>
Leave empty for no expiry
Time before redirect after completion
Fields to collect before showing results
Users must answer all questions to submit
Select redirect configuration
ID, '_quiz_questions', true) ?: array();
?>
$q): ?>
Correct Answer:
sanitize_text_field($q['question']),
'a' => sanitize_text_field($q['a']),
'b' => sanitize_text_field($q['b']),
'c' => sanitize_text_field($q['c']),
'd' => sanitize_text_field($q['d']),
'correct' => in_array($q['correct'], ['a','b','c','d']) ? $q['correct'] : 'a'
);
}
update_post_meta($post_id, '_quiz_questions', $sanitized_questions);
}
// Save other fields with sanitization
if (isset($_POST['quiz_timer'])) {
update_post_meta($post_id, '_quiz_timer', absint($_POST['quiz_timer']));
}
if (isset($_POST['quiz_expiry'])) {
update_post_meta($post_id, '_quiz_expiry', sanitize_text_field($_POST['quiz_expiry']));
}
update_post_meta($post_id, '_is_required', isset($_POST['is_required']) ? 'yes' : 'no');
if (isset($_POST['enabled_fields']) && is_array($_POST['enabled_fields'])) {
$sanitized_fields = array_map('sanitize_text_field', $_POST['enabled_fields']);
update_post_meta($post_id, '_enabled_fields', $sanitized_fields);
} else {
delete_post_meta($post_id, '_enabled_fields');
}
if (isset($_POST['linked_setting_id'])) {
update_post_meta($post_id, '_linked_setting_id', absint($_POST['linked_setting_id']));
}
if (isset($_POST['mcq_redirect_url'])) {
update_post_meta($post_id, '_mcq_redirect_url', esc_url_raw($_POST['mcq_redirect_url']));
}
}, 10, 1);
// ============================================================================
// 5. ELEMENTOR WIDGET V46 - FULL STYLING CONTROLS
// ============================================================================
add_action('elementor/widgets/register', function($widgets_manager) {
class MCQ_Master_Widget_V46 extends \Elementor\Widget_Base {
public function get_name() {
return 'mcq_master_v46';
}
public function get_title() {
return 'MCQ Master V46 (Full Custom Styling)';
}
public function get_icon() {
return 'eicon-form-horizontal';
}
public function get_categories() {
return array('general');
}
protected function register_controls() {
// ------------------------------------------------------------------------
// CONTENT SECTION
// ------------------------------------------------------------------------
$this->start_controls_section('content', array(
'label' => 'Quiz Settings'
));
$quizzes = get_posts(array('post_type' => 'quiz', 'numberposts' => -1));
$options = array('' => 'Select Quiz');
foreach ($quizzes as $q) {
$options[$q->ID] = $q->post_title;
}
$this->add_control('qid', array(
'label' => 'Choose Quiz',
'type' => \Elementor\Controls_Manager::SELECT,
'options' => $options,
'description' => 'Select a quiz to display'
));
$this->end_controls_section();
// ------------------------------------------------------------------------
// TIMER STYLE SECTION
// ------------------------------------------------------------------------
$this->start_controls_section('style_timer', array(
'label' => 'Timer Style',
'tab' => \Elementor\Controls_Manager::TAB_STYLE
));
$this->add_group_control(
\Elementor\Group_Control_Typography::get_type(),
array(
'name' => 't_typo',
'selector' => '{{WRAPPER}} .live-expiry-timer',
)
);
$this->add_control('t_color', array(
'label' => 'Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .live-expiry-timer' => 'color: {{VALUE}};',
),
));
$this->add_control('t_bg', array(
'label' => 'Background Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .live-expiry-timer' => 'background-color: {{VALUE}};',
),
));
$this->add_group_control(
\Elementor\Group_Control_Border::get_type(),
array(
'name' => 't_border',
'selector' => '{{WRAPPER}} .live-expiry-timer',
)
);
$this->add_control('t_radius', array(
'label' => 'Border Radius',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .live-expiry-timer' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_responsive_control('t_margin', array(
'label' => 'Margin',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .live-expiry-timer' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_responsive_control('t_padding', array(
'label' => 'Padding',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .live-expiry-timer' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->end_controls_section();
// ------------------------------------------------------------------------
// QUESTION STYLE SECTION
// ------------------------------------------------------------------------
$this->start_controls_section('style_q', array(
'label' => 'Question Style',
'tab' => \Elementor\Controls_Manager::TAB_STYLE
));
$this->add_group_control(
\Elementor\Group_Control_Typography::get_type(),
array(
'name' => 'q_typo',
'selector' => '{{WRAPPER}} .mcq-q-text',
)
);
$this->add_control('q_color', array(
'label' => 'Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-q-text' => 'color: {{VALUE}};',
),
));
$this->add_control('q_bg', array(
'label' => 'Background Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .q-block' => 'background-color: {{VALUE}};',
),
));
$this->add_group_control(
\Elementor\Group_Control_Border::get_type(),
array(
'name' => 'q_border',
'selector' => '{{WRAPPER}} .q-block',
)
);
$this->add_control('q_radius', array(
'label' => 'Border Radius',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .q-block' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_group_control(
\Elementor\Group_Control_Box_Shadow::get_type(),
array(
'name' => 'q_shadow',
'selector' => '{{WRAPPER}} .q-block',
)
);
$this->add_responsive_control('q_margin', array(
'label' => 'Margin',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .q-block' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_responsive_control('q_padding', array(
'label' => 'Padding',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .q-block' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->end_controls_section();
// ------------------------------------------------------------------------
// OPTIONS STYLE SECTION
// ------------------------------------------------------------------------
$this->start_controls_section('style_opts', array(
'label' => 'Options (Answers)',
'tab' => \Elementor\Controls_Manager::TAB_STYLE
));
$this->add_group_control(
\Elementor\Group_Control_Typography::get_type(),
array(
'name' => 'a_typo',
'selector' => '{{WRAPPER}} .opt-text',
)
);
$this->start_controls_tabs('a_tabs');
// Normal State
$this->start_controls_tab('a_norm', array('label' => 'Normal'));
$this->add_control('a_bg', array(
'label' => 'Background Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-option-label' => 'background-color: {{VALUE}};',
),
));
$this->add_control('a_color', array(
'label' => 'Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .opt-text' => 'color: {{VALUE}};',
),
));
$this->add_control('a_border_color', array(
'label' => 'Border Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-option-label' => 'border-color: {{VALUE}};',
),
));
$this->end_controls_tab();
// Hover/Selected State
$this->start_controls_tab('a_hov', array('label' => 'Hover/Selected'));
$this->add_control('a_bg_h', array(
'label' => 'Background Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-option-label:hover, {{WRAPPER}} .mcq-option-label.is-selected' => 'background-color: {{VALUE}} !important;',
),
));
$this->add_control('a_color_h', array(
'label' => 'Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-option-label:hover .opt-text, {{WRAPPER}} .mcq-option-label.is-selected .opt-text' => 'color: {{VALUE}};',
),
));
$this->add_control('a_border_color_h', array(
'label' => 'Border Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-option-label:hover, {{WRAPPER}} .mcq-option-label.is-selected' => 'border-color: {{VALUE}} !important;',
),
));
$this->add_control('a_hov_anim', array(
'label' => 'Hover Animation',
'type' => \Elementor\Controls_Manager::HOVER_ANIMATION,
));
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_group_control(
\Elementor\Group_Control_Border::get_type(),
array(
'name' => 'a_border',
'selector' => '{{WRAPPER}} .mcq-option-label',
)
);
$this->add_control('a_radius', array(
'label' => 'Border Radius',
'type' => \Elementor\Controls_Manager::SLIDER,
'size_units' => array('px', '%'),
'range' => array(
'px' => array('min' => 0, 'max' => 50),
'%' => array('min' => 0, 'max' => 50),
),
'selectors' => array(
'{{WRAPPER}} .mcq-option-label' => 'border-radius: {{SIZE}}{{UNIT}};',
),
));
$this->add_responsive_control('a_padding', array(
'label' => 'Padding',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .mcq-option-label' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_responsive_control('a_gap', array(
'label' => 'Gap Between Options',
'type' => \Elementor\Controls_Manager::SLIDER,
'size_units' => array('px'),
'range' => array(
'px' => array('min' => 0, 'max' => 50),
),
'selectors' => array(
'{{WRAPPER}} .mcq-grid' => 'gap: {{SIZE}}{{UNIT}};',
),
));
$this->end_controls_section();
// ------------------------------------------------------------------------
// MAIN SUBMIT BUTTON STYLE
// ------------------------------------------------------------------------
$this->start_controls_section('style_btn', array(
'label' => 'Main Submit Button',
'tab' => \Elementor\Controls_Manager::TAB_STYLE
));
$this->add_group_control(
\Elementor\Group_Control_Typography::get_type(),
array(
'name' => 'btn_typo',
'selector' => '{{WRAPPER}} .mcq-submit-btn',
)
);
$this->start_controls_tabs('btn_tabs');
// Normal State
$this->start_controls_tab('btn_norm', array('label' => 'Normal'));
$this->add_control('btn_bg', array(
'label' => 'Background Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-submit-btn' => 'background-color: {{VALUE}};',
),
));
$this->add_control('btn_color', array(
'label' => 'Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-submit-btn' => 'color: {{VALUE}};',
),
));
$this->end_controls_tab();
// Hover State
$this->start_controls_tab('btn_hov', array('label' => 'Hover'));
$this->add_control('btn_bg_h', array(
'label' => 'Background Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-submit-btn:hover' => 'background-color: {{VALUE}};',
),
));
$this->add_control('btn_color_h', array(
'label' => 'Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-submit-btn:hover' => 'color: {{VALUE}};',
),
));
$this->add_control('btn_hov_anim', array(
'label' => 'Hover Animation',
'type' => \Elementor\Controls_Manager::HOVER_ANIMATION,
));
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_group_control(
\Elementor\Group_Control_Border::get_type(),
array(
'name' => 'btn_border',
'selector' => '{{WRAPPER}} .mcq-submit-btn',
)
);
$this->add_control('btn_radius', array(
'label' => 'Border Radius',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .mcq-submit-btn' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_group_control(
\Elementor\Group_Control_Box_Shadow::get_type(),
array(
'name' => 'btn_shadow',
'selector' => '{{WRAPPER}} .mcq-submit-btn',
)
);
$this->add_responsive_control('btn_margin', array(
'label' => 'Margin',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .mcq-submit-btn' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_responsive_control('btn_padding', array(
'label' => 'Padding',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .mcq-submit-btn' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->end_controls_section();
// ------------------------------------------------------------------------
// REGISTRATION POPUP STYLE
// ------------------------------------------------------------------------
$this->start_controls_section('style_popup', array(
'label' => 'Registration Popup',
'tab' => \Elementor\Controls_Manager::TAB_STYLE
));
// Popup Background
$this->add_control('pop_heading', array(
'label' => 'Popup Background',
'type' => \Elementor\Controls_Manager::HEADING,
));
$this->add_control('pop_bg', array(
'label' => 'Background Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner' => 'background-color: {{VALUE}};',
),
));
$this->add_control('pop_overlay_bg', array(
'label' => 'Overlay Background',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .lead-modal' => 'background-color: {{VALUE}};',
),
));
// Input Fields
$this->add_control('pop_input_heading', array(
'label' => 'Input Fields',
'type' => \Elementor\Controls_Manager::HEADING,
'separator' => 'before',
));
$this->add_group_control(
\Elementor\Group_Control_Typography::get_type(),
array(
'name' => 'pop_in_typo',
'selector' => '{{WRAPPER}} .mcq-popup-inner input',
)
);
$this->start_controls_tabs('pop_in_tabs');
// Normal State
$this->start_controls_tab('pop_in_norm', array('label' => 'Normal'));
$this->add_control('pop_in_bg', array(
'label' => 'Input Background',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner input' => 'background-color: {{VALUE}};',
),
));
$this->add_control('pop_in_color', array(
'label' => 'Input Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner input' => 'color: {{VALUE}};',
),
));
$this->add_control('pop_in_border_color', array(
'label' => 'Border Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner input' => 'border-color: {{VALUE}};',
),
));
$this->end_controls_tab();
// Focus State
$this->start_controls_tab('pop_in_focus', array('label' => 'Focus'));
$this->add_control('pop_in_focus_bg', array(
'label' => 'Input Background',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner input:focus' => 'background-color: {{VALUE}};',
),
));
$this->add_control('pop_in_focus_color', array(
'label' => 'Input Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner input:focus' => 'color: {{VALUE}};',
),
));
$this->add_control('pop_in_focus_border', array(
'label' => 'Focus Border Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner input:focus' => 'border-color: {{VALUE}}; box-shadow: 0 0 0 3px {{VALUE}}33;',
),
));
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_group_control(
\Elementor\Group_Control_Border::get_type(),
array(
'name' => 'pop_in_border',
'selector' => '{{WRAPPER}} .mcq-popup-inner input',
)
);
$this->add_control('pop_in_radius', array(
'label' => 'Border Radius',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner input' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_responsive_control('pop_in_padding', array(
'label' => 'Input Padding',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .mcq-popup-inner input' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
// Popup Submit Button
$this->add_control('pop_btn_heading', array(
'label' => 'Popup Submit Button',
'type' => \Elementor\Controls_Manager::HEADING,
'separator' => 'before',
));
$this->add_group_control(
\Elementor\Group_Control_Typography::get_type(),
array(
'name' => 'pop_btn_typo',
'selector' => '{{WRAPPER}} .pop-submit-btn',
)
);
$this->add_control('pop_btn_bg', array(
'label' => 'Button Background',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .pop-submit-btn' => 'background-color: {{VALUE}};',
),
));
$this->add_control('pop_btn_color', array(
'label' => 'Button Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .pop-submit-btn' => 'color: {{VALUE}};',
),
));
$this->add_group_control(
\Elementor\Group_Control_Border::get_type(),
array(
'name' => 'pop_btn_border',
'selector' => '{{WRAPPER}} .pop-submit-btn',
)
);
$this->add_control('pop_btn_radius', array(
'label' => 'Border Radius',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .pop-submit-btn' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_responsive_control('pop_btn_padding', array(
'label' => 'Button Padding',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .pop-submit-btn' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->end_controls_section();
// ------------------------------------------------------------------------
// SUCCESS MESSAGE STYLE
// ------------------------------------------------------------------------
$this->start_controls_section('style_success', array(
'label' => 'Success Message',
'tab' => \Elementor\Controls_Manager::TAB_STYLE
));
$this->add_control('success_bg', array(
'label' => 'Background Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .inline-success-box' => 'background-color: {{VALUE}};',
),
));
$this->add_control('success_border_color', array(
'label' => 'Border Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .inline-success-box' => 'border-color: {{VALUE}};',
),
));
$this->add_control('success_text_color', array(
'label' => 'Text Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .inline-success-box' => 'color: {{VALUE}};',
),
));
$this->add_control('success_timer_color', array(
'label' => 'Timer Color',
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => array(
'{{WRAPPER}} .inline-success-box .redir-timer' => 'color: {{VALUE}};',
),
));
$this->add_responsive_control('success_padding', array(
'label' => 'Padding',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .inline-success-box' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->add_control('success_radius', array(
'label' => 'Border Radius',
'type' => \Elementor\Controls_Manager::DIMENSIONS,
'size_units' => array('px', '%'),
'selectors' => array(
'{{WRAPPER}} .inline-success-box' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
),
));
$this->end_controls_section();
}
protected function render() {
$settings = $this->get_settings_for_display();
$qid = intval($settings['qid']);
if (!$qid) {
echo '';
echo 'Please select a quiz in the widget settings.';
echo '';
return;
}
// Get quiz data
$quiz_post = get_post($qid);
if (!$quiz_post || $quiz_post->post_type !== 'quiz') {
echo '';
echo 'Invalid quiz selected.';
echo '';
return;
}
// Get expiry timestamp
$expiry = get_post_meta($qid, '_quiz_expiry', true);
$expiry_ts = $expiry ? strtotime($expiry) : 0;
// Get animation classes
$btn_anim = !empty($settings['btn_hov_anim']) ? 'elementor-animation-' . $settings['btn_hov_anim'] : '';
$opt_anim = !empty($settings['a_hov_anim']) ? 'elementor-animation-' . $settings['a_hov_anim'] : '';
$widget_id = $this->get_id();
// Inline styles for base structure
echo "";
// Widget wrapper
echo "";
// Timer display
if ($expiry_ts > 0) {
echo "Loading Timer...";
}
// MCQ content area
echo "";
echo "";
echo "";
echo "";
// JavaScript to load MCQ
?>
register(new MCQ_Master_Widget_V46());
});
// ============================================================================
// 6. AJAX HANDLERS - LOAD & SUBMIT
// ============================================================================
add_action('wp_ajax_load_mcq_v46', 'handle_load_mcq_v46');
add_action('wp_ajax_nopriv_load_mcq_v46', 'handle_load_mcq_v46');
function handle_load_mcq_v46() {
$qid = intval($_POST['qid']);
$widget_id = sanitize_text_field($_POST['widget_id']);
// Validate quiz
$quiz_post = get_post($qid);
if (!$quiz_post || $quiz_post->post_type !== 'quiz') {
wp_send_json_error('Invalid quiz');
}
// Check expiry
$expiry = get_post_meta($qid, '_quiz_expiry', true);
if ($expiry && strtotime($expiry) < time()) {
wp_send_json_error(array(
'html' => 'This quiz has expired.'
));
}
$questions = get_post_meta($qid, '_quiz_questions', true);
$fields = get_post_meta($qid, '_enabled_fields', true);
$is_required = get_post_meta($qid, '_is_required', true);
if (empty($questions) || !is_array($questions)) {
wp_send_json_error(array(
'html' => 'No questions found in this quiz.'
));
}
ob_start();
?>
Identity Information
Please provide your details to see results.
Congratulations!
You have successfully completed the test.
Redirecting in 0 seconds.
ob_get_clean()));
}
add_action('wp_ajax_submit_mcq_v46', 'handle_submit_mcq_v46');
add_action('wp_ajax_nopriv_submit_mcq_v46', 'handle_submit_mcq_v46');
function handle_submit_mcq_v46() {
// Security: Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'mcq_submit_' . $_POST['qid'])) {
wp_send_json_error('Security validation failed');
}
$qid = intval($_POST['qid']);
$ans = isset($_POST['ans']) ? $_POST['ans'] : array();
$info = isset($_POST['info']) ? $_POST['info'] : array();
// Validate quiz
$quiz_post = get_post($qid);
if (!$quiz_post || $quiz_post->post_type !== 'quiz') {
wp_send_json_error('Invalid quiz');
}
// Check expiry (server-side validation)
$expiry = get_post_meta($qid, '_quiz_expiry', true);
if ($expiry && strtotime($expiry) < time()) {
wp_send_json_error('Quiz has expired');
}
$questions = get_post_meta($qid, '_quiz_questions', true);
$score = 0;
$details = array();
if (!is_array($questions)) {
wp_send_json_error('No questions found');
}
foreach($questions as $i => $q) {
$user_answer = isset($ans[$i]) ? sanitize_text_field($ans[$i]) : 'N/A';
$is_correct = ($user_answer === $q['correct']);
if($is_correct) $score++;
$details[] = array(
'q' => sanitize_text_field($q['question']),
'u' => $user_answer,
'c' => sanitize_text_field($q['correct']),
'ok' => $is_correct
);
}
// Save submission
$submission_title = !empty($info['name']) ? 'Result: ' . sanitize_text_field($info['name']) : 'Result: Guest';
$sid = wp_insert_post(array(
'post_type' => 'quiz_submission',
'post_title' => $submission_title,
'post_status' => 'publish',
'post_author' => get_current_user_id()
));
if ($sid) {
update_post_meta($sid, '_submission_details_array', $details);
update_post_meta($sid, '_submission_score', "$score / " . count($questions));
update_post_meta($sid, '_submission_quiz_id', $qid);
}
// Save lead info if provided
if (!empty($info)) {
$lead_title = sanitize_text_field($info['name']);
$lid = wp_insert_post(array(
'post_type' => 'quiz_leads',
'post_title' => $lead_title,
'post_status' => 'publish',
'post_author' => get_current_user_id()
));
if ($lid) {
// Sanitize all info fields
$sanitized_info = array_map('sanitize_text_field', $info);
update_post_meta($lid, '_user_data', $sanitized_info);
update_post_meta($lid, '_related_submission_id', $sid);
update_post_meta($lid, '_quiz_id', $qid);
}
}
// Get redirect settings
$timer = absint(get_post_meta($qid, '_quiz_timer', true)) ?: 5;
$setting_id = get_post_meta($qid, '_linked_setting_id', true);
$redirect_url = home_url('/');
if ($setting_id) {
$custom_url = get_post_meta($setting_id, '_mcq_redirect_url', true);
if (!empty($custom_url)) {
$redirect_url = esc_url_raw($custom_url);
}
}
wp_send_json_success(array(
'score' => $score,
'total' => count($questions),
'timer' => $timer,
'redir' => wp_sanitize_redirect($redirect_url),
'submission_id' => $sid
));
}
// ============================================================================
// 7. FRONTEND JAVASCRIPT ENGINE
// ============================================================================
add_action('wp_footer', function() {
?>
'mcq_setting', 'numberposts' => 1));
if (empty($settings)) {
$default_setting_id = wp_insert_post(array(
'post_type' => 'mcq_setting',
'post_title' => 'Default Redirect',
'post_status' => 'publish'
));
update_post_meta($default_setting_id, '_mcq_redirect_url', home_url());
}
});
register_deactivation_hook(__FILE__, function() {
flush_rewrite_rules();
});
/* ডেস্কটপ ও ল্যাপটপের জন্য (1025px এর বেশি) */
@media only screen and (min-width: 1025px) {
.elementor-menu-cart__container {
position: fixed !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
right: auto !important;
width: 80% !important;
max-width: 600px !important;
height: auto !important;
max-height: 90vh !important;
overflow-y: auto !important;
z-index: 99999 !important;
}
}
/* ট্যাবলেটের জন্য (768px থেকে 1024px) */
@media only screen and (min-width: 768px) and (max-width: 1024px) {
.elementor-menu-cart__container {
position: fixed !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
right: auto !important;
width: 60% !important;
max-width: 500px !important;
height: auto !important;
max-height: 90vh !important;
overflow-y: auto !important;
z-index: 99999 !important;
}
}
/* মোবাইলের জন্য (767px এর কম) */
@media only screen and (max-width: 767px) {
.elementor-menu-cart__container {
position: fixed !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
right: auto !important;
width: 90% !important;
max-width: 400px !important;
height: auto !important;
max-height: 85vh !important;
overflow-y: auto !important;
z-index: 99999 !important;
}
}