Kontakte für REDAXO, aufgebaut wie eine Kontakte-App: Adressbücher, Listen, beschriftete Mehrfachfelder, eigene Felder und Fotos. Über CardDAV erscheinen die Adressbücher direkt in Apple Kontakte, auf iPhone und iPad, in Thunderbird und auf Android.
- Adressbücher trennen Bestände, etwa „Verein“ und „Presse“. Rollen legen fest, wer welches pflegt.
- Listen ordnen Kontakte innerhalb eines Adressbuchs. Ein Kontakt kann in beliebig vielen Listen stehen. In Apps erscheinen Listen als Gruppen.
- Mehrfachfelder für Telefon, E-Mail, Adresse, Website, Datum, zugehörige Personen, soziale Profile und Messenger. Jeder Eintrag trägt eine Beschriftung: eine vorgegebene („Mobil“, „Arbeit“) oder eine eigene („Geschäftsstelle“).
- Eigene Felder wie „Kundennummer“ oder „Mitglied seit“: spontan je Kontakt oder als Vorgabe für alle.
- Fotos aus dem Medienpool oder aus der App. Sie gleichen sich in beide Richtungen ab.
- vCard zum Importieren und Exportieren, auch ganzer Adressbücher.
- REDAXO ab 5.18, PHP ab 8.4
- Addon
dav. Es stellt den DAV-Server, die Anmeldung, die App-Passwörter und die sabre-Bibliotheken. contacts bringt selbst keine Laufzeit-Abhängigkeiten mit. - Optional
a11y_datetime_addonfür den Datumswähler.
Zuerst das Addon dav installieren, dann contacts nach redaxo/src/addons/contacts klonen. contacts hat keine eigenen Laufzeit-Abhängigkeiten, ein composer install ist nur für die Tests nötig.
- Addon installieren.
- Unter Kontakte › Adressbücher ein Adressbuch anlegen.
- Den Rollen das Recht Kontakte: Kontakte pflegen (
contacts[]) geben und unter Adressbücher auswählen, welche sie pflegen dürfen. Kontakte: Adressbücher verwalten (contacts[books]) erlaubt zusätzlich das Anlegen von Adressbüchern und den Zugriff auf alle. - Unter Kontakte Listen in der Seitenleiste anlegen und Kontakte erfassen.
Die Seite Kontakte hat drei Spalten: links Adressbücher und Listen, in der Mitte die Kontakte mit Suche, rechts die Karte.
| Aufgabe | Weg |
|---|---|
| Kontakt anlegen | grüner Plus-Knopf neben der Suche. Steht links eine Liste, landet der Kontakt gleich darin. |
| Feld ergänzen | im Editor Feld hinzufügen: Telefon, E-Mail, Adresse, Website, Datum, zugehörige Person, soziales Profil, Messenger, Geburtstag, Notiz, eigenes Feld |
| Eigene Beschriftung | in der Auswahl vor dem Feld Eigene Beschriftung … wählen und Text eingeben |
| Eigenes Feld | Feld hinzufügen › Eigenes Feld …, dann Feldname und Wert. Vorgaben aus den Einstellungen stehen direkt im Menü. |
| Firma | Als Firma anzeigen: Die Firma wird zum Anzeigenamen und bestimmt die Sortierung. |
| Geburtstag ohne Jahr | Jahr einfach leer lassen |
| Listen zuordnen | Kontakt mit der Maus auf eine Liste in der Seitenleiste ziehen. Sind mehrere angehakt, wandern alle gemeinsam. Ohne Maus: im Editor unter Adressbuch und Listen, oder Kontakte anhaken und Zur Liste hinzufügen. Listen nehmen nur Kontakte aus ihrem eigenen Adressbuch an. |
| Liste umbenennen, exportieren, löschen | Liste wählen, dann das Menü mit den drei Punkten. Beim Löschen bleiben die Kontakte erhalten. |
| Suchen | findet Namen, Firma, Notiz und alle Feldwerte, etwa Telefonnummern oder die Kundennummer |
Die Suche arbeitet im gewählten Adressbuch oder in der gewählten Liste, unter Alle Kontakte über alles, was du pflegen darfst.
Kontaktdaten sind personenbezogen. Deshalb gilt: Ohne ausdrückliche Freigabe verlässt nichts das Backend. Drei Ebenen greifen ineinander, jede kann nur einschränken.
| Ebene | Wo | Wirkung |
|---|---|---|
| Kontakt | Editor, Abschnitt Website: Im Frontend zeigen | Ohne diesen Schalter erscheint der Kontakt nirgends. Mit ihm ist zunächst nur der Name öffentlich. |
| Angabe | Weltkugel-Knopf an jedem Eintrag, Häkchen für Foto, Firma und Position, Geburtstag, Notiz | gibt genau diese Angabe frei |
| Global | Einstellungen › Nie auf der Website zeigen | sperrt Stammdaten, ganze Feldarten oder einzelne Beschriftungen für alle Kontakte, etwa „Telefon: nur Mobil“. Geht jeder Freigabe vor. |
In der Kontaktliste und auf der Karte markiert eine grüne Weltkugel, was öffentlich ist. Die Freigabe kennt nur das Backend: Kontakte-Apps sehen sie nicht, und ein Abgleich per CardDAV setzt sie nicht zurück. Ändert sich in der App die Nummer selbst, gilt der Eintrag als neu und ist zunächst nicht freigegeben.
Unter Kontakte › Module lässt sich das Modul contacts: Kontaktliste installieren. Im Artikel wählt die Redaktion:
| Auswahl | Möglichkeiten |
|---|---|
| Kontakte aus | alle Adressbücher, ein Adressbuch oder eine Liste |
| Darstellung | Karten nebeneinander, Liste untereinander, Tabelle |
| Anzeigen | Foto, Firma und Position, Telefon, E-Mail, Adresse, Website, weitere Angaben, Notiz |
Die Auswahl im Modul schränkt nur weiter ein. Was am Kontakt nicht freigegeben oder global gesperrt ist, erscheint nie. Typisch: eine Liste „Vorstand“ als Karten mit Foto und E-Mail, dieselbe Liste an anderer Stelle als Tabelle mit Telefon.
use KLXM\Contacts\Contacts;
use KLXM\Contacts\Frontend\Frontend;
$people = Contacts::published(book: 'verein', list: 'Vorstand'); // nur öffentliche Kontakte, nur freigegebene Angaben
echo Frontend::renderList($people, ['layout' => 'cards', 'show' => ['photo', 'organization', 'email']]);
// oder ganz frei:
foreach ($people as $person) {
echo $person->displayName();
$photo = Frontend::photoUrl($person); // null, wenn das Foto nicht freigegeben ist
foreach ($person->items as $item) { … } // enthält nur freigegebene Einträge
}Contacts::published() liefert eine bereinigte Kopie jedes Kontakts. Nicht freigegebene Daten stecken darin nicht, ein Template kann sie also nicht versehentlich ausgeben. Auch die Suche (search:) durchsucht nur Freigegebenes. Das Fragment fragments/contacts/list.php lässt sich im Projekt überschreiben. Wer dagegen Contacts::contacts()->query() im Frontend nutzt, bekommt die vollständigen Daten und ist selbst verantwortlich.
| Einstellung | Wirkung |
|---|---|
| Namen anzeigen als | „Vorname Nachname“ oder „Nachname, Vorname“ |
| Sortieren nach | Nachname oder Vorname. Firmenkontakte sortieren nach der Firma. |
| Eigene Felder | ein Feldname je Zeile. Erscheinen bei jedem Kontakt im Menü Feld hinzufügen. |
| Eigene Beschriftungen | eine je Zeile. Stehen bei allen Mehrfachfeldern zusätzlich zur Wahl. |
| Nie auf der Website zeigen | globale Sperren, siehe oben |
- Beim Adressbuch In Kontakte-Apps anbieten eingeschaltet lassen. Ausschalten für Bestände, die nur im Backend leben sollen.
- Kontakte › Kontakte-Apps öffnen. Die Seite zeigt, welche Adressbücher dein Konto in der App sieht, und führt in drei Schritten zum App-Passwort und zu den Zugangsdaten.
- In der App ein CardDAV-Konto anlegen:
| Angabe | Wert |
|---|---|
| Server | https://example.org/dav/ |
| Benutzername | der REDAXO-Login |
| Passwort | das App-Passwort, nicht das REDAXO-Passwort |
| App | Weg |
|---|---|
| iPhone, iPad | Einstellungen › Kontakte › Accounts › Account hinzufügen › Andere › CardDAV-Account |
| Apple Kontakte (Mac) | Einstellungen › Accounts › Anderer Kontakte-Account › CardDAV, Accounttyp „Manuell“ |
| Thunderbird | Adressbuch › Neues Adressbuch › CardDAV-Adressbuch hinzufügen |
| Android | DAVx⁵ mit „URL und Benutzername“ |
| Inhalt | Verhalten |
|---|---|
| Namen, Firma, Abteilung, Position, Spitzname, Geburtstag (auch ohne Jahr), Notiz | vollständig in beide Richtungen |
| Telefon, E-Mail, Adresse, Website, Datum, zugehörige Personen, Profile, Messenger | mit Beschriftung, auch mit eigener |
| Eigene Felder | reisen als beschriftetes Textfeld. Apple zeigt sie unter „Zugehöriger Name“ mit dem Feldnamen als Beschriftung an und lässt sie dort bearbeiten. |
| Listen | erscheinen als Gruppen. Mitgliedschaften lassen sich in der App ändern. |
| Fotos | aus der App ins Backend und zurück. Ein Bild aus dem Medienpool hat Vorrang. Ein neues Foto aus der App ersetzt es. Bilder über 1,5 MB gehen nicht an Apps. |
| Angaben, die contacts nicht kennt (etwa phonetische Namen) | bleiben erhalten und gehen unverändert zurück |
Adressbücher lassen sich über CardDAV weder anlegen noch löschen oder umbenennen, das gehört dem Backend. Es gelten dieselben Rechte wie im Backend. Ein App-Passwort „nur lesen“ verhindert jede Änderung.
| App | Hinweis |
|---|---|
| Apple Kontakte auf dem Mac | zeigt je Account nur ein Adressbuch, das erste. Für den Mac eignet sich ein Adressbuch mit mehreren Listen. iPhone, iPad, Thunderbird und DAVx⁵ zeigen alle Adressbücher. |
| iPhone, iPad | zeigen Listen als Gruppen. Gruppen anlegen geht ab iOS 16 auch in der App. |
| Thunderbird | kennt keine Gruppen über CardDAV. Die Kontakte erscheinen vollständig, Listen nicht. |
| Alle | Apple verlangt HTTPS mit gültigem Zertifikat. |
Fehlersuche zur Verbindung (404 unter /dav/, 401 trotz richtigem Passwort) steht in der Hilfe des Addons dav.
Kontakte › Import und Export liest vCard-Dateien (.vcf) mit beliebig vielen Karten, etwa den Export aus Apple Kontakte, Google oder Outlook. Kontakte mit bekannter UID werden aktualisiert statt verdoppelt, Gruppenkarten werden zu Listen. Der Export liefert ein ganzes Adressbuch oder eine Liste als eine Datei, inklusive Fotos.
Namespace KLXM\Contacts, Einstieg über die Fassade Contacts.
use KLXM\Contacts\Contacts;
use KLXM\Contacts\Domain\ItemKind;
$book = Contacts::book('verein'); // per Slug oder ID
$lists = Contacts::lists()->forBook($book->id); // array<int, ContactList>
// Kontakte einer Liste, nach Name sortiert
foreach (Contacts::contacts()->query(listId: 3) as $contact) {
echo $contact->displayName(); // "Anna Beispiel" oder die Firma
echo $contact->first(ItemKind::Email)?->value; // erste E-Mail-Adresse
echo $contact->custom('Kundennummer'); // eigenes Feld
foreach ($contact->items(ItemKind::Phone) as $phone) {
echo $phone->labelText(), ': ', $phone->value; // "Mobil: +49 …"
}
}
// Suchen und blättern
$found = Contacts::contacts()->query(bookIds: [$book->id], search: 'kleve', limit: 20, offset: 0);
$total = Contacts::contacts()->count(bookIds: [$book->id], search: 'kleve');Es gibt einen Schreibweg: ContactRepository::save(). Er prüft, vergibt UID und Version, pflegt die Listen und hält die Änderung für den CardDAV-Abgleich fest. Backend, Import und CardDAV nutzen alle diesen Weg.
use KLXM\Contacts\Domain\Contact;
use KLXM\Contacts\Domain\Item;
$contact = new Contact();
$contact->bookId = $book->id;
$contact->firstName = 'Anna';
$contact->lastName = 'Beispiel';
$contact->items = [
new Item(ItemKind::Phone, 'mobile', '+49 171 1234567'),
new Item(ItemKind::Email, 'Geschäftsstelle', 'anna@example.org'), // eigene Beschriftung
Item::address('work', 'Hauptstr. 1', '47533', 'Kleve', country: 'Deutschland'),
new Item(ItemKind::Custom, 'Kundennummer', '4711'), // eigenes Feld
];
$contact->listIds = [3, 5];
Contacts::contacts()->save($contact);| Klasse | Aufgabe |
|---|---|
Contacts |
Fassade: books(), lists(), contacts(), book(), contact() |
Domain\Contact |
displayName(), personName(), subtitle(), sortName(), initials(), items(ItemKind), first(ItemKind), custom(string), birthdayDate(), Eigenschaften hasPhoto, birthdayHasYear |
Domain\Item |
kind, label, value, data (Adressbestandteile), labelText(), addressText(), href() |
Domain\ItemKind |
Phone, Email, Address, Url, Date, Related, Social, Messenger, Custom, jeweils mit labels() |
Domain\Book, Domain\ContactList |
Adressbuch und Liste |
Repository\ContactRepository |
find(), findByUid(), query(), count(), save(), delete() |
Repository\ListRepository |
forBook(), find(), save(), delete(), setListsOfContact() |
Repository\BookRepository |
all(), find(), findBySlug(), save(), delete(), counts() |
VCard\Serializer, VCard\Parser |
vCard 3.0 schreiben und lesen |
Import\Importer, Import\Exporter |
vCard-Dateien |
Frontend\Frontend |
renderList(), photoUrl(), reduce(); Konstanten LAYOUTS, SHOW_OPTIONS |
Settings |
publicBlocked(), isItemBlocked(), isFieldBlocked(), eigene Felder und Beschriftungen |
Security\Access |
canUse(), canEditBook(), books(), davBooks() |
Dav\AddressBookProvider, Dav\AddressBookBackend |
Anbindung an das Addon dav |
query() lädt keine Fotodaten. Das vollständige Objekt mit Foto liefert find(). Im Backend kommt das Bild über index.php?rex-api-call=contacts&action=photo&id=….
| Tabelle | Inhalt |
|---|---|
rex_contacts_book |
Adressbücher mit Sync-Token |
rex_contacts_contact |
Kontakte mit Namensfeldern, Foto, UID, Version und unbekannten vCard-Angaben |
rex_contacts_item |
Mehrfachfelder und eigene Felder: Art, Beschriftung, Wert |
rex_contacts_list, rex_contacts_list_member |
Listen und ihre Mitglieder |
rex_contacts_change |
Änderungsprotokoll für den CardDAV-Abgleich |
Alle Texte stehen in lang/de_de.lang und lang/en_gb.lang mit dem Präfix contacts_. Im Code: I18n::t('key'), für HTML I18n::e('key'). Texte der Web Components tragen das Präfix contacts_js_.
vendor/bin/phpunit --testsuite unit
CONTACTS_REDAXO_BOOT=/pfad/zur/boot-datei.php vendor/bin/phpunitDie REDAXO-Tests arbeiten in einem eigenen Adressbuch, das sie danach wieder löschen.
MIT, siehe LICENSE. Technische Grundlage für vCard und CardDAV ist sabre/dav.