WP-Standard-Widgets pimpen

Vor einiger Zeit hatte ich einen Hack vorgestellt, mit dem man schnell mal das Link-Widget von der Startseite verschwinden lassen kann. Dabei spielten erst einmal nur mein persönlicher Geschmack und eine ordentliche Portion Neugier eine entscheidende Rolle. So eine Lösung ist keinesfalls schön und für komplexere Probleme auch nicht sehr empfehlenswert.

An der Stelle sollte vielleicht noch einmal kurz herausgearbeitet werden, was Widgets eigentlich sind. Im Netz geistern ja die verschiedensten Erklärungen herum. Das geht soweit, dass behauptet wird, Widgets würden etwas sein, was sich als eine Art Zwitter zwischen Theme und Plugin befindet. Das stimmt so nicht!

Natürlich haben Widgets die Bestimmung in einem Frontend dargestellt zu werden, was sie aber nicht zwangsweise zum Teil des WordPress-Themes werden lässt. Schließlich werden die verfügbaren Widgets im Backend unter Design > Widgets gesteuert und stehen, falls sich ihr Code nicht in der functions.php des Themes befindet, auch noch nach einem Designwechsel zur Disposition.

Zudem ist es einem Widget auch herzlich egal, ob sich sein Code in den Wodpress-Core-Dateien, in der functions.php des Themes oder in einem Plugin befindet. Wichtig ist lediglich, dass es sich an die vorgegebenen Regeln, sprich an die Widget-API hält. Ich persönlich finde den Begriff API hierbei etwas unglücklich gewählt.

Im weitesten Sinne kann man wohl von einem Framework sprechen. Um es noch greifbarer auszudrücken, die Widget-API mit den Standard-Widgets ist eine Sammlung von Klassen. Alle Widgets müssen die WP_Widget-Klasse erweitern und einige wenige Methoden implementieren, um sich regelgerecht in das Rahmenwerk einzufügen.

An dieser Stelle muss man sich zurecht die Frage stellen, ob man nicht einfach die Standard-Widgets erweitern kann, um selbst zu bestimmen, wann sie in einer der definierten dynamischen Sidebars auftauchen oder nicht. Das ist tatsächlich nicht nur möglich, sondern sogar recht simpel einzurichten.

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
 </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>
  <p>The requested URL <code>/svn/trunk/examples/MY_Widget_Links.php</code> was not found on this server.  <ins>That’s all we know.</ins>

Der Code lässt sich in der functions.php oder in einem Plugin leicht unterbringen und ist auch schnell erklärt:

Die Klasse MY_Widget_Links erweitert das Standard-Widget, welches sich um die Darstellung der Blogroll kümmert. Die Methode widget, welche die Ausgabe übernimmt, stellt über Conditional-Tags fest, dass es sich nicht um die Startseite handelt und ruft die Methode der Eltern-Klasse auf. Danach wird über eine Funktion, die beim Initialisieren der Widgets getriggert wird, das Standard-Widget deaktiviert und das modifizierte Widget registriert.

Have fun!

Das Link-Widget auf der Startseite deaktivieren

In den letzten Tagen hatte ich viel mit WordPress 3.0 getestet und bin dabei oft tiefer in die Sourcen gestiegen, als mir letztlich lieb gewesen wäre. Ich arbeite gern mit WP und sehe da auch weiterhin viel Potenzial für meine Kunden. Aber manche Erkenntnisse hätte ich lieber nicht gewonnen. Ich bin nunmehr fest davon überzeugt, dass das Aktivieren von einigen Features dem Anwender überlassen werden sollte. Um nur ein Beispiel zu nennen: WordPress verfügt über einen Filter, der dafür sorgt, dass man WordPress „richtig“ (mit einem großen P) schreibt.

Aber Filter und Actions sind nicht die einzigen Dinge, die standardmäßig aktiviert werden, um dann vom Benutzer wieder deaktiviert zu werden. Bei den Widgets gibt es auch einige Kandidaten, deren Existenzberechtigung weiterhin eher zweifelhaft bleibt. Auch hier kann man nacharbeiten, um gezielt Standard-Widgets zu deaktivieren. Ich habe mir noch nicht so genau angesehen, zu welchem Zeitpunkt genau deren Aktivierung erfolgt. Allerdings frage ich mich ernsthaft, warum es nicht standardmäßig Optionen gibt, die dieses Verhalten steuern.

Die WordPress-Options werden doch zu einem großen Teil sowieso global verfügbar gemacht. Warum also werden keine Abfragen gebaut, die sicherstellen, dass keine unerwünschten Filter, Actions und Widgets aktiviert werden? Die einzusparende Rechenzeit ist bei einigen Websites sicher nicht unerheblich. Dazu kommt noch, dass man einige dieser Widgets – so Klasse das Konzept der WordPress-Widgets auch ist – „out-of-the-box“ nicht wirklich flexibel verwenden kann.

Auf der Suche nach der Lösung meines Problem mit WPML und den Widgets bin ich beispielsweise auf das  LinkTranslationWidget gestoßen. Aber meine spontane Idee, zwei Sidebars einzurichten, finde ich immer noch ziemlich in Ordnung und an sich war ja nur noch eine Lösung dafür zu finden, wie man das Link-Widget auf der Startseite entfernt, während es auf den anderen Seiten seine Aufgabe ganz normal erfüllen soll. Einen weiteren Anhaltspunkt für eine mögliche Lösung ergab sich beim Lesen von Disable wordpress sidebars without editing template.

Allerdings wollte ich ja nur ein Widget ausschließen. Interessant war die gebotene Möglichkeit aber allemal, sodass ich mir erst einmal angesehen habe, welche Daten mir der Filter zur Verfügung stellt. Letztlich handelt es sich nur ein mehrdimensionales Array, dass recht überschaubare Informationen zu den Sidebars und den eingesetzten Widgets enthält. Abgelegt ist hier jeweils eine Art ID, die aus dem registrierten Namen, einem Minuszeichen und einer Zahl besteht, wahrscheinlich um mehrere Instanzen eines Widgets zuzulassen.

Das bringt mich dann auf folgende Lösung, die auch wieder einfach in der functions.php oder einem Custom Plugin eingebaut werden kann:

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
 </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>
  <p>The requested URL <code>/svn/trunk/examples/my_disable_widget.php</code> was not found on this server.  <ins>That’s all we know.</ins>

In der Callback-Funktion für array_filter hatte ich ursprünglich preg_match verwendet. Allerdings ist strpos meist die bessere Wahl, wenn es um Geschwindigkeit geht, wovon man sich auch bei diesem Vergleich überzeugen kann.

Have fun!