File: /mnt/data/dreamssalon-wp/wp-content/plugins/dreamsalon-core/inc/init.php
<?php /**
* Exclude all WooCommerce products from WordPress search results
*/
add_action( 'pre_get_posts', function( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
// Exclude WooCommerce products
$query->set( 'post_type', array( 'post' ) );
}
});
function dreamsalon_hash_email( $email ) {
return wp_hash( strtolower( trim( $email ) ) );
}
// Header style
function add_header_style_meta_box()
{
add_meta_box(
'header_style_meta_box',
'Header Style',
'render_header_style_meta_box',
'page',
'side',
'default'
);
}
add_action('add_meta_boxes', 'add_header_style_meta_box');
function render_header_style_meta_box($post)
{
wp_nonce_field('header_style_meta_action', 'header_style_meta_nonce');
$current_style = get_post_meta($post->ID, '_header_style', true);
?>
<select name="header_style" id="header_style">
<option value="default" <?php selected($current_style, 'default'); ?>><?php echo esc_html__('Default Header','dreamsalon-core'); ?></option>
<option value="style1" <?php selected($current_style, 'style1'); ?>><?php echo esc_html__('Header Style 1','dreamsalon-core'); ?></option>
<option value="style2" <?php selected($current_style, 'style2'); ?>><?php echo esc_html__('Header Style 2','dreamsalon-core'); ?></option>
<option value="style3" <?php selected($current_style, 'style3'); ?>><?php echo esc_html__('Header Style 3','dreamsalon-core'); ?></option>
</select>
<?php
}
function save_header_style_meta($post_id)
{
if (!isset($_POST['header_style_meta_nonce']) ||
!wp_verify_nonce($_POST['header_style_meta_nonce'], 'header_style_meta_action')) {
return $post_id;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['header_style'])) {
update_post_meta($post_id, '_header_style', sanitize_text_field($_POST['header_style']));
}
}
add_action('save_post', 'save_header_style_meta');
function add_header_style_to_quick_edit($column_name, $post_type)
{
if ($column_name === 'header_style' && $post_type === 'page') {
wp_nonce_field('header_style_quick_edit', 'header_style_nonce');
?>
<fieldset class="inline-edit-col-right">
<div class="inline-edit-col">
<label>
<span class="title"><?php echo esc_html__('Header Style','dreamsalon-core'); ?></span>
<select name="_header_style">
<option value="default"><?php echo esc_html__('Default','dreamsalon-core'); ?></option>
<option value="style1"><?php echo esc_html__('Style 1','dreamsalon-core'); ?></option>
<option value="style2"><?php echo esc_html__('Style 2','dreamsalon-core'); ?></option>
<option value="style3"><?php echo esc_html__('Style 3','dreamsalon-core'); ?></option>
</select>
</label>
</div>
</fieldset>
<?php
}
}
add_action('quick_edit_custom_box', 'add_header_style_to_quick_edit', 10, 2);
function save_quick_edit_header_style($post_id)
{
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!isset($_POST['header_style_nonce']) || !wp_verify_nonce($_POST['header_style_nonce'], 'header_style_quick_edit')) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['_header_style'])) {
update_post_meta($post_id, '_header_style', sanitize_text_field($_POST['_header_style']));
}
}
add_action('save_post', 'save_quick_edit_header_style');
function add_header_style_column($columns)
{
$columns['header_style'] = 'Header Style';
return $columns;
}
add_filter('manage_pages_columns', 'add_header_style_column');
function display_header_style_column($column, $post_id)
{
if ($column === 'header_style') {
$header_style = get_post_meta($post_id, '_header_style', true) ?: 'default';
echo '<span id="header_style-' . $post_id . '" data-value="' . esc_attr($header_style) . '">' . ucfirst($header_style) . '</span>';
}
}
add_action('manage_pages_custom_column', 'display_header_style_column', 10, 2);
// 1. Add Meta Box for Footer Style
function add_footer_style_meta_box()
{
add_meta_box(
'footer_style_meta_box',
'Footer Style',
'render_footer_style_meta_box',
'page',
'side',
'default'
);
}
add_action('add_meta_boxes', 'add_footer_style_meta_box');
function render_footer_style_meta_box($post)
{
$current_style = get_post_meta($post->ID, '_footer_style', true);
?>
<select name="footer_style" id="footer_style">
<option value="default" <?php selected($current_style, 'default'); ?>><?php echo esc_html__('Default Footer','dreamsalon-core'); ?></option>
<option value="style1" <?php selected($current_style, 'style1'); ?>><?php echo esc_html__('Footer Style 1','dreamsalon-core'); ?></option>
<option value="style2" <?php selected($current_style, 'style2'); ?>><?php echo esc_html__('Footer Style 2','dreamsalon-core'); ?></option>
<option value="style3" <?php selected($current_style, 'style3'); ?>><?php echo esc_html__('Footer Style 3','dreamsalon-core'); ?></option>
</select>
<?php
}
// 2. Save Footer Style
function save_footer_style_meta($post_id)
{
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['footer_style'])) {
update_post_meta($post_id, '_footer_style', sanitize_text_field($_POST['footer_style']));
}
}
add_action('save_post', 'save_footer_style_meta');
// 3. Add Footer Style to Quick Edit
function add_footer_style_to_quick_edit($column_name, $post_type)
{
if ($column_name === 'footer_style' && $post_type === 'page') {
wp_nonce_field('footer_style_quick_edit', 'footer_style_nonce');
?>
<fieldset class="inline-edit-col-right">
<div class="inline-edit-col">
<label>
<span class="title"><?php echo esc_html__('Footer Style','dreamsalon-core'); ?></span>
<select name="_footer_style">
<option value="default"><?php echo esc_html__('Default','dreamsalon-core'); ?></option>
<option value="style1"><?php echo esc_html__('Style 1','dreamsalon-core'); ?></option>
<option value="style2"><?php echo esc_html__('Style 2','dreamsalon-core'); ?></option>
<option value="style3"><?php echo esc_html__('Style 3','dreamsalon-core'); ?></option>
</select>
</label>
</div>
</fieldset>
<?php
}
}
add_action('quick_edit_custom_box', 'add_footer_style_to_quick_edit', 10, 2);
// 4. Save Quick Edit Footer Style
function save_quick_edit_footer_style($post_id)
{
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!isset($_POST['footer_style_nonce']) || !wp_verify_nonce($_POST['footer_style_nonce'], 'footer_style_quick_edit')) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['_footer_style'])) {
update_post_meta($post_id, '_footer_style', sanitize_text_field($_POST['_footer_style']));
}
}
add_action('save_post', 'save_quick_edit_footer_style');
// 5. Add Footer Style Column to Admin
function add_footer_style_column($columns)
{
$columns['footer_style'] = 'Footer Style';
return $columns;
}
add_filter('manage_pages_columns', 'add_footer_style_column');
// 6. Display Footer Style Column
function display_footer_style_column($column, $post_id)
{
if ($column === 'footer_style') {
$footer_style = get_post_meta($post_id, '_footer_style', true) ?: 'default';
echo '<span id="footer_style-' . $post_id . '" data-value="' . esc_attr($footer_style) . '">' . ucfirst($footer_style) . '</span>';
}
}
add_action('manage_pages_custom_column', 'display_footer_style_column', 10, 2);
/*custom code */
// Add "Hide Breadcrumb" option to Page Attributes
function custom_add_hide_breadcrumb_meta_box() {
add_meta_box(
'hide_breadcrumb_meta_box', // ID
'Breadcrumb Options', // Title
'custom_hide_breadcrumb_meta_box_cb', // Callback
'page', // Screen (post type)
'side', // Context (same as Page Attributes)
'default' // Priority
);
}
add_action('add_meta_boxes', 'custom_add_hide_breadcrumb_meta_box');
// Meta box HTML
function custom_hide_breadcrumb_meta_box_cb($post) {
$value = get_post_meta($post->ID, '_hide_breadcrumb', true);
wp_nonce_field('hide_breadcrumb_nonce_action', 'hide_breadcrumb_nonce');
?>
<p>
<label>
<input type="checkbox" name="hide_breadcrumb" value="1" <?php checked($value, '1'); ?> />
<?php esc_html_e('Hide Breadcrumb on this Page', 'textdomain'); ?>
</label>
</p>
<?php
}
// Save meta box data
function custom_save_hide_breadcrumb_meta_box($post_id) {
if (!isset($_POST['hide_breadcrumb_nonce']) ||
!wp_verify_nonce($_POST['hide_breadcrumb_nonce'], 'hide_breadcrumb_nonce_action')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (isset($_POST['hide_breadcrumb'])) {
update_post_meta($post_id, '_hide_breadcrumb', '1');
} else {
delete_post_meta($post_id, '_hide_breadcrumb');
}
}
add_action('save_post_page', 'custom_save_hide_breadcrumb_meta_box');
/**
* Complete SVG support solution
*/
function complete_svg_support() {
// Allow SVG upload
function cc_mime_types($mimes) {
$mimes['svg'] = 'image/svg+xml';
return $mimes;
}
add_filter('upload_mimes', 'cc_mime_types');
// Fix MIME type detection
function fix_svg_mime_type($data = null, $file = null, $filename = null, $mimes = null) {
$ext = $data['ext'] ?? '';
$type = $data['type'] ?? '';
if ($ext === 'svg' || $type === 'image/svg+xml') {
$data['ext'] = 'svg';
$data['type'] = 'image/svg+xml';
}
return $data;
}
add_filter('wp_check_filetype_and_ext', 'fix_svg_mime_type', 75, 4);
// Fix admin display
function svg_admin_display_fix() {
echo '<style>
.media-icon img[src$=".svg"],
.wp-admin .thumbnail img[src$=".svg"],
.wp-admin .attachment img[src$=".svg"] {
width: 100% !important;
height: auto !important;
max-width: 150px !important;
}
</style>';
}
add_action('admin_head', 'svg_admin_display_fix');
// Generate dimensions for SVG
function svg_dimensions($metadata, $attachment_id) {
$mime_type = get_post_mime_type($attachment_id);
if ($mime_type === 'image/svg+xml') {
$file_path = get_attached_file($attachment_id);
$svg_content = file_get_contents($file_path);
// Extract width and height from SVG
preg_match('/width="([^"]+)"/', $svg_content, $width_matches);
preg_match('/height="([^"]+)"/', $svg_content, $height_matches);
$width = isset($width_matches[1]) ? intval($width_matches[1]) : 100;
$height = isset($height_matches[1]) ? intval($height_matches[1]) : 100;
$metadata['width'] = $width;
$metadata['height'] = $height;
$metadata['sizes'] = [];
}
return $metadata;
}
add_filter('wp_generate_attachment_metadata', 'svg_dimensions', 10, 2);
}
complete_svg_support();
//OTP_Function
// Enqueue OTP scripts
function dreamsalon_enqueue_otp_scripts() {
if (is_page_template('registerform.php')) {
wp_enqueue_script('jquery');
}
}
add_action('wp_enqueue_scripts', 'dreamsalon_enqueue_otp_scripts');
// OTP Functions using transients
function mark_email_verified($email) {
// Store verification status in options table
$verification_data = array(
'email' => $email,
'verified' => true,
'verified_at' => time()
);
update_option('dreamsalon_verified_' . dreamsalon_hash_email($email), $verification_data, 30 * MINUTE_IN_SECONDS); // Keep for 30 minutes
}
function is_email_verified($email) {
$verification_data = get_option('dreamsalon_verified_' . dreamsalon_hash_email($email));
return !empty($verification_data['verified']);
}
// AJAX handler for verifying OTP
function verify_otp_ajax() {
// Check nonce
if (!check_ajax_referer('otp_nonce', 'security', false)) {
wp_send_json_error('Security verification failed.');
}
$email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
$otp = isset($_POST['otp']) ? sanitize_text_field($_POST['otp']) : '';
if (empty($email) || empty($otp)) {
wp_send_json_error('Email and OTP are required.');
}
if (verify_otp($email, $otp)) {
// Mark email as verified
mark_email_verified($email);
// Clear OTP data after successful verification
clear_otp_data($email);
wp_send_json_success('OTP verified successfully! You can now complete your registration.');
} else {
wp_send_json_error('Invalid or expired OTP. Please try again.');
}
}
add_action('wp_ajax_nopriv_verify_otp', 'verify_otp_ajax');
add_action('wp_ajax_verify_otp', 'verify_otp_ajax');
// Registration form handler
// OTP Login Functions
function dreamsalon_generate_login_otp($user_id) {
// Generate 6-digit OTP
$otp = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT);
$otp_expiry = time() + (15 * 60); // 15 minutes
// Store OTP in user meta
update_user_meta($user_id, 'login_otp', $otp);
update_user_meta($user_id, 'login_otp_expiry', $otp_expiry);
update_user_meta($user_id, 'login_otp_attempts', 0);
return $otp;
}
function dreamsalon_send_login_otp_email($user_id, $otp) {
$user = get_userdata($user_id);
$email = $user->user_email;
// Get theme options
$options = get_option('dreamsalon_theme_options');
// Get email subject from Redux or use default
$subject = !empty($options['otp_login_subject_from_email'])
? $options['otp_login_subject_from_email']
: 'Your Login Confirmation Code';
// Get email content from Redux or use default template
$email_content = !empty($options['login_otp_content'])
? $options['login_otp_content']
: "
<p>Enter the code below and verify the user email</p>
<p>{otp}</p>
<p>This code will expire in {expiration_time} minutes.</p>
<p>Use the above code to proceed with Login</p>";
// Get OTP expiration time from Redux
// $otp_expiry_minutes = !empty($options['otp_expiration_time']) ? intval($options['otp_expiration_time']) : 15;
$otp_expiry_minutes = dreamsalon_fl_framework_getoptions('otp_expiration_time');
// Replace template tags with actual values
$message = str_replace(
array(
'{otp}',
'{user_email}',
'{expiration_time}',
'{user_name}'
),
array(
$otp,
$email,
$otp_expiry_minutes,
$user->display_name
),
$email_content
);
// Get email logo from Redux
$email_logo_url = '';
if (!empty($options['otp_login_email_logo']['url'])) {
$email_logo_url = $options['otp_login_email_logo']['url'];
} elseif (function_exists('dreamsalon_fl_framework_getoptions')) {
$main_logo = dreamsalon_fl_framework_getoptions('frontend_logo');
if (!empty($main_logo['url'])) {
$email_logo_url = $main_logo['url'];
}
}
// Wrap message in email template
$full_message = "
<html>
<head>
<title>" . esc_html($subject) . "</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.header { text-align: center; margin-bottom: 30px; }
.logo { max-width: 200px; height: auto; }
.otp-code {
font-size: 32px;
font-weight: bold;
color: #007cba;
text-align: center;
margin: 30px 0;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
letter-spacing: 5px;
}
.content { background: #fff; padding: 30px; border-radius: 8px; border: 1px solid #e9ecef; }
.footer { margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; color: #666; text-align: center; }
.note { background: #fff3cd; padding: 15px; border-radius: 5px; border: 1px solid #ffeaa7; margin: 20px 0; }
</style>
</head>
<body>
<div class='container'>
<div class='header'>";
// Add logo if available
if ($email_logo_url) {
$full_message .= "<img src='" . esc_url($email_logo_url) . "' alt='" . esc_attr(get_bloginfo('name')) . "' class='logo'>";
} else {
$full_message .= "<h1>" . get_bloginfo('name') . "</h1>";
}
$full_message .= "
</div>
<div class='content'>
" . $message . "
</div>
<div class='footer'>
<p>" . sprintf(__('Best regards,<br><strong>%s</strong> Team', 'dreamsalon-core'), get_bloginfo('name')) . "</p>
</div>
</div>
</body>
</html>";
$headers = array(
'Content-Type: text/html; charset=UTF-8',
'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>'
);
return wp_mail($email, $subject, $full_message, $headers);
}
function dreamsalon_verify_otp_login($user_id, $entered_otp) {
$stored_otp = get_user_meta($user_id, 'login_otp', true);
$otp_expiry = (int) get_user_meta($user_id, 'login_otp_expiry', true);
$attempts = (int) get_user_meta($user_id, 'login_otp_attempts', true);
// OTP Not Found
if (empty($stored_otp)) {
return 'No OTP found. Please request a new OTP.';
}
// OTP Expired
if ($otp_expiry < time()) {
dreamsalon_clear_login_otp($user_id);
return 'OTP has expired. Please request a new OTP.';
}
// Attempt Limit
if ($attempts >= 5) {
dreamsalon_clear_login_otp($user_id);
return 'Too many failed attempts. Please request a new OTP.';
}
// Validate format (only 4–6 digits allowed)
if (!preg_match('/^[0-9]{4,6}$/', $entered_otp)) {
update_user_meta($user_id, 'login_otp_attempts', $attempts + 1);
return 'Invalid OTP format.';
}
// OTP Match
if ((string)$stored_otp === (string)$entered_otp) {
// Clear OTP after successful login
dreamsalon_clear_login_otp($user_id);
update_user_meta($user_id, 'last_otp_verified', current_time('mysql'));
return true;
}
// Wrong OTP – increase attempts
$remaining = max(0, 4 - $attempts); // remaining attempts before lock
update_user_meta($user_id, 'login_otp_attempts', $attempts + 1);
return "Invalid OTP. {$remaining} attempts remaining.";
}
function dreamsalon_clear_login_otp($user_id) {
delete_user_meta($user_id, 'login_otp');
delete_user_meta($user_id, 'login_otp_expiry');
delete_user_meta($user_id, 'login_otp_attempts');
}
// AJAX handler for sending login OTP
function send_login_otp_ajax() {
// Check nonce
if (!check_ajax_referer('otp_nonce', 'security', false)) {
wp_send_json_error('Security verification failed.');
}
$username = isset($_POST['username']) ? sanitize_text_field($_POST['username']) : '';
if (empty($username)) {
wp_send_json_error('Email or username is required.');
}
// Check if user exists by email or username
$user = get_user_by('email', $username);
if (!$user) {
$user = get_user_by('login', $username);
}
if (!$user) {
wp_send_json_error('No account found with this email or username.');
}
// Generate and store OTP
$otp = dreamsalon_generate_login_otp($user->ID);
// Send OTP email
$sent = dreamsalon_send_login_otp_email($user->ID, $otp);
// if ($sent) {
wp_send_json_success('OTP has been sent to your registered email.');
// } else {
// // Even if email fails, don't show OTP - just show error
// wp_send_json_error('Failed to send OTP. Please try again.');
// }
}
add_action('wp_ajax_nopriv_send_login_otp', 'send_login_otp_ajax');
add_action('wp_ajax_send_login_otp', 'send_login_otp_ajax');
// Configure SMTP for email sending
// Clean up old OTP data (optional - can be run as cron)
function dreamsalon_cleanup_expired_login_otp() {
global $wpdb;
$current_time = time();
$users_with_otp = $wpdb->get_results(
"SELECT user_id, meta_value as expiry
FROM $wpdb->usermeta
WHERE meta_key = 'login_otp_expiry' AND meta_value < $current_time"
);
foreach ($users_with_otp as $user_otp) {
dreamsalon_clear_login_otp($user_otp->user_id);
}
}
// AJAX handler for verifying OTP
function verify_registration_otp_ajax() {
// Check nonce
if (!check_ajax_referer('otp_nonce', 'security', false)) {
wp_send_json_error('Security verification failedddd.');
}
$email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
$otp = isset($_POST['otp']) ? sanitize_text_field($_POST['otp']) : '';
if (empty($email) || empty($otp)) {
wp_send_json_error('Email and OTP are required.');
}
$verification_result = verify_registration_otp($email, $otp);
if ($verification_result === true) {
wp_send_json_success('OTP verified successfully!');
} else {
wp_send_json_error($verification_result);
}
}
add_action('wp_ajax_nopriv_verify_registration_otp', 'verify_registration_otp_ajax');
add_action('wp_ajax_verify_registration_otp', 'verify_registration_otp_ajax');
// Send OTP via AJAX
function send_otp_ajax() {
global $dreamsalon_theme_options;
// Verify nonce
if (!check_ajax_referer('otp_nonce', 'security', false)) {
wp_send_json_error('Security verification failed.');
}
// Sanitize Email
$email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
// Validate email
if (empty($email)) {
wp_send_json_error('Email is required.');
}
if (!is_email($email)) {
wp_send_json_error('Please enter a valid email address.');
}
// Check if email already registered
if (email_exists($email)) {
wp_send_json_error('This email is already registered. Please login.');
}
$hash = dreamsalon_hash_email($email);
// Check send attempt limit (rate-limit - 60 seconds)
$last_sent = get_transient('otp_last_sent_' . $hash);
if ($last_sent) {
wp_send_json_error('OTP already sent. Please wait 60 seconds.');
}
// Generate 6-digit OTP
$otp = wp_rand(100000, 999999);
// Store OTP for 10 minutes
set_transient('registration_otp_' . $hash, $otp, 10 * MINUTE_IN_SECONDS);
set_transient('registration_otp_email_' . $hash, $email, 10 * MINUTE_IN_SECONDS);
// Set resend limit 60 seconds
set_transient('otp_last_sent_' . $hash, true, 60);
// Get email settings from dreamsalon theme options
$otp_emails_name = $dreamsalon_theme_options['otp_emails_name'] ?? 'Dreamsalon';
$otp_emails_from_email = $dreamsalon_theme_options['otp_emails_from_email'] ?? get_bloginfo('admin_email');
$otp_subject_from_email = $dreamsalon_theme_options['otp_subject_from_email'] ?? 'Your Verification OTP';
$otp_content_from_email = $dreamsalon_theme_options['otp_content_from_email'] ?? 'Your OTP code is {otp}.';
$otp_email_logo = $dreamsalon_theme_options['otp_email_logo'] ?? '';
$otp_email_logo_url = is_array($otp_email_logo) && isset($otp_email_logo['url']) ? $otp_email_logo['url'] : '';
// Replace placeholders in the email content
$email_content = str_replace(
['{user_email}', '{otp}', '{site_name}', '{admin_email}'],
[$email, $otp, get_bloginfo('name'), get_bloginfo('admin_email')],
$otp_content_from_email
);
// Use the email content directly from theme options (no custom HTML wrapper)
$subject = $otp_subject_from_email;
$message = $email_content;
// Set email headers
$headers = array(
'Content-Type: text/html; charset=UTF-8',
'From: ' . $otp_emails_name . ' <' . $otp_emails_from_email . '>',
'Reply-To: ' . $otp_emails_from_email
);
// Send email
$sent = wp_mail($email, $subject, $message, $headers);
if (!$sent) {
// Clean up on failure
$hash = dreamsalon_hash_email($email);
delete_transient('registration_otp_' . $hash);
delete_transient('registration_otp_email_' . $hash);
}
// FOR TESTING/DEBUGGING - Return OTP in development environment
$response_data = 'OTP has been sent to your email address.';
wp_send_json_success($response_data);
}
// add_action('wp_ajax_nopriv_send_otp', 'send_otp_ajax');
// add_action('wp_ajax_send_otp', 'send_otp_ajax');
// Verify OTP for registration
function verify_registration_otp($email = '', $otp = '') {
// If called via AJAX
if (wp_doing_ajax()) {
if (!check_ajax_referer('otp_nonce', 'security', false)) {
wp_send_json_error('Security verification failed.');
}
$email = sanitize_email($_POST['email']);
$otp = sanitize_text_field($_POST['otp']);
}
if (empty($email) || empty($otp)) {
if (wp_doing_ajax()) {
wp_send_json_error('Email and OTP are required.');
}
return 'Email and OTP are required.';
}
$hash = dreamsalon_hash_email($email);
$transient_key = 'registration_otp_' . $hash;
$stored_otp = get_transient($transient_key);
$stored_email = get_transient('registration_otp_email_' . $hash);
// Verify OTP exists
// Verify OTP matches
if ($stored_otp == $otp) {
if (wp_doing_ajax()) {
wp_send_json_error('verified.');
}
return 'verified.';
}
// Verify email matches
if ($stored_email == $email) {
if (wp_doing_ajax()) {
wp_send_json_error('Email mismatch. Please use the same email you requested OTP for.');
}
return 'Email mismatch. Please use the same email you requested OTP for.';
}
// OTP verified successfully - mark as verified
set_transient('registration_otp_verified_' . dreamsalon_hash_email($email), true, 10 * MINUTE_IN_SECONDS);
if (wp_doing_ajax()) {
wp_send_json_success('OTP verified successfully!');
}
return true;
}
add_action('wp_ajax_nopriv_verify_registration_otp', 'verify_registration_otp');
add_action('wp_ajax_verify_registration_otp', 'verify_registration_otp');
// Check if OTP is verified
function is_otp_verified($email) {
return get_transient('registration_otp_verified_' . dreamsalon_hash_email($email)) === true;
}
// Clean up OTP data after registration
function cleanup_otp_after_registration($email) {
$email_hash = dreamsalon_hash_email($email);
delete_transient('registration_otp_' . $email_hash);
delete_transient('registration_otp_email_' . $email_hash);
delete_transient('registration_otp_verified_' . $email_hash);
delete_transient('otp_last_sent_' . $email_hash);
}
// Get stored OTP for testing/debugging
function get_stored_otp($email) {
if (empty($email) || !is_email($email)) {
return false;
}
$otp = get_transient('registration_otp_' . dreamsalon_hash_email($email));
return $otp;
}
// Add email availability check AJAX handler
add_action('wp_ajax_check_email_availability', 'check_email_availability');
add_action('wp_ajax_nopriv_check_email_availability', 'check_email_availability');
function check_email_availability() {
// Verify nonce
if (!wp_verify_nonce($_POST['security'], 'email_check_nonce')) {
wp_send_json_error('Security verification failed.');
}
$email = sanitize_email($_POST['email']);
if (empty($email) || !is_email($email)) {
wp_send_json_error('Invalid email address.');
}
// Check if email exists
$email_exists = email_exists($email);
$username_exists = username_exists($email);
wp_send_json_success(array(
'available' => !$email_exists && !$username_exists,
'message' => $email_exists || $username_exists ? 'Email already registered' : 'Email available'
));
}
/**
* Custom registration form handler for DreamSalon Register template
*/
function dreamsalon_handle_registration_form() {
if ($_SERVER['REQUEST_METHOD'] === 'POST'
&& isset($_POST['email'], $_POST['password'], $_POST['name'])) {
global $wpdb;
$name = sanitize_text_field($_POST['name']);
$email = sanitize_email($_POST['email']);
$password = $_POST['password'];
$user_login = sanitize_user($name, true);
// Ensure username is unique
$original_login = $user_login;
$suffix = 1;
while (username_exists($user_login)) {
$user_login = $original_login . $suffix;
$suffix++;
}
if (empty($name) || empty($email) || empty($password)) {
wc_add_notice(__('All fields are required.', 'dreamsalon-core'), 'error');
return;
}
if (email_exists($email)) {
wc_add_notice(__('Email already registered.', 'dreamsalon-core'), 'error');
return;
}
$hashed_password = wp_hash_password($password);
$inserted = $wpdb->insert(
$wpdb->users,
[
'user_login' => $user_login,
'user_pass' => $hashed_password,
'user_nicename' => sanitize_title($name),
'user_email' => $email,
'user_registered' => current_time('mysql'),
'user_status' => 0,
'display_name' => $name
],
['%s','%s','%s','%s','%s','%d','%s']
);
if ($inserted) {
$user_id = $wpdb->insert_id;
// Assign role
$user = new WP_User($user_id);
$user->set_role('customer');
// SAVE USER META → verification status
update_user_meta($user_id, 'ds_email_verified', 'yes'); // or "no" if waiting OTP
//wc_add_notice(__('Registration successful! Please login with your credentials.', 'dreamsalon-core'), 'success');
$creds = array(
'user_login' => $email, // or username
'user_password' => $_POST['password'], // the password user entered
'remember' => true,
);
$user = wp_signon($creds);
if (!is_wp_error($user)) {
// Check if cart has items
if (WC()->cart && WC()->cart->get_cart_contents_count() > 0) {
// Redirect to checkout page
wp_safe_redirect(wc_get_checkout_url());
} else {
// Redirect to homepage or account page
wp_safe_redirect(site_url('/'));
}
exit;
} else {
// Handle login error
wp_safe_redirect(site_url('/login/?login=failed'));
exit;
}
// wp_safe_redirect(site_url('/'));
exit;
}
else {
wc_add_notice(__('Error creating account. Please try again.', 'dreamsalon-core'), 'error');
}
}
}
add_action('template_redirect', 'dreamsalon_handle_registration_form');