Initial commit.

This commit is contained in:
dcooperdalrymple
2021-02-19 16:43:21 -06:00
commit 22f6c8188e
206 changed files with 33366 additions and 0 deletions

View File

@@ -0,0 +1,563 @@
<?php
/**
* WP Package Updater
* Plugins and themes update library to enable with WP Plugin Update Server
*
* @author Alexandre Froger
* @version 1.4.0
* @see https://github.com/froger-me/wp-package-updater
* @copyright Alexandre Froger - https://www.froger.me
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/* ================================================================================================ */
/* WP Package Updater */
/* ================================================================================================ */
/**
* Copy/paste this section to your main plugin file or theme's functions.php and uncomment the sections below
* where appropriate to enable updates with WP Plugin Update Server.
*
* WARNING - READ FIRST:
* Before deploying the plugin or theme, make sure to change the following value
* - https://your-update-server.com => The URL of the server where WP Plugin Update Server is installed.
* - $prefix_updater => Change this variable's name with your plugin or theme prefix
**/
/** Uncomment for plugin updates **/
// require_once plugin_dir_path( __FILE__ ) . 'lib/wp-package-updater/class-wp-package-updater.php';
/** Enable plugin updates with license check **/
// $prefix_updater = new WP_Package_Updater(
// 'https://your-update-server.com',
// wp_normalize_path( __FILE__ ),
// wp_normalize_path( plugin_dir_path( __FILE__ ) ),
// true
// );
/** Enable plugin updates without license check **/
// $prefix_updater = new WP_Package_Updater(
// 'https://your-update-server.com',
// wp_normalize_path( __FILE__ ),
// wp_normalize_path( plugin_dir_path( __FILE__ ) ),
// false // Can be omitted, false by default
// );
/** Uncomment for theme updates **/
// require_once get_stylesheet_directory() . '/lib/wp-package-updater/class-wp-package-updater.php';
/** Enable theme updates with license check **/
// $prefix_updater = new WP_Package_Updater(
// 'https://your-update-server.com',
// wp_normalize_path( __FILE__ ),
// get_stylesheet_directory(),
// true
// );
/** Enable theme updates without license check **/
// $prefix_updater = new WP_Package_Updater(
// 'https://your-update-server.com',
// wp_normalize_path( __FILE__ ),
// get_stylesheet_directory(),
// false // Can be omitted, false by default
// );
/* ================================================================================================ */
if ( ! class_exists( 'WP_Package_Updater' ) ) {
class WP_Package_Updater {
const VERSION = '1.0.2';
private $license_server_url;
private $package_slug;
private $update_server_url;
private $package_path;
private $package_url;
private $update_checker;
private $type;
private $use_license;
public function __construct(
$update_server_url,
$package_file_path,
$package_path,
$use_license = false
) {
$this->package_path = trailingslashit( $package_path );
$this->set_type();
$package_path_parts = explode( '/', $package_path );
if ( 'Plugin' === $this->type ) {
$package_slug = $package_path_parts[ count( $package_path_parts ) - 2 ];
} elseif ( 'Theme' === $this->type ) {
$package_slug = $package_path_parts[ count( $package_path_parts ) - 1 ];
}
$package_file_path_parts = explode( '/', $package_file_path );
$package_id_parts = array_slice( $package_file_path_parts, -2, 2 );
$package_id = implode( '/', $package_id_parts );
$this->package_id = $package_id;
$this->update_server_url = trailingslashit( $update_server_url ) . 'wppus-update-api/';
$this->package_slug = $package_slug;
$this->use_license = $use_license;
if ( ! class_exists( 'Puc_v4_Factory' ) ) {
require $this->package_path . 'lib/plugin-update-checker/plugin-update-checker.php';
}
$metadata_url = trailingslashit( $this->update_server_url ) . '?action=get_metadata&package_id=';
$metadata_url .= rawurlencode( $this->package_slug );
$this->update_checker = Puc_v4_Factory::buildUpdateChecker( $metadata_url, $package_file_path );
$this->set_type();
if ( 'Plugin' === $this->type ) {
$this->package_url = plugin_dir_url( $package_file_path );
} elseif ( 'Theme' === $this->type ) {
$this->package_url = trailingslashit( get_theme_root_uri() ) . $package_slug;
}
$this->update_checker->addQueryArgFilter( array( $this, 'filter_update_checks' ) );
if ( $this->use_license ) {
$this->license_server_url = trailingslashit( $update_server_url ) . 'wppus-license-api/';
$this->update_checker->addResultFilter( array( $this, 'set_license_error_notice_content' ) );
if ( 'Plugin' === $this->type ) {
add_action( 'after_plugin_row_' . $this->package_id, array( $this, 'print_license_under_plugin' ), 10, 3 );
} elseif ( 'Theme' === $this->type ) {
add_action( 'admin_menu', array( $this, 'setup_theme_admin_menus' ), 10, 0 );
add_filter( 'custom_menu_order', array( $this, 'alter_admin_appearence_submenu_order' ), 10, 1 );
}
add_action( 'wp_ajax_wppu_' . $this->package_id . '_activate_license', array( $this, 'activate_license' ), 10, 0 );
add_action( 'wp_ajax_wppu_' . $this->package_id . '_deactivate_license', array( $this, 'deactivate_license' ), 10, 0 );
add_action( 'admin_enqueue_scripts', array( $this, 'add_admin_scripts' ), 99, 1 );
add_action( 'admin_notices', array( $this, 'show_license_error_notice' ), 10, 0 );
add_action( 'init', array( $this, 'load_textdomain' ), 10, 0 );
}
}
public function load_textdomain() {
$i10n_path = trailingslashit( basename( $this->package_path ) ) . 'lib/wp-update-migrate/languages';
if ( 'Plugin' === $this->type ) {
load_plugin_textdomain( 'wp-package-updater', false, $i10n_path );
} else {
load_theme_textdomain( 'wp-update-migrate', $i10n_path );
}
}
public function setup_theme_admin_menus() {
add_submenu_page(
'themes.php',
'Theme License',
'Theme License',
'manage_options',
'theme-license',
array( $this, 'theme_license_settings' )
);
}
public function alter_admin_appearence_submenu_order( $menu_ord ) {
global $submenu;
$theme_menu = $submenu['themes.php'];
$reordered_menu = array();
$first_key = 0;
$license_menu = null;
foreach ( $theme_menu as $key => $menu ) {
if ( 'themes.php' === $menu[2] ) {
$reordered_menu[ $key ] = $menu;
$first_key = $key;
} elseif ( 'theme-license' === $menu[2] ) {
$license_menu = $menu;
} else {
$reordered_menu[ $key + 1 ] = $menu;
}
}
$reordered_menu[ $first_key + 1 ] = $license_menu;
ksort( $reordered_menu );
$submenu['themes.php'] = $reordered_menu; // @codingStandardsIgnoreLine
return $menu_ord;
}
public function theme_license_settings() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'Sorry, you are not allowed to access this page.' ) ); // @codingStandardsIgnoreLine
}
$this->print_license_form_theme_page();
}
public function add_admin_scripts( $hook ) {
$debug = (bool) ( constant( 'WP_DEBUG' ) );
$condition = 'plugins.php' === $hook;
$condition = $condition || 'appearance_page_theme-license' === $hook;
$condition = $condition || 'appearance_page_parent-theme-license' === $hook;
$condition = $condition && ! wp_script_is( 'wp-package-updater-script' );
if ( $condition ) {
$js_ext = ( $debug ) ? '.js' : '.min.js';
$ver_js = filemtime( $this->package_path . 'lib/wp-package-updater/js/main' . $js_ext );
$params = array(
'action_prefix' => 'wppu_' . $this->package_id,
'ajax_url' => admin_url( 'admin-ajax.php' ),
);
wp_enqueue_script( 'wp-package-updater-script', $this->package_url . '/lib/wp-package-updater/js/main' . $js_ext, array( 'jquery' ), $ver_js, true );
wp_localize_script( 'wp-package-updater-script', 'WP_PackageUpdater', $params );
}
}
public function filter_update_checks( $query_args ) {
if ( $this->use_license ) {
$license = get_option( 'license_key_' . $this->package_slug );
$license_signature = get_option( 'license_signature_' . $this->package_slug );
if ( $license ) {
$query_args['update_license_key'] = rawurlencode( $license );
$query_args['update_license_signature'] = rawurlencode( $license_signature );
}
}
$query_args['update_type'] = $this->type;
return $query_args;
}
public function print_license_form_theme_page() {
$theme = wp_get_theme();
$title = __( 'Theme License - ', 'wp-package-updater' ) . $theme->get( 'Name' );
$form = $this->get_license_form();
ob_start();
require_once $this->package_path . 'lib/wp-package-updater/templates/theme-page-license.php';
echo ob_get_clean(); // @codingStandardsIgnoreLine
}
public function print_license_under_plugin( $plugin_file = null, $plugin_data = null, $status = null ) {
$form = $this->get_license_form();
ob_start();
require_once $this->package_path . 'lib/wp-package-updater/templates/plugin-page-license-row.php';
echo ob_get_clean(); // @codingStandardsIgnoreLine
}
public function activate_license() {
$license_data = $this->do_query_license( 'activate' );
if ( isset( $license_data->package_slug, $license_data->license_key ) ) {
update_option( 'license_key_' . $license_data->package_slug, $license_data->license_key );
if ( isset( $license_data->license_signature ) ) {
update_option( 'license_signature_' . $license_data->package_slug, $license_data->license_signature );
} else {
delete_option( 'license_signature_' . $license_data->package_slug );
}
} else {
$error = new WP_Error( 'License', $license_data->message );
if ( $license_data->clear_key ) {
delete_option( 'license_signature_' . $this->package_slug );
delete_option( 'license_key_' . $this->package_slug );
}
wp_send_json_error( $error );
}
// @todo remove in 2.0
if ( 'Theme' === $this->type ) {
delete_option( 'license_signature_' . $license_data->package_slug . '/functions.php' );
delete_option( 'license_key_' . $license_data->package_slug . '/functions.php' );
} else {
delete_option( 'license_signature_' . $license_data->package_slug . '/' . $license_data->package_slug . '.php' );
delete_option( 'license_key_' . $license_data->package_slug . '/' . $license_data->package_slug . '.php' );
}
delete_option( 'wppu_' . $this->package_slug . '_license_error' );
wp_send_json_success( $license_data );
}
public function deactivate_license() {
$license_data = $this->do_query_license( 'deactivate' );
if ( isset( $license_data->package_slug, $license_data->license_key ) ) {
update_option( 'license_key_' . $license_data->package_slug, '' );
if ( isset( $license_data->license_signature ) ) {
update_option( 'license_signature_' . $license_data->package_slug, '' );
} else {
delete_option( 'license_signature_' . $license_data->package_slug );
}
} else {
$error = new WP_Error( 'License', $license_data->message );
if ( $license_data->clear_key ) {
delete_option( 'license_signature_' . $this->package_slug );
delete_option( 'license_key_' . $this->package_slug );
}
wp_send_json_error( $error );
}
// @todo remove in 2.0
if ( 'Theme' === $this->type ) {
delete_option( 'license_signature_' . $license_data->package_slug . '/functions.php' );
delete_option( 'license_key_' . $license_data->package_slug . '/functions.php' );
} else {
delete_option( 'license_signature_' . $license_data->package_slug . '/' . $license_data->package_slug . '.php' );
delete_option( 'license_key_' . $license_data->package_slug . '/' . $license_data->package_slug . '.php' );
}
wp_send_json_success( $license_data );
}
public function set_license_error_notice_content( $package_info, $result ) {
if ( isset( $package_info->license_error ) && ! empty( $package_info->license_error ) ) {
$license_data = $this->handle_license_errors( $package_info->license_error );
update_option( 'wppu_' . $this->package_slug . '_license_error', $package_info->name . ': ' . $license_data->message );
} else {
delete_option( 'wppu_' . $this->package_slug . '_license_error' );
}
return $package_info;
}
public function show_license_error_notice() {
$error = get_option( 'wppu_' . $this->package_slug . '_license_error' );
if ( $error ) {
$class = 'license-error-' . $this->package_slug . ' notice notice-error is-dismissible';
printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $error ); // @codingStandardsIgnoreLine
}
}
protected function do_query_license( $query_type ) {
if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'license_nonce' ) ) {
$error = new WP_Error( 'License', 'Unauthorised access.' );
wp_send_json_error( $error );
}
$license_key = $_REQUEST['license_key'];
$this->package_slug = $_REQUEST['package_slug'];
if ( empty( $license_key ) ) {
$error = new WP_Error( 'License', 'A license key is required.' );
wp_send_json_error( $error );
}
$api_params = array(
'action' => $query_type,
'license_key' => $license_key,
'allowed_domains' => $_SERVER['SERVER_NAME'],
'package_slug' => rawurlencode( $this->package_slug ),
);
$query = esc_url_raw( add_query_arg( $api_params, $this->license_server_url ) );
$response = wp_remote_get( $query, array(
'timeout' => 20,
'sslverify' => true,
) );
if ( is_wp_error( $response ) ) {
$license_data = new stdClass();
$license_data->clear_key = true;
$license_data->message = $response->get_error_message();
return $license_data;
}
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
if ( JSON_ERROR_NONE !== json_last_error() ) {
$license_data = new stdClass();
$license_data->message = __( 'Unexpected Error! The query to retrieve the license data returned a malformed response.', 'wp-package-updater' );
return $license_data;
}
if ( ! isset( $license_data->id ) ) {
$license_data = $this->handle_license_errors( $license_data, $query_type );
}
return $license_data;
}
protected function handle_license_errors( $license_data, $query_type = null ) {
$license_data->clear_key = false;
if ( 'activate' === $query_type ) {
if ( isset( $license_data->allowed_domains ) ) {
$license_data->message = __( 'The license is already in use for this domain.', 'wp-package-updater' );
} elseif ( isset( $license_data->max_allowed_domains ) ) {
$license_data->clear_key = true;
$license_data->message = __( 'The license has reached the maximum number of activations and cannot be activated for this domain.', 'wp-package-updater' );
}
} elseif ( 'deactivate' === $query_type ) {
if ( isset( $license_data->allowed_domains ) ) {
$license_data->clear_key = true;
$license_data->message = __( 'The license is already inactive for this domain.', 'wp-package-updater' );
}
}
if (
isset( $license_data->status ) &&
'expired' === $license_data->status
) {
if ( isset( $license_data->date_expiry ) ) {
$license_data->message = sprintf(
// translators: the license expiry date
__( 'The license expired on %s and needs to be renewed to be updated.', 'wp-package-updater' ),
date_i18n( get_option( 'date_format' ), $license_data->date_expiry )
);
} else {
$license_data->message = __( 'The license expired and needs to be renewed to be updated.', 'wp-package-updater' );
}
} elseif (
isset( $license_data->status ) &&
'blocked' === $license_data->status
) {
$license_data->message = __( 'The license is blocked and cannot be updated anymore. Please use another license key.', 'wp-package-updater' );
} elseif (
isset( $license_data->status ) &&
'pending' === $license_data->status
) {
$license_data->clear_key = true;
$license_data->message = __( 'The license has not been activated and its status is stil pending. Please try again or use another license key.', 'wp-package-updater' );
} elseif (
isset( $license_data->status ) &&
'invalid' === $license_data->status
) {
$license_data->clear_key = true;
$license_data->message = __( 'The provided license key is invalid. Please use another license key.', 'wp-package-updater' );
} elseif ( isset( $license_data->license_key ) ) {
$license_data->clear_key = true;
$license_data->message = __( 'The provided license key does not appear to be valid. Please use another license key.', 'wp-package-updater' );
} elseif ( 1 === count( (array) $license_data ) ) {
if ( 'Plugin' === $this->type ) {
$license_data->message = __( 'An active license is required to update the plugin. Please provide a valid license key in Plugins > Installed Plugins.', 'wp-package-updater' );
} else {
$license_data->message = __( 'An active license is required to update the theme. Please provide a valid license key in Appearence > Theme License.', 'wp-package-updater' );
}
} elseif ( ! isset( $license_data->message ) || empty( $license_data->message ) ) {
$license_data->clear_key = true;
if ( 'Plugin' === $this->type ) {
$license_data->message = __( 'An unexpected error has occured. Please try again. If the problem persists, please contact the author of the plugin.', 'wp-package-updater' );
} else {
$license_data->message = __( 'An unexpected error has occured. Please try again. If the problem persists, please contact the author of the theme.', 'wp-package-updater' );
}
}
return $license_data;
}
protected function get_license_form() {
// @todo remove in 2.0
if ( get_option( 'license_key_' . $this->package_id ) ) {
update_option( 'license_key_' . $this->package_slug, get_option( 'license_key_' . $this->package_id ), true );
delete_option( 'license_key_' . $this->package_id );
}
$license = get_option( 'license_key_' . $this->package_slug );
$package_id = $this->package_id;
$package_slug = $this->package_slug;
$show_license = ( ! empty( $license ) );
ob_start();
require_once $this->package_path . 'lib/wp-package-updater/templates/license-form.php';
return ob_get_clean();
}
protected static function is_plugin_file( $absolute_path ) {
$plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );
$mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
if ( ( 0 === strpos( $absolute_path, $plugin_dir ) ) || ( 0 === strpos( $absolute_path, $mu_plugin_dir ) ) ) {
return true;
}
if ( ! is_file( $absolute_path ) ) {
return false;
}
if ( function_exists( 'get_file_data' ) ) {
$headers = get_file_data( $absolute_path, array( 'Name' => 'Plugin Name' ), 'plugin' );
return ! empty( $headers['Name'] );
}
return false;
}
protected static function get_theme_directory_name( $absolute_path ) {
if ( is_file( $absolute_path ) ) {
$absolute_path = dirname( $absolute_path );
}
if ( file_exists( $absolute_path . '/style.css' ) ) {
return basename( $absolute_path );
}
return null;
}
protected function set_type() {
$theme_directory = self::get_theme_directory_name( $this->package_path );
if ( self::is_plugin_file( $this->package_path ) ) {
$this->type = 'Plugin';
} elseif ( null !== $theme_directory ) {
$this->type = 'Theme';
} else {
throw new RuntimeException(
sprintf(
'The package updater cannot determine if "%s" is a plugin or a theme. ',
htmlentities( $this->package_path )
)
);
}
}
}
}