is_active() ) { return; } $booking_id = $this->extract_id( $booking ); if ( ! $booking_id ) { return; } try { $this->sync_booking( $booking_id ); } catch ( \Throwable $e ) { TMDO_Logger::error( $this->module, 'booking_changed', $e->getMessage() ); } } /** * Deletes a booking index record when a booking is deleted. * * @param mixed $booking Booking object, array, or ID. * @return void */ public function action_booking_deleted( $booking ): void { if ( ! $this->is_active() ) { return; } $booking_id = $this->extract_id( $booking ); if ( ! $booking_id ) { return; } try { global $wpdb; $wpdb->delete( TMDO_DB::table( 'hpct_latepoint_idx' ), array( 'booking_id' => $booking_id ), array( '%d' ) ); } catch ( \Throwable $e ) { TMDO_Logger::error( $this->module, 'booking_deleted', $e->getMessage() ); } } /** * Extracts a booking ID from various input types. * * @param mixed $booking Booking object, array, or integer ID. * @return int Booking ID, or 0 if not found. */ private function extract_id( $booking ): int { if ( is_object( $booking ) && isset( $booking->id ) ) { return (int) $booking->id; } if ( is_array( $booking ) && isset( $booking['id'] ) ) { return (int) $booking['id']; } return (int) $booking; } /** * Syncs a LatePoint booking to the hpct_latepoint_idx table. * * @param int $booking_id Booking ID. * @return void */ private function sync_booking( int $booking_id ): void { global $wpdb; $table = TMDO_DB::table( 'hpct_latepoint_idx' ); $now = TMDO_DB::now(); // Read from LatePoint's own table. $lp_table = $wpdb->prefix . 'latepoint_bookings'; $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM `{$lp_table}` WHERE id = %d LIMIT 1", $booking_id ), // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- lp_table is $wpdb->prefix . 'latepoint_bookings', prefix-validated. ARRAY_A ); if ( ! $row ) { return; } $data = array( 'booking_id' => $booking_id, 'agent_id' => (int) ( $row['agent_id'] ?? 0 ), 'service_id' => (int) ( $row['service_id'] ?? 0 ), 'customer_id' => (int) ( $row['customer_id'] ?? 0 ), 'status' => sanitize_text_field( $row['status'] ?? '' ), 'start_date' => $row['start_date'] ?? null, 'end_date' => $row['end_date'] ?? null, 'start_time' => (int) ( $row['start_time'] ?? 0 ), 'end_time' => (int) ( $row['end_time'] ?? 0 ), 'price' => $row['payment_amount'] ?? '0', 'created_at' => $row['created_at'] ?? $now, ); $existing = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM `{$table}` WHERE booking_id = %d LIMIT 1", $booking_id ) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name validated by TMDO_DB::table() + sanitize_key(). ); $row_format = array( '%d', '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%s', '%s' ); if ( $existing ) { $update_data = $data; unset( $update_data['booking_id'], $update_data['created_at'] ); $update_format = array_slice( $row_format, 1, count( $update_data ) ); $wpdb->update( $table, $update_data, array( 'booking_id' => $booking_id ), $update_format, array( '%d' ) ); } else { $wpdb->insert( $table, $data, $row_format ); } } }