File: /mnt/data/dev/dev-dreamstour-wp/wp-content/plugins/dreams-tour/dreams-tour.php
<?php
/**
* Plugin Name: Dreams Tour
* Description: Custom Tours plugin with templates.
* Version: 1.0
* Author: Your Name
* Text Domain: dreams-tour
* Domain Path: /languages
*/
if (! defined('ABSPATH')) exit;
define('DSBTOUR_PLUGIN_PATH', plugin_dir_path(__FILE__));
/**
* Create plugin custom tables on activation
*/
function dreamstour_activate()
{
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'dreamstour_enquiries';
$sql1 = "CREATE TABLE {$table_name} (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
tour_id bigint(20) unsigned NOT NULL,
name varchar(200) NOT NULL,
email varchar(200) NOT NULL,
phone varchar(100) DEFAULT '' NOT NULL,
message longtext,
created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY tour_id (tour_id),
KEY email (email)
) {$charset_collate};";
$wishlist_table = $wpdb->prefix . 'dreamstour_wishlists';
$sql2 = "CREATE TABLE {$wishlist_table} (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
user_id bigint(20) unsigned NOT NULL,
tour_id bigint(20) unsigned NOT NULL,
created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY user_tour (user_id, tour_id),
KEY tour_id (tour_id)
) {$charset_collate};";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($sql1);
dbDelta($sql2);
// Register rewrites for Author Tours pretty URLs and flush
if (function_exists('dreamstour_register_author_tours_rewrites')) {
dreamstour_register_author_tours_rewrites();
}
flush_rewrite_rules();
}
register_activation_hook(__FILE__, 'dreamstour_activate');
/**
* Register custom user roles for Dreams Tour plugin
*/
function dreamstour_register_custom_roles()
{
add_role(
'agent',
__('Agent', 'dreams-tour'),
array(
'read' => true,
)
);
add_role(
'regular_user',
__('Customer', 'dreams-tour'),
array(
'read' => true,
)
);
}
register_activation_hook(__FILE__, 'dreamstour_register_custom_roles');
/**
* Remove custom user roles on plugin deactivation
*/
function dreamstour_remove_custom_roles()
{
remove_role('agent');
remove_role('regular_user');
}
register_deactivation_hook(__FILE__, 'dreamstour_remove_custom_roles');
// Flush rewrite rules on deactivation as well
register_deactivation_hook(__FILE__, function(){
flush_rewrite_rules();
});
/**
* Pretty URLs for Author Tours page: /{author-tours-page-slug}/{author_nicename}
*/
function dreamstour_register_author_tours_rewrites() {
$page_id = function_exists('dreamstour_fl_framework_getoptions') ? dreamstour_fl_framework_getoptions('author_tours_page') : 0;
if ($page_id) {
$slug = get_post_field('post_name', $page_id);
if ($slug) {
add_rewrite_rule(
'^' . preg_quote($slug, '#') . '/([^/]+)/?$',
'index.php?pagename=' . $slug . '&author_name=$matches[1]',
'top'
);
}
}
}
add_action('init', 'dreamstour_register_author_tours_rewrites');
// Ensure author_name is an allowed public query var (typically already is)
add_filter('query_vars', function($vars){
if (!in_array('author_name', $vars, true)) {
$vars[] = 'author_name';
}
return $vars;
});
/**
* Check if tour is in user's wishlist
*/
function dreamstour_is_in_wishlist($user_id, $tour_id)
{
global $wpdb;
$table = $wpdb->prefix . 'dreamstour_wishlists';
$exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$table} WHERE user_id=%d AND tour_id=%d LIMIT 1", $user_id, $tour_id));
return ! empty($exists);
}
/**
* AJAX: Delete tour without page refresh
*/
add_action('wp_ajax_dt_delete_tour_ajax', function () {
if (!is_user_logged_in()) {
wp_send_json_error(['message' => __('Login required.', 'dreams-tour')], 401);
}
$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
$nonce = isset($_POST['_wpnonce']) ? sanitize_text_field($_POST['_wpnonce']) : '';
if (!$post_id || get_post_type($post_id) !== 'tour') {
wp_send_json_error(['message' => __('Invalid tour.', 'dreams-tour')], 400);
}
if (!wp_verify_nonce($nonce, 'dt_delete_tour_' . $post_id)) {
wp_send_json_error(['message' => __('Security check failed.', 'dreams-tour')], 403);
}
if (!current_user_can('delete_post', $post_id)) {
$author_id = (int) get_post_field('post_author', $post_id);
if (get_current_user_id() !== $author_id) {
wp_send_json_error(['message' => __('Not allowed to delete this tour.', 'dreams-tour')], 403);
}
}
$result = wp_trash_post($post_id);
if (!$result) {
wp_send_json_error(['message' => __('Failed to delete tour.', 'dreams-tour')]);
}
wp_send_json_success(['message' => __('Tour deleted.', 'dreams-tour'), 'post_id' => $post_id]);
});
/**
* Get wishlist count for a user
*/
function dreamstour_get_wishlist_count($user_id)
{
if (! $user_id) {
return 0;
}
global $wpdb;
$table = $wpdb->prefix . 'dreamstour_wishlists';
$count = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table} WHERE user_id=%d", $user_id));
return $count;
}
/**
* Toggle wishlist (AJAX, logged-in only)
*/
add_action('wp_ajax_dreamstour_toggle_wishlist', 'dreamstour_toggle_wishlist');
function dreamstour_toggle_wishlist()
{
if (! is_user_logged_in()) {
wp_send_json_error(array('message' => __('Login required', 'dreams-tour')), 401);
}
$nonce = isset($_POST['nonce']) ? sanitize_text_field($_POST['nonce']) : '';
if (! wp_verify_nonce($nonce, 'dreamstour_wishlist')) {
wp_send_json_error(array('message' => __('Security check failed', 'dreams-tour')), 403);
}
$tour_id = isset($_POST['tour_id']) ? absint($_POST['tour_id']) : 0;
if (! $tour_id || get_post_type($tour_id) !== 'tour') {
wp_send_json_error(array('message' => __('Invalid tour', 'dreams-tour')), 400);
}
$user_id = get_current_user_id();
$user = get_user_by('id', $user_id);
if (! $user || ! in_array('regular_user', (array) $user->roles, true)) {
wp_send_json_error(array('message' => __('Only customers can use wishlist.', 'dreams-tour')), 403);
}
global $wpdb;
$table = $wpdb->prefix . 'dreamstour_wishlists';
if (dreamstour_is_in_wishlist($user_id, $tour_id)) {
$wpdb->delete($table, array('user_id' => $user_id, 'tour_id' => $tour_id), array('%d', '%d'));
$count = dreamstour_get_wishlist_count($user_id);
wp_send_json_success(array('status' => 'removed', 'count' => $count));
} else {
$wpdb->insert($table, array('user_id' => $user_id, 'tour_id' => $tour_id, 'created_at' => current_time('mysql')), array('%d', '%d', '%s'));
$count = dreamstour_get_wishlist_count($user_id);
wp_send_json_success(array('status' => 'added', 'count' => $count));
}
}
/**
* Get wishlist count (AJAX)
*/
add_action('wp_ajax_dreamstour_get_wishlist_count', function () {
if (! is_user_logged_in()) {
wp_send_json_success(array('count' => 0));
}
$count = dreamstour_get_wishlist_count(get_current_user_id());
wp_send_json_success(array('count' => $count));
});
add_action('wp_ajax_nopriv_dreamstour_get_wishlist_count', function () {
wp_send_json_success(array('count' => 0));
});
/**
* Load plugin textdomain for translations
*/
add_action('init', 'dreamstour_load_textdomain_core');
function dreamstour_load_textdomain_core()
{
load_plugin_textdomain(
'dreams-tour',
false,
dirname(plugin_basename(__FILE__)) . '/languages'
);
}
// Include CPT
require_once plugin_dir_path(__FILE__) . 'includes/cpt-tour.php';
require_once plugin_dir_path(__FILE__) . 'includes/recent-posts-widgets.php';
require_once plugin_dir_path(__FILE__) . 'includes/search-widget.php';
require_once plugin_dir_path(__FILE__) . 'includes/categories-widget.php';
require_once plugin_dir_path(__FILE__) . 'includes/tags-widget.php';
if (! class_exists('Gamajo_Template_Loader')) {
require_once plugin_dir_path(__FILE__) . 'lib/class-gamajo-template-loader.php';
}
require_once plugin_dir_path(__FILE__) . 'includes/dreamsrent-core-templates.php';
/**
* Load single template for Tour CPT
*/
add_filter('single_template', 'dreamstour_single_template');
function dreamstour_single_template($single)
{
global $post;
if ($post->post_type == 'tour') {
$template = plugin_dir_path(__FILE__) . 'templates/single-tour.php';
if (file_exists($template)) {
return $template;
}
}
return $single;
}
/**
* Load archive template for Tour CPT
*/
add_filter('archive_template', 'dreamstour_archive_template');
function dreamstour_archive_template($archive)
{
if (is_post_type_archive('tour')) {
$template = plugin_dir_path(__FILE__) . 'templates/archive-tour.php';
if (file_exists($template)) {
return $template;
}
}
return $archive;
}
/**
* Register a custom page template
*/
add_filter('theme_page_templates', 'dreamstour_register_page_template');
function dreamstour_register_page_template($templates)
{
$templates['page-template-add-tour.php'] = 'Dreams Template Add Tour';
return $templates;
}
add_filter('template_include', 'dreamstour_load_page_template');
function dreamstour_load_page_template($template)
{
if (is_page()) {
$chosen_template = get_page_template_slug(get_queried_object_id());
if ($chosen_template == 'page-template-add-tour.php') {
$new_template = plugin_dir_path(__FILE__) . 'templates/page-template-add-tour.php';
if (file_exists($new_template)) {
return $new_template;
}
}
}
return $template;
}
add_filter('theme_page_templates', 'dreamstour_register_register_template');
function dreamstour_register_register_template($templates)
{
$templates['register-form.php'] = 'Dreams Register Template';
return $templates;
}
add_filter('template_include', 'dreamstour_load_register_template');
function dreamstour_load_register_template($template)
{
if (is_page()) {
$chosen_template = get_page_template_slug(get_queried_object_id());
if ($chosen_template == 'register-form.php') {
$new_template = plugin_dir_path(__FILE__) . 'templates/register-form.php';
if (file_exists($new_template)) {
return $new_template;
}
}
}
return $template;
}
add_filter('theme_page_templates', 'dreamstour_forgotpass_template');
function dreamstour_forgotpass_template($templates)
{
$templates['forget-password.php'] = 'Forget Password Template';
return $templates;
}
add_filter('template_include', 'dreamstour_load_forgetpass_template');
function dreamstour_load_forgetpass_template($template)
{
if (is_page()) {
$chosen_template = get_page_template_slug(get_queried_object_id());
if ($chosen_template == 'forget-password.php') {
$new_template = plugin_dir_path(__FILE__) . 'templates/forget-password.php';
if (file_exists($new_template)) {
return $new_template;
}
}
}
return $template;
}
add_filter('theme_page_templates', 'dreamstour_register_login_template');
function dreamstour_register_login_template($templates)
{
$templates['login-form.php'] = 'Dreams Login Template';
return $templates;
}
add_filter('template_include', 'dreamstour_load_login_template');
function dreamstour_load_login_template($template)
{
if (is_page()) {
$chosen_template = get_page_template_slug(get_queried_object_id());
if ($chosen_template == 'login-form.php') {
$new_template = plugin_dir_path(__FILE__) . 'templates/login-form.php';
if (file_exists($new_template)) {
return $new_template;
}
}
}
return $template;
}
/**
* AJAX: Submit Tour Review
* Saves as a WP comment on the tour post.
* Also updates average rating and count in post meta: tour_rating, tour_review_count
*/
add_action('wp_ajax_submit_tour_review', 'dreamstour_submit_tour_review');
add_action('wp_ajax_nopriv_submit_tour_review', 'dreamstour_submit_tour_review');
function dreamstour_submit_tour_review()
{
if (empty($_POST['tour_review_nonce']) || ! wp_verify_nonce($_POST['tour_review_nonce'], 'tour_review_nonce')) {
wp_send_json_error(array('message' => 'Security check failed'));
}
// Require user to be logged in to submit a review
if (! is_user_logged_in()) {
wp_send_json_error(array('message' => __('Login required to submit a review.', 'dreams-tour')), 401);
}
$tour_id = isset($_POST['tour_id']) ? absint($_POST['tour_id']) : 0;
if (! $tour_id || get_post_type($tour_id) !== 'tour') {
wp_send_json_error(array('message' => 'Invalid tour'));
}
$rating = isset($_POST['rating']) ? intval($_POST['rating']) : 0;
$content = isset($_POST['review_content']) ? sanitize_textarea_field($_POST['review_content']) : '';
// Always use logged-in user's data for author name/email
$current_user = wp_get_current_user();
$name = $current_user ? $current_user->display_name : '';
$email = $current_user ? $current_user->user_email : '';
if ($rating < 1 || $rating > 5 || empty($name) || empty($email) || empty($content)) {
wp_send_json_error(array('message' => 'Please complete all required fields'));
}
// Insert comment
$commentdata = array(
'comment_post_ID' => $tour_id,
'comment_author' => $name,
'comment_author_email' => $email,
'comment_content' => $content,
'user_id' => get_current_user_id(),
// 'comment_approved' => 0, // pending moderation
);
$comment_id = wp_insert_comment($commentdata);
if (is_wp_error($comment_id) || ! $comment_id) {
wp_send_json_error(array('message' => 'Could not save review'));
}
// Save rating as comment meta
update_comment_meta($comment_id, 'rating', $rating);
// Recalculate rating and count from approved comments only
$args = array(
'post_id' => $tour_id,
'status' => 'approve',
'count' => false,
'type' => 'comment',
);
$approved_comments = get_comments($args);
$ratings = array();
foreach ($approved_comments as $c) {
$r = get_comment_meta($c->comment_ID, 'rating', true);
if ($r) {
$ratings[] = intval($r);
}
}
$review_count = count($ratings);
$average = $review_count ? round(array_sum($ratings) / $review_count, 1) : 0;
update_post_meta($tour_id, 'tour_review_count', $review_count);
update_post_meta($tour_id, 'tour_rating', $average);
wp_send_json_success(array('message' => 'Review submitted', 'average' => $average, 'count' => $review_count));
}
// AJAX handler for tour enquiry
function dreamstour_handle_tour_enquiry()
{
if (!wp_verify_nonce($_POST['tour_enquiry_nonce'], 'tour_enquiry_nonce')) {
wp_send_json_error(array('message' => 'Security check failed'));
}
$tour_id = intval($_POST['tour_id']);
$name = sanitize_text_field($_POST['enquiry_name']);
$email = sanitize_email($_POST['enquiry_email']);
$phone = sanitize_text_field($_POST['enquiry_phone']);
$message = sanitize_textarea_field($_POST['enquiry_message']);
// Validate required fields
if (empty($name) || empty($email) || empty($message)) {
wp_send_json_error(array('message' => 'Please fill in all required fields'));
}
// Store enquiry in custom table
global $wpdb;
$table = $wpdb->prefix . 'dreamstour_enquiries';
$result = $wpdb->insert(
$table,
array(
'tour_id' => $tour_id,
'name' => $name,
'email' => $email,
'phone' => $phone,
'message' => $message,
'created_at' => current_time('mysql'),
),
array('%d', '%s', '%s', '%s', '%s', '%s')
);
if ($result === false) {
wp_send_json_error(array('message' => 'Failed to save enquiry. Please try again.'));
}
// Send email notification
$to = get_option('admin_email');
$subject = 'New Tour Enquiry - ' . get_the_title($tour_id);
$body = "Tour: " . get_the_title($tour_id) . "\n";
$body .= "Name: " . $name . "\n";
$body .= "Email: " . $email . "\n";
$body .= "Phone: " . $phone . "\n";
$body .= "Message: " . $message . "\n";
wp_mail($to, $subject, $body);
wp_send_json_success(array('message' => 'Enquiry submitted successfully'));
}
add_action('wp_ajax_submit_tour_enquiry', 'dreamstour_handle_tour_enquiry');
add_action('wp_ajax_nopriv_submit_tour_enquiry', 'dreamstour_handle_tour_enquiry');
/**
* Export agent bookings as CSV
*/
add_action('admin_post_dreamstour_export_bookings', 'dreamstour_export_bookings');
function dreamstour_export_bookings() {
if (!is_user_logged_in()) {
wp_die(__('You must be logged in.', 'dreams-tour'), 400);
}
if (!isset($_GET['dreamstour_export_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['dreamstour_export_nonce'])), 'dreamstour_export_bookings')) {
wp_die(__('Security check failed.', 'dreams-tour'), 400);
}
$current_user = wp_get_current_user();
$agent_id = (int) $current_user->ID;
global $wpdb;
$book_table = $wpdb->prefix . 'dreamstour_booking';
$posts = $wpdb->posts;
$search = isset($_GET['search']) ? sanitize_text_field(wp_unslash($_GET['search'])) : '';
$status = isset($_GET['status']) ? sanitize_key(wp_unslash($_GET['status'])) : '';
$from = isset($_GET['from']) ? sanitize_text_field(wp_unslash($_GET['from'])) : '';
$to = isset($_GET['to']) ? sanitize_text_field(wp_unslash($_GET['to'])) : '';
$where = array('p.post_author = %d');
$params = array($agent_id);
if ($search !== '') {
$like = '%' . $wpdb->esc_like($search) . '%';
$where[] = '(b.booking_reference LIKE %s OR b.customer_name LIKE %s OR b.customer_email LIKE %s OR b.customer_phone LIKE %s OR p.post_title LIKE %s)';
array_push($params, $like, $like, $like, $like, $like);
}
if (!empty($status)) {
$where[] = 'b.booking_status = %s';
$params[] = $status;
}
if ($from !== '') {
$where[] = 'b.booking_date >= %s';
$params[] = $from . ' 00:00:00';
}
if ($to !== '') {
$where[] = 'b.booking_date <= %s';
$params[] = $to . ' 23:59:59';
}
$where_sql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';
$sql = "SELECT b.*, p.post_title FROM $book_table b INNER JOIN $posts p ON p.ID = b.tour_id $where_sql ORDER BY b.booking_date DESC";
$rows = $wpdb->get_results($wpdb->prepare($sql, $params));
// Prepare CSV
$filename = 'dreamstour-bookings-' . date('Ymd-His') . '.csv';
nocache_headers();
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=' . $filename);
$out = fopen('php://output', 'w');
// Header row
fputcsv($out, array(
'S.No', 'Booking Ref', 'Tour Title', 'Customer Name', 'Customer Email', 'Customer Phone',
'Adults', 'Children', 'Departure Date', 'Return Date', 'Days', 'Total Price',
'Booking Date', 'Booking Status', 'Order ID', 'Order Status', 'Payment Method'
));
$sn = 1;
foreach ((array)$rows as $row) {
$order_status = '';
$order_method = '';
$bill_name = '';
$bill_email = '';
$bill_phone = '';
if (function_exists('wc_get_order') && !empty($row->order_id)) {
$order = wc_get_order((int)$row->order_id);
if ($order) {
$order_status = wc_get_order_status_name($order->get_status());
$order_method = $order->get_payment_method_title();
$bill_first = $order->get_billing_first_name();
$bill_last = $order->get_billing_last_name();
$bill_name = trim($bill_first . ' ' . $bill_last);
$bill_email = $order->get_billing_email();
$bill_phone = $order->get_billing_phone();
}
} else {
$order_method = !empty($row->payment_method) ? $row->payment_method : '';
}
$days = '';
$d1 = strtotime($row->departure_date);
$d2 = strtotime($row->return_date);
if ($d1 && $d2) {
$diff = max(0, (int) round(($d2 - $d1) / DAY_IN_SECONDS));
$days = $diff;
}
// Resolve customer details (Woo billing first, fallback to booking table)
$csv_name = $bill_name ? $bill_name : (string)$row->customer_name;
$csv_email = $bill_email ? $bill_email : (string)$row->customer_email;
$csv_phone = $bill_phone ? $bill_phone : (string)$row->customer_phone;
fputcsv($out, array(
$sn,
(string)($row->booking_reference ?: $row->booking_id),
(string)($row->post_title ?: '(no title)'),
$csv_name,
$csv_email,
$csv_phone,
(int)$row->adults,
(int)$row->children,
$row->departure_date,
$row->return_date,
$days,
number_format((float)$row->total_price, 2, '.', ''),
$row->booking_date,
(string)$row->booking_status,
(string)$row->order_id,
(string)$order_status,
(string)$order_method
));
$sn++;
}
fclose($out);
exit;
}
/**
* AJAX handler for user registration (frontend)
*/
add_action('wp_ajax_nopriv_dreamstour_register_user', 'dreamstour_ajax_register_user');
add_action('wp_ajax_dreamstour_register_user', 'dreamstour_ajax_register_user');
function dreamstour_ajax_register_user()
{
// Check nonce
if (empty($_POST['dreams_tour_register_nonce']) || ! wp_verify_nonce($_POST['dreams_tour_register_nonce'], 'dreams_tour_register')) {
wp_send_json_error(['message' => __('Security check failed.', 'dreams-tour')]);
}
// Sanitize input
$username = sanitize_user($_POST['username']);
$full_name = sanitize_text_field($_POST['full_name']);
$user_type = sanitize_text_field($_POST['user_type']);
$agree_terms = isset($_POST['agree_terms']) ? sanitize_text_field($_POST['agree_terms']) : '';
$email = sanitize_email($_POST['email']);
$password = $_POST['password'];
$confirm_password = $_POST['confirm_password'];
// Validate required fields
if (empty($username) || empty($full_name) || empty($user_type) || empty($agree_terms)) {
wp_send_json_error(['message' => __('All fields are required.', 'dreams-tour')]);
} elseif (username_exists($username)) {
wp_send_json_error(['message' => __('Username already exists. Please choose a different username.', 'dreams-tour')]);
} elseif (email_exists($email)) {
wp_send_json_error(['message' => __('Email already exists. Please use a different email address.', 'dreams-tour')]);
} elseif (! is_email($email)) {
wp_send_json_error(['message' => __('Please enter a valid email address.', 'dreams-tour')]);
} elseif (strlen($password) < 6) {
wp_send_json_error(['message' => __('Password must be at least 6 characters long.', 'dreams-tour')]);
} elseif ($password !== $confirm_password) {
wp_send_json_error(['message' => __('Passwords do not match.', 'dreams-tour')]);
}
// Validate user role
$allowed_roles = array('agent', 'regular_user');
if (! in_array($user_type, $allowed_roles, true)) {
$user_type = 'regular_user'; // Default role
}
// Create user
$user_id = wp_create_user($username, $password, $email);
if (is_wp_error($user_id)) {
wp_send_json_error(['message' => $user_id->get_error_message()]);
}
// Set user role
$user = new WP_User($user_id);
$user->set_role($user_type);
// Update user meta for full name
update_user_meta($user_id, 'first_name', $full_name);
update_user_meta($user_id, 'display_name', $full_name);
// Success: send login URL
$login_page = dreamstour_fl_framework_getoptions('header_login_link');
$redirect_url = ! empty($login_page) ? get_permalink($login_page) : wp_login_url();
wp_send_json_success([
'message' => __('Registration successful! Please log in.', 'dreams-tour'),
'redirect' => $redirect_url
]);
}
/**
* Enqueue AJAX scripts on login/register templates only
*/
add_action('wp_enqueue_scripts', function () {
wp_enqueue_script(
'dreams-script-js',
plugins_url('assets/js/dreams-script.js', __FILE__),
array('jquery'),
'1.1.0',
true
);
wp_enqueue_script(
'dreams-rangeSlider-script-js',
plugins_url('lib/ion-rangeslider/js/ion.rangeSlider.js', __FILE__),
array('jquery'),
'1.0.0',
true
);
wp_enqueue_script(
'dreams-range-script-js',
plugins_url('lib/ion-rangeslider/js/custom-rangeslider.js', __FILE__),
array('jquery'),
'1.0.0',
true
);
wp_enqueue_script(
'dreams-rangeSlidermin-script-js',
plugins_url('lib/ion-rangeslider/js/ion.rangeSlider.min.js', __FILE__),
array('jquery'),
'1.0.0',
true
);
wp_enqueue_style(
'dreams-rangeSlider-style-css',
plugins_url('lib/ion-rangeslider/css/ion.rangeSlider.css', __FILE__),
array(),
'1.0.0',
'all'
);
wp_enqueue_style(
'dreams-rangeSlider-style-min-css',
plugins_url('lib/ion-rangeslider/css/ion.rangeSlider.min.css', __FILE__),
array(),
'1.0.0',
'all',
);
$wishlist_count = is_user_logged_in() ? dreamstour_get_wishlist_count(get_current_user_id()) : 0;
$current_user = wp_get_current_user();
$is_customer = ($current_user && in_array('regular_user', (array) $current_user->roles, true));
wp_localize_script('dreams-script-js', 'DreamsAxaj', array(
'ajax_url' => admin_url('admin-ajax.php'),
'register_nonce' => wp_create_nonce('dreams_tour_register'),
'login_nonce' => wp_create_nonce('dreams_tour_login'),
'wishlist_nonce' => wp_create_nonce('dreamstour_wishlist'),
'wishlist_count' => (int) $wishlist_count,
'is_logged_in' => is_user_logged_in(),
'is_customer' => $is_customer,
'login_url' => wp_login_url(),
'messages' => array(
'login_required' => __('Please login to save tours.', 'dreams-tour'),
'customer_only' => __('Only customers can use wishlist.', 'dreams-tour'),
'error_generic' => __('Something went wrong', 'dreams-tour'),
'added_to_wishlist' => __('added to wishlist.', 'dreams-tour'),
'removed_from_wishlist' => __('removed from wishlist.', 'dreams-tour'),
),
));
});
/**
* AJAX handler for user login (frontend)
*/
add_action('wp_ajax_nopriv_dreamstour_login_user', function () {
if (empty($_POST['dreams_tour_login_nonce']) || ! wp_verify_nonce($_POST['dreams_tour_login_nonce'], 'dreams_tour_login')) {
wp_send_json_error(['message' => __('Security check failed.', 'dreams-tour')]);
}
$raw_login = isset($_POST['user_login']) ? sanitize_text_field($_POST['user_login']) : '';
$password = isset($_POST['user_pass']) ? $_POST['user_pass'] : '';
if (empty($raw_login) || empty($password)) {
wp_send_json_error(['message' => __('Please enter both username/email and password.', 'dreams-tour')]);
}
// Resolve username if an email was provided
if (is_email($raw_login)) {
$user_obj = get_user_by('email', $raw_login);
if ($user_obj && ! empty($user_obj->user_login)) {
$login_username = $user_obj->user_login;
} else {
wp_send_json_error(['message' => __('No account found with that email address.', 'dreams-tour')]);
}
} else {
$login_username = $raw_login;
}
$remember = (!empty($_POST['rememberme']) || !empty($_POST['remember_me']) || !empty($_POST['remembers_me'])) ? true : false;
$creds = array(
'user_login' => $login_username,
'user_password' => $password,
'remember' => $remember,
);
$user = wp_signon($creds, is_ssl());
if (is_wp_error($user)) {
wp_send_json_error(['message' => $user->get_error_message()]);
}
wp_set_current_user($user->ID);
$redirect_url = site_url('/');
wp_send_json_success([
'message' => __('Login successful! Redirecting....', 'dreams-tour'),
'redirect' => $redirect_url
]);
});
// Add template to page attributes
function add_tour_grid_template($templates)
{
$templates['tour-grid.php'] = 'Tour Grid Template';
return $templates;
}
add_filter('theme_page_templates', 'add_tour_grid_template');
// Load the template
function load_tour_grid_template($template)
{
if (is_page()) {
$chosen_template = get_page_template_slug(get_queried_object_id());
if ($chosen_template == 'tour-grid.php') {
$new_template = plugin_dir_path(__FILE__) . 'templates/tour-grid.php';
if (file_exists($new_template)) {
return $new_template;
}
}
}
return $template;
}
add_filter('template_include', 'load_tour_grid_template');
function add_tour_list_template($templates)
{
$templates['tour-list.php'] = 'Tour List Template';
return $templates;
}
add_filter('theme_page_templates', 'add_tour_list_template');
// Load the template
function load_tour_list_template($template)
{
if (is_page()) {
$chosen_template = get_page_template_slug(get_queried_object_id());
if ($chosen_template == 'tour-list.php') {
$new_template = plugin_dir_path(__FILE__) . 'templates/tour-list.php';
if (file_exists($new_template)) {
return $new_template;
}
}
}
return $template;
}
add_filter('template_include', 'load_tour_list_template');
// Register Author Tours page template
function dreamstour_register_author_tours_template($templates)
{
$templates['author-tours.php'] = 'Author Tours Template';
return $templates;
}
add_filter('theme_page_templates', 'dreamstour_register_author_tours_template');
// Load the Author Tours template
function dreamstour_load_author_tours_template($template)
{
if (is_page()) {
$chosen_template = get_page_template_slug(get_queried_object_id());
if ($chosen_template === 'author-tours.php') {
$new_template = plugin_dir_path(__FILE__) . 'templates/author-tours.php';
if (file_exists($new_template)) {
return $new_template;
}
}
}
return $template;
}
add_filter('template_include', 'dreamstour_load_author_tours_template');
/**
* Admin-post handler: Delete (trash) a Tour from dashboard links
* URL pattern is built with wp_nonce_url in templates: action=dt_delete_tour&post_id={ID}
*/
add_action('admin_post_dt_delete_tour', 'dreamstour_handle_delete_tour');
function dreamstour_handle_delete_tour()
{
// Must be logged in
if (!is_user_logged_in()) {
wp_die(__('You must be logged in to delete a tour.', 'dreams-tour'), 403);
}
$post_id = isset($_GET['post_id']) ? absint($_GET['post_id']) : 0;
if (!$post_id || get_post_type($post_id) !== 'tour') {
wp_die(__('Invalid tour.', 'dreams-tour'), 400);
}
// Verify nonce created as: $action . '_' . $post_id with default _wpnonce param
$nonce = isset($_GET['_wpnonce']) ? sanitize_text_field($_GET['_wpnonce']) : '';
if (!wp_verify_nonce($nonce, 'dt_delete_tour_' . $post_id)) {
wp_die(__('Security check failed.', 'dreams-tour'), 403);
}
// Permission: user must be able to delete this post
if (!current_user_can('delete_post', $post_id)) {
// As an extra safety, allow post author
$author_id = (int) get_post_field('post_author', $post_id);
if (get_current_user_id() !== $author_id) {
wp_die(__('You do not have permission to delete this tour.', 'dreams-tour'), 403);
}
}
// Trash the post (non-permanent delete)
$result = wp_trash_post($post_id);
// Redirect back with status
$referer = wp_get_referer();
if (!$referer) {
$referer = home_url('/');
}
$referer = add_query_arg(
array(
'dt_deleted' => $result ? 1 : 0,
'post_id' => $post_id,
),
$referer
);
wp_safe_redirect($referer);
exit;
}
/**
* WooCommerce checkout template override: use plugin template if available
*/
add_filter('woocommerce_locate_template', function ($template, $template_name, $template_path) {
if ($template_name === 'checkout/form-checkout.php') {
$plugin_template = plugin_dir_path(__FILE__) . 'templates/woocommerce/checkout/form-checkout.php';
if (file_exists($plugin_template)) {
return $plugin_template;
}
}
return $template;
}, 10, 3);
// Add AJAX actions for logged-in and non-logged-in users
add_action('wp_ajax_tour_search_filter', 'tour_search_filter_ajax_handler');
add_action('wp_ajax_nopriv_tour_search_filter', 'tour_search_filter_ajax_handler');
function tour_search_filter_ajax_handler()
{
// Verify nonce for security
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'tour_ajax_nonce')) {
wp_die('Security check failed');
}
// Get the page number
$paged = isset($_POST['paged']) ? intval($_POST['paged']) : 1;
// Build query args
$args = array(
'post_type' => 'tour',
'posts_per_page' => 9,
'paged' => $paged,
'post_status' => 'publish'
);
// Add search query if exists
if (isset($_POST['s']) && !empty($_POST['s'])) {
$args['s'] = sanitize_text_field($_POST['s']);
}
// Add destination filter
if (isset($_POST['destination']) && !empty($_POST['destination'])) {
$args['meta_query'][] = array(
'key' => 'tour_destination',
'value' => sanitize_text_field($_POST['destination']),
'compare' => 'LIKE'
);
}
// Add check-in date filter
if (isset($_POST['check_in']) && !empty($_POST['check_in'])) {
$args['meta_query'][] = array(
'key' => 'tour_start_date',
'value' => sanitize_text_field($_POST['check_in']),
'compare' => '>=',
'type' => 'DATE'
);
}
// Add duration filter
if (isset($_POST['tour_duration_days']) && !empty($_POST['tour_duration_days'])) {
$args['tax_query'][] = array(
'taxonomy' => 'tour_duration_days',
'field' => 'term_id',
'terms' => intval($_POST['tour_duration_days']),
'operator' => 'IN'
);
}
// Add price range filter
if (isset($_POST['price_range']) && !empty($_POST['price_range'])) {
$price_range = explode(';', sanitize_text_field($_POST['price_range']));
if (count($price_range) === 2) {
$args['meta_query'][] = array(
'key' => 'tour_price',
'value' => array_map('intval', $price_range),
'type' => 'NUMERIC',
'compare' => 'BETWEEN'
);
}
}
// Add category filter
if (isset($_POST['tour_category']) && !empty($_POST['tour_category'])) {
$args['tax_query'][] = array(
'taxonomy' => 'tour_category',
'field' => 'term_id',
'terms' => array_map('intval', $_POST['tour_category']),
'operator' => 'IN'
);
}
// Add rating filter
if (isset($_POST['rating']) && !empty($_POST['rating'])) {
$args['meta_query'][] = array(
'key' => 'tour_rating',
'value' => array_map('intval', $_POST['rating']),
'type' => 'NUMERIC',
'compare' => 'IN'
);
}
// Add sorting
if (isset($_POST['sort']) && !empty($_POST['sort'])) {
switch ($_POST['sort']) {
case 'price_low':
$args['meta_key'] = 'tour_price';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'ASC';
break;
case 'price_high':
$args['meta_key'] = 'tour_price';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
case 'newest':
$args['orderby'] = 'date';
$args['order'] = 'DESC';
break;
case 'rating':
$args['meta_key'] = 'tour_rating';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
case 'reviews':
$args['meta_key'] = 'tour_reviews';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
default:
// Recommended - default ordering
break;
}
}
// Execute query
$tours_query = new WP_Query($args);
// Start output buffer to capture template output
ob_start();
if ($tours_query->have_posts()) :
while ($tours_query->have_posts()) : $tours_query->the_post();
// Get tour data
$tour_price = get_post_meta(get_the_ID(), 'tour_price', true);
$tour_offer_price = get_post_meta(get_the_ID(), 'tour_offer_price', true);
$tour_duration = get_post_meta(get_the_ID(), 'tour_duration', true);
$tour_guests = get_post_meta(get_the_ID(), 'tour_guests', true);
$tour_rating = get_post_meta(get_the_ID(), 'tour_rating', true);
$tour_reviews = get_post_meta(get_the_ID(), 'tour_reviews', true);
$tour_destination = get_post_meta(get_the_ID(), 'tour_destination', true);
$tour_types = get_the_terms(get_the_ID(), 'tour_category');
$gallery = get_post_meta(get_the_ID(), 'tour_gallery', true);
$author_id = get_the_author_meta('ID');
$author_id_post = get_the_author_meta('ID');
$author_avatar = get_avatar_url($author_id, array('size' => 96));
$author_tours_page = function_exists('dreamstour_fl_framework_getoptions') ? dreamstour_fl_framework_getoptions('author_tours_page') : 0;
$author_tours_page_url = $author_tours_page ? get_permalink($author_tours_page) : '';
$author_link = $author_tours_page_url ? add_query_arg(array(
'author_id' => (int) $author_id_post,
), $author_tours_page_url) : 'javascript:void(0);';
// Get first image from gallery or featured image
$tour_image = '';
if (!empty($gallery) && is_array($gallery)) {
$tour_image = wp_get_attachment_url($gallery[0]);
}
if (!$tour_image && has_post_thumbnail()) {
$tour_image = get_the_post_thumbnail_url(get_the_ID(), 'large');
}
if (!$tour_image) {
$tour_image = get_template_directory_uri() . '/assets/img/tours/tours-07.jpg';
}
?>
<!-- Tours Grid -->
<div class="col-xxl-4 col-md-6 d-flex">
<div class="place-item mb-4 flex-fill">
<div class="place-img">
<a href="<?php the_permalink(); ?>">
<img src="<?php echo esc_url($tour_image); ?>" class="img-fluid" alt="<?php the_title_attribute(); ?>">
</a>
<div class="fav-item">
<a href="javascript:void(0);" class="fav-icon">
<i class="isax isax-heart5"></i>
</a>
<span class="badge bg-info d-inline-flex align-items-center"><i class="isax isax-ranking me-1"></i><?php esc_html_e('Trending','dreams-tour'); ?></span>
</div>
</div>
<div class="place-content">
<div class="d-flex align-items-center justify-content-between mb-1">
<div class="d-flex flex-wrap align-items-center">
<span class="me-1"><i class="ti ti-receipt text-primary"></i></span>
<p class="fs-14 text-gray-9">
<?php
if ($tour_types && !is_wp_error($tour_types)) {
echo esc_html($tour_types[0]->name);
} else {
esc_html_e('Tour','dreams-tour');
}
?>
</p>
</div>
<span class="d-inline-block border vertical-splits">
<span class="bglight text-light d-flex align-items-center justify-content-center"></span>
</span>
<div class="d-flex align-items-center flex-wrap">
<span class="badge badge-warning badge-xs text-gray-9 fs-13 fw-medium me-1"><?php echo $tour_rating ? esc_html($tour_rating) : '4.5'; ?></span>
<p class="fs-14">(<?php echo $tour_reviews ? esc_html($tour_reviews) : '0'; ?> <?php esc_html_e('Reviews','dreams-tour'); ?>)</p>
</div>
</div>
<h5 class="mb-1 text-truncate"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h5>
<p class="d-flex align-items-center mb-3"><i class="isax isax-location5 me-2"></i><?php echo $tour_destination ? esc_html($tour_destination) : get_the_excerpt(); ?></p>
<div class="mb-3">
<h6 class="d-flex align-items-center text-gray-6 fs-14 fw-normal"><?php esc_html_e('Starts From','dreams-tour'); ?>
<span class="ms-1 fs-18 fw-semibold text-primary"><?php echo get_woocommerce_currency_symbol(); ?><?php echo $tour_price ? esc_html($tour_price) : '0'; ?></span>
<?php if ($tour_offer_price) : ?>
<span class="ms-1 fs-18 fw-semibold text-gray-3 text-decoration-line-through"><?php echo get_woocommerce_currency_symbol(); ?><?php echo esc_html($tour_offer_price); ?></span>
<?php endif; ?>
</h6>
</div>
<div class="d-flex align-items-center justify-content-between border-top pt-3">
<div class="d-flex flex-wrap align-items-center me-2">
<span class="me-1"><i class="isax isax-calendar-tick text-gray-6"></i></span>
<p class="fs-14 text-gray-9"><?php echo $tour_duration ? esc_html($tour_duration) : 'N/A'; ?></p>
</div>
<span class="d-inline-block border vertical-splits">
<span class="bglight text-light d-flex align-items-center justify-content-center"></span>
</span>
<div class="ms-2 d-flex align-items-center">
<p class="fs-14 text-gray-9 mb-0 text-truncate d-flex align-items-center">
<i class="isax isax-profile-2user me-1"></i><?php echo $tour_guests ? esc_html($tour_guests) : '0'; ?> <?php esc_html_e('Guests','dreams-tour'); ?>
</p>
<a href="<?php echo esc_url($author_link); ?>" class="avatar avatar-sm ms-3">
<img src="<?php echo esc_url($author_avatar); ?>" class="rounded-circle" alt="<?php the_author(); ?>">
</a>
</div>
</div>
</div>
</div>
</div>
<!-- /Tours Grid -->
<?php endwhile;
else :
?>
<div class="col-12">
<div class="alert alert-info"><?php esc_html_e('No tours found matching your criteria.','dreams-tour'); ?></div>
</div>
<?php
endif;
// Get the tours HTML
$tours_html = ob_get_clean();
// Generate pagination
ob_start();
$big = 999999999; // need an unlikely integer
echo paginate_links(array(
'base' => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
'format' => '?paged=%#%',
'current' => $paged,
'total' => $tours_query->max_num_pages,
'prev_text' => '<span aria-hidden="true"><i class="fa-solid fa-chevron-left"></i></span>',
'next_text' => '<span aria-hidden="true"><i class="fa-solid fa-chevron-right"></i></span>',
));
$pagination_html = ob_get_clean();
// Return JSON response
wp_send_json_success(array(
'tours_html' => $tours_html,
'pagination_html' => $pagination_html,
'found_posts' => $tours_query->found_posts,
'max_num_pages' => $tours_query->max_num_pages
));
wp_die(); // Always die in AJAX functions
}
// Enqueue tour AJAX script
function enqueue_tour_ajax_script()
{
$should_enqueue = is_page_template('tour-grid-template.php') || is_singular('tour');
if ($should_enqueue) {
wp_enqueue_script('tour-ajax', plugin_dir_url(__FILE__) . 'assets/js/script.js', array('jquery'), '1.0', true);
wp_localize_script('tour-ajax', 'tour_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('tour_ajax_nonce')
));
}
}
add_action('wp_enqueue_scripts', 'enqueue_tour_ajax_script');
// Function to create custom booking table
function dreamstour_create_booking_table()
{
global $wpdb;
$table_name = $wpdb->prefix . 'dreamstour_booking';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
booking_id bigint(20) NOT NULL AUTO_INCREMENT,
tour_id bigint(20) NOT NULL,
user_id bigint(20) DEFAULT 0,
booking_date datetime DEFAULT CURRENT_TIMESTAMP,
departure_date date NOT NULL,
return_date date NOT NULL,
adults int(11) NOT NULL DEFAULT 1,
children int(11) NOT NULL DEFAULT 0,
total_price decimal(10,2) NOT NULL,
booking_status varchar(50) DEFAULT 'pending',
payment_status varchar(50) DEFAULT 'pending',
customer_name varchar(100) NOT NULL,
customer_email varchar(100) NOT NULL,
customer_phone varchar(20),
special_requests text,
booking_reference varchar(50) UNIQUE,
product_id bigint(20) DEFAULT 0,
order_id bigint(20) DEFAULT 0,
order_status varchar(50) DEFAULT '',
payment_method varchar(100) DEFAULT '',
cancel_reason text,
PRIMARY KEY (booking_id),
KEY tour_id (tour_id),
KEY user_id (user_id),
KEY booking_status (booking_status),
KEY order_id (order_id),
KEY product_id (product_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
// Hook this function to plugin activation or theme setup
register_activation_hook(__FILE__, 'dreamstour_create_booking_table');
// Ensure new columns exist for existing installs
function dreamstour_maybe_update_booking_table() {
global $wpdb;
$table = $wpdb->prefix . 'dreamstour_booking';
$columns = $wpdb->get_col("SHOW COLUMNS FROM $table", 0);
if (empty($columns)) {
return;
}
$additions = [];
if (!in_array('product_id', $columns, true)) {
$additions[] = 'ADD COLUMN product_id bigint(20) DEFAULT 0';
}
if (!in_array('order_id', $columns, true)) {
$additions[] = 'ADD COLUMN order_id bigint(20) DEFAULT 0';
}
if (!in_array('order_status', $columns, true)) {
$additions[] = "ADD COLUMN order_status varchar(50) DEFAULT ''";
}
if (!in_array('payment_method', $columns, true)) {
$additions[] = "ADD COLUMN payment_method varchar(100) DEFAULT ''";
}
if (!in_array('cancel_reason', $columns, true)) {
$additions[] = 'ADD COLUMN cancel_reason text';
}
if (!empty($additions)) {
$sql = 'ALTER TABLE ' . $table . ' ' . implode(', ', $additions);
$wpdb->query($sql); // phpcs:ignore WordPress.DB.PreparedSQL
// Add keys if missing (best-effort)
$wpdb->query('CREATE INDEX order_id ON ' . $table . ' (order_id)'); // phpcs:ignore
$wpdb->query('CREATE INDEX product_id ON ' . $table . ' (product_id)'); // phpcs:ignore
}
}
add_action('plugins_loaded', 'dreamstour_maybe_update_booking_table');
// Link bookings to WooCommerce order and product
function dreamstour_link_booking_to_order($item, $cart_item_key, $values, $order) {
if (empty($values['dreamstour_booking']) || !is_array($values['dreamstour_booking'])) {
return;
}
$bk = $values['dreamstour_booking'];
$booking_id = isset($bk['booking_id']) ? (int) $bk['booking_id'] : 0;
$tour_id = isset($bk['tour_id']) ? (int) $bk['tour_id'] : 0;
if ($booking_id && $tour_id) {
global $wpdb;
$table = $wpdb->prefix . 'dreamstour_booking';
$product_id = (int) $item->get_product_id();
$payment_method = method_exists($order, 'get_payment_method_title') ? (string) $order->get_payment_method_title() : '';
$order_status = method_exists($order, 'get_status') ? (string) $order->get_status() : '';
$wpdb->update(
$table,
[
'order_id' => (int) $order->get_id(),
'product_id' => $product_id,
'payment_method' => $payment_method,
'order_status' => $order_status,
],
[
'booking_id' => $booking_id,
'tour_id' => $tour_id,
],
['%d','%d','%s','%s'],
['%d','%d']
);
// Save booking reference/id on the order for traceability
$order->update_meta_data('_dreamstour_booking_id', $booking_id);
if (!empty($bk['booking_ref'])) {
$order->update_meta_data('_dreamstour_booking_ref', sanitize_text_field($bk['booking_ref']));
}
}
}
add_action('woocommerce_checkout_create_order_line_item', 'dreamstour_link_booking_to_order', 10, 4);
// Keep booking status in sync with order status changes
function dreamstour_sync_booking_status($order_id, $old_status, $new_status, $order) {
global $wpdb;
$table = $wpdb->prefix . 'dreamstour_booking';
$map = [
'pending' => 'pending',
'processing' => 'confirmed',
'on-hold' => 'pending',
'completed' => 'completed',
'cancelled' => 'cancelled',
'refunded' => 'cancelled',
'failed' => 'cancelled',
];
$booking_status = isset($map[$new_status]) ? $map[$new_status] : $new_status;
$payment_method = method_exists($order, 'get_payment_method_title') ? (string) $order->get_payment_method_title() : '';
$wpdb->update(
$table,
[
'booking_status' => $booking_status,
'order_status' => $new_status,
'payment_status' => in_array($new_status, ['processing','completed'], true) ? 'paid' : 'pending',
'payment_method' => $payment_method,
],
['order_id' => (int) $order_id],
['%s','%s','%s','%s'],
['%d']
);
}
add_action('woocommerce_order_status_changed', 'dreamstour_sync_booking_status', 10, 4);
// Handle booking cancel (agent initiated)
function dreamstour_cancel_booking_handler() {
if (!is_user_logged_in()) {
wp_die(__('You must be logged in to cancel a booking.', 'dreams-tour'));
}
if (!isset($_POST['dreamstour_cancel_nonce']) || !wp_verify_nonce($_POST['dreamstour_cancel_nonce'], 'dreamstour_cancel_booking')) {
wp_die(__('Security check failed.', 'dreams-tour'));
}
global $wpdb;
$booking_id = isset($_POST['booking_id']) ? absint($_POST['booking_id']) : 0;
$reason = isset($_POST['cancel_reason']) ? sanitize_textarea_field(wp_unslash($_POST['cancel_reason'])) : '';
if (!$booking_id) {
wp_die(__('Invalid booking.', 'dreams-tour'));
}
$table = $wpdb->prefix . 'dreamstour_booking';
// Verify current user owns the tour of this booking
$posts = $wpdb->posts;
$owner_id = (int) get_current_user_id();
$sql = "SELECT p.post_author FROM $table b INNER JOIN $posts p ON p.ID = b.tour_id WHERE b.booking_id = %d";
$author = (int) $wpdb->get_var($wpdb->prepare($sql, $booking_id));
if ($author !== $owner_id) {
wp_die(__('You are not allowed to cancel this booking.', 'dreams-tour'));
}
$wpdb->update(
$table,
[
'booking_status' => 'cancelled',
'cancel_reason' => $reason,
],
['booking_id' => $booking_id],
['%s','%s'],
['%d']
);
// Optionally cancel Woo order if exists
$order_id = (int) $wpdb->get_var($wpdb->prepare("SELECT order_id FROM $table WHERE booking_id = %d", $booking_id));
if ($order_id && function_exists('wc_get_order')) {
$order = wc_get_order($order_id);
if ($order && ! $order->has_status(['cancelled','refunded','failed'])) {
$order->update_status('cancelled', __('Cancelled by agent from dashboard', 'dreams-tour'));
}
}
$redirect = isset($_POST['redirect']) ? esc_url_raw($_POST['redirect']) : home_url('/');
wp_safe_redirect(add_query_arg(['ref' => 'bookings', 'type' => 'agent', 'cancelled' => 1], $redirect));
exit;
}
add_action('admin_post_dreamstour_cancel_booking', 'dreamstour_cancel_booking_handler');
// Handle tour booking form submission
function dreamstour_process_booking()
{
// Verify nonce
if (!wp_verify_nonce($_POST['tour_booking_nonce'], 'tour_booking_nonce')) {
wp_die('Security check failed');
}
$booking_allow_guest_booking = function_exists('dreamstour_fl_framework_getoptions') ? (bool) dreamstour_fl_framework_getoptions('booking_allow_guest_booking') : false;
$booking_allow_customer_dates = function_exists('dreamstour_fl_framework_getoptions') ? (bool) dreamstour_fl_framework_getoptions('booking_allow_customer_dates') : false;
if ( ! is_user_logged_in() ) {
if ( ! $booking_allow_guest_booking ) {
wp_send_json_error(array(
'message' => __('Only customers can book this tour.', 'dreams-tour')
));
}
} else {
$current_user = wp_get_current_user();
if ( ! in_array( 'regular_user', (array) $current_user->roles, true ) ) {
wp_send_json_error(array(
'message' => __('Only customers can book this tour.', 'dreams-tour')
));
}
}
global $wpdb;
// Sanitize input data
$tour_id = intval($_POST['tour_id']);
$user_id = is_user_logged_in() ? get_current_user_id() : 0;
$adults = intval($_POST['adults']);
$children = intval($_POST['children']);
$tour_price = floatval($_POST['tour_price']);
$departure_date = sanitize_text_field($_POST['departure_date']);
$return_date = sanitize_text_field($_POST['return_date']);
$customer_name = sanitize_text_field($_POST['customer_name']);
$customer_email = sanitize_email($_POST['customer_email']);
$customer_phone = sanitize_text_field($_POST['customer_phone']);
$special_requests = sanitize_textarea_field($_POST['special_requests']);
// Calculate total price
$children_price = $children * ($tour_price * 0.7); // 30% discount for children
$total_price = ($adults * $tour_price) + $children_price;
if ( ! $booking_allow_customer_dates ) {
$availability_check = dreamstour_check_availability($tour_id, $departure_date, $adults + $children);
}
if ( $departure_date < current_time('Y-m-d') ) {
wp_send_json_error( array(
'message' => __( 'Booking is expired Cur date-'.current_time('Y-m-d'). 'Dep date- ' .$departure_date, 'dreams-tour' )
) );
}
if ( ! $booking_allow_customer_dates && isset($availability_check) && ! $availability_check['available']) {
wp_send_json_error(array(
'message' => $availability_check['message']
));
}
// Generate a provisional reference to carry along via cart meta
$booking_reference = 'TB-' . date('Ymd') . '-' . strtoupper(bin2hex(random_bytes(4)));
// Add linked WooCommerce product to cart and redirect to WC checkout (if WooCommerce active)
$checkout_url = '';
if (function_exists('WC')) {
// Get linked product id created when adding/updating a tour
$linked_product_id = (int) get_post_meta($tour_id, '_linked_product_id', true);
if ($linked_product_id) {
// Total people as quantity
$quantity = max(1, (int) ($adults + $children));
// Ensure cart available
if (WC()->cart) {
// Optionally keep cart clean (one tour per order)
WC()->cart->empty_cart();
// Attach booking metadata to cart item (no booking_id yet)
$cart_item_data = array(
'dreamstour_booking' => array(
'tour_id' => $tour_id,
'departure_date' => $departure_date,
'return_date' => $return_date,
'adults' => $adults,
'children' => $children,
'total_price' => $total_price,
'customer_name' => $customer_name,
'customer_email' => $customer_email,
'customer_phone' => $customer_phone,
'special_requests'=> $special_requests,
'booking_ref' => $booking_reference,
'user_id' => $user_id,
),
);
WC()->cart->add_to_cart($linked_product_id, $quantity, 0, array(), $cart_item_data);
// WooCommerce checkout URL
$checkout_url = wc_get_checkout_url();
}
}
}
// Fallback to custom checkout page if WooCommerce not available
if (empty($checkout_url)) {
$checkout_page_id = get_option('tour_checkout_page_id');
$checkout_url = $checkout_page_id ? get_permalink($checkout_page_id) : home_url('/checkout/');
}
wp_send_json_success(array(
'message' => 'Availability confirmed. Proceed to checkout.',
'redirect_url' => $checkout_url
));
}
add_action('wp_ajax_process_tour_booking', 'dreamstour_process_booking');
add_action('wp_ajax_nopriv_process_tour_booking', 'dreamstour_process_booking');
add_action('woocommerce_checkout_create_order_line_item', function($item, $cart_item_key, $values, $order) {
if (!empty($values['dreamstour_booking']) && is_array($values['dreamstour_booking'])) {
$item->add_meta_data('_dreamstour_booking', $values['dreamstour_booking'], true);
}
}, 10, 4);
function dreamstour_render_booking_details_on_order_item($item_id, $item, $order, $plain_text) {
$booking_meta = $item->get_meta('_dreamstour_booking', true);
if (empty($booking_meta) || !is_array($booking_meta)) {
return;
}
$departure_date = isset($booking_meta['departure_date']) ? $booking_meta['departure_date'] : '';
$return_date = isset($booking_meta['return_date']) ? $booking_meta['return_date'] : '';
$adults = isset($booking_meta['adults']) ? (int) $booking_meta['adults'] : 0;
$children = isset($booking_meta['children']) ? (int) $booking_meta['children'] : 0;
$total_price = isset($booking_meta['total_price']) ? (float) $booking_meta['total_price'] : (float) $item->get_total();
$booking_reference = isset($booking_meta['booking_ref']) ? $booking_meta['booking_ref'] : '';
$date_label = '';
if ($departure_date && $return_date) {
$date_label = sprintf('%s - %s', $departure_date, $return_date);
} elseif ($departure_date) {
$date_label = $departure_date;
}
$people_label_parts = array();
if ($adults > 0) {
$people_label_parts[] = sprintf(_n('%d Adult', '%d Adults', $adults, 'dreams-tour'), $adults);
}
if ($children > 0) {
$people_label_parts[] = sprintf(_n('%d Child', '%d Children', $children, 'dreams-tour'), $children);
}
$people_label = implode(', ', $people_label_parts);
$currency = method_exists($order, 'get_currency') ? $order->get_currency() : get_woocommerce_currency();
$price_formatted = wc_price($total_price, array('currency' => $currency));
$billing_email = method_exists($order, 'get_billing_email') ? $order->get_billing_email() : '';
$billing_address = method_exists($order, 'get_formatted_billing_address') ? $order->get_formatted_billing_address() : '';
if ($plain_text) {
echo "\n" . __('Booking Details:', 'dreams-tour') . "\n";
if ($booking_reference) {
echo sprintf("- %s %s\n", __('Reference:', 'dreams-tour'), $booking_reference);
}
if ($date_label) {
echo sprintf("- %s %s\n", __('Dates:', 'dreams-tour'), $date_label);
}
if ($people_label) {
echo sprintf("- %s %s\n", __('Guests:', 'dreams-tour'), $people_label);
}
if ($billing_email) {
echo sprintf("- %s %s\n", __('Email:', 'dreams-tour'), $billing_email);
}
if ($billing_address) {
$billing_address_plain = wp_strip_all_tags($billing_address);
echo sprintf("- %s %s\n", __('Address:', 'dreams-tour'), $billing_address_plain);
}
echo sprintf("- %s %s\n", __('Price:', 'dreams-tour'), wp_strip_all_tags($price_formatted));
} else {
echo '<div class="dreamstour-booking-details">';
echo '<strong>' . esc_html__('Booking Details:', 'dreams-tour') . '</strong><br />';
if ($booking_reference) {
echo '<small>' . esc_html__('Reference:', 'dreams-tour') . ' ' . esc_html($booking_reference) . '</small><br />';
}
if ($date_label) {
echo '<small>' . esc_html__('Dates:', 'dreams-tour') . ' ' . esc_html($date_label) . '</small><br />';
}
if ($people_label) {
echo '<small>' . esc_html__('Guests:', 'dreams-tour') . ' ' . esc_html($people_label) . '</small><br />';
}
if ($billing_email) {
echo '<small>' . esc_html__('Email:', 'dreams-tour') . ' ' . esc_html($billing_email) . '</small><br />';
}
if ($billing_address) {
echo '<small>' . esc_html__('Address:', 'dreams-tour') . '<br />' . wp_kses_post($billing_address) . '</small><br />';
}
echo '<small>' . esc_html__('Price:', 'dreams-tour') . ' ' . wp_kses_post($price_formatted) . '</small>';
echo '</div>';
}
}
add_action('woocommerce_order_item_meta_end', 'dreamstour_render_booking_details_on_order_item', 10, 4);
// After order is placed, create booking record(s) in custom table
add_action('woocommerce_thankyou', function($order_id){
if (!function_exists('wc_get_order') || !$order_id) return;
$order = wc_get_order($order_id);
if (!$order) return;
global $wpdb;
$table_name = $wpdb->prefix . 'dreamstour_booking';
foreach ($order->get_items() as $item_id => $item) {
$bk = $item->get_meta('_dreamstour_booking', true);
if (empty($bk) || !is_array($bk)) {
continue;
}
$tour_id = isset($bk['tour_id']) ? (int)$bk['tour_id'] : 0;
$user_id = isset($bk['user_id']) ? (int)$bk['user_id'] : 0;
$product_id = (int)$item->get_product_id();
$departure_date = isset($bk['departure_date']) ? sanitize_text_field($bk['departure_date']) : '';
$return_date = isset($bk['return_date']) ? sanitize_text_field($bk['return_date']) : '';
$adults = isset($bk['adults']) ? (int)$bk['adults'] : 0;
$children = isset($bk['children']) ? (int)$bk['children'] : 0;
$total_price = isset($bk['total_price']) ? (float)$bk['total_price'] : (float)$item->get_total();
$customer_name = isset($bk['customer_name']) ? sanitize_text_field($bk['customer_name']) : '';
$customer_email = isset($bk['customer_email']) ? sanitize_email($bk['customer_email']) : '';
$customer_phone = isset($bk['customer_phone']) ? sanitize_text_field($bk['customer_phone']) : '';
$special_requests= isset($bk['special_requests']) ? sanitize_textarea_field($bk['special_requests']) : '';
$booking_reference = isset($bk['booking_ref']) ? sanitize_text_field($bk['booking_ref']) : ('TB-' . date('Ymd') . '-' . strtoupper(bin2hex(random_bytes(4))));
if (!$tour_id) continue;
// Avoid duplicate insert if this was already created for this order+ref
$exists = (int)$wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table_name} WHERE order_id = %d AND booking_reference = %s", $order_id, $booking_reference));
if ($exists > 0) {
continue;
}
// Determine payment and booking status
$payment_status = $order->is_paid() ? 'paid' : 'pending';
$booking_status = 'pending';
// Insert booking now that we have an order
$wpdb->insert(
$table_name,
array(
'tour_id' => $tour_id,
'user_id' => $user_id,
'order_id' => (int)$order_id,
'departure_date' => $departure_date,
'return_date' => $return_date,
'adults' => $adults,
'children' => $children,
'total_price' => $total_price,
'booking_status' => $booking_status,
'payment_status' => $payment_status,
'customer_name' => $customer_name,
'customer_email' => $customer_email,
'customer_phone' => $customer_phone,
'special_requests' => $special_requests,
'booking_reference'=> $booking_reference,
'booking_date' => current_time('mysql'),
'product_id' => $product_id,
'payment_method' => method_exists($order, 'get_payment_method_title') ? (string) $order->get_payment_method_title() : '',
'order_status' => method_exists($order, 'get_status') ? (string) $order->get_status() : '',
),
array('%d','%d','%d','%s','%s','%d','%d','%f','%s','%s','%s','%s','%s','%s','%s','%s','%d','%s','%s')
);
}
}, 10, 1);
// Availability check function
function dreamstour_check_availability($tour_id, $date, $total_people)
{
global $wpdb;
$table_name = $wpdb->prefix . 'dreamstour_booking';
// Get tour capacity
$tour_capacity = get_post_meta($tour_id, 'tour_people_limit', true);
$tour_capacity = $tour_capacity ? intval($tour_capacity) : 20; // Default capacity
// Check total bookings for this date
$booked_count = $wpdb->get_var($wpdb->prepare(
"SELECT SUM(adults + children)
FROM $table_name
WHERE tour_id = %d
AND departure_date = %s
AND booking_status IN ('pending', 'confirmed')",
$tour_id,
$date
));
$booked_count = $booked_count ? $booked_count : 0;
$available_spots = $tour_capacity - $booked_count;
if ($total_people > $available_spots) {
return array(
'available' => false,
'message' => sprintf(
'Only %d spots available for this date. Please reduce the number of people or choose another date.',
$available_spots
)
);
}
return array(
'available' => true,
'message' => 'Available'
);
}
/**
* Ensure agent role has necessary capabilities
*/
function dreamstour_ensure_agent_capabilities()
{
$agent_role = get_role('agent');
if ($agent_role) {
$agent_role->add_cap('read');
$agent_role->add_cap('upload_files');
$agent_role->add_cap('edit_posts');
$agent_role->add_cap('publish_posts');
$agent_role->add_cap('edit_published_posts');
$agent_role->add_cap('delete_posts');
}
}
add_action('init', 'dreamstour_ensure_agent_capabilities');
add_action('init', function() {
if (!current_user_can('administrator') && !is_admin()) {
show_admin_bar(false);
}
});
add_filter('login_redirect', 'redirect_admin_to_dashboard', 10, 3);
function redirect_admin_to_dashboard($redirect_to, $request, $user) {
// Check if a valid user is logged in
if (isset($user->roles) && is_array($user->roles)) {
// If the user is an administrator
if (in_array('administrator', $user->roles)) {
return admin_url(); // Redirect to /wp-admin/
} else {
// Redirect other users to homepage (or any other page)
return home_url('/');
}
}
return $redirect_to;
}
/**
* Limit media library results for agents to only their own uploads (media modal)
*/
function dreamstour_limit_agent_attachments($query_args)
{
if (! is_user_logged_in()) {
return $query_args;
}
$user = wp_get_current_user();
if (in_array('agent', (array) $user->roles, true) && ! current_user_can('manage_options')) {
$query_args['author'] = (int) $user->ID;
}
return $query_args;
}
add_filter('ajax_query_attachments_args', 'dreamstour_limit_agent_attachments');
/**
* Limit admin Media Library list/grid to own uploads for agents
*/
function dreamstour_restrict_media_library_query($wp_query)
{
if (! is_admin() || ! is_user_logged_in()) {
return;
}
// Only affect main media queries on upload.php or media modal related screens
$screen = function_exists('get_current_screen') ? get_current_screen() : null;
if ($screen && $screen->base !== 'upload') {
// Still allow for cases where screen isn't available (e.g., AJAX) handled by the filter above
}
$user = wp_get_current_user();
if (in_array('agent', (array) $user->roles, true) && ! current_user_can('manage_options')) {
$wp_query->set('author', (int) $user->ID);
}
}
add_action('pre_get_posts', 'dreamstour_restrict_media_library_query');
// Dashboard shortcode
add_shortcode('dreamstour_dashboard', 'dreamstour_dashboard_shortcode');
function dreamstour_dashboard_shortcode($atts) {
ob_start();
if (!is_user_logged_in()) {
echo '<div class="alert alert-danger my-2 py-3" role="alert">' . esc_html__('Please log in to access the dashboard.', 'dreamstour') . '</div>';
return ob_get_clean();
}
// Load the dashboard template
include( DREAMSTOUR_URL.'/templates/dashboard/dashboard-main.php' );
return ob_get_clean();
}
/**
* 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' ) );
}
});
// 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'); ?>>Default Header</option>
<option value="style1" <?php selected($current_style, 'style1'); ?>>Header Style 1</option>
<option value="style2" <?php selected($current_style, 'style2'); ?>>Header Style 2</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">Header Style</span>
<select name="_header_style">
<option value="default">Default</option>
<option value="style1">Style 1</option>
<option value="style2">Style 2</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'); ?>>Default Footer</option>
<option value="style1" <?php selected($current_style, 'style1'); ?>>Footer Style 1</option>
<option value="style2" <?php selected($current_style, 'style2'); ?>>Footer Style 2</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">Footer Style</span>
<select name="_footer_style">
<option value="default">Default</option>
<option value="style1">Style 1</option>
<option value="style2">Style 2</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');