mirror of
https://github.com/WenPai-org/wp-domain-mapping.git
synced 2025-08-03 05:33:23 +08:00
1009 lines
31 KiB
PHP
1009 lines
31 KiB
PHP
<?php
|
|
/**
|
|
* UpdatePulse Updater
|
|
* Plugins and themes update library to enable with UpdatePulse Server
|
|
*
|
|
* @author Alexandre Froger
|
|
* @version 2.0
|
|
* @copyright Alexandre Froger - https://www.froger.me
|
|
*/
|
|
|
|
namespace Anyape\UpdatePulse\Updater\v2_0;
|
|
|
|
defined( 'ABSPATH' ) || exit; // Exit if accessed directly
|
|
|
|
use DateTime;
|
|
use DateTimeZone;
|
|
use WP_Error;
|
|
use RuntimeException;
|
|
use stdClass;
|
|
use YahnisElsts\PluginUpdateChecker\v5p3\PucFactory;
|
|
|
|
/* ================================================================================================ */
|
|
/* UpdatePulse 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 UpdatePulse Server.
|
|
*
|
|
* WARNING - READ FIRST:
|
|
*
|
|
* Before deploying the plugin or theme, make sure to change the value of `server` in updatepulse.json
|
|
* with the URL of the server where UpdatePulse Server is installed.
|
|
*
|
|
* Also change $prefix_updater below - replace "prefix" in this variable's name with a unique prefix
|
|
*
|
|
* If the plugin or theme requires a license, change the header `Require License` to either `yes`, `true`, or `1`
|
|
* in the main plugin file or the `style.css` file.
|
|
*
|
|
* If the plugin or theme uses the license of another plugin or theme, add the header `Licensed With`
|
|
* with the slug of the plugin or theme that provides the license in the main plugin file or the `style.css` file.
|
|
*
|
|
**/
|
|
|
|
/** Enable updates **/
|
|
/* phpcs:ignore Squiz.PHP.CommentedOutCode.Found
|
|
use Anyape\UpdatePulse\Updater\v2_0\UpdatePulse_Updater;
|
|
require_once __DIR__ . '/lib/updatepulse-updater/class-updatepulse-updater.php';
|
|
|
|
$prefix_updater = new UpdatePulse_Updater(
|
|
wp_normalize_path( __FILE__ ),
|
|
0 === strpos( __DIR__, WP_PLUGIN_DIR ) ? wp_normalize_path( __DIR__ ) : get_stylesheet_directory()
|
|
);
|
|
*/
|
|
|
|
/* ================================================================================================ */
|
|
|
|
if ( ! class_exists( __NAMESPACE__ . '\UpdatePulse_Updater' ) ) {
|
|
|
|
class UpdatePulse_Updater {
|
|
private $license_server_url;
|
|
private $package_slug;
|
|
private $update_server_url;
|
|
private $package_path;
|
|
private $package_url;
|
|
private $update_checker;
|
|
private $type;
|
|
private $require_license;
|
|
private $package_id;
|
|
private $json_options;
|
|
|
|
public function __construct( $package_file_path, $package_path ) {
|
|
global $wp_filesystem;
|
|
|
|
if ( ! isset( $wp_filesystem ) ) {
|
|
include_once ABSPATH . 'wp-admin/includes/file.php';
|
|
|
|
WP_Filesystem();
|
|
}
|
|
|
|
$this->package_path = trailingslashit( $package_path );
|
|
|
|
if ( ! $wp_filesystem->exists( $this->package_path . 'updatepulse.json' ) ) {
|
|
throw new RuntimeException(
|
|
sprintf(
|
|
'The package updater cannot find the updatepulse.json file in "%s". ',
|
|
esc_html( htmlentities( $this->package_path ) )
|
|
)
|
|
);
|
|
}
|
|
|
|
$info = array();
|
|
$update_server_url = $this->get_option( 'server' );
|
|
$file_path = '';
|
|
$package_path_parts = explode( '/', untrailingslashit( $this->package_path ) );
|
|
$package_slug = $package_path_parts[ count( $package_path_parts ) - 1 ];
|
|
|
|
$this->set_type();
|
|
|
|
if ( 'Plugin' === $this->type ) {
|
|
$this->package_url = plugin_dir_url( $package_file_path );
|
|
$file_path = $package_file_path;
|
|
} elseif ( 'Theme' === $this->type ) {
|
|
$this->package_url = trailingslashit( get_theme_root_uri() ) . $package_slug;
|
|
$file_path = dirname( $package_file_path ) . '/style.css';
|
|
}
|
|
|
|
if ( function_exists( 'get_file_data' ) ) {
|
|
$info = get_file_data(
|
|
$file_path,
|
|
array(
|
|
'licensed_with' => 'Licensed With',
|
|
'require_license' => 'Require License',
|
|
)
|
|
);
|
|
}
|
|
|
|
$require_license = (
|
|
isset( $info['require_license'] ) &&
|
|
(
|
|
strtolower( $info['require_license'] ) === 'yes' ||
|
|
strtolower( $info['require_license'] ) === 'true'
|
|
)
|
|
);
|
|
$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 ) . 'updatepulse-server-update-api/';
|
|
$this->package_slug = $package_slug;
|
|
$this->require_license = $require_license;
|
|
$metadata_url = trailingslashit( $this->update_server_url )
|
|
. '?action=get_metadata&package_id=';
|
|
$metadata_url .= rawurlencode( $this->package_slug );
|
|
|
|
if ( ! class_exists( 'YahnisElsts\PluginUpdateChecker\v5p3\PucFactory' ) ) {
|
|
require $this->package_path . 'lib/plugin-update-checker/plugin-update-checker.php';
|
|
}
|
|
|
|
$this->update_checker = PucFactory::buildUpdateChecker( $metadata_url, $package_file_path );
|
|
|
|
$this->update_checker->addQueryArgFilter( array( $this, 'filter_update_checks' ) );
|
|
|
|
if ( $this->require_license ) {
|
|
$this->license_server_url = trailingslashit( $update_server_url )
|
|
. 'updatepulse-server-license-api/';
|
|
|
|
$this->update_checker->addResultFilter( array( $this, 'set_license_error_notice_content' ) );
|
|
|
|
if ( ! isset( $info['licensed_with'] ) || empty( $info['licensed_with'] ) ) {
|
|
|
|
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_filter( 'wp_prepare_themes_for_js', array( $this, 'wp_prepare_themes_for_js' ), 10, 1 );
|
|
}
|
|
|
|
if ( ! $this->get_option( 'licenseKey' ) || ! $this->get_option( 'licenseSignature' ) ) {
|
|
$suffix_type = strtolower( $this->type );
|
|
|
|
add_filter( "auto_update_{$suffix_type}", array( $this, 'auto_update_package' ), 10, 2 );
|
|
add_filter( "site_transient_update_{$suffix_type}s", array( $this, 'site_transient_update_packages' ), 10, 1 );
|
|
}
|
|
|
|
add_action( 'wp_ajax_upupdater_' . $this->package_id . '_activate_license', array( $this, 'activate_license' ), 10, 0 );
|
|
add_action( 'wp_ajax_upupdater_' . $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 );
|
|
} else {
|
|
$this->update_option( 'licensed_with', $info['licensed_with'] );
|
|
}
|
|
|
|
add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete' ), 10, 2 );
|
|
|
|
add_filter( 'upgrader_pre_install', array( $this, 'upgrader_pre_install' ), 10, 2 );
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
* Public methods
|
|
*******************************************************************/
|
|
|
|
// WordPress hooks ---------------------------------------------
|
|
|
|
public function wp_prepare_themes_for_js( $prepared_themes ) {
|
|
|
|
if ( isset( $prepared_themes[ $this->package_slug ] ) ) {
|
|
$prepared_themes[ $this->package_slug ]['description'] .= '<div>'
|
|
. $this->get_license_form()
|
|
. '</div>';
|
|
}
|
|
|
|
return $prepared_themes;
|
|
}
|
|
|
|
public function load_textdomain() {
|
|
$i10n_path = trailingslashit( basename( $this->package_path ) ) . 'lib/updatepulse-updater/languages';
|
|
|
|
if ( 'Plugin' === $this->type ) {
|
|
load_plugin_textdomain( 'updatepulse-updater', false, $i10n_path );
|
|
} else {
|
|
load_theme_textdomain( 'updatepulse-updater', $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; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
|
|
|
return $menu_ord;
|
|
}
|
|
|
|
public function add_admin_scripts( $hook ) {
|
|
$debug = (bool) ( constant( 'WP_DEBUG' ) );
|
|
|
|
$condition = 'plugins.php' === $hook ||
|
|
'themes.php' === $hook ||
|
|
'appearance_page_theme-license' === $hook ||
|
|
'appearance_page_parent-theme-license' === $hook &&
|
|
! wp_script_is( 'updatepulse-updater-script' );
|
|
|
|
if ( $condition ) {
|
|
$js_ext = ( $debug ) ? '.js' : '.min.js';
|
|
$ver_js = filemtime( $this->package_path . 'lib/updatepulse-updater/js/main' . $js_ext );
|
|
$params = array(
|
|
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
|
);
|
|
|
|
wp_enqueue_script(
|
|
'updatepulse-updater-script',
|
|
$this->package_url . '/lib/updatepulse-updater/js/main' . $js_ext,
|
|
array( 'jquery' ),
|
|
$ver_js,
|
|
true
|
|
);
|
|
wp_localize_script( 'updatepulse-updater-script', 'UPupdater', $params );
|
|
|
|
if ( ! wp_style_is( 'updatepulse-updater-style' ) ) {
|
|
wp_register_style( 'updatepulse-updater-style', false, array(), '1.0' );
|
|
wp_enqueue_style( 'updatepulse-updater-style' );
|
|
|
|
$css = '
|
|
.appearance_page_theme-license .license-error.notice {
|
|
display: none;
|
|
}
|
|
|
|
.appearance_page_theme-license .postbox {
|
|
max-width: 500px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.appearance_page_theme-license .wrap-license label {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.appearance_page_theme-license .wrap-license input[type="text"],
|
|
.theme-about .wrap-license input[type="text"] {
|
|
width: 100%;
|
|
}
|
|
|
|
.appearance_page_theme-license .inside {
|
|
margin: 2em;
|
|
}
|
|
|
|
.license-change {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1em;
|
|
margin: 2em;
|
|
}
|
|
|
|
.plugin-update .license-change {
|
|
flex-direction: row;
|
|
align-items: center;
|
|
margin: 1em 0;
|
|
}
|
|
|
|
.license-message {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.current-license-error {
|
|
background: #a00;
|
|
color: white;
|
|
padding: 0.25em;
|
|
}
|
|
';
|
|
|
|
wp_add_inline_style( 'updatepulse-updater-style', $css );
|
|
}
|
|
}
|
|
}
|
|
|
|
public function filter_update_checks( $query_args ) {
|
|
$licensed_with = $this->get_option( 'licensed_with' );
|
|
$license = null;
|
|
|
|
if ( ! empty( $licensed_with ) ) {
|
|
$query_args['licensed_with'] = $licensed_with;
|
|
$license = $this->get_option( 'licenseKey', $licensed_with );
|
|
$license_signature = $this->get_option( 'licenseSignature', $licensed_with );
|
|
} elseif ( $this->require_license ) {
|
|
$license = $this->get_option( 'licenseKey' );
|
|
$license_signature = $this->get_option( 'licenseSignature' );
|
|
}
|
|
|
|
if ( $license && $license_signature ) {
|
|
$query_args['license_key'] = rawurlencode( $license );
|
|
$query_args['license_signature'] = rawurlencode( $license_signature );
|
|
}
|
|
|
|
$query_args['update_type'] = $this->type;
|
|
|
|
return $query_args;
|
|
}
|
|
|
|
public function print_license_under_plugin( $plugin_file = null, $plugin_data = null, $status = null ) {
|
|
$this->get_template(
|
|
'plugin-page-license-row.php',
|
|
array(
|
|
'form' => $this->get_license_form(),
|
|
'plugin_file' => $plugin_file,
|
|
'plugin_data' => $plugin_data,
|
|
'slug' => $this->package_slug,
|
|
'status' => $status,
|
|
)
|
|
);
|
|
}
|
|
|
|
public function activate_license() {
|
|
$license_data = $this->do_query_license( 'activate' );
|
|
|
|
if ( isset( $license_data->package_slug, $license_data->license_key ) ) {
|
|
$this->update_option( 'licenseKey', $license_data->license_key );
|
|
|
|
if ( isset( $license_data->license_signature ) ) {
|
|
$this->update_option( 'licenseSignature', $license_data->license_signature );
|
|
} else {
|
|
$this->delete_option( 'licenseSignature' );
|
|
}
|
|
|
|
$license_data->may_deactivate = true;
|
|
$license_data->deactivate_text = __( 'Deactivate', 'updatepulse-updater' );
|
|
|
|
if ( isset( $license_data->next_deactivate ) ) {
|
|
$this->update_option( 'licenseNextDeactivate', $license_data->next_deactivate );
|
|
|
|
if ( time() < $license_data->next_deactivate ) {
|
|
$license_data->may_deactivate = false;
|
|
$license_data->deactivate_text = __( 'Deactivation is possible after:', 'updatepulse-updater' );
|
|
$license_data->date_format = get_option( 'date_format' ) . ' H:i:s';
|
|
}
|
|
} else {
|
|
$this->delete_option( 'licenseNextDeactivate' );
|
|
}
|
|
} else {
|
|
$error = new WP_Error( 'License', $license_data->message );
|
|
|
|
if ( property_exists( $license_data, 'clear_key' ) && $license_data->clear_key ) {
|
|
$this->delete_option( 'licenseSignature' );
|
|
$this->delete_option( 'licenseKey' );
|
|
}
|
|
|
|
wp_send_json_error( $error );
|
|
}
|
|
|
|
if ( 'Theme' === $this->type ) {
|
|
wp_update_themes();
|
|
} else {
|
|
wp_update_plugins();
|
|
}
|
|
|
|
$this->delete_option( 'licenseError' );
|
|
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 ) ) {
|
|
$this->update_option( 'licenseKey', '' );
|
|
|
|
if ( isset( $license_data->license_signature ) ) {
|
|
$this->update_option( 'licenseSignature', '' );
|
|
} else {
|
|
$this->delete_option( 'licenseSignature' );
|
|
}
|
|
|
|
if ( isset( $license_data->next_deactivate ) ) {
|
|
$this->update_option( 'licenseNextDeactivate', $license_data->next_deactivate );
|
|
} else {
|
|
$this->delete_option( 'licenseNextDeactivate' );
|
|
}
|
|
} else {
|
|
$error = new WP_Error( 'License', $license_data->message );
|
|
|
|
if ( $license_data->clear_key ) {
|
|
$this->delete_option( 'licenseSignature' );
|
|
$this->delete_option( 'licenseKey' );
|
|
}
|
|
|
|
wp_send_json_error( $error );
|
|
}
|
|
|
|
$transient_name = 'Theme' === $this->type ? 'update_themes' : 'update_plugins';
|
|
$update_packages = get_site_transient( $transient_name );
|
|
|
|
if ( 'Theme' === $this->type ) {
|
|
unset( $update_packages->response[ $this->package_slug ] );
|
|
} else {
|
|
unset( $update_packages->response[ $this->package_id ] );
|
|
}
|
|
|
|
set_site_transient( $transient_name, $update_packages );
|
|
|
|
if ( 'Theme' === $this->type ) {
|
|
wp_update_themes();
|
|
} else {
|
|
wp_update_plugins();
|
|
}
|
|
|
|
wp_send_json_success( $license_data );
|
|
}
|
|
|
|
public function set_license_error_notice_content( $package_info, $result ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
|
|
|
if (
|
|
isset( $package_info->license_error ) &&
|
|
is_object( $package_info->license_error )
|
|
) {
|
|
$license_data = $this->handle_license_errors( $package_info->license_error );
|
|
|
|
$this->update_option( 'licenseError', $package_info->name . ': ' . $license_data->message );
|
|
} else {
|
|
$this->delete_option( 'licenseError' );
|
|
}
|
|
|
|
return $package_info;
|
|
}
|
|
|
|
public function show_license_error_notice() {
|
|
$error = $this->get_option( 'licenseError' );
|
|
|
|
if ( $error ) {
|
|
$class = 'license-error license-error-' . $this->package_slug . ' notice notice-error is-dismissible';
|
|
|
|
printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $error ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
}
|
|
|
|
public function upgrader_process_complete( $upgrader_object, $options ) {
|
|
|
|
if ( 'update' === $options['action'] ) {
|
|
|
|
if (
|
|
'plugin' === $options['type'] &&
|
|
isset( $options['plugins'] ) &&
|
|
is_array( $options['plugins'] )
|
|
) {
|
|
|
|
foreach ( $options['plugins'] as $plugin ) {
|
|
|
|
if ( $plugin === $this->package_id ) {
|
|
$this->restore_updatepulse_options();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
'theme' === $options['type'] &&
|
|
isset( $options['themes'] ) &&
|
|
is_array( $options['themes'] )
|
|
) {
|
|
|
|
foreach ( $options['themes'] as $theme ) {
|
|
|
|
if ( $theme === $this->package_slug ) {
|
|
$this->restore_updatepulse_options();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function upgrader_pre_install( $_true, $hook_extra ) {
|
|
|
|
if ( isset( $hook_extra['plugin'] ) ) {
|
|
$plugin_to_update = $hook_extra['plugin'];
|
|
|
|
if ( $plugin_to_update === $this->package_id ) {
|
|
$this->save_updatepulse_options();
|
|
}
|
|
}
|
|
|
|
if ( isset( $hook_extra['theme'] ) ) {
|
|
$theme_to_update = $hook_extra['theme'];
|
|
|
|
if ( $theme_to_update === $this->package_slug ) {
|
|
$this->save_updatepulse_options();
|
|
}
|
|
}
|
|
|
|
return $_true;
|
|
}
|
|
|
|
public function auto_update_package( $update, $info ) {
|
|
|
|
if ( 'Theme' === $this->type && $this->package_slug === $info->theme ) {
|
|
return false;
|
|
} elseif ( 'Plugin' === $this->type && $this->package_id === $info->plugin ) {
|
|
return false;
|
|
}
|
|
|
|
return $update;
|
|
}
|
|
|
|
public function site_transient_update_packages( $transient ) {
|
|
|
|
if ( 'Theme' === $this->type ) {
|
|
unset( $transient->response[ $this->package_slug ] );
|
|
} else {
|
|
unset( $transient->response[ $this->package_id ] );
|
|
}
|
|
|
|
return $transient;
|
|
}
|
|
|
|
// Misc. -------------------------------------------------------
|
|
|
|
public function locate_template( $template_name, $load = false, $required_once = true ) {
|
|
$template = apply_filters(
|
|
'upupdater_' . $this->package_id . '_locate_template',
|
|
$this->package_path . 'lib/updatepulse-updater/templates/' . $template_name,
|
|
$template_name,
|
|
str_replace( $template_name, '', $this->package_path . 'lib/updatepulse-updater/templates/' )
|
|
);
|
|
|
|
if ( $load && '' !== $template ) {
|
|
load_template( $template, $required_once );
|
|
}
|
|
|
|
return $template;
|
|
}
|
|
|
|
public function get_template( $template_name, $args = array(), $load = true, $required_once = false ) {
|
|
$template_name = apply_filters(
|
|
'upupdater_' . $this->package_id . '_get_template_name',
|
|
$template_name,
|
|
$args
|
|
);
|
|
$template_args = apply_filters(
|
|
'upupdater_' . $this->package_id . '_get_template_args',
|
|
$args,
|
|
$template_name
|
|
);
|
|
|
|
if ( ! empty( $template_args ) ) {
|
|
|
|
foreach ( $template_args as $key => $arg ) {
|
|
$key = is_numeric( $key ) ? 'var_' . $key : $key;
|
|
|
|
set_query_var( $key, $arg );
|
|
}
|
|
}
|
|
|
|
return $this->locate_template( $template_name, $load, $required_once );
|
|
}
|
|
|
|
public function theme_license_settings() {
|
|
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_die( __( 'Sorry, you are not allowed to access this page.' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
$theme = wp_get_theme();
|
|
$title = __( 'Theme License - ', 'updatepulse-updater' ) . $theme->get( 'Name' );
|
|
|
|
$this->get_template(
|
|
'theme-page-license.php',
|
|
array(
|
|
'form' => $this->get_license_form(),
|
|
'title' => $title,
|
|
'theme' => $theme,
|
|
)
|
|
);
|
|
}
|
|
|
|
/*******************************************************************
|
|
* Protected methods
|
|
*******************************************************************/
|
|
|
|
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 get_option( $option, $other_package_slug = false ) {
|
|
global $wp_filesystem;
|
|
|
|
if ( ! isset( $wp_filesystem ) ) {
|
|
include_once ABSPATH . 'wp-admin/includes/file.php';
|
|
|
|
WP_Filesystem();
|
|
}
|
|
|
|
if ( $other_package_slug && $this->package_path ) {
|
|
$parts = explode( '/', untrailingslashit( $this->package_path ) );
|
|
$index = count( $parts ) - 1;
|
|
$parts[ $index ] = $other_package_slug;
|
|
$package_path = trailingslashit( implode( '/', $package_path ) );
|
|
|
|
if ( $wp_filesystem->exists( $package_path . 'updatepulse.json' ) ) {
|
|
$updatepulse_json = $wp_filesystem->get_contents( $package_path . 'updatepulse.json' );
|
|
}
|
|
|
|
if ( $updatepulse_json ) {
|
|
$json_options = json_decode( $updatepulse_json, true );
|
|
|
|
if ( isset( $json_options[ $option ] ) ) {
|
|
return $json_options[ $option ];
|
|
}
|
|
}
|
|
} else {
|
|
|
|
if (
|
|
$this->package_path &&
|
|
! isset( $this->json_options ) &&
|
|
$wp_filesystem->exists( $this->package_path . 'updatepulse.json' )
|
|
) {
|
|
$updatepulse_json = $wp_filesystem->get_contents( $this->package_path . 'updatepulse.json' );
|
|
|
|
if ( $updatepulse_json ) {
|
|
$this->json_options = json_decode( $updatepulse_json, true );
|
|
}
|
|
}
|
|
|
|
if ( isset( $this->json_options[ $option ] ) ) {
|
|
return $this->json_options[ $option ];
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
protected function update_option( $option, $value ) {
|
|
global $wp_filesystem;
|
|
|
|
if ( ! isset( $wp_filesystem ) ) {
|
|
include_once ABSPATH . 'wp-admin/includes/file.php';
|
|
|
|
WP_Filesystem();
|
|
}
|
|
|
|
if ( ! isset( $this->json_options ) ) {
|
|
$updatepulse_json = $wp_filesystem->get_contents( $this->package_path . 'updatepulse.json' );
|
|
|
|
if ( $updatepulse_json ) {
|
|
$this->json_options = json_decode( $updatepulse_json, true );
|
|
}
|
|
}
|
|
|
|
$this->json_options[ $option ] = $value;
|
|
$updatepulse_json = wp_json_encode(
|
|
$this->json_options,
|
|
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
|
|
);
|
|
|
|
$wp_filesystem->put_contents( $this->package_path . 'updatepulse.json', $updatepulse_json, FS_CHMOD_FILE );
|
|
}
|
|
|
|
protected function delete_option( $option ) {
|
|
global $wp_filesystem;
|
|
|
|
if ( ! isset( $wp_filesystem ) ) {
|
|
include_once ABSPATH . 'wp-admin/includes/file.php';
|
|
|
|
WP_Filesystem();
|
|
}
|
|
|
|
if ( ! isset( $this->json_options ) ) {
|
|
$updatepulse_json = $wp_filesystem->get_contents( $this->package_path . 'updatepulse.json' );
|
|
|
|
if ( $updatepulse_json ) {
|
|
$this->json_options = json_decode( $updatepulse_json, true );
|
|
}
|
|
}
|
|
|
|
if ( isset( $this->json_options[ $option ] ) ) {
|
|
unset( $this->json_options[ $option ] );
|
|
|
|
$updatepulse_json = wp_json_encode(
|
|
$this->json_options,
|
|
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
|
|
);
|
|
|
|
$wp_filesystem->put_contents(
|
|
$this->package_path . 'updatepulse.json',
|
|
$updatepulse_json,
|
|
FS_CHMOD_FILE
|
|
);
|
|
}
|
|
}
|
|
|
|
protected function save_updatepulse_options() {
|
|
global $wp_filesystem;
|
|
|
|
if ( ! isset( $wp_filesystem ) ) {
|
|
include_once ABSPATH . 'wp-admin/includes/file.php';
|
|
|
|
WP_Filesystem();
|
|
}
|
|
|
|
if ( ! isset( $this->json_options ) ) {
|
|
$updatepulse_json = $wp_filesystem->get_contents( $this->package_path . 'updatepulse.json' );
|
|
|
|
if ( $updatepulse_json ) {
|
|
$this->json_options = json_decode( $updatepulse_json, true );
|
|
}
|
|
}
|
|
|
|
update_option( 'updatepulse_' . $this->package_slug . '_options', $this->json_options );
|
|
}
|
|
|
|
protected function restore_updatepulse_options() {
|
|
$updatepulse_options = get_option( 'updatepulse_' . $this->package_slug . '_options' );
|
|
|
|
if ( $updatepulse_options ) {
|
|
global $wp_filesystem;
|
|
|
|
if ( ! isset( $wp_filesystem ) ) {
|
|
include_once ABSPATH . 'wp-admin/includes/file.php';
|
|
|
|
WP_Filesystem();
|
|
}
|
|
|
|
$server = $this->get_option( 'server' );
|
|
$updatepulse_options['server'] = $server;
|
|
$updatepulse_json = wp_json_encode(
|
|
$updatepulse_options,
|
|
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
|
|
);
|
|
|
|
$wp_filesystem->put_contents(
|
|
$this->package_path . 'updatepulse.json',
|
|
$updatepulse_json,
|
|
FS_CHMOD_FILE
|
|
);
|
|
delete_option( 'updatepulse_' . $this->package_slug . '_options' );
|
|
}
|
|
}
|
|
|
|
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 ),
|
|
'locale' => get_locale(),
|
|
);
|
|
$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.', 'updatepulse-updater' );
|
|
|
|
return $license_data;
|
|
}
|
|
|
|
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
|
$license_data = $this->handle_license_errors( $license_data );
|
|
}
|
|
|
|
return $license_data;
|
|
}
|
|
|
|
protected function handle_license_errors( $license_data ) {
|
|
$timezone = new DateTimeZone( wp_timezone_string() );
|
|
$return = array( 'clear_key' => false );
|
|
$error_code = ( isset( $license_data->code ) ) ? $license_data->code : 'unknown';
|
|
$error_data = ( isset( $license_data->data ) ) ? $license_data->data : (object) array();
|
|
|
|
switch ( $error_code ) {
|
|
case 'license_already_activated':
|
|
$return['message'] = __( 'The license is already in use for this domain.', 'updatepulse-updater' );
|
|
|
|
break;
|
|
case 'max_domains_reached':
|
|
$return['clear_key'] = true;
|
|
$return['message'] = __( 'The license has reached the maximum number of activations and cannot be activated for this domain.', 'updatepulse-updater' );
|
|
|
|
break;
|
|
case 'license_already_deactivated':
|
|
$return['clear_key'] = true;
|
|
$return['message'] = __( 'The license is already inactive for this domain.', 'updatepulse-updater' );
|
|
|
|
break;
|
|
case 'too_early_deactivation':
|
|
$return['message'] = __( 'The license may not be deactivated yet.', 'updatepulse-updater' );
|
|
|
|
break;
|
|
case 'illegal_license_status':
|
|
$status = ( isset( $error_data->status ) ) ? $error_data->status : 'unknown';
|
|
|
|
if ( 'blocked' === $status ) {
|
|
$return['message'] = __( 'The license is blocked and cannot be updated anymore. Please use another license key.', 'updatepulse-updater' );
|
|
} elseif ( 'pending' === $status ) {
|
|
$return['clear_key'] = true;
|
|
$return['message'] = __( 'The license has not been activated and its status is still pending. Please try again or use another license key.', 'updatepulse-updater' );
|
|
} elseif ( 'invalid' === $status ) {
|
|
$return['clear_key'] = true;
|
|
$return['message'] = __( 'The provided license key is invalid. Please use another license key.', 'updatepulse-updater' );
|
|
} elseif ( 'expired' === $status ) {
|
|
|
|
if ( isset( $error_data->date_expiry ) ) {
|
|
$date = new DateTime( 'now', $timezone );
|
|
|
|
$date->setTimestamp( intval( $license_data->date_expiry ) );
|
|
|
|
$return['message'] = sprintf(
|
|
// translators: the license expiry date
|
|
__( 'The license expired on %s and needs to be renewed to be updated.', 'updatepulse-updater' ),
|
|
$date->format( get_option( 'date_format' ) )
|
|
);
|
|
} else {
|
|
$return['message'] = __( 'The license expired and needs to be renewed to be updated.', 'updatepulse-updater' );
|
|
}
|
|
}
|
|
|
|
break;
|
|
case 'invalid_license_key':
|
|
$return['clear_key'] = true;
|
|
$return['message'] = __( 'The provided license key does not appear to be valid. Please use another license key.', 'updatepulse-updater' );
|
|
|
|
break;
|
|
case 'invalid_license':
|
|
if ( 'Plugin' === $this->type ) {
|
|
$return['message'] = __( 'An active license is required to update the plugin. Please provide a valid license key in Plugins > Installed Plugins.', 'updatepulse-updater' );
|
|
} else {
|
|
$return['message'] = __( 'An active license is required to update the theme. Please provide a valid license key in Appearence > Theme License.', 'updatepulse-updater' );
|
|
}
|
|
|
|
break;
|
|
case 'license_error':
|
|
$return['message'] = __( 'An unexpected error has occured.', 'updatepulse-updater' );
|
|
$return['message'] .= '<br>' . $error_data->message;
|
|
|
|
break;
|
|
case 'unexpected_error':
|
|
default:
|
|
$return['message'] = __( 'An unexpected error has occured. Please try again. If the problem persists, please contact support.', 'updatepulse-updater' );
|
|
|
|
break;
|
|
}
|
|
|
|
return (object) $return;
|
|
}
|
|
|
|
protected function get_license_form() {
|
|
$license = $this->get_option( 'licenseKey' );
|
|
$next_deactivate = $this->get_option( 'licenseNextDeactivate' );
|
|
$may_deactivate = false;
|
|
$deactivate_text = '';
|
|
|
|
if ( time() < $next_deactivate ) {
|
|
$deactivate_text = __( 'Deactivation is possible after:', 'updatepulse-updater' );
|
|
} else {
|
|
$may_deactivate = true;
|
|
$deactivate_text = __( 'Deactivate', 'updatepulse-updater' );
|
|
}
|
|
|
|
ob_start();
|
|
|
|
$this->get_template(
|
|
'license-form.php',
|
|
array(
|
|
'license' => $license,
|
|
'package_id' => $this->package_id,
|
|
'package_slug' => $this->package_slug,
|
|
'show_license' => ( ! empty( $license ) ),
|
|
'may_deactivate' => $may_deactivate,
|
|
'deactivate_text' => $deactivate_text,
|
|
'next_deactivate' => intval( $next_deactivate ),
|
|
'date_format' => get_option( 'date_format' ) . ' H:i:s',
|
|
)
|
|
);
|
|
|
|
return ob_get_clean();
|
|
}
|
|
|
|
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. ',
|
|
esc_html( htmlentities( $this->package_path ) )
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|