Viele Stunden Spaß: Fehler bei WordPress MU 3.3 und fehlendem Datenbank-Prefix
Seit dem Upgrade von WordPress auf WordPress 3.3 funktionierte irgendetwas bei meinem WordPress MU nicht mehr richtig. Dieses WordPress hier ist die Master-Seite einer MU Installation mit dem Domain Remapping Plugin, so dass ich viele verschiedene Seiten mit einer Codebasis betreuen kann - eine sehr angenehmes Feature, um alles einfacher zu halten und mehr Sicherheit durch immer aktuelle Software zu erhalten. Soweit, so gut.
Nach dem Upgrade auf 3.3 wurden die Nutzer aber nicht mehr zu ihrer Admin-Seite weitergeleitet, wenn sie sich auf einem anderen Blog als auf diesem hier (also dem Master Blog) einloggen wollten. Stattdessen kamen sie auf ihre Nutzerseite hier direkt auf sectio-aurea.org/wp-admin/user/ . Ausserdem wurde in der "Meine Blogs" Liste nur noch das Hauptblog angezeigt, nicht aber all die anderen Blogs, wo ein Nutzer Rechte hatte.
Da sich meine erste Vermutung, es könne sich dabei um einen Plugin-Fehler des noch nicht vollständig an WordPress 3.3 angepassten Domain Remapping Plugins halten, nicht bestätigt hat (es gibt aber eine Beta-Version, die die sonstigen Fehler des Plugins behebt) ging es in den Code. Verantwortlich für die Weiterleitung auf die richtige Seite war dieses Codefragment in der wp-login.php:
if ( is_multisite() && !get_active_blog_for_user($user->ID) && !is_super_admin( $user->ID ) )
$redirect_to = user_admin_url();
Die Funktion get_active_blog_for_user() gab null zurück, obwohl dies das Aktive Blog des Nutzers war. Merkwürdig. Die aufgerufene Funktion befand sich in wp-include/ms-functions.php:
$blogs = get_blogs_of_user( $user_id );
if ( empty( $blogs ) )
return null;
Ah. Da kommt unsere null her. Aber warum ist $blogs leer, wenn der Nutzer doch Teild es Blogs war? Ein Blick in wp-include/user.php verrät es:
foreach ( $keys as $key ) {
if ( 'capabilities' !== substr( $key, -12 ) )
continue;
if ( 0 !== strpos( $key, $wpdb->base_prefix ) )
continue;
Dort wird bei den Optionen geschaut, ob der Nutzer Rechte an dem Blog hat. Und dabei wird abgebrochen, wenn der Database Prefix irgendwo gefunden wird. Mein Database Prefix war ein leerer String, also "". Was ziemlich häufig im String vorkommt. Bzw nicht wirklich definiert sein dürfte. Verdammt.
Dies ist eine Änderung in WordPress 3.3 (siehe user.php von WordPress 3.2.1). Ich dachte erst an einen Bug, aber dann stolperte ich über diesen Bug-Report. Und letztlich die Aussage, dass kein Datenbank-Prefix scheinbar noch nie unterstützt wurde, dies aber lange Zeit nicht kontrolliert wurde (wohl bis Version 3.0). Leider wurde im Zuge der Upgrades nie so richtig darauf hingewiesen, es gab keine Fehlermeldungen oder sonst etwas. Nur bei Neuinstallationen gibt es ab Version 3.0 einen Hinweis. Meine Installation hat aber schon einige Jahre auf dem Buckel. Also - Prefix hinzufügen. Aber wie?
Google hilft, und so fand ich diese Anleitung, in der alle Schritte beschrieben wurden. Der zweite Schritt stellte mich bereits vor einige Probleme, wie ändert man bei 301 Tabellen den Namen? Geholfen hat hier TextWrangler. Zunächst habe ich nach Auswahl der WordPress Datenbank folgenden Befehl in MySQL ausgeführt:
show tables
Die damit erhaltene Liste habe ich in TextWrangler hineinkopiert. Der Befehl, um eine Tabelle umzubenennen lautet:
RENAME TABLE `DATENBANKNAME`.`TABELLENNAME` TO `DATENBANKNAME`.`NEUERTABELLENNAME` ;
Mit dem Reg-Exp-fähigem Suchen-Ersetzen-Befehl von TextWrangelr kann man dies nun für alle Zeilen machen. Man trage dafür in die Zeile Suchen:
(.+?)\r
und in die Zeile ersetzen:
RENAME TABLE `DATENBANKNAME`.`\1` TO `DATENBANKNAME`.`\1` ;
ein (Achtung! Neue Zeile steht da bewusst - sonst wird es sehr unübersichtlich!). Voila. Diese ganzen Befehle müssen wir nur noch MySQL geben, dann sind alle Tabellen richtig benannt.
Schritt 3 und 4 sind ebenfalls herausfordernd. Wenn man kein Prefix hat, kann man auch schwerlich danach suchen. Aber wie findet man jetzt die richtigen Werte? Man erstellt sich eine Testinstallation und schaut nach. Bei Schritt 3 müssen alle Optionstabellen geändert werden, also PREFIX_options und PREFIX_BLOGID_options jeweils in der Spalte option_name den Begriff user_roles in PREFIX_user_rolls. Schritt 4 bringt noch einmal mehr Spaß, dort müssen in der Tabelle PREFIX_user_meta alle Werte dashboard_quick_press_last_post_id, capabilities und user_level in der Spalte meta_key auf jeweils PREFIX_dashboard_quick_press_last_post_id, PREFIX_capabilities und PREFIX_user_level ändern. Das ist viel, viel manuelle Arbeit (oder ein Job für ein Script, was ich aber nicht erstellt habe).
Wenn alle Tabelleneinträge aktualisiert sind, kann man mit der WordPress-Seite wieder online gehen - und darüber fluchen, dass WordPress wirklich zu wenig Dokumentation hat, an sonst aber eine nette Software ist.



