Release: CalDAV sync bundle hardening and LMW sync

This commit is contained in:
Jürgen Mummert
2026-03-27 22:16:48 +01:00
commit c6f63a56a9
36 changed files with 2993 additions and 0 deletions
+118
View File
@@ -0,0 +1,118 @@
# 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`