# CalDAV Sync Bundle (Contao 5.7) Produktionsreifes Grundgeruest fuer einen 2-Way-CalDAV-Sync (V1) zwischen `tl_calendar_events` und einem CalDAV-Kalender. ## V1-Scope - Kein RRULE/EXDATE/RECURRENCE-ID - Kein Backend-Button, nur Command - Harte Loeschung bei fehlendem Gegenstueck - Konfliktregel: remote gewinnt - Contao-only-Felder werden niemals remote geschrieben ## Verzeichnisstruktur ```text caldav-sync-bundle/ composer.json config/ services.yaml contao/ dca/ tl_calendar.php tl_calendar_events.php languages/ de/ tl_calendar.php tl_calendar_events.php src/ CalDavSyncBundle.php Command/ CalDavSyncCommand.php Config/ CalendarSyncConfig.php Contao/Manager/ Plugin.php DependencyInjection/ CalDavSyncExtension.php Repository/ ContaoCalendarRepository.php ContaoCalendarEventRepository.php Migration/ Version20260327000000.php Service/ CalendarConfigProvider.php CalDav/ Transport/ CalDavTransportInterface.php CalDavTransport.php TransportResponse.php Parser/ CalDavXmlParser.php ICalendarParser.php ICalendarSerializer.php Remote/ RemoteCalendarReader.php RemoteCalendarWriter.php Sync/ RemoteEvent.php EventMatchResolver.php SyncFieldExtractor.php SyncHashGenerator.php SyncResult.php RemoteToLocalSynchronizer.php LocalToRemoteSynchronizer.php SyncRunner.php ``` ## Klassenuebersicht - `CalendarConfigProvider`: Liefert pro `tl_calendar` die Sync-Konfiguration. - `ContaoCalendarRepository`: Zugriff auf Sync-faehige Kalender. - `ContaoCalendarEventRepository`: CRUD fuer `tl_calendar_events`. - `CalDavTransport`: HTTP/WebDAV via Symfony HttpClient (`PROPFIND`, `REPORT`, `GET`, `PUT`, `DELETE`). - `CalDavXmlParser`: Parsing von WebDAV-Multistatus XML. - `ICalendarParser`: VEVENT-Parsing via `sabre/vobject`. - `ICalendarSerializer`: VEVENT-Serialisierung via `sabre/vobject`. - `RemoteCalendarReader`: Liest Remote-Kalender. - `RemoteCalendarWriter`: Schreibt/loescht Remote-Events mit ETag-Unterstuetzung. - `EventMatchResolver`: Matching zuerst ueber `caldavHref`, dann `caldavUid`. - `SyncFieldExtractor`: Trennt bidirektionale Sync-Felder von lokalen Contao-only-Feldern. - `SyncHashGenerator`: SHA-256 ueber kanonische Sync-Felder. - `RemoteToLocalSynchronizer`: Pull inkl. Konfliktregel und Hard-Delete lokal. - `LocalToRemoteSynchronizer`: Push inkl. Konfliktregel und Hard-Delete remote. - `SyncRunner`: Orchestrierung je Kalender und Richtung. - `CalDavSyncCommand`: CLI-Einstiegspunkt. ## Mapping-Strategie Bidirektionale Felder (sync-relevant): - `title` - `start/end` - `all-day / with-time` (`addTime` Mapping) - `description` (`details`) - `location` - optional `url` Contao-only-Felder sind explizit nicht Teil des Sync-Hashes und loesen damit keinen Push aus. ## Logging-Strategie - `info`: erfolgreicher Abschluss pro Kalender inkl. Zaehler - `warning`: Konflikte (`remote wins`) mit Kontext (`calendarId`, `eventId`, `href`, `uid`) - Fehler laufen als Exceptions hoch und werden im Command als `FAILURE` signalisiert ## Command ```bash php bin/console contao:caldav:sync --direction=both php bin/console contao:caldav:sync --calendar=3 --direction=pull php bin/console contao:caldav:sync --direction=push --dry-run ``` Optionen: - `--calendar=ID` - `--direction=pull|push|both` - `--dry-run`