toscho.design

Plugin Review: Gridster

Gridster ist ein WordPress-Plugin von Carsten Bach (@carstenbach).

Die Nutzer können damit Auszüge aus allen vorhandenen Posttypen als Widgets in einem Raster anordnen, und diese Anordnung später per Shortcode in einer beliebigen Seite einbinden.

In diesem Review habe ich Version 1.4 getestet. Kleine Fehler übergehe ich hier; die sind bei einem Plugin dieser Komplexität unvermeidlich und sicher bald repariert. Mich interessieren hier eher konzeptionelle Details, die man als Autor oft nicht so leicht sieht, wenn man zu dicht am eigenen Code steht.

Fehler melden kann man auf GitHub, denn dort liegt die Arbeitsversion. Das ist auch schon der erste Pluspunkt: ein öffentliches Repository mit einem Bugtracker ist sehr wichtig, wenn man Feedback von Entwicklern haben möchte.

$ git clone git://github.com/carstingaxion/cbach-wp-gridster.git
$ git checkout -b review270413

Backend

Es gibt drei Seiten: eine für allgemeine Einstellungen, eine Übersicht bereits angelegter Gridster und eine zum Erstellen und Bearbeiten eines Gridsters.

Allgemeine Einstellungen

Gridstereinstellungen

Die Optionsseite wird ordentlich aus der Pluginliste heraus verlinkt, so findet man sie leicht.

Auf den Reiter hätte ich verzichtet, es gibt ja nur einen.

Die Maßangaben sind vermutlich für die Einheit Pixel gedacht – das sollte dort auch stehen, denn viele moderne Layout setzen eher auf em. Ich hätte hier auch type="number" für die Eingabefelder verwendet. Damit geht bei Mobilgeräten gleich das passende Tastaturlayout auf.

Die Validierung der Werte ist mir nicht pingelig genug: Man kann eine negative Zahl der Standardspalten festlegen oder die Widgethöhe auf -15e0 setzen. Die Widget-Basis-Breite kann man breiter setzen als die globale Variable $content_width. Hier fehlen genauere Prüfungen und bessere Voreinstellungen.

Gridster erstellen und bearbeiten

Carsten hat Gridster als separaten Posttypen angelegt – sicher die beste Option, denn so bekommt man an vielen Stellen ein vorgefertigtes Interface, das sich gut in WordPress einfügt und doch nicht zu sehr bindet.

Gridster bearbeiten

Sehr gut: $content_width, die vom Theme vorgegebene Breite, wird mit einer roten Linie dargestellt. Aber die einzelnen Boxen schnappen dort nicht ein; man kann sie auch nicht manuell auf Kante setzen.
Das Layout sieht nach dem Speichern nicht immer so aus wie davor, denn dann wird es auf die Maximalbreite heruntergezogen. Das ist sinnvoll, sollte aber schon im Erstellungsprozess passieren.

Die Boxen für Seiten und Custom-Post-Types sind immer geschlossen; auch das manuelle Öffnen wird nicht gespeichert. Gibt es in einem Posttypen keine Einträge, sollte die Box entweder gar nicht auftauchen, oder einen Link anbieten, um einen neuen Eintrag dort zu erstellen. Und man braucht keine Suchbox, wenn weniger als zwei Einträge in einem Posttypen existieren – die Suche finde ich ansonsten sehr gelungen.

Die Seiten, die man sich als statische Startseite und Blogseite eingestellt hat, sollten nicht verfügbar sein. Ich kann mir keine Situation vorstellen, in der es sinnvoll wäre, sie hier wiederzuverwenden.

Hilfreich wäre eventuell ein nicht-öffentlicher Hilfsposttyp für freie Texte, die nur im Grid auftauchen und nicht verlinkt werden. Und gäbe es eine Gridvorlage, die der Administrator festlegt, damit die Redakteure sie bloß befüllen aber nicht ändern können, so ließen sich damit sicher einige der Bedenken auflösen, die ich bei einem so starken Einfluss der Redakteure aufs Layout habe.

Wenn man einen Gridster zum Verwenden freigibt, so heißt der Button dafür Publish (im Deutschen Veröffentlichen). Ich bin mir nicht sicher, ob das so gut passt; schließlich wird er ja nicht direkt veröffentlicht. Finish (Fertigstellen) würde vielleicht besser passen.

Ein Link zu den allgemeinen Einstellungen wäre hier nicht schlecht.

Mein allgemeiner Eindruck: Schönes Beispiel dafür, was man aus dem Posteditor machen kann, viele gute Ideen und Ansätze. Das Konzept stimmt, ein paar Details brauchen noch Feinschliff.

Liste vorhandener Gridster

Gridsterliste

Dazu habe ich nicht viel zu sagen. Die Shortcodes in der Liste finde ich sehr handlich. Beim Fokussieren so eines Feldes wir der Shortcode auch gleich markiert – das spart einen Tastengriff. Prima.

Frontend

Die Ausgabe entspricht in der Einzelansicht der Ansicht im Backend. Keine Überraschungen.

Nur erzeugt Gridster aus dem Titel des Grids ein id-Attribut ohne Präfix. Das kann dazu führen, dass man plötzlich zweimal die gleiche ID im Dokument hat, beispielsweise wenn man den Titel Container verwendet und es im Theme eine ID container gibt. Hier sollten also alle Klassen und IDs mit einem Präfix versehen werden, um dieses Risiko zu verringern.

Die title-Attribute bei den Links sollten verschwinden. Sie duplizieren nur den Linktext und nützen niemandem.

Änderungen der Permalinks werden in den Widgets nicht berücksichtigt. Das muss repariert werden.

Schwierig finde ich den Einsatz absoluter Positionierung. Das verträgt sich kaum mit flexiblen Layouts. Flexboxen oder display:table mit Mediaqueries wären hier sicher kompatibler.

Diese Ausgabe ist vermutlich der Punkt, anhand dessen die meisten Anwender das Plugin beurteilen werden. Hier könnte man auch andere Wege gehen, vielleicht auch mehrere zur Auswahl anbieten. Der nächste Reiter für die Optionsseite?

Der Code

Gridstercodestruktur

Auf den ersten Blick sieht die Verzeichnisstruktur schön übersichtlich aus: Es gibt jeweils ein Verzeichnis für Bilder, CSS, JavaScript und Sprachdateien. Aber keins für PHP. Der Grund: Alles wird in einem Gottobjekt erledigt, das wir in der Hauptdatei finden.

So etwas kann man während des Prototypings machen oder wenn man nur sieben oder acht Funktionen braucht, die auf die gleichen Variablen zugreifen müssen. Aber hier haben wir 61 Methoden und einen Konstruktor. Als potentieller Contributor würde ich hier auf das unvermeidliche Refactoring warten, nach dem jede Klasse hoffentlich nur noch eine Aufgabe erledigt.

Im Docblock jeder Methode sollte stehen, bei welchem Hook sie aufgerufen wird. Ich mache das meistens so:

/**
 * Flush rules for custom post types.
 *
 * @wp-hook registered_post_type
 * @param   string $post_type
 * @param   stdClass $args
 * @return  void
 */
function t5_silent_flush_cpt( $post_type, $args )
{
}

Das erspart dem Leser viel Scrollen und Suchen.

Die folgenden Notizen habe ich beim Durchscrollen lose gesammelt; den genauen Arbeitsablauf des Plugins kann ich im Moment schwer beurteilen.

Die Einrückungen sind ein Gemisch aus Tabs und Leerzeichen; das erschwert das Lesen ohne Not. Faustregel: führende Einrückungen mit Tabs, zwischen sichtbaren Zeichen nur Leerzeichen. Und Leerzeichen am Zeilenende müssen ganz weg.

&$this ist eine Krücke aus der Zeit vor PHP 5. Es sollte nicht mehr verwendet werden.

Das Stylesheet fürs Backend wird auf allen Seiten geladen, selbst im Dashboard. Bei den JavaScripten hingegen gibt es erst eine ordentliche Bedarfskontrolle.

JavaScripte und Stylesheets liegen jeweils in einer komprimierten Variante vor und in einer lesbaren mit Dokumentation. Sehr gut. jQuery 1.7.2 (oder jede andere Version) hat aber in einem Plugin nichts verloren. Man ersetzt ohnehin niemals das eingebaute jQuery.

Die Instanz der Klasse wird einfach dann erzeugt, wenn das Plugin geladen wurde. Nicht gut, denn so kann man das kaum gezielt abschalten. Besser wartet man entweder bis plugins_loaded oder noch länger, beispielsweise bis wp_loaded.

Bei jedem Aufruf prüft das Plugin, ob die PHP- und die WordPress-Version noch passt. Zeitverschwendung, da genügt die Kontrolle auf der Pluginseite.

Es gibt einen Uninstall-Handler. Das ist gut. Er rennt durch alle Posts des plugineigenen Posttypen. Das ist riskant. Wenn zu viele existieren, bricht die Deinstallation mit einem häßlichen Fehler ab; vielleicht ruiniert man sogar die Integrität der Datenbank. Betrachte 'posts_per_page'=> -1 immer als dringend zu behebenden Bug; zähle die vorhandenen Einträge, bevor du sie löschst.

Mir gefällt der durchgehende Einsatz der Funktion esc_attr(). Das ist leider noch nicht überall Standard.

settings_errors() wird im Code aufgerufen. Das ist nicht gut: Diese Funktion wird normalerweise von WordPress selbst aufgerufen, wenn Fehler registriert wurden. Hier führt der Aufruf dazu, dass an vielen Stellen im Backend Hinweise doppelt angezeigt werden, auch wenn sie mit dem Plugin gar nichts zu tun haben.

Das Laden des Pluginstylesheets im Frontend verhindert man im Theme mit einer zusätzlichen Konstante:

define( 'GRIDSTER_FRONTEND_CSS', false );

Gut finde ich, dass Carsten daran überhaupt gedacht hat. Allerdings bietet WordPress für genau solche Fälle eine kleine API an: add_theme_support( $feature ) und get_theme_support( $feature ). Damit bliebe auch der globale Namensraum ein bißchen sauberer.

Im Shortcode-Handler gibt es zwei Aktionen:

do_action( 'gridster_before_shortcode_render', $id, $title, $widgets );
do_action( 'gridster_after_shortcode_render', $id, $title, $widgets );

Zwar finde ich zusätzliche Aktionen oft sehr nützlich, aber in einem Shortcode darf man ja keine Ausgabe erzeugen, daher wären hier Filter sicher besser. Deren Ausgabe könnte dann dem Shortcode hinzugefügt werden.

Insgesamt wirkt der Code auf mich wie: Es läuft, also erstmal raus damit. Prinzipiell richtig, aber ästhetisch nicht sehr befriedigend. Wer man eine API anbietet, sollte ein wenig strenger mit sich sein.

Fazit

Ich habe im Interface viel Liebe zum Detail gefunden; einige Ideen werde ich mir sicher abgucken. Die Umsetzung finde ich im Großen recht gelungen, das Konzept sehr originell. Der Code sollte einem Refactoring unterzogen werden, ehe dabei zu viel Rücksicht auf existierende Themes genommen werden muss.

In eigenen Projekten würde ich das Plugin derzeit vermutlich nicht einsetzen. Redakteure dürfen bei mir nicht am Layout herumspielen. Ich kann mir aber Situationen vorstellen, in denen das anders gehandhabt wird.

3 Kommentare

  1. Torsten am 03.05.2013 · 14:42

    Spannender Einblick. Auch beim Review eines fremden Plugins kann man viel lernen.

  2. Birgit Engelhardt am 07.05.2013 · 10:36

    Grad mal nach Testberichten zum Plugin gegooglet und gleich hier reingestolpert. Eine ausführliche Betrachtung, vielen Dank! Ganz verstanden hab ich nur nicht, was beim Klicken auf ein Grid-Bestandteil passiert. Geht eine neue Seite auf, eine Lightbox, oder kann ich das frei einstellen?

  3. Thomas Scholz am 08.05.2013 · 01:09

    @Birgit Engelhardt: Bei einem Klick gelangt man auf die Seite, die von der Box repräsentiert wird. Man bleibt im selben Tab, und es gibt auch keine Lightbox.
    Das gefällt mir so eigentlich auch am besten. Für mich als Tastaturntzer sind Lightboxen oft schwierig zu bedienen, und neue Fenster … möchte man ohnehin nicht.