update
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
namespace YachtBooking\Integrations\ICal;
|
||||
|
||||
use YachtBooking\Availability;
|
||||
use YachtBooking\Settings;
|
||||
use YachtBooking\Yacht;
|
||||
|
||||
// Exit if accessed directly.
|
||||
@@ -29,6 +30,14 @@ class ICal_Import {
|
||||
*/
|
||||
const GLOBAL_IMPORT_SOURCE = 'ical_import_global';
|
||||
|
||||
/**
|
||||
* Booking source identifier dla trybu "wspólny kalendarz" (sync_mode=global).
|
||||
*
|
||||
* Eventy z tym source nie blokują dostępności jachtów (yacht_id=0) i są pokazywane
|
||||
* tylko na widgecie zbiorczym "wszystkie jachty".
|
||||
*/
|
||||
const GLOBAL_CALENDAR_SOURCE = 'ical_global_calendar';
|
||||
|
||||
/**
|
||||
* Separator między prefiksem nazwy jachtu a resztą tytułu eventu.
|
||||
*
|
||||
@@ -95,13 +104,30 @@ class ICal_Import {
|
||||
return false;
|
||||
}
|
||||
|
||||
$events = self::parse_ics( $body );
|
||||
$events = self::parse_ics( $body );
|
||||
$mode = Settings::get_ical_sync_mode();
|
||||
|
||||
if ( 'global' === $mode ) {
|
||||
self::run_global_calendar_mode( $events );
|
||||
} else {
|
||||
self::run_per_yacht_mode( $events );
|
||||
}
|
||||
|
||||
update_option( 'yacht_booking_global_ical_last_import', current_time( 'mysql' ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tryb per-jacht: dopasowanie po prefiksie SUMMARY, wpisy do availability.
|
||||
*
|
||||
* @param array $events Sparsowane eventy iCal.
|
||||
*/
|
||||
protected static function run_per_yacht_mode( $events ) {
|
||||
$yacht_map = self::build_yacht_lookup_map();
|
||||
|
||||
if ( empty( $yacht_map ) ) {
|
||||
self::log( 'Global iCal: no yachts in DB — nothing to match', 'error' );
|
||||
update_option( 'yacht_booking_global_ical_last_import', current_time( 'mysql' ) );
|
||||
return true;
|
||||
self::log( 'Per-yacht iCal: no yachts in DB — nothing to match', 'error' );
|
||||
return;
|
||||
}
|
||||
|
||||
$existing_map = self::get_existing_global_import_map();
|
||||
@@ -117,11 +143,11 @@ class ICal_Import {
|
||||
continue;
|
||||
}
|
||||
|
||||
$summary = isset( $event['summary'] ) ? (string) $event['summary'] : '';
|
||||
$summary = isset( $event['summary'] ) ? (string) $event['summary'] : '';
|
||||
$yacht_id = self::match_yacht_by_prefix( $summary, $yacht_map );
|
||||
|
||||
if ( ! $yacht_id ) {
|
||||
self::log( sprintf( 'Global iCal: skip event "%s" — no yacht match for prefix', $summary ) );
|
||||
self::log( sprintf( 'Per-yacht iCal: skip event "%s" — no yacht match for prefix', $summary ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -131,20 +157,76 @@ class ICal_Import {
|
||||
$booking_id = self::upsert_global_booking( $yacht_id, $event, $existing_id );
|
||||
|
||||
if ( ! $booking_id ) {
|
||||
self::log( sprintf( 'Global iCal: failed to upsert event %s', $event['uid'] ), 'error' );
|
||||
self::log( sprintf( 'Per-yacht iCal: failed to upsert event %s', $event['uid'] ), 'error' );
|
||||
}
|
||||
}
|
||||
|
||||
// Stale cleanup — usuń bookingi których UID nie ma już w feedzie.
|
||||
// Ograniczone do GLOBAL_IMPORT_SOURCE (per-yacht) — nie tyka GLOBAL_CALENDAR_SOURCE.
|
||||
foreach ( $existing_map as $uid => $booking_id ) {
|
||||
if ( ! in_array( $uid, $seen_uids, true ) ) {
|
||||
\YachtBooking\Availability::clear_booking_availability( $booking_id );
|
||||
wp_delete_post( $booking_id, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_option( 'yacht_booking_global_ical_last_import', current_time( 'mysql' ) );
|
||||
return true;
|
||||
/**
|
||||
* Tryb global: wszystkie eventy (bez filtrowania) zapisane jako wspólne wydarzenia
|
||||
* kalendarza. yacht_id=0, brak wpisów do wp_yacht_availability.
|
||||
*
|
||||
* @param array $events Sparsowane eventy iCal.
|
||||
*/
|
||||
protected static function run_global_calendar_mode( $events ) {
|
||||
$existing_map = self::get_existing_global_calendar_map();
|
||||
$seen_uids = array();
|
||||
$imported = 0;
|
||||
$updated = 0;
|
||||
|
||||
foreach ( $events as $event ) {
|
||||
if ( empty( $event['uid'] ) || empty( $event['start'] ) || empty( $event['end'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip past events.
|
||||
if ( strtotime( $event['end'] ) < time() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$seen_uids[] = $event['uid'];
|
||||
$existing_id = isset( $existing_map[ $event['uid'] ] ) ? (int) $existing_map[ $event['uid'] ] : 0;
|
||||
|
||||
$booking_id = self::upsert_global_calendar_event( $event, $existing_id );
|
||||
|
||||
if ( ! $booking_id ) {
|
||||
self::log( sprintf( 'Global calendar iCal: failed to upsert event %s', $event['uid'] ), 'error' );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $existing_id > 0 ) {
|
||||
$updated++;
|
||||
} else {
|
||||
$imported++;
|
||||
}
|
||||
}
|
||||
|
||||
// Stale cleanup — usuń tylko eventy z GLOBAL_CALENDAR_SOURCE których UID brakuje.
|
||||
$deleted = 0;
|
||||
foreach ( $existing_map as $uid => $booking_id ) {
|
||||
if ( ! in_array( $uid, $seen_uids, true ) ) {
|
||||
wp_delete_post( $booking_id, true );
|
||||
$deleted++;
|
||||
}
|
||||
}
|
||||
|
||||
self::log(
|
||||
sprintf(
|
||||
'Global calendar iCal: imported=%d, updated=%d, deleted=%d',
|
||||
$imported,
|
||||
$updated,
|
||||
$deleted
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,6 +379,95 @@ class ICal_Import {
|
||||
return (int) $booking_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapa istniejących eventów GLOBAL_CALENDAR_SOURCE (tryb global): uid => booking_id.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function get_existing_global_calendar_map() {
|
||||
$bookings = get_posts(
|
||||
array(
|
||||
'post_type' => 'yacht_booking',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => -1,
|
||||
'fields' => 'ids',
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_booking_source',
|
||||
'value' => self::GLOBAL_CALENDAR_SOURCE,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$map = array();
|
||||
foreach ( $bookings as $booking_id ) {
|
||||
$uid = get_post_meta( $booking_id, '_ical_event_uid', true );
|
||||
if ( $uid ) {
|
||||
$map[ $uid ] = (int) $booking_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tworzy lub aktualizuje wspólne wydarzenie kalendarza (sync_mode=global).
|
||||
*
|
||||
* yacht_id=0, brak wpisów do availability — event tylko informacyjny na widgecie zbiorczym.
|
||||
*
|
||||
* @param array $event Parsed event data.
|
||||
* @param int $existing_id Existing booking ID (0 dla nowego).
|
||||
* @return int|false
|
||||
*/
|
||||
protected static function upsert_global_calendar_event( $event, $existing_id = 0 ) {
|
||||
$summary = ! empty( $event['summary'] )
|
||||
? sanitize_text_field( $event['summary'] )
|
||||
: __( 'Wydarzenie kalendarza', 'yacht-booking' );
|
||||
|
||||
$post_data = array(
|
||||
'post_type' => 'yacht_booking',
|
||||
'post_status' => 'publish',
|
||||
'post_title' => sprintf(
|
||||
/* translators: %s: event summary */
|
||||
__( 'GCal (wspólny): %s', 'yacht-booking' ),
|
||||
$summary
|
||||
),
|
||||
);
|
||||
|
||||
if ( $existing_id > 0 ) {
|
||||
$post_data['ID'] = $existing_id;
|
||||
$booking_id = wp_update_post( $post_data, true );
|
||||
} else {
|
||||
$booking_id = wp_insert_post( $post_data, true );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $booking_id ) || ! $booking_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
update_post_meta( $booking_id, '_booking_yacht_id', 0 );
|
||||
update_post_meta( $booking_id, '_booking_start_date', $event['start'] );
|
||||
update_post_meta( $booking_id, '_booking_end_date', $event['end'] );
|
||||
update_post_meta( $booking_id, '_booking_status', 'confirmed' );
|
||||
update_post_meta( $booking_id, '_booking_customer_name', __( 'Google Calendar (kalendarz wspólny)', 'yacht-booking' ) );
|
||||
update_post_meta( $booking_id, '_booking_customer_email', '' );
|
||||
update_post_meta( $booking_id, '_booking_customer_phone', '' );
|
||||
update_post_meta( $booking_id, '_booking_total_price', 0 );
|
||||
update_post_meta( $booking_id, '_booking_source', self::GLOBAL_CALENDAR_SOURCE );
|
||||
update_post_meta( $booking_id, '_ical_event_uid', $event['uid'] );
|
||||
update_post_meta( $booking_id, '_booking_notes', $summary );
|
||||
|
||||
// CELOWO BEZ Availability::mark_as_booked() — wspólne eventy nie blokują dostępności jachtów.
|
||||
// Defensywnie: jeśli kiedyś existing_id miał wpisy availability (np. po przełączeniu trybu),
|
||||
// usuń je, by nie zostawiały śmieci.
|
||||
if ( $existing_id > 0 ) {
|
||||
\YachtBooking\Availability::clear_booking_availability( $existing_id );
|
||||
}
|
||||
|
||||
return (int) $booking_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse .ics content into array of events.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user