Eine kleine lokale Website verwendet ein Terminbuchungs-Plugin. Diese Buchungen wurden anschließend manuell in einen Online-Kalender übertragen, damit das Team einen Überblick über die Buchungen hatte. Leider unterstützte das Plugin keine Funktion, mit der die Buchungen dynamisch in einer Kalender-App angezeigt werden konnten. Daher wurde ich gefragt, ob ich hier helfen kann. Um das Gezeigte aber für euch aber etwas nützlicher zu machen, werde ich nicht zeigen, die ich das für dieses spezielle Terminbuchungs-Plugin umgesetzt habe, sondern wie man den gleichen Ansatz verwenden kann, um alle eure veröffentlichten und geplanten Beiträge anzuzeigen.
Installieren der Abhängigkeiten
Wir werden eine dynamische .ical
Datei erstellen. Das ist eine Textdatei und wir könnten den „Code“ einfach selbst erzeugen, aber wir verwenden eine kleine Bibliothek, die uns dabei helfen wird. Für das Projekt habe ich die spatie/icalendar-generator
Library verwendet, welche alles hatte, was ich brauchte (und noch vieles mehr). Wir installieren sie einfach mit Composer in unseren Plugin-Ordner:
composer require spatie/icalendar-generator
Anschließend müssen wir die notwendigen Dateien laden. Der einfachste Weg, das mit Paketen zu tun, die mit Composer installiert wurden, ist die Verwendung des Composer-Autoloaders. Hierzu fügen wir diesen der PHP-Datei des Plugins hinzu:
require_once 'vendor/autoload.php';
Erstellung eines Kalenders
Jetzt können wir damit loslegen, einen dynamischen Kalender zu erstellen. Ich werde hier sehr einfache Codebeispiele verwenden, in der Dokumentation des Pakets findet ihr aber auch einige komplexere. Erstellen wir also erst einmal das $calender
Objekt:
$calendar = Calendar::create( 'example.com' );
Der Parameter der create()
Funktion wird für den Titel verwendet, er kann aber auch leer gelassen werden. Nachdem wir nun unser $calender
Objekt haben, würden wir uns die Daten für die Events holen. Hier führen wir lediglich eine Query aus, die uns die letzten veröffentlichten und geplanten Blog-Beiträge holt:
// Get all blog posts.
$query_args = [
'post_type' => 'post',
'post_status' => [
'publish',
'future',
],
'posts_per_page' => - 1,
];
$posts = get_posts( $query_args );
Nachdem wir alle Beiträge geladen haben, können wir für jeden davon ein individuelles Event erstellen:
// Create an event per blog post.
foreach ( $posts as $post ) {
$start_date = new DateTime( $post->post_date_gmt, new DateTimeZone( 'UTC' ) );
$end_date = ( clone $start_date )->add( new DateInterval( 'PT15M' ) );
$event = Event::create();
$event->name( $post->post_title );
$event->startsAt( $start_date );
$event->endsAt( $end_date );
$event->uniqueIdentifier( $post->ID );
$calendar->event( $event );
}
Wir verwenden hier GMT/UTC Zeiten, um es dem Kalender zu ermöglichen, sich an die lokale Zeitzone anzupassen. Für das „Enddatum“ addieren wir 15 Minuten dazu. Durch die Verwendung der Post-ID als „unique identifier“ kann eine Kalender-Applikation einfacher einzelne Events aktualisieren/synchronisieren. Zum Schluss fügen wir dann noch das Event zum zuvor erstellten $calendar
Objekt hinzu.
Im letzten Schritt müssen wir dann noch sie Ausgabe senden. Das wird mit folgenden Zeilen erreicht:
// Print the calendar output.
header( 'Content-Type: text/calendar; charset=utf-8' );
echo $calendar->get();
exit;
Importieren des iCalendar in eine Kalender-Anwendung
Den fertigen dynamischen Kalender wollen wir jetzt vermutlich in eine Kalender-App importieren (und synchronisieren). Dazu muss er über eine URL aufrufbar sein, die wir in der Anwendung eintragen müssen. Ich habe mich dazu entschieden, hierfür einen eigenen REST-Endpoint zu erstellen. Den bisherigen Code habe ich also in eine Callback-Funktion verschoben und dann den Endpoint wie folgt registriert:
function blog_posts_calendar_register_rest_route() {
register_rest_route(
'blog-posts-calendar/v1',
'/ical.ics',
[
'methods' => 'GET',
'callback' => 'blog_posts_calendar_generate_ical',
'permission_callback' => '__return_true',
]
);
}
add_action( 'rest_api_init', 'blog_posts_calendar_register_rest_route' );
Der Kalender kann dann über folgende URL aufgerufen werden: https://example.com/wp-json/blog-posts-calendar/v1/ical.ics
Der permission_callback
würde es hier allen erlauben, den Kalender zu abonnieren. Wenn ihr etwas restriktiver sein wollt, könnt ihr hier eure eigene Callback-Funktion implementieren.
Fazit
Selbst wenn ein Plugin eine Funktion mal nicht anbieten, kann man meistens etwas eigenen Code schreiben, um es verfügbar zu machen. Das ist oft auch einfacher als das ganze Plugin durch ein anderes zu ersetzen, was dann vielleicht eine andere Funktion nicht mehr hat. Im Falle eines Terminbuchungs-Plugins kann es vermutlich besonders schwer sein, dies durch ein anderes zu ersetzen, da man auch alle Daten zum andern Plugin migrieren muss.
Wenn ihr den Code mal selbst mit eurer Website testen wollt, dann findet ihr in als Plugin auf GitHub.