v1.2.0 - Fix product selection, cart pricing, admin tabs + CI/CD

Fix three critical bugs that persisted through v1.1.11-v1.1.14:

- Product selection always empty: meta_query checked _product_type in
  postmeta, but WooCommerce uses the product_type taxonomy. Replaced
  with correct tax_query using NOT IN operator.
- Cart price always 0.00: composable_price_calculated flag persisted
  in session, preventing recalculation on page loads. Removed flag;
  static variable already handles per-request dedup.
- Admin tabs both visible on load: JS now triggers WooCommerce native
  tab click instead of manually toggling panel visibility.

Add Gitea CI/CD release workflow triggered on v* tags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 12:01:20 +01:00
parent 29a68b0be4
commit 6507f4d8bb
68 changed files with 351 additions and 82 deletions

View File

@@ -200,7 +200,7 @@ class Cart_Handler {
return;
}
// Use static flag to prevent multiple executions
// Use static flag to prevent multiple executions within the same request
static $already_calculated = false;
if ($already_calculated) {
return;
@@ -208,13 +208,10 @@ class Cart_Handler {
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
if (isset($cart_item['data']) && $cart_item['data']->get_type() === 'composable') {
if (isset($cart_item['composable_products']) && !isset($cart_item['composable_price_calculated'])) {
if (isset($cart_item['composable_products'])) {
$product = $cart_item['data'];
$price = $product->calculate_composed_price($cart_item['composable_products']);
$cart_item['data']->set_price($price);
// Mark as calculated to prevent re-calculation by other plugins
$cart->cart_contents[$cart_item_key]['composable_price_calculated'] = true;
}
}
}

View File

@@ -110,24 +110,20 @@ class Product_Type extends \WC_Product {
'post_status' => 'publish',
'orderby' => 'title',
'order' => 'ASC',
'tax_query' => [],
];
// Exclude composable products from selection
$args['meta_query'] = [
// Exclude composable products using the product_type taxonomy
// (WooCommerce stores product types as taxonomy terms, NOT as postmeta)
$args['tax_query'] = [
'relation' => 'AND',
[
'key' => '_product_type',
'value' => 'composable',
'compare' => '!=',
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => ['composable'],
'operator' => 'NOT IN',
],
];
// Debug logging
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('Composable Product Criteria: ' . print_r($criteria, true));
}
switch ($criteria['type']) {
case 'category':
if (!empty($criteria['categories'])) {
@@ -154,28 +150,20 @@ class Product_Type extends \WC_Product {
case 'sku':
if (!empty($criteria['skus'])) {
$skus = array_map('trim', explode(',', $criteria['skus']));
$args['meta_query'][] = [
'key' => '_sku',
'value' => $skus,
'compare' => 'IN',
$args['meta_query'] = [
[
'key' => '_sku',
'value' => $skus,
'compare' => 'IN',
],
];
}
break;
}
// Debug logging
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('Composable Product Query Args: ' . print_r($args, true));
}
$query = new \WP_Query($args);
$products = [];
// Debug logging
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('Composable Product Query Found: ' . $query->found_posts . ' posts');
}
if ($query->have_posts()) {
foreach ($query->posts as $post) {
$product = wc_get_product($post->ID);
@@ -186,36 +174,21 @@ class Product_Type extends \WC_Product {
// Handle variable products by including their variations
if ($product->is_type('variable')) {
// Get variation IDs directly from the product
$variation_ids = $product->get_children();
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('Variable product ' . $product->get_id() . ' has ' . count($variation_ids) . ' variations');
}
foreach ($variation_ids as $variation_id) {
$variation = wc_get_product($variation_id);
if ($variation && $variation->is_purchasable()) {
$products[] = $variation;
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('Added variation ' . $variation_id . ' - ' . $variation->get_name());
}
}
}
} elseif ($product->is_purchasable()) {
// Simple and other product types
$products[] = $product;
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('Added simple product ' . $product->get_id() . ' - ' . $product->get_name());
}
}
}
}
wp_reset_postdata();
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('Total products available: ' . count($products));
}
return $products;
}