Einen Beitrag mit der REST API von WordPress veröffentlichen

Heute geht es darum, wie man einen Beitrag mit Hilfe der REST API von WordPress veröffentlicht. Außerdem wird kurz erklärt, mit welchem Plugin man am einfachsten und meiner Meinung nach am sichersten die Authentifizierung für den Request einrichtet – da WordPress das von Haus aus nicht für uns macht.

Vorab möchte ich sagen, dass ich die Dokumentation der REST API von WordPress nur ausreichend finde. Außerdem kann ich es überhaupt nicht nachvollziehen, warum man es keine Authentifizierung gibt und man alles mit Plugins lösen muss.

Authentifizierung

Um Beiträge mit Hilfe der REST API von WordPress auf anderen Blogs zu veröffentlichen, muss eine Authentifizierung her. Dafür gibt es einige Plugins, aber meiner Meinung nur ein Plugin, was wirklich sicher und vor allem einfach ist:

https://wordpress.org/plugins/application-passwords/

Application Passwords wird ab WordPress 5.6 nicht mehr benötigt, da es direkt in WordPress integriert wurde.

Das Plugin lässt sich direkt im WordPress Admin (wp-admin) herunterladen und installieren. Einmal installiert, ermöglicht uns das Plugin das Generieren von Passwörtern (damit nicht das eigenen Benutzerpasswort für den WordPress-Login verwendet werden muss). Das macht das Plugin zum Platzhirisch in Sachen einfacher Authentifizierung.

Um solch ein Passwort zu erhalten, wechselt man im WordPress Admin auf die Seite „Mein Profil“. Dort lässt sich jetzt ganz unten auf der Seite ein Passwort generieren. Mit diesem Passwort und dem Benutzernamen (für die Anmeldung), können wir dann jetzt Beiträge veröffentlichen.

Das Plugin muss immer auf der Zielseite installiert sein, damit es funktioniert. Gegebenenfalls muss dafür die .htaccess im Installationsordner von WordPress angepasst werden, damit die Authentifizierung überhaupt möglich ist. Dafür tragen wir dann folgendes in unsere .htaccess ein:

# BEGIN Pixelbart
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
</IfModule>
# END PixelbartCode-Sprache: HTML, XML (xml)

Der neue Beitrag

Jetzt geht es darum, dass wir unseren Beitrag mit der REST API von WordPress erstellen wollen. Den Code habe ich nur leicht kommentiert, aber so das ihn jeder versteht:

/* Request URL */
$url = 'https://meinedomain.de/wp-json/wp/v2/posts';

/**
 * Hier tragen wir jetzt den Benutzer ein, der den Beitrag veröffentlichen soll.
 * Als Passwort verwenden wir das generierte Passwort durch Applications Passwords.
 */
$user = '<benutzername>';
$pass = '<applications passwords>';

/* Request Header */
$headers = [
    'Authorization' => 'Basic ' . base64_encode($user . ':' . $pass),
    'cache-control' => 'no-cache',
];

/* Request Body, unser Beitrag */
$body = [
    'status' => 'draft',
    'type' => 'post',
    'title' => 'Meine Überschrift',
    'content' => 'Mein Content',
];

/* Request Arguments */
$args = [
    'headers' => $headers,
    'body' => $body,
    'method' => 'POST',
    'timeout' => 45,
    'redirection' => 5,
    'httpversion' => '1.0',
    'blocking' => true,
    'cookies' => [],
];

/* Unser Request */
$response = wp_remote_post($url, $args);

/* Falls der Request einen Fehler zurückgibt, wird der Fehler ausgegeben */
if (is_wp_error($response)) {
    print_r($response->get_error_message());
}
Code-Sprache: PHP (php)

So veröffentlichen wir mit Hilfe der REST API von WordPress einen Beitrag auf der Zielseite, auf der das Plugin Application Passwords installiert ist.

Beitragsbild hochladen

Tipp: Kopiere dir die Code-Beispiele direkt in deinen Code-Editor, damit sie einfacher zu lesen sind.

Mit der REST API von WordPress ist es aktuell leider noch nicht möglich Bilder direkt hochzuladen. Dafür muss man das Bild zuerst bei sich hochladen und dann die URL an die API übergeben.

Hier der gesamte Code zum Hochladen einer temporären Datei um die URL eines Bildes zu erhalten und die anschließende Übergabe an die REST API auf dem Zielserver:

URL des Bildes ist nicht vorhanden:

Wenn du das Bild erst mit einem Formular hochlädst und temporär speichern musst, um die URL des Bildes zu erhalten, dann verwendest du diesen Code:

/* Die Datei die wir hochladen wollen */
$file = $_FILES[0];

/* WordPress Upload-Verzeichnis */
$wp_upload_dir = wp_upload_dir();

/**
 * Verzeichnis in dem wir temporär die Datei ablegen:
 * /wp-content/uploads/temp/
 */
$upload_dir = $wp_upload_dir['basedir'] . '/temp/';
$upload_url = $wp_upload_dir['baseurl'] . '/temp/';

/* Hier prüfen wir, ob das Verzeichnis existiert und erstellen es ansonsten */
if (!is_dir($upload_dir)) {
    mkdir($upload_dir, 0755);
}

/* Hier legen wir die Dateiendung fest */
$extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));

/* Diese Endungen sind erlaubt */
$extensions = ['jpg', 'jpeg', 'png', 'gif', 'svg'];

if (in_array($extension, $extensions)) {

    /* Ein zufälliger Name für die Datei */
    $file_name = bin2hex(openssl_random_pseudo_bytes(14)) . '.' . $extension;

    $temp_file_path = $upload_dir . $file_name;

    /* Hier laden wir die temporäre Datei hoch */
    if (true !== move_uploaded_file($file['tmp_name'], $temp_file_path)) {
        wp_die('Die Datei konnte nicht hochgeladen werden.');
    }

    /* Die URL zur Datei */
    $temp_file_url = $upload_url . $file_name;

    /* Der Endpoint um das Bild auf dem Zielserver hochzuladen */
    $endpoint = 'https://meinedomain.de/wp-json/wp/v2/media/';

    $args = [
        'body' => file_get_contents($temp_file_url),
        'method' => 'POST',
        'headers' => [
            'Authorization' => 'Basic ' . base64_encode($user . ':' . $pass),
            'Content-Disposition' => 'attachment; filename="' . basename($temp_file_url) . '"',
        ],
    ];

    $response = wp_remote_post($endpoint, $args);
    $response = wp_remote_retrieve_body($response);
    $response = json_decode($response);

    if (!isset($response->id)) {
        wp_die('Das Bild konnte nicht auf dem Zielserver hochgeladen werden.');
    }

    /* Hier löschen wir die temporäre Datei */
    if (file_exists($temp_file_path)) {
        unlink($temp_file_path);
    }

    /* Hier haben wir jetzt unsere Thumbnail-ID */
    $thumbnail_id = $response->id;
}Code-Sprache: PHP (php)

URL des Bildes ist vorhanden:

Hast du das Bild bereits irgendwo hochgeladen und eine URL für das Bild, dann kannst du mit diesem Code fortfahren und musst nur noch die URL austauschen:

/* Die URL zur Datei */
$image_url = 'mein-bild.jpg';

/* Der Endpoint um das Bild auf dem Zielserver hochzuladen */
$endpoint = 'https://meinedomain.de/wp-json/wp/v2/media/';

$args = [
    'body' => file_get_contents($image_url),
    'method' => 'POST',
    'headers' => [
        'Authorization' => 'Basic ' . base64_encode($user . ':' . $pass),
        'Content-Disposition' => 'attachment; filename="' . basename($image_url) . '"',
    ],
];

$response = wp_remote_post($endpoint, $args);
$response = wp_remote_retrieve_body($response);
$response = json_decode($response);

if (!isset($response->id)) {
    wp_die('Das Bild konnte nicht auf dem Zielserver hochgeladen werden.');
}

/* Hier haben wir jetzt unsere Thumbnail-ID */
$thumbnail_id = $response->id;Code-Sprache: PHP (php)

Mit der $thumbnail_id können wir jetzt den Beitrag oben erstellen und die ID direkt weitergeben. Dafür ändern wir einfach im ersten Code-Beispiel den Body und passen ihn so an:

/* Request Body, unser Beitrag */
$body = [
    'status' => 'draft',
    'type' => 'post',
    'title' => 'Meine Überschrift',
    'content' => 'Mein Content',
    'featured_media' => $thumbnail_id, // unser Thumbnail
];Code-Sprache: PHP (php)

Also du beginnst zuerst mit dem Part womit du das Bild hochlädst und erstellst dann den Beitrag. Du kannst auch den Beitrag aktualisieren, sollte er bereits existieren und so die neue $thumbnail_id weitergeben.

Beitragsbild nachträglich festlegen

Um das Beitragsbild nachträglich an einen Beitrag zu heften, wird die ID des Beitrags benötigt. Ohne die ID des Beitrags, kannst du mit der REST API von WordPress keine Beiträge bearbeiten. Das Beispiel:

/* Die ID des Beitrags */
$post_id = 12345;

/* Der neue Endpunkt des Zielservers */
$endpoint = 'https://meinedomain.de/wp-json/wp/v2/posts/' . $post_id;

/* Request Header */
$headers = [
    'Authorization' => 'Basic ' . base64_encode($user . ':' . $pass),
    'cache-control' => 'no-cache',
];

/* Request Body, unser Beitrag */
$body = [
    'featured_media' => $thumbnail_id, // unser Thumbnail
];

/* Request Arguments */
$args = [
    'headers' => $headers,
    'body' => $body,
    'method' => 'POST',
    'timeout' => 45,
    'redirection' => 5,
    'httpversion' => '1.0',
    'blocking' => true,
    'cookies' => [],
];

/* Unser Request */
$response = wp_remote_post($url, $args);

/* Falls der Request einen Fehler zurückgibt, wird der Fehler ausgegeben */
if (is_wp_error($response)) {
    print_r($response->get_error_message());
}Code-Sprache: PHP (php)

So ist es möglich das Thumbnail nachträglich an einen Beitrag zu hängen. Der gesamte Part ab „Beitragsbild hochladen“ ist nachträglich eingefügt wurden, Weshalb die Reihenfolge zu Beginn nicht mehr ganz korrekt ist. Dafür findest du jetzt zum Schluss noch das Beispiel mit dem Aktualisieren eines Beitrags bzw. wie du das Thumbnail einem bestehenden Beitrag anhängst.

WordPress 5.6+

Mit WordPress 5.6 ist das Plugin Application Passwords nicht mehr notwendig, da WordPress die Funktionsweise von Application Passwords ab Version 5.6 direkt integriert hat.

Damit nicht jeder deiner Redakteure die Optionen zum Anlegen von API-Zugangsdaten sehen muss oder kann, kannst du folgendes in deiner functions.php platzieren:

/**
 * Ermöglicht die Vergabe von API-Zugangsdaten nur Benutzern mit den Rechten "manage_options".
 *
 * @param bool $available
 * @param WP_User $user
 * @return bool
 */
add_filter('wp_is_application_passwords_available_for_user', function ($available, $user) {
    if (!user_can($user, 'manage_options')) {
        $available = false;
    }

    return $available;
}, 10, 2);Code-Sprache: PHP (php)

Jetzt haben nur noch Benutzer mit den Rechten „manage_options“ die Möglichkeit sich API-Zugangsdaten generieren zu lassen, wenn sie ihr Profil bearbeiten.

Weiterführende Links: