WordPress: Kommentare – oder wie Spam verkauft wird

Kommentare gehören zu einem Blog wie das Weihwasser in die Kirche. Sie machen viele Artikel erst lesenswert, frischen sie auf, stellen vielleicht auch mal was richtig. Durch die Diskussion am Ende des Artikels kann der neue Leser auch eine Übersicht erhalten, wie die bisherigen Schreiber den Wert des Artikels einschätzen. Also eine tolle Sache, sollte man meinen. Doch mit Kommentaren handelt man sich eine Menge Probleme ein. Dies ist der Grund, warum auf dieser Seite auch keine Kommentare zugelassen sind.

1.    Der Seitenbetreiber haftet für die Kommentare
Nach deutschem Recht haftet der Seitenbetreiber auch für die Kommentare und Links, denn sie sind Bestandteil seiner Seite. Daher sollte kein in Deutschland ansässiger Webmaster Kommentare ungeprüft auf seiner Seite aufnehmen. Auch alle Links müssen auf die manuell im Hinblick auf die Gesetzmäßigkeit geprüft werden.

2.    Über 90 Prozent der Kommentare sind Spam
Ihr werdet feststellen, dass nahezu jeder Kommentar Spam ist. Die Kommentare werden zum Großteil automatisiert durch Boots erzeugt, die nur die Absicht haben, einen Kommentar mit einem Backlink zu hinterlassen, der auf Roulette-, Wett- oder Pillen-Verkaufsseiten verlinkt.

3.    SEOs versuchen, so kostenlose Backlinks zu generieren
Jeder Backlink, also jeder eingehende Link auf die eigene Seite, ist bares Geld wert. Warum? Es geht nicht einmal darum, durch den Link neue Besucher zu generieren, sondern darum, die Wertigkeit der eigenen Seite zu steigern. Suchmaschinen wie Google bewerten unter anderem eine Seite durch die Menge der Links, die auf die Seite zeigen. Hier zählt der Gedanke, dass wenn viele Seiten eine bestimmte Seite verlinken, muss die Seite gut sein. Und eine gute Seite steigt automatisch in den Suchergebnissen nach oben, bringt also automatisch mehr Besucher.
Viele Suchmaschinen-Optimierer (SEO = Person(en), die eine Seite bzw. die Linkstruktur optimiert mit dem Ziel, die Seite möglichst gut in den Suchergebnissen der Suchmaschine zu positionieren) sind inzwischen einen Schritt weiter, und verfassen manuell Kommentare. Natürlich zum Thema passend, aber nur mit dem Ziel, dass der Blog-Webmaster den Kommentar samt Backlink veröffentlich.

4.    Follow oder NoFollow: Ein Link ist ein Link
Durch die Möglichkeit, einem Link das Attribut „nofollow“ zu geben, versuchen einige Blog-Webmaster, die Spamflut und den sogenannten „Linkjuice“ einzudämmen. Es ist richtig, dass Google nach eigenen Angaben nofollow-Links anders behandelt, als „normale“, also „follow“ oder „dofollow“-Links. Doch ein Link ist ein Link. Und nicht nur Google, sondern auch der geneigte Leser wird sich wundern, wenn von einem Blog plötzlich Links zu dubiosen Seiten zeigen.

5.    Spam-Plugins sind keine Lösung
Wenn man täglich zehn Kommentare erhält, die man prüfen muss und feststellt, dass sie fast ausnahmslos (SEO)-Spam sind, verliert man schnell die Lust am Bloggen. Abhilfe sollen Plugins schaffen, die Kommentare auf Spam prüfen. Die erste Möglichkeit ist nur per Chapta Kommentare zuzulassen, ist ein erster Schritt. Doch viele Boots können per OCR auch Chaptas erkennen. So soll es auch in Entwicklungsländer das Geschäftsmodell der manuellen Kommentare geben. Billige Löhne machen dies interessant.
Auch erkennen die Spam-Plugins menschlichen SEO-Spam nicht, da der SEO schon so schlau ist, den Kommentar individuell für den Blog-Post einmalig zu erfassen.

Der Blog-Webmaster handelt sich also durch die Öffnung der Kommentare eine Menge Arbeit ein. Es muss der Webmaster selbst bewerten, ob er Kommentare zulässt oder nicht. Ich persönlich finde es schade, dass immer mehr Webmaster – so auch ich – die Zeit nicht mehr aufbringen können, Kommentare von Spam zu unterscheiden und deshalb gezwungen sind, die Kommentar-Funktion zu deaktivieren.

Weiterleitung ModRewrite 301 von altem CMS zu WordPress – Teil 5

Den Anfang unseres Tutorials verpasst? Hier geht es zum Teil 1.

Im eigentlichen Programm warden wir nicht alle Werte, die oben abgefragt, auch wirklich nutzen. Doch zu Testzwecken ist diese Abfrage sinnvoll.

Nun endlich können wir uns mit dem C#-Code beschäftigen:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using MySql.Data.MySqlClient;

namespace wp_permalinks
{
 class Program
 {
 public static string sConnection = "data source=127.0.0.1;DATABASE=local;UID=root;PASSWORD=xxx;";

 static void Main(string[] args)
 {
 string sSQL = "";
 try
 {
 //Lies hier einmal alle aktiven Artikel aus der alten Artikel-Tabelle ein
 sSQL = "SELECT id, perm, titel FROM artikel WHERE status=1";

 using (MySqlConnection conn = new MySqlConnection(sConnection))
 {
 MySqlDataReader rdr = null;
 conn.Open();
 using (MySqlCommand cmd = new MySqlCommand(sSQL, conn))
 {
 rdr = cmd.ExecuteReader();
 if (rdr.HasRows)
 {
 while (rdr.Read())
 {
 //Prüfe, ob der Perm vorhanden ist
 if (rdr["perm"].ToString().Length < 1)
 {
 //Kein Perm vorhanden
 Ausgabe("Kein Perm für Datei ID " + rdr["id"].ToString() + " " + rdr["titel"].ToString(), true);
 }
 else
 {
 //hier ncoh einige spezifische Überprüfuungen

 //sind Leerzeichen im Perm? -> Fehler
 if (rdr["perm"].ToString().Contains(" ")) Ausgabe("Leerzeichen im Perm für Datei ID " + rdr["id"].ToString() + " " + rdr["titel"].ToString(), true);
 else
 {
 //Wenn zwei Bindestriche im Perm auftauchen, ist das unschön. Hinweis (kein Fehler) in Fehlertabelle
 if (rdr["perm"].ToString().Contains("--")) Ausgabe("HINWEIS: Doppelte -- im Perm für Datei ID " + rdr["id"].ToString() + " " + rdr["titel"].ToString(), true);

 GetNeuerPerm(rdr["perm"].ToString());
 }
 }
 }
 } //has rows
 } //Using
 } //using

 //Warte auf manuelles Ende
 Console.WriteLine("Fertig!");
 Console.ReadLine();

 }
 catch (MySqlException ex)
 {
 Console.WriteLine(ex.Message);
 }
 }

 private static void GetNeuerPerm(string sPerm)
 {
 string sSQL = "";
 try
 {
 //Erstelle nun den Perm, wie er ein der Zieltabelle vorhanden sein soll
 //Umschlüsselung von Unterstrich in Bindestrich
 string sNeuerPerm = sPerm.Replace("_", "-");

 //Lies hier einmal alle aktiven Artikel aus der alten Artikel-Tabelle ein
 sSQL = "SELECT a.id, c.slug FROM wp_posts as a " +
 "LEFT JOIN wp_term_relationships as b ON a.id=b.object_id "+
 "LEFT JOIN wp_terms as c ON b.term_taxonomy_id=c.term_id "+
 "WHERE a.post_name='" + sNeuerPerm + "'";

 using (MySqlConnection conn = new MySqlConnection(sConnection))
 {
 MySqlDataReader rdr = null;
 conn.Open();
 using (MySqlCommand cmd = new MySqlCommand(sSQL, conn))
 {
 rdr = cmd.ExecuteReader();
 if (rdr.HasRows)
 {
 while (rdr.Read())
 {
 //Schreibe hier die ModRewrite-Zeile
 //Redirect 301 /artikel/perm_mit_unterstrichen.html http://www.domaine.de/kategorie/perm-mit-bindestriche.html

 Ausgabe("Redirect 301 /artikel/" + sPerm + ".htm http://www.planet-polo.de/" + rdr["slug"].ToString() + "/" + sNeuerPerm + "-" + rdr["id"].ToString() + ".html");
 Console.WriteLine("ID " + rdr["id"].ToString() + " erfolgreich geschrieben.");
 }
 } //has rows
 else Console.WriteLine("*** FEHLER: Kein Ziel-Perm für " + sNeuerPerm);
 } //Using
 } //using

 }
 catch (MySqlException ex)
 {
 Console.WriteLine(ex.Message);
 }      
 }

 private static void Ausgabe(string sText, bool bFehler=false)
 {
 string sFile = "";
 try
 {
 //Die Ausgabedatei soll den aktuellen Tag + ".txt" erhalten
 if (bFehler) sFile = "Fehler-" + DateTime.Now.ToString("yyyyMMdd") + ".txt";
 else sFile = DateTime.Now.ToString("yyyyMMdd") + ".txt";

 //Erzeuge die dDatei
 FileStream outStream = new FileStream(sFile, FileMode.Append);
 StreamWriter myWriter = new StreamWriter(outStream, System.Text.Encoding.Default);
 myWriter.WriteLine(sText);
 myWriter.Close();
 }
 catch (Exception ex)
 {
 Console.WriteLine("FEHLER in Ausgabe: " + ex.Message);
 }
 }

 }
}

Weiterleitung ModRewrite 301 von altem CMS zu WordPress – Teil 4

Teil 4: Das Programm zum Erzeugen der ModRewrite 301 Daten

Den Anfang unseres Tutorials verpasst? Hier geht es zum Teil 1.

Wir haben in unserem Fall das Problem, dass nicht für alle Artikel im CMS-Altsystem entsprechende Permalinks hinterlegt wurden. Diese Artikel müssen manuell geprüft werden. Diese müssen als Fehler in der Textdatei ausgegeben werden. Diese Fehlerdatei sollte nach dem ersten Lauf überprüft und gegebenenfalls die Permalinks in WordPress angepasst werden. So kann eine saubere Permalink-Struktur aufgebaut werden. Beachten sollte man nur: Wenn sich die Permalinks in WordPress ändern (original), muss ein neuer Dump der Tabelle „wp_posts“ auf das lokale System eingespielt werden.

Rubriken=Kategorien: Zuordnung der Kategorie in WordPress zum Artikel (Post)
Da in WordPress ein Artikel in mehreren Rubriken (Kategorien) erscheinen kann, haben die Entwickler die Zuordnung eines Artikels nicht in der Tabelle „wp_posts“ vorgenommen, sondern die zwei Tabellen „wp_terms“ und „wp_term_relationships“ ausgelagert. Daran ist per se nichts auszusetzen, macht unsere Arbeit an dieser Stelle nur ein wenig Aufwendiger. Es bedeutet für uns, dass wir in unserer lokalen SQL-DB auch diese beiden Tabellen kopieren müssen. Ein Join bei der Abfrage wird uns dann die korrekte Kategorie zum Artikel ermitteln, so dass wir die Ziel-URL (domain.de /kategorie/permalinks-mit-Bindestrich-getrennt.html) auch richtig schreiben können.

Ermitteln wir zuerst einmal alle WordPress-Artikel. Mit

SELECT id, post_name, post_title FROM wp_posts

erhalten wir alle relevanten Daten. In der Tabelle „wp_term_relationships“ finden wir die ID der  Kategorie (“term_taxonomy_id”), die wir per Join hinzufügen:

SELECT id, post_name, post_title, b.term_taxonomy_id FROM wp_posts as a
LEFT JOIN wp_term_relationships as b ON a.id=b.object_id

Nun haben wir die ID der Kategorie. Wir brauchen jedoch den Klarnamen der Kategorie. Ind er Tabelle „terms“ finden wir unsere Kategorien. Für uns interessant ist der „slug“, also nicht der Anzeigename, sondern der Wert der URL.

So lautet der SQL-Code für die Abfrage wie folgt:

SELECT a.id, b.object_id, c.slug FROM wp_posts as a
LEFT JOIN wp_term_relationships as b ON a.id=b.object_id
LEFT JOIN wp_terms as c ON b.term_taxonomy_id=c.term_id

Weiter zu Teil 5: Der C# Programmcode

Weiterleitung ModRewrite 301 von altem CMS zu WordPress – Teil 3

Teil 3: Grundlegende Überlegung für das Erstellen der ModRewrite-Tabelle

Im 1. Teil dieses Tutorials haben wir uns mit der grundlegenden Problematik von geänderten Permalinks beschäftigt. Im 2. Teil haben wir den Aufbau der ModRewrite 301-Weiterleitung weiter unter die Lupe genommen. Die ganze Problematik basiert auf dem Umstand, dass die Migration von einem Content Management System zu einem anderen (hier: WordPress), uns eventuell neue Permalinks beschert. Und diese sind – je nach Ausgangslage – nicht durch eine einfache Regel definierbar. Wir müssen nun also ein Programm schreiben, was uns einmalig die ModRewrite-Umsetzungstabelle für die htaccess-Datei erstellt. Dieser Vorgang muss nur einmalig erfolgen, da alle neue Artikel ja bereits mit den neuen Permalinks erstellt werden.
Das folgende Beispielprogramm wird in C# geschrieben. Denkbar ist jedoch auch, es in PHP zu verfassen. Die grundlegende Idee und der Ablauf im Programm wird in beiden Sprachen identisch sein.

Wir haben in unserer Ausgangslage eine Datenbank (hier: lokale MySQL-Datenbank), in der die Tabelle „artikel“ (CMS-alt) und die Tabelle „wp_posts“ (WordPress neu) vorhanden sind. Wir kennen den bisherigen Permalink aus der Tabelle „artikel“ und müssen nun den neuen Permalink aus der Tabelle „wp_posts“ ermitteln. Da die Artikel-ID sich bei der Migration geändert hat, kann einfache Beziehung hergestellt werden. Wir müssen also die ursprüngliche Artikel-Tabelle durchgehen und zu jedem Artikel den passenden neuen Artikel suchen. Dies ist insofern einfach, da der Perma-Link in der Tabelle aus der alten und der neuen Tabelle sich nicht grundsätzlich geändert hat. Gegen eine Umsetzung direkt in SQL spricht eigentlich auch nichts. Da jedoch neben der Umsetzung von Unterstrich in Bindestrich auch das Hinzufügen der Rubrik im Link erfolgen muss, möchten wir der Einfachheit halber dies über eine kleine C#-Konsolenanwendung erledigen.

Wir erstellen hierfür eine C# Konsolenanwendung. Das .NET Framework 2.0 ist für unsere Zwecke ausreichend. Entscheidend ist der Datenbankzugriff. Da wir auf einen lokalen MySQL-Server zugreifen wollen, benötigen wir die MySql.Data.dll, die über die MySQL-Webseite zu beziehen ist. Wer einen M$-SQL-Server betreibt, braucht diese DLL nicht extra einzubinden. Diese DLL muss unter „Verweise“ in das Projekt mit eingebunden werden. Nicht vergessen werden darf das Using: „using MySql.Data.MySqlClient;“

Der eigentliche Programmablauf ist in Teil 4 unseres Tutorials beschrieben.

Weiterleitung ModRewrite 301 von altem CMS zu WordPress – Teil 2

Automatisierte Erstellung der htaccess-Datei für eine Weiterleitung ModRewrite 301

Im 1. Teil gingen wir davon aus, dass wir aufgrund einer Migration von einem CMS zu WordPress Artikel mit Permalinks haben, die nun auf der neuen WordPress-Installation nicht mehr übereinstimmen. Wir möchten per ModRewrite 301 vom alten auf den neuen Link weiterleiten.

Die Links ändern sich deutlich, so dass keine einfache Regel gefunden werden kann (die Artikel-ID und die Kategorie ist in der WordPress-Installation mit im Permalink vorhanden).

Alt: domaine.de/artikel/mein_premalink_mit_unterstrich_getrennt.htm
Neu: domain.de /kategorie/permalinks-mit-Bindestrich-getrennt.html

Dies bedeutet, dass wir alle alten und neuen Links in der htaccess-Datei manuell eintragen müssen. Bei 15 bis 20 Artikel kann dies sicherlich manuell erfolgen. In unserem Fall haben wir 300 Artikel. In einem folgenden Projekt werden es über 1.000 Artikel sein.
Da jeder Artikel in der htaccess-Datei auftauchen wird, bläht es die Datei natürlich mächtig auf. Dies ist unschön, jedoch leider nicht anders machbar. Die Lösung, alle Eingaben via PHP-Skript in WordPress abzufangen und dann via PHP den Status 301 zu senden, haben wir verworfen. Jedoch kann dies beim Projekt mit über 1.000 Seiten noch mal neu bewertet werden.

Wie lange müssen die 301-Weiterleitungen in der htaccess-Datei verbleiben?
Auf diese Frage haben wir selbst noch keine Antwort gefunden. Aus Suchmaschinen-Sicht dürften einige Tage bzw. Wochen genügen. Denn wenn der automatische Boot der Suchmaschine die Seite neu gespidert hat, hat die „301“ ihren Dienst getan. Je nach Wichtigkeit der Seite kommen die Boots der Suchmaschinen täglich oder wöchentlich. Lediglich bei Seiten, die sich in der Vergangenheit nur selten geändert haben, sind Besuchsintervalle von Monaten vorhanden. Allerdings wird man es nicht erreichen, dass alle Links von fremden Seiten von den jeweiligen Webmastern in absehbarer Zeit geändert werden. Und da wir ja froh sind, wenn jemand einen Link gesetzt hat, werden wir ihn auf keinen Fall bitten, den Link zu ändern. Zu groß ist die Gefahr, dass er sich die Arbeit nicht macht und den Link löscht, was noch weniger Arbeit für ihn bedeutet.
Die Auswertung der Logfiles in den kommenden Monaten wird zeigen, in wieweit die htaccess-Datei entschlackt werden kann. Wenn keine Aufrufe auf ein bestimmten Artikel in ein oder zwei Monaten mehr verzeichnet werden, kann der Eintrag in der htaccess-Datei gelöscht werden. Erzielen wir nach wie vor Traffic über einen veralteten Link, wird die ModRewrite-Weiterleitung weiter bestehen bleiben.

Weiter zu Teil 3 dieses kleinen WordPress Tutorials

Weiterleitung ModRewrite 301 von altem CMS zu WordPress – Teil 1

Wer einen Umzug von einem alten CMS (Content Management System) zu WordPress vollzieht, wird vor dem Problem stehen, dass die Links, die bisher zu den einzelnen Seiten zeigen, nicht mehr passen. Selbst wenn vorher schon Permalinks definiert waren und diese nach WordPress migriert wurden, passt der Link nicht unbedingt.
Wir wollen also erreichen, dass alle Seiten, die bisher mit dem alten Link verlink waren, nach wie vor erreichbar sind. Aus suchmaschinengründen wollen wir keinen doppelten Content erzeugen (Seite unter dem alten und neuen Link erreichbar), sondern möchten per „Redirect 301“ der Suchmaschine zeigen, dass die bisherige Seite einen neuen Link hat. Ein User merkt davon nichts, er wir einfach zur neuen Seite weitergeleitet.

In folgendem Beispiel nehmen wir folgendes an:

  1. Die bisherigen Permalinks lauteten domaine.de/artikel/mein_premalink_mit_unterstrich_getrennt.htm
  2. Die neuen Permalinks in WordPress lauten domain.de /kategorie/permalinks-mit-Bindestrich-getrennt.html
  3. Die IDs der Artikel bzw. Posts haben sich bei der Migration geändert
  4. Der Permalink wurde bei der Migration in die WordPress-Datenbank (Tabelle: „wp_posts“) im Feld „post_name“ übernommen; der Unterstrich („_“) wurde durch ein Bindestrich („-„) ersetzt

Zur Erklärung
Die bisherigen Permalinks waren falsch oder zumindest „suboptimal“. Nach wie vor geht die Literatur davon aus, dass Suchmaschinen wie Google Wörterketten, die mit einem Unterstrich getrennt sind, als ein Wort betrachtet. Somit macht der Permalink „keyword1_keyword2“ keinen Sinn, da die Suchmaschine dies nicht trennt. Richtig wäre wohl „keyword1-keyword2“. Natürlich kann man bis zum jüngsten Tage darüber streiten, wie sinnvoll der Links ist, ob es die Position in den Suchergebnissen beeinflusst und so weiter … Da wir aus anderen Gründen eine Migration vor uns haben, passen wir einfach die Links an.

Wie können wir das Ziel erreichen?
Das Geheimnis liegt wie schon erwähnt in ModRewrite. Dabei handelt es sich um eine Apache-Modul, dass serverseitig URL-Anfragen analysiert und umschlüsselt. Aus SEO-Gründen für eine optimale Suchmaschinenpositionierung wollen wir nicht, dass ModRewrite die Seite unter beiden Links ausliefert. Wir wollen, dass die Seite via „Redirect 301“ weitergeleitet wird.

Dazu passen wir die .htaccess-Datei von ModRewrite an. Diese liegt im Root der WordPress-Installation. Achtung: Je nach Installation wurde die Datei manuell erzeugt, oder WordPress hat das Recht, diese zu generieren. Im zweiten Fall müssen dann die Änderungen via WordPress erzeugt werden, da sonst WordPress die manuelle Änderungen wieder überschreiben würde.

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
Redirect 301 /pfad/alter-link.htm  http://www.domain.de/pfad/neuer-link-350.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Erklärung
Bei einem Aufruf schaut das Modul ModRewrite die übergebene URL an. Wenn eine Regel oder eine fest codierte URL aufgelistet ist, leitet das Modul die Anfrage an die neue URL weiter und sendet gleichzeitig den Status „301“ an die Anfrager. Ist dies eine Suchmaschine, erkennt diese, dass sich die URL geändert hat und berücksichtigt dies in ihren Suchergebnissen.

Wie wir die ModRewrite-Datei automatisiert einmalig anlegen, erfahrt Ihr im 2. Teil dieses Tutorials.

Artikel-Migration von CMS nach WordPress – Teil 4

Zum Anfang der Serie Artikel-Migration von CMS nach WordPress – Teil 1

Schritt 9: Die Migration der Artikel nach WordPress
Nach soviel Vorarbeit und Analyse wird es endlich spannend. Wir haben für die Migration ein Programm in C# .NET geschrieben. Denkbar wäre auch, die Migration per PHP umzusetzen. In unserem Beispiel haben wir zwei Datenbanken („db_alt“ und „db_neu“). In der „db_alt“ ist lediglich die Tabelle „artikel“ vorhanden. In dieser Tabelle sind alle Artikel des Altsystems gespeichert. In der Datenbank „db_neu“ wurden per Export alle Tabellen der WordPress-Installation eingespielt. So haben wir die Möglichkeit, die Migration mehrfach durchzuführen, da wir die Datenbank „db_neu“ bedenkenlos neu aufsetzen können. Von Migrationen auf Echtsystemen ohne Backup ist abzuraten.

using System;
using System.Collections.Generic;
using System.Text;
using MySql.Data.MySqlClient;
using System.IO;
using System.Collections;

namespace WP_import
{
 class Program
 {
 public static string connALT = "data source=127.0.0.1;DATABASE=db_alt;UID=root;PASSWORD=xxx;";
 public static string connNEU = "data source=127.0.0.1;DATABASE=db_neu;UID=root;PASSWORD=xxx;";
 public static ArrayList list = new ArrayList();

 public static string sRubrikid="-1";
 public static string pic="";

 static void Main(string[] args)
 {
 Console.WriteLine("START");

 GetData();

 Console.WriteLine("ENDE");
 Console.ReadLine();
 }

 private static string GetmyDate(string sTimestamp)
 {
 string sRes = "";
 try
 {
 sRes = sTimestamp;
 sRes = sTimestamp.Substring(6, 4) + "-" + sTimestamp.Substring(3, 2) + "-" + sTimestamp.Substring(0, 2) + sTimestamp.Substring(10);

 }
 catch (Exception ex)
 {
 Console.WriteLine(ex.Message);
 }
 return sRes;
 }

 private static void GetData()
 {
 try
 {
 //Lies hier einmal alles aus der alten Artikel-Tabelle ein
 string sSQL = "SELECT modelleid,timestamp,titel,perm,beschreibung, text FROM artikel where status=1";
 MySqlDataReader rdr = null;
 MySqlConnection cn = new MySqlConnection(connALT);
 cn.Open();
 MySqlCommand cmd2 = new MySqlCommand(sSQL, cn);
 rdr = cmd2.ExecuteReader();
 while (rdr.Read())
 {
 list.Clear();

 string sDate = "";
 try
 {
 //Mach ein Date aus dem Timestamp
 string s = rdr["timestamp"].ToString();
 sDate = GetmyDate(s);
 }
 catch {
 sDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
 }

 //Benötigte Felder in WordPress
 //    post_author: ID des Autors (1)
 list.Add("1");

 //    post_date: DateTime
 list.Add(sDate);

 //    post_date_gmt: DateTime
 list.Add(sDate);

 //    post_content: Text
 list.Add(Umsetzung(rdr["beschreibung"].ToString()) + "<br>" + Umsetzung(rdr["text"].ToString()));

 //    post_title: Überschrift
 list.Add(Umsetzung(rdr["titel"].ToString()));

 //    post_excerpt=''
 list.Add("");

 //    post_status=publish
 list.Add("publish");

 //    comment_status=closed
 list.Add("closed");

 //    ping_status=closed
 list.Add("closed");

 //    post_password=''
 list.Add("");

 //    post_name='name-des-titels-like-seo'
 string sBuffer = rdr["perm"].ToString();
 sBuffer = sBuffer.Replace("_", "-");
 list.Add(sBuffer); 

 //to_ping=''
 list.Add("");

 //pinged=''
 list.Add("");

 //    post_modified: DateTime
 list.Add(sDate);

 //    post_modified_gmt: DateTime
 list.Add(sDate);

 //    post_content_filtered=''
 list.Add("");

 //    post_parent=0
 list.Add("0");

 //Guid='http://www.domain.de/?p=' + ID (eigen)
 list.Add("http://www.domain.de/?p=");

 //    menu_order=0
 list.Add("0");

 //post_type='post'
 list.Add("post");

 //post_mime_type=''
 list.Add("");

 //comment_count=''
 list.Add("0");

 //Rubrikid umschlüsseln
 switch (rdr["modelleid"].ToString())
 {
 case "1": sRubrikid = "4"; break;
 case "2": sRubrikid = "5"; break;
 case "3": sRubrikid = "6"; break;
 case "4": sRubrikid = "7"; break;
 case "5": sRubrikid = "8"; break;
 }

 Console.WriteLine("Lege Artikel an ...");
 LegeArtikelan();

 }
 rdr.Close();
 cn.Close();

 }
 catch (MySqlException ex)
 {
 Console.WriteLine(ex.Message);
 }
 }

 //Benötigte Felder in WordPress
 //    post_author: ID des Autors (1)
 //    post_date: DateTime
 //    post_date_gmt: DateTime
 //    post_content: Text
 //    post_title: Überschrift
 //    post_excerpt=''
 //    post_status=publish
 //    comment_status=closed
 //    ping_status=closed
 //    post_password=''
 //    post_name='name-des-titels-like-seo'
 //to_ping=''
 //pinged=''
 //    post_modified: DateTime
 //    post_modified_gmt: DateTime
 //    post_content_filtered=''
 //    post_parent=0
 //    Guid='http://www.domain.de/?p=' + ID (eigen)
 //    menu_order=0
 //post_type='post'
 //post_mime_type=''
 //comment_count=''

 private static string Umsetzung(string sText)
 {
 //Schlüssel die gängigsten HTML-Sonderzeichen wieder um
 sText = sText.Replace("&amp;", "&");

 sText = sText.Replace("&auml;", "ä");
 sText = sText.Replace("&Auml;", "Ä");
 sText = sText.Replace("&ouml;", "ö");
 sText = sText.Replace("&Ouml;", "Ö");
 sText = sText.Replace("&uuml;", "ü");
 sText = sText.Replace("&Uuml;", "Ü");
 sText = sText.Replace("&szlig;", "ß");
 sText = sText.Replace("&lt;", "<");
 sText = sText.Replace("&gt;", ">");
 sText = sText.Replace("&quot;", """);
 sText = sText.Replace("&nbsp;", " ");

 return sText;
 }

 private static void LegeArtikelan()
 {
 string sSQL = "";
 try
 {

 sSQL = "INSERT into wp_posts (post_author,post_date,post_date_gmt,post_content,post_title,post_excerpt,post_status," +
 "comment_status,ping_status,post_password,post_name,to_ping,pinged,post_modified,post_modified_gmt,post_content_filtered,"+
 "post_parent,guid,menu_order,post_type,post_mime_type,comment_count) VALUES (";

 int i = 0;
 foreach (string sValue in list)
 {
 sSQL +="'"+sValue+"'";
 i++;
 if (i < list.Count) sSQL += ",";

 }
 sSQL+=")";

 //    post_author: ID des Autors (1)
 //    post_date: DateTime
 //    post_date_gmt: DateTime
 //    post_content: Text
 //    post_title: Überschrift
 //    post_excerpt=''
 //    post_status=publish
 //    comment_status=closed
 //    ping_status=closed
 //    post_password=''
 //    post_name='name-des-titels-like-seo'
 //to_ping=''
 //pinged=''
 //    post_modified: DateTime
 //    post_modified_gmt: DateTime
 //    post_content_filtered=''
 //    post_parent=0
 //Guid='http://www.domain.de/?p=' + ID (eigen)
 //    menu_order=0
 //post_type='post'
 //post_mime_type=''
 //comment_count=''              

 MySqlConnection cn = new MySqlConnection(connNEU);
 cn.Open();
 MySqlCommand cmd = new MySqlCommand(sSQL, cn);
 cmd.ExecuteNonQuery();
 //cn.Close();

 //ID des Artikels ermitteln
 sSQL = "SELECT @@IDENTITY AS 'LastID'";
 MySqlCommand dbcSelect = new MySqlCommand(sSQL, cn);
 MySqlDataReader dbrSelect = dbcSelect.ExecuteReader();
 dbrSelect.Read();
 int iLastID = Int32.Parse(dbrSelect.GetValue(0).ToString());
 dbrSelect.Dispose();

 //Mach jetzt ein Update auf den eben eingefügten DS (Um die guid zu aktualisieren)
 sSQL = "UPDATE wp_posts SET guid = concat(`guid`,"+iLastID.ToString()+") WHERE ID=" + iLastID.ToString();
 MySqlCommand cmd2 = new MySqlCommand(sSQL, cn);
 cmd2.ExecuteNonQuery();

 //Lege nun die Rubrik zu diesem Artikel an
 sSQL = "INSERT into wp_term_relationships (object_id, term_taxonomy_id, term_order) VALUES ("+
 iLastID.ToString()+"," + sRubrikid + ",0)";
 MySqlCommand cmd3 = new MySqlCommand(sSQL, cn);
 cmd3.ExecuteNonQuery();

 //Hier könnten noch Meta-Daten gespeichert werden: wp_postmeta
 sSQL = "INSERT into wp_postmeta (post_id, meta_key, meta_value) VALUES ("+
 iLastID.ToString() + ",'Meta-Name','Meta_value')";
 MySqlCommand cmd4 = new MySqlCommand(sSQL, cn);
 cmd4.ExecuteNonQuery();

 cn.Close();

 }
 catch (MySqlException ex)
 {
 Console.WriteLine(ex.Message);
 }      
 }

 }
}

Artikel-Migration von CMS nach WordPress – Teil 3

Zum Anfang der Serie Artikel-Migration von CMS nach WordPress – Teil 1

Schritt 7: WordPress analysieren
Wir kennen bereits die Tabellen „wp_user“ und „wp_terms“. Artikel speichert WordPress in der Tabelle „wp_posts“. Hier ist ersichtlich, dass WordPress eigentlich ein Blogsystem ist. Doch inzwischen eignet sich WordPress auch als klassisches Content Management System. Die Entwickler haben hier einen wichtigen und richtigen Schritt getan.
Wenn Sie die Tabelle „wp_posts“ analysieren, werden Sie feststellen, dass es eine direkte Beziehung über eine ID zur Tabelle „wp_user“ gibt. Oder anders ausgedrückt: Die ID eines Benutzers wird direkt im Artikeldatensatz gespeichert.
Leider werden Sie keine direkte Beziehung zur Kategorie finden. Aber wie speichert WordPress die Kategorie zu einem Artikel? In der Tabelle „wp_term_relationships“ finden Sie die Spalten „object_id”, “term_taxonomy_id” und “term_order”. Die Object-ID ist nicht eindeutig und beinhaltet die ID des Artikels (“wp_posts”). Im Feld „term_taxonomy_id“ finden Sie die ID der Kategorie („wp_terms“).
Warum dieser Umweg? Sie können unter WordPress einen Artikel in mehreren Kategorien veröffentlichen. Wie sinnvoll dies ist, muss jeder für sich selbst entscheiden. Aus SEO-Gründen ist davon auf jeden Fall Abstand zu nehmen: zu groß die Gefahr, doppelten Content zu erzeugen.

Schritt 8: Benutzerdefinierte Felder in WordPress
Sie können in WordPress benutzerdefinierte Felder anlegen. Sei es, um Meta-Daten zum Artikel zu speichern, oder als Datenhaltung für diverse Plugins. Bei den meisten Migrationen dürfte dieser Schritt nicht notwendig sein, denn es ist keine Pflicht, für einen Artikel auch Metadaten anzulegen.
Wordpress speichert die Daten in der Tabelle „wp_postmeta“. Neben einer eindeutigen ID finden wir die Felder „postid“ (->ID aus der Tabelle „wp_posts“), „meta_key“ und „meta_value“. Hier kann ein Meta-Feld („meta_key“) zum Artikel angelegt werden. Der Wert des Feldes findet sich in der Spalte „meta_value“.

Weiter geht es im nächsten Teil unserer kleinen Serie: Artikel-Migration von CMS nach WordPress – Teil 4

Artikel-Migration von CMS nach WordPress – Teil 2

Zum Anfang der Serie Artikel-Migration von CMS nach WordPress – Teil 1

In der Tabelle wp_terms werden in WordPress die Kategorien gespeichert
In der Tabelle wp_terms werden in WordPress die Kategorien gespeichert

Schritt 3: Kategorien anlegen
Wenn das bisherige CMS mit Kategorien gearbeitet hat, was sinnvoll ist, sollten diese im Dashboard unter dem Punkt „Artikel/Kategorien“ angelegt werden (siehe auch „WordPress: mehrdimensionale Kategorien„). Bei der Anlage der Kategorie ist darauf zu achten, dass im Feld „Slug“ die Kategorie URL-verträglich eingegeben wird. So sollte beispielsweise aus „Meine Tipps“ „meine-tipps“ und aus „Kuriositäten“ ein „kuriositaeten“ werden.
In der Tabelle „wp_terms“ speichert WordPress diese Daten. Wir werden diese später noch benötigen.

 


Schritt 4: Benutzer anlegen
Es ist darauf zu achten, dass nun auch alle Benutzer, die auf dem alten CMS Artikel verfasst haben, auf der neuen WordPress-Installation angelegt wurden. Sind Artikel im Altsystem von Benutzer verfasst worden, die inzwischen nicht mehr tätig sind, sollten diese Benutzer ebenfalls angelegt werden, damit der Artikel samt Benutzerdaten migriert werden kann. Andernfalls muss man sich überlegen, wie mit den Artikeln umgegangen werden soll. Die Benutzerdaten speichert WordPress in der Tabelle „wp_user“.

Schritt 5: Datenbank sichern
Wenn alle Benutzer angelegt wurden, alle Kategorien angelegt sind und alle Einstellungen getätigt sind, ist es Zeit, die Datenbank zu sichern. Via „phpmyadmin“ kann beispielsweise ein Export erfolgen.

Schritt 6: Alte CMS-Datei analysieren
Es gilt zu analysieren, wie das bisherige CMS mit seinen Daten umgegangen ist. Es stellen sich die Fragen, in welchem Feld die bisherige Kategorie zum Artikel angegeben ist, wie der Benutzer gekennzeichnet ist, und ob alle Felder in einer Tabelle vorhanden sind. Im folgenden Beispiel gehen wir davon aus, dass alle Daten in der Tabelle „artikel“ enthalten sind. Ein Datensatz kennzeichnet einen Artikel. Über Normalisierung sind die Beziehungen zum Benutzer und zur Kategorie verfügbar.

Weiter geht es im nächsten Teil unserer kleinen Serie: Artikel-Migration von CMS nach WordPress – Teil 3

Artikel-Migration von CMS nach WordPress – Teil 1

Die Gründe, auf WordPress als Content Management System (CMS) umzusteigen, sind vielfältig. Gerade im Netz sind viele Meinungen über die verschiedenen Content Management Systeme nachzulesen. Letztlich entscheidet der persönliche Geschmack, das persönliche Anfreunden mit der Oberfläche und natürlich auch die Frage, ob das CMS alle Funktionen abdeckt, die man benötigt, ob WordPress das CMS erster Wahl ist. Und sicherlich haben viele – so auch ich – in der Vergangenheit ihr eigenes Content Management System geschrieben und haben einfach nicht mehr die Zeit, dieses System weiter zu pflegen. Und dort liegt auf jeden Fall eine der Stärken von WordPress: Das Open Source-Projekt wird von vielen fleißigen Händen gepflegt, ständig weiterentwickelt und auch zeitnah mit neuen Sicherheits-Patches versorgt. Da in meinem Fall der Code (die ersten Teile sind über acht Jahre alt) komplett neu geschrieben werden müsste, war es einfacher, auf WordPress zu wechseln.

Schritt 1: Die Basis-Installation
Die Installation von WordPress geht schnell von der Hand. Voraussetzung ist ein Webserver mit einer MySQL-Datenbank. Auf das Web wird am Besten die deutsche Version via FTP hochgeladen. Im Root der WordPress-Installation ist eine Datei namens „config.php“. Diese ist mit einem Texteditor zu öffnen. An den beschriebenen Stellen muss der Datenbankname, der Datenbank-Benutzer sowie das Passwort eingetragen werden. Die Datei benötigt auf dem Webserver die Rechte „777“.
Über den Browser wird das Web aufgerufen. WordPress meldet sich mit einem kurzen Installationsdialog. Lediglich die ersten Benutzerdaten und ein paar Textvariablen werden abgefragt. Fertig ist die Basisinstallation.

Schritt 2: Die Installation verfeinern
Es sollte dann unter dem Ordner „wp_content“ ein Ordner „uploads“ manuell angelegt werden. Dieser Ordner erhält die Rechte „777“. In diesen Ordner werden später alle Bilder und Medien, die von den Redakteuren in die Artikel eingefügt werden, zentral gespeichert.
Loggen Sie sich danach im Dashbord ein. In der Regel finden Sie einen Link „Anmelden“ (oder sie geben im Browser „domain.de/wp-admin“ ein). Es sollten unter „Einstellungen“ einige Angaben verfeinert werden. Die Zeitzone ist ggfls. einzustellen. Auch unter dem Punkt „Diskussion“ sollte geschaut werden. Wer die Kommentarfunktion „offen“ lässt, riskiert, dass blindwütige SEOs massenhaft Backlinks in Kommentare hinterlassen. Diverse blaue Pillen dürften sich auch schnell in den Kommentaren finden. Und letztendlich sind die Plugins zu installieren. Welche Plugins sinnvoll sind, das würde eine eigene Artikelserie füllen (und kommt vielleicht noch aus meiner Feder).

Weiter geht es im nächsten Teil unserer kleinen Serie: Artikel-Migration von CMS nach WordPress – Teil 2