You've already forked wc-licensed-product
Fix licensed variable products showing as sold out (v0.5.11)
- Fixed is_purchasable() method in LicensedVariableProduct to delegate to parent WC_Product_Variable instead of checking for price (variable products don't have direct prices, only their variations do) - Fixed getProductClass() filter to accept all 4 WooCommerce parameters and use product_id for reliable variation parent detection - Fallback to global $post when product_id not available for backwards compat Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.5.11] - 2026-01-27
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **CRITICAL:** Fixed "sold out" message on licensed variable products by correcting `is_purchasable()` method
|
||||||
|
- Variable products don't have a direct price - `is_purchasable()` now delegates to parent `WC_Product_Variable` class
|
||||||
|
- Fixed variation class detection by using product ID parameter instead of unreliable global `$post`
|
||||||
|
- Product class filter now properly accepts all 4 WooCommerce filter parameters for reliable variation detection
|
||||||
|
|
||||||
## [0.5.10] - 2026-01-27
|
## [0.5.10] - 2026-01-27
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
BIN
releases/wc-licensed-product-0.5.11.zip
Normal file
BIN
releases/wc-licensed-product-0.5.11.zip
Normal file
Binary file not shown.
1
releases/wc-licensed-product-0.5.11.zip.sha256
Normal file
1
releases/wc-licensed-product-0.5.11.zip.sha256
Normal file
@@ -0,0 +1 @@
|
|||||||
|
32571178bfa8f0d0a03ed05b498d5f9b3c860104393a96732e86a03b6de298d2 wc-licensed-product-0.5.11.zip
|
||||||
@@ -32,7 +32,7 @@ final class LicensedProductType
|
|||||||
{
|
{
|
||||||
// Register product types
|
// Register product types
|
||||||
add_filter('product_type_selector', [$this, 'addProductType']);
|
add_filter('product_type_selector', [$this, 'addProductType']);
|
||||||
add_filter('woocommerce_product_class', [$this, 'getProductClass'], 10, 2);
|
add_filter('woocommerce_product_class', [$this, 'getProductClass'], 10, 4);
|
||||||
|
|
||||||
// Add product data tabs
|
// Add product data tabs
|
||||||
add_filter('woocommerce_product_data_tabs', [$this, 'addProductDataTab']);
|
add_filter('woocommerce_product_data_tabs', [$this, 'addProductDataTab']);
|
||||||
@@ -76,8 +76,13 @@ final class LicensedProductType
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get product class for licensed types
|
* Get product class for licensed types
|
||||||
|
*
|
||||||
|
* @param string $className Default class name
|
||||||
|
* @param string $productType Product type
|
||||||
|
* @param string $postType Post type (usually 'product' or 'product_variation')
|
||||||
|
* @param int $productId Product ID
|
||||||
*/
|
*/
|
||||||
public function getProductClass(string $className, string $productType): string
|
public function getProductClass(string $className, string $productType, string $postType = '', int $productId = 0): string
|
||||||
{
|
{
|
||||||
if ($productType === 'licensed') {
|
if ($productType === 'licensed') {
|
||||||
return LicensedProduct::class;
|
return LicensedProduct::class;
|
||||||
@@ -87,10 +92,21 @@ final class LicensedProductType
|
|||||||
}
|
}
|
||||||
// Handle variations of licensed-variable products
|
// Handle variations of licensed-variable products
|
||||||
if ($productType === 'variation') {
|
if ($productType === 'variation') {
|
||||||
// Check if parent is licensed-variable
|
// Get parent ID from the product post
|
||||||
|
$parentId = 0;
|
||||||
|
if ($productId > 0) {
|
||||||
|
$parentId = wp_get_post_parent_id($productId);
|
||||||
|
}
|
||||||
|
// Fallback to global $post if product ID not available
|
||||||
|
if (!$parentId) {
|
||||||
global $post;
|
global $post;
|
||||||
if ($post && $post->post_parent) {
|
if ($post && $post->post_parent) {
|
||||||
$parentType = \WC_Product_Factory::get_product_type($post->post_parent);
|
$parentId = $post->post_parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($parentId) {
|
||||||
|
$parentType = \WC_Product_Factory::get_product_type($parentId);
|
||||||
if ($parentType === 'licensed-variable') {
|
if ($parentType === 'licensed-variable') {
|
||||||
return LicensedProductVariation::class;
|
return LicensedProductVariation::class;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,11 +50,14 @@ class LicensedVariableProduct extends WC_Product_Variable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Licensed products are purchasable
|
* Licensed variable products are purchasable if the parent check passes
|
||||||
|
* Variable products don't have a direct price - their variations do
|
||||||
*/
|
*/
|
||||||
public function is_purchasable(): bool
|
public function is_purchasable(): bool
|
||||||
{
|
{
|
||||||
return $this->exists() && $this->get_price() !== '';
|
// Use the parent WC_Product_Variable logic
|
||||||
|
// which checks exists() and status, not price
|
||||||
|
return parent::is_purchasable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Plugin Name: WooCommerce Licensed Product
|
* Plugin Name: WooCommerce Licensed Product
|
||||||
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-licensed-product
|
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-licensed-product
|
||||||
* Description: WooCommerce plugin to sell software products using license keys with domain-based validation.
|
* Description: WooCommerce plugin to sell software products using license keys with domain-based validation.
|
||||||
* Version: 0.5.10
|
* Version: 0.5.11
|
||||||
* Author: Marco Graetsch
|
* Author: Marco Graetsch
|
||||||
* Author URI: https://src.bundespruefstelle.ch/magdev
|
* Author URI: https://src.bundespruefstelle.ch/magdev
|
||||||
* License: GPL-2.0-or-later
|
* License: GPL-2.0-or-later
|
||||||
@@ -28,7 +28,7 @@ if (!defined('ABSPATH')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Plugin constants
|
// Plugin constants
|
||||||
define('WC_LICENSED_PRODUCT_VERSION', '0.5.10');
|
define('WC_LICENSED_PRODUCT_VERSION', '0.5.11');
|
||||||
define('WC_LICENSED_PRODUCT_PLUGIN_FILE', __FILE__);
|
define('WC_LICENSED_PRODUCT_PLUGIN_FILE', __FILE__);
|
||||||
define('WC_LICENSED_PRODUCT_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
define('WC_LICENSED_PRODUCT_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||||
define('WC_LICENSED_PRODUCT_PLUGIN_URL', plugin_dir_url(__FILE__));
|
define('WC_LICENSED_PRODUCT_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||||
|
|||||||
Reference in New Issue
Block a user