Diese Woche hat Walter Ebert einen spannenden Tweet getwittert. Es ging um einen Codeschnipsel mit dem in WordPress die YouTube-URL geändert wurde auf die „ohne Cookies“-Variante. Johannes Kinast empfahl einen geeigneteren Filter, der performanter sein soll und ich fragte mich, wann genau das eigentlich gecached wird und wann welcher Filter eigentlich feuert. Ralf Wiechers hat dann noch einen weiteren Filter ausgegraben. Schauen wir uns dieses Wirwarr mal an und versuchen daraus schlau zu werden. Aber ohne Gewähr, denn ich schaue mir das Ganze beim Schreiben an. Wenn ich am Artikel-Ende keine Lösung habe, müsst ihr mir in den Kommentaren helfen …
Starten wir mit Walters Snippet, der den Anstoß geliefert hat:
/* Use YouTube privacy-enhanced mode. More info: https://support.google.com/youtube/answer/171780?visit_id=637419781721286051-946666784&rd=1 */ add_filter( 'the_content', function( $content ) { return str_replace( ' src="https://www.youtube.com/embed/', ' src="https://www.youtube-nocookie.com/embed/', $content ); }, 11 );
Der genutzte Filter ist hier the_content
. Laut Doku gilt für den Filter:
This filter is used to filter the content of a post after it is retrieved from the database and before it is printed to the screen.
Er feuert also jedes Mal, wenn der Artikel ausgegeben wird (ein mögliches Cache-Plugin ignorieren wir für die Betrachtung) mal. Daher vermutlich der Einwand, dass es performanter gehen müsste. Und zwar mit embed_oembed_html. Für diesen Filter gibt es nur eine sehr kurze Beschreibung:
Filters the cached oEmbed HTML.
Er filtert also nur einen Cache. Soso … dieser Cache muss ja auch mal generiert werden. Suchen wir also weiter. Da gibt es noch oembed_dataparse
und oembed_result
.
Wenn WordPress einen einbettungsfähigen Link im Inhalt findet, dann wird das vom oEmbed-Provider gelieferte HTML zurückgegeben. oembed_dataparse
filtert das zurückgelieferte HTML als erstes und passt das HTML je nach Typ gegebenenfalls etwas an. oembed_result
filtert dann direkt danach. Das Ergebnis wird gecached.
Daher müsste the_content
tatsächlich am längsten dauern. Der Filter kommt erst ganz am Ende zum Einsatz und filtert bei jedem Aufruf das gesamte HTML des Inhalts. embed_oembed_html
filtert zwar nur noch das gecachte HTML des oEmbed-Providers, aber eben auch jedes Mal. Nur die beiden letzten Kandidaten oembed_dataparse
und oembed_result
filtern bereits vor dem Cache und dürften so die performantesten sein. Siehe auch diese Diskussion auf WordPress Stackexchange.
Aber (!) mit einem kleinen Haken: Wenn der Filter erst aktiviert wird, nachdem der Cache bereits angelegt wurde, dann passiert gar nichts. Damit der Filter auch für bereits bestehende Artikel/Seiten greift, müssten die Postmeta-Informationen gelöscht werden.
Unser neuer Snippet (Ralfs version) sieht jetzt also so aus:
/* * Remove Cookies from YouTube Videos */ add_filter( 'oembed_result', 'sm_youtube_nocookie_domain', 10, 3 ); function sm_youtube_nocookie_domain($html, $url, $args) { if ( preg_match('#https?://(www\.)?youtu#i', $url) ) { return preg_replace( '#src=(["\'])(https?:)?//(www\.)?youtube\.com#i', 'src=$1$2//$3youtube-nocookie.com', $html ); } return $html; }
Da fiel mir ein, dass Embed Privacy doch mit dem gleichen Problem zu tun gehabt haben müsste. Schauen wir doch mal neugierig in den Quelltext:
Sie nutzen den Filter embed_oembed_html
:
add_filter( 'embed_oembed_html', [ $this, 'replace_embeds' ], 10, 3 );
Ändern ebenfalls die URL (und geben dann aber ein Template zum Nachladen aus):
// replace youtube.com to youtube-nocookie.com $output = str_replace( 'youtube.com', 'youtube-nocookie.com', $output );
Nur ein paar Sachen verwundern mich. Bei Aktivierung und Deaktivierung wird die Funktion clear_embed_cache
aufgerufen, mit foldender Erklärung im DocBlock:
/** * Embeds are cached in the postmeta database table and need to be removed * whenever the plugin will be enabled or disabled. */
Nach meinem Verständnis filtert doch embed_oembed_html
das gecachte Ergebnis!? Ein Löschen der Caches wäre daher gar nicht nötig. Das wäre nur bei oembed_dataparse
und oembed_result
notwendig.
Und wieso werden die Postmeta-Daten mit einem manuellen Query gelöscht?
// the query to delete cache $query = "DELETE FROM " . $wpdb->get_blog_prefix() . "postmeta WHERE meta_key LIKE '%_oembed_%'";
Und nicht mit delete_post_meta? Und warum hat WordPress genau dafür, zum Löschen aller oEmbed-Caches eine Funktion, nutzt sie aber nicht mehr selbst?
Und noch einen anderen Gedanken hatte ich: Wenn der oEmbed-Provider nicht angefragt werden soll, dann müssten sie doch eigentlich den Filter pre_oembed_result
nutzen, weil sonst der http-Request ja doch gemacht wird (oder ist das nur auf Serverebene und daher irrelevant)?
***
Vielleicht konnte ich ein bisschen zum Quelltext lesen anregen und vielleicht hat ja auch jemand Lust hier mitzumachen und weiter zu fachsimpeln. Stimmt das so? Habe ich was übersehen?
Ich freue mich über Gegenrede, Lob & Kritik und über Kekse (wieso komme ich gerade auf Cookies?). Falls also jemand keine Fachmeinung, aber Weihnachtskekse hat, dann gerne auch die schicken