WordPress bietet uns über den Punkt DashboardAktualisierungen eine ziemlich komfortable Möglichkeit, Updates für Core, Themes, Plugins und Übersetzungen einzuspielen.

Manchmal ist diese Möglichkeit aber nicht genug – ich arbeite beispielsweise gerade an einem Projekt, das Updates programmatisch anstoßen muss. Dabei wäre ein naheligender Weg die Nutzung von WP-CLI, der Weg ist mir allerdings versperrt, und so habe ich mich näher mit den PHP-Funktionen beschäftigt, die sich um Updates kümmern.

Auf neue Updates prüfen

Wenn wir die Updates anstoßen, möchten wir die zu diesem Zeitpunkt verfügbaren Updates installieren. Auf der Backend-Seite zum Aktualisieren von WordPress gibt es den Button »Erneut überprüfen«, mit dem eine Prüfung auf Updates erzwungen werden kann.

Dieses Verhalten möchten wir nachstellen, da es sonst vorkommen kann, dass kürzlich veröffentlichte Updates noch nicht in den Transients in der Datenbank gespeichert sind, die WordPress für die Updates nutzt.

Dabei helfen uns die zwei Funktionen im folgenden Code-Block:

.wp-block-code {
border: 0;
padding: 0;
}

.wp-block-code > div {
overflow: auto;
}

.shcb-language {
border: 0;
clip: rect(1px, 1px, 1px, 1px);
-webkit-clip-path: inset(50%);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
word-wrap: normal;
word-break: normal;
}

.hljs {
box-sizing: border-box;
}

.hljs.shcb-code-table {
display: table;
width: 100%;
}

.hljs.shcb-code-table > .shcb-loc {
color: inherit;
display: table-row;
width: 100%;
}

.hljs.shcb-code-table .shcb-loc > span {
display: table-cell;
}

.wp-block-code code.hljs:not(.shcb-wrap-lines) {
white-space: pre;
}

.wp-block-code code.hljs.shcb-wrap-lines {
white-space: pre-wrap;
}

.hljs.shcb-line-numbers {
border-spacing: 0;
counter-reset: line;
}

.hljs.shcb-line-numbers > .shcb-loc {
counter-increment: line;
}

.hljs.shcb-line-numbers .shcb-loc > span {
padding-left: 0.75em;
}

.hljs.shcb-line-numbers .shcb-loc::before {
border-right: 1px solid #ddd;
content: counter(line);
display: table-cell;
padding: 0 0.75em;
text-align: right;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
white-space: nowrap;
width: 1%;
}
// Update-Checks für Plugins und Themes.
wp_update_plugins();
wp_update_themes();
Code-Sprache: PHP (php)

Nachdem dieser Code ausgeführt wurde, sollten die Update-Transients für Plugins und Themes auf dem neuesten Stand sein und wir können die Updates installieren.

Updates installieren

Zum Installieren der Updates benötigen wir ein paar Funktionen aus Dateien, die nicht unbedingt standardmäßig eingebunden werden, wir müssen also selbst sicherstellen, dass sie geladen sind:

include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
include_once ABSPATH . 'wp-admin/includes/file.php';
include_once ABSPATH . 'wp-admin/includes/misc.php';
Code-Sprache: PHP (php)

Jetzt holen wir uns nacheinander die verfügbaren Updates für Plugins, Themes und Core und installieren sie.

// Plugin-Updates ausführen.
$update_plugins = get_site_transient( 'update_plugins' );
if ( ! empty( $update_plugins->response ) && count( $update_plugins->response ) > 0 ) {
$plugin_upgrader = new Plugin_Upgrader();
$upgraded_plugins = $plugin_upgrader->bulk_upgrade( $update_plugins );
}

// Theme-Updates ausführen.
$update_themes = get_site_transient( 'update_themes' );
if ( ! empty( $update_themes->response ) && count( $update_themes->response ) > 0 ) {
$theme_upgrader = new Theme_Upgrader();
$upgraded_themes = $theme_upgrader->bulk_upgrade( $update_themes );
}

// Core-Updates ausführen.
include_once ABSPATH . 'wp-admin/includes/update.php';
wp_version_check();
$update_core = get_core_updates();
// Prüfen, ob etwas anderes als `latest` vorhanden ist.
foreach ( $update_core as $tmp ) {
if ( $tmp->response !== 'latest' ) {
if ( $tmp->response === 'upgrade' ) {
if ( $tmp->locale !== get_locale() ) {
continue;
}
}
$core_upgrader = new Core_Upgrader();
$result = $core_upgrader->upgrade(
$tmp,
[
'attempt_rollback' => true,
]
);
break;
}
}

// Übersetzungen aktualisieren.
$translation_upgrader = new Language_Pack_Upgrader();
$language_updates = wp_get_translation_updates();
if ( $language_updates ) {
$translation_upgrader->bulk_upgrade( $language_updates );
}
Code-Sprache: PHP (php)

Theme- und Plugin-Updates

Der Update-Prozess für Plugins und Themes ähnelt sich sehr – wir lesen den Inhalt der Update-Transients aus und übergeben den Inhalt an die bulk_upgrade-Methode eines Upgrader-Objekts.

Core-Updates

Bei Core-Updates ist es etwas komplexer. Zunächst binden wir eine weitere Datei ein, um auf benötigte Funktionen zugreifen zu können. Dann starten wir einen Version-Check und holen uns mit get_core_updates() verfügbare Core-Updates. Die Funktion liefert ein Array von Objekten zurück, jedes Objekt beinhaltet die Informationen für ein verfügbares WordPress-Update.

Wenn wir die neueste Version von WordPress nutzen, ist diese trotzdem in dem Ergebnis-Array vorhanden – der Wert für die response-Eigenschaft des Objekts ist in dem Fall latest, weshalb wir diesen Eintrag ignorieren.

Ebenfalls zusätzlich kann in dem Ergebnis-Array die englische Version des Updates vorliegen. Wenn wir sichergehen wollen, dass bei einem Update auf eine stabile Version (der Wert für response ist upgrade) auf die Locale der Website aktualisiert wird, können wir den Wert von $tmp->locale mit get_locale() vergleichen.

Für den Fall, dass eine Entwicklungsversion von WordPress eingesetzt wird, ist der Wert von $tmp->response development und die Locale en_US, weshalb dort ein Test auf die Sprache keinen Sinn ergibt.

Der Core_Upgrader erwartet in seiner upgrade()-Methode als ersten Parameter das Objekt für das Update, das get_core_updates() zurückgibt. Als zweiten Parameter geben wir an, dass ein Rollback versucht werden soll, wenn etwas schief geht.

Übersetzungs-Updates

Übersetzungen werden nach Theme-und Plugin-Updates automatisch aktualisiert. Wenn kein Theme oder Plugin aktualisiert wurde, kann das Update aber über den Language_Pack_Upgrader auch manuell angestoßen werden. Bei den Übersetzungen habe ich allerdings noch nicht herausgefunden, wie eine Prüfung auf neue Übersetzungen erzwungen werden kann.

Dieses ganze Vorgehen ist natürlich eher etwas für Sonderfälle – wie gesagt, wenn Updates programmatisch installiert werden sollen, wäre WP-CLI normalerweise das Mittel der Wahl. Wenn WP-CLI allerdings nicht zur Verfügung steht, muss sich direkt über die PHP-Funktionen geholfen werden.