Gutenberg Test

Vorwort

Dieser Artikel ist auf der Fahrt zum WordCamp Cologne entstanden. Ich habe dabei zum ersten Mal Gutenberg getestet und da ich nicht einfach nur sinnlosen Text tippen wollte, habe ich mich entschieden, daraus eine Geschichte zu machen. Aber lest selbst …

Eine kleine WeihnachtsGutenberg-Geschichte

Das sieht ja schon mal sehr schick aus. Was kann man denn hier alles machen? Wie wäre es zum Beispiel mit fettem oder kursivem Text?

Oder mit einem Link auf meinen Blog? Geht das vielleicht auch noch immer mit STRG + V, wie ich es mal beschrieben hatte? Ja, das klappt noch, super!

Weiterlesen →

Shortcodes in Sidebar-Widgets einfügen

Shortcodes sind wirklich praktisch, wenn man dynamischen Content in statische Seiten und Beiträge einfügen will. WordPress bringt schon einige interne shortcodes mit, wie etwa den gallery shortcode (der normalerweise im Backend gerendert wird).Standardmäßig funktionieren diese Shortcodes nur im Inhalt von Seiten und Beiträgen

Einfügen von Shortcodes mit dem Text oder HTML Widget?

Nun könnte man annehmen, dass man einfach das Text oder HTML widget verwenden kann. Aber leider funktioniert diese Lösung nur für einige Shortcodes, bei anderen führt es dazu, dass der Shortcode gar nicht ausgewertet wird. The gallery Shortcode etwa wird bei beiden nicht angezeigt und das Syntax-Highlighting-Plugin, das ich einsetzte, spuckt entweder falschen Code aus oder es funktioniert gar nicht.

Das Shortcode Widget Plugin

Wie fast immer ist dieses Problem nicht neu ein jemand anderes hat schon eine Lösung hiefür gefunden. Das Plugin Shortcode Widget wurde genau für diese eine Aufgabe geschrieben. Sobald man es installiert und aktiviert hat, findet man ein neues Widget, das ein wenig wie das alte Text-Widget aussieht und nur einen Titel und eine Textbox hat. Hier hinein kann man nun einen beliebigen Shortcode einfügen und das Widget dann in einer beliebigen Widget-Area verwenden.

Der Umgang mit geschlossenen Plugins aus dem Plugin-Verzeichnis

Ich bin mir sicher, dass ihr alle Plugins aus dem offiziellen Plugin Directory verwendet. Alle diese Plugins werden bei der Einreichung geprüft, bevor sie online gehen. Sollten sie in den letzten zwei Jahren nicht aktualisiert worden sein, kann man sie über die Suche nicht mehr finden (man kann sie aber weiterhin downloaden, sofern man den Direktlink noch kennt). Aber habt ihr euch mal gefragt was passiert, wenn ein Plugin geschlossen und aus dem Plugin-Directory entfernt wurde, aus welchem Grund auch immer?

Ein potentielles Sicherheitsrisiko

Ein Plugin kann aus verschiedenen Gründen geschlossen und/oder entfernt werden. Aktuell sind folgende Gründe denkbar:

  • Security Issue
  • Author Request
  • Guideline Violation
  • Licensing/Trademark violations
  • Merged into Core

Zwei meiner eigenen Plugins werden wohl auch bald geschlossen werden, da ihre Funktionalität entweder bereits im Core gelandet ist oder dieses in naher Zukunft passieren wird. In diesen Fällen ist es also nicht unbedingt kritisch, wenn diese weiterhin installiert und aktiviert sind, sofern sie sich nicht mit den Core-Funktionen ins Gehege kommen. Aber was ist mit Plugins, die ein Sicherheitsrisiko darstellen können? Das ist ein echtes Problem.

Keine Benachrichtigung der Nutzer

Wenn ein Plugin geschlossen wird, werden die Nutzer, die es noch installiert (und vielleicht sogar aktiviert) haben darüber nicht informiert. Selbst wenn der Pluginautor also einen Weg gefunden hat, die Sicherheitslücke zu schließen, würde kein Nutzer davon profitieren, da der einzige Weg einer Aktualisierung, der über das Plugin-Directory, nicht mehr existiert. In der Zwischenzeit sind alle Websites mit der alten Version potentiell für Hacker angreifbar.

Ein Plugin als Rettung

Da dieses Problem schon eine ganz Weile besteht und das Plugin-Team bisher noch mit keiner schnellen Lösung dienen konnte, wurde das Plugin No Longer in Directory veröffentlicht. Wenn man es installiert und auf dessen Einstellungsseite geht, bekommt man eine Liste aller Plugins angezeigt, die seit mehr als zwei Jahren nicht mehr aktualisiert wurden sowie eine Liste aller Plugins, die nicht im Plugin-Directory gefunden werden konnten.

Diese zweite Liste würde aber auch Plugins auflisten, die niemals im Plugin-Directrory veröffentlicht waren. Das sind beispielsweise Premium-Plugin oder Plugins, die man speziell für ein Kundenprojekt entwickelt hat. Die Lösung ist also auch nicht optimal.

Ein neuer Weg geschlossene Plugins hervorzuheben

Über die „Ideas“ Seite auf WordPress.org wurde daher eine ganze Weile zu diesem Thema diskutiert. Gestern hat das Meta/Plugin-Team auf dem Contributor Day des WordCamp US angekündigt, dass gerade hart an einer Lösung gearbeitet wird. Sie haben hierzu ein paar Mockups im entsprechenden Trac-Ticket veröffentlicht und auch ein erstes Beispiel für die Ansicht eines geschlossenen Plugins existiert bereits. Vorher wurde beim Aufruf eines geschlossenen Plugins eine 404 Fehlerseite angezeigt ohne einen Hinweis darauf, dass dieses Plugin mal existiert hat und warum es geschlossen/entfernt wurde.

Fazit

Der Umgang mit geschlossenen und entfernen Plugins ist sehr wichtig und sollte in einer transparenten Art und Weise passieren, damit die Nutzer dieses Plugins über mögliche Sicherheitsprobleme informiert sind, und das Plugin entfernen können, bevor ihre Website gehackt wird. Ich bin mir nicht sicher, ob es zusätzlich möglich sein sollte Plugins direkt zu löschen oder den Nutzern einen Hinweis im Dashboard anzuzeigen. Aber ich hoffe, dass dieses Thema nun etwas mehr Aufmerksamkeit bekommt.

Multisite-Administratoren die Option „Zusätzliches CSS“ freischalten

Dieser Blog läuft auf einer Multisite, damit ich meine Beiträge einfach mit MultilingualPress übersetzen kann. Eine weitere Seite auf dieser Multisite-Installation ist die Website des WP Meetup Berlin. Auf diese Seite gibt es weitere Nutzer mit der Adminstrator-Rolle. Mit dieser Rolle kann man die meisten Dinge tun, die man auch auf einer Singlesite tun kann. Mit einigen Ausnahmen:

  • Aktualisieren von Core, Plugins, Themes, etc.
  • Websites hinzufügen
  • Nutzer hinzufügen
  • Plugins installieren
  • Themes installieren
  • Den Editor für Plugins/Themes nuzten (was man ohnehin nie tun sollte)
  • Ungefiltertes HTML verwenden
  • Die Option „Zusätzliches CSS“ im Customizer verwenden

Diese letzte Ausnahme hat mich wirklich überrascht. Ich hätte erwartet, dass dies die einzige Möglichkeit ist, mit der Adminsitratoren einer Website das Design der Seite anpassen können (da sie ja keine Themes oder Child-Theme hochladen oder deren Dateien verändern können). Aber nur Super-Administratoren können diese Option nutzen.

Die Option für Website-Administratoren freischalten

Glücklicherweise gibt es für diese Option die Berechtigung edit_css, die wir lediglich die diesen Admins zuweisen müssen. Die kann man entweder mit einem Role-Management-Plugin wie Members tun, oder aber mit dem Plugin Multisite Custom CSS, das genau diese eine Aufgabe erfüllt.

Fazit

Aus Sicherheitsgründen macht es absolut Sinn, dass Admins einer einzelnen Website einer Multisite die Dateien eines Themes nicht verändern dürfen. Ihnen aber auch die Möglichkeit zu nehmen, die Option „Zusätzliches CSS“ im Customizer zu verwenden, macht für mich keinen Sinn. Zum Glück ist es mit einem der vorgestellten Plugins sehr einfach möglich, diese Option zu aktivieren.

Den WordPress.org Link aus Meta Widget entfernen

WordPress bring eine Menge Widget mit. Eines dieser Widgets ist das Meta Widget. Wenn man WordPress frisch installiert, wird dieses Widget normalerweise auch in die Sidebar eingefügt. Auf den meisten Seiten wird dieses Widget direkt wieder entfernt, da sein Nutzen nicht gesehen wird. Aber auch manchen Seiten kann es echt praktisch sein. Es hat Link zur Registrierung (falls erlaubt), zur Anmeldung (falls nicht gerade angemeldet), dem RSS-Feed der Beiträge, dem RSS-Feed der Kommentare der aktuellen Seite bzw. des aktuellen Beitrags:

In einer Facebook-Gruppe kam die Frage auf, ob man den Link zur WordPress.org Website im Meta-Widget entfernen können. Glücklicherweise gibt es genau für diesen Link einen Filter. Hierüber kann man den Inhalt des Links ändern oder einfach einen leeren String zurückgeben. Mit einer der „magischen Callback-Funktionen“ in WordPress erreicht man das mit einer einzelnen Zeile Code:

add_filter( 'widget_meta_poweredby', '__return_empty_string' );

Mehr braucht es nicht, um den Link zu WordPress.org aus dem Meta-Widget zu entfernen. Ich würde den Links selbst nicht entfernen, aber wenn ihr ihn nicht haben möchtet, könnt ihr einfach diese eine Zeile Code verwenden oder das kleine Plugin, das ich hierzu als Gist veröffentlicht haben.

Den „Geschützt“ und „Privat“ Präfix bei Beiträgen entfernen

Vor ein paar Wochen hatten wir in einem Projekt die Anfrage, die beiden Präfixe „Privat: “ und „Geschützt: “ vor dem Titel eines Custom Post Types zu entfernen. Wenn ihr nicht wisst, wovon ich gerade rede, lasst es mich kurz erklären.

Die Sichtbarkeit von Beiträgen

Wenn man einen Blogbeitrag schreibt hat man in der Metabox „Veröffentlichen“ die Option „Sichtbarkeit“. Normalerweise steht diese immer auf „Öffentlich“. Es gibt aber zwei weitere Optionen: „Passwortgescshützt“ und „Privat“. Wenn man die erste Option auswählt, werden Beiträge nur angemeldeten Besuchern angezeigt, egal welche Rolle diese haben. Bei der zweiten Option kann man ein einzelnes Passwort festlegen, das die Beiträge schützt (dieses Passwort wird im Klartext im Beitrag gespeichert).

Änderungen am Beitragstitel

Wenn man einen der beiden Sichtbarkeiten wählt, fügt WordPress einen Präfix „Geschützt: “ oder „Privat: “ vor den Beitragstitel ein, sofern die Funktion the_title() zur Ausgabe verwendet wird. Wie kann man also den Präfix entfernen, wenn man ihn nicht möchte?

Den Präfix über Filter entfernen

Um den Filter zu entfernen können wir einfach die beiden Filter private_title_format und protected_title_format verwenden, um den Beitragstitel solcher Beiträge zu ändern. Hierzu brauchen wir nur diese wenigen Zeilen Code:

function remove_pp_prefix_title_format( $content ) {
    return '%s';
}
add_filter( 'private_title_format', 'remove_pp_prefix_title_format' );
add_filter( 'protected_title_format', 'remove_pp_prefix_title_format' );

Fazit

Mit wenigen Zeilen Code können wir also einfach den Titel von geschützten und privaten Beiträgen ändern. Als die gleiche Frage etwas später in Facebook aufkam, habe daraus ein kleines Plugin gemacht und als Gist veröffentlicht. Kurz danach habe ich aber rausgefunden, dass jemand sogar Plugin im offiziellen Plugin Directory veröffentlicht wurde. Ich hoffe also, dass euch dies auch weiterhelfen kann.

MailChimp ändert Anmeldeformulare auf Single-Opt-in

Eine Freundin, deren WordPress Website ich erstellt habe und die MailChimp für ihren Newsletter verwendet, hat vor ein paar Stunden folgende E-Mail erhalten und mit weitergeleitet:

In dieser E-Mail kündigt MailChimp an, dass ab dem 31. Oktober alle Anmeldeformulare auf eine Single-Opt-in Verfahren umgestellt werden, statt dem bisherigen Double-Opt-in.

Ein riesiges Problem für Websites in Europa

Sie wusste nicht genau, was das für sie bedeutet, aber als ich die E-Mail gesehen habe, konnte ich kaum glauben, was ich da lesen musste. Das Double-Opt-in Verfahren ist das einzige zulässige, bei dem man berechtigt ist, die Empfänger auf der E-Mail-Liste anzuschreiben. Hierzu muss muss jeder Empfänger seine Eintragung in diese Liste „ein zweites Mal bestätigen“, indem er nach dem eigentlichen Anmeldeformular zusätzlich noch auf einen Link in der Willkommens-E-Mail klickt. Nur so wird sicher gestellt, dass der Empfänger sich selbst angemeldet hat und dem späteren Empfang von Newslettern zustimmt.

Viele Unternehmen in den USA oder anderen Teilen der Welt haben dieses Verfahren vermutlich nicht gemocht, führte es doch dazu, dass einige potentielle Empfänger diesen Link niemals geklickt haben und daher auch nicht angeschrieben werden durften. Aber genau dieses Double Opt-in Verfahren ist fundamental wichtig für Europa. Es stellt aktuell den einzigen legalen Weg dar, eine E-Mail-Empfängerliste anzulegen. Jeder Single-Opt-in Verfahren birgt die Gefahr einer Abmahnung oder anderer rechtlicher Konsequenzen. In Deutschland ist das mit dem „Gesetz gegen den unlauteren Wettbewerb“ begründet.

Wie kann man das Problem beheben?

Am Ende der E-Mail befindet sich ein Link, der zu einer Einstellungsseite führt, auf der man alle Listen auswählen kann, für die man das Double-Opt-in Verfahren wieder aktivieren möchte:

Ich kann nur jedem Webseitenbetreiber in Deutschland (und wohl auch in allen anderen europäischen Ländern) nur dringend empfehlen, diese Einstellung unverzüglich vorzunehmen.

Update: Solltet ihr die Mail (noch) nicht bekommen haben, versucht mal folgenden Link: https://admin.mailchimp.com/lists/opt-in-status/

Fazit

Selbst wenn MailChimp gute Gründe für diesen Schritt haben sollte, so kann ich dennoch nicht verstehen, wie sie dies auch für bestehende Formulare umsetzen können und wieso sie ihre Kunden gerade einmal eine Woche vorher informieren. Es war schon immer schwierig, um nicht zu sagen gefährlich, MailChimp in Deutschland einzusetzen. Mit dieser Änderung werden sich wohl einige Kunden nach Alternativen wie etwa CleverReach umsehen.

Haftungsausschuss

Ich bin kein Anwalt, daher sind alle Informationen nach besten Wissen und Gewissen geschrieben worden. Kontaktiert also im besten Fall einen Fachanwalt, um eure persönliche Situation einschätzen zu lassen.

Customizer Optionen mit Polylang übersetzen

Wenn es um das Übersetzen von WordPress Seiten geht, ist mein Lieblingsplugin MultilingualPress. Für ein neues Kundenprojekt mit sehr kleinem Budget, das nur wenige statische Seiten hatte und bei dem eine Multisite nicht umbedingt notwendig war, haben wir uns aber für Polylang entschieden.

Probleme bei der Übersetzung der Inhalte

Einer der Hauptgründe, weshalb ich MultilingualPress gegenüber den anderen Lösungen bevorzuge ist die Tatsache, dass es auf die Multisite-Funktionalität von WordPress aufsetzt. In diesem Fall ist es nämlich sehr einfach wirklich jeden Bereich der Website zu übersetzen. Selbst die Verwendungen unterschiedlicher Themes, Plugins, Widgets, Menüeinträgen, usw. ist hiermit ohne weiteres möglich. Mit einer normalen WordPress Installation sind manche Texte nur einmal vorhanden, wie etwa die Einstellungen eines Plugins und die Customizer Optionen.

In dem erwähnten Projekt hat das Theme Customizer Optionen angeboten, um auf der Startseite im Header Kontaktinformationen direkt neben dem Logo zu platziern. Weiterhin konnte man den Text im Footer über eine Textarea überschreiben. Das braucht man auf einer deutschen Website auch meisten, da hier in der Regel die Links zu Impressum und Datenschutzerklärung positioniert sind. Diese Optionen mussten also übersetze werden, ebenso wie die Kontaktinformationen im Header, da hier Uhrzeiten angegeben waren.

Erstellung eines Child Themes für die Übersetzungen

Leider konnte ich keine Lösung finden, die mit der Codebasis des Themes umgesetzt werden konnte. Also habe ich mich dazu entschlossen ein Child Theme zu erstellen, das das Header- und Footer-Template überschreibt. Der Header sah in etwa wie folgt aus:

<div class="intro-wrap">
  <?php echo wp_kses_post( wpautop( get_theme_mod( 'header_intro' ) ) ); ?>
</div><!-- end .intro-wrap -->

Die Customizer Option header_intro wurde hierbei einfach nur ausgeben. Es gibt hier keinen Filter auf den Wert, den man verwenden konnte. Wie kann man den Text also dennoch übersetzen? Hierzu bietet die Polylang API die Funktion pll__, mit der der Wert vor der Ausgabe übersetzt werden kann:

<div class="intro-wrap">
  <?php echo wp_kses_post( wpautop( pll__( get_theme_mod( 'header_intro' ) ) ) ); ?>
</div><!-- end .intro-wrap -->

Nun kann der Text übersetzt werden, wenn eine solche Übersetzung für die aktuelle Sprache exisiert. Aber wie genau funktioniert die eigentliche Übersetzung der Option?

Texte für die Übersetzung registrieren

Damit man einen Text überhaupt erst übersetzen kann, muss man Polylang mitteilen, dass es ihn gibt. Hierzu wird die Funktion pll_register_string der Polylang API verwendet. In die function.php Datei fügt man einfach folgene Zeilen ein:

if ( function_exists( 'pll_register_string' ) ) :
	/**
	 * Register some string from the customizer to be translated with Polylang
	 */
	function child_theme_name_pll_register_string() {
		pll_register_string( 'header_intro', get_theme_mod( 'header_intro' ), 'child-theme-name', true );
	}

	add_action( 'after_setup_theme', 'child_theme_name_pll_register_string' );
endif;

Zuerst wird überprüft, ob die Funktion existiert, da es ansonsten zu einem Fatal Error kommen würde, sobald Polylang deaktiviert wird. Anschließend wird eine Callback-Funktion registiert, in der die Funktion zur Registrierung von Texten verwendet wird. Der erste Parameter ist hierbei lediglich ein Name zur Sortieung der übersetzbaren Strings. Der zweite Parameter ist der eigentliche Text, der übersetzt werden soll. In diesem Fall ist es der dynamische Wert der Customizer Option. Der dritte Parameter definiert eine Gruppe für der String und der letzte besagt, dass es sich bei der Text um einen mehrzeiligen Text handelt. Somit wird bei der Übersetzung im Backend eine Textarea und kein einzeiliges Textfeld verwendet.

Den Text übersetzen

Alle reigistrierten Strings befinden sich unter „Sprachen -> Übersetzungen von Zeichenketten“ im Backend. Hier steht in einer Tabelle in der ersten Spalte der aktuelle Wert aus dem Customizer und in der letzten Spalte kann dieser Text dann pro Sprache übersetzt werden. Hierbei ist zu beachten, dass bei jeder Änderung des Wertes in der Customizer Option auch die Übersetztung neu vorgenommen werden muss, da ansonten der unübersetzte Wert in allen Sprachen verwendet wird.

Fazit

Es ust auch mit Polylang möglich, die verschiedenen Optionen des Customizers pro Sprache anzupassen. Hierzu muss aber in den meisten Fällen ein Child Theme erstellt werden. Die Übersetzung von Optionen eines Plugins können schon viel schwieriger werden, da man hier nicht einfach ein „Child Plugin“ erstellen kann. Dabei ist man dann meistens auf Filter angewiesen, die das Plugin dann hoffentlich anbietet, um Texte anzupassen. Das ist auch ein weiterer Grund, wieso ich bei mehrsprachigen Seiten eher zu einer Multisitelösung tendiere.

Bonustipp

Da Polylang ein noch eher neues Plugin ist, sehr viel neues als WPML (das ich in der Regel nicht nutze), unterstützt es das sogenannten WPML language configuration file wpml-config.xml, was einem ein bisschen Arbeit erspart. Wenn also das Theme sagt, dass es „WPML ready“ ist und eine solche Datei mitliefert, können eventuell einige der Schritte übersprungen werden, die ich in diesem Beitrag gezeigt habe,

Global WordPress Translation Day 3

Am Samstag den 30. September fand der dritte Global WordPress Translation Day rund um den Globus statt. Ab Mitternacht UTC gab es ein 24h Programm mit insgesamt 22 Päsentationen.

Lokale Events

Wie schon bei den ersten WP Translation Days gab es viele lokale Events. Beim zweiten waren es noch 38, dieses mal mit 71 fast doppelt so viele (vielleich sogar mehr, die nicht offiziell angekündigt waren), davon sechs in Deutschland:

Weiterlesen →

Schlagwörter von privaten Beiträgen in der Tag-Cloud anzeigen

Keine Angst, an den letzten Wochenenden gab es mal kein WordCamp und daher gibt es heute mal wieder einen normalen Beitrag 😉 Vorletzte Woche gab es an einem Kundenprojekt eine interessante Anfrage. Die WordPress Website hatte einen FAQ-Bereich und manche Fragen waren auf privat gesetzt. Die Website hat außerdeme eine Tag-Cloud eingesetzt, um es den Besuchern zu erleichtern, passende Fragen zu finden. Aber selbst, wenn sich die Nutzer angemeldet haben, konnten sie keine Schlagwörter in der Tag-Cloud sehen, die lediglich in privaten Fragen verwendet wurden.

Wie werden die Schlagwörter in der Tag-Cloud erzeugt?

Wenn in WordPress der HTML-Code für die Schlagwörter-Wolke erzeugt wird, dann werden nur eine begrenzte Anzahl an Schlagwörtern ausgelesen. Aber wie genau wird diese Auswahl berechnet? Man würde vermuten, dass hierzu eine Datenbank-Abfrage gestartet wird, die nach der Häufigkeit des verwendeten Schlagwortes gruppiert und die IDs zurückliefert, die am meisten verwendet wurden. Aber so funktioniert es nicht in WordPress. Aus Geschwindigkeitsgründen wird die Anzahl der Nutzung eines Schlagwortes statisch in einer Spalte in der Datenbanktabelle gespeichert. Aber wieso sind dann private Beiträge in der Tag-Cloud nicht sichtbar? Das liegt daran, dass sobald man die Sichtbarkeit eines Beitrags auf privat stellt, dieser Beitrag nicht mehr mitgezählt wird, wenn es um die Ermittlung der Gesamtanzahl geht. Nur öffentliche Beiträge werden hierbei beachtet. Es gibt also leider keinen einfachen Lösungsweg über einen Filter oder eine Action, um auch private Beiträge anzuzeigen. Aber wie können wir das Problem lösen?

Die Datenbankabfrage anpassen

Fadst jede Datenbankabfrage, die „eine Liste“ erzeugt wird in WordPress durch die Klasse WP_Query umgesetzt. Für die Tag-Cloud ist es genau genommen die Klasse WP_Term_Query, die aber sehr ähnlich funktioniert. Wir müssen also lediglich die Abfrage ändern, die hierbei ausgeführt wird. Aber wie stellen wir fest, dass es sich bei der aktuellen Abfrage um die Tag-Cloud handelt und nicht im eine andere Abfrage auf Taxonomien? Es gibt leider keinen Conditional-Tag is_tag_cloud() oder ähnliches.

Im Grunde ist es recht einfach. Bei der Erstellung der Schlagwörter-Wolke werden zwei Argumente eingesetzt, die nur hier vorkommen: largest und smallest. Diese beiden Werte geben an, welches die größte bzw. kleinste Schriftgröße ist, die in der Tag-Cloud verwendet werden soll. Wir können also einfach prüfen, ob einer dieser beiden Argumente vorhanden ist und wissen dann, dass es sich bei der aktuellen WP_Term_Query um die Abfrage für die Tag-Cloud handelt. Der Rest ist eigentlich recht einfach. Wir müssen nur den term_clause Filter verwenden, um die SQL-Abfrage entsprechend anzupassen:

function private_posts_in_tc_terms_clauses( $pieces, $taxonomies, $args ) {
	if ( isset( $args['largest'] ) && is_user_logged_in() ) {
		// Count by the grouped term_id.
		$pieces['fields'] .= ', COUNT(t.term_id) AS grouped_count';
		// Join the relationship to the posts.
		$pieces['join'] .= ' INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id';
		// Remove the "redundant" count (only for public posts).
		$pieces['where'] = str_replace( 'AND tt.count > 0', '', $pieces['where'] );
		// Group by the term_id to remove duplicates and calculate the count.
		$pieces['where'] .= ' GROUP BY tt.term_id HAVING grouped_count &gt; 0';
	}
	
	return $pieces;
}
add_filter( 'terms_clauses', 'private_posts_in_tc_terms_clauses', 10, 3 );

Bevor wir die Abfrage anpassen, müssen wir natürlich noch sicherstellen, dass der aktuelle Nutzer auch angemeldet ist und die privaten Schlagwörter auch sehen darf. In der veränderten Abfrage machen wir dann einen JOIN auf die term_relationship Tabelle und gruppieren anhand der Term-ID. Hierdurch können wir dann mit SQL sehr einfach die Anzahl inklusive der privaten Beiträge berechnen. Die Abfrage selbst ist natürlich etwas langsamer als die Originalabfrage, da sie keine zwischengespeicherten Werte aus der Tabelle verwendet. Aber da ohnehin jede WP_Term_Query in einem Transient zwischengespeichert wird, ist die Performance-Einbuße nicht wirklicht groß.

Fazit

Es ist nicht immer ganz so einfach, dass man nur den richtigen Hook finden muss, um eine Query in WordPress zu ändern. Aber normalerweise gibt es fast immer einen Weg, das gewünschte Ergebnis zu erreichen. Wenn ihr diese Funktion auch mal ausprobieren wollt, dann findet ihr den Code dazu wie immer in einem GIST. Hier könnt ihr euch auch wieder alles als ZIP-Datei runterladen und einfach als Plugin auf eurer Seite installieren.