WordPress Upgrade-Mechanismus mit eigenen URLs

Seit WordPress die automatischen Aktualisierung anbietet habe ich mich gefragt, ob es irgendwie möglich ist Plugins auch von einem anderen Ort als der offiziellen Plugin-DB nachzuladen. Hintergrund: ich habe einige selbst geschriebene Plugins, die ich auf mehreren Seiten einsetze, die ich aber nicht in die Plugin-DB hochladen möchte, weil sie zu speziell (oder trivial) sind. Für solche Fälle wäre es schön Plugins auch von einem eigenen Webspace nachladen zu können. Prinzipiell lässt sich das mit ein paar Dutzend Zeilen PHP bewerkstelligen. Da ich aber weiß das in WordPress die Funktionalität schon vorhanden (und gut getestet) ist, machte ich mich auf die Suche.

In der Datei „wp-admin/includes/class-wp-upgrader.php“ wurde ich fündig. Hier gibt es die Basisklasse „WP_Upgrader“ und die von abgeleiteten Klassen für Core, Themes und Plugins. Relevant für die Plugin-Updates ist dabei die Funktion „Plugin_Upgrader->upgrade()“ Die Steuerung des Update-Prozesses übernimmt der Code aus der Datei „wp-admin/update.php„.

Democode

Aus den Informationen dieser Dateien habe ich mir folgenden Code zusammengestellt, den ich der Einfachheit halber in die functions.php meines Themes eingebunden habe. Der Code erstellt einen Menüpunkt „Einstellungen > PersonalUpdate“ der, sobald gedrückt, das Plugin Aksimet neu herunterläd, installiert und ggf. wieder aktiviert. In dem Beispielcode habe ich die offizielle URL des Plugins genutzt, es lässt sich aber jede beliebige andere URL einfügen.

<?php
class PersonalUpdate {

    function __construct() {
        add_action('admin_menu', array(&$this,'admin_menu'));
    }

    function admin_menu() {
        add_options_page('PersonalUpdate', 'PersonalUpdate', 'update_plugins', 'personal-update-handle', array(&$this,'admin_submenu'));
    }

    function admin_submenu() {
        $_array = array(
            'package' => 'http://downloads.wordpress.org/plugin/akismet.2.5.0.zip',
            'destination' => WP_PLUGIN_DIR,
            'clear_destination' => TRUE,
            'clear_working' => TRUE,
            'hook_extra' => array(
                'plugin' => 'akismet/akismet.php'
            )
        );

        $result = $this->run_update($_array);
        //...
    }

    function run_update($_array) {
        if(!current_user_can('update_plugins')) {
            wp_die( __('You do not have sufficient permissions to access this page.') );
        }

        include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
        $upgrader = new Plugin_Upgrader( null );

        $is_active = is_plugin_active($_array['hook_extra']['plugin']);

        add_filter('upgrader_pre_install', array(&$upgrader, 'deactivate_plugin_before_upgrade'), 10, 2);
        add_filter('upgrader_clear_destination', array(&$upgrader, 'delete_old_plugin'), 10, 4);

        $upgrader->run($_array);

        // Cleanup our hooks, incase something else does a upgrade on this connection.
        remove_filter('upgrader_pre_install', array(&$upgrader, 'deactivate_plugin_before_upgrade'));
        remove_filter('upgrader_clear_destination', array(&$upgrader, 'delete_old_plugin'));

        if( !$upgrader->result || is_wp_error($upgrader->result) ) {
            return $upgrader->result;
        } else {
            if($is_active) {
                activate_plugin($_array['hook_extra']['plugin']);//reactivate
            }
        }
        return $upgrader->result;
    }
}
$MyPersonalUpdate = new PersonalUpdate();

Die eigentliche Hauptarbeit wird durch den Code in Zeile 39 bewerkstelligt. Hier wird ein das Array mit Plugin-Informationen an das Upgrade-Objekt übergeben, welches sich dann um den Rest kümmert. Das Array wird in diesem Fall ab Ziel 12 zusammengebaut. Die wichtigsten Werte sind hierbei „package“ (Zeile 13) mit der URL von der die ZIP-Datei geladen werden soll, und „hook_extra > plugin“ in dem der Pfad zur Hauptdatei des Plugins steht.

Ausgabe des Demo-Codes

Wie weiter?

Um aus der Demo-Funktionalität einen praktischen nutzen zu ziehen, könnte man nun eine Erweiterung schreiben, die die gewünschten URLs und Plugin-Pfade zu mehreren Plugins speichert. Per Knopfdruck könnten diese dann jederzeit von einem eigenen Server aktualisiert werden.

Getestet in WordPress 3.0.3