Wordpress PlugIn: “Page Linker”

Was sicherlich schon viele Wordpress User vermisst haben, ist ein einfacher “Einbau” von internen Verlinkungen. Der Page Linker erweitert den internen WYSIWYG-Editor um ein entsprechendes Menü, über das man mit wenigen Klicks Links zu eigenen “Pages” in seine Texte einfügen kann.

Screenshot - Seitenauswahl im Page-Linker
Screenshot: Beim Schreiben einfach Seite anwählen, Knopf drücken -
Und schon steht der richtige Link im Text.

Wirklich eine Erleichterung: Bisher gibt’s diesen Komfort zwar nur für statische Seiten, aber wer Wordpress als CMS einsetzt, hat sowieso überwiegend mit “Pages” zu tun - und mit “URL-Kopier-Aktionen” braucht man sich dank “Page Linker” nicht mehr herumzuärgern.

 

Dynamisch?

Leider wird der interne Link als gewandelter “Permalink” in den Text eingefügt. Das kann zu fehlerhaften Verlinkungen führen, wenn man bereits verlinkte Pages so verschiebt, dass sich der Permalink ändert. So etwas passiert u.a. wenn man eine Seite einer anderen “Mutterseite” unterordnet:

Aus dem Link

<a href="http://www.seite.de/beispiel/irgendwas/">irgendwas</a>

… könnte beispielsweise werden:

<a href="http://www.seite.de/exempel/alt/irgendwas/">irgendwas</a>

Alle älteren Seiten und Beiträge, die auf die Seite “irgendwas” verlinken, müssten dann aktualisiert werden. Es wäre weitaus praktischer, wenn sich alle bereits bestehenden Verlinkungen “automatisch” aktualisieren würden. Und eben das klappt mit Wordpress nicht, wenn interne Links als schon “fertig umgeformter” Permalink gespeichert sind.

Einen anderen Weg geht das PlugIn “Easy Post-to-Post Links” - Damit wird innerhalb spezieller HTML-Kommentare die ID oder der Titel einer Page statt Link in den Text eingefügt. Gleichzeitig ist ein “Filter” aktiv, der genau diese Kommentare bei Ausgabe der Inhalte in einen Link umwandelt. So kann man seine Seiten verschieben, wie man’s grad braucht.

Der Nachteil: Wenn man das PlugIn deaktiviert, gibt es gar keine Links mehr, sondern nur die HTML-Kommentarmarken. Also auch nicht ganz unproblematisch. Und außerdem weiß kaum jemand die “IDs” aller seiner Seiten aus dem Kopf …

 

Vorüberlegungen

Damit man unbesorgt seine Pages verschieben und anders anordnen kann, ohne nachträglich die Links in älteren Seiten korrigieren zu müssen, empfiehlt es sich, interne Verlinkungen mit der ID in seine Texte einzufügen.

Denn Links à la <a href="http://www.seite.de/?page_id=123"> werden grundsätzlich immer gefunden (sofern die Seite nicht gänzlich gelöscht ist).

Für Suchmaschinen ist das allerdings nicht ideal, denn damit ist ein und dieselbe Seite über verschiedene Links erreichbar - Stichwort “doppelter Content” - und den sollte man nach Möglichkeit vermeiden.

Es gibt zwar das (übrigens sehr empfehlenswerte) PlugIn “Permalink Redirect”, mit dem alle “ID”-Verlinkungen mit Permanent Redirect auf die “Permalink”-Adresse weitergeleitet werden, aber es wäre schöner, wenn im Quelltext immer gleich der “gewünschte” Link stehen würde.

Für unser Page Linker PlugIn heißt das:

  1. “Umbau”, damit interne Links mit der ID konstruiert werden
  2. “Link-Filter” programmieren, damit die “ID-Links” vor Ausgabe des Inhaltes in “schöne” Permalinks umgewandelt werden

 

Überarbeitung: “Page Linker Reloaded”

Das Original PlugIn besteht aus mehreren Dateien, die allesamt in einem eigenen PlugIn-Ordner namens “wp-page-linker” abgelegt werden.

An den ganzen JavaScript-Dateien brauchen wir nichts zu ändern,* » siehe unten

Für den ersten Schritt ist die Datei “selectPage.php” interessant: Denn diese schreibt Link-Adressen und Seitentitel in ein Array, aus dem nachher das neue Page-Linker Menüfenster den Code generiert, der als Link in den Text eingefügt wird.

Fix und fertige Permalinks wollen wir nicht, deshalb suchen wir folgende Zeile

$arrayPages .= "pages[{$parent->ID}]=new Array('".get_page_link($parent->ID)."','$parent->post_title');\n";

… und ändern sie um in …

$arrayPages .= "pages[{$parent->ID}]=new Array('".get_bloginfo('wpurl')."/?page_id=".$parent->ID."','".$parent->post_title."');\n";

Damit “kennt” der Page-Linker keine Permalinks mehr und kann nur noch “ID-Links” einfügen. Wer keine Angst vor doppeltem Content bzw. das oben genannte PlugIn “Permalink Redirect” installiert hat, ist an dieser Stelle eigentlich fertig.

 

“Automatische Permalinks”

Ein neuer Wordpress Filter: Damit “unschöne” Links gar nicht erst im HTML-Quelltext auftauchen, sondern gleich der “Permalink” angezeigt wird, muss der Seiten- bzw. Beitrags-Inhalt vor der Ausgabe ein bisschen bearbeitet werden. Also muss der Filter ans Ende der Haupt-Datei des PlugIns eingefügt werden, weil diese ja “immer” aktiv ist und nicht nur im Admin-Bereich wirkt.

In der Datei “wp-linker.php” legen legen wir erst einmal fest, wie Wordpress interne Links ohne aktive Permalink-Optionen konstruiert. Der Vollständigkeit halber nehmen wir nicht nur statische Seiten, sondern auch Blog-Beiträge in unseren Filter mit auf.

define(PageLinkConstruct,get_bloginfo('wpurl')."/?page_id=");
define(PostLinkConstruct,get_bloginfo('wpurl')."/?p=");

Vorsicht: Nachher wird mit Regular Expressions nach internen Links gesucht - Zeichen, die eventuell als Modifier im Suchmuster interpretiert werden könnten, müssen also “escaped” werden:

define(PageLinkConstruct,get_bloginfo('wpurl')."/\?page_id\=");
define(PostLinkConstruct,get_bloginfo('wpurl')."/\?p\=");

Link-Suche mit preg_replace - Gefunden werden muss folgendes: Alles, was mit

  • <a plus Leerzeichen anfängt,
  • mit > endet,
  • und dabei gleichzeitig eine Zeichenkette href=" plus PageLinkConstruct oder PostLinkConstruct plus ID-Nummer plus " enthält

… denn das sollte als “Konstruktions-Prinzip” auf das öffnende Tag eines internen Wordpress-Links zutreffen. Der passende reguläre Ausdruck für das entsprechende Suchmuster ist dann dieser:

'#<a [^>]*href="'.PageLinkConstruct.'|'.PostLinkConstruct.'[^"]*"[^>]*>#'

Alte Links ersetzen: Jetzt wollen wir aber nicht nur alle Links finden, sondern auch die ID-Nummern aus den Fundstellen herausziehen, damit daraus Permalinks erzeugt werden können. Und diese Permalinks müssen wiederum in die Fundstellen anstelle des “alten” Links eingefügt werden.

Das Suchmuster ist also mit einigen Runden Klammern zu erweitern, aus denen nachher Rückreferenzierungen gebildet werden können. Denn wir wollen ja nicht die gesamte Fundstelle ersetzen, sondern nur den href-Bereich. Damit wird’s schon etwas umfangreicher.

Und letztlich brauchen wir für das Zusammensetzen des “neuen” Links eine eigene Funktion, in die gefundene “ID”-Nummern übergeben werden, aus denen dann mit “Anfang” und “Ende” des Link-Tags der gewünschte Permalink gebildet wird.

Im Zusammenhang sieht das Ganze dann so aus:


define(PageLinkConstruct,get_bloginfo('wpurl')."/\?page_id\=");
define(PostLinkConstruct,get_bloginfo('wpurl')."/\?p\=");

function gunnART_LinkHandler($Before,$p_id,$After) {
	return $Before.get_permalink($p_id).$After;
}

function gunnART_LinkFilter($Text){
	$LinkFilterSearch = '#(<a [^>]*href=")(('.PageLinkConstruct.'|'.PostLinkConstruct.')([^"]*))("[^>]*>)#ismeU';
	return preg_replace($LinkFilterSearch,"gunnART_LinkHandler(\"$1\",\"$4\",\"$5\")",$Text);
}

add_filter('the_content', 'gunnART_LinkFilter');
add_filter('the_excerpt', 'gunnART_LinkFilter');
	

Fertig: Jetzt hat man eine komfortable Möglichkeit, interne Links in seinen Inhalten zu veröffentlichen - Und als zusätzliches “Bonbon” werden global alle in Content- und Excerpt-Texten auftauchenden internen “Nicht-Permalinks” vor der HTML-Ausgabe in Suchmaschinen freundliche URLs umgewandelt.

 

Download

Die geänderte Version des PlugIns kann direkt hier heruntergeladen werden:
wp-page-linker_Reloaded.zip
wp-page-linker_Reloaded2.zip

 

Nachtrag und Version 2

1) Datei “form.js”:

Eine der “mitgelieferten” JavaScript-Dateien hab ich doch bearbeitet und vergessen, das zu notieren, ich bitte um Entschuldigung. Die Zeile 15 der Datei “form.js” muss noch umgeändert werden in

myValue = "<a href='"+href+"' title='"+title+"'>"+title+"</a> ";

Der Tiny MCE-Editor wandelt bei mehrfacher Bearbeitung “Single Quotes” innerhalb von HTML-Tags in “Double Quotes” um - Und das Suchmuster im (alten) Linkfilter sucht daher auch gleich nur nach solchen Links. Das hab ich aber vorhin geändert.

2) Verbesserter LinkFilter:

Um Links zu finden, die mit Hochkommata <a href='http://meinblog.de/?p=123'> konstruiert sind, muss das Suchmuster im Linkfilter erweitert werden - Wird ein solcher Link dann gefunden, tauchen die Escape-Marken als überflüssige Backslashes vor den Single-Quotes auf. Die müssen dann wieder entfernt werden:

define(PageLinkConstruct,get_bloginfo('wpurl')."/\?page_id\=");
define(PostLinkConstruct,get_bloginfo('wpurl')."/\?p\=");

function gunnART_LinkHandler($Before,$p_id,$After) {
	return stripcslashes($Before.get_permalink($p_id).$After);
}

function gunnART_LinkFilter($Text){
	$LinkFilterSearch = '#(<a [^>]*href=["\'])(('.PageLinkConstruct.'|'.PostLinkConstruct.')([^"\']*))(["\'][^>]*>)#ismeU';
	return preg_replace($LinkFilterSearch,"gunnART_LinkHandler(\"$1\",\"$4\",\"$5\")",$Text);
}
	

Das kann man sicherlich bedeutend eleganter hinkriegen, Vorschläge sind immer willkommen.

3) Anpassung für Wordpress 2.0x?

Da Wordpress 2.1x Beiträge und Seiten anders kennzeichnet als Wordpress 2.0x ergibt sich für “selectPage.php” die folgendermaßen geänderte Abfrage:

$query = "SELECT * FROM {$wpdb->posts} ";
$query .= "WHERE post_status = 'static' AND ";
$query .= "post_parent='$parent' $excludeString ORDER BY post_title;";
return $wpdb->get_results($query);
	

Desweiteren sind Änderungen in “wp-linker.php” nötig, die von den Autoren aber bereits “vorbereitet” und gekennzeichnet sind - es müssen lediglich einige Kommentar-Marken entfernt werden.

Nur werden die angeklickten Links leider nicht in den Text-Editor übernommen - und bei jedem Versuch gibt es JavaScript-Fehlermeldungen. Den Fehler hab ich bisher noch nicht finden können. Also wer dazu eine Idee hat …