Last active
May 26, 2024 10:12
-
-
Save drazenbebic/448f018ba2095626ecb9edc93980fd1c to your computer and use it in GitHub Desktop.
Self-Hosted WordPress Plugin Updates (Server Plugin)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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