You've already forked wp-fedistream
654 lines
17 KiB
PHP
654 lines
17 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* License management class.
|
||
|
|
*
|
||
|
|
* Wraps the wc-licensed-product-client library for WordPress integration.
|
||
|
|
*
|
||
|
|
* @package WP_FediStream
|
||
|
|
*/
|
||
|
|
|
||
|
|
namespace WP_FediStream\License;
|
||
|
|
|
||
|
|
use Magdev\WcLicensedProductClient\SecureLicenseClient;
|
||
|
|
use Magdev\WcLicensedProductClient\Dto\LicenseInfo;
|
||
|
|
use Magdev\WcLicensedProductClient\Dto\LicenseStatus;
|
||
|
|
use Magdev\WcLicensedProductClient\Dto\LicenseState;
|
||
|
|
use Magdev\WcLicensedProductClient\Dto\ActivationResult;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseException;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseNotFoundException;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseExpiredException;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseInvalidException;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseRevokedException;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseInactiveException;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\DomainMismatchException;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\MaxActivationsReachedException;
|
||
|
|
use Magdev\WcLicensedProductClient\Exception\RateLimitExceededException;
|
||
|
|
use Magdev\WcLicensedProductClient\Security\SignatureException;
|
||
|
|
use Symfony\Component\HttpClient\HttpClient;
|
||
|
|
|
||
|
|
// Prevent direct file access.
|
||
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* License Manager class.
|
||
|
|
*
|
||
|
|
* Handles license validation, activation, and status checking.
|
||
|
|
*/
|
||
|
|
final class Manager {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Option names for license settings.
|
||
|
|
*/
|
||
|
|
public const OPTION_LICENSE_KEY = 'wp_fedistream_license_key';
|
||
|
|
public const OPTION_SERVER_URL = 'wp_fedistream_license_server_url';
|
||
|
|
public const OPTION_SERVER_SECRET = 'wp_fedistream_license_server_secret';
|
||
|
|
public const OPTION_LICENSE_STATUS = 'wp_fedistream_license_status';
|
||
|
|
public const OPTION_LICENSE_DATA = 'wp_fedistream_license_data';
|
||
|
|
public const OPTION_LAST_CHECK = 'wp_fedistream_license_last_check';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Transient name for caching license validation.
|
||
|
|
*/
|
||
|
|
private const TRANSIENT_LICENSE_CHECK = 'wp_fedistream_license_check';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Cache TTL in seconds (24 hours).
|
||
|
|
*/
|
||
|
|
private const CACHE_TTL = 86400;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Singleton instance.
|
||
|
|
*
|
||
|
|
* @var Manager|null
|
||
|
|
*/
|
||
|
|
private static ?Manager $instance = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* License client instance.
|
||
|
|
*
|
||
|
|
* @var SecureLicenseClient|null
|
||
|
|
*/
|
||
|
|
private ?SecureLicenseClient $client = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get singleton instance.
|
||
|
|
*
|
||
|
|
* @return Manager
|
||
|
|
*/
|
||
|
|
public static function get_instance(): Manager {
|
||
|
|
if ( null === self::$instance ) {
|
||
|
|
self::$instance = new self();
|
||
|
|
}
|
||
|
|
return self::$instance;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Private constructor.
|
||
|
|
*/
|
||
|
|
private function __construct() {
|
||
|
|
$this->init_hooks();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Initialize WordPress hooks.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
private function init_hooks(): void {
|
||
|
|
add_action( 'wp_ajax_fedistream_validate_license', array( $this, 'ajax_validate_license' ) );
|
||
|
|
add_action( 'wp_ajax_fedistream_activate_license', array( $this, 'ajax_activate_license' ) );
|
||
|
|
add_action( 'wp_ajax_fedistream_deactivate_license', array( $this, 'ajax_deactivate_license' ) );
|
||
|
|
add_action( 'wp_ajax_fedistream_check_license_status', array( $this, 'ajax_check_status' ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Initialize the license client.
|
||
|
|
*
|
||
|
|
* @return bool True if client was initialized successfully.
|
||
|
|
*/
|
||
|
|
private function init_client(): bool {
|
||
|
|
if ( null !== $this->client ) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
$server_url = self::get_server_url();
|
||
|
|
$server_secret = self::get_server_secret();
|
||
|
|
|
||
|
|
if ( empty( $server_url ) || empty( $server_secret ) ) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
$this->client = new SecureLicenseClient(
|
||
|
|
httpClient: HttpClient::create(),
|
||
|
|
baseUrl: $server_url,
|
||
|
|
serverSecret: $server_secret,
|
||
|
|
);
|
||
|
|
return true;
|
||
|
|
} catch ( \Throwable $e ) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Validate the current license.
|
||
|
|
*
|
||
|
|
* @return array{success: bool, message: string, data?: array}
|
||
|
|
*/
|
||
|
|
public function validate(): array {
|
||
|
|
if ( ! $this->init_client() ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License server configuration is incomplete.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
$license_key = self::get_license_key();
|
||
|
|
if ( empty( $license_key ) ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'No license key provided.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
$domain = wp_parse_url( home_url(), PHP_URL_HOST );
|
||
|
|
|
||
|
|
try {
|
||
|
|
$result = $this->client->validate( $license_key, $domain );
|
||
|
|
|
||
|
|
// Update cached status.
|
||
|
|
$this->update_cached_status( 'valid', array(
|
||
|
|
'product_id' => $result->productId,
|
||
|
|
'expires_at' => $result->expiresAt?->format( 'c' ),
|
||
|
|
'version_id' => $result->versionId,
|
||
|
|
) );
|
||
|
|
|
||
|
|
return array(
|
||
|
|
'success' => true,
|
||
|
|
'message' => __( 'License validated successfully.', 'wp-fedistream' ),
|
||
|
|
'data' => array(
|
||
|
|
'status' => 'valid',
|
||
|
|
'product_id' => $result->productId,
|
||
|
|
'expires_at' => $result->expiresAt?->format( 'Y-m-d' ),
|
||
|
|
'lifetime' => $result->isLifetime(),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
} catch ( LicenseNotFoundException $e ) {
|
||
|
|
$this->update_cached_status( 'invalid' );
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License key not found. Please check your license key.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( LicenseExpiredException $e ) {
|
||
|
|
$this->update_cached_status( 'expired' );
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'Your license has expired. Please renew to continue.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( LicenseRevokedException $e ) {
|
||
|
|
$this->update_cached_status( 'revoked' );
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'Your license has been revoked.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( LicenseInactiveException $e ) {
|
||
|
|
$this->update_cached_status( 'inactive' );
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License is inactive. Please activate it first.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( DomainMismatchException $e ) {
|
||
|
|
$this->update_cached_status( 'invalid' );
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'This license is not activated for this domain.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( SignatureException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License verification failed. Please check your server secret.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( RateLimitExceededException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'Too many requests. Please try again later.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( LicenseException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => sprintf(
|
||
|
|
/* translators: %s: Error message */
|
||
|
|
__( 'License validation failed: %s', 'wp-fedistream' ),
|
||
|
|
$e->getMessage()
|
||
|
|
),
|
||
|
|
);
|
||
|
|
} catch ( \Throwable $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'Unable to verify license. Please try again later.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Activate the license for this domain.
|
||
|
|
*
|
||
|
|
* @return array{success: bool, message: string, data?: array}
|
||
|
|
*/
|
||
|
|
public function activate(): array {
|
||
|
|
if ( ! $this->init_client() ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License server configuration is incomplete.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
$license_key = self::get_license_key();
|
||
|
|
if ( empty( $license_key ) ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'No license key provided.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
$domain = wp_parse_url( home_url(), PHP_URL_HOST );
|
||
|
|
|
||
|
|
try {
|
||
|
|
$result = $this->client->activate( $license_key, $domain );
|
||
|
|
|
||
|
|
if ( $result->success ) {
|
||
|
|
// Validate after activation to get full license info.
|
||
|
|
return $this->validate();
|
||
|
|
}
|
||
|
|
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => $result->message,
|
||
|
|
);
|
||
|
|
} catch ( MaxActivationsReachedException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'Maximum number of activations reached. Please deactivate another site first.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( LicenseNotFoundException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License key not found. Please check your license key.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( LicenseExpiredException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'Your license has expired. Please renew to continue.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( SignatureException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License verification failed. Please check your server secret.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
} catch ( LicenseException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => sprintf(
|
||
|
|
/* translators: %s: Error message */
|
||
|
|
__( 'License activation failed: %s', 'wp-fedistream' ),
|
||
|
|
$e->getMessage()
|
||
|
|
),
|
||
|
|
);
|
||
|
|
} catch ( \Throwable $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'Unable to activate license. Please try again later.', 'wp-fedistream' ),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the current license status.
|
||
|
|
*
|
||
|
|
* @param bool $force_refresh Force a fresh check from the server.
|
||
|
|
* @return array{success: bool, message: string, data?: array}
|
||
|
|
*/
|
||
|
|
public function get_status( bool $force_refresh = false ): array {
|
||
|
|
// Check cached status first.
|
||
|
|
if ( ! $force_refresh ) {
|
||
|
|
$cached = $this->get_cached_validation();
|
||
|
|
if ( null !== $cached ) {
|
||
|
|
return $cached;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( ! $this->init_client() ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License server configuration is incomplete.', 'wp-fedistream' ),
|
||
|
|
'data' => array(
|
||
|
|
'status' => 'unconfigured',
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
$license_key = self::get_license_key();
|
||
|
|
if ( empty( $license_key ) ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'No license key configured.', 'wp-fedistream' ),
|
||
|
|
'data' => array(
|
||
|
|
'status' => 'unchecked',
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
$result = $this->client->status( $license_key );
|
||
|
|
|
||
|
|
$status_map = array(
|
||
|
|
LicenseState::Active->value => 'valid',
|
||
|
|
LicenseState::Inactive->value => 'inactive',
|
||
|
|
LicenseState::Expired->value => 'expired',
|
||
|
|
LicenseState::Revoked->value => 'revoked',
|
||
|
|
);
|
||
|
|
|
||
|
|
$status = $status_map[ $result->status->value ] ?? 'invalid';
|
||
|
|
|
||
|
|
$data = array(
|
||
|
|
'status' => $status,
|
||
|
|
'valid' => $result->valid,
|
||
|
|
'domain' => $result->domain,
|
||
|
|
'expires_at' => $result->expiresAt?->format( 'Y-m-d' ),
|
||
|
|
'lifetime' => $result->isLifetime(),
|
||
|
|
'activations_count' => $result->activationsCount,
|
||
|
|
'max_activations' => $result->maxActivations,
|
||
|
|
);
|
||
|
|
|
||
|
|
// Cache the result.
|
||
|
|
$this->cache_validation( array(
|
||
|
|
'success' => $result->valid,
|
||
|
|
'message' => $result->valid
|
||
|
|
? __( 'License is active.', 'wp-fedistream' )
|
||
|
|
: __( 'License is not active.', 'wp-fedistream' ),
|
||
|
|
'data' => $data,
|
||
|
|
) );
|
||
|
|
|
||
|
|
$this->update_cached_status( $status, $data );
|
||
|
|
|
||
|
|
return array(
|
||
|
|
'success' => $result->valid,
|
||
|
|
'message' => $result->valid
|
||
|
|
? __( 'License is active.', 'wp-fedistream' )
|
||
|
|
: __( 'License is not active.', 'wp-fedistream' ),
|
||
|
|
'data' => $data,
|
||
|
|
);
|
||
|
|
} catch ( LicenseNotFoundException $e ) {
|
||
|
|
$this->update_cached_status( 'invalid' );
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License key not found.', 'wp-fedistream' ),
|
||
|
|
'data' => array(
|
||
|
|
'status' => 'invalid',
|
||
|
|
),
|
||
|
|
);
|
||
|
|
} catch ( SignatureException $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'License verification failed. Please check your server secret.', 'wp-fedistream' ),
|
||
|
|
'data' => array(
|
||
|
|
'status' => 'error',
|
||
|
|
),
|
||
|
|
);
|
||
|
|
} catch ( \Throwable $e ) {
|
||
|
|
return array(
|
||
|
|
'success' => false,
|
||
|
|
'message' => __( 'Unable to check license status.', 'wp-fedistream' ),
|
||
|
|
'data' => array(
|
||
|
|
'status' => 'error',
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Deactivate the license (clear local data).
|
||
|
|
*
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public function deactivate(): bool {
|
||
|
|
self::clear_license_data();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if the license is currently valid.
|
||
|
|
*
|
||
|
|
* Uses cached status for performance.
|
||
|
|
*
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function is_license_valid(): bool {
|
||
|
|
$status = get_option( self::OPTION_LICENSE_STATUS, 'unchecked' );
|
||
|
|
return 'valid' === $status;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the license key.
|
||
|
|
*
|
||
|
|
* @return string
|
||
|
|
*/
|
||
|
|
public static function get_license_key(): string {
|
||
|
|
return get_option( self::OPTION_LICENSE_KEY, '' );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the license server URL.
|
||
|
|
*
|
||
|
|
* @return string
|
||
|
|
*/
|
||
|
|
public static function get_server_url(): string {
|
||
|
|
return get_option( self::OPTION_SERVER_URL, '' );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the server secret.
|
||
|
|
*
|
||
|
|
* @return string
|
||
|
|
*/
|
||
|
|
public static function get_server_secret(): string {
|
||
|
|
return get_option( self::OPTION_SERVER_SECRET, '' );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get cached license status.
|
||
|
|
*
|
||
|
|
* @return string
|
||
|
|
*/
|
||
|
|
public static function get_cached_status(): string {
|
||
|
|
return get_option( self::OPTION_LICENSE_STATUS, 'unchecked' );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get cached license data.
|
||
|
|
*
|
||
|
|
* @return array
|
||
|
|
*/
|
||
|
|
public static function get_cached_data(): array {
|
||
|
|
return get_option( self::OPTION_LICENSE_DATA, array() );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get last check timestamp.
|
||
|
|
*
|
||
|
|
* @return int
|
||
|
|
*/
|
||
|
|
public static function get_last_check(): int {
|
||
|
|
return (int) get_option( self::OPTION_LAST_CHECK, 0 );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Save license settings.
|
||
|
|
*
|
||
|
|
* @param array $data Settings data.
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function save_settings( array $data ): bool {
|
||
|
|
if ( isset( $data['license_key'] ) ) {
|
||
|
|
update_option( self::OPTION_LICENSE_KEY, sanitize_text_field( $data['license_key'] ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( isset( $data['server_url'] ) ) {
|
||
|
|
update_option( self::OPTION_SERVER_URL, esc_url_raw( $data['server_url'] ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( isset( $data['server_secret'] ) ) {
|
||
|
|
// Only update if a new secret is provided.
|
||
|
|
$secret = sanitize_text_field( $data['server_secret'] );
|
||
|
|
if ( ! empty( $secret ) ) {
|
||
|
|
update_option( self::OPTION_SERVER_SECRET, $secret );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Reset status when settings change.
|
||
|
|
update_option( self::OPTION_LICENSE_STATUS, 'unchecked' );
|
||
|
|
delete_transient( self::TRANSIENT_LICENSE_CHECK );
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Clear all license data.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public static function clear_license_data(): void {
|
||
|
|
update_option( self::OPTION_LICENSE_STATUS, 'unchecked' );
|
||
|
|
update_option( self::OPTION_LICENSE_DATA, array() );
|
||
|
|
update_option( self::OPTION_LAST_CHECK, 0 );
|
||
|
|
delete_transient( self::TRANSIENT_LICENSE_CHECK );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update cached license status.
|
||
|
|
*
|
||
|
|
* @param string $status Status value.
|
||
|
|
* @param array $data Additional data.
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
private function update_cached_status( string $status, array $data = array() ): void {
|
||
|
|
update_option( self::OPTION_LICENSE_STATUS, $status );
|
||
|
|
update_option( self::OPTION_LICENSE_DATA, $data );
|
||
|
|
update_option( self::OPTION_LAST_CHECK, time() );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Cache validation result.
|
||
|
|
*
|
||
|
|
* @param array $result Validation result.
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
private function cache_validation( array $result ): void {
|
||
|
|
set_transient( self::TRANSIENT_LICENSE_CHECK, $result, self::CACHE_TTL );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get cached validation result.
|
||
|
|
*
|
||
|
|
* @return array|null
|
||
|
|
*/
|
||
|
|
private function get_cached_validation(): ?array {
|
||
|
|
$cached = get_transient( self::TRANSIENT_LICENSE_CHECK );
|
||
|
|
return false === $cached ? null : $cached;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* AJAX handler: Validate license.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function ajax_validate_license(): void {
|
||
|
|
check_ajax_referer( 'fedistream_license_action', 'nonce' );
|
||
|
|
|
||
|
|
if ( ! current_user_can( 'manage_fedistream_settings' ) ) {
|
||
|
|
wp_send_json_error( array(
|
||
|
|
'message' => __( 'You do not have permission to perform this action.', 'wp-fedistream' ),
|
||
|
|
) );
|
||
|
|
}
|
||
|
|
|
||
|
|
$result = $this->validate();
|
||
|
|
|
||
|
|
if ( $result['success'] ) {
|
||
|
|
wp_send_json_success( $result );
|
||
|
|
} else {
|
||
|
|
wp_send_json_error( $result );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* AJAX handler: Activate license.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function ajax_activate_license(): void {
|
||
|
|
check_ajax_referer( 'fedistream_license_action', 'nonce' );
|
||
|
|
|
||
|
|
if ( ! current_user_can( 'manage_fedistream_settings' ) ) {
|
||
|
|
wp_send_json_error( array(
|
||
|
|
'message' => __( 'You do not have permission to perform this action.', 'wp-fedistream' ),
|
||
|
|
) );
|
||
|
|
}
|
||
|
|
|
||
|
|
$result = $this->activate();
|
||
|
|
|
||
|
|
if ( $result['success'] ) {
|
||
|
|
wp_send_json_success( $result );
|
||
|
|
} else {
|
||
|
|
wp_send_json_error( $result );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* AJAX handler: Deactivate license.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function ajax_deactivate_license(): void {
|
||
|
|
check_ajax_referer( 'fedistream_license_action', 'nonce' );
|
||
|
|
|
||
|
|
if ( ! current_user_can( 'manage_fedistream_settings' ) ) {
|
||
|
|
wp_send_json_error( array(
|
||
|
|
'message' => __( 'You do not have permission to perform this action.', 'wp-fedistream' ),
|
||
|
|
) );
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->deactivate();
|
||
|
|
|
||
|
|
wp_send_json_success( array(
|
||
|
|
'success' => true,
|
||
|
|
'message' => __( 'License deactivated.', 'wp-fedistream' ),
|
||
|
|
) );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* AJAX handler: Check license status.
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
*/
|
||
|
|
public function ajax_check_status(): void {
|
||
|
|
check_ajax_referer( 'fedistream_license_action', 'nonce' );
|
||
|
|
|
||
|
|
if ( ! current_user_can( 'manage_fedistream_settings' ) ) {
|
||
|
|
wp_send_json_error( array(
|
||
|
|
'message' => __( 'You do not have permission to perform this action.', 'wp-fedistream' ),
|
||
|
|
) );
|
||
|
|
}
|
||
|
|
|
||
|
|
$force_refresh = isset( $_POST['force'] ) && 'true' === $_POST['force'];
|
||
|
|
$result = $this->get_status( $force_refresh );
|
||
|
|
|
||
|
|
if ( $result['success'] ) {
|
||
|
|
wp_send_json_success( $result );
|
||
|
|
} else {
|
||
|
|
wp_send_json_error( $result );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|