Files
jachty.pkmp.com.pl/.paul/codebase/integrations.md
2026-05-06 00:18:37 +02:00

5.6 KiB

External Integrations

Analysis Date: 2026-05-05

Google Calendar API v3

Purpose: Bidirectional sync — bookings push to Google Calendar as events; Google Calendar events pull back as availability blocks.

Implementation: Native PHP, no SDK. Uses WordPress HTTP API (wp_remote_post, wp_remote_get, wp_remote_request).

Files:

  • integrations/google-calendar/class-gcal-service.php — API calls
  • integrations/google-calendar/class-oauth-handler.php — OAuth 2.0 token management
  • integrations/google-calendar/class-sync-controller.php — Cron orchestration (Singleton)

Authentication: OAuth 2.0 with offline access (refresh token).

  • Auth endpoint: https://accounts.google.com/o/oauth2/v2/auth
  • Token endpoint: https://oauth2.googleapis.com/token
  • Scope: https://www.googleapis.com/auth/calendar
  • Credentials stored in wp_options key yacht_booking_gcal_credentials
  • Tokens stored in wp_options key yacht_booking_gcal_tokens
  • Calendar ID stored in yacht_booking_gcal_calendar_id (defaults to 'primary')
  • OAuth redirect URI hardcoded: https://jachty.pagedev.pl/wp-admin/admin.php?page=yacht-bookings-settings&tab=google-calendar&gcal_callback=1

Outbound API calls:

Method URL Purpose
POST .../calendars/{id}/events Create event
PATCH .../calendars/{id}/events/{eventId} Update event
DELETE .../calendars/{id}/events/{eventId} Delete event
GET .../calendars/{id}/events List events (pull sync)
GET .../users/me/calendarList List calendars
POST https://oauth2.googleapis.com/token Token exchange/refresh
GET https://www.googleapis.com/oauth2/v2/userinfo Get connected email

Sync model: Pull-only for external → local (hourly WP Cron yacht_booking_pull_from_gcal). Push for local → GCal on yacht_booking_created / yacht_booking_status_changed (scheduled single cron events).

Limitations:

  • Single shared calendar for all yachts — GCal events apply to every yacht, not per-yacht
  • No incoming webhooks — polling model only
  • No retry logic on API failure

iCal Integration

Export (Feed)

Purpose: Generate .ics file per yacht for subscription by external clients (other booking systems, personal calendars).

File: integrations/ical/class-ical-feed.php

URL pattern: {home_url}/yacht-ical/{yacht_id}/{token}.ics

  • Token stored in _yacht_ical_token post meta (24-char alphanumeric, auto-generated)
  • Verified with hash_equals() — timing-safe
  • Returns text/calendar with all non-cancelled bookings for that yacht
  • Regenerate token: ICal_Feed::regenerate_token($yacht_id)

Import (Subscribe)

Purpose: Subscribe to external iCal URLs per yacht; import events as availability blocks (hourly cron).

File: integrations/ical/class-ical-import.php

Config: Per-yacht _yacht_ical_import_url post meta (set via ICal_Import::set_import_url())

Behavior: Fetches URL via wp_remote_get() (30-second timeout, SSL verification), parses VEVENT components, creates yacht_booking posts with _booking_source = 'ical_import', marks dates as blocked via Availability::mark_as_blocked().

Limitation: Does not check VEVENT STATUS property — cancelled events in the feed are imported as blocks.

jsDelivr CDN

Purpose: FullCalendar library loaded from CDN (no local copy).

Asset URL
FullCalendar JS https://cdn.jsdelivr.net/npm/fullcalendar@6.1.10/index.global.min.js
FullCalendar CSS https://cdn.jsdelivr.net/npm/fullcalendar@6.1.10/index.global.min.css
Polish locale https://cdn.jsdelivr.net/npm/@fullcalendar/core@6.1.10/locales/pl.global.min.js

Enqueued in Yacht_Booking::enqueue_frontend_assets(), conditional on page content.

Email

Provider: WordPress wp_mail() only — no Mailgun, SendGrid, or other transactional service.

Templates: includes/class-email-templates.php — templates stored in wp_options as tagged strings, compiled with get_booking_template_data().

When sent:

  • On booking creation: admin notification via Rest_Controller::send_booking_notification() (hooked on yacht_booking_created)
  • On status change: customer notification via Admin::send_customer_notification() (hooked on yacht_booking_status_changed)
  • On inquiry create: admin + customer emails via Inquiry::send_emails() (built inline, not using Email_Templates)

Headers: From: pulled from yacht_booking_email_from option; Reply-To: set explicitly.

REST API (Internal)

Namespace: yacht-booking/v1 — base: /wp-json/yacht-booking/v1/

Method Endpoint Auth Handler
GET /yachts Public get_yachts()
GET /yachts/{id} Public get_yacht()
GET /availability/{yacht_id}?start=Y-m-d&end=Y-m-d Public get_availability()
POST /bookings Public + X-WP-Nonce create_booking()
POST /inquiries Public + X-WP-Nonce create_inquiry()
GET /bookings Admin cap get_bookings()
PUT /bookings/{id}/status Admin cap update_booking_status()

All registered in api/class-rest-controller.php.

Monitoring & Observability

  • No error tracking service (no Sentry, Bugsnag)
  • error_log() used with prefixes: [Yacht Booking - GCal], [Yacht Booking - GCal Sync], [Yacht Booking - iCal]
  • Logging only fires when WP_DEBUG === true — silent in production

Deployment

  • Method: FTP via VS Code ftp-kr extension (.vscode/ftp-kr.json)
  • CI/CD: None — fully manual
  • Production URL: https://jachty.pagedev.pl (hardcoded in GCal OAuth redirect)