Mit den WordPressboardmitteln, etwas php-gefuddel und einem JQuery-Plugin lassen sich ziemlich nette Statistikgrafiken erzeugen.

visualize

Die Seite mit den Monatsarchiven war mir schon länger ein Dorn im Auge, irgendwie war die Liste mit Monatsnamen und der Anzahl der Artikel zwar funktional, aber doch ziemlich, hm, langweilig.

Ich wollte schon länger mal was mit dem jQuery Plugin "Visualize" ausprobieren, da ich das bei einem Job gebrauchen könnte ... was bietet sich besser an, als das eigene Blog, in dem man hemmungslos rumfrickeln und kaputtmachen kann, ohne das es etwas anderes als das eigene Ego ankratzt?

Aufgabe: Ich möchte am Ende eine Infografik auf der Seite sehen, in der man die Entwicklung der Beitragsanzahl im Laufe der Monate sehen kann.

Diese Informationen stecken offenbar schon in der Liste, die das Monatsarchiv ausgibt. Monatsname, Jahr und Anzahl der Artikel werden in der Form "Monatsname Jahreszahl (n)" von wp_get_archives() ausgegeben. Je nachdem, welche Parameter man der Funktion mit auf den Weg gibt, sieht die Ausgabe leicht anders aus, ausserdem kann man die Ausgabe auch als Wert für weiter php-Scriptverarbeitung zurückgeben, statt sie auf der Seite ausgeben zu lassen. Das klingt doch schon recht vielversprechend.

Das Visualize-Plugin braucht als Grundlage zur dynamischen Erstellung der Grafik eine saubere HTML-Tabelle. Hmmm. Das könnte tricky werden, da die Ausgabe der Archivfunktion erst einmal alles in einem einzigen Schwung, in einem String, zurück gibt - inklusive der HTML-Linkformatierung.

Die erste Hürde ist also, WordPress dazu zu bringen, eine einfache HTML-Tabelle dort auszugeben, wo eigentlich eine Linkliste stünde. Dazu wird die wp_get_archive() Funktion so aufgerufen, dass sie

  • die Werte nicht auf der Seite ausgibt, sondern für weitere Script verarbeitung "return"t (echo=0)
  • keine Listenformatierung macht, sondern nur den Text mit Link und Zahl zurückgibt (format=custom&before=&after=)
$data = wp_get_archives('type=monthly&show_post_count=1&format=custom&before=&after=&echo=0);

Lässt man sich die so gefüllte $data-Variable ausgeben, sieht man

<a href="...">August 2009</a>&nbsp;(13)
<a href="...">Juli 2009</a>&nbsp;(39)
<a href="...">Juni 2009</a>&nbsp;(21)
(...)

(Die Linkadressen habe ich mal rausgelassen).
Aha. Anscheinend werden also die einzelnen Einträge in eine eigene Zeile geschrieben, und zwischen dem verlinkten Text und der darauf folgenden Zahl steht immer ein "&nbsp;", ein geschütztes Leerzeichen.

Die Verlinkung brauche ich nicht für meine Grafikgrundlagentabelle, also lasse ich die php-Funktion "strip_tags()" auf den String los:

$data = strip_tags($data);

Kurze Kontrolle mit "print_r($data)" ergibt:

August 2009&nbsp;(13)
Juli 2009&nbsp;(39)
Juni 2009&nbsp;(21)
(...)

Super, die Verlinkung ist schon mal raus aus dem String.
Da ich später, um die einzelnen Tabellenzeilen zu füllen, an die einzelnen Elemente "Datum" und "Anzahl" rankommen will, muss ich zunächst mal diesen kompletten String mit allen Einträgen drin in ein Array verwandeln. Da die einzelnen Zeilen den einzelnen Einträgen entsprechen, kann ich den String am Zeilenumbruch aufteilen und so die einzelnen Brocken in das Array schubsen:

$data = explode('\n',$data);

Kurz nachgeschaut mit print_r($data):

Array(
	[0] => "August 2009&nbsp;(13)",
	[1] => "Juli 2009&nbsp;(39)",
	[2] => "Juni 2009&nbsp;(21)"
)

Tschaka, jetzt kann der eigentlich spannende Teil folgen: Anhand des "&nbsp;" kann jetzt jede einzelne Zeile, also jeder Eintrag im Array, erneut "exploded" werden, danach erhalte ich ein mehrdimensionales Array, in dem jeweils das Datum und die Anzahl in eigenen Werten stehen; schön gruppiert nach den Zeilen.
Das klingt ja fast schon wie eine Tabelle, und richtig, man muss nur noch dieses Array entsprechend durchnudeln und das HTML-Tabellen-Markup dazu bauen:

$out = '<table>';
$out .= '<caption>Titel der Grafik</caption>';
$out .= '<tr><td></td><th>Artikelanzahl</th></tr>';
for ($i = 0; $i < count($data); $i++) {
	$data[$i] = explode('&nbsp;',$data[$i]);
	$out .= '<tr><th>'. trim($data[$i][0]) . '</th>';
	$out .= '<td>'. trim($data[$i][1]) . '</td>< /tr>';
}
$out .= '</table>';
echo $out;

Ha, fast. In der Spalte mit den Artikelzahlen stehrt jetzt noch "(13)", also in Klammern, damit kann das Visualize-Plugin nix anfangen, da muss eine nackte Zahl rein. Ausserdem sollte man der Tabelle eine CSS-ID oder -Klasse geben, damit jQuery/Visualize später weiss, wo es anpacken darf:

$out = '<table id="poststats">';
$out .= '<caption>Titel der Grafik</caption>';
$out .= '<tr><td></td><th>Artikelanzahl</th></tr>';
for ($i = 0; $i < count($data); $i++) {
	$data[$i] = explode('&nbsp;',$data[$i]);
	$out .= '<tr><th>'. trim($data[$i][0]) . '</th>';
	$data[$i][1] = str_replace(array('(',')','',$data[$i][1]));
	$out .= '<td>'. trim($data[$i][1]) . '</td>< /tr>';
}
$out .= '</table>';
echo $out;

So, jetzt nur noch die Reihenfolge des initalen Arrays umdrehen, da in der Grafik ja von links nach rechts die Historie entsprechnend der Leserichtung stehen soll - im Moment wäre aber der neueste Eintrag der erste, also genau andersrum. Ausserdem enthält das Array am Ende einen leeren Eintrag, der durch den letzten Zeilenumbruch beim ersten explode() hinzugefügt wurde. Wird das Array umgedreht, ist dieser leere Eintrag der Erste, deshalb lasse ich die for-Schleife nicht bei "0", sondern bei "1" starten - und weg ist er:

$data = wp_get_archives('type=monthly&show_post_count=1&format=custom&before=&after=&echo=0');
$data = strip_tags($data);
$data = explode('\n',$data);
$data = array_reverse($data);
 
$out = '<table id="poststats">';
$out .= '<caption>Titel der Grafik</caption>';
$out .= '<tr><td></td><th>Artikelanzahl</th></tr>';
for ($i = 1; $i < count($data); $i++) {
	$data[$i] = explode('&nbsp;',$data[$i]);
	$out .= '<tr><th>'. trim($data[$i][0]) . '</th>';
	$data[$i][1] = str_replace(array('(',')','',$data[$i][1]));
	$out .= '<td>'. trim($data[$i][1]) . '</td>< /tr>';
}
$out .= '</table>';
echo $out;

Und Bingo, jetzt erscheint auf der Seite eine einfache Tabelle, die man mit dem Visualize Plugin in eine Grafik verwandeln kann, indem man in Javascript mittels jQuery('#poststats').visualize(); aufruft. '#poststats' muss mit der CSS-Klasse oder der ID übereinstimmen, die man im Tabellen-Markup angegeben hat.

Ich habe auf meiner Archivseite noch weiter mit den Häppchen im Array rumgespielt, weil die Monatsnamen und Jahreszahlen zu lang waren, um sie vernünftig unter der Grafik dargestellt zu bekommen. Der Übersicht halber habe ich das aber aus den Beispielen hier rausgelassen :-)

Damit am Ende alles funktioniert, müssen die Scripte des visualize-Plugins auf dem Server geladen und in den Blog-Header oder -Footer eingebunden werden. Damit die Template-Datei, auf der das Archiv erscheint, übersichtlich bleibt, empfiehlt es sich, den php-Kram in eine eigene Funktion zu schreiben, und diese in die functions.php des Themes zu packen und im Template nur noch die Funtion aufzurufen. Vielleicht schreibe ich dazu noch mal einen Beitrag.

Update 24.8.2010

In dem Codeabschnitt, wo die Klammern um die Ziffer rausfliegen, kann man noch ein wenig optimieren: Statt der str_replace() Funktion bietet sich hier trim() an, vorausgesetzt, man benutzt php5; denn dann kann man beliebige Zeichen angeben, die am Anfang und Ende des Strings entfernt werden - was ja genau das ist, was hier geschehen soll:

(...)
$data[$i][1] = trim($data[$i][1], '()' );
(...)