--- phase: 09-finalizacja plan: 03 subsystem: cleanup tags: [cleanup, oauth-removal, ical-consolidation, migration] requires: - phase: 09-finalizacja/09-02 provides: globalna iCal sync (export feed + import + alias) — staje się jedynym mechanizmem po usunięciu konkurencji provides: - Plugin z jednym mechanizmem GCal sync (globalny iCal) - Cleanup migration "po cichu" (Installer::migrate, idempotent, version-aware) - Czysta baza po upgrade (4 stale meta keys + 6 stale options + per-yacht ical_import bookings + 5 cron hooków usuniętych) - Skrócony codebase (~700 linii martwego kodu usuniętych, 3 pliki OAuth znikają) affects: - 09-04 Security audit — mniej powierzchni do auditu - 09-05 Testy + i18n + dokumentacja — mniej do udokumentowania - przyszłe milestone'y v1.x — czysty fundament bez OAuth dependencies tech-stack: added: [] patterns: - "Idempotent version-gated migration: Installer::migrate() porównuje get_option('yacht_booking_version') z YACHT_BOOKING_VERSION i wykonuje cleanup tylko przy upgrade" - "Cleanup po cichu — bez admin notice, klient nie musi wykonywać żadnych akcji ręcznych" key-files: created: [] 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 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 key-decisions: - "Per-yacht bookings z source 'ical_import' — usuwamy w migration (klient ponownie zaimportuje przez globalny mechanizm), zamiast migrować je do source 'ical_import_global'" - "Migration idempotentna przez version_compare — kolejna aktywacja nie powtarza cleanup" - "Bez admin notice po migration — klient wybrał 'po cichu'" - "Per-yacht feedy iCal usunięte całkowicie (nie zostawione jako fallback) — model mentalny: jeden mechanizm" patterns-established: - "Wersja-aware cleanup w Installer::install() — pattern do reuse w przyszłych planach refaktorujących/usuwających legacy" - "FQN namespace + lazy require_once dla klas używanych w activation hook (przed ładowaniem bootstrap)" duration: ~30min started: 2026-05-06T11:30:00Z completed: 2026-05-06T12:00:00Z --- # Phase 9 Plan 03: Cleanup OAuth + per-yacht iCal Summary **Wycofanie OAuth (3 pliki + cała sekcja UI), per-yacht iCal feed/import (pole "Google Calendar ID", "iCal Import URL", kolumna w yacht-list, cron) z bezgłośną migracją bazy — plugin sprowadzony do jednego mechanizmu sync (globalny iCal z 09-02).** ## Performance | Metric | Value | |--------|-------| | Duration | ~30min | | Tasks | 3 auto + 1 human-verify (wszystkie zaakceptowane) | | Files modified | 10 | | Files deleted | 3 | | Lines removed | ~700+ (3 OAuth files + per-yacht iCal + UI + handlers) | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: Pliki OAuth usunięte i nie ładowane | Pass | 3 pliki + katalog `integrations/google-calendar/` usunięte. Bootstrap (`yacht-booking-system.php`, `class-yacht-booking.php`) bez require/wiring. PHP lint OK. | | AC-2: Sekcja OAuth zniknęła z Settings | Pass | `render_google_calendar_settings()` zawiera tylko nagłówek + sekcję "Globalna synchronizacja iCal". Usunięte: handle_oauth_callback, save_gcal_credentials, callback/disconnect/credentials w process_settings_save, notice connected/disconnected. | | AC-3: Pola per-jacht zniknęły z yacht-edit i yacht-list | Pass | yacht-edit nie ma "Google Calendar ID", "iCal Import URL", "iCal Feed URL". Ma tylko Alias. Lista jachtów bez kolumny "Google Calendar". | | AC-4: Per-jacht iCal cron i feed wyłączone | Pass | Cron `yacht_booking_ical_import` nie rejestrowany. Rewrite rule `^yacht-ical/(\d+)/...` usunięta — URL per-yacht zwróci 404. Globalny `^yacht-ical-global/...` aktywny. | | AC-5: Cleanup migration | Pass | `Installer::migrate()` — version-gated. Kasuje 4 meta keys (delete_post_meta_by_key), 6 opcji OAuth, bookings z source 'ical_import' (Availability::clear_booking_availability + wp_delete_post), 5 cron hooków. | | AC-6: Globalna iCal sync bez regresji | Pass | Boundary chronił z 09-02 — wszystkie globalne metody/UI/cron nietknięte, alias zachowany. | | AC-7: uninstall.php zaktualizowany | Pass | Dodane delete_option dla `yacht_booking_global_ical_*`, `yacht_booking_enabled`. Defensywne delete_option dla legacy gcal_* keys. | ## Accomplishments - Plugin ma JEDEN spójny mechanizm sync z GCal (globalny iCal), zamiast 4 (OAuth push, OAuth pull, per-yacht iCal feed, per-yacht iCal import) — drastyczne zmniejszenie powierzchni mentalnej i bug surface - Czysta baza po automatycznej migracji — klient nie wykonuje żadnych akcji ręcznych, niepotrzebne meta i opcje znikają przy następnej aktywacji pluginu - Codebase odchudzony o ~700+ linii martwego kodu (3 pliki OAuth/Sync + UI/CRUD per-yacht iCal) - Zero regresji w globalnej iCal sync ani frontendzie (kalendarz widget, REST API, CPT, availability) — boundaries respektowane - Plugin gotowy produkcyjnie w warstwie integracji GCal — pozostają tylko 09-04 (security audit) i 09-05 (testy + i18n + docs) do zamknięcia milestone v1.0 ## Files Created/Modified | File | Change | Purpose | |------|--------|---------| | `integrations/google-calendar/class-sync-controller.php` | **Deleted** | OAuth orchestrator usunięty całkowicie | | `integrations/google-calendar/class-gcal-service.php` | **Deleted** | Google Calendar API calls usunięte | | `integrations/google-calendar/class-oauth-handler.php` | **Deleted** | OAuth tokens + credentials usunięte | | `yacht-booking-system.php` | Modified | Wycięte require + setup_cron + clear_cron Sync_Controller w activate/deactivate hooks | | `includes/class-yacht-booking.php` | Modified | Wycięte 3 require_once + Sync_Controller::get_instance/register_cron_actions w `load_dependencies()` | | `includes/class-yacht.php` | Modified | Usunięte `get_gcal_id()`, `update_gcal_id()` | | `includes/class-installer.php` | Modified | Dodana `migrate()` (version-gated, idempotent), usunięty `yacht_booking_gcal_sync_enabled` z create_options | | `admin/class-admin.php` | Modified | Wycięte: handle_oauth_callback, save_gcal_credentials, OAuth bloki w process_settings_save i display_admin_notices, cała sekcja OAuth w render_google_calendar_settings, save_yacht zapisuje tylko alias | | `admin/views/yacht-edit.php` | Modified | Usunięte 3 wiersze tabeli (Google Calendar ID, iCal Import URL, iCal Feed URL) + 4 zmienne PHP. Pozostaje Alias. | | `admin/class-yacht-list-table.php` | Modified | Usunięta kolumna `gcal` z get_columns + metoda column_gcal | | `integrations/ical/class-ical-import.php` | Modified | Usunięte: const IMPORT_SOURCE, run_import, get_import_url, set_import_url, import_for_yacht, get_existing_import_map, upsert_booking, get_last_import_time. Cron 'yacht_booking_ical_import' nie rejestrowany. | | `integrations/ical/class-ical-feed.php` | Modified | Usunięte: rewrite rule per-yacht, query var yacht_ical_id, branch per-yacht w handle_feed_request, output_ics, get_feed_token, regenerate_token, get_feed_url. Pozostaje globalna ścieżka. | | `uninstall.php` | Modified | Dodane: yacht_booking_global_ical_*, yacht_booking_enabled. Defensywne legacy gcal_* delete_option. | ## Decisions Made | Decision | Rationale | Impact | |----------|-----------|--------| | Usunięcie per-yacht bookings 'ical_import' w migration | Bez per-yacht importu nie będą odświeżane — lepsze UX usunąć i pozwolić ponowny globalny import niż zostawić "skamieniałe" blokady | Klient po deploy uruchamia "Importuj teraz" raz i ma świeże dane | | Migration version-gated z version_compare | Idempotencja — kolejna aktywacja po pierwszej nie powtarza cleanup, bezpieczne dla repeated activate/deactivate | Zero ryzyka przy ręcznych re-aktywacjach lub WP auto-update | | FQN dla `\YachtBooking\Availability` w migrate() | Activation hook ładuje Installer ręcznie przed bootstrap — autoloader może być nieaktywny | Lazy require_once jako fallback wewnątrz pętli `if (!class_exists)` | | Defensywne delete_option dla legacy gcal_* w uninstall.php | Migration usuwa je przy upgrade, ale uninstall.php może być uruchomiony bezpośrednio na starszej wersji bez upgrade | Wszystkie ścieżki sprzątają legacy keys | | Brak admin notice po migration | Klient w fazie planowania wybrał "po cichu" — żeby nie zaprzątać uwagi | Płynne UX, klient zauważy tylko że stare pola znikły | ## Deviations from Plan ### Summary | Type | Count | Impact | |------|-------|--------| | Auto-fixed | 1 | Drobny | | Scope additions | 0 | — | | Deferred | 0 | — | **Total impact:** Plan wykonany w pełni, jeden drobny auto-fix dla bezpieczeństwa. ### Auto-fixed Issues **1. [Migration safety] Availability class loading w activation hook** - **Found during:** Task 3 (Installer::migrate) - **Issue:** Migration wywołuje `\YachtBooking\Availability::clear_booking_availability()`, ale Installer jest ładowany przez activation hook PRZED `plugins_loaded` (gdzie autoloader spl_autoload_register() jest rejestrowany). Pierwotna implementacja zakładała że Availability jest dostępne automatycznie. - **Fix:** Dodany guard `if ( ! class_exists( '\YachtBooking\Availability' ) ) { require_once YACHT_BOOKING_PLUGIN_DIR . 'includes/class-availability.php'; }` przed pętlą usuwającą stale bookings. Dodatkowo otoczone `if (!empty($stale_bookings))` żeby nie ładować pliku gdy nie ma nic do usunięcia. - **Files:** includes/class-installer.php - **Verification:** PHP lint OK; logika idempotentna; w testach klient potwierdził że upgrade nie powoduje fatal error. ### Deferred Items Brak. ## Issues Encountered | Issue | Resolution | |-------|------------| | Brak konkretnych fatal errors lub regresji | — | ## Reproduction Path (do testów regresyjnych) 1. Po deploy FTP — aktywuj plugin (lub deactivate→activate na produkcji). Wyzwoli `Installer::install()` → `migrate()`. 2. Sprawdź WP Admin → Settings → Google Calendar: tylko sekcja "Globalna synchronizacja iCal" (z 09-02). 3. Sprawdź edycję jachtu: brak "Google Calendar ID"/"iCal Import URL"/"iCal Feed URL". Jest tylko "Alias dla Google Calendar". 4. Lista jachtów: brak kolumny "Google Calendar". 5. URL `/yacht-ical/X/token.ics` → 404. URL `/yacht-ical-global/{token}.ics` → poprawny .ics. 6. phpMyAdmin: brak meta `_yacht_gcal_id`/`_yacht_ical_*`, brak opcji `yacht_booking_gcal_*` (poza globalnymi `*_global_ical_*`), brak bookingów z source `ical_import`. 7. Druga aktywacja → migrate() nie powtarza cleanup (version match). ## Next Phase Readiness **Ready:** - Codebase czysty, 1 mechanizm GCal sync - Migration mechanizm gotowy do reuse w przyszłych planach refaktorujących - Plugin z punktu widzenia integracji GCal jest produkcyjnie skończony **Concerns:** - Klient po deploy musi pamiętać o uruchomieniu globalnego "Importuj teraz" w Settings, żeby ponownie zaimportować eventy z Google Calendar (stare per-yacht zostały skasowane). Mitigacja: zostało udokumentowane w checkpoint verify steps. - `yacht_booking_capabilities_added` flag jest sprawdzany raz w `Yacht_Booking::add_custom_capabilities()` — zachowany w uninstall.php. Nie ruszamy go. **Blockers:** None ## Otwarte kwestie milestone v1.0 - 09-04: Security audit (nonce, escaping, SQL prepare, capabilities) - 09-05: Testy + tłumaczenia .pot/.po/.mo + dokumentacja użytkownika i dewelopera --- *Phase: 09-finalizacja, Plan: 03* *Completed: 2026-05-06*