senäh

17senäh und so…

Wordpress Logo

PHP, Server & Config, WordPress
09. Aug 2012
Kommentare: 0

Blogpost absenden und ein notwendiger Hack

Kategorien: PHP, Server & Config, WordPress | 09. Aug 2012 | Kommentare: 0

Serie: Effizienteres Bloggen mit WordPress dank XML-RPC

Wir sind fast am Ziel. Wir haben Metadaten extrahiert, Markup ersetzt und Bilder hochgeladen. Alles, was jetzt noch nötig ist, ist das Hochladen des eigentlichen Blogposts. An sich ein leichtes, wie ihr sehen werdet. Wenn wir jedoch tatsächlich das Verhalten von WordPress in Bezug auf die Mediendaten komplett mimen und uns die Verwaltung über die Mediathek erhalten wollen, müssen wir einen kleinen Hack implementieren. WordPress hat bei seiner XML-RPC-Schnittstelle nämlich ein weig geschlampt. Aber dazu später mehr.

Neue Methode: createPost

Unsere index.php sollte fertig so aussehen:

1
2
3
4
5
6
7
8
<?php
require_once 'inc/EnnoAutoPost.php';
$htmlString = $_SERVER['KMVAR_temp'];
$obj = new EnnoAutoPost($htmlString);
$obj->setMetadata();
$obj->replaceCode();
$obj->replaceImageMarkup();
echo $obj->createPost();

Die createPost-Methode müssen wir in unserer Klasse (in meinem Fall EnnoAutoPost) noch anlegen.

Warum geben wir das Ergebnis dieses Aufrufs mit echo aus? Weil wir hier die ID des erstellten Posts an Keyboard Maestro zurückgeben. Dadurch können wir den Artikel direkt im WordPress-Backend aufrufen sobald er einmal hochgeladen ist. Aber das werde ich erst im nächsten Teil abdecken.

Zurück zu unserer Methode createPost(). Wie sieht die Implementierung im Detail aus?

1
2
3
4
5
6
7
8
9
10
11
12
public function createPost()
{
    $user = $this->_user;
    $pass = $this->_pass;
    $this->_postData['post_content'] = $this->_content;
    $this->_postData['comment_status'] = 'open';

    if (!$this->_client->query('wp.newPost', 1, $user, $pass, $this->_postData))
        $this->_displayError('creating post');

    return $this->_client->getResponse();
}

Nicht weiter tricky. Wir holen uns Benutzernamen und Passwort. Außerdem setzen wir den HTML-Content, der übertragen werden soll. Wichtig ist, dass wir die Kommentare explizit erlauben, da WordPress hier standardmäßig davon ausgeht, dass wir keine Kommentare unter unserem Blogpost haben wollen.

Anschließend wird der XML-RPC-Request verschickt. Das Ergebnis ist die erzeugte ID des Blogposts, welche als Ergebnis der Methode zurückgegeben wird.

Das war’s auch schon. Der Blogpost liegt nun im WP-Backend als Entwurf vor, um von uns perfektioniert zu werden (Artikelbild festlegen, korrekturlesen, schauen, ob im Layout nichts zerhackt wird, etc.).

Notwendiger Hack für die Mediathek-Kompatibilität

Ich hatte am Start der Serie mal erwähnt, dass ich zwar außerhalb des WP-Backends schreiben möchte, jedoch letztenendes alles genau so gespeichert werden soll, wie WordPress es selbst generieren würde. Das gilt für das HTML-Markup der Bilder genauso wie für deren Speicherung in der Datenbank. Und hier müssen wir nachrüsten.

Update: da ich mich doch mal dazu durchgerungen habe, den WordPress-Devs einen Bug Report da zu lassen, wird der folgende Hack ab WordPress 3.5 nicht mehr nötig sein. Hallelujah ;) Ihr könnt also weiter zum Abschnitt What’s next springen.

Hinweis: wir müssen etwas im Source von WordPress editieren. Das bedeutet diese Änderung wird vermutlich mit jedem Update erneut nötig sein. Ich hatte bis jetzt keine Zeit (lies: ich war zu faul) einen entsprechenden Bug beim Dev-Team zu melden. Darum: den Hack müsst ihr nur nachempfinden, wenn ihr ähnlich perfektionistisch veranlagt seid wie ich und eure Bilder zwingend auch über die Mediathek im WordPress-Backend verarbeiten können wollt. Wofür auch immer.

Die Symptome

In der Mediathek wird das hochgeladene Bild nicht angezeigt. Zwar geht es in die angezeigte Anzahl der Bilder mit ein, jedoch ist es nirgendwo zu finden.

Die Ursache

Wie bereits angekündigt müssen wir im Source-Code der WordPress-PHP-Dateien Änderungen vornehmen. Nicht, weil unsere Erwartungen zu hoch sind, sondern weil das Dev-Team ein klein wenig geschlampt hat. Das Datenbank-Design von WordPress ist so ausgelegt, dass auch Bilder eigene Posts sind, von daher einen Eintrag in der wp_posts Tabelle haben. Beim Hochladen der Bilder über unser Skript bekommen Bilder den post_status ‘draft’. So weit, so gut.

Sobald Bilder in einen Blogpost eingefügt werden, sind sie deren Kinderelemente. Dafür gibt es die Spalte post_parent. Hier muss die ID unseres Blogposts hin. Das Coole dabei: das macht WordPress für uns. Sobald wir über unser Skript den fertigen Artikel hochladen, durchsucht WordPress das Markup auf Bilder. Alle Bilder, die bisher nicht verknüpft wurden, erhalten nun die ID des Blogposts als post_parent. Läuft.

Was die Devs jedoch vergessen haben: der Status des Bildes muss von ‘draft’ auf ‘inherit’ gesetzt werden. Genau das ist, was wir nun erledigen müssen.

Die Lösung

Also, ab in den Source-Code. Sucht im Ordner wp-includes die Datei class-wp-xmlrpc-server.php. Dort gibt es eine Funktion namens attach_uploads. Hier müssen wir lediglich den post_status hinzufügen.

1
2
3
4
5
6
7
8
9
10
11
12
function attach_uploads( $post_ID, $post_content ) {
    global $wpdb;

    // find any unattached files
    $attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '0' AND post_type = 'attachment'" );
    if ( is_array( $attachments ) ) {
        foreach ( $attachments as $file ) {
            if ( strpos( $post_content, $file->guid ) !== false )
                $wpdb->update($wpdb->posts, array('post_parent' => $post_ID, 'post_status' => 'inherit'), array('ID' => $file->ID) );
        }
    }
}

via

What’s next?

3 Sachen:

  • Account-Switch und automatisierter Aufruf des Artikels im WordPress-Backend über Keyboard Maestro
  • passende Daten in eine Config-Klasse auslagern
  • Source bei GitHub

Bitte freuen Sie sich jetzt ;)

Autor: Enno

Ich bin Enno. PHP ist mein Ding, aber auch alles Neue rund um die Themen HTML5, CSS3 & Co finde ich interessant. Ich mag es Leuten zu helfen und mein Wissen weiterzugeben. Sollte dir mein Beitrag gefallen haben, lass doch nen Kommentar da oder benutze einen der Social Buttons, um deinen Dank auszudrücken ;)

Kommentare (0)

Für diesen Beitrag wurden Kommentare deaktiviert.