Geschachtelte Shortcodes

Geschachtelte Shortcodes

Mit Shortcodes kann WordPress um nützliche Funktionen erweiterte werden. Neben den einfachen Shortcodes und solche, die einen Bereich umschließen, ist es auch möglich sie ineinander zu verschachteln.

Raus aus der Formatierungsfalle

In meinem Blog gibt es ab und an Kochrezepte, wie zum Beispiel gestern für die Aioli. Wenn man sich den Artikel näher ansieht, stößt man auf eine Besonderheit. Optisch stich das eigentliche Rezept hervor. Es ist eine Art gelber Notizzettel. Schaut man in den HTMl-Quelltext, zeigt sich der div-Block, mit dem dies realisiert wurde. Die verwendete Klasse, „notice“, gab es bereits im Theme „Pinboard“ — bei der Umstellung auf das neue Theme habe ich die CSS-Anweisungen entsprechen übertragen. Je häufiger ich Rezepte poste, desto nerviger wird für mich die Formatierung des Rezeptes. Es ist umständlich, da ich das nur in der Quelltextansicht von WordPress machen kann. Wenn ich länger kein Rezept mehr als Blogbeitrag bringe, habe ich wieder die Formatierung vergessen. Ich muss dann in alten Einträgen schauen, wie genau ich das formatiert habe. Der HTML-Block mit einer CSS-Klasse gefällt mir nicht wirklich im Beitrag. Beim Theme-Wechsel muss ich zudem wie beschrieben jedes Mal Anpassungen vornehmen.

Shortcodes in WordPress
MIH83 / Pixabay

Weiterer Nachteil

Ein weiterer Nachteil des hart formatierten Rezeptes ist die fehlende Flexibilität. Bewusst wurde mir das im Zusammenhang mit richtigen Foodblogs und anderen Seiten, auf denen sich Rezepte finden. Sollte ich eines Tages eine ganz andere Form der Darstellung wünschen, müsste ich jeden Blogeintrag mit Rezepten manuell ändern. Eine Umstellung zum Beispiel auf das strukturierte Format von schema.org für Rezepte würde von vornherein am Arbeitsaufwand scheitern. Dabei ist die Lösung beider Problem im Grunde genommen relativ simple. Statt wie bisher über HTML-Tags das Rezept zu formatieren, definiere ich mir eigene Shortcodes. Das geht entweder über die Datei functions.php des aktuellen Themes oder noch eleganter über ein Plugin.

Bisheriger harte Formatierung

Die bisherige harte Formatierung sieht so aus:

<div class="notice warning">
<h4>TITEL</h4>
<p><strong>Zutaten</strong><br>
…
</p>
<p><strong>Zubereitung</strong></p>
<p>
…
</p>
</div>

Bei den Zutaten sind die einzelnen Bestandteile simple aufgelistet. Jede Zutat steht in einer neuen Zeile, es gibt keine spezielle Liste oder ähnliches. Die Schritte der Zubereitung sind jeweils in Absätze unterteilt. Weitere Angaben wie zum Beispiel Kochzeit und Anzahl der Portionen fehlen vollständig.

Die Shortcodes Variante

Wenn ich die bisherige Formatierung 1:1 durch Shortcodes ablösen wollte, sähe die neue Fassung für ein Rezept innerhalb eines Blogeintrages im Backend wie folgt aus:

[rezept titel="TITEL"]
	[zutaten]
	[/zutaten]
	[zubereitung]
	[/zubereitung]
[/rezept]

Würde ich das jetzt so verwende, passiert selbstverständlich noch gar nichts. Die Darstellung im Frontend entspräche genau dem, was ich im Backend eingeben würde. Es muss also entsprechend eine Funktion festgelegt werden, die die Shortcodes umwandelt. Fangen wir von außen an und gehen dann nach innen. Die Funktion für den äußeren umschließende Shortcode entspricht in etwa der, die ich für den Zitat-Shortcode verwendet habe:

function rezept_shortcode($atts,$content) {
extract(shortcode_atts( array(
'titel' => 'Rezept ohne Titel',
), $atts, 'rezept' ));
return '<div class="notice warning"><h4>'.$titel.'</h4>'.$content.'</div>';
}
add_shortcode('rezept', 'rezept_shortcode');

Unschöne Absätze

Ohne CSS-Formatierung sieht man noch nicht viel, aber man kann sich die Ausgabe im Quelltext ansehen. Dabei fällt ein unschönes Detail auf:

<div class="notice warning"><h4>Gebratener Thunfisch</h4><p></p>
<p>Hier könnte noch was stehen</p>
<p></p></div>

WordPress hat den Inhalt um zusätzliche p-Tags ergänzt. Verantwortlich dafür ist die Funktion wpautop(), welche bei WordPress standardmäßig immer aktiv ist. Sie sorgt für eine Umwandlung doppelte Zeilenumbrüche, so dass der Inhalt mit p-Tags umschlossen wird. In der Regel muss und sollte man diese Funktion nicht deaktivieren, es sei denn man hat ein guten Grund dafür und weis, was man tut:

remove_filter( 'the_content', 'wpautop' );

Schaltet man nämlich die automatische Formatierung komplett ab, wirkt sich das auf alles aus, was im Frontend ausgegeben wird. Beim eigenen Shortcode würde es daher im Prinzip reichen, wenn wpauto erst aktiv wird, nach dem der Shortcode von WordPress verarbeitet wurde.

WordPress Prioritäten

Bei der Abarbeitung von WordPress Funktionen werden Prioritäten verwendet. Dadurch wird definiert, zu welchem Zeitpunkt ein bestimmter Prozess abläuft. Die Standard-Priorität für wpauto ist 10. Für die Verarbeitung von Shortcodes ist die Priorität 11. Genau hier liegt der Schlüssel für die Lösung unseres Problems. Wir müssen WordPress lediglich anweisen, für wpauot eine andere Priorität zu verwenden. Das geschieht durch folgende Ergänzung in der Datei functions.php des Themes:

remove_filter('the_content', 'wpautop');
add_filter('the_content', 'wpautop', 12);

Zunächst wird damit der Filter wpauto komplett entfernt und anschließend wieder neu gesetzt, diesmal mit einer niedrigeren Priorität — je höher die Zahl, desto niedriger die Priorität in Bezug auf die Ausführung.

Geschachtelte Zutaten

Wird jetzt der Shortcode für ein Rezept erweitert, so dass innerhalb des Rezeptes auch die Zutaten stehen, reicht die Funktion dafür innerhalb der functions.php nicht aus:

function zutaten_shortcode($atts,$content) {
return '<p><strong>Zutaten</strong><br>'.$content.'</p>';
}
add_shortcode('zutaten', 'zutaten_shortcode');  

Der Block [zutaten] [/zutaten] wird im genau so wie im Backend eingetragen im Frontend angezeigt. Ursache dafür ist, dass innerhalb der Funktion rezept_shortcode() der Inhalt der Variable $content ungefiltert ausgegeben wird. Entsprechend wird damit auch kein Shortcode, der sich innerhalb befindet, verarbeitet. Um das zu ändern, muss die Funktion rezept_shortcode() erweiterte werden:

function rezept_shortcode($atts,$content) {
extract(shortcode_atts( array(
'titel' => 'Rezept ohne Titel',
), $atts, 'rezept' ));
return '<div class="notice warning"><h4>'.$titel.'</h4>'. do_shortcode($content).'</div>';
}
add_shortcode('rezept', 'rezept_shortcode');

Die entscheidenen Änderung hier ist die Verwendung der WordPress-Funktion do_shortcode(). Damit wird innerhalb der Inhalt der Variable $content auf mögliche Shortcodes untersuchen und sofern welche vorhanden sind, diese entsprechend angewendet.

Die Zubereitung

Für die Zubereitung kann parallel zur Funktion für die Zutaten eine Funktion erstellt werden. Die Rückgabewerte sieht hier etwas anders aus, da die Überschrift „Zutaten“ in einem eigenen Absatz stehen soll:

function zubereitung_shortcode($atts,$content) {
return '<p><strong>Zubereitung</strong></p>'.$content;
}
add_shortcode('zubereitung', 'zubereitung_shortcode');  

In diesem Beispiel werden eingegeben Absätze im Backend auch bei der Ausgabe der einzelnen Schritte im Frontend berücksichtigt. Sollte das bei anderen eigene Shortcodes nicht der Fall sein, kann die Funktion wpauto() auf die Inhaltsvariable angewendet werden.

Fazit

Mit dem Codebeispiel sollte es möglich sein, für eigene Anwendungsfälle Funktionen für geschachtelte Shortcodes zu entwicklen.

One Reply to “Geschachtelte Shortcodes”

Kommentar verfassen

über Thomas Boley

Geboren wurde ich im Jahre des Herren 1971 in Wesel am Niederrhein – die Kommentare an dieser Stelle bezüglich des Bürgermeisters bitte verkneifen! Mein Verhältnis zu dieser Stadt würde wohl den Umfang dieser Seite sprengen. Nur soviel sei gesagt: Es ist durchaus durchwachsen, worin es sich aber nicht von meinem Verhältnis zu Bielefeld unterscheidet. Nach dem üblichen Werdegang (Kindergarten, Schule, Abitur, Zivildienst) und den üblichen jugendlichen Irrungen und Wirrungen verschlug es mich zum Studium nach Bielefeld verschlagen. 18 Jahre später ging es dann zurück an den Rhein, in die Domstadt Köln. mehr erfahren