546 lines
17 KiB
PHP
546 lines
17 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* WooCommerce Cart Handler.
|
||
|
|
*
|
||
|
|
* Handles cart item data, availability validation, and dynamic pricing.
|
||
|
|
*
|
||
|
|
* @package Magdev\WpBnb\Integration\WooCommerce
|
||
|
|
*/
|
||
|
|
|
||
|
|
declare( strict_types=1 );
|
||
|
|
|
||
|
|
namespace Magdev\WpBnb\Integration\WooCommerce;
|
||
|
|
|
||
|
|
use Magdev\WpBnb\Booking\Availability;
|
||
|
|
use Magdev\WpBnb\PostTypes\Room;
|
||
|
|
use Magdev\WpBnb\PostTypes\Service;
|
||
|
|
use Magdev\WpBnb\Pricing\Calculator;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Cart Handler class.
|
||
|
|
*
|
||
|
|
* Manages booking data in the WooCommerce cart, validates availability,
|
||
|
|
* and calculates dynamic pricing based on dates and services.
|
||
|
|
*/
|
||
|
|
final class CartHandler {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Initialize cart handler.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public static function init(): void {
|
||
|
|
// Add booking data to cart item.
|
||
|
|
add_filter( 'woocommerce_add_cart_item_data', array( self::class, 'add_cart_item_data' ), 10, 3 );
|
||
|
|
|
||
|
|
// Restore booking data from session.
|
||
|
|
add_filter( 'woocommerce_get_cart_item_from_session', array( self::class, 'get_cart_item_from_session' ), 10, 2 );
|
||
|
|
|
||
|
|
// Validate before adding to cart.
|
||
|
|
add_filter( 'woocommerce_add_to_cart_validation', array( self::class, 'validate_add_to_cart' ), 10, 5 );
|
||
|
|
|
||
|
|
// Re-validate availability on cart load.
|
||
|
|
add_action( 'woocommerce_cart_loaded_from_session', array( self::class, 'validate_cart_items' ) );
|
||
|
|
|
||
|
|
// Display booking info in cart.
|
||
|
|
add_filter( 'woocommerce_get_item_data', array( self::class, 'display_cart_item_data' ), 10, 2 );
|
||
|
|
|
||
|
|
// Calculate dynamic price.
|
||
|
|
add_action( 'woocommerce_before_calculate_totals', array( self::class, 'calculate_cart_item_prices' ) );
|
||
|
|
|
||
|
|
// Prevent quantity changes for room products.
|
||
|
|
add_filter( 'woocommerce_quantity_input_args', array( self::class, 'lock_quantity' ), 10, 2 );
|
||
|
|
|
||
|
|
// Add booking data to order item meta.
|
||
|
|
add_action( 'woocommerce_checkout_create_order_line_item', array( self::class, 'add_order_item_meta' ), 10, 4 );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add a room to cart with booking data.
|
||
|
|
*
|
||
|
|
* @param int $room_id Room post ID.
|
||
|
|
* @param string $check_in Check-in date (Y-m-d).
|
||
|
|
* @param string $check_out Check-out date (Y-m-d).
|
||
|
|
* @param int $guests Number of guests.
|
||
|
|
* @param array $services Array of service selections.
|
||
|
|
* @return string|bool Cart item key or false on failure.
|
||
|
|
*/
|
||
|
|
public static function add_room_to_cart(
|
||
|
|
int $room_id,
|
||
|
|
string $check_in,
|
||
|
|
string $check_out,
|
||
|
|
int $guests = 1,
|
||
|
|
array $services = array()
|
||
|
|
) {
|
||
|
|
// Get product ID for room.
|
||
|
|
$product_id = ProductSync::get_product_for_room( $room_id );
|
||
|
|
|
||
|
|
if ( ! $product_id ) {
|
||
|
|
// Try to sync the room first.
|
||
|
|
$product_id = ProductSync::sync_room_to_product( $room_id );
|
||
|
|
|
||
|
|
if ( ! $product_id ) {
|
||
|
|
wc_add_notice( __( 'Unable to add room to cart. Product not found.', 'wp-bnb' ), 'error' );
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store booking data in session temporarily for the filter.
|
||
|
|
WC()->session->set(
|
||
|
|
'bnb_pending_booking',
|
||
|
|
array(
|
||
|
|
'room_id' => $room_id,
|
||
|
|
'check_in' => $check_in,
|
||
|
|
'check_out' => $check_out,
|
||
|
|
'guests' => $guests,
|
||
|
|
'services' => $services,
|
||
|
|
)
|
||
|
|
);
|
||
|
|
|
||
|
|
// Add to cart.
|
||
|
|
$cart_item_key = WC()->cart->add_to_cart( $product_id, 1 );
|
||
|
|
|
||
|
|
// Clean up session.
|
||
|
|
WC()->session->set( 'bnb_pending_booking', null );
|
||
|
|
|
||
|
|
return $cart_item_key;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add booking data to cart item when adding to cart.
|
||
|
|
*
|
||
|
|
* @param array $cart_item_data Cart item data.
|
||
|
|
* @param int $product_id Product ID.
|
||
|
|
* @param int $variation_id Variation ID.
|
||
|
|
* @return array Modified cart item data.
|
||
|
|
*/
|
||
|
|
public static function add_cart_item_data( array $cart_item_data, int $product_id, int $variation_id ): array {
|
||
|
|
// Check if this is a room product.
|
||
|
|
$room_id = ProductSync::get_room_for_product( $product_id );
|
||
|
|
|
||
|
|
if ( ! $room_id ) {
|
||
|
|
return $cart_item_data;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get booking data from session or POST.
|
||
|
|
$booking_data = WC()->session->get( 'bnb_pending_booking' );
|
||
|
|
|
||
|
|
if ( ! $booking_data ) {
|
||
|
|
// Try to get from POST (for direct form submissions).
|
||
|
|
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
||
|
|
$booking_data = array(
|
||
|
|
'room_id' => isset( $_POST['bnb_room_id'] ) ? absint( $_POST['bnb_room_id'] ) : $room_id,
|
||
|
|
'check_in' => isset( $_POST['bnb_check_in'] ) ? sanitize_text_field( wp_unslash( $_POST['bnb_check_in'] ) ) : '',
|
||
|
|
'check_out' => isset( $_POST['bnb_check_out'] ) ? sanitize_text_field( wp_unslash( $_POST['bnb_check_out'] ) ) : '',
|
||
|
|
'guests' => isset( $_POST['bnb_guests'] ) ? absint( $_POST['bnb_guests'] ) : 1,
|
||
|
|
'services' => isset( $_POST['bnb_services'] ) ? self::sanitize_services( $_POST['bnb_services'] ) : array(),
|
||
|
|
);
|
||
|
|
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate required fields.
|
||
|
|
if ( empty( $booking_data['check_in'] ) || empty( $booking_data['check_out'] ) ) {
|
||
|
|
return $cart_item_data;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate nights.
|
||
|
|
$check_in = new \DateTime( $booking_data['check_in'] );
|
||
|
|
$check_out = new \DateTime( $booking_data['check_out'] );
|
||
|
|
$nights = (int) $check_in->diff( $check_out )->days;
|
||
|
|
|
||
|
|
if ( $nights < 1 ) {
|
||
|
|
return $cart_item_data;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate price breakdown.
|
||
|
|
$calculator = new Calculator( $room_id, $booking_data['check_in'], $booking_data['check_out'] );
|
||
|
|
$price_breakdown = $calculator->calculate();
|
||
|
|
$room_total = $price_breakdown['total'];
|
||
|
|
|
||
|
|
// Calculate services total.
|
||
|
|
$services_total = 0;
|
||
|
|
$services_data = array();
|
||
|
|
|
||
|
|
foreach ( $booking_data['services'] as $service_selection ) {
|
||
|
|
$service_id = $service_selection['service_id'] ?? 0;
|
||
|
|
$quantity = $service_selection['quantity'] ?? 1;
|
||
|
|
|
||
|
|
if ( ! $service_id ) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$service_price = Service::calculate_service_price( $service_id, $quantity, $nights );
|
||
|
|
$service_data = Service::get_service_data( $service_id );
|
||
|
|
|
||
|
|
$services_data[] = array(
|
||
|
|
'service_id' => $service_id,
|
||
|
|
'quantity' => $quantity,
|
||
|
|
'price' => $service_price,
|
||
|
|
'pricing_type' => $service_data['pricing_type'] ?? 'per_booking',
|
||
|
|
'name' => $service_data['name'] ?? '',
|
||
|
|
);
|
||
|
|
|
||
|
|
$services_total += $service_price;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store booking data.
|
||
|
|
$cart_item_data[ Manager::CART_ITEM_KEY ] = array(
|
||
|
|
'room_id' => $room_id,
|
||
|
|
'check_in' => $booking_data['check_in'],
|
||
|
|
'check_out' => $booking_data['check_out'],
|
||
|
|
'guests' => $booking_data['guests'],
|
||
|
|
'nights' => $nights,
|
||
|
|
'services' => $services_data,
|
||
|
|
'price_breakdown' => array(
|
||
|
|
'room_total' => $room_total,
|
||
|
|
'services_total' => $services_total,
|
||
|
|
'grand_total' => $room_total + $services_total,
|
||
|
|
'full_breakdown' => $price_breakdown,
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
// Generate unique key based on booking data to allow multiple bookings.
|
||
|
|
$cart_item_data['unique_key'] = md5(
|
||
|
|
$room_id . $booking_data['check_in'] . $booking_data['check_out'] . microtime()
|
||
|
|
);
|
||
|
|
|
||
|
|
return $cart_item_data;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Restore booking data from session.
|
||
|
|
*
|
||
|
|
* @param array $cart_item Cart item data.
|
||
|
|
* @param array $values Session values.
|
||
|
|
* @return array Modified cart item data.
|
||
|
|
*/
|
||
|
|
public static function get_cart_item_from_session( array $cart_item, array $values ): array {
|
||
|
|
if ( isset( $values[ Manager::CART_ITEM_KEY ] ) ) {
|
||
|
|
$cart_item[ Manager::CART_ITEM_KEY ] = $values[ Manager::CART_ITEM_KEY ];
|
||
|
|
}
|
||
|
|
return $cart_item;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Validate room availability before adding to cart.
|
||
|
|
*
|
||
|
|
* @param bool $passed Whether validation passed.
|
||
|
|
* @param int $product_id Product ID.
|
||
|
|
* @param int $quantity Quantity.
|
||
|
|
* @param int $variation_id Variation ID.
|
||
|
|
* @param array $variations Variations.
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function validate_add_to_cart( bool $passed, int $product_id, int $quantity, int $variation_id = 0, array $variations = array() ): bool {
|
||
|
|
// Check if this is a room product.
|
||
|
|
$room_id = ProductSync::get_room_for_product( $product_id );
|
||
|
|
|
||
|
|
if ( ! $room_id ) {
|
||
|
|
return $passed;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get booking data.
|
||
|
|
$booking_data = WC()->session->get( 'bnb_pending_booking' );
|
||
|
|
|
||
|
|
if ( ! $booking_data ) {
|
||
|
|
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
||
|
|
$booking_data = array(
|
||
|
|
'check_in' => isset( $_POST['bnb_check_in'] ) ? sanitize_text_field( wp_unslash( $_POST['bnb_check_in'] ) ) : '',
|
||
|
|
'check_out' => isset( $_POST['bnb_check_out'] ) ? sanitize_text_field( wp_unslash( $_POST['bnb_check_out'] ) ) : '',
|
||
|
|
'guests' => isset( $_POST['bnb_guests'] ) ? absint( $_POST['bnb_guests'] ) : 1,
|
||
|
|
);
|
||
|
|
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate dates provided.
|
||
|
|
if ( empty( $booking_data['check_in'] ) || empty( $booking_data['check_out'] ) ) {
|
||
|
|
wc_add_notice( __( 'Please select check-in and check-out dates.', 'wp-bnb' ), 'error' );
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate date format.
|
||
|
|
$check_in = \DateTime::createFromFormat( 'Y-m-d', $booking_data['check_in'] );
|
||
|
|
$check_out = \DateTime::createFromFormat( 'Y-m-d', $booking_data['check_out'] );
|
||
|
|
|
||
|
|
if ( ! $check_in || ! $check_out ) {
|
||
|
|
wc_add_notice( __( 'Invalid date format. Please use the date picker.', 'wp-bnb' ), 'error' );
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate check-out after check-in.
|
||
|
|
if ( $check_out <= $check_in ) {
|
||
|
|
wc_add_notice( __( 'Check-out date must be after check-in date.', 'wp-bnb' ), 'error' );
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate not in past.
|
||
|
|
$today = new \DateTime( 'today' );
|
||
|
|
if ( $check_in < $today ) {
|
||
|
|
wc_add_notice( __( 'Check-in date cannot be in the past.', 'wp-bnb' ), 'error' );
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check availability.
|
||
|
|
$is_available = Availability::check_availability(
|
||
|
|
$room_id,
|
||
|
|
$booking_data['check_in'],
|
||
|
|
$booking_data['check_out']
|
||
|
|
);
|
||
|
|
|
||
|
|
if ( ! $is_available ) {
|
||
|
|
wc_add_notice( __( 'Sorry, this room is not available for the selected dates.', 'wp-bnb' ), 'error' );
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check capacity.
|
||
|
|
$capacity = get_post_meta( $room_id, '_bnb_room_capacity', true );
|
||
|
|
if ( $capacity && $booking_data['guests'] > (int) $capacity ) {
|
||
|
|
wc_add_notice(
|
||
|
|
sprintf(
|
||
|
|
/* translators: %d: Room capacity */
|
||
|
|
__( 'This room has a maximum capacity of %d guests.', 'wp-bnb' ),
|
||
|
|
$capacity
|
||
|
|
),
|
||
|
|
'error'
|
||
|
|
);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if same room with same dates already in cart.
|
||
|
|
foreach ( WC()->cart->get_cart() as $cart_item ) {
|
||
|
|
if ( isset( $cart_item[ Manager::CART_ITEM_KEY ] ) ) {
|
||
|
|
$existing = $cart_item[ Manager::CART_ITEM_KEY ];
|
||
|
|
if ( $existing['room_id'] === $room_id
|
||
|
|
&& $existing['check_in'] === $booking_data['check_in']
|
||
|
|
&& $existing['check_out'] === $booking_data['check_out']
|
||
|
|
) {
|
||
|
|
wc_add_notice( __( 'This room with the same dates is already in your cart.', 'wp-bnb' ), 'error' );
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $passed;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Validate cart items on cart load.
|
||
|
|
*
|
||
|
|
* @param \WC_Cart $cart Cart object.
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public static function validate_cart_items( \WC_Cart $cart ): void {
|
||
|
|
$items_to_remove = array();
|
||
|
|
|
||
|
|
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
|
||
|
|
if ( ! isset( $cart_item[ Manager::CART_ITEM_KEY ] ) ) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$booking_data = $cart_item[ Manager::CART_ITEM_KEY ];
|
||
|
|
|
||
|
|
// Check if dates are still valid.
|
||
|
|
$check_in = \DateTime::createFromFormat( 'Y-m-d', $booking_data['check_in'] );
|
||
|
|
$today = new \DateTime( 'today' );
|
||
|
|
|
||
|
|
if ( $check_in < $today ) {
|
||
|
|
$items_to_remove[] = array(
|
||
|
|
'key' => $cart_item_key,
|
||
|
|
'message' => __( 'A room booking was removed because the check-in date has passed.', 'wp-bnb' ),
|
||
|
|
);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if room still available.
|
||
|
|
$is_available = Availability::check_availability(
|
||
|
|
$booking_data['room_id'],
|
||
|
|
$booking_data['check_in'],
|
||
|
|
$booking_data['check_out']
|
||
|
|
);
|
||
|
|
|
||
|
|
if ( ! $is_available ) {
|
||
|
|
$items_to_remove[] = array(
|
||
|
|
'key' => $cart_item_key,
|
||
|
|
'message' => __( 'A room booking was removed because the room is no longer available for those dates.', 'wp-bnb' ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Remove invalid items.
|
||
|
|
foreach ( $items_to_remove as $item ) {
|
||
|
|
$cart->remove_cart_item( $item['key'] );
|
||
|
|
wc_add_notice( $item['message'], 'error' );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Display booking info in cart.
|
||
|
|
*
|
||
|
|
* @param array $item_data Item data for display.
|
||
|
|
* @param array $cart_item Cart item.
|
||
|
|
* @return array Modified item data.
|
||
|
|
*/
|
||
|
|
public static function display_cart_item_data( array $item_data, array $cart_item ): array {
|
||
|
|
if ( ! isset( $cart_item[ Manager::CART_ITEM_KEY ] ) ) {
|
||
|
|
return $item_data;
|
||
|
|
}
|
||
|
|
|
||
|
|
$booking_data = $cart_item[ Manager::CART_ITEM_KEY ];
|
||
|
|
|
||
|
|
// Format dates.
|
||
|
|
$date_format = get_option( 'date_format' );
|
||
|
|
$check_in = \DateTime::createFromFormat( 'Y-m-d', $booking_data['check_in'] );
|
||
|
|
$check_out = \DateTime::createFromFormat( 'Y-m-d', $booking_data['check_out'] );
|
||
|
|
|
||
|
|
$item_data[] = array(
|
||
|
|
'key' => __( 'Check-in', 'wp-bnb' ),
|
||
|
|
'value' => $check_in ? $check_in->format( $date_format ) : $booking_data['check_in'],
|
||
|
|
);
|
||
|
|
|
||
|
|
$item_data[] = array(
|
||
|
|
'key' => __( 'Check-out', 'wp-bnb' ),
|
||
|
|
'value' => $check_out ? $check_out->format( $date_format ) : $booking_data['check_out'],
|
||
|
|
);
|
||
|
|
|
||
|
|
$item_data[] = array(
|
||
|
|
'key' => __( 'Nights', 'wp-bnb' ),
|
||
|
|
'value' => $booking_data['nights'],
|
||
|
|
);
|
||
|
|
|
||
|
|
$item_data[] = array(
|
||
|
|
'key' => __( 'Guests', 'wp-bnb' ),
|
||
|
|
'value' => $booking_data['guests'],
|
||
|
|
);
|
||
|
|
|
||
|
|
// Display services.
|
||
|
|
if ( ! empty( $booking_data['services'] ) ) {
|
||
|
|
$services_list = array();
|
||
|
|
foreach ( $booking_data['services'] as $service ) {
|
||
|
|
$services_list[] = $service['name'] . ' × ' . $service['quantity'];
|
||
|
|
}
|
||
|
|
$item_data[] = array(
|
||
|
|
'key' => __( 'Services', 'wp-bnb' ),
|
||
|
|
'value' => implode( ', ', $services_list ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $item_data;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Calculate dynamic prices for cart items.
|
||
|
|
*
|
||
|
|
* @param \WC_Cart $cart Cart object.
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public static function calculate_cart_item_prices( \WC_Cart $cart ): void {
|
||
|
|
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ( $cart->get_cart() as $cart_item ) {
|
||
|
|
if ( ! isset( $cart_item[ Manager::CART_ITEM_KEY ] ) ) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$booking_data = $cart_item[ Manager::CART_ITEM_KEY ];
|
||
|
|
$grand_total = $booking_data['price_breakdown']['grand_total'] ?? 0;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Filter the cart item price for a booking.
|
||
|
|
*
|
||
|
|
* @param float $price The calculated price.
|
||
|
|
* @param array $cart_item The cart item.
|
||
|
|
*/
|
||
|
|
$grand_total = apply_filters( 'wp_bnb_wc_cart_item_price', $grand_total, $cart_item );
|
||
|
|
|
||
|
|
// Set the price.
|
||
|
|
$cart_item['data']->set_price( $grand_total );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Lock quantity to 1 for room products.
|
||
|
|
*
|
||
|
|
* @param array $args Input arguments.
|
||
|
|
* @param \WC_Product $product Product object.
|
||
|
|
* @return array Modified arguments.
|
||
|
|
*/
|
||
|
|
public static function lock_quantity( array $args, \WC_Product $product ): array {
|
||
|
|
if ( ProductSync::is_room_product( $product ) ) {
|
||
|
|
$args['min_value'] = 1;
|
||
|
|
$args['max_value'] = 1;
|
||
|
|
$args['readonly'] = true;
|
||
|
|
}
|
||
|
|
return $args;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add booking data to order item meta.
|
||
|
|
*
|
||
|
|
* @param \WC_Order_Item_Product $item Order item.
|
||
|
|
* @param string $cart_item_key Cart item key.
|
||
|
|
* @param array $values Cart item values.
|
||
|
|
* @param \WC_Order $order Order object.
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public static function add_order_item_meta( \WC_Order_Item_Product $item, string $cart_item_key, array $values, \WC_Order $order ): void {
|
||
|
|
if ( ! isset( $values[ Manager::CART_ITEM_KEY ] ) ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$booking_data = $values[ Manager::CART_ITEM_KEY ];
|
||
|
|
|
||
|
|
// Store booking data in order item meta.
|
||
|
|
$item->add_meta_data( '_bnb_room_id', $booking_data['room_id'] );
|
||
|
|
$item->add_meta_data( '_bnb_check_in', $booking_data['check_in'] );
|
||
|
|
$item->add_meta_data( '_bnb_check_out', $booking_data['check_out'] );
|
||
|
|
$item->add_meta_data( '_bnb_guests', $booking_data['guests'] );
|
||
|
|
$item->add_meta_data( '_bnb_nights', $booking_data['nights'] );
|
||
|
|
$item->add_meta_data( '_bnb_services', wp_json_encode( $booking_data['services'] ) );
|
||
|
|
$item->add_meta_data( '_bnb_price_breakdown', wp_json_encode( $booking_data['price_breakdown'] ) );
|
||
|
|
|
||
|
|
// Add visible meta for admin display.
|
||
|
|
$date_format = get_option( 'date_format' );
|
||
|
|
$check_in = \DateTime::createFromFormat( 'Y-m-d', $booking_data['check_in'] );
|
||
|
|
$check_out = \DateTime::createFromFormat( 'Y-m-d', $booking_data['check_out'] );
|
||
|
|
|
||
|
|
$item->add_meta_data( __( 'Check-in', 'wp-bnb' ), $check_in ? $check_in->format( $date_format ) : $booking_data['check_in'] );
|
||
|
|
$item->add_meta_data( __( 'Check-out', 'wp-bnb' ), $check_out ? $check_out->format( $date_format ) : $booking_data['check_out'] );
|
||
|
|
$item->add_meta_data( __( 'Nights', 'wp-bnb' ), $booking_data['nights'] );
|
||
|
|
$item->add_meta_data( __( 'Guests', 'wp-bnb' ), $booking_data['guests'] );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sanitize services array from POST data.
|
||
|
|
*
|
||
|
|
* @param mixed $services Raw services data.
|
||
|
|
* @return array Sanitized services array.
|
||
|
|
*/
|
||
|
|
private static function sanitize_services( $services ): array {
|
||
|
|
if ( ! is_array( $services ) ) {
|
||
|
|
return array();
|
||
|
|
}
|
||
|
|
|
||
|
|
$sanitized = array();
|
||
|
|
|
||
|
|
foreach ( $services as $service ) {
|
||
|
|
if ( ! is_array( $service ) ) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$service_id = isset( $service['service_id'] ) ? absint( $service['service_id'] ) : 0;
|
||
|
|
$quantity = isset( $service['quantity'] ) ? absint( $service['quantity'] ) : 1;
|
||
|
|
|
||
|
|
if ( $service_id > 0 ) {
|
||
|
|
$sanitized[] = array(
|
||
|
|
'service_id' => $service_id,
|
||
|
|
'quantity' => max( 1, $quantity ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $sanitized;
|
||
|
|
}
|
||
|
|
}
|