Skip to content

Instantly share code, notes, and snippets.

@drazenbebic
Last active May 26, 2024 10:12
Show Gist options
  • Save drazenbebic/448f018ba2095626ecb9edc93980fd1c to your computer and use it in GitHub Desktop.
Save drazenbebic/448f018ba2095626ecb9edc93980fd1c to your computer and use it in GitHub Desktop.
Self-Hosted WordPress Plugin Updates (Server Plugin)
<?php
/*
Plugin Name: Self-Hosted WordPress Plugin Updates - Server
Description: Demo plugin showcasing a server which acts as a custom update server for other plugins.
Version: 1.0.0
Author: Drazen Bebic
Author URI: https://drazen.bebic.dev
Text Domain: shwpus
Domain Path: /languages
*/
/**
* Registers the routes needed by the plugins.
*
* @return void
*/
function shwpus_register_routes() {
register_rest_route(
'shwpus/v1',
'/version/(?P<plugin>[\w-]+)',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => 'shwpus_handle_plugin_version_request',
'permission_callback' => 'shwpus_handle_permission_callback',
'args' => array(
'plugin' => array(
'description' => 'The plugin slug, i.e. "my-plugin"',
'type' => 'string',
),
),
),
)
);
register_rest_route(
'shwpus/v1',
'/info/(?P<plugin>[\w-]+)',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => 'shwpus_handle_plugin_info_request',
'permission_callback' => 'shwpus_handle_permission_callback',
'args' => array(
'plugin' => array(
'description' => 'The plugin slug, i.e. "my-plugin"',
'type' => 'string',
),
),
),
)
);
register_rest_route(
'shwpus/v1',
'/package/(?P<plugin>[\w.-]+)',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => 'shwpus_handle_plugin_package_request',
'permission_callback' => 'shwpus_handle_permission_callback',
'args' => array(
'plugin' => array(
'description' => 'The plugin slug with the version, ending in .zip, i.e. "my-plugin.2.0.0.zip"',
'type' => 'string',
),
),
),
)
);
}
add_action( 'rest_api_init', 'shwpus_register_routes' );
/**
* @param WP_REST_Request $request
*
* @return true|WP_Error
*/
function shwpus_handle_permission_callback( $request ) {
$slug = $request->get_param( 'plugin' );
$license = $request->get_param( 'license' );
if ( $license !== 'XXX-YYY-ZZZ' ) {
return new WP_Error(
401,
'Invalid license',
array(
'slug' => $slug,
'license' => $license
)
);
}
return true;
}
/**
* Finds the latest version for a given plugin.
*
* @param WP_REST_Request $request
*
* @return void
*/
function shwpus_handle_plugin_version_request( $request ) {
// Retrieve the plugin slug from the
// request. Use this slug to find the
// latest version of your plugin.
$slug = $request->get_param( 'plugin' );
// This is hardcoded for demo purposes.
// Normally you would fetch this from
// your database or whatever other
// source of truth you have.
$version = '1.0.1';
header('Content-Type: text/html; charset=utf-8');
http_response_code( 200 );
echo $version;
die();
}
/**
* Fetches information about the latest version
* of the plugin with the given slug.
*
* @param WP_REST_Request $request
*
* @return void
*/
function shwpus_handle_plugin_info_request( $request ) {
$slug = $request->get_param( 'plugin' );
$version = '1.0.1';
// This data should be fetched dynamically
// but for demo purposes it is hardcoded.
$info = new stdClass();
$info->name = 'Self-Hosted WordPress Plugin Updates - Client';
$info->slug = 'self-hosted-plugin-updates-client';
$info->plugin_name = 'self-hosted-plugin-updates-client';
$info->new_version = $version;
$info->requires = '6.0';
$info->tested = '6.5.3';
$info->downloaded = 12540;
$info->last_updated = '2024-05-23';
$info->sections = array(
'description' => '
<h1>Self-Hosted WordPress Plugin Updates - Client</h1>
<p>
Demo plugin showcasing a client plugin
which updates from a custom update
server.
</p>
',
'changelog' => '
<h1>We did exactly 3 things!</h1>
<p>
You thought this is going to be a huge update.
But it\'s not. Sad face.
</p>
<ul>
<li>Added a cool new feature</li>
<li>Added another cool new feature</li>
<li>Fixed an old feature</li>
</ul>
',
// You can add more sections this way.
'new_tab' => '
<h1>Woah!</h1>
<p>We are so cool, we know how to add a new tab.</p>
',
);
$info->url = 'https://drazen.bebic.dev';
$info->download_link = get_rest_url( null, "/shwpus/v1/package/$slug.$version.zip" );
header('Content-Type: text/html; charset=utf-8');
http_response_code( 200 );
echo serialize( $info );
die();
}
/**
* @param WP_REST_Request $request
*
* @return void
*/
function shwpus_handle_plugin_package_request( $request ) {
// Contains the plugin name, version, and .zip
// extension. Example:
// self-hosted-plugin-updates-server.1.0.1.zip
$plugin = $request->get_param( 'plugin' );
// The packages are located in wp-content for
// demo purposes.
$file = WP_CONTENT_DIR . "/packages/$plugin";
if ( ! file_exists( $file ) ) {
header( 'Content-Type: text/plain' );
http_response_code( 404 );
echo "The file $file does not exist.";
die();
}
$file_size = filesize( $file );
header( 'Content-Type: application/octet-stream' );
header( "Content-Length: $file_size" );
header( "Content-Disposition: attachment; filename=\"$plugin\"" );
header( 'Access-Control-Allow-Origin: *' );
http_response_code( 200 );
readfile( $file );
die();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment