How to host a WordPress plugin on my own server and provide updates?

admin2025-01-07  4

I am developing a game, and I am planning that, I will have partners, so they can run a game like mine.

For this, I developed a plugin, with some classes, and functions, to handle the game requests.

Because, this plugin is totally unusable for all the wordpress users, I want to send to my partners this plugin in an email in zipped format, but I want them to make able to upgrade plugin, if they need.

So, is it possible, to store the plugin on my own server, and force plugin to check updates from my site, not from the wp plugins directory?

I am developing a game, and I am planning that, I will have partners, so they can run a game like mine.

For this, I developed a plugin, with some classes, and functions, to handle the game requests.

Because, this plugin is totally unusable for all the wordpress users, I want to send to my partners this plugin in an email in zipped format, but I want them to make able to upgrade plugin, if they need.

So, is it possible, to store the plugin on my own server, and force plugin to check updates from my site, not from the wp plugins directory?

Share Improve this question edited Oct 29, 2022 at 9:43 Jesse Nickles 7357 silver badges19 bronze badges asked Mar 10, 2015 at 15:28 vaso123vaso123 1811 silver badge4 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 6

All Credit to the following post goes to Abid Omar. The full tutorial can be found on Tuts+: A Guide to the WordPress HTTP API: Automatic Plugin Updates

View Plugin On Github


The gist is to create a new class which will post an external file ( API ) and return plugin to download if it's out of date. The below assumes you're creating a plugin using the following code ( not in functions.php or mu-plugins directory ).

  1. wp_autoupdate.php will be an external file ( in your plugin ) holding the Auto Update class defined below
  2. update.php is an external "remote" file used to check for update, creates the API.

The below will be our initial setup.

add_action( 'init', 'wptuts_activate_au' );
function wptuts_activate_au()
{
    require_once ('wp_autoupdate.php');      // File which contains the Class below
    $wptuts_plugin_current_version = '1.0';
    $wptuts_plugin_remote_path     = 'http://localhost/update.php';
    $wptuts_plugin_slug            = plugin_basename(__FILE__);
    new wp_auto_update( $wptuts_plugin_current_version, $wptuts_plugin_remote_path, $wptuts_plugin_slug );
}

Autoupdate Class - wp_autoupdate.php

class wp_auto_update
{
    /**
     * The plugin current version
     * @var string
     */
    public $current_version;

    /**
     * The plugin remote update path
     * @var string
     */
    public $update_path;

    /**
     * Plugin Slug (plugin_directory/plugin_file.php)
     * @var string
     */
    public $plugin_slug;

    /**
     * Plugin name (plugin_file)
     * @var string
     */
    public $slug;

    /**
     * Initialize a new instance of the WordPress Auto-Update class
     * @param string $current_version
     * @param string $update_path
     * @param string $plugin_slug
     */
    function __construct( $current_version, $update_path, $plugin_slug )
    {
        // Set the class public variables
        $this->current_version = $current_version;
        $this->update_path     = $update_path;
        $this->plugin_slug     = $plugin_slug;
        list ($t1, $t2)        = explode('/', $plugin_slug);
        $this->slug            = str_replace( '.php', '', $t2 );

        // define the alternative API for updating checking
        add_filter( 'pre_set_site_transient_update_plugins', array( &$this, 'check_update' ) );

        // Define the alternative response for information checking
        add_filter('plugins_api', array(&$this, 'check_info'), 10, 3);
    }

    /**
     * Add our self-hosted autoupdate plugin to the filter transient
     *
     * @param $transient
     * @return object $ transient
     */
    public function check_update( $transient )
    {
        if( empty( $transient->checked ) ) {
            return $transient;
        }

        // Get the remote version
        $remote_version = $this->getRemote_version();

        // If a newer version is available, add the update
        if ( version_compare( $this->current_version, $remote_version, '<' ) ) {
            $obj          = new stdClass();
            $obj->slug    = $this->slug;
            $obj->new_version = $remote_version;
            $obj->url     = $this->update_path;
            $obj->package = $this->update_path;
            $transient->response[$this->plugin_slug] = $obj;
        }
        var_dump( $transient );
        return $transient;
    }

    /**
     * Add our self-hosted description to the filter
     *
     * @param boolean $false
     * @param array $action
     * @param object $arg
     * @return bool|object
     */
    public function check_info( $false, $action, $arg )
    {
        if( $arg->slug === $this->slug ) {
            $information = $this->getRemote_information();
            return $information;
        }
        return false;
    }

    /**
     * Return the remote version
     * @return string $remote_version
     */
    public function getRemote_version()
    {
        $request = wp_remote_post( $this->update_path, array( 'body' => array( 'action' => 'version' ) ) );
        if( ! is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) === 200 ) {
            return $request['body'];
        }
        return false;
    }

    /**
     * Get information about the remote version
     * @return bool|object
     */
    public function getRemote_information()
    {
        $request = wp_remote_post( $this->update_path, array( 'body' => array( 'action' => 'info' ) ) );
        if( ! is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) === 200) {
            return unserialize( $request['body'] );
        }
        return false;
    }

    /**
     * Return the status of the plugin licensing
     * @return boolean $remote_license
     */
    public function getRemote_license()
    {
        $request = wp_remote_post( $this->update_path, array( 'body' => array( 'action' => 'license' ) ) );
        if( ! is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) === 200 ) {
            return $request['body'];
        }
        return false;
    }
}

Remote ( External ) Update API - update.php

if( isset( $_POST['action'] ) ) {
  switch( $_POST['action'] ) {
    case 'version':
      echo '1.1';
        break;

    case 'info':
      $obj              = new stdClass();
      $obj->slug        = 'plugin.php';
      $obj->plugin_name = 'plugin.php';
      $obj->new_version = '1.1';
      $obj->requires    = '3.0';
      $obj->tested      = '3.3.1';
      $obj->downloaded  = 12540;
      $obj->last_updated = '2012-01-12';
      $obj->sections    = array(
        'description'     => 'The new version of the Auto-Update plugin',
        'another_section' => 'This is another section',
        'changelog'       => 'Some new features'
      );
      $obj->download_link = 'http://localhost/update.php';
      echo serialize( $obj );

    case 'license':
      echo 'false';
        break;
  }
} else {
    header( 'Cache-Control: public' );
    header( 'Content-Description: File Transfer' );
    header( 'Content-Type: application/zip' );
    readfile( 'update.zip' );
}

update.php will keep the most up-to-date information on your plugin. Using the init function you would pass the currently installed version so that it can post it to update.php and check against the current it has. There's some room for improvement on the code to make it more streamlined but I used this to do exactly ( sorta ) what you're trying to do so it's a good jumping point.

Yes, it is possible to host your own plugin and have the plugin check for updates from your server. You need to put some custom code in your plugin to tell it to check with your server for updates. There are some frameworks to help you do that, try these:

  • Plugin Update Checker

  • Github Plugin Updater

I have returned to this "problem" several times over the years, and a few of the projects on GitHub shared in the answers here are fantastic, although some of them appear dead now. There have also been some WooCommerce extensions that have attempted to solve this problem while also providing a billing solution, but they were kinda janky and difficult to maintain in my experience.

However one other fantastic solution is Andy Fragen's Git Updater. Instead of having to host your plugin ZIP files on your (unreliable) self-hosted server and/or hack your plugins and themes to add more files and dependencies etc, you simply add a simple one-line "header" inside your style.css file for WordPress themes or inside your plugin.php file for plugins. Literally, that's all that's required.

Here's an example:

https://github.com/littlebizzy/hovercraft/blob/master/style.css

GitHub Theme URI: littlebizzy/hovercraft

Andy's approach is one of the cleanest I've seen, and saved me tons of time and headache trying to find a simple solution for updating my WordPress extensions.

It works out-of-the-box for public repos, and has support for API keys for private repos. So you could literally just have like a PayPal or Patreon subscription where customers pay for access to whichever code they want and then you provide them the API key to those private repos on GitHub or GitLab, etc. You don't need to manage any ZIP files or billing whatsover.

And the implementation only takes around 30 seconds for most projects.

I built an other solution to self-host plugins directly from Github and deliver updates. More details you can found at this post: https://eduardovillao.me/how-to-self-host-wordpress-plugins-on-github-and-deliver-updates/

In summary you will need just:

  1. This Github action: https://github.com/eduardovillao/wp-self-host-updater-generator
  2. Add this file in your plugin: https://github.com/eduardovillao/wp-self-host-updater-checker

Good lock with your projects!

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1736254549a215.html

最新回复(0)