--- phase: 09-finalizacja plan: 03 type: execute wave: 1 depends_on: ["09-02"] files_modified: - wp-content/plugins/yacht-booking-system/yacht-booking-system.php - wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php - wp-content/plugins/yacht-booking-system/includes/class-yacht.php - wp-content/plugins/yacht-booking-system/includes/class-installer.php - wp-content/plugins/yacht-booking-system/admin/class-admin.php - wp-content/plugins/yacht-booking-system/admin/views/yacht-edit.php - wp-content/plugins/yacht-booking-system/admin/class-yacht-list-table.php - wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php - wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-feed.php - wp-content/plugins/yacht-booking-system/uninstall.php files_deleted: - wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-sync-controller.php - wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-gcal-service.php - wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-oauth-handler.php autonomous: false delegation: off --- ## Goal Posprzątać po globalnej iCal sync: usunąć martwe i zbędne mechanizmy (OAuth push do GCal, per-jacht iCal import URL, per-jacht feed, pole "Google Calendar ID"). Pozostawić tylko jeden mechanizm — globalny iCal feed (export + import) wprowadzony w 09-02. ## Purpose Po 09-02 plugin ma DWA równoległe mechanizmy synchronizacji z GCal: globalny iCal (używany przez klienta) i OAuth push (uśpiony, klient nie używa) + per-yacht iCal feedy/importy (relikt sprzed globalnego). To komplikuje model mentalny i potencjalnie powoduje duplikaty. Sprzątanie eliminuje confusing UI i tysiące linii martwego kodu, czyniąc plugin gotowym produkcyjnie do v1.0. ## Output - Usunięte 3 pliki OAuth/GCal (`class-sync-controller.php`, `class-gcal-service.php`, `class-oauth-handler.php`) - Wyłączony cały OAuth flow (UI w settings, hooki cron, callback redirect, AJAX manual sync) - Usunięty per-jacht iCal feed (`output_ics`, `get_feed_token`, rewrite rule `^yacht-ical/(\d+)/...`) - Usunięty per-jacht iCal import (cron `yacht_booking_ical_import`, `run_import`, `import_for_yacht`, pole `iCal Import URL` w yacht-edit, kolumna w yacht-list) - Usunięte pole "Google Calendar ID" w yacht-edit + metody `Yacht::get_gcal_id`/`update_gcal_id` - Cleanup migration: jednorazowy `delete_post_meta` (_yacht_gcal_id, _yacht_ical_import_url, _yacht_ical_token, _yacht_ical_last_import) + `delete_option` (gcal_*, gcal credentials, gcal_sync_enabled) - Zaktualizowany `uninstall.php` ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md @.paul/codebase/architecture.md @.paul/phases/09-finalizacja/09-02-SUMMARY.md ## Source Files @wp-content/plugins/yacht-booking-system/yacht-booking-system.php @wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php @wp-content/plugins/yacht-booking-system/admin/class-admin.php @wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php @wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-feed.php @wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-sync-controller.php @wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-gcal-service.php @wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-oauth-handler.php - **GCal ID per-jacht** — Usunąć z UI + skasować meta z bazy. → Odpowiedź: pole `_yacht_gcal_id` było martwe (OAuth używał globalnej opcji). Usuwamy pole z yacht-edit, metody `Yacht::get_gcal_id`/`update_gcal_id`, kolumnę z yacht-list-table, oraz wywołujemy `delete_post_meta` w cleanup migration. - **Per-jacht iCal Import URL** — Usunąć całkowicie (UI + cron + dane). → Odpowiedź: usuwamy pole `iCal Import URL` z yacht-edit, kolumnę z yacht-list, hook `yacht_booking_ical_import`, metody `run_import`, `import_for_yacht`, `get_import_url`, `set_import_url`, `get_last_import_time`, `get_existing_import_map`, `upsert_booking` (per-yacht), stałą `IMPORT_SOURCE`. Per-yacht booking source `ical_import` zostaje rozpoznany w cleanup migration jako kandydat do usunięcia (rozważymy w boundaries — patrz niżej). - **OAuth push do GCal** — Wyłączyć całkowicie i usunąć. → Odpowiedź: usuwamy 3 pliki (`class-sync-controller.php`, `class-gcal-service.php`, `class-oauth-handler.php`), wszystkie hooki w bootstrap, sekcję UI OAuth w `render_google_calendar_settings`, AJAX `wp_ajax_yacht_booking_manual_sync`, ścieżkę OAuth callback w `process_settings_save`, notice connected/disconnected. Sekcja Settings → Google Calendar zawiera już teraz TYLKO globalną iCal sync. - **Migracja** — Bez widocznej migracji, po cichu. → Odpowiedź: cleanup wykonuje się w `Installer::install()` przy aktywacji nowej wersji (sprawdzamy zapisaną wersję pluginu vs `YACHT_BOOKING_VERSION` — jeśli upgrade z wersji ## AC-1: Pliki OAuth/Sync usunięte i nie ładowane ```gherkin Given plugin po nowym deploy When sprawdzamy strukturę katalogu integrations/ Then nie istnieje plik class-sync-controller.php And nie istnieje plik class-gcal-service.php And nie istnieje plik class-oauth-handler.php And bootstrap pluginu (yacht-booking-system.php + class-yacht-booking.php) nie odwołuje się do żadnej z tych klas And `php -l` na bootstrap nie zgłasza błędów And aktywacja pluginu w WP Admin nie powoduje fatal error ``` ## AC-2: Sekcja OAuth zniknęła z Settings, globalna iCal pozostała ```gherkin Given admin otwiera WP Admin → Rezerwacje Jachtów → Ustawienia → zakładka Google Calendar When strona się renderuje Then NIE widzi "Krok 1: Dodaj dane OAuth" And NIE widzi "Krok 2: Autoryzuj połączenie" And NIE widzi przycisku "Synchronizuj teraz" (AJAX manual sync) And NIE widzi pola "Client ID"/"Client Secret" And widzi sekcję "Globalna synchronizacja iCal" (z 09-02) z polami import URL + export URL And działa "Importuj teraz" + zapis URL + regeneracja tokenu ``` ## AC-3: Pola per-jacht zniknęły z yacht-edit i yacht-list ```gherkin Given admin otwiera Edycję jachtu (yacht-bookings-add-yacht) When strona się renderuje Then NIE widzi pola "Google Calendar ID" And NIE widzi pola "iCal Import URL" And NIE widzi linku "iCal Feed URL" per-jacht And widzi nadal pole "Alias dla Google Calendar" (z 09-02 — to jest aktywne dla globalnego importu) And lista jachtów (yacht-bookings) NIE pokazuje kolumny GCal ID ani iCal status ``` ## AC-4: Per-jacht iCal cron i feed wyłączone ```gherkin Given plugin po deploy nowej wersji When sprawdzamy zarejestrowane crony WP Then NIE jest zaplanowany hook 'yacht_booking_ical_import' (per-yacht) And NIE jest zaplanowany hook 'yacht_booking_pull_from_gcal' (OAuth pull) And NIE jest zaplanowany hook 'yacht_booking_sync_to_gcal' (OAuth push) And JEST zaplanowany hook 'yacht_booking_ical_global_import' (z 09-02) And URL `/yacht-ical/{yacht_id}/{token}.ics` zwraca 404 (per-yacht feed niedostępny) And URL `/yacht-ical-global/{token}.ics` nadal działa (z 09-02) ``` ## AC-5: Cleanup migration — czysta baza ```gherkin Given baza ma stare meta (_yacht_gcal_id, _yacht_ical_import_url, _yacht_ical_token, _yacht_ical_last_import) And baza ma stare opcje (yacht_booking_gcal_calendar_id, yacht_booking_gcal_credentials, yacht_booking_gcal_oauth_*, yacht_booking_gcal_sync_enabled) And baza ma rezerwacje z _booking_source = 'ical_import' (per-yacht) When admin aktywuje nową wersję pluginu (lub uruchomi się hook upgrade) Then wszystkie wymienione meta są usunięte (delete_post_meta) And wszystkie wymienione opcje są usunięte (delete_option) And rezerwacje z source 'ical_import' są usunięte (Availability::clear_booking_availability + wp_delete_post) And opcja `yacht_booking_version` ma nową wartość pluginu And cleanup wykonuje się TYLKO RAZ (kolejna aktywacja nie powtarza) ``` ## AC-6: Globalna iCal sync (z 09-02) działa bez regresji ```gherkin Given po cleanup admin ma globalny iCal Import URL ustawiony When kliknie "Importuj teraz" Then plugin pobiera kalendarz Google And eventy z prefiksem nazwy jachtu są importowane jako rezerwacje (source 'ical_import_global') And frontend kalendarz per-jacht pokazuje tylko swoje rezerwacje And export feed `/yacht-ical-global/{token}.ics` zwraca poprawny .ics ``` ## AC-7: uninstall.php zaktualizowany ```gherkin Given admin usuwa plugin przez Plugins → Delete When uruchamia się uninstall.php Then NIE próbuje delete_option dla nieistniejących już kluczy (lub robi to bezpiecznie — delete_option jest no-op dla nieistniejących) And usuwa wszystkie aktualne klucze: yacht_booking_global_ical_*, yacht_booking_default_status, yacht_booking_email_*, etc. And usuwa wszystkie meta jachtów + bookingów + tabele wp_yacht_availability (jak dotąd) ``` Task 1: Usunąć OAuth/Sync/GCal_Service — pliki i wszystkie odniesienia wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-sync-controller.php (DELETE), wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-gcal-service.php (DELETE), wp-content/plugins/yacht-booking-system/integrations/google-calendar/class-oauth-handler.php (DELETE), wp-content/plugins/yacht-booking-system/yacht-booking-system.php, wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php, wp-content/plugins/yacht-booking-system/admin/class-admin.php 1. **Usunąć 3 pliki** w `integrations/google-calendar/`: - `class-sync-controller.php` - `class-gcal-service.php` - `class-oauth-handler.php` Można usunąć cały katalog `integrations/google-calendar/` jeśli to jedyne pliki (sprawdź `ls integrations/google-calendar/` przed delete). 2. **`yacht-booking-system.php` (bootstrap)**: - Usunąć `require_once` dla 3 plików GCal (jeśli są) - Usunąć wywołania `Sync_Controller::get_instance()`, `Sync_Controller::register_cron_actions()`, `Sync_Controller::setup_cron()`, `Sync_Controller::clear_cron()` w hookach activate/deactivate/plugins_loaded - Zachować bez zmian wszystkie wywołania ICal_* (te zostają) 3. **`includes/class-yacht-booking.php`**: - W metodzie `init()` lub `register()` usunąć linie tworzące/inicjalizujące `Sync_Controller`, `GCal_Service`, `OAuth_Handler` - Usunąć `require_once` dla 3 plików GCal 4. **`admin/class-admin.php` — masywny refactor sekcji OAuth**: - W `process_settings_save()`: - Usunąć `require_once` dla `class-oauth-handler.php` i `class-gcal-service.php` - Usunąć blok obsługujący `gcal_callback` (OAuth callback redirect) - Usunąć blok `yacht_booking_disconnect_gcal` - Usunąć blok `yacht_booking_save_gcal_credentials` - **ZACHOWAĆ** bloki: globalny iCal save, regenerate token, run global import, save_settings (general), save_email_templates - Usunąć metodę `handle_oauth_callback()` - Usunąć metodę `save_gcal_credentials()` - W `display_admin_notices()`: usunąć notice `connected`, `disconnected`. Pozostawić: saved, templates_saved, templates_reset, error, global_ical_saved, token_regenerated, global_import_done, global_import_failed - W `render_google_calendar_settings()`: usunąć CAŁĄ sekcję `if ( ! $is_connected ) ... else ... endif` (Step 1: credentials, Step 2: authorize, Connected status, Manual sync, Instrukcja). **ZACHOWAĆ** sekcję "Globalna synchronizacja iCal" (z 09-02). Metoda po refactorze powinna mieć tylko: nagłówek `

` + tę jedną sekcję `
` z 09-02. - Usunąć lokalne require_once `OAuth_Handler` i `GCal_Service` w tej metodzie (już niepotrzebne). - Pozostawić bez zmian `process_yacht_save`, `save_yacht`, list table'y, eksport CSV, etc. Avoid: - Nie ruszać sekcji "Globalna synchronizacja iCal" (z 09-02) — to jest TO co zostaje - Nie usuwać CSS/JS dla globalnego iCal - Nie usuwać AJAX handler globalnego iCal (jeśli istnieje — w 09-02 jest tylko form POST, żaden AJAX) - `ls integrations/google-calendar/` zwraca pustkę lub katalog nie istnieje - `grep -r "OAuth_Handler\|GCal_Service\|Sync_Controller\|GoogleCalendar" wp-content/plugins/yacht-booking-system --include="*.php"` zwraca 0 wyników (poza komentarzami w summary/changelog) - `php -l` przechodzi na: yacht-booking-system.php, class-yacht-booking.php, class-admin.php - W WP Admin → Settings → Google Calendar widać TYLKO sekcję "Globalna synchronizacja iCal" - Brak fatal error przy aktywacji (sprawdź `?WP_DEBUG=true` lub error log) AC-1 i część AC-2 satisfied (sekcja OAuth zniknęła) Task 2: Usunąć per-jacht iCal feed/import + pole gcal_id z UI wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php, wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-feed.php, wp-content/plugins/yacht-booking-system/admin/views/yacht-edit.php, wp-content/plugins/yacht-booking-system/admin/class-yacht-list-table.php, wp-content/plugins/yacht-booking-system/admin/class-admin.php, wp-content/plugins/yacht-booking-system/includes/class-yacht.php 1. **`class-ical-import.php` — usuwamy mechanizm per-yacht, zostaje tylko globalny**: - Usunąć stałą `IMPORT_SOURCE` (zachować `GLOBAL_IMPORT_SOURCE` i `SUMMARY_SEPARATOR`) - W `register()`: usunąć `add_action( 'yacht_booking_ical_import', ... )` (zostaje tylko `yacht_booking_ical_global_import`) - W `setup_cron()`: usunąć `wp_schedule_event` dla `yacht_booking_ical_import` - W `clear_cron()`: usunąć `wp_clear_scheduled_hook( 'yacht_booking_ical_import' )` - Usunąć metody publiczne: `run_import()`, `get_import_url()`, `set_import_url()`, `get_last_import_time()` - Usunąć metody prywatne: `import_for_yacht()`, `get_existing_import_map()`, `upsert_booking()` (per-yacht — zachować `upsert_global_booking`!) - Zachować: `parse_ics`, helpers (`line_starts_with`, `extract_value`, `parse_ical_date`, `unescape_ical`), `log`, oraz cały globalny mechanizm (run_global_import, build_yacht_lookup_map, match_yacht_by_prefix, get_existing_global_import_map, upsert_global_booking) 2. **`class-ical-feed.php` — usuwamy per-yacht feed, zostaje tylko globalny**: - W `add_rewrite_rules()`: usunąć rule `^yacht-ical/([0-9]+)/([a-zA-Z0-9]+)\.ics$` (zostaje tylko global). Zaktualizować flush check. - W `add_query_vars()`: usunąć `yacht_ical_id` (zostają `yacht_ical_token` i `yacht_ical_global`) - W `handle_feed_request()`: usunąć cały blok per-yacht (zachować tylko branch global) - Usunąć metody: `get_feed_token()`, `regenerate_token()`, `get_feed_url()`, `output_ics()` - Zachować: `register()`, `add_rewrite_rules()` (już poprawiony), `add_query_vars()` (poprawiony), `handle_feed_request()` (poprawiony), wszystkie metody global, `escape_ical()` 3. **`admin/views/yacht-edit.php`**: - Usunąć całe wiersze tabeli z polami: `yacht_gcal_id`, `yacht_ical_import_url`, oraz blok wyświetlający per-yacht iCal Feed URL (z tokenem) - Usunąć z PHP na górze pliku: `$gcal_id = ...`, `$ical_import_url = ...`, `$ical_feed_url = ...`, `$ical_last_import = ...` - **ZACHOWAĆ** pole `yacht_gcal_alias` (z 09-02 — używane przez globalny import) - Pozostawić bez zmian: title, description, capacity, price_per_day, features 4. **`admin/class-yacht-list-table.php`**: - Usunąć z `get_columns()` kolumnę dla GCal i iCal status (jeśli istnieją) - Usunąć metodę `column_gcal_id()` lub equivalent (linia ok. 173 — `Yacht::get_gcal_id`) - Sprawdź czy są inne kolumny używające usuniętych meta — usuń ich rendering 5. **`admin/class-admin.php` — czyszczenie save_yacht**: - W `save_yacht()`: usunąć linie: - `$gcal_id = ...` - `Yacht::update_gcal_id( $saved_id, $gcal_id );` - `$ical_import_url = ...` - `\YachtBooking\Integrations\ICal\ICal_Import::set_import_url( ... )` - **ZACHOWAĆ** zapis aliasu (`Yacht::update_gcal_alias`) 6. **`includes/class-yacht.php`**: - Usunąć metody: `get_gcal_id()`, `update_gcal_id()` - **ZACHOWAĆ**: get_capacity, update_capacity, get_price_per_day, update_price_per_day, get_features, update_features, get_gcal_alias, update_gcal_alias Avoid: - Nie tknąć w żaden sposób mechanizmu globalnego iCal (run_global_import, output_global_ics, alias) - Nie usuwać cron `yacht_booking_ical_global_import` (z 09-02) - Nie usuwać `parse_ics` ani helperów iCal — używane przez globalny import - `php -l` przechodzi na: class-ical-import.php, class-ical-feed.php, yacht-edit.php, class-yacht-list-table.php, class-admin.php, class-yacht.php - `grep -r "yacht_booking_ical_import\|run_import\|import_for_yacht\|get_gcal_id\|update_gcal_id\|_yacht_gcal_id\|_yacht_ical_import_url" wp-content/plugins/yacht-booking-system --include="*.php"` zwraca 0 wyników (lub tylko komentarze) - W WP Admin → Edycja jachtu: NIE widać pól "Google Calendar ID", "iCal Import URL", "iCal Feed URL". WIDAĆ pole "Alias dla Google Calendar". - URL `/yacht-ical/824/jakistoken.ics` zwraca 404 - URL `/yacht-ical-global/{token}.ics` nadal działa AC-3, AC-4, część AC-2 (UI per-yacht) satisfied Task 3: Cleanup migration w Installer + uninstall.php wp-content/plugins/yacht-booking-system/includes/class-installer.php, wp-content/plugins/yacht-booking-system/uninstall.php 1. **`class-installer.php` — dodać metodę `migrate()` wywoływaną z `install()`**: - Logika: pobierz `yacht_booking_version` z opcji. Jeśli istnieje i jest niższa niż `YACHT_BOOKING_VERSION` (czyli to upgrade) — uruchom cleanup. - Cleanup operacje: a. **Delete post meta** dla wszystkich jachtów: - `_yacht_gcal_id` - `_yacht_ical_import_url` - `_yacht_ical_token` - `_yacht_ical_last_import` Sposób: `delete_post_meta_by_key( '_yacht_gcal_id' )` (WordPress core function — usuwa meta dla wszystkich postów). Powtórzyć dla każdego klucza. b. **Delete options** (OAuth/credentials): - `yacht_booking_gcal_calendar_id` - `yacht_booking_gcal_credentials` - `yacht_booking_gcal_oauth_access_token` - `yacht_booking_gcal_oauth_refresh_token` - `yacht_booking_gcal_oauth_token_expires` - `yacht_booking_gcal_oauth_email` - `yacht_booking_gcal_sync_enabled` (sprawdź faktyczne nazwy w `class-oauth-handler.php` ZANIM zostanie usunięty w Task 1 — albo grep bashem PRZED. Lista powyżej to typowe; jeśli różne nazwy, skoryguj) c. **Delete bookings** z `_booking_source = 'ical_import'` (per-yacht): ```php $bookings = get_posts( array( 'post_type' => 'yacht_booking', 'posts_per_page' => -1, 'fields' => 'ids', 'meta_query' => array( array( 'key' => '_booking_source', 'value' => 'ical_import' ), ), ) ); foreach ( $bookings as $booking_id ) { Availability::clear_booking_availability( $booking_id ); wp_delete_post( $booking_id, true ); } ``` d. **Clear stale crons**: `wp_clear_scheduled_hook( 'yacht_booking_ical_import' )`, `wp_clear_scheduled_hook( 'yacht_booking_pull_from_gcal' )`, `wp_clear_scheduled_hook( 'yacht_booking_sync_to_gcal' )`, `wp_clear_scheduled_hook( 'yacht_booking_update_in_gcal' )`, `wp_clear_scheduled_hook( 'yacht_booking_delete_from_gcal' )`. - Idempotencja: `set_version()` w `install()` ZAWSZE nadpisuje `yacht_booking_version` aktualną wartością → przy kolejnej aktywacji warunek `version < CURRENT` jest fałszem → migrate() nic nie robi. ✓ - Wywołać `migrate()` w `install()` PRZED `set_version()`. 2. **`uninstall.php`**: - Sprawdź obecną zawartość (`Read`). - Usuń `delete_option` dla nieistniejących już kluczy GCal (te z punktu 1.b) - **ZACHOWAJ** delete_option dla: - `yacht_booking_default_status`, `yacht_booking_email_from_name`, `yacht_booking_email_from`, `yacht_booking_date_format`, `yacht_booking_currency_symbol`, `yacht_booking_terms_page_id`, `yacht_booking_enable_notifications` - `yacht_booking_global_ical_import_url`, `yacht_booking_global_ical_token`, `yacht_booking_global_ical_last_import` - `yacht_booking_email_templates`, `yacht_booking_version`, `yacht_booking_installed_at`, `yacht_booking_enabled` - **ZACHOWAJ** delete `wp_yacht_availability` table + delete_post_meta dla wszystkich CPT meta + wp_delete_post dla CPT. Avoid: - Nie usuwać `_yacht_gcal_alias` (aktywny dla globalnego importu) - Nie usuwać `_booking_source = 'ical_import_global'` (aktywne globalne importy z 09-02 — zostawić!) - Nie usuwać innych user data (rezerwacji ze strony — `_booking_source != 'ical_import'`) - Cleanup ma być idempotentny — uruchamia się TYLKO przy upgrade z wersji < CURRENT - `php -l` przechodzi na: class-installer.php, uninstall.php - Symulacja upgrade: ustaw `yacht_booking_version` na '0.9.0' w bazie testowej (lub starsza), aktywuj plugin → cleanup wykonuje się; wszystkie wymienione meta i opcje zniknęły; rezerwacje ze starym source 'ical_import' usunięte; rezerwacje globalne ('ical_import_global') i ze strony pozostały - Po cleanup: `wp_options` nie zawiera kluczy gcal_oauth_*, gcal_credentials, gcal_calendar_id, gcal_sync_enabled - Druga aktywacja po pierwszej → migrate() nic nie robi (cicha) AC-5, AC-7 satisfied Posprzątany plugin: jeden mechanizm sync (globalny iCal), zero martwych pól, czysta baza po upgrade. - Usunięte 3 pliki OAuth/Sync/GCal_Service - Usunięty per-jacht iCal feed (URL `/yacht-ical/{id}/...` zwraca 404) - Usunięty per-jacht iCal import (cron i pole) - Usunięte pole "Google Calendar ID" z yacht-edit - Cleanup migration: stare meta, opcje OAuth, rezerwacje per-yacht 'ical_import' → wyczyszczone - Settings → Google Calendar zawiera TYLKO sekcję "Globalna synchronizacja iCal" 1. Po deploy FTP wejdź do WP Admin (jeśli plugin nieaktywny — aktywuj). To wyzwoli `Installer::install()` z migracją. 2. Sprawdź WP Admin → Rezerwacje Jachtów → Ustawienia → Google Calendar: - **NIE ma** sekcji OAuth (Client ID, "Połącz z Google Calendar", "Synchronizuj teraz") - **JEST** sekcja "Globalna synchronizacja iCal" z 09-02 (export URL, import URL, "Importuj teraz") 3. Wejdź w edycję dowolnego jachtu (np. yacht_id=824): - **NIE ma** pól "Google Calendar ID", "iCal Import URL", "iCal Feed URL" - **JEST** pole "Alias dla Google Calendar" 4. Sprawdź listę jachtów (Rezerwacje Jachtów → Wszystkie Jachty): - **Nie ma** kolumn związanych z GCal/iCal per-jacht 5. Otwórz w przeglądarce dowolny stary URL per-yacht: `https://jachty3.pagedev.pl/yacht-ical/824/jakikolwiek_token.ics` → **404 Not Found** 6. Otwórz globalny URL z Settings (Krok 1) → **zwraca .ics z rezerwacjami** 7. Settings → "Importuj teraz" → komunikat sukcesu, w error log nie ma fatal error 8. Sprawdź bazę (phpMyAdmin lub WP-CLI): - `SELECT * FROM wp_postmeta WHERE meta_key IN ('_yacht_gcal_id','_yacht_ical_import_url','_yacht_ical_token','_yacht_ical_last_import')` → 0 wierszy - `SELECT * FROM wp_options WHERE option_name LIKE 'yacht_booking_gcal_%'` → 0 wierszy - `SELECT post_id FROM wp_postmeta WHERE meta_key='_booking_source' AND meta_value='ical_import'` → 0 wierszy - `SELECT option_value FROM wp_options WHERE option_name='yacht_booking_global_ical_token'` → JEST (zachowane) 9. Frontend: otwórz stronę z kalendarzem dowolnego jachtu → kalendarz się ładuje, dostępność pokazuje (test regresji widget) 10. Złóż testową rezerwację na frontendzie → trafia do bazy, pojawia się w admin → po refresh GCal subscription pojawi się w globalnym kalendarzu Google admina Wpisz "approved" gdy 10 punktów przejdzie, lub opisz problemy do naprawy ## DO NOT CHANGE - **Globalna synchronizacja iCal (09-02)** — `output_global_ics`, `run_global_import`, `build_yacht_lookup_map`, `match_yacht_by_prefix`, `upsert_global_booking`, settings UI sekcja "Globalna synchronizacja iCal", `_yacht_gcal_alias`, opcje `yacht_booking_global_ical_*`, cron `yacht_booking_ical_global_import` - **`Yacht::get_gcal_alias`/`update_gcal_alias`** — używane przez globalny import - **CPT yacht_booking i yacht** — schemat, capabilities, registration - **`wp_yacht_availability`** — tabela i logika `Availability` - **Frontend widget i shortcode** — działają dzięki `_booking_yacht_id` - **REST API** (`Rest_Controller`) — endpoint POST /bookings używa wewnętrznych funkcji booking::create, niezależny od GCal - **Email templates + Inquiry CPT + CSV export** — out of scope ## SCOPE LIMITS - Plan NIE dotyka security audit (to 09-04) - Plan NIE dotyka tłumaczeń .pot/.po/.mo (to 09-05) - Plan NIE refactoruje `parse_ics` ani helperów iCal (działają — zostają) - Plan NIE zmienia formatu prefiksu w SUMMARY (separator `" - "` z 09-02 zostaje) - Brak nowych dependencies - Brak admin notice o migracji (klient wybrał "po cichu") - Plan NIE migruje rezerwacji typu 'ical_import' do 'ical_import_global' — usuwa je (klient ponownie zaimportuje przez globalny mechanizm) Przed deklaracją ukończenia planu: - [ ] `php -l` przechodzi na wszystkich zmodyfikowanych plikach - [ ] `grep -r "OAuth_Handler\|GCal_Service\|Sync_Controller"` w plugin dir → 0 wyników (poza logami/changelog) - [ ] `grep -r "yacht_booking_ical_import[^_]"` (bez `_global`) → 0 wyników - [ ] `grep -r "_yacht_gcal_id\|_yacht_ical_import_url\|_yacht_ical_token"` → 0 wyników w runtime code - [ ] Aktywacja pluginu w WP nie powoduje fatal error (sprawdź error log) - [ ] Cleanup migration wykonuje się raz (przy upgrade) i jest idempotentne - [ ] Globalna iCal sync działa bez regresji (export + import + frontend) - [ ] URL per-yacht feed zwraca 404 - [ ] uninstall.php usuwa wszystkie aktualne klucze (nic więcej, nic mniej) - [ ] Wszystkie 7 acceptance criteria spełnione - [ ] Checkpoint human-verify zaakceptowany przez klienta - Plugin ma JEDEN mechanizm synchronizacji z GCal: globalny iCal feed (eksport + import) - Zero martwego kodu (3 pliki usunięte, ~500+ linii zbędnego UI/cron usuniętych) - Czysta baza po upgrade (klient nie widzi starych pól, baza nie zawiera nieaktywnych meta/opcji) - Brak regresji w globalnej iCal sync ani frontendzie - Plugin gotowy produkcyjnie w warstwie integracji GCal (pozostaje security audit + i18n + docs) Po ukończeniu utwórz `.paul/phases/09-finalizacja/09-03-SUMMARY.md` zawierający: - Co usunięto (lista plików + linii kodu jeśli istotna) - Co zachowano (globalna iCal sync, alias, frontend) - Wyniki cleanup migration (ile meta/opcji/rezerwacji zostało skasowanych — z error_log) - Lista usuniętych klas/metod/hooków - Otwarte kwestie (jeśli wyszły w trakcie)