Erstellen eines dynamischen iCalendar mit Blog-Beiträgen

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.

Veröffentlicht von

Bernhard ist fest angestellter Webentwickler, entwickelt in seiner Freizeit Plugins, schreibt in seinem Blog über WordPress und andere Themen, treibt sich gerne bei den WP Meetups in Berlin und Potsdam herum und läuft nach Feierabend den ein oder anderen Halbmarathon.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert