Tag Cloud ohne Inline-Styles in WordPress

Lange habe ich nach einer Möglichkeit gesucht, die Tag Cloud von WordPress ohne Inline-Styles zu gestalten. Die angezeigten Fehler beim W3C Validierungsdienst waren mir doch ein großes Dorn im Auge. Also habe ich etwas rumprobiert und mir schließlich meine eigene Funktion geschrieben, die ich in die functions.php meines Themes integriert habe. Jetzt hat meine Tag Cloud endlich keine Inline-Styles mehr, nur noch Klassen. Per CSS kann ich so die Schriftgröße der Tags anpassen.

Tag Cloud Filter: wp_generate_tag_cloud

Grundlage meine Funktion ist der WordPress-eigene Filter wp_generate_tag_cloud. Der gibt einen HTML-String zurück aus dem die Tag Cloud gebildet wird. In diesem String suche ich nun per Regular Expression nach den class=““ und style=““ Abschnitten. Die class-Abschnitte ignoriere ich, da diese ja rausfallen bzw. ersetzt werden sollen. Von den style-Abschnitten behalte ich mir die Zahl, die die Schriftgröße angibt, da ich diese noch weiter verwende. Um mehr Flexibilität zu haben, benutze ich dafür schließlich die PHP-Funktion preg_replace_callback, da ich so auf eine weitere Funktion zurückgreife in der ich meine Ersetzung weiter definieren kann. Am Ende sah das Konstrukt dann so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
add_filter('wp_generate_tag_cloud', 'my_tag_cloud_widget', 10, 3);
function my_tag_cloud_widget($tag_string) {
    $suchen = array(
        '#class=\'tag-link-(.*)\'#U',
        '#style=\'font-size: (.*)pt;\'#U'
    );
    return preg_replace_callback($suchen, 'replace_tags', $tag_string);
}
function replace_tags($hit) {
    if( strpos($hit[0], 'style') !== false ) {
        if($hit[1] >= '8' && $hit[1] <= '22') {
            if(strpos($hit[1], '.') !== false) {
                $str = strstr($hit[1], '.', true);
            } else {
                $str = $hit[1];
            }
            $font = 'class="tag-link-'.$str.'"';
            return $font;
        }
    }
}
add_filter('wp_generate_tag_cloud', 'my_tag_cloud_widget', 10, 3);
function my_tag_cloud_widget($tag_string) {
    $suchen = array(
        '#class=\'tag-link-(.*)\'#U',
        '#style=\'font-size: (.*)pt;\'#U'
    );
    return preg_replace_callback($suchen, 'replace_tags', $tag_string);
}
function replace_tags($hit) {
    if( strpos($hit[0], 'style') !== false ) {
        if($hit[1] >= '8' && $hit[1] <= '22') {
            if(strpos($hit[1], '.') !== false) {
                $str = strstr($hit[1], '.', true);
            } else {
                $str = $hit[1];
            }
            $font = 'class="tag-link-'.$str.'"';
            return $font;
        }
    }
}

In der zweiten Funktion wird der Parameter $hit übergeben. Dieser beinhaltet ein Array des gefundenen Elements (des zuvor angegebenen Patterns). Das wird für jedes Element einzeln gemacht, wenn ich es also per var_dump($hit) ausgebe, bekomme ich ganz viele Arrays hinter einander – erst alle für die gefunden Klassen und dann alle für die gefundenen Styles. Das sieht in etwa so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
array(2) {
  [0]=>
  string(19) "class='tag-link-64'"
  [1]=>
  string(2) "64"
}
 
// alle Treffer (pro Tag), die mit class='tag-link-xx' gefunden werden
 
array(2) {
  [0]=>
  string(23) "style='font-size: 8pt;'"
  [1]=>
  string(1) "8"
}
 
// alle Treffer (pro Tag), die mit style='font-size: xxpt;' gefunden werden
array(2) {
  [0]=>
  string(19) "class='tag-link-64'"
  [1]=>
  string(2) "64"
}

// alle Treffer (pro Tag), die mit class='tag-link-xx' gefunden werden

array(2) {
  [0]=>
  string(23) "style='font-size: 8pt;'"
  [1]=>
  string(1) "8"
}

// alle Treffer (pro Tag), die mit style='font-size: xxpt;' gefunden werden

Da alles mit class aus der Tag Cloud herausgefiltert werden soll, ignoriere ich diese Treffer und bearbeite nur das was über style gefunden wurde (Zeile 11 im ersten Codeblock). Anschließend frage ich ab, ob die Zahl des zweiten Elements zwischen 8 und 22 liegt (das ist standardmäßig die Schriftgröße, die WordPress für die kleinste und größte Taggröße verwendet). Diese Abfrage könnte man theoretisch auch weglassen. Aber ich baue darauf meine CSS-Klassen auf, muss also wissen welche Zahlen ich dafür verwende.
Wordpress stuft die Schriftgrößen der Tag Cloud, von 8 bis 22, immer ab, dadurch kann es zu Fließkommazahlen kommen. Da ich diese nicht für einen Klassennamen verwenden kann, prüfe ich nun noch ob in der Zahl ein Punkt vorhanden ist. Wenn ja, schneide ich alles nach dem Punkt ab, wenn nicht, nehme ich die Zahl wie sie ist. Das übergebe ich jetzt noch an meine neu gebaute Klasse (die ich zufällig auch „tag-link-“ nenne, die aber auch jeden anderen Klassennamen haben kann) inkl. der Zahl und gebe das per return zurück an meinen preg_replace_callback Aufruf.

Die Style-Definition

Die Tag Cloud Ersetzung ist damit erfolgreich verlaufen und nun fehlt nur noch die neue CSS-Definition, die ich in die style.css meines (Child-)Themes notiert habe. Um möglichst alle Schriftgrößen abzudecken, habe ich einfach alle Zahlen zwischen 8 und 22 berücksichtigt. Außerdem gebe ich die Schriftgröße nun per em Einheit an, um responsive zu bleiben und da ich einfach mit der Einheit fast immer arbeite.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.tag-link-8 { font-size: 0.7em; }
.tag-link-9 { font-size: 0.75em; }
.tag-link-10 { font-size: 0.8em; }
.tag-link-11 { font-size: 0.95em; }
.tag-link-12 { font-size: 1em; }
.tag-link-13 { font-size: 1.05em; }
.tag-link-14 { font-size: 1.2em; }
.tag-link-15 { font-size: 1.3em; }
.tag-link-16 { font-size: 1.35em; }
.tag-link-17 { font-size: 1.45em; }
.tag-link-18 { font-size: 1.5em; }
.tag-link-19 { font-size: 1.6em; }
.tag-link-20 { font-size: 1.65em; }
.tag-link-21 { font-size: 1.7em; }
.tag-link-22 { font-size: 1.85em; }
.tag-link-8 { font-size: 0.7em; }
.tag-link-9 { font-size: 0.75em; }
.tag-link-10 { font-size: 0.8em; }
.tag-link-11 { font-size: 0.95em; }
.tag-link-12 { font-size: 1em; }
.tag-link-13 { font-size: 1.05em; }
.tag-link-14 { font-size: 1.2em; }
.tag-link-15 { font-size: 1.3em; }
.tag-link-16 { font-size: 1.35em; }
.tag-link-17 { font-size: 1.45em; }
.tag-link-18 { font-size: 1.5em; }
.tag-link-19 { font-size: 1.6em; }
.tag-link-20 { font-size: 1.65em; }
.tag-link-21 { font-size: 1.7em; }
.tag-link-22 { font-size: 1.85em; }

Weitere Möglichkeiten

Das Ganze könnte man nun noch weiterführen. Zum Beispiel könnte man die Ersetzung (in Zeile 18 erster Codeblock) wie folgt aussehen lassen, um die Tag Cloud Links noch besser gestalten zu können:

1
$font = 'class="tagcloud size-'.$str.'"';
$font = 'class="tagcloud size-'.$str.'"';

Nun könnte man über die Klasse tagcloud z.B. Hintergrundfarbe, Rand, Schatten oder ähnliches festlegen, was dann für alle Links gilt und über size-xx wieder die Schriftgrößen. Dem Einfallsreichtum sind da keine Grenzen gesetzt. Hauptsache die elendichen Inline-Styles gehören der Vergangenheit an. 😉

Soweit zu meine kleinen Tag Cloud Funktion. Vielleicht hilft sie dem einen oder anderen von euch ja auch, die Fehler im W3C auszumerzen. Ich jedenfalls bin zufrieden und setze die Funktion schon auf mehreren Blogs ein.

MySQL: Teilstring durch anderen ersetzen

Heute hab ich mich dumm und dämlich gesucht nach der Möglichkeit in einer MySQL-Abfrage einen Teilstring durch einen anderen zu ersetzen. Google hat nicht wirklich sinnvolle Sachen geliefert. Also hab ich es durch probieren und das MySQL-Referenzbuch schließlich doch hinbekommen.

Das Prinzip

Zum Beispiel habe ich eine Tabelle admins und darin eine Spalte email (nur als Anschauungsbeispiel 😉 ). Bisher hat jeder Admin seine eigene Email-Adresse eingetragen. Doch nun möchte ich für alle Admins eine einheitliche „@website-der-admins.de“-Domain einrichten.

Also aus heiko.tester@gmx.de soll dann heiko.tester@website-der-admins.de werden. Alles vor dem @ soll bleiben wie es ist, alles danach soll ersetzt werden. Die passenden Email-Adressen wurden natürlich bereits angelegt.

MySQL kommt ins Spiel

1
2
3
4
UPDATE
    admins
SET
    email = CONCAT(SUBSTRING_INDEX(email, '@', 1), '@website-der-admins.de');
UPDATE
    admins
SET
    email = CONCAT(SUBSTRING_INDEX(email, '@', 1), '@website-der-admins.de');

Mit der Funktion CONCAT kombiniert ihr zwei Teilstrings zu einem. Innerhalb von CONCAT nutze ich die Funktion SUBSTRING_INDEX, um alles vor dem @ (das gibt der dritte Parameter, die 1, an) als ersten Teilstring zu wählen und alles ab dem @ wird mit ‚@website-der-admins.de‘ ersetzt. Wenn ihr es nur bei bestimmten Admins machen wollt, dann könnt ihr das Statement noch mit einer WHERE-Anweisung erweitern.

» Zum Nachlesen

Vielleicht hilft es dem ein oder anderen. Viel Spaß damit.

Link-Empfehlung: Tutorial zur Erstellung eines WordPress-Themes

Auf meiner Suche durch das weite Web, bin ich heute auf ein tolles Tutorial gestoßen. Es ist schon etwas älter und ich frage mich warum ich darauf nicht früher gekommen bin?!
Es erklärt sehr anschaulich (mit vielen Beispielen, Screenshots und Codeschnipseln) wie – einfach eigentlich – ein schönes WordPress-Theme zu erstellen ist. Mit dieser Steilvorlage werde ich mich wohl auch demnächst mal an einem schönen WordPress-Theme versuchen. Was dabei rauskommt teile ich euch dann mit 😉

Zum Theme-Tutorial (bestehend aus 12 Teilen)

Viel Spaß beim Lesen und Rumprobieren!