File: /var/www/html/CW-techs/wp-content/themes/cw-techs/functions.php
<?php
require_once get_template_directory() . '/templates/country-codes.php';
function add_data_attribute_to_slick_script($tag, $handle)
{
if ($handle === 'slick-js') {
// Modify the script tag to include data-id
$tag = '<script src="https://ywndev-api.kornerstonemedia.com/api/v1/ad-client.js" data-id="eiDaHmBJFpD2"></script>';
}
return $tag;
}
add_filter('script_loader_tag', 'add_data_attribute_to_slick_script', 10, 2);
function enqueue_custom_shop_assets()
{
// Load on shop, category, or tag archive
if (is_shop() || is_product_category() || is_product_tag()) {
wp_enqueue_style('style-css', get_template_directory_uri() . '/css/style.css');
wp_enqueue_style('product-list-css', get_template_directory_uri() . '/css/product-list.css');
}
if (is_product()) {
wp_enqueue_style('product-details-css', get_template_directory_uri() . '/css/product-details.css');
}
if (is_page('signup')) {
wp_enqueue_style('signup-css', get_template_directory_uri() . '/css/register.css');
}
if (is_page('login') || is_page('forgot-password') || is_page('password-reset')) {
wp_enqueue_style('login-css', get_template_directory_uri() . '/css/login.css');
}
if (is_account_page()) {
wp_enqueue_style('custom-account-css', get_stylesheet_directory_uri() . '/css/account.css');
}
if (is_page('cart')) {
wp_enqueue_style('custom-cart-css', get_stylesheet_directory_uri() . '/css/cart.css');
}
if (is_page('checkout') || is_wc_endpoint_url('order-received')) {
wp_enqueue_style('custom-chekout-css', get_stylesheet_directory_uri() . '/css/chekout.css');
}
if (is_page('favorites')) {
wp_enqueue_style('custom-favorites-css', get_stylesheet_directory_uri() . '/css/favorites.css');
}
wp_enqueue_style('custom-favorites-css', get_stylesheet_directory_uri() . '/css/modal.css');
if (is_page('contact-us')) {
wp_enqueue_style('custom-contact-css', get_stylesheet_directory_uri() . '/css/contact.css');
}
// Toastr CSS
wp_enqueue_style(
'toastr-css',
'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css',
[],
null
);
wp_deregister_script('jquery');
wp_register_script(
'jquery',
'https://code.jquery.com/jquery-3.6.0.min.js',
false,
'3.6.0',
true // Load in footer
);
wp_enqueue_script('jquery'); // Enqueues WP's jQuery
wp_enqueue_script('bootstrap-js', 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.bundle.min.js', ['jquery'], null, true);
wp_enqueue_script('slick-js', 'https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js', ['jquery'], null, true);
// wp_enqueue_script('slick-js', 'https://ywndev-api.kornerstonemedia.com/api/v1/ad-client.js', data-id="YvGLXVg91IBk" ['jquery'], null, true);
wp_enqueue_script('jquery-ui', 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js', ['jquery'], null, true);
wp_enqueue_script('main-script', get_template_directory_uri() . '/js/main.js', ['jquery'], null, true);
wp_enqueue_script('custom-ajax-script', get_template_directory_uri() . '/js/custom-ajax.js', ['jquery'], null, true);
wp_enqueue_script('account-ajax-script', get_template_directory_uri() . '/js/account.js', ['jquery'], null, true);
// Toastr JS
wp_enqueue_script(
'toastr-js',
'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js',
['jquery'],
null,
true
);
// Pass the admin AJAX URL to the script
wp_localize_script('custom-ajax-script', 'ajax_obj', [
'ajaxurl' => admin_url('admin-ajax.php'),
'is_logged_in' => is_user_logged_in(),
'redirect_url' => home_url()
]);
}
function enqueue_password_toggle_script()
{
wp_enqueue_script(
'password-toggle-js',
get_stylesheet_directory_uri() . '/js/password-toggle.js',
array('jquery'),
null,
true
);
// Pass PHP variables to JS
wp_localize_script(
'password-toggle-js',
'passwordToggleVars',
array(
'eyeOpen' => get_stylesheet_directory_uri() . '/img/eye_ico_open.svg',
'eyeClose' => get_stylesheet_directory_uri() . '/img/eye-ico.png',
)
);
}
add_action('wp_enqueue_scripts', 'enqueue_password_toggle_script');
add_action('wp_enqueue_scripts', 'enqueue_custom_shop_assets');
function cw_enqueue_scripts()
{
if (is_product()) {
// wp_enqueue_script('jquery');
wp_enqueue_script('wc-add-to-cart'); // WooCommerce core
wp_enqueue_script('woocommerce'); // Optional but helpful
}
}
add_action('wp_enqueue_scripts', 'cw_enqueue_scripts');
function cw_enqueue_parsley_validation()
{
// Load Parsley CSS (optional but good for styling)
wp_enqueue_style(
'parsley-css',
'https://cdn.jsdelivr.net/npm/parsleyjs/src/parsley.css',
[],
null
);
// Load Parsley JS
wp_enqueue_script(
'parsley-js',
'https://cdn.jsdelivr.net/npm/parsleyjs',
['jquery'], // depends on jQuery
null,
true
);
}
add_action('wp_enqueue_scripts', 'cw_enqueue_parsley_validation');
add_action('wp_enqueue_scripts', 'custom_order_success_script');
function custom_order_success_script()
{
// Check if it's order received page
if (is_order_received_page()) {
wp_enqueue_script('custom-checkout-success', get_template_directory_uri() . '/js/checkout-success.js', array('jquery'), '1.0', true);
// Pass order ID to JS
$order_id = absint(get_query_var('order-received'));
wp_localize_script('custom-checkout-success', 'order_success_vars', array(
'order_id' => $order_id,
'show_modal' => true,
));
}
}
add_action('after_setup_theme', function () {
add_theme_support('woocommerce');
});
// // ✅ Force product category base to be empty (clean URLs)
// add_filter( 'woocommerce_permalinks', function( $permalinks ) {
// $permalinks['category_base'] = '';
// return $permalinks;
// });
// // ✅ Remove "/product-category" from generated term links
// add_filter( 'term_link', function( $url, $term, $taxonomy ) {
// if ( $taxonomy === 'product_cat' ) {
// return str_replace( '/product-category', '', $url );
// }
// return $url;
// }, 10, 3 );
// // ✅ Add rewrite rules to support clean category and subcategory URLs
// add_action( 'init', function() {
// // Nested categories
// add_rewrite_rule(
// '^([^/]+)/([^/]+)/?$',
// 'index.php?product_cat=$matches[1]/$matches[2]',
// 'top'
// );
// // Top-level categories
// add_rewrite_rule(
// '^([^/]+)/?$',
// 'index.php?product_cat=$matches[1]',
// 'top'
// );
// });
// add_action( 'init', function() {
// flush_rewrite_rules();
// }, 99 );
add_action('wp_ajax_nopriv_register_user', 'handle_user_registration');
add_action('wp_ajax_register_user', 'handle_user_registration');
function handle_user_registration()
{
// Sanitize and validate input
$first_name = sanitize_text_field($_POST['first_name']);
$last_name = sanitize_text_field($_POST['last_name']);
$email = sanitize_email($_POST['email']);
$country_code = sanitize_text_field($_POST['country_code']);
$phone = sanitize_text_field($_POST['phone']);
$password = sanitize_text_field($_POST['password']);
$confirm_password = sanitize_text_field($_POST['confirm_password']);
$terms = isset($_POST['terms']) ? true : false;
// Validate email
if (!is_email($email)) {
wp_send_json_error(['message' => 'Invalid email address.']);
}
// Check if email already exists
if (email_exists($email)) {
wp_send_json_success(['message' => 'If the provided email was not already registered, you have been successfully registered, and a verification email has been sent.']);
}
// Check password match
if ($password !== $confirm_password) {
wp_send_json_error(['message' => 'Passwords do not match.']);
}
// Generate username
$user_login = strstr($email, '@', true); // Part before @ in email
$user_nicename = sanitize_title($first_name . '-' . $last_name);
$display_name = trim($first_name . ' ' . $last_name);
$phone_no = trim($country_code . ' ' . $phone);
// Prepare user data
$user_data = [
'user_login' => $user_login,
'user_pass' => $password,
'user_email' => $email,
'first_name' => $first_name,
'last_name' => $last_name,
'user_nicename' => $user_nicename,
'display_name' => $display_name,
// 'email_verified' => 0,
];
// Insert user into database
$user_id = wp_insert_user($user_data);
// Handle errors during user creation
if (is_wp_error($user_id)) {
wp_send_json_error(['message' => $user_id->get_error_message()]);
}
update_user_meta($user_id, 'phone', $phone);
update_user_meta($user_id, 'email_verified', 0);
update_user_meta($user_id, 'phone_country_code', $country_code);
// Email Verification Logic
$verification_code = wp_generate_password(20, false); // Generate a secure random code
update_user_meta($user_id, 'email_verification_code', $verification_code);
$token = base64_encode(json_encode([
'user_id' => $user_id,
'code' => $verification_code,
'timestamp' => time(),
]));
// Generate verification link
$verification_link = add_query_arg('token', $token, site_url('/email-verification/'));
$base_url = get_template_directory_uri();
// Load the email template
$template_path = __DIR__ . '/emails/email-verification.php';
if (!file_exists($template_path)) {
wp_send_json_error(['message' => 'Email template not found.']);
}
$email_body = file_get_contents($template_path);
// Replace placeholders with dynamic data
$email_body = str_replace('{{verification_link}}', esc_url($verification_link), $email_body);
$email_body = str_replace('{{display_name}}', esc_html($display_name), $email_body);
$email_body = str_replace('{{base_url}}', $base_url, $email_body);
// Send email
$subject = "Verify Your Email Address";
$headers = ['Content-Type: text/html; charset=UTF-8'];
if (!wp_mail($email, $subject, $email_body, $headers)) {
wp_send_json_error(['message' => 'Failed to send verification email.']);
}
$admin_email = get_option('admin_email');
$admin_subject = "New User Registration: " . $display_name;
$admin_panel_url = admin_url('user-edit.php?user_id=' . $user_id);
$user_info = get_userdata($user_id);
$registered_date = $user_info->user_registered;
$registered_date_formatted = date('F j, Y \a\t g:i A', strtotime($registered_date));
// Load the email template
$template_path = __DIR__ . '/emails/admin-new-user.php';
if (!file_exists($template_path)) {
wp_send_json_error(['message' => 'Admin email template not found.']);
}
$admin_message = file_get_contents($template_path);
// Replace placeholders with dynamic data
$admin_message = str_replace('{{display_name}}', esc_html($display_name), $admin_message);
$admin_message = str_replace('{{email}}', esc_html($email), $admin_message);
$admin_message = str_replace('{{user_login}}', esc_html($user_login), $admin_message);
$admin_message = str_replace('{{phone_no}}', esc_html($phone_no), $admin_message);
$admin_message = str_replace('{{admin_panel_url}}', esc_url($admin_panel_url), $admin_message);
$admin_message = str_replace('{{base_url}}', $base_url, $admin_message);
$admin_message = str_replace('{{registered_date}}', esc_html($registered_date_formatted), $admin_message);
// Send the email
wp_mail($admin_email, $admin_subject, $admin_message, $headers);
// Send success response
wp_send_json_success(['message' => 'If the provided email was not already registered, you have been successfully registered, and a verification email has been sent.']);
}
//email verification
add_action('init', 'verify_user_email');
function verify_user_email()
{
// Check if the verification parameters are present
if (isset($_GET['token']) && !empty($_GET['token'])) {
$token = sanitize_text_field($_GET['token']);
$data = json_decode(base64_decode($token), true);
// Validate the token structure and verify the code
if (isset($data['user_id'], $data['code']) && valid_code($data['user_id'], $data['code'])) {
$user_id = intval($data['user_id']);
$code = sanitize_text_field($data['code']);
// Retrieve user using meta key and value
$user_query = new WP_User_Query([
'meta_key' => 'email_verification_code',
'meta_value' => $code,
]);
update_user_meta($user_id, 'email_verified', 1);
if (!empty($user_query->results)) {
$user = $user_query->results[0];
// Clean up meta data and mark email as verified
delete_user_meta($user->ID, 'email_verification_code');
update_user_meta($user->ID, 'email_verified', true);
// Redirect to login page with success message
wp_redirect(site_url('/login?verified=success'));
exit;
}
}
// Invalid or expired token
wp_die("Invalid or expired verification link.");
}
}
// Helper function to validate the code against the user ID
function valid_code($user_id, $code)
{
$stored_code = get_user_meta($user_id, 'email_verification_code', true);
return !empty($stored_code) && hash_equals($stored_code, $code);
}
//login
add_action('wp_ajax_nopriv_login_user', 'login_user');
add_action('wp_ajax_login_user', 'login_user');
function login_user()
{
// Verify Nonce
// if (!isset($_POST['security']) || !check_ajax_referer('login-user-nonce', 'security', false)) {
// wp_send_json_error(['message' => 'Security check failed.']);
// }
// Sanitize Input
$email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
$password = isset($_POST['password']) ? sanitize_text_field($_POST['password']) : '';
// Validate Inputs
if (empty($email) || empty($password)) {
wp_send_json_error(['message' => 'Email and password are required.']);
}
// Get User by Email
$user = get_user_by('email', $email);
if (!$user || !wp_check_password($password, $user->user_pass, $user->ID)) {
wp_send_json_error(['message' => 'Invalid email or password']);
}
// Check if User Email is Verified
$email_verified = get_user_meta($user->ID, 'email_verified', true);
if ($email_verified != '1') { // Ensure strict check for verification
wp_send_json_error(['message' => 'Email verification is required before logging in']);
}
// Prepare Credentials for Login
$credentials = [
'user_login' => $user->user_login,
'user_password' => $password,
'remember' => !empty($_POST['remember']) && $_POST['remember'] === 'true',
];
// Attempt Login
$login_user = wp_signon($credentials, false);
// Handle Login Errors or Success
if (is_wp_error($login_user)) {
$error_message = $login_user->get_error_message();
$filtered_message = preg_replace('/<a.*?Lost your password\?.*?<\/a>/', '', $error_message);
$filtered_message = strip_tags(trim($filtered_message)); // Remove HTML tags and trim spaces
// wp_send_json_error(['message' => $filtered_message]);
}
// Call additional login function (if required)
if (function_exists('main_site_login')) {
main_site_login($user->ID);
}
// Send Success Response
wp_send_json_success([
'message' => 'Login successful!',
'redirect' => site_url('/my-account'), // Ensure proper redirect path
]);
}
// Handle add/remove favorites
add_action('wp_ajax_toggle_favorite', 'toggle_favorite_callback');
function toggle_favorite_callback()
{
// check_ajax_referer('favorites_nonce', 'nonce');
if (!is_user_logged_in()) {
wp_send_json_error('You must be logged in.');
}
$user_id = get_current_user_id();
$product_id = intval($_POST['product_id']);
$favorites = get_user_meta($user_id, 'favorite_products', true);
if (!is_array($favorites)) {
$favorites = [];
}
if (in_array($product_id, $favorites)) {
// Remove from favorites
$favorites = array_diff($favorites, [$product_id]);
$action = 'removed';
} else {
// Add to favorites
$favorites[] = $product_id;
$action = 'added';
}
update_user_meta($user_id, 'favorite_products', $favorites);
wp_send_json_success(['action' => $action]);
}
add_action('wp_ajax_move_to_cart', 'move_to_cart_callback');
function move_to_cart_callback()
{
if (!is_user_logged_in()) {
wp_send_json_error('You must be logged in.');
}
$product_id = intval($_POST['product_id']);
if (!wc_get_product($product_id)) {
wp_send_json_error('Invalid product.');
}
$cart = WC()->cart;
if (!$cart) {
wp_send_json_error('Cart not found.');
}
$cart->add_to_cart($product_id);
wp_send_json_success();
}
add_action('wp_ajax_change_user_password', 'handle_password_change');
function handle_password_change()
{
if (!is_user_logged_in()) {
wp_send_json_error(['message' => 'Unauthorized.']);
}
$current_password = $_POST['current_password'];
$new_password = $_POST['new_password'];
$user_id = get_current_user_id();
$user = get_userdata($user_id);
if (!wp_check_password($current_password, $user->user_pass, $user_id)) {
wp_send_json_error(['message' => 'Current password is incorrect']);
}
wp_set_password($new_password, $user_id);
wp_logout();
// wp_send_json_success(['message' => 'Password updated successfully.']);
wp_send_json_success([
'message' => 'Password updated successfully.',
'logout_url' => site_url('/login/')
]);
}
function handle_forgot_password()
{
if (!isset($_POST['user_email']) || empty($_POST['user_email'])) {
wp_send_json_error(['message' => 'Please enter a valid email address']);
return;
}
$email = sanitize_email($_POST['user_email']);
$user = get_user_by('email', $email);
if (!$user) {
wp_send_json_success(['message' => 'If this email is registered, you will receive a password reset link.']);
return;
}
// 1. Delete any previous password reset meta
delete_user_meta($user->ID, 'rp_key');
delete_user_meta($user->ID, 'password_reset_status');
delete_user_meta($user->ID, 'rp_expiration');
// 2. Generate a new reset key and store it
$reset_key = get_password_reset_key($user);
if (is_wp_error($reset_key)) {
wp_send_json_error(['message' => 'Unable to generate reset link. Please try again later.']);
return;
}
// 3. Force update the password reset key and expiration manually
update_user_meta($user->ID, 'password_reset_status', 0); // Mark as unused
update_user_meta($user->ID, 'rp_key', $reset_key);
update_user_meta($user->ID, 'rp_expiration', time() + HOUR_IN_SECONDS * 24); // 24-hour expiry
// 4. Create the reset URL
$reset_url = site_url("/password-reset?action=rp&key=" . urlencode($reset_key) . "&login=" . urlencode($user->user_login));
// 5. Load and replace the email template
$template_path = __DIR__ . '/emails/change_pwd.php';
if (!file_exists($template_path)) {
wp_send_json_error(['message' => 'Email template not found.']);
return;
}
$email_body = file_get_contents($template_path);
$email_body = str_replace('{{reset_link}}', esc_url($reset_url), $email_body);
$base_url = get_template_directory_uri();
$email_body = str_replace('{{base_url}}', $base_url, $email_body);
// 6. Send the email
$subject = "Password Reset Request";
$headers = ['Content-Type: text/html; charset=UTF-8'];
if (wp_mail($email, $subject, $email_body, $headers)) {
wp_send_json_success(['message' => 'If this email is registered, you will receive a password reset link.']);
} else {
wp_send_json_error(['message' => 'Failed to send email. Please try again.']);
}
}
add_action('wp_ajax_handle_forgot_password', 'handle_forgot_password');
add_action('wp_ajax_nopriv_handle_forgot_password', 'handle_forgot_password');
function handle_password_reset()
{
if (!isset($_POST['new_password'], $_POST['reset_key'], $_POST['user_login'])) {
wp_send_json_error(array('message' => 'Invalid request.'));
return;
}
$user_login = sanitize_text_field($_POST['user_login']);
$new_password = $_POST['new_password'];
$reset_key = sanitize_text_field($_POST['reset_key']);
// Get user by login
$user = get_user_by('login', $user_login);
if (!$user) {
wp_send_json_error(array('message' => 'User not found.'));
return;
}
// Validate reset key
$check_key = check_password_reset_key($reset_key, $user->user_login);
if (is_wp_error($check_key)) {
wp_send_json_error(array('message' => 'The reset link is invalid or has expired'));
return;
}
// Prevent using the same password
if (wp_check_password($new_password, $user->user_pass, $user->ID)) {
wp_send_json_error(array('message' => 'New password cannot be the same as the old password.'));
return;
}
// Reset password
reset_password($user, $new_password);
// Delete reset key to prevent reuse
delete_user_meta($user->ID, 'rp_key');
delete_user_meta($user->ID, 'password_reset_status');
delete_user_meta($user->ID, 'rp_expiration');
wp_send_json_success(array('message' => 'Password reset successfully. You can now log in.'));
}
add_action('wp_ajax_handle_password_reset', 'handle_password_reset');
add_action('wp_ajax_nopriv_handle_password_reset', 'handle_password_reset');
add_action('wp_ajax_update_cart_item_qty', 'update_cart_item_qty');
add_action('wp_ajax_nopriv_update_cart_item_qty', 'update_cart_item_qty');
function update_cart_item_qty()
{
$cart_item_key = sanitize_text_field($_POST['cart_item_key']);
$quantity = intval($_POST['quantity']);
if ($cart_item_key && WC()->cart->get_cart_item($cart_item_key)) {
WC()->cart->set_quantity($cart_item_key, $quantity);
WC()->cart->calculate_totals();
wp_send_json_success('Cart updated.');
} else {
wp_send_json_error('Item not found.');
}
}
add_action('wp_ajax_update_user_profile', function () {
parse_str($_POST['form_data'], $form_data);
$user_id = get_current_user_id();
if (!$user_id) {
wp_send_json_error('User not logged in');
}
$first_name = sanitize_text_field($form_data['first_name']);
$last_name = sanitize_text_field($form_data['last_name']);
$phone = sanitize_text_field($form_data['phone']);
$email = sanitize_email($form_data['email']);
$country_code = sanitize_text_field($form_data['country_code']);
if (!is_email($email)) {
wp_send_json_error('Invalid email');
}
$current_email = wp_get_current_user()->user_email;
if ($email != $current_email && email_exists($email)) {
wp_send_json_error('Email already exists');
}
// Update user fields
wp_update_user([
'ID' => $user_id,
'user_email' => $email,
'first_name' => $first_name,
'last_name' => $last_name
]);
// update_user_meta($user_id, 'phone', $country_code . ' ' . $phone);
update_user_meta($user_id, 'phone', sanitize_text_field($phone));
update_user_meta($user_id, 'phone_country_code', sanitize_text_field($country_code));
wp_send_json_success();
});
add_action('wp_ajax_upload_profile_image', 'upload_profile_image_callback');
function upload_profile_image_callback()
{
// check_ajax_referer('profile_image_nonce');
if (!is_user_logged_in()) {
wp_send_json_error(['message' => 'User not logged in']);
}
if (!isset($_FILES['profile_image'])) {
wp_send_json_error(['message' => 'No file uploaded']);
}
$file = $_FILES['profile_image'];
require_once(ABSPATH . 'wp-admin/includes/file.php');
$upload = wp_handle_upload($file, ['test_form' => false]);
if (isset($upload['error'])) {
wp_send_json_error(['message' => $upload['error']]);
}
// Save URL to user meta
$user_id = get_current_user_id();
update_user_meta($user_id, 'profile_picture', $upload['url']);
wp_send_json_success(['image_url' => $upload['url']]);
}
add_action('wp_ajax_delete_user_account', 'delete_user_account_callback');
function delete_user_account_callback()
{
// check_ajax_referer('delete_account_nonce');
if (!is_user_logged_in()) {
wp_send_json_error(['message' => 'User not logged in']);
}
$user_id = get_current_user_id();
// Optional: Clean up user meta or files here
require_once(ABSPATH . 'wp-admin/includes/user.php');
wp_delete_user($user_id);
wp_send_json_success();
}
function handle_ajax_contact_form()
{
// Sanitize input values
$name = sanitize_text_field($_POST['cf_name']);
$email = sanitize_email($_POST['cf_email']);
$phone = sanitize_text_field($_POST['cf_phone']);
$subject = sanitize_text_field($_POST['cf_subject']);
$message = sanitize_textarea_field($_POST['cf-message']);
// print_r($_POST);die();
// // Check if either phone or email is provided
// if (empty($email) && empty($phone)) {
// wp_send_json_error(array('message' => 'Enter either a phone number or an email address.'));
// return;
// }
$admin_email = get_option('admin_email');
$headers = ['Content-Type: text/html; charset=UTF-8'];
// Load the email template
$template_path = __DIR__ . '/emails/contact-email.php';
if (!file_exists($template_path)) {
wp_send_json_error(['message' => 'Contact email template not found.']);
}
// Set default subject if empty
if (empty($subject)) {
$subject_contact = "New contact form submission from $name";
} else {
$subject_contact = sanitize_text_field($_POST['cf_subject'] ?? '');
}
$admin_message = file_get_contents($template_path);
$base_url = get_template_directory_uri();
// $subject_contact = "New contact form submission from $name";
// Replace placeholders with dynamic data
$admin_message = str_replace('{{display_name}}', esc_html($name), $admin_message);
$admin_message = str_replace('{{email}}', esc_html($email), $admin_message);
$admin_message = str_replace('{{phone_no}}', esc_html($phone), $admin_message);
$admin_message = str_replace('{{message}}', esc_html($message), $admin_message);
$admin_message = str_replace('{{base_url}}', $base_url, $admin_message);
// Send email
if (wp_mail($admin_email, $subject_contact, $admin_message, $headers)) {
wp_send_json_success(array('message' => 'Thank you for contacting us. We will be in touch shortly!'));
} else {
wp_send_json_error(array('message' => 'Failed to send the message. Please try again later.'));
}
wp_die();
}
add_action('wp_ajax_submit_contact_form', 'handle_ajax_contact_form');
add_action('wp_ajax_nopriv_submit_contact_form', 'handle_ajax_contact_form');
// Handle newsletter subscription
add_action('wp_ajax_newsletter_subscribe', 'newsletter_subscribe');
add_action('wp_ajax_nopriv_newsletter_subscribe', 'newsletter_subscribe');
// function newsletter_subscribe() {
// $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
// if (empty($email) || !is_email($email)) {
// wp_send_json_error(array('message' => 'Invalid email address.'));
// }
// // Check for duplicates (optional)
// $existing = get_option('newsletter_emails', []);
// if (!is_array($existing)) {
// $existing = [];
// }
// if (in_array($email, $existing)) {
// wp_send_json_error(array('message' => 'You are already subscribed.'));
// }
// // Save email
// $existing[] = $email;
// update_option('newsletter_emails', $existing);
// wp_send_json_success(array('message' => 'Subscribed successfully!'));
// }
function newsletter_subscribe()
{
$email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
if (empty($email) || !is_email($email)) {
wp_send_json_error(array('message' => 'Invalid email address.'));
}
// Check for duplicates (optional)
$existing = get_option('newsletter_emails', []);
if (!is_array($existing)) {
$existing = [];
}
if (in_array($email, $existing)) {
wp_send_json_error(array('message' => 'You are already subscribed.'));
}
// Save email
$existing[] = $email;
update_option('newsletter_emails', $existing);
// Send email to subscriber
$subject_user = 'Thank you for subscribing';
$message_user = 'Hi there,' . "\r\n\r\n" .
'Thank you for subscribing to our newsletter!';
$headers_user = ['Content-Type: text/plain; charset=UTF-8'];
wp_mail($email, $subject_user, $message_user, $headers_user);
// Send email to admin
$admin_email = get_option('admin_email');
$subject_admin = 'New Newsletter Subscription';
$message_admin = 'A new user has subscribed to the newsletter: ' . $email;
$headers_admin = ['Content-Type: text/plain; charset=UTF-8'];
wp_mail($admin_email, $subject_admin, $message_admin, $headers_admin);
wp_send_json_success(array('message' => 'Subscribed successfully!'));
}
//----------------------------Main Search-------------------------------------------------------------
// add_action('wp_ajax_autocomplete_products', 'autocomplete_products_callback');
// add_action('wp_ajax_nopriv_autocomplete_products', 'autocomplete_products_callback');
// function autocomplete_products_callback() {
// $term = sanitize_text_field($_POST['term']);
// $args = array(
// 'post_type' => 'product',
// 's' => $term,
// 'posts_per_page' => 10,
// );
// $query = new WP_Query($args);
// $results = [];
// if ($query->have_posts()) {
// while ($query->have_posts()) {
// $query->the_post();
// $results[] = [
// 'name' => get_the_title(),
// 'url' => get_permalink(),
// ];
// }
// }
// wp_reset_postdata();
// echo json_encode($results);
// wp_die();
// }
add_action('wp_ajax_product_suggestions', 'get_product_suggestions');
add_action('wp_ajax_nopriv_product_suggestions', 'get_product_suggestions');
function get_product_suggestions()
{
$query = sanitize_text_field($_GET['query']);
global $wpdb;
// Custom fast query using LIKE on post_title only
$like = '%' . $wpdb->esc_like($query) . '%';
$results = $wpdb->get_results(
$wpdb->prepare(
"
SELECT ID, post_title
FROM $wpdb->posts
WHERE post_type = 'product'
AND post_status = 'publish'
AND post_title LIKE %s
ORDER BY post_title ASC
LIMIT 5
",
$like
)
);
if (!empty($results)) {
echo '<ul class="suggestion-list">';
foreach ($results as $row) {
echo '<li><a href="' . get_permalink($row->ID) . '">' . esc_html($row->post_title) . '</a></li>';
}
echo '</ul>';
} else {
echo '<p>No products found.</p>';
}
wp_die();
}
// AJAX handler
add_action('wp_ajax_filter_products', 'handle_ajax_product_filter');
add_action('wp_ajax_nopriv_filter_products', 'handle_ajax_product_filter');
function handle_ajax_product_filter()
{
$args = [
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => [],
'tax_query' => ['relation' => 'AND'],
];
if (!empty($_POST['categories'])) {
$args['tax_query'][] = [
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array_map('sanitize_text_field', $_POST['categories']),
];
}
if (!empty($_POST['brands'])) {
$args['tax_query'][] = [
'taxonomy' => 'product_brand',
'field' => 'slug',
'terms' => array_map('sanitize_text_field', $_POST['brands']),
];
}
if (!empty($_POST['min_price']) || !empty($_POST['max_price'])) {
$min = floatval($_POST['min_price']);
$max = floatval($_POST['max_price']);
if ($min >= 0 && $max > 0) {
$args['meta_query'][] = [
'key' => '_price',
'value' => [$min, $max],
'type' => 'NUMERIC',
'compare' => 'BETWEEN',
];
}
}
if (!empty($_POST['stock'])) {
$args['meta_query'][] = [
'key' => '_stock_status',
'value' => $_POST['stock'],
'compare' => 'IN'
];
}
if (!empty($_POST['rating'])) {
$rating = max($_POST['rating']);
$args['meta_query'][] = [
'key' => '_wc_average_rating',
'value' => $rating,
'compare' => '>=',
'type' => 'NUMERIC'
];
}
if (!empty($_POST['discount'])) {
$discount_values = array_map('intval', $_POST['discount']);
$min_discount = min($discount_values);
$args['meta_query'][] = [
'relation' => 'AND',
[
'key' => '_sale_price',
'compare' => 'EXISTS'
],
[
'key' => '_regular_price',
'compare' => 'EXISTS'
]
];
add_filter('posts_where', function ($where) use ($min_discount) {
global $wpdb;
$where .= " AND (
(SELECT CAST(pm1.meta_value AS DECIMAL(10,2))
FROM {$wpdb->postmeta} AS pm1
WHERE pm1.post_id = {$wpdb->posts}.ID AND pm1.meta_key = '_sale_price') /
(SELECT CAST(pm2.meta_value AS DECIMAL(10,2))
FROM {$wpdb->postmeta} AS pm2
WHERE pm2.post_id = {$wpdb->posts}.ID AND pm2.meta_key = '_regular_price')
<= " . (1 - $min_discount / 100) . "
)";
return $where;
});
}
$query = new WP_Query($args);
$user_id = get_current_user_id();
$favorites = get_user_meta($user_id, 'favorite_products', true);
if (!is_array($favorites))
$favorites = [];
if ($query->have_posts()) {
ob_start();
while ($query->have_posts()) {
$query->the_post();
global $product;
if (!$product || !is_a($product, 'WC_Product'))
continue;
$product_id = get_the_ID();
$is_favorite = in_array($product_id, $favorites);
$fav_icon = $is_favorite ? 'fav-list-selected.svg' : 'fav-list-plain.svg';
$fav_img = '<img src="' . get_template_directory_uri() . '/img/' . $fav_icon . '" alt="">';
$regular_price = (float) $product->get_regular_price();
$sale_price = (float) $product->get_sale_price();
$has_discount = ($regular_price > 0 && $sale_price > 0 && $sale_price < $regular_price);
$discount = $has_discount ? round(100 - ($sale_price / $regular_price) * 100) : 0;
?>
<div class="product-col">
<a class="listing-blks" href="<?php the_permalink(); ?>">
<div class="products-wrp">
<?php if ($has_discount): ?>
<div class="off-label">
<span class="icon">
<img src="<?php echo get_stylesheet_directory_uri(); ?>/img/discount-icon.svg" alt="discount">
</span>
<span class="txt"><?php echo $discount; ?>% OFF</span>
</div>
<?php endif; ?>
<div class="fav-list fav-btn" data-product="<?php echo esc_attr($product_id); ?>">
<?php echo $fav_img; ?>
</div>
<div class="prod-img">
<?php echo woocommerce_get_product_thumbnail(); ?>
</div>
</div>
<div class="product-desc">
<div class="prod-title"><?php the_title(); ?></div>
<div class="price-blk">
<span class="price"><?php echo $product->get_price_html(); ?></span>
</div>
<div class="bottom-blk">
<div class="save-tag">
<?php if ($has_discount): ?>
Save - <?php echo $discount; ?>%
<?php endif; ?>
</div>
<div class="rating-wrp">
<div class="rating">
<?php
$rating = round($product->get_average_rating()); // 0 to 5
$star_img = get_template_directory_uri() . '/img/rating-star.svg';
$empty_star_img = get_template_directory_uri() . '/img/rating-star.svg'; // same image, but faded via CSS
for ($i = 1; $i <= 5; $i++) {
$is_active = $i <= $rating ? 'active' : '';
echo '<button class="rating-btn ' . $is_active . '">
<img src="' . esc_url($star_img) . '" alt="star">
</button>';
}
?>
</div>
</div>
</div>
</div>
</a>
</div>
<?php
}
wp_reset_postdata();
echo ob_get_clean();
} else {
echo '<section class="no-data">
<div class="no-data-img">
<img src="' . get_stylesheet_directory_uri() . '/img/no-data-img.svg" alt="No data">
</div>
<p class="no-msg">No products found.</p>
</section>';
}
wp_die();
}
function add_product_custom_fields()
{
add_meta_box(
'product_extra_info',
'Product Extra Info',
'render_product_extra_fields',
'product',
'normal',
'default'
);
}
add_action('add_meta_boxes', 'add_product_custom_fields');
function render_product_extra_fields($post)
{
$color = get_post_meta($post->ID, 'product_color', true);
$spec = get_post_meta($post->ID, 'product_specification', true);
echo '<label>Color:</label><br>';
echo '<input type="text" name="product_color" value="' . esc_attr($color) . '" /><br><br>';
echo '<label>Specification:</label><br>';
echo '<textarea name="product_specification">' . esc_textarea($spec) . '</textarea>';
}
function save_product_custom_fields($post_id)
{
if (isset($_POST['product_color'])) {
update_post_meta($post_id, 'product_color', sanitize_text_field($_POST['product_color']));
}
if (isset($_POST['product_specification'])) {
update_post_meta($post_id, 'product_specification', sanitize_textarea_field($_POST['product_specification']));
}
}
add_action('save_post_product', 'save_product_custom_fields');
add_action('wp_ajax_submit_custom_product_review', 'handle_ajax_custom_review');
function handle_ajax_custom_review()
{
if (!is_user_logged_in()) {
wp_send_json_error(['message' => 'You must be logged in to submit a review.']);
}
$user = wp_get_current_user();
$user_id = $user->ID;
$product_id = intval($_POST['product_id']);
$review = sanitize_text_field($_POST['review']);
$rating = intval($_POST['rating']);
if (!$product_id || !$review || !$rating || $rating < 1 || $rating > 5) {
wp_send_json_error(['message' => 'Please provide a valid rating and review.']);
}
$existing_reviews = get_comments([
'user_id' => $user_id,
'post_id' => $product_id,
'type' => 'review',
'status' => 'approve',
'number' => 1,
]);
if (!empty($existing_reviews)) {
wp_send_json_error(['message' => 'You have already submitted a review for this product.']);
}
// ✅ Insert new review
$comment_data = [
'comment_post_ID' => $product_id,
'comment_author' => $user->display_name,
'comment_author_email' => $user->user_email,
'comment_content' => $review,
'comment_type' => 'review',
'user_id' => $user_id,
'comment_approved' => 1,
];
$comment_id = wp_insert_comment($comment_data);
if ($comment_id) {
add_comment_meta($comment_id, 'rating', $rating);
wp_send_json_success(['message' => 'Review submitted successfully!']);
} else {
wp_send_json_error(['message' => 'Unable to save your review.']);
}
}
add_action('wp_ajax_save_user_address', function () {
parse_str($_POST['data'], $form);
$user_id = get_current_user_id();
if (!$user_id)
wp_send_json_error(['message' => 'Unauthorized']);
$new = [
'label' => sanitize_text_field($form['label']),
'address_line' => sanitize_text_field($form['address_line']),
'city' => sanitize_text_field($form['city']),
'state' => sanitize_text_field($form['state']),
'postcode' => sanitize_text_field($form['postcode']),
'country' => sanitize_text_field($form['country']),
];
$addresses = get_user_meta($user_id, 'saved_addresses', true);
$addresses = is_array($addresses) ? $addresses : [];
// Fix: convert index to int and validate it
$index = isset($form['address_index']) && $form['address_index'] !== ''
? (int) $form['address_index']
: null;
if ($index !== null && isset($addresses[$index])) {
// Edit
$addresses[$index] = $new;
} else {
// Add new
$addresses[] = $new;
}
update_user_meta($user_id, 'saved_addresses', array_values($addresses)); // reindex to avoid gaps
wp_send_json_success(['message' => 'Address saved successfully']);
});
// Delete Address AJAX
add_action('wp_ajax_delete_user_address', function () {
$index = intval($_POST['index']);
$user_id = get_current_user_id();
if (!$user_id)
wp_send_json_error(['message' => 'Unauthorized']);
$addresses = get_user_meta($user_id, 'saved_addresses', true);
if (!is_array($addresses) || !isset($addresses[$index])) {
wp_send_json_error(['message' => 'Invalid address']);
}
unset($addresses[$index]);
update_user_meta($user_id, 'saved_addresses', array_values($addresses));
wp_send_json_success();
});
// add_action('woocommerce_before_checkout_billing_form', 'display_saved_addresses_checkout');
function display_saved_addresses_checkout()
{
if (!is_user_logged_in())
return;
$user_id = get_current_user_id();
$addresses = get_user_meta($user_id, 'saved_addresses', true);
$addresses = is_array($addresses) ? $addresses : [];
// Reverse the array to show the most recent address first
$addresses = array_reverse($addresses);
?>
<div class="card-section">
<div class="title-sec">
<h5 class="checkout-title">Saved Addresses</h5>
<!-- <button class="btn add-address" data-bs-toggle="modal" data-bs-target="#addressModal">+ Add New Address</button> -->
</div>
<?php if (!empty($addresses)): ?>
<?php foreach ($addresses as $index => $addr):
$is_active = $index === 0 ? 'address-active' : '';
$full_address = esc_html($addr['address_line']) . ', ' .
esc_html($addr['city']) . ', ' .
esc_html($addr['state']) . ' - ' .
esc_html($addr['postcode']) . ', ' .
esc_html($addr['country']);
?>
<div class="address-box <?php echo $is_active; ?>" data-index="<?php echo esc_attr($index); ?>">
<div class="address-col">
<div class="img-sec"><img src="<?php echo get_template_directory_uri(); ?>/img/loc.svg" alt="loc"></div>
<div class="content-sec">
<p class="address-txt"><?php echo $full_address; ?></p>
<?php if (!empty($addr['phone'])): ?>
<p class="phn-nmbr"><?php echo esc_html($addr['phone']); ?></p>
<?php endif; ?>
</div>
</div>
<div class="rt-sec">
<!-- <button class="btn edit-btn"
data-bs-toggle="modal"
data-bs-target="#addressModal"
data-index="<?php echo esc_attr($index); ?>"
data-address='<?php echo json_encode($addr); ?>'>
<img src="<?php echo get_template_directory_uri(); ?>/img/edit-icon11.svg" alt="edit-icon11">
</button> -->
<button class="btn delivery-btn select-address-btn"
data-index="<?php echo esc_attr($index); ?>">Select</button>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<p class="no-msg">You have no saved addresses yet.</p>
<?php endif; ?>
</div>
<script>
// Store PHP address data into JS
window.savedAddresses = <?php echo json_encode($addresses); ?>;
</script>
<?php
}
add_action('woocommerce_checkout_update_user_meta', 'save_billing_address_to_saved_addresses');
function save_billing_address_to_saved_addresses($user_id)
{
if (!$user_id)
return;
// Get the billing details from the checkout fields
$billing_address = [
'label' => sanitize_text_field($_POST['billing_first_name'] . ' ' . $_POST['billing_last_name']),
'address_line' => isset($_POST['billing_address_1']) ? sanitize_text_field($_POST['billing_address_1']) : '',
'city' => isset($_POST['billing_city']) ? sanitize_text_field($_POST['billing_city']) : '',
'state' => isset($_POST['billing_state']) ? sanitize_text_field($_POST['billing_state']) : '',
'postcode' => isset($_POST['billing_postcode']) ? sanitize_text_field($_POST['billing_postcode']) : '',
'country' => isset($_POST['billing_country']) ? sanitize_text_field($_POST['billing_country']) : '',
];
// Check for empty key fields
if (empty($billing_address['address_line']) || empty($billing_address['city'])) {
return;
}
// Fetch current saved addresses
$saved_addresses = get_user_meta($user_id, 'saved_addresses', true);
$saved_addresses = is_array($saved_addresses) ? $saved_addresses : [];
// Avoid duplicates using hash key
$key = md5(implode('|', $billing_address));
$exists = false;
foreach ($saved_addresses as $address) {
if (md5(implode('|', $address)) === $key) {
$exists = true;
break;
}
}
if (!$exists) {
$saved_addresses[] = $billing_address;
update_user_meta($user_id, 'saved_addresses', $saved_addresses);
}
}
function get_available_discount_brackets()
{
$args = [
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => [
[
'key' => '_sale_price',
'compare' => 'EXISTS',
]
],
];
$query = new WP_Query($args);
$discounts = [];
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$product = wc_get_product(get_the_ID());
$regular = (float) $product->get_regular_price();
$sale = (float) $product->get_sale_price();
if ($regular > 0 && $sale > 0 && $sale < $regular) {
$discount = round((($regular - $sale) / $regular) * 100);
$bracket = floor($discount / 10) * 10;
$discounts[] = $bracket;
}
}
wp_reset_postdata();
}
$discounts = array_unique($discounts);
rsort($discounts); // Sort high to low
return $discounts;
}