Skip to content

Instantly share code, notes, and snippets.

@thisissandip
Created February 24, 2026 09:39
Show Gist options
  • Select an option

  • Save thisissandip/a03bfd81dc3616917c73d51d9c8954a9 to your computer and use it in GitHub Desktop.

Select an option

Save thisissandip/a03bfd81dc3616917c73d51d9c8954a9 to your computer and use it in GitHub Desktop.
<?php
/**
* Cross-Resource Booking Blocker
*
* When a booking is paid using one resource, block the related resources
* to prevent double-booking of shared spaces.
*/
// Define the resource relationships (update these IDs after creating resources)
define('PRIMARY_RESOURCE_ID', 123); // Replace with actual resource ID (e.g., Entire Space)
define('SECONDARY_RESOURCE_A_ID', 456); // Replace with actual resource ID (e.g., Space A)
define('SECONDARY_RESOURCE_B_ID', 789); // Replace with actual resource ID (e.g., Space B)
function get_resources_to_block($booked_resource_id) {
$resources_to_block = [];
switch ($booked_resource_id) {
case PRIMARY_RESOURCE_ID:
// Primary resource booked → block secondary resources
$resources_to_block = [SECONDARY_RESOURCE_A_ID, SECONDARY_RESOURCE_B_ID];
break;
case SECONDARY_RESOURCE_A_ID:
case SECONDARY_RESOURCE_B_ID:
// Secondary resource booked → block primary resource
$resources_to_block = [PRIMARY_RESOURCE_ID];
break;
}
return $resources_to_block;
}
function get_resource_name($resource_id) {
$resource_name = get_the_title($resource_id);
return $resource_name ? $resource_name : 'Unknown Resource';
}
function block_related_resources_on_payment($booking_id) {
$booking = new WC_Booking($booking_id);
$resource_id = $booking->get_resource_id();
$start_time = $booking->get_start();
$end_time = $booking->get_end();
if (!$resource_id) {
return;
}
$resources_to_block = get_resources_to_block($resource_id);
if (empty($resources_to_block) || !$start_time || !$end_time) {
return;
}
$from_date = date('Y-m-d', $start_time);
$to_date = date('Y-m-d', $end_time);
$from_time = date('H:i', $start_time);
$to_time = date('H:i', $end_time);
$is_full_day = ($from_time === '00:00' && ($to_time === '00:00' || $to_time === '23:59'));
// Build the availability rule
$availability_rule = [
'bookable' => 'no',
'priority' => 1,
'booking_id' => $booking_id, // Track which booking created this rule (for cleanup)
];
if ($is_full_day) {
$availability_rule['type'] = 'custom';
$availability_rule['from'] = $from_date;
$availability_rule['to'] = $to_date;
} else {
$availability_rule['type'] = 'custom:daterange';
$availability_rule['from_date'] = $from_date;
$availability_rule['to_date'] = $to_date;
$availability_rule['from'] = $from_time;
$availability_rule['to'] = $to_time;
}
// Get booked resource name for logging
$booked_resource_name = get_resource_name($resource_id);
// Add blocking rule to each related resource
foreach ($resources_to_block as $block_resource_id) {
$existing_availability = get_post_meta($block_resource_id, '_wc_booking_availability', true);
if (!is_array($existing_availability)) {
$existing_availability = [];
}
$existing_availability[] = $availability_rule;
update_post_meta($block_resource_id, '_wc_booking_availability', $existing_availability);
// Log the action
if (function_exists('wc_get_logger')) {
$logger = wc_get_logger();
$blocked_resource_name = get_resource_name($block_resource_id);
if ($is_full_day) {
$log_message = sprintf(
'Booking #%d paid: "%s" (Resource ID: %d) was blocked from %s to %s (full day) — triggered by booking of "%s" (Resource ID: %d)',
$booking_id,
$blocked_resource_name,
$block_resource_id,
$from_date,
$to_date,
$booked_resource_name,
$resource_id
);
} else {
$log_message = sprintf(
'Booking #%d paid: "%s" (Resource ID: %d) was blocked from %s %s to %s %s — triggered by booking of "%s" (Resource ID: %d)',
$booking_id,
$blocked_resource_name,
$block_resource_id,
$from_date,
$from_time,
$to_date,
$to_time,
$booked_resource_name,
$resource_id
);
}
$logger->info($log_message, ['source' => 'cross-resource-blocker']);
}
}
}
// Hook into payment status transitions
add_action('woocommerce_booking_in-cart_to_paid', 'block_related_resources_on_payment');
add_action('woocommerce_booking_unpaid_to_paid', 'block_related_resources_on_payment');
add_action('woocommerce_booking_confirmed_to_paid', 'block_related_resources_on_payment');
/**
* Remove blocking rules when a booking is cancelled or refunded
*/
function unblock_related_resources_on_cancellation($booking_id) {
$booking = new WC_Booking($booking_id);
$resource_id = $booking->get_resource_id();
if (!$resource_id) {
return;
}
$resources_to_unblock = get_resources_to_block($resource_id);
if (empty($resources_to_unblock)) {
return;
}
// Get cancelled resource name for logging
$cancelled_resource_name = get_resource_name($resource_id);
foreach ($resources_to_unblock as $unblock_resource_id) {
$existing_availability = get_post_meta($unblock_resource_id, '_wc_booking_availability', true);
if (!is_array($existing_availability)) {
continue;
}
// Remove rules that were created by this booking
$updated_availability = array_filter($existing_availability, function($rule) use ($booking_id) {
return !isset($rule['booking_id']) || $rule['booking_id'] !== $booking_id;
});
update_post_meta($unblock_resource_id, '_wc_booking_availability', array_values($updated_availability));
// Log the action
if (function_exists('wc_get_logger')) {
$logger = wc_get_logger();
$unblocked_resource_name = get_resource_name($unblock_resource_id);
$log_message = sprintf(
'Booking #%d cancelled: "%s" (Resource ID: %d) was unblocked — triggered by cancellation of "%s" (Resource ID: %d)',
$booking_id,
$unblocked_resource_name,
$unblock_resource_id,
$cancelled_resource_name,
$resource_id
);
$logger->info($log_message, ['source' => 'cross-resource-blocker']);
}
}
}
// Hook into cancellation/refund status transitions
add_action('woocommerce_booking_paid_to_cancelled', 'unblock_related_resources_on_cancellation');
add_action('woocommerce_booking_confirmed_to_cancelled', 'unblock_related_resources_on_cancellation');
add_action('woocommerce_booking_paid_to_refunded', 'unblock_related_resources_on_cancellation');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment