119 lines
3.4 KiB
Markdown
119 lines
3.4 KiB
Markdown
# 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`
|