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

8.0 KiB
Raw Permalink Blame History

Architecture

Analysis Date: 2026-05-05

Pattern Overview

WordPress plugin with layered architecture: CPT-backed data model, REST API surface, Singleton orchestrators, static utility classes.

  • Entry point bootstraps a single Singleton (Yacht_Booking) via plugins_loaded
  • All public-facing state changes go through REST API (/wp-json/yacht-booking/v1/)
  • Admin state changes use WordPress PRG pattern (form POST → redirect)
  • External calendar sync handled by separate Integration namespaces

Class Inventory

Class File Pattern Responsibility
Yacht_Booking includes/class-yacht-booking.php Singleton Master orchestrator — wires all subsystems
Yacht includes/class-yacht.php Static utility yacht CPT registration + meta accessors
Booking includes/class-booking.php Static utility yacht_booking CPT + create() + status
Inquiry includes/class-inquiry.php Static utility yacht_inquiry CPT + send_emails()
Availability includes/class-availability.php Static utility All wp_yacht_availability table operations
Rest_Controller api/class-rest-controller.php Extends WP_REST_Controller 7 REST endpoints, booking orchestration
Settings includes/class-settings.php Static utility Typed wp_options accessors + formatting helpers
Installer includes/class-installer.php Plain class DB table creation + default options on activation
Email_Templates includes/class-email-templates.php Static utility Template storage, compilation, tag replacement
Admin admin/class-admin.php Singleton (admin-only) Menu, form processing, CSV export, customer emails
Booking_List_Table admin/class-booking-list-table.php Extends WP_List_Table Bookings admin table
Yacht_List_Table admin/class-yacht-list-table.php Extends WP_List_Table Yachts admin table
Inquiry_List_Table admin/class-inquiry-list-table.php Extends WP_List_Table Inquiries admin table
Sync_Controller integrations/google-calendar/class-sync-controller.php Singleton GCal cron sync orchestration
GCal_Service integrations/google-calendar/class-gcal-service.php Plain class Google Calendar API calls
OAuth_Handler integrations/google-calendar/class-oauth-handler.php Plain class OAuth 2.0 token storage + refresh
ICal_Feed integrations/ical/class-ical-feed.php Static/plain iCal feed generation + rewrite rule
ICal_Import integrations/ical/class-ical-import.php Static/plain External iCal URL import + cron
Shortcode frontend/class-shortcode.php Singleton [yacht_calendar] shortcode
Calendar_Widget frontend/class-calendar-widget.php Extends Elementor Widget_Base Elementor yacht-calendar widget

Dependency Graph

yacht-booking-system.php
    └── Yacht_Booking (Singleton)
            ├── Yacht (static)
            ├── Booking (static)
            │       └── fires: yacht_booking_created
            │                   yacht_booking_status_changed
            ├── Availability (static)
            ├── Settings (static)
            ├── Email_Templates (static)
            ├── Rest_Controller
            │       ├── Yacht, Booking, Availability, Settings, Inquiry
            │       ├── Email_Templates
            │       └── listens: yacht_booking_created → send_booking_notification (admin email)
            ├── Admin (Singleton, admin-only)
            │       ├── Booking, Availability, Yacht, Settings, Email_Templates, Inquiry
            │       ├── Booking_List_Table → Booking, Availability, Settings
            │       ├── Yacht_List_Table, Inquiry_List_Table
            │       └── listens: yacht_booking_status_changed → send_customer_notification
            ├── Sync_Controller (Singleton)
            │       ├── GCal_Service → OAuth_Handler
            │       └── writes: Availability::mark_as_blocked
            ├── ICal_Import → Availability::mark_as_blocked
            └── ICal_Feed (feed output)

WP Hook Map

Hook Type Registered by Handler
plugins_loaded (p10) action bootstrap yacht_booking_init()Yacht_Booking::get_instance()
init (p10) action Yacht_Booking register_post_types()
init (p15) action Yacht_Booking register_shortcodes()
init action bootstrap yacht_booking_load_textdomain()
wp_enqueue_scripts action Yacht_Booking enqueue_frontend_assets() (conditional)
admin_enqueue_scripts action Yacht_Booking enqueue_admin_assets() (conditional)
rest_api_init action Yacht_Booking register_rest_routes()
elementor/widgets/register action Yacht_Booking register_elementor_widgets()
admin_init action Yacht_Booking add_custom_capabilities()
admin_menu (p9) action Admin register_admin_menu()
admin_init action Admin process_bulk_actions(), process_booking_actions(), process_yacht_save(), process_settings_save(), process_export_download()
admin_notices action Admin display_admin_notices()
yacht_booking_created custom action Rest_Controller send_booking_notification() (admin email)
yacht_booking_status_changed custom action Admin send_customer_notification()
before_delete_post action Sync_Controller on_booking_deleted() (GCal event delete)
wp_ajax_yacht_booking_manual_sync action Sync_Controller ajax_manual_sync()
yacht_booking_sync_to_gcal cron action Sync_Controller sync_booking_to_gcal()
yacht_booking_pull_from_gcal cron action (hourly) Sync_Controller pull_from_gcal()
yacht_booking_ical_import cron action (hourly) ICal_Import run_import()
init action ICal_Feed add_rewrite_rules()
template_redirect action ICal_Feed handle_feed_request()

Key Data Flows

Booking Creation (Frontend → REST → DB)

  1. User picks dates on FullCalendar → GET /availability/{yacht_id}Availability::get_availability_calendar()
  2. User submits form → POST /bookings with X-WP-Nonce header
  3. Rest_Controller::create_booking(): nonce check → is_booking_enabled()Availability::is_available()
  4. Price: count_days() × get_price_per_day()
  5. Booking::create() → inserts CPT post + meta → fires yacht_booking_created
  6. Availability::mark_as_booked() → inserts rows in wp_yacht_availability
  7. Admin email sent via Email_Templates; JSON response to frontend

Admin Booking Management

  1. Bookings list → Booking_List_Table::prepare_items() (WP_Query)
  2. Row action URLs: nonce-protected GET ?action=approve_booking_{id}
  3. Admin::process_booking_actions()Booking::update_status() → fires yacht_booking_status_changed
  4. Admin::send_customer_notification() → customer email
  5. On cancel/delete: Availability::clear_booking_availability($booking_id) deletes rows by booking_id
  6. PRG redirect back to list

GCal Sync

  1. Hourly WP Cron: pull_from_gcal()GCal_Service → Google API → Availability::mark_as_blocked()
  2. On booking create: scheduled single cron yacht_booking_sync_to_gcal → push to GCal
  3. OAuth token refresh: OAuth_Handler::get_access_token() → auto-refresh if expired

Error Handling Strategy

  • REST endpoints return WP_Error with HTTP status codes
  • Admin operations: wp_die() on capability failure; ?error=1 redirect on soft errors
  • Booking::create() returns false on failure — caller checks
  • GCal API: is_wp_error() check only; HTTP 4xx/5xx responses silently ignored
  • No exceptions used anywhere

Custom Capabilities

Added once to administrator role via Yacht_Booking::add_custom_capabilities():

  • yacht_booking_manage_yachts
  • yacht_booking_manage_bookings
  • yacht_booking_manage_settings