Websupporter

Vor allem über WordPress.

Automatisches Plugin Update auch außerhalb von wordpress.org

Nicht immer platziert man sein Plugin im WordPress Repository. Zum Beispiel, wenn man ein Premium Plugin entwickelt hat, welches man verkaufen möchte. Nun stellt sich natürlich die Frage, wie man seinen Kunden in diesem Fall eine möglichst unkomplizierte Aktualisierungs-Routine zur Verfügung stellen kann.

WordPress verfügt ja für das Repository schon über eine Update Logik und es wäre schön, wenn man sich in diese einhaken kann, um auch das eigene Premium Plugin automatisch aktualisieren zu lassen.

Plugins aktualisieren
In der Plugin Übersicht von WordPress sieht man, welche Plugins aktualisiert werden müssen.

In dem obigen Screenshot sehen wir zwei Plugins, welche aktualisiert werden müssen: Das allseits bekannte Akismet, welches im WordPress Repository zu finden ist, sowie ein Plugin Namens „Autoupdate Tester“. Normalerweise erhält WordPress die Informationen, welches Plugin veraltet ist aus dem Repository. Doch unser Plugin Autoupdate Tester ist dort nicht zu finden. In diesem Beitrag werde ich Schritt für Schritt erklären, wie man für ein Plugin, welches nicht im Repository zu finden ist, eine Updateroutine schreiben kann, die sich nahtlos in WordPress einpasst.

Einhaken, wenn die Aktualität von Plugins geprüft wird

Im ersten Schritt müssen wir herausfinden, wie und wann WordPress prüft, ob ein Plugin veraltet ist. Dies geschieht in der Funktion wp_update_plugins() (wp-includes/update.php). Diese Datei schickt Informationen über alle installierten Plugins an die WordPress API, konkret an http://api.wordpress.org/plugins/update-check/1.1/, und erhält von dort die Information, welches Plugin veraltet ist. Diese Informationen werden dabei aus dem Repository bezogen. Da unser Premium Plugin dort nicht zu finden ist kann aus diesem auch keine Information über den Versionsstatus kommen.

Die Informationen, welche Plugins aktualisiert werden müssen und so weiter, legt WordPress am Ende schließlich als Transient ab. Mit Hilfe der Transient API kann man Daten für eine gewisse Zeit in der WordPress Datenbank speichern und so den Server entlasten. Das ist für uns insoweit von Interesse, als wir uns genau an dieser Stelle einhaken können, denn die Transient API verfügt über ihre ganz eigenen Filterhooks. So speichert wp_update_plugins() über die Funktion set_site_transient() die Update-Informationen im Transient 'update_plugins'. Mit dem Filter 'pre_set_site_transient_update_plugins' können wir diese Informationen nun abändern, bevor sie in der Datenbank abgelegt werden.

Die Plugin-Update Information

Der Transient ist ein std Class Objekt, welches unter anderem den Array response enthält. Dieser Array enthält alle veralteten Plugins und in diesen Array möchten auch wir unser Plugin einschreiben, sollte es veraltet sein. Der Array-Schlüssel ist dabei der Plugin Slug, welcher unter Verwendung von plugin_basename() ermittelt werden kann. Hinter diesem Schlüssel verbirgt sich nun erneut ein std Class Objekt mit folgenden Informationen:

plugin, slug
Diese beiden Werte enthalten den Plugin Slug, welcher über plugin_basename() ermittelt werden kann.
new_version
Hier wird die neue Versionsnummer abgelegt.
url
Hier wird die URL zum Plugin hinterlegt.
package
Das ist die zentrale Information! Hier wird die URL zum aktuellen Plugin-ZIP hinterlegt!

Einhaken, Versionsprüfung, Ablegen

Mit diesen Informationen können wir unser kostenpflichtiges Plugin schon in den Update Prozess einhaken und WordPress prüfen lassen, ob das Plugin veraltet ist.

Embed from pastebin.com

Click the button below to load the content from pastebin.com.


Always allow pastebin.com

Dazu haken uns in den Filter 'pre_set_site_transient_update_plugins' ein. Natürlich müssen wir irgendwo hinterlegt haben, welche Versionsnummer derzeit aktuell ist. Mit wp_remote_get() greifen wir diese Information deshalb ab (Wer am Unterschied zwischen wp_remote_get() und wp_safe_remote_get() interessiert ist, kann dies in diesem Blogbeitrag erfahren.). Im Anschluss nutzen wir die Funktion get_plugin_data(), um die Daten des aktuell installierten Plugins zu erfahren. Sollte die Versionsnummer des aktuellen Plugins kleiner sein als die Versionsnummer, welche wir über wp_remote_get() erhalten haben, fügen wir nun unser Plugin in den Transient mit ein.

Die plugins_api(), beziehungsweise: Noch ein letzter Schritt

Wenn unser Plugin, dessen aktuelle Version wir außerhalb des Repositories hosten, veraltet ist wird WordPress uns dies nun anzeigen. Das genügt allerdings noch nicht. Uns fehlen noch Informationen wie die Kompatibilität zur aktuellen WordPress Version, Changelog und ähnliches. Diese werden von der Funktion plugins_api() (wp-admin/includes/plugin-install.php) zur Verfügung gestellt. Wie schon zuvor wird dabei auf Informationen aus dem WordPress Repository zurückgegriffen. Nun wollen wir diese Informationen im gewohnten WordPress Interface für unser Plugin zur Verfügung stellen. Auch diese Funktion ermöglicht es uns, mit Hilfe eines Filters den Output zu übernehmen: 'plugins_api'.

Weitere Informationen über das Update in der WP Thickbox
Weitere Informationen über das Update in der WP Thickbox

Auch in diesem Fall müssen wir über zwei Seiten vorgehen. Auf der Serverseite brauchen wir eine Datei, welche die Informationen zur Verfügung stellt. Dabei handelt es sich um ein std Class Objekt. Und clientseitig, also in unserem Plugin, müssen wir uns in den Filter einhaken und die Informationen mit wp_remote_get() abrufen.

Serverseitig

Schauen wir uns zunächst die Informationen an, welche unser Remote Server übergeben muss:

Embed from pastebin.com

Click the button below to load the content from pastebin.com.


Always allow pastebin.com

Wie sie sehen übermitteln wir einfach ein serialisiertes stdClass Objekt, deren Inhalt sich eigentlich selbst erklärt. Es wird nochmals die aktuelle Version übergeben, bis zu welcher WordPress Version diese getestet wurde, wann das Update stattgefunden hat und wir erhalten auch die unterschiedlichen Sektionen, welche in der Thickbox, welche wir öffnen, wenn wir auf „weitere Informationen“ klicken, erscheinen.

Clientseitig

Nun müssen wir diese Informationen clientseitig im entsprechenden Filter entgegennehmen:

Embed from pastebin.com

Click the button below to load the content from pastebin.com.


Always allow pastebin.com

Wir fragen also zunächst ab, ob plugins_api() im aktuellen Fall für unser Plugin ausgeführt wird. Ist dies der Fall setzen wir einen Request ab, fordern die Daten von unserem Remote Server an und übergeben diese. So haben wir nun auch diese Informationen zur Hand und stellen Sie dem WordPress Administrator zur Verfügung.

Schluß

Mit Hilfe der Filter 'pre_set_site_transient_update_plugins' und 'plugins_api' können wir uns schnell und einfach in die WordPress Plugin Update Routine einklinken und auch Plugins, welche außerhalb des Repositories gehostet werden updaten. Dieser Blogbeitrag wäre nicht möglich gewesen ohne diese schöne Klasse, welche eigentlich alles notwendige nochmal etwas eleganter zusammenfasst. Zwei Tage nachdem Sergej Müller sich aus der Community verabschiedet hat, sieht man mal wo er doch noch immer anzutreffen ist. So gehört er zu den Contributern der wp_autoupdate.php. Vielen Dank!

Über den Autoren

Seine erste Webseite hat David Remer 1998 in HTML verfasst. Wenig später war er fasziniert von DHTML und JavaScript. Nach jahrelanger Freelancerei arbeitete er zunächst für Inpsyde und ist heute Entwickler bei Automattic. Außerdem hat er das Buch "WordPress für Entwickler" verfasst.

Kommentare

    1. Hi Martin,
      vielen Dank 🙂

      In Bezug auf Themes läuft das eigentlich analog. Statt einer wp_update_plugins() gibt es in der wp-includes/updates.php eine wp_update_themes(). Das Ergebnis der Abfrage wird im Transient 'update_themes' abgelegt. Auch dort kannst Du Dich wieder einhaken…

      Aber ich müsste da nochmal näher in die Details gucken. Hmm… Vielleicht ein weiterer Blogpost 😀

  1. Hallo David,

    danke für Deinen Artikel. Sehr ausführlich und informativ. Ist Dein Workaround auf die aktuellen WordPress Version immer noch anwendbar, oder gilt es dabei speziell etwas zu beachten?

    Grüsse Christian.

    1. Hi Christian,
      entschuldige die späte Antwort. Weihnachten erst wieder dazu gekommen, ein bisschen ringsherum zu putzen. Die Methode müsste eigentlich nach wie vor funktionieren.

      Beste Grüße,
      David.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.