You've already forked wc-licensed-product
Add licensed variable product support for duration-based licenses (v0.5.3)
Customers can now purchase licenses with different durations (monthly, yearly, lifetime) through WooCommerce product variations. Each variation can have its own license validity settings. New features: - LicensedVariableProduct class for variable licensed products - LicensedProductVariation class for individual variations - Per-variation license duration and max activations settings - Duration labels in checkout (Monthly, Quarterly, Yearly, etc.) - Full support for WooCommerce Blocks checkout with variations - Updated translations for German (de_CH) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,8 @@ namespace Jeremias\WcLicensedProduct\Product;
|
||||
use Jeremias\WcLicensedProduct\Admin\SettingsController;
|
||||
|
||||
/**
|
||||
* Registers and handles the Licensed product type for WooCommerce
|
||||
* Registers and handles the Licensed product types for WooCommerce
|
||||
* Supports both simple licensed products and variable licensed products
|
||||
*/
|
||||
final class LicensedProductType
|
||||
{
|
||||
@@ -29,7 +30,7 @@ final class LicensedProductType
|
||||
*/
|
||||
private function registerHooks(): void
|
||||
{
|
||||
// Register product type
|
||||
// Register product types
|
||||
add_filter('product_type_selector', [$this, 'addProductType']);
|
||||
add_filter('woocommerce_product_class', [$this, 'getProductClass'], 10, 2);
|
||||
|
||||
@@ -39,9 +40,11 @@ final class LicensedProductType
|
||||
|
||||
// Save product meta
|
||||
add_action('woocommerce_process_product_meta_licensed', [$this, 'saveProductMeta']);
|
||||
add_action('woocommerce_process_product_meta_licensed-variable', [$this, 'saveProductMeta']);
|
||||
|
||||
// Show price and add to cart for licensed products
|
||||
add_action('woocommerce_licensed_add_to_cart', [$this, 'addToCartTemplate']);
|
||||
add_action('woocommerce_licensed-variable_add_to_cart', [$this, 'variableAddToCartTemplate']);
|
||||
|
||||
// Make product virtual by default
|
||||
add_filter('woocommerce_product_is_virtual', [$this, 'isVirtual'], 10, 2);
|
||||
@@ -51,25 +54,48 @@ final class LicensedProductType
|
||||
|
||||
// Enqueue frontend CSS for licensed products on single product pages
|
||||
add_action('wp_enqueue_scripts', [$this, 'enqueueFrontendStyles']);
|
||||
|
||||
// Variable product support - variation settings
|
||||
add_action('woocommerce_variation_options', [$this, 'addVariationOptions'], 10, 3);
|
||||
add_action('woocommerce_product_after_variable_attributes', [$this, 'addVariationFields'], 10, 3);
|
||||
add_action('woocommerce_save_product_variation', [$this, 'saveVariationFields'], 10, 2);
|
||||
|
||||
// Admin scripts for licensed-variable type
|
||||
add_action('admin_footer', [$this, 'addVariableProductScripts']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add product type to selector
|
||||
* Add product types to selector
|
||||
*/
|
||||
public function addProductType(array $types): array
|
||||
{
|
||||
$types['licensed'] = __('Licensed Product', 'wc-licensed-product');
|
||||
$types['licensed-variable'] = __('Licensed Variable Product', 'wc-licensed-product');
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product class for licensed type
|
||||
* Get product class for licensed types
|
||||
*/
|
||||
public function getProductClass(string $className, string $productType): string
|
||||
{
|
||||
if ($productType === 'licensed') {
|
||||
return LicensedProduct::class;
|
||||
}
|
||||
if ($productType === 'licensed-variable') {
|
||||
return LicensedVariableProduct::class;
|
||||
}
|
||||
// Handle variations of licensed-variable products
|
||||
if ($productType === 'variation') {
|
||||
// Check if parent is licensed-variable
|
||||
global $post;
|
||||
if ($post && $post->post_parent) {
|
||||
$parentType = \WC_Product_Factory::get_product_type($post->post_parent);
|
||||
if ($parentType === 'licensed-variable') {
|
||||
return LicensedProductVariation::class;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $className;
|
||||
}
|
||||
|
||||
@@ -81,7 +107,7 @@ final class LicensedProductType
|
||||
$tabs['licensed_product'] = [
|
||||
'label' => __('License Settings', 'wc-licensed-product'),
|
||||
'target' => 'licensed_product_data',
|
||||
'class' => ['show_if_licensed'],
|
||||
'class' => ['show_if_licensed', 'show_if_licensed-variable'],
|
||||
'priority' => 21,
|
||||
];
|
||||
return $tabs;
|
||||
@@ -236,9 +262,16 @@ final class LicensedProductType
|
||||
*/
|
||||
public function isVirtual(bool $isVirtual, \WC_Product $product): bool
|
||||
{
|
||||
if ($product->is_type('licensed')) {
|
||||
if ($product->is_type('licensed') || $product->is_type('licensed-variable')) {
|
||||
return true;
|
||||
}
|
||||
// Also handle variations of licensed-variable products
|
||||
if ($product->is_type('variation') && $product->get_parent_id()) {
|
||||
$parent = wc_get_product($product->get_parent_id());
|
||||
if ($parent && $parent->is_type('licensed-variable')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $isVirtual;
|
||||
}
|
||||
|
||||
@@ -253,7 +286,7 @@ final class LicensedProductType
|
||||
|
||||
global $product;
|
||||
|
||||
if (!$product || !$product->is_type('licensed')) {
|
||||
if (!$product || (!$product->is_type('licensed') && !$product->is_type('licensed-variable'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -272,11 +305,11 @@ final class LicensedProductType
|
||||
{
|
||||
global $product;
|
||||
|
||||
if (!$product || !$product->is_type('licensed')) {
|
||||
if (!$product || (!$product->is_type('licensed') && !$product->is_type('licensed-variable'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var LicensedProduct $product */
|
||||
/** @var LicensedProduct|LicensedVariableProduct $product */
|
||||
$version = $product->get_current_version();
|
||||
|
||||
if (empty($version)) {
|
||||
@@ -289,4 +322,200 @@ final class LicensedProductType
|
||||
esc_html($version)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to cart template for variable licensed products
|
||||
*/
|
||||
public function variableAddToCartTemplate(): void
|
||||
{
|
||||
wc_get_template('single-product/add-to-cart/variable.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add variation options (checkboxes next to variation header)
|
||||
*/
|
||||
public function addVariationOptions(int $loop, array $variationData, \WP_Post $variation): void
|
||||
{
|
||||
// Check if parent is licensed-variable
|
||||
$parentId = $variation->post_parent;
|
||||
$parentProduct = wc_get_product($parentId);
|
||||
|
||||
if (!$parentProduct || !$parentProduct->is_type('licensed-variable')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$isVirtual = get_post_meta($variation->ID, '_virtual', true);
|
||||
?>
|
||||
<label class="tips" data-tip="<?php esc_attr_e('Licensed products are always virtual', 'wc-licensed-product'); ?>">
|
||||
<input type="checkbox" class="checkbox" disabled checked />
|
||||
<?php esc_html_e('Virtual', 'wc-licensed-product'); ?>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Add variation fields for license settings
|
||||
*/
|
||||
public function addVariationFields(int $loop, array $variationData, \WP_Post $variation): void
|
||||
{
|
||||
// Check if parent is licensed-variable
|
||||
$parentId = $variation->post_parent;
|
||||
$parentProduct = wc_get_product($parentId);
|
||||
|
||||
if (!$parentProduct || !$parentProduct->is_type('licensed-variable')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get variation values
|
||||
$validityDays = get_post_meta($variation->ID, '_licensed_validity_days', true);
|
||||
$maxActivations = get_post_meta($variation->ID, '_licensed_max_activations', true);
|
||||
|
||||
// Get parent defaults for placeholder
|
||||
$parentValidityDays = $parentProduct->get_validity_days();
|
||||
$parentMaxActivations = $parentProduct->get_max_activations();
|
||||
|
||||
$parentValidityDisplay = $parentValidityDays !== null
|
||||
? sprintf(__('%d days', 'wc-licensed-product'), $parentValidityDays)
|
||||
: __('Lifetime', 'wc-licensed-product');
|
||||
|
||||
?>
|
||||
<div class="wclp-variation-license-settings">
|
||||
<p class="form-row form-row-first">
|
||||
<label><?php esc_html_e('License Duration (Days)', 'wc-licensed-product'); ?></label>
|
||||
<input type="number"
|
||||
name="wclp_validity_days[<?php echo esc_attr($loop); ?>]"
|
||||
class="short"
|
||||
min="0"
|
||||
step="1"
|
||||
placeholder="<?php echo esc_attr($parentValidityDisplay); ?>"
|
||||
value="<?php echo esc_attr($validityDays); ?>"
|
||||
/>
|
||||
<span class="description"><?php esc_html_e('Leave empty for parent default. 0 = Lifetime.', 'wc-licensed-product'); ?></span>
|
||||
</p>
|
||||
<p class="form-row form-row-last">
|
||||
<label><?php esc_html_e('Max Activations', 'wc-licensed-product'); ?></label>
|
||||
<input type="number"
|
||||
name="wclp_max_activations[<?php echo esc_attr($loop); ?>]"
|
||||
class="short"
|
||||
min="1"
|
||||
step="1"
|
||||
placeholder="<?php echo esc_attr($parentMaxActivations); ?>"
|
||||
value="<?php echo esc_attr($maxActivations); ?>"
|
||||
/>
|
||||
<span class="description"><?php esc_html_e('Leave empty for parent default.', 'wc-licensed-product'); ?></span>
|
||||
</p>
|
||||
</div>
|
||||
<style>
|
||||
.wclp-variation-license-settings {
|
||||
background: #f8f8f8;
|
||||
border: 1px solid #e5e5e5;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.wclp-variation-license-settings .description {
|
||||
display: block;
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save variation fields
|
||||
*/
|
||||
public function saveVariationFields(int $variationId, int $loop): void
|
||||
{
|
||||
// Check if parent is licensed-variable
|
||||
$variation = wc_get_product($variationId);
|
||||
if (!$variation) {
|
||||
return;
|
||||
}
|
||||
|
||||
$parentProduct = wc_get_product($variation->get_parent_id());
|
||||
if (!$parentProduct || !$parentProduct->is_type('licensed-variable')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save validity days
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce is verified by WooCommerce
|
||||
if (isset($_POST['wclp_validity_days'][$loop])) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$validityDays = sanitize_text_field($_POST['wclp_validity_days'][$loop]);
|
||||
if ($validityDays !== '') {
|
||||
update_post_meta($variationId, '_licensed_validity_days', absint($validityDays));
|
||||
} else {
|
||||
delete_post_meta($variationId, '_licensed_validity_days');
|
||||
}
|
||||
}
|
||||
|
||||
// Save max activations
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
if (isset($_POST['wclp_max_activations'][$loop])) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$maxActivations = sanitize_text_field($_POST['wclp_max_activations'][$loop]);
|
||||
if ($maxActivations !== '') {
|
||||
update_post_meta($variationId, '_licensed_max_activations', absint($maxActivations));
|
||||
} else {
|
||||
delete_post_meta($variationId, '_licensed_max_activations');
|
||||
}
|
||||
}
|
||||
|
||||
// Set variation as virtual (licensed products are always virtual)
|
||||
update_post_meta($variationId, '_virtual', 'yes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add JavaScript for licensed-variable product type in admin
|
||||
*/
|
||||
public function addVariableProductScripts(): void
|
||||
{
|
||||
global $post, $pagenow;
|
||||
|
||||
if ($pagenow !== 'post.php' && $pagenow !== 'post-new.php') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$post || get_post_type($post) !== 'product') {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function($) {
|
||||
// Show/hide panels based on product type
|
||||
function toggleLicensedVariableOptions() {
|
||||
var productType = $('#product-type').val();
|
||||
|
||||
if (productType === 'licensed-variable') {
|
||||
// Show variable product options
|
||||
$('.show_if_variable').show();
|
||||
$('.hide_if_variable').hide();
|
||||
|
||||
// Show licensed product options
|
||||
$('.show_if_licensed-variable').show();
|
||||
$('.show_if_licensed').show();
|
||||
|
||||
// Show general and variations tabs
|
||||
$('.general_tab').show();
|
||||
$('.variations_tab').show();
|
||||
|
||||
// Hide shipping tab (virtual products)
|
||||
$('.shipping_tab').hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Initial check
|
||||
toggleLicensedVariableOptions();
|
||||
|
||||
// On product type change
|
||||
$('#product-type').on('change', function() {
|
||||
toggleLicensedVariableOptions();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
196
src/Product/LicensedProductVariation.php
Normal file
196
src/Product/LicensedProductVariation.php
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/**
|
||||
* Licensed Product Variation Class
|
||||
*
|
||||
* @package Jeremias\WcLicensedProduct\Product
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jeremias\WcLicensedProduct\Product;
|
||||
|
||||
use Jeremias\WcLicensedProduct\Admin\SettingsController;
|
||||
use WC_Product_Variation;
|
||||
|
||||
/**
|
||||
* Licensed Product Variation type extending WooCommerce Product Variation
|
||||
*
|
||||
* Each variation can have its own license duration settings.
|
||||
*/
|
||||
class LicensedProductVariation extends WC_Product_Variation
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($product = 0)
|
||||
{
|
||||
parent::__construct($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Licensed products are always virtual
|
||||
*/
|
||||
public function is_virtual(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get max activations for this variation
|
||||
* Falls back to parent product, then to default settings
|
||||
*/
|
||||
public function get_max_activations(): int
|
||||
{
|
||||
// Check variation-specific setting first
|
||||
$value = $this->get_meta('_licensed_max_activations', true);
|
||||
if ($value !== '' && $value !== null) {
|
||||
return max(1, (int) $value);
|
||||
}
|
||||
|
||||
// Fall back to parent product
|
||||
$parent = wc_get_product($this->get_parent_id());
|
||||
if ($parent && method_exists($parent, 'get_max_activations')) {
|
||||
return $parent->get_max_activations();
|
||||
}
|
||||
|
||||
return SettingsController::getDefaultMaxActivations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if variation has custom max activations set
|
||||
*/
|
||||
public function has_custom_max_activations(): bool
|
||||
{
|
||||
$value = $this->get_meta('_licensed_max_activations', true);
|
||||
return $value !== '' && $value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get validity days for this variation
|
||||
* This is the primary license setting that varies per variation
|
||||
* Falls back to parent product, then to default settings
|
||||
*/
|
||||
public function get_validity_days(): ?int
|
||||
{
|
||||
// Check variation-specific setting first
|
||||
$value = $this->get_meta('_licensed_validity_days', true);
|
||||
if ($value !== '' && $value !== null) {
|
||||
$days = (int) $value;
|
||||
// 0 means lifetime
|
||||
return $days > 0 ? $days : null;
|
||||
}
|
||||
|
||||
// Fall back to parent product
|
||||
$parent = wc_get_product($this->get_parent_id());
|
||||
if ($parent && method_exists($parent, 'get_validity_days')) {
|
||||
return $parent->get_validity_days();
|
||||
}
|
||||
|
||||
return SettingsController::getDefaultValidityDays();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if variation has custom validity days set
|
||||
*/
|
||||
public function has_custom_validity_days(): bool
|
||||
{
|
||||
$value = $this->get_meta('_licensed_validity_days', true);
|
||||
return $value !== '' && $value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if license should be bound to major version
|
||||
* Falls back to parent product, then to default settings
|
||||
*/
|
||||
public function is_bound_to_version(): bool
|
||||
{
|
||||
// Check variation-specific setting first
|
||||
$value = $this->get_meta('_licensed_bind_to_version', true);
|
||||
if ($value !== '' && $value !== null) {
|
||||
return $value === 'yes';
|
||||
}
|
||||
|
||||
// Fall back to parent product
|
||||
$parent = wc_get_product($this->get_parent_id());
|
||||
if ($parent && method_exists($parent, 'is_bound_to_version')) {
|
||||
return $parent->is_bound_to_version();
|
||||
}
|
||||
|
||||
return SettingsController::getDefaultBindToVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if variation has custom bind to version setting
|
||||
*/
|
||||
public function has_custom_bind_to_version(): bool
|
||||
{
|
||||
$value = $this->get_meta('_licensed_bind_to_version', true);
|
||||
return $value !== '' && $value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the license duration label for display
|
||||
*/
|
||||
public function get_license_duration_label(): string
|
||||
{
|
||||
$days = $this->get_validity_days();
|
||||
|
||||
if ($days === null) {
|
||||
return __('Lifetime', 'wc-licensed-product');
|
||||
}
|
||||
|
||||
if ($days === 30) {
|
||||
return __('Monthly', 'wc-licensed-product');
|
||||
}
|
||||
|
||||
if ($days === 90) {
|
||||
return __('Quarterly', 'wc-licensed-product');
|
||||
}
|
||||
|
||||
if ($days === 365) {
|
||||
return __('Yearly', 'wc-licensed-product');
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
/* translators: %d: number of days */
|
||||
_n('%d day', '%d days', $days, 'wc-licensed-product'),
|
||||
$days
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current software version from parent product
|
||||
*/
|
||||
public function get_current_version(): string
|
||||
{
|
||||
$parent = wc_get_product($this->get_parent_id());
|
||||
if ($parent && method_exists($parent, 'get_current_version')) {
|
||||
return $parent->get_current_version();
|
||||
}
|
||||
|
||||
$versionManager = new VersionManager();
|
||||
$latestVersion = $versionManager->getLatestVersion($this->get_parent_id());
|
||||
|
||||
return $latestVersion ? $latestVersion->getVersion() : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get major version number from parent product
|
||||
*/
|
||||
public function get_major_version(): int
|
||||
{
|
||||
$parent = wc_get_product($this->get_parent_id());
|
||||
if ($parent && method_exists($parent, 'get_major_version')) {
|
||||
return $parent->get_major_version();
|
||||
}
|
||||
|
||||
$versionManager = new VersionManager();
|
||||
$latestVersion = $versionManager->getLatestVersion($this->get_parent_id());
|
||||
|
||||
if ($latestVersion) {
|
||||
return $latestVersion->getMajorVersion();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
151
src/Product/LicensedVariableProduct.php
Normal file
151
src/Product/LicensedVariableProduct.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
/**
|
||||
* Licensed Variable Product Class
|
||||
*
|
||||
* @package Jeremias\WcLicensedProduct\Product
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jeremias\WcLicensedProduct\Product;
|
||||
|
||||
use Jeremias\WcLicensedProduct\Admin\SettingsController;
|
||||
use WC_Product_Variable;
|
||||
|
||||
/**
|
||||
* Licensed Variable Product type extending WooCommerce Variable Product
|
||||
*
|
||||
* This allows selling license subscriptions with different durations
|
||||
* (e.g., monthly, yearly, lifetime) as product variations.
|
||||
*/
|
||||
class LicensedVariableProduct extends WC_Product_Variable
|
||||
{
|
||||
/**
|
||||
* Product type
|
||||
*/
|
||||
protected $product_type = 'licensed-variable';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($product = 0)
|
||||
{
|
||||
parent::__construct($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product type
|
||||
*/
|
||||
public function get_type(): string
|
||||
{
|
||||
return 'licensed-variable';
|
||||
}
|
||||
|
||||
/**
|
||||
* Licensed products are always virtual
|
||||
*/
|
||||
public function is_virtual(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Licensed products are purchasable
|
||||
*/
|
||||
public function is_purchasable(): bool
|
||||
{
|
||||
return $this->exists() && $this->get_price() !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get max activations for this product (parent default)
|
||||
* Falls back to default settings if not set on product
|
||||
*/
|
||||
public function get_max_activations(): int
|
||||
{
|
||||
$value = $this->get_meta('_licensed_max_activations', true);
|
||||
if ($value !== '' && $value !== null) {
|
||||
return max(1, (int) $value);
|
||||
}
|
||||
return SettingsController::getDefaultMaxActivations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if product has custom max activations set
|
||||
*/
|
||||
public function has_custom_max_activations(): bool
|
||||
{
|
||||
$value = $this->get_meta('_licensed_max_activations', true);
|
||||
return $value !== '' && $value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get validity days (parent default - variations override this)
|
||||
* Falls back to default settings if not set on product
|
||||
*/
|
||||
public function get_validity_days(): ?int
|
||||
{
|
||||
$value = $this->get_meta('_licensed_validity_days', true);
|
||||
if ($value !== '' && $value !== null) {
|
||||
return (int) $value > 0 ? (int) $value : null;
|
||||
}
|
||||
return SettingsController::getDefaultValidityDays();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if product has custom validity days set
|
||||
*/
|
||||
public function has_custom_validity_days(): bool
|
||||
{
|
||||
$value = $this->get_meta('_licensed_validity_days', true);
|
||||
return $value !== '' && $value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if license should be bound to major version
|
||||
* Falls back to default settings if not set on product
|
||||
*/
|
||||
public function is_bound_to_version(): bool
|
||||
{
|
||||
$value = $this->get_meta('_licensed_bind_to_version', true);
|
||||
if ($value !== '' && $value !== null) {
|
||||
return $value === 'yes';
|
||||
}
|
||||
return SettingsController::getDefaultBindToVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if product has custom bind to version setting
|
||||
*/
|
||||
public function has_custom_bind_to_version(): bool
|
||||
{
|
||||
$value = $this->get_meta('_licensed_bind_to_version', true);
|
||||
return $value !== '' && $value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current software version (derived from latest product version)
|
||||
*/
|
||||
public function get_current_version(): string
|
||||
{
|
||||
$versionManager = new VersionManager();
|
||||
$latestVersion = $versionManager->getLatestVersion($this->get_id());
|
||||
|
||||
return $latestVersion ? $latestVersion->getVersion() : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get major version number from version string
|
||||
*/
|
||||
public function get_major_version(): int
|
||||
{
|
||||
$versionManager = new VersionManager();
|
||||
$latestVersion = $versionManager->getLatestVersion($this->get_id());
|
||||
|
||||
if ($latestVersion) {
|
||||
return $latestVersion->getMajorVersion();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user