You've already forked wc-tier-and-package-prices
Release version 1.3.0 - License management and settings sub-tabs
Breaking Changes: - PHP 8.3+ now required (previously 7.4+) Added: - License management integration using magdev/wc-licensed-product-client - Settings page split into General and License sub-tabs - License validation and activation via AJAX - PHP version check with admin notice Changed: - Refactored settings class to use modern WooCommerce patterns - Updated all translations with new license-related strings Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
422
includes/class-wc-tpp-settings.php
Normal file → Executable file
422
includes/class-wc-tpp-settings.php
Normal file → Executable file
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* WooCommerce Settings Integration
|
||||
*
|
||||
* Adds Tier & Package Prices settings to WooCommerce Settings > Advanced tab
|
||||
* Adds Tier & Package Prices settings to WooCommerce Settings with sub-tabs
|
||||
*
|
||||
* @package WC_Tier_Package_Prices
|
||||
*/
|
||||
@@ -21,40 +21,39 @@ if (!class_exists('WC_Settings_Page')) {
|
||||
if (!class_exists('WC_TPP_Settings')) {
|
||||
class WC_TPP_Settings extends WC_Settings_Page {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'tier_package_prices';
|
||||
$this->label = __('Tier & Package Prices', 'wc-tier-package-prices');
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'tier_package_prices';
|
||||
$this->label = __('Tier & Package Prices', 'wc-tier-package-prices');
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
parent::__construct();
|
||||
|
||||
/**
|
||||
* Get sections
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sections() {
|
||||
$sections = array(
|
||||
'' => __('General', 'wc-tier-package-prices'),
|
||||
);
|
||||
// Add AJAX handlers for license validation
|
||||
add_action('wp_ajax_wc_tpp_validate_license', array($this, 'ajax_validate_license'));
|
||||
add_action('wp_ajax_wc_tpp_activate_license', array($this, 'ajax_activate_license'));
|
||||
}
|
||||
|
||||
return apply_filters('woocommerce_get_sections_' . $this->id, $sections);
|
||||
}
|
||||
/**
|
||||
* Get own sections - Modern WooCommerce pattern
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_own_sections() {
|
||||
return array(
|
||||
'' => __('General', 'wc-tier-package-prices'),
|
||||
'license' => __('License', 'wc-tier-package-prices'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings array
|
||||
*
|
||||
* @param string $current_section Current section name.
|
||||
* @return array
|
||||
*/
|
||||
public function get_settings($current_section = '') {
|
||||
$settings = array();
|
||||
|
||||
if ('' === $current_section) {
|
||||
$settings = array(
|
||||
/**
|
||||
* Get settings for the default (General) section
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_settings_for_default_section() {
|
||||
return array(
|
||||
array(
|
||||
'title' => __('Tier & Package Prices Settings', 'wc-tier-package-prices'),
|
||||
'type' => 'title',
|
||||
@@ -121,23 +120,352 @@ if (!class_exists('WC_TPP_Settings')) {
|
||||
);
|
||||
}
|
||||
|
||||
return apply_filters('woocommerce_get_settings_' . $this->id, $settings, $current_section);
|
||||
}
|
||||
/**
|
||||
* Get settings for the License section
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_settings_for_license_section() {
|
||||
return array(
|
||||
array(
|
||||
'title' => __('License Management', 'wc-tier-package-prices'),
|
||||
'type' => 'title',
|
||||
'desc' => __('Enter your license key to receive updates and support.', 'wc-tier-package-prices'),
|
||||
'id' => 'wc_tpp_license_settings',
|
||||
),
|
||||
|
||||
/**
|
||||
* Output the settings
|
||||
*/
|
||||
public function output() {
|
||||
$settings = $this->get_settings();
|
||||
WC_Admin_Settings::output_fields($settings);
|
||||
}
|
||||
array(
|
||||
'title' => __('License Server URL', 'wc-tier-package-prices'),
|
||||
'desc' => __('The URL of the license server.', 'wc-tier-package-prices'),
|
||||
'id' => 'wc_tpp_license_server_url',
|
||||
'type' => 'url',
|
||||
'default' => '',
|
||||
'css' => 'min-width:400px;',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
|
||||
/**
|
||||
* Save settings
|
||||
*/
|
||||
public function save() {
|
||||
$settings = $this->get_settings();
|
||||
WC_Admin_Settings::save_fields($settings);
|
||||
array(
|
||||
'title' => __('License Key', 'wc-tier-package-prices'),
|
||||
'desc' => __('Your license key for this plugin.', 'wc-tier-package-prices'),
|
||||
'id' => 'wc_tpp_license_key',
|
||||
'type' => 'text',
|
||||
'default' => '',
|
||||
'css' => 'min-width:400px;',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __('License Status', 'wc-tier-package-prices'),
|
||||
'type' => 'wc_tpp_license_status',
|
||||
'id' => 'wc_tpp_license_status_display',
|
||||
),
|
||||
|
||||
array(
|
||||
'type' => 'sectionend',
|
||||
'id' => 'wc_tpp_license_settings',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached license status
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
private function get_cached_license_status() {
|
||||
return get_transient('wc_tpp_license_status');
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for license validation
|
||||
*/
|
||||
public function ajax_validate_license() {
|
||||
check_ajax_referer('wc_tpp_license_nonce', 'nonce');
|
||||
|
||||
if (!current_user_can('manage_woocommerce')) {
|
||||
wp_send_json_error(array('message' => __('Permission denied.', 'wc-tier-package-prices')));
|
||||
}
|
||||
|
||||
$license_key = sanitize_text_field(wp_unslash($_POST['license_key'] ?? ''));
|
||||
$server_url = esc_url_raw(wp_unslash($_POST['server_url'] ?? ''));
|
||||
|
||||
if (empty($license_key) || empty($server_url)) {
|
||||
wp_send_json_error(array('message' => __('License key and server URL are required.', 'wc-tier-package-prices')));
|
||||
}
|
||||
|
||||
try {
|
||||
$client = $this->get_license_client($server_url);
|
||||
$domain = $this->get_current_domain();
|
||||
$result = $client->validate($license_key, $domain);
|
||||
|
||||
// Cache the status
|
||||
set_transient('wc_tpp_license_status', array(
|
||||
'valid' => true,
|
||||
'product_id' => $result->productId,
|
||||
'expires_at' => $result->expiresAt?->format('Y-m-d H:i:s'),
|
||||
'is_lifetime' => $result->isLifetime(),
|
||||
'checked_at' => current_time('mysql'),
|
||||
), DAY_IN_SECONDS);
|
||||
|
||||
wp_send_json_success(array(
|
||||
'message' => __('License is valid!', 'wc-tier-package-prices'),
|
||||
'status' => $this->get_cached_license_status(),
|
||||
));
|
||||
|
||||
} catch (\Magdev\WcLicensedProductClient\Exception\LicenseException $e) {
|
||||
delete_transient('wc_tpp_license_status');
|
||||
wp_send_json_error(array(
|
||||
'message' => $e->getMessage(),
|
||||
'code' => $e->errorCode ?? 'unknown',
|
||||
));
|
||||
} catch (\Exception $e) {
|
||||
delete_transient('wc_tpp_license_status');
|
||||
wp_send_json_error(array(
|
||||
'message' => $e->getMessage(),
|
||||
'code' => 'exception',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for license activation
|
||||
*/
|
||||
public function ajax_activate_license() {
|
||||
check_ajax_referer('wc_tpp_license_nonce', 'nonce');
|
||||
|
||||
if (!current_user_can('manage_woocommerce')) {
|
||||
wp_send_json_error(array('message' => __('Permission denied.', 'wc-tier-package-prices')));
|
||||
}
|
||||
|
||||
$license_key = sanitize_text_field(wp_unslash($_POST['license_key'] ?? ''));
|
||||
$server_url = esc_url_raw(wp_unslash($_POST['server_url'] ?? ''));
|
||||
|
||||
if (empty($license_key) || empty($server_url)) {
|
||||
wp_send_json_error(array('message' => __('License key and server URL are required.', 'wc-tier-package-prices')));
|
||||
}
|
||||
|
||||
try {
|
||||
$client = $this->get_license_client($server_url);
|
||||
$domain = $this->get_current_domain();
|
||||
$result = $client->activate($license_key, $domain);
|
||||
|
||||
if ($result->success) {
|
||||
// Validate to get full status after activation
|
||||
$validate_result = $client->validate($license_key, $domain);
|
||||
|
||||
set_transient('wc_tpp_license_status', array(
|
||||
'valid' => true,
|
||||
'product_id' => $validate_result->productId,
|
||||
'expires_at' => $validate_result->expiresAt?->format('Y-m-d H:i:s'),
|
||||
'is_lifetime' => $validate_result->isLifetime(),
|
||||
'checked_at' => current_time('mysql'),
|
||||
), DAY_IN_SECONDS);
|
||||
|
||||
wp_send_json_success(array(
|
||||
'message' => __('License activated successfully!', 'wc-tier-package-prices'),
|
||||
'status' => $this->get_cached_license_status(),
|
||||
));
|
||||
}
|
||||
|
||||
wp_send_json_error(array('message' => $result->message));
|
||||
|
||||
} catch (\Magdev\WcLicensedProductClient\Exception\LicenseException $e) {
|
||||
wp_send_json_error(array(
|
||||
'message' => $e->getMessage(),
|
||||
'code' => $e->errorCode ?? 'unknown',
|
||||
));
|
||||
} catch (\Exception $e) {
|
||||
wp_send_json_error(array(
|
||||
'message' => $e->getMessage(),
|
||||
'code' => 'exception',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get license client instance
|
||||
*
|
||||
* @param string $server_url License server URL.
|
||||
* @return \Magdev\WcLicensedProductClient\LicenseClientInterface
|
||||
*/
|
||||
private function get_license_client(string $server_url): \Magdev\WcLicensedProductClient\LicenseClientInterface {
|
||||
$httpClient = \Symfony\Component\HttpClient\HttpClient::create();
|
||||
return new \Magdev\WcLicensedProductClient\LicenseClient(
|
||||
httpClient: $httpClient,
|
||||
baseUrl: $server_url,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current domain for license validation
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_current_domain(): string {
|
||||
return wp_parse_url(home_url(), PHP_URL_HOST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the settings
|
||||
*/
|
||||
public function output() {
|
||||
global $current_section;
|
||||
|
||||
// Register custom field type for license status display
|
||||
add_action('woocommerce_admin_field_wc_tpp_license_status', array($this, 'output_license_status_field'));
|
||||
|
||||
parent::output();
|
||||
|
||||
// Add JavaScript for license section
|
||||
if ('license' === $current_section) {
|
||||
$this->output_license_scripts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output license status custom field
|
||||
*
|
||||
* @param array $value Field configuration.
|
||||
*/
|
||||
public function output_license_status_field($value) {
|
||||
$status = $this->get_cached_license_status();
|
||||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label><?php esc_html_e('License Status', 'wc-tier-package-prices'); ?></label>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<div id="wc-tpp-license-status-container" class="<?php echo !empty($status['valid']) ? 'valid' : 'invalid'; ?>">
|
||||
<?php $this->render_license_status_html($status); ?>
|
||||
</div>
|
||||
<p class="description" style="margin-top: 10px;">
|
||||
<button type="button" class="button" id="wc-tpp-validate-license">
|
||||
<?php esc_html_e('Validate License', 'wc-tier-package-prices'); ?>
|
||||
</button>
|
||||
<button type="button" class="button" id="wc-tpp-activate-license">
|
||||
<?php esc_html_e('Activate License', 'wc-tier-package-prices'); ?>
|
||||
</button>
|
||||
<span class="spinner" id="wc-tpp-license-spinner"></span>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render license status HTML
|
||||
*
|
||||
* @param array|false $status License status data.
|
||||
*/
|
||||
private function render_license_status_html($status) {
|
||||
if (empty($status)) {
|
||||
echo '<span class="wc-tpp-license-inactive">' . esc_html__('No license activated', 'wc-tier-package-prices') . '</span>';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($status['valid'])) {
|
||||
echo '<span class="wc-tpp-license-active">' . esc_html__('License Active', 'wc-tier-package-prices') . '</span>';
|
||||
if (!empty($status['expires_at']) && empty($status['is_lifetime'])) {
|
||||
echo '<br><small>' . sprintf(
|
||||
/* translators: %s: Expiration date */
|
||||
esc_html__('Expires: %s', 'wc-tier-package-prices'),
|
||||
esc_html($status['expires_at'])
|
||||
) . '</small>';
|
||||
} elseif (!empty($status['is_lifetime'])) {
|
||||
echo '<br><small>' . esc_html__('Lifetime License', 'wc-tier-package-prices') . '</small>';
|
||||
}
|
||||
if (!empty($status['checked_at'])) {
|
||||
echo '<br><small>' . sprintf(
|
||||
/* translators: %s: Last check timestamp */
|
||||
esc_html__('Last checked: %s', 'wc-tier-package-prices'),
|
||||
esc_html($status['checked_at'])
|
||||
) . '</small>';
|
||||
}
|
||||
} else {
|
||||
echo '<span class="wc-tpp-license-inactive">' . esc_html__('License Invalid', 'wc-tier-package-prices') . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output JavaScript for license management
|
||||
*/
|
||||
private function output_license_scripts() {
|
||||
$nonce = wp_create_nonce('wc_tpp_license_nonce');
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
jQuery(function($) {
|
||||
var $validateBtn = $('#wc-tpp-validate-license');
|
||||
var $activateBtn = $('#wc-tpp-activate-license');
|
||||
var $spinner = $('#wc-tpp-license-spinner');
|
||||
|
||||
function getLicenseData() {
|
||||
return {
|
||||
license_key: $('#wc_tpp_license_key').val(),
|
||||
server_url: $('#wc_tpp_license_server_url').val(),
|
||||
nonce: '<?php echo esc_js($nonce); ?>'
|
||||
};
|
||||
}
|
||||
|
||||
function showSpinner() {
|
||||
$spinner.addClass('is-active');
|
||||
$validateBtn.prop('disabled', true);
|
||||
$activateBtn.prop('disabled', true);
|
||||
}
|
||||
|
||||
function hideSpinner() {
|
||||
$spinner.removeClass('is-active');
|
||||
$validateBtn.prop('disabled', false);
|
||||
$activateBtn.prop('disabled', false);
|
||||
}
|
||||
|
||||
$validateBtn.on('click', function() {
|
||||
var data = getLicenseData();
|
||||
if (!data.license_key || !data.server_url) {
|
||||
alert('<?php echo esc_js(__('Please enter both license server URL and license key.', 'wc-tier-package-prices')); ?>');
|
||||
return;
|
||||
}
|
||||
|
||||
showSpinner();
|
||||
$.post(ajaxurl, $.extend({action: 'wc_tpp_validate_license'}, data))
|
||||
.done(function(response) {
|
||||
if (response.success) {
|
||||
alert(response.data.message);
|
||||
location.reload();
|
||||
} else {
|
||||
alert(response.data.message || '<?php echo esc_js(__('Validation failed.', 'wc-tier-package-prices')); ?>');
|
||||
}
|
||||
})
|
||||
.fail(function() {
|
||||
alert('<?php echo esc_js(__('Request failed. Please try again.', 'wc-tier-package-prices')); ?>');
|
||||
})
|
||||
.always(hideSpinner);
|
||||
});
|
||||
|
||||
$activateBtn.on('click', function() {
|
||||
var data = getLicenseData();
|
||||
if (!data.license_key || !data.server_url) {
|
||||
alert('<?php echo esc_js(__('Please enter both license server URL and license key.', 'wc-tier-package-prices')); ?>');
|
||||
return;
|
||||
}
|
||||
|
||||
showSpinner();
|
||||
$.post(ajaxurl, $.extend({action: 'wc_tpp_activate_license'}, data))
|
||||
.done(function(response) {
|
||||
if (response.success) {
|
||||
alert(response.data.message);
|
||||
location.reload();
|
||||
} else {
|
||||
alert(response.data.message || '<?php echo esc_js(__('Activation failed.', 'wc-tier-package-prices')); ?>');
|
||||
}
|
||||
})
|
||||
.fail(function() {
|
||||
alert('<?php echo esc_js(__('Request failed. Please try again.', 'wc-tier-package-prices')); ?>');
|
||||
})
|
||||
.always(hideSpinner);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user