diff --git a/README.md b/README.md index 8b8cef3..a4058da 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # CalDAV Sync Bundle (Contao 5.7) -Produktionsreifes 2-Way-CalDAV-Sync-Bundle fuer Contao 5.7 (PHP 8.4). -Es synchronisiert Events zwischen `tl_calendar_events` und einem oder mehreren CalDAV-Kalendern. +Internes Bundle fuer 2-Way-CalDAV-Sync in Contao 5.7 (PHP 8.4). +Diese README ist bewusst technisch gehalten (Prinzip, Logik, Betriebs-Commands) und kein oeffentliches Tutorial. ## Umfang (V1) @@ -11,58 +11,25 @@ Es synchronisiert Events zwischen `tl_calendar_events` und einem oder mehreren C - Konfliktaufloesung pro Event ueber Last-Modified-Wins (mit Toleranz) - Contao-only-Felder werden nicht in den Sync-Hash aufgenommen -## Voraussetzungen +## Betriebsrelevante Konfiguration (tl_calendar) -- PHP `^8.4` -- Contao `^5.7` -- `symfony/http-client` `^7.3` -- `sabre/vobject` `^4.5` +Verwendete CalDAV-Felder pro Kalender: -## Installation +- `caldavSyncEnabled` +- `caldavUrl` +- `caldavUsername` +- `caldavPassword` +- `caldavAuthorId` +- `caldavTimezone` (Fallback `UTC`) +- `caldavCalendarHrefs` (Mehrfachauswahl) +- `caldavPastSyncRange` (`none|all|1y|2y`) +- `caldavFutureSyncRange` (`all|1y|2y`) +- `caldavSyncCtags` (technischer Cache pro Remote-URL) -### 1) Bundle als Composer-Abhaengigkeit einbinden +Mehrfachauswahl-Logik: -Bei lokalem Bundle-Checkout z. B. im Projekt-Composer: - -```json -{ - "repositories": [ - { - "type": "path", - "url": "bundles/caldav-sync-bundle", - "options": { "symlink": true } - } - ], - "require": { - "mummert/caldav-sync-bundle": "*@dev" - } -} -``` - -Dann installieren: - -```bash -composer update mummert/caldav-sync-bundle -php vendor/bin/contao-console contao:migrate -php vendor/bin/contao-console cache:clear -``` - -## Backend-Konfiguration (Kalender) - -In `System -> Kalender` den gewuenschten Kalender oeffnen und unter CalDAV konfigurieren: - -- `CalDAV Sync aktivieren` -- `CalDAV URL` -- `CalDAV Benutzername` -- `CalDAV Passwort` -- `CalDAV Autor` (Pflichtfeld, wird fuer importierte Events gesetzt) -- optional `CalDAV Zeitzone` (Fallback: `UTC`) -- `Remote-Kalender` als Mehrfachauswahl (CheckboxWizard) - -Hinweis zur Mehrfachauswahl: - -- Es koennen mehrere Remote-Kalender unter einer Verbindung ausgewaehlt werden. -- Events aus abgewaehlten Remote-Kalendern werden beim naechsten Pull fuer den betroffenen Contao-Kalender entfernt. +- Ein Contao-Kalender kann mehrere Remote-Kalender referenzieren. +- Beim Pull werden importierte Events aus abgewaehlten Remote-Kalendern entfernt. ## Sync ausfuehren @@ -78,6 +45,13 @@ Optionen: - `--direction=pull|push|both`: Richtung waehlen (Default `both`) - `--dry-run`: keine Schreiboperationen lokal/remote +Ergaenzende Betriebs-Commands: + +```bash +php vendor/bin/contao-console contao:migrate --no-interaction +php vendor/bin/contao-console cache:clear +``` + ## Sync-Verhalten im Detail ### Reihenfolge bei `--direction=both` @@ -85,18 +59,33 @@ Optionen: 1. Push (lokal -> remote) 2. Pull (remote -> lokal) +### Delta-Sync (CTAG + ETAG) + +- CTAG wird per `PROPFIND` gelesen und pro Kalender-URL in `caldavSyncCtags` gespeichert. +- Wenn CTAG unveraendert ist, wird Pull fruehzeitig uebersprungen. +- Delta-Inventar per `REPORT` (href + etag). +- `GET` nur fuer neue/geaenderte Remote-Objekte. + ### Konfliktregel (Last-Modified-Wins) - Lokal wird ueber `tl_calendar_events.tstamp` bewertet. - Remote wird ueber `LAST-MODIFIED` bzw. `DTSTAMP` bewertet. - Es gilt eine Toleranz von 120 Sekunden. - Wenn Remote-Zeitstempel fehlen, wird konservativ lokal bevorzugt. +- Alle Vergleiche erfolgen auf Unix-Timestamps. + +### Kalenderbindung beim Matching + +- Events werden pro `tl_calendar_events.pid` geladen und nur in diesem Kalender verarbeitet. +- Matcher nutzt `caldavHref` und `caldavUid`, optional mit explizitem Guard auf erwartete `calendarId`. +- Zielkalender fuer Push wird ueber `caldavCalendarHref` auf die aktuelle Config-URL aufgeloest. ### Loeschverhalten - Pull: lokale Gegenstuecke ohne Remote-Pendant werden geloescht. - Push: Remote-Events ohne lokales Pendant werden geloescht. - Zusaetzlich entfernt der Runner bei Pull importierte Events aus inzwischen abgewaehlten Remote-Kalendern. +- Bei aktivem Zeitfenster werden Events ausserhalb des Fensters nicht aktiv geloescht. ### Publikationsverhalten @@ -113,6 +102,11 @@ Bidirektional (hash-relevant): - `location` - `url` (optional) +Hash-Regel: + +- SyncHash basiert ausschliesslich auf den oben genannten bidirektionalen Feldern. +- Push erfolgt nur bei Hash-Aenderung (oder Initialzustand ohne gespeicherten Hash). + Technische Sync-Felder in `tl_calendar_events`: - `caldavCalendarHref` @@ -145,6 +139,14 @@ Alias-Verhalten: - Sync ist command-getrieben; ein Cronjob sollte das Command zyklisch starten. - CalDAV-Passwort wird als Klartext fuer Authentifizierung verwendet. +## Kernkomponenten + +- `SyncRunner`: Orchestrierung je Kalender und Richtung +- `LocalToRemoteSynchronizer`: Push + LMW + Hash-Guard + Deletes +- `RemoteToLocalSynchronizer`: Pull + LMW + Delta + Deletes +- `RemoteCalendarReader`: CTAG/REPORT/GET-Deltalogik +- `SyncFieldExtractor`: Feldmapping inkl. all-day-Umrechnung + ## Troubleshooting - Keine Kalender in der Mehrfachauswahl: