session) {
$customer_id = WC()->session->get_customer_id();
if (!empty($customer_id)) {
return (string)$customer_id;
}
}
return '';
}
private function is_abptb_product($product_id): int {
$linked_id = absint(get_post_meta($product_id, 'abptb_link_id', true));
if ($linked_id > 0 && $linked_id !== absint($product_id) && get_post_type($linked_id) === ABPTB_Function::get_cpt()) {
return $linked_id;
}
return 0;
}
public function validate_abptb_add_to_cart($passed, $product_id, $quantity) {
if (!$passed) {
return $passed;
}
$post_id = $this->is_abptb_product($product_id);
if (!$post_id) {
return $passed;
}
// Prevent direct (non-form) purchases of the internal WooCommerce product.
$valid_submission = false;
if (isset($_POST['_wpnonce']) && isset($_POST['post_id'])) {
$valid_submission = wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'abptb_registration_nonce')
&& absint($_POST['post_id']) === $post_id;
}
if (!$valid_submission) {
wc_add_notice(__('This transport cannot be purchased directly. Please book through the transport booking form.', 'abp-transport-booking'), 'error');
return false;
}
$bp_dp = isset($_POST['bp_dp']) ? sanitize_text_field(wp_unslash($_POST['bp_dp'])) : '';
$return_bp_dp = isset($_POST['return_bp_dp']) ? sanitize_text_field(wp_unslash($_POST['return_bp_dp'])) : '';
if (empty($bp_dp) && empty($return_bp_dp)) {
wc_add_notice(__('Please select a valid route before booking.', 'abp-transport-booking'), 'error');
return false;
}
$post_infos = ABPTB_Function::get_all_meta($post_id);
$legs = ['' => $bp_dp, 'return_' => $return_bp_dp];
foreach ($legs as $prefix => $leg) {
if (empty($leg)) {
continue;
}
$info = self::get_booking_info($post_infos, $leg, $prefix);
if (empty($info['info'])) {
wc_add_notice(__('Invalid booking. Please select at least one valid ticket or seat from the booking form.', 'abp-transport-booking'), 'error');
return false;
}
$seat_type = $info['seat_type'] ?? 'ticket';
$form_data = [
'post_id' => $post_id,
'start_time' => $info['start_time'] ?? '',
'bp_dp' => $leg,
'sp_id' => $info['sp_id'] ?? '',
];
if ($seat_type === 'sp') {
$sold = ABPTB_Query::get_sold_seat($form_data, true);
$held = ABPTB_Query::get_held_seat($form_data, '');
foreach (($info['info'] ?? []) as $seat) {
$name = $seat['name'] ?? '';
if (!empty($name) && (in_array($name, $sold, true) || in_array($name, $held, true))) {
// translators: %s: seat name.
wc_add_notice(sprintf(__('Sorry, the seat "%s" is no longer available.', 'abp-transport-booking'), $name), 'error');
return false;
}
}
} else {
$sold = ABPTB_Query::get_sold_ticket($form_data, true);
$held = ABPTB_Query::get_held_ticket($form_data, '');
$_ticket_infos = $post_infos['ticket_infos'] ?? [];
foreach (($info['info'] ?? []) as $tic_id => $ticket) {
$qty = intval($ticket['qty'] ?? 0);
$config = $_ticket_infos[$tic_id] ?? [];
$total_qty = intval($config['qty'] ?? 0);
$reserve = intval($config['reserve'] ?? 0);
$available = $total_qty - intval($sold[$tic_id] ?? 0) - intval($held[$tic_id] ?? 0) - $reserve;
if ($qty <= 0 || $qty > $available) {
// translators: %d: number of remaining tickets.
wc_add_notice(sprintf(__('Sorry, only %d ticket(s) remain for the selected transport.', 'abp-transport-booking'), max($available, 0)), 'error');
return false;
}
}
}
}
return $passed;
}
public function create_cart_holds($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data): void {
$post_id = $cart_item_data['post_id'] ?? 0;
if (empty($post_id) || get_post_type($post_id) !== ABPTB_Function::get_cpt()) {
return;
}
$booking_infos = $cart_item_data['booking_infos'] ?? [];
$session = self::hold_session();
if (empty($session) || empty($booking_infos)) {
return;
}
foreach ($booking_infos as $bp_dp => $info) {
if (empty($info)) {
continue;
}
$seat_type = $info['seat_type'] ?? 'ticket';
$start_time = $info['start_time'] ?? '';
$sp_id = $info['sp_id'] ?? 0;
$created = true;
if ($seat_type === 'sp') {
foreach (($info['info'] ?? []) as $seat) {
$name = $seat['name'] ?? '';
if (!empty($name) && !ABPTB_Query::create_seat_hold($post_id, $start_time, $bp_dp, $sp_id, $name, 1, $session, $cart_item_key)) {
$created = false;
}
}
} else {
foreach (($info['info'] ?? []) as $tic_id => $ticket) {
$qty = intval($ticket['qty'] ?? 0);
if ($qty > 0 && !ABPTB_Query::create_seat_hold($post_id, $start_time, $bp_dp, $sp_id, 'ticket:' . $tic_id, $qty, $session, $cart_item_key)) {
$created = false;
}
}
}
if (!$created && WC() && WC()->cart) {
wc_add_notice(__('Sorry, one of the selected seats was just booked by someone else.', 'abp-transport-booking'), 'error');
WC()->cart->remove_cart_item($cart_item_key);
return;
}
}
}
public function release_cart_holds($cart_item_key, $cart): void {
$session = self::hold_session();
if (!empty($session)) {
ABPTB_Query::delete_seat_holds($session, $cart_item_key);
}
}
public function release_session_holds(): void {
$session = self::hold_session();
if (!empty($session)) {
ABPTB_Query::delete_seat_holds($session, '');
}
}
public function add_cart_item_data($cart_item, $product_id) {
$linked_id = ABPTB_Function::get_post_info($product_id, 'abptb_link_id', $product_id);
$post_id = is_string(get_post_status($linked_id)) ? $linked_id : $product_id;
if (get_post_type($post_id) == ABPTB_Function::get_cpt() && isset($_POST['_wpnonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'abptb_registration_nonce')) {
$post_val = fn($key, $default = '') => isset($_POST[$key]) ? sanitize_text_field(wp_unslash($_POST[$key])) : $default;
$post_infos = ABPTB_Function::get_all_meta($post_id);
$bp_dp = $post_val('bp_dp');
$booking_infos = [];
if (!empty($bp_dp)) {
$route_info = self::get_booking_info($post_infos, $bp_dp);
if (!empty($route_info)) {
$booking_infos[$bp_dp] = $route_info;
}
}
$return_bp_dp = $post_val('return_bp_dp');
if (!empty($return_bp_dp)) {
$route_info = self::get_booking_info($post_infos, $return_bp_dp, 'return_');
if (!empty($route_info)) {
$booking_infos[$return_bp_dp] = $route_info;
}
}
$total_price = 0;
if (!empty($booking_infos)) {
foreach ($booking_infos as $booking_info) {
$total_price += ($booking_info['total'] ?? 0);
}
}
$cart_item['post_id'] = $post_id;
$cart_item['booking_infos'] = $booking_infos;
$cart_item['total_price'] = $total_price;
$cart_item['line_total'] = $total_price;
$cart_item['line_subtotal'] = $total_price;
$cart_item = apply_filters('abptb_add_cart_item_data', $cart_item, $post_id);
$_SESSION['abptb_cart_success'] = get_the_title($post_id) . ' ' . __('Add to cart successfully!', 'abp-transport-booking');
}
//echo '
'; print_r($cart_item); echo '
'; die();
return $cart_item;
}
public function before_calculate_totals($cart_object): void {
foreach ($cart_object->cart_contents as $value) {
$post_id = $value['post_id'] ?? 0;
if (get_post_type($post_id) == ABPTB_Function::get_cpt()) {
$total_price = $value['total_price'] ?? 0;
$value['data']->set_price($total_price);
$value['data']->set_regular_price($total_price);
$value['data']->set_sale_price($total_price);
$value['data']->set_sold_individually(true);
}
}
}
public function cart_item_thumbnail($thumbnail, $cart_item) {
$post_id = $cart_item['post_id'] ?? 0;
if (get_post_type($post_id) == ABPTB_Function::get_cpt()) {
$url = ABPTB_Function::get_image_url($post_id) ?: ABPTB_BLANK_IMG_URL;
if (!empty($url)) {
$thumbnail = '';
}
}
return $thumbnail;
}
public function get_item_data($item_data, $booking_items) {
$post_id = $booking_items['post_id'] ?? 0;
if (get_post_type($post_id) == ABPTB_Function::get_cpt()) {
global $post;
$is_block_cart = false;
$is_block_checkout = false;
if (is_a($post, 'WP_Post')) {
$is_block_cart = has_block('woocommerce/cart', $post->ID);
$is_block_checkout = has_block('woocommerce/checkout', $post->ID);
}
if (is_checkout() && $is_block_checkout) {
$item_data = $this->display_cart_item_block($booking_items);
} elseif (is_cart() && $is_block_cart) {
$item_data = $this->display_cart_item_block($booking_items);
} else {
ob_start();
do_action('abptb_display_cart_item', $booking_items);
$content = ob_get_clean();
if (!empty($content)) {
$item_data[] = array(
'name' => __('Booking Details', 'abp-transport-booking'),
'value' => $content
);
}
}
}
return $item_data;
}
public static function get_booking_info($post_infos = [], $bp_dp = '', $prefix = '') {
$booking_info = [];
if (isset($_POST['_wpnonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'abptb_registration_nonce')) {
$post_int_array = fn($key) => (isset($_POST[$key]) && is_array($_POST[$key])) ? array_map('absint', wp_unslash($_POST[$key])) : [];
$post_array = fn($key) => (isset($_POST[$key]) && is_array($_POST[$key])) ? array_map('sanitize_text_field', wp_unslash($_POST[$key])) : [];
$post_int = fn($key, $default = '') => isset($_POST[$key]) ? absint($_POST[$key]) : $default;
$post_val = fn($key, $default = '') => isset($_POST[$key]) ? sanitize_text_field(wp_unslash($_POST[$key])) : $default;
$post_id = $post_infos['post_id'] ?? '';
$seat_type = $post_infos['seat_type'] ?? 'sp';
$seat_type = ABPTB_Function::on_off('sp') ? $seat_type : 'ticket';
$bp_time = $post_val($prefix . 'bp_time');
$start_time = $post_val($prefix . 'start_time');
$start_point = ABPTB_Function::start_point($post_infos, $bp_dp);
$end_point = ABPTB_Function::start_point($post_infos, $bp_dp, true);
$is_return = ABPTB_Function::return_check($post_infos, $bp_dp);
$ticket_price = 0;
if (!empty($bp_time) && !empty($bp_dp) && !empty($post_id) && !empty($start_time)) {
if ($seat_type == 'ticket') {
$ticket_types = $post_array($prefix . 'item_check');
$item_qty = $post_int_array($prefix . 'item_qty');
if (!empty($ticket_types) && !empty($item_qty) && sizeof($ticket_types) > 0) {
foreach ($ticket_types as $key => $ticket_type) {
$qty = absint($item_qty[$key] ?? '');
if (!empty($ticket_type) && $qty > 0) {
$price = ABPTB_Function::get_price($post_infos, $bp_dp, $ticket_type, $start_time);
$booking_info['info'][$ticket_type]['id'] = $ticket_type;
$booking_info['info'][$ticket_type]['name'] = ABPTB_Function::ticket_name($ticket_type);
$booking_info['info'][$ticket_type]['price'] = $price;
$booking_info['info'][$ticket_type]['qty'] = $qty;
$ticket_price = $ticket_price + $price * $qty;
}
}
}
} else {
$seats = $post_val($prefix . 'sp_selected_seat');
$seats = $seats ? explode(',', $seats) : [];
$types = $post_val($prefix . 'sp_selected_seat_id');
$types = $types ? explode(',', $types) : [];
$sp_id = $post_int($prefix . 'sp_id');
if (!empty($sp_id) && !empty($seats) && !empty($types)) {
foreach ($types as $index => $type) {
$seat = $seats[$index] ?? '';
if (!empty($seat) && !empty($type)) {
$price = ABPTB_Function::get_price($post_infos, $bp_dp, $type, $start_time);
$booking_info['info'][$index]['id'] = $type;
$booking_info['info'][$index]['name'] = $seat;
$booking_info['info'][$index]['price'] = $price;
$booking_info['info'][$index]['qty'] = 1;
$ticket_price = $ticket_price + $price * 1;
}
}
$booking_info['sp_id'] = $sp_id;
}
}
if (!empty($booking_info['info'])) {
[$bp, $dp] = array_map('intval', explode('_', $bp_dp));
$pick_up = $post_val($prefix . 'pick_up');
$drop_off = $post_val($prefix . 'drop_off');
$dp_time = $post_val($prefix . 'dp_time');
$additional_info = self::get_additional_info($post_infos, $prefix);
$additional_price = self::get_additional_price($additional_info);
$booking_info['seat_type'] = $seat_type;
$booking_info['post_id'] = $post_id;
$booking_info['bp_time'] = $bp_time;
$booking_info['dp_time'] = $dp_time;
$booking_info['pick_up'] = $pick_up;
$booking_info['drop_off'] = $drop_off;
$booking_info['pick_up_time'] = ABPTB_Function::get_pd_time($bp, $bp_time, $pick_up,$is_return);
$booking_info['drop_off_time'] = ABPTB_Function::get_pd_time($dp, $dp_time, $drop_off,$is_return);
$booking_info['start_time'] = $start_time;
$booking_info['start_point'] = $start_point;
$booking_info['bp_dp'] = $start_point . '_' . $end_point;
$booking_info['duration'] = ABPTB_Function::date_time_difference($bp_time, $dp_time);
$booking_info['pass_info'] = self::get_passenger_info($post_infos, $prefix);
$booking_info['additional_info'] = $additional_info;
$booking_info['price'] = $ticket_price;
$booking_info['ex_price'] = $additional_price;
$booking_info['total'] = $ticket_price + $additional_price;
}
}
}
return apply_filters('abptb_cart_booking_info_filter', $booking_info);
}
public static function get_additional_price($services) {
$price = 0;
if (is_array($services) && sizeof($services) > 0) {
foreach ($services as $service) {
$qty = $service['qty'] ?? '';
if (!empty($qty) && $qty > 0) {
$ticket_price = $service['price'] ?? 0;
$price = $price + $ticket_price * $qty;
}
}
}
return $price;
}
public static function get_additional_info($post_infos = [], $prefix = ''): array {
$infos = array();
if (isset($_POST['_wpnonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'abptb_registration_nonce')) {
$services = ABPTB_Function::additional_data($post_infos);
if (!empty($services) && is_array($services)) {
foreach ($services as $id => $service) {
$name = isset($_POST[$prefix . 'name_' . $id]) ? sanitize_text_field(wp_unslash($_POST[$prefix . 'name_' . $id])) : '';
$quantity = isset($_POST[$prefix . 'qty_' . $id]) ? sanitize_text_field(wp_unslash($_POST[$prefix . 'qty_' . $id])) : '';
if (!empty($name) && !empty($quantity) && $quantity > 0 && !empty($id)) {
$infos[$id]['name'] = $name;
$infos[$id]['qty'] = $quantity;
$infos[$id]['price'] = ABPTB_Function::get_additional_price($post_infos, $id);
$infos[$id]['icon'] = $service['icon'] ?? '';
$infos[$id]['returnable'] = $service['returnable'] ?? 'no';
}
}
}
}
return $infos;
}
public static function get_passenger_info($post_infos = [], $prefix = ''): array {
$pass_info = [];
if (ABPTB_Function::on_off('client_info') && isset($_POST['_wpnonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'abptb_registration_nonce')) {
$forms = ABPTB_Function::client_data($post_infos);
if (!empty($forms) && is_array($forms)) {
foreach ($forms as $id => $form) {
$infos = isset($_POST[$prefix . $id]) ? array_map('sanitize_text_field', wp_unslash($_POST[$prefix . $id])) : [];
if (!empty($infos)) {
foreach ($infos as $key => $info) {
if (!empty($info)) {
$pass_info[$key][$id]['label'] = $form['label'] ?? '';
$pass_info[$key][$id]['value'] = $info;
}
}
}
}
}
}
return $pass_info;
}
public function display_cart_item_block($booking_infos): array {
$item_data = [];
$booking_info = $booking_infos['booking_infos'] ?? [];
$post_id = $booking_infos['post_id'] ?? '';
if (!empty($booking_info) && sizeof($booking_info) > 0 && !empty($post_id) && get_post_type($post_id) == ABPTB_Function::get_cpt()) {
$return = '';
foreach ($booking_info as $bp_dp => $booking_item) {
if (!empty($booking_item)) {
$ticket_infos = $booking_item['info'] ?? [];
if (!empty($ticket_infos) && sizeof($ticket_infos) > 0) {
$bp_time = $booking_item['bp_time'] ?? '';
$dp_time = $booking_item['dp_time'] ?? '';
[$bp, $dp] = array_map('intval', explode('_', $bp_dp));
$pick_up = $booking_item['pick_up'] ?? '';
$drop_off = $booking_item['drop_off'] ?? '';
$start_point = $booking_item['start_point'] ?? '';
$item_data[] = array('name' => __('Booking Information', 'abp-transport-booking') . ' ' . $return, 'value' => '
');
if (intval($start_point) !== intval($bp)) {
$item_data[] = array('name' => __('Starting Point', 'abp-transport-booking'), 'value' => ABPTB_Function::location_value($start_point) . ' - ' . ABPTB_Function::date_format($booking_item['start_time'] ?? '') . '
');
}
$item_data[] = array('name' => __('Boarding Point', 'abp-transport-booking'), 'value' => ABPTB_Function::location_value($bp) . ' - ' . ABPTB_Function::date_format($bp_time) . '
');
$item_data[] = array('name' => __('Arrival', 'abp-transport-booking'), 'value' => ABPTB_Function::location_value($dp) . ' - ' . ABPTB_Function::date_format($dp_time) . '
');
if (intval($pick_up) !== intval($bp)) {
$item_data[] = array('name' => __('Pick Up', 'abp-transport-booking'), 'value' => ABPTB_Function::pd_label($pick_up, $booking_item['pick_up_time'] ?? '') . '
');
}
if (intval($drop_off) !== intval($dp)) {
$item_data[] = array('name' => __('Drop-Off', 'abp-transport-booking'), 'value' => ABPTB_Function::pd_label($drop_off, $booking_item['drop_off_time'] ?? '') . '
');
}
$item_data[] = array('name' => __('Approximate Time ', 'abp-transport-booking'), 'value' => ($booking_item['duration'] ?? '') . '
');
$item_data[] = array('name' => __('Ticket Information', 'abp-transport-booking'), 'value' => '
');
foreach ($ticket_infos as $ticket_info) {
$price = $ticket_info['price'] ?? 0;
$qty = $ticket_info['qty'] ?? 1;
$price_text = $price > 0 ? wc_price($price) : __('FREE', 'abp-transport-booking');
$price = $price > 0 ? wc_price($price * $qty) : __('FREE', 'abp-transport-booking');
$name = ABPTB_Function::ticket_label($ticket_info, $booking_item);
$item_data[] = array('name' => __('Ticket', 'abp-transport-booking'), 'value' => '(' . $name . ')' . $price_text . ' X ' . $qty . ' = ' . $price . '
');
}
$additional_info = $booking_item['additional_info'] ?? [];
if (ABPTB_Function::on_off('additional_info') && !empty($additional_info) && sizeof($additional_info) > 0) {
$item_data[] = array('name' => __('Additional Information', 'abp-transport-booking'), 'value' => '
');
foreach ($additional_info as $additional) {
if (is_array($additional)) {
$qty = $additional['qty'] ?? 1;
$price = $additional['price'] ?? 0;
$price_text = $price > 0 ? wc_price($price) : __('FREE', 'abp-transport-booking');
$ex_price = $price > 0 ? wc_price($price * $qty) : __('FREE', 'abp-transport-booking');
$item_data[] = array('name' => $additional['name'] ?? '', 'value' => $price_text . ' X ' . $qty . ' = ' . $ex_price . '
');
}
}
}
$attendee_infos = $booking_item['pass_info'] ?? [];
if (ABPTB_Function::on_off('client_info') && !empty($attendee_infos) && sizeof($attendee_infos) > 0) {
$item_data[] = array('name' => __('Passenger Information', 'abp-transport-booking'), 'value' => '
');
foreach ($attendee_infos as $attendee_info) {
if (!empty($attendee_info)) {
foreach ($attendee_info as $attendee) {
$label = $attendee['label'] ?? '';
$value = $attendee['value'] ?? '';
if ($label && $value) {
$item_data[] = array('name' => $label, 'value' => $value . '
');
}
}
}
}
}
$return = __('( Return )', 'abp-transport-booking');
}
}
}
}
return $item_data;
}
//=============================//
public function checkout_process_validation(): void {
$booking_items = WC()->cart->get_cart();
if (!empty($booking_items)) {
foreach ($booking_items as $booking_item) {
$post_id = $booking_item['post_id'] ?? '';
if (!empty($booking_item) && !empty($post_id) && get_post_type($post_id) == ABPTB_Function::get_cpt()) {
if (!ABPTB_Function::checkout_validation($booking_item)) {
WC()->cart->empty_cart();
wc_add_notice(
__('Oh! We are sorry, something went wrong. Please try again later.', 'abp-transport-booking'),
'error'
);
wp_safe_redirect(wc_get_page_permalink('cart'));
exit;
}
}
}
}
}
public function checkout_create_order_line_item($item, $_key, $booking_infos): void {
$booking_info = $booking_infos['booking_infos'] ?? [];
$post_id = $booking_infos['post_id'] ?? 0;
if (!empty($booking_info) && sizeof($booking_info) > 0 && !empty($post_id) && get_post_type($post_id) == ABPTB_Function::get_cpt()) {
$return = '';
foreach ($booking_info as $bp_dp => $booking_item) {
if (!empty($booking_item)) {
$ticket_infos = $booking_item['info'] ?? [];
if (!empty($ticket_infos) && sizeof($ticket_infos) > 0) {
[$bp, $dp] = array_map('intval', explode('_', $bp_dp));
$additional_infos = $booking_item['additional_info'] ?? [];
$attendee_infos = $booking_item['pass_info'] ?? [];
$pick_up = $booking_item['pick_up'] ?? '';
$drop_off = $booking_item['drop_off'] ?? '';
$start_point = $booking_item['start_point'] ?? '';
$item->add_meta_data(__('Booking Information', 'abp-transport-booking') . ' ' . $return, '');
if (intval($start_point) !== intval($bp)) {
$item->add_meta_data(__('Starting Point', 'abp-transport-booking'), ABPTB_Function::location_value($start_point) . ' - ' . ABPTB_Function::date_format($booking_item['start_time'] ?? ''));
}
$item->add_meta_data(__('Boarding Point', 'abp-transport-booking'), ABPTB_Function::location_value($bp) . ' - ' . ABPTB_Function::date_format($booking_item['bp_time'] ?? ''));
$item->add_meta_data(__('Arrival', 'abp-transport-booking'), ABPTB_Function::location_value($dp) . ' - ' . ABPTB_Function::date_format($booking_item['dp_time'] ?? ''));
if (intval($pick_up) !== intval($bp)) {
$item->add_meta_data(__('Pick Up', 'abp-transport-booking'), ABPTB_Function::pd_label($pick_up, $booking_item['pick_up_time'] ?? ''));
}
if (intval($drop_off) !== intval($dp)) {
$item->add_meta_data(__('Drop-Off', 'abp-transport-booking'), ABPTB_Function::pd_label($drop_off, $booking_item['drop_off_time'] ?? ''));
}
$item->add_meta_data(__('Approximate Time ', 'abp-transport-booking'), ($booking_item['duration'] ?? ''));
$item->add_meta_data(__('Ticket Information', 'abp-transport-booking'), '');
foreach ($ticket_infos as $ticket_info) {
$price = $ticket_info['price'] ?? 0;
$qty = $ticket_info['qty'] ?? 1;
$price_text = $price > 0 ? wc_price($price) : __('FREE', 'abp-transport-booking');
$price = $price > 0 ? wc_price($price * $qty) : __('FREE', 'abp-transport-booking');
$name = ABPTB_Function::ticket_label($ticket_info, $booking_item);
$item->add_meta_data($name, ($price_text . ' X ' . $qty . ' = ' . $price));
}
if (ABPTB_Function::on_off('additional_info') && !empty($additional_infos) && sizeof($additional_infos) > 0) {
$item->add_meta_data(__('Additional Information', 'abp-transport-booking'), '');
foreach ($additional_infos as $additional) {
$name = $additional['name'] ?? '';
$qty = $additional['qty'] ?? 1;
$price = $additional['price'] ?? 0;
$price_text = $price > 0 ? wc_price($price) : __('FREE', 'abp-transport-booking');
if (!empty($name) && $qty > 0) {
$ex_price = $price > 0 ? wc_price($price * $qty) : __('FREE', 'abp-transport-booking');
$item->add_meta_data($name, ' ( ' . $price_text . ' X ' . $qty . ') = ' . $ex_price);
}
}
}
if (ABPTB_Function::on_off('client_info') && !empty($attendee_infos) && sizeof($attendee_infos) > 0) {
$item->add_meta_data(__('Passenger Information', 'abp-transport-booking'), '');
foreach ($attendee_infos as $attendee_info) {
if (!empty($attendee_info)) {
foreach ($attendee_info as $attendee) {
$label = $attendee['label'] ?? '';
$value = $attendee['value'] ?? '';
if (!empty($label) && !empty($value)) {
$item->add_meta_data($label, $value);
}
}
}
}
}
//=============================//
}
}
}
$item_info = [
'post_id' => $post_id,
'user_id' => get_current_user_id(),
'booking_infos' => $booking_info,
'item_total' => $booking_infos['total_price'] ?? '',
];
$item_info = apply_filters('abptb_checkout_create_order_line_item', $item_info, $booking_infos);
$item->add_meta_data('_abptb_items', $item_info, true);
}
}
public static function save_custom_data($order_id): void {
if ($order_id) {
$order = wc_get_order($order_id);
if (!$order) {
return;
}
$order_status = $order->get_status();
$payment_method = $order->get_payment_method_title();
$user_id = $order->get_customer_id();
$_billing_first_name = $order->get_billing_first_name();
$_billing_last_name = $order->get_billing_last_name();
$billing_email = $order->get_billing_email();
$billing_phone = $order->get_billing_phone();
$_billing_address_1 = $order->get_billing_address_1();
$_billing_address_2 = $order->get_billing_address_2();
$billing_name = $_billing_first_name . ' ' . $_billing_last_name;
$billing_address = $_billing_address_1 . ' ' . $_billing_address_2;
if ($order_status != 'failed') {
$total_order = ABPTB_Query::get_booking_query(['order_id' => $order_id, 'status' => 'all'], 0, 0, true);
if ($total_order == 0) {
foreach ($order->get_items() as $item_id => $item) {
$item_infos = wc_get_order_item_meta($item_id, '_abptb_items');
if (!empty($item_infos) && is_array($item_infos) && sizeof($item_infos) > 0) {
$post_id = $item_infos['post_id'] ?? '';
$booking_info = $item_infos['booking_infos'] ?? [];
if (!empty($post_id) && get_post_type($post_id) == ABPTB_Function::get_cpt() && !empty($booking_info) && sizeof($booking_info) > 0) {
$hold_session = self::hold_session();
foreach ($booking_info as $bp_dp => $item_info) {
if (!empty($item_info)) {
$seat_type = $item_info['seat_type'] ?? '';
$ticket_infos = $item_info['info'] ?? [];
[$bp, $dp] = array_map('intval', explode('_', $bp_dp));
$additional_info = $item_info['additional_info'] ?? [];
// Final availability re-check (seat plan) to prevent overselling.
if ($seat_type === 'sp' && !empty($ticket_infos)) {
$check_data = [
'post_id' => $post_id,
'start_time' => $item_info['start_time'] ?? '',
'bp_dp' => $bp_dp,
'sp_id' => $item_info['sp_id'] ?? '',
];
$sold_seat = ABPTB_Query::get_sold_seat($check_data, true);
$held_seat = ABPTB_Query::get_held_seat($check_data, $hold_session);
$still_available = true;
foreach ($ticket_infos as $seat) {
$name = $seat['name'] ?? '';
if (!empty($name) && (in_array($name, $sold_seat, true) || in_array($name, $held_seat, true))) {
$still_available = false;
break;
}
}
if (!$still_available) {
continue;
}
}
global $wpdb;
$table_name = $wpdb->prefix . 'abptb_orders';
if (!empty($ticket_infos) && sizeof($ticket_infos) > 0) {
$ticket_id = $ex_id = [];
$qty = 0;
foreach ($ticket_infos as $ticket_info) {
if ($seat_type == 'sp') {
$ticket_id[] = $ticket_info['name'] ?? '';
} else {
$ticket_id[] = $ticket_info['id'] ?? '';
}
$qty = $qty + ($ticket_info['qty'] ?? 1);
}
if (!empty($additional_info) && sizeof($additional_info) > 0) {
foreach ($additional_info as $key => $additional) {
$ex_id[] = $key;
}
}
$others['duration'] = $item_info['duration'] ?? '';
$_order_status = 'wc-' . $order_status;
$data = [
'order_id' => intval($order_id),
'item_id' => intval($item_id),
'post_id' => intval($post_id),
'user_id' => intval($user_id),
'start_point' => intval($item_info['start_point'] ?? ''),
'start_time' => sanitize_text_field($item_info['start_time'] ?? ''),
'seat_type' => sanitize_text_field($seat_type),
'bp_dp' => sanitize_text_field($item_info['bp_dp'] ?? ''),
'bp' => intval($bp),
'dp' => intval($dp),
'bp_time' => sanitize_text_field($item_info['bp_time'] ?? ''),
'dp_time' => sanitize_text_field($item_info['dp_time'] ?? ''),
'pick_up' => sanitize_text_field($item_info['pick_up'] ?? ''),
'pick_up_time' => sanitize_text_field($item_info['pick_up_time'] ?? ''),
'drop_off' => sanitize_text_field($item_info['drop_off'] ?? ''),
'drop_off_time' => sanitize_text_field($item_info['drop_off_time'] ?? ''),
'sp_id' => intval($item_info['sp_id'] ?? ''),
'ticket_info' => wp_json_encode($ticket_infos),
'ticket_id' => wp_json_encode($ticket_id),
'qty' => intval($qty),
'price' => sanitize_text_field($item_info['price'] ?? ''),
'ex_info' => wp_json_encode($additional_info),
'ex_id' => wp_json_encode($ex_id),
'ex_price' => sanitize_text_field($item_info['ex_price'] ?? ''),
'total' => sanitize_text_field($item_info['total'] ?? ''),
'pass_info' => wp_json_encode($item_info['pass_info'] ?? []),
'checkin' => 0,
'female' => 0,
'book_type' => 0,
'order_status' => sanitize_text_field($_order_status),
'payment_method' => sanitize_text_field($payment_method),
'billing_name' => sanitize_text_field($billing_name),
'billing_email' => sanitize_text_field($billing_email),
'billing_phone' => sanitize_text_field($billing_phone),
'billing_address' => sanitize_text_field($billing_address),
'others' => wp_json_encode($others),
'created_at' => current_time('Y-m-d H:i'),
'updated_at' => current_time('Y-m-d H:i')
];
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->insert($table_name, $data);
}
}
}
}
}
}
}
}
}
// The order (or failure) now owns whatever is booked - release this session's holds.
ABPTB_Query::delete_seat_holds(self::hold_session(), '');
}
public function checkout_order_processed($order_id): void {
self::save_custom_data($order_id);
}
public function api_checkout_order_processed($order): void {
$this->checkout_order_processed($order->get_id());
}
public function order_status_changed($order_id): void {
if (!empty($order_id) && $order_id > 0) {
global $wpdb;
$table_name = $wpdb->prefix . 'abptb_orders';
$order = wc_get_order($order_id);
$order_status = $order->get_status();
foreach ($order->get_items() as $item_id => $item_values) {
if ($item_id) {
$order_infos = ABPTB_Query::get_booking_query(['item_id' => $item_id]);
if (!empty($order_infos) && sizeof($order_infos) > 0) {
$order_info = current($order_infos);
$others = $order_info['others'] ?? '';
if (!empty($others)) {
$others = json_decode($others, true);
$user_id = get_current_user_id();
$others['updated_by'] = $user_id;
$data = [
'others' => wp_json_encode($others),
'order_status' => 'wc-' . $order_status,
'updated_at' => current_time('Y-m-d H:i')
];
$where = ['item_id' => $item_id];
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->update($table_name, $data, $where, ['%s', '%s', '%s'], ['%d']);
$mail_send = apply_filters('abptb_send_mail', false, $item_id);
}
}
}
}
}
}
}
new ABPTB_Woocommerce();
}