You've already forked wc-tier-and-package-prices
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e4ecc2c0be | |||
| e2e40538df | |||
| 67e11d3030 | |||
| 2de6a92784 | |||
| 47f2ed771b |
0
.claude/commands/.gitignore
vendored
Normal file
0
.claude/commands/.gitignore
vendored
Normal file
@@ -1,5 +0,0 @@
|
|||||||
# Finish the current session
|
|
||||||
|
|
||||||
Update the CLAUDE.md according to your needs and what you've learned in this session.
|
|
||||||
|
|
||||||
Create a commit and push this file to branch `dev`
|
|
||||||
@@ -21,7 +21,25 @@
|
|||||||
"Bash(php -l:*)",
|
"Bash(php -l:*)",
|
||||||
"Bash(git push:*)",
|
"Bash(git push:*)",
|
||||||
"Bash(git checkout:*)",
|
"Bash(git checkout:*)",
|
||||||
"Bash(git rebase:*)"
|
"Bash(git rebase:*)",
|
||||||
|
"Bash(git merge:*)",
|
||||||
|
"Bash(git stash:*)",
|
||||||
|
"Bash(for po in languages/*.po)",
|
||||||
|
"Bash('wc-tier-and-package-prices/*.log' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/.claude/*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/CLAUDE.md' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/releases/*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/node_modules/*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/.DS_Store' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/Thumbs.db' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/.vscode/*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/.idea/*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/*.sublime-*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/notes.*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/logs/*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/templates/cache/*' )",
|
||||||
|
"Bash('wc-tier-and-package-prices/composer.lock' )",
|
||||||
|
"Bash('*/wordpress/*')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
CHANGELOG.md
31
CHANGELOG.md
@@ -5,6 +5,37 @@ All notable changes to WooCommerce Tier and Package Prices will be documented in
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.2.5] - 2025-12-30
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Parent Product Default Pricing**: Variable products can now define tier and package pricing at the parent product level that applies as defaults to all variations. Individual variations can override these defaults with their own specific pricing. This makes it much easier to set up pricing for products with many variations - set defaults once on the parent, then only customize the variations that need different pricing.
|
||||||
|
|
||||||
|
- **Hide Empty Table Headers**: Table headers for tier and package pricing in the admin area now automatically hide when no pricing rules are defined. This creates a cleaner interface when starting to configure a product, showing only the helpful empty state message and "Add" button.
|
||||||
|
|
||||||
|
### Technical Details
|
||||||
|
|
||||||
|
**Parent Fallback Implementation**:
|
||||||
|
- Modified `WC_TPP_Frontend::get_tier_price()` and `WC_TPP_Frontend::get_package_price()` to fall back to parent product pricing when variation doesn't have its own pricing
|
||||||
|
- Updated `WC_TPP_Cart` to use helper methods `get_packages_with_fallback()` and `is_restriction_enabled()` for consistent parent fallback behavior
|
||||||
|
- All cart validation, quantity restriction, and display methods now support parent product defaults
|
||||||
|
- Fixed cart pricing calls to pass parent `$product_id` instead of `$effective_id` for proper fallback resolution
|
||||||
|
|
||||||
|
**CSS Enhancement**:
|
||||||
|
- Added `:has()` pseudo-class selectors to hide table headers when tbody is empty
|
||||||
|
- Leverages existing empty state message styling for consistent UX
|
||||||
|
|
||||||
|
**Backward Compatibility**:
|
||||||
|
- 100% backward compatible - existing products continue working as before
|
||||||
|
- No database migrations required
|
||||||
|
- Variations with specific pricing take precedence over parent defaults
|
||||||
|
|
||||||
|
### Changed Files
|
||||||
|
|
||||||
|
- `includes/class-wc-tpp-frontend.php` - Added parent fallback logic to `get_tier_price()` and `get_package_price()` methods
|
||||||
|
- `includes/class-wc-tpp-cart.php` - Added helper methods `get_packages_with_fallback()` and `is_restriction_enabled()`; updated all cart methods to support parent fallback; fixed pricing calls to use correct product ID
|
||||||
|
- `assets/css/admin.css` - Added CSS rules to hide table headers when no pricing rules exist
|
||||||
|
|
||||||
## [1.2.4] - 2025-12-30
|
## [1.2.4] - 2025-12-30
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
122
CLAUDE.md
122
CLAUDE.md
@@ -1,7 +1,7 @@
|
|||||||
# WooCommerce Tier and Package Prices - AI Context Document
|
# WooCommerce Tier and Package Prices - AI Context Document
|
||||||
|
|
||||||
**Last Updated:** 2025-12-29
|
**Last Updated:** 2025-12-30
|
||||||
**Current Version:** 1.2.4
|
**Current Version:** 1.2.5
|
||||||
**Author:** Marco Graetsch
|
**Author:** Marco Graetsch
|
||||||
**Project Status:** Production-ready WordPress plugin
|
**Project Status:** Production-ready WordPress plugin
|
||||||
|
|
||||||
@@ -305,6 +305,41 @@ Location: includes/class-wc-tpp-cart.php:233
|
|||||||
- **Fix:** Changed method signature to accept `WC_Product $product` instead of `$cart_item` array
|
- **Fix:** Changed method signature to accept `WC_Product $product` instead of `$cart_item` array
|
||||||
- **Status:** FIXED in v1.1.20
|
- **Status:** FIXED in v1.1.20
|
||||||
|
|
||||||
|
### CSS Specificity Issues (v1.2.3 → v1.2.4)
|
||||||
|
|
||||||
|
**Problem:** Admin table borders still visible despite `border: none` declarations in v1.2.3
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Issue: WooCommerce's core admin CSS has higher specificity border rules
|
||||||
|
Location: assets/css/admin.css
|
||||||
|
Symptom: Tables still showing borders in product edit screens
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Root Cause:** WooCommerce's default admin CSS uses highly specific selectors that override simple `border: none` declarations
|
||||||
|
- **Failed Approach (v1.2.3):** Adding `border: none` to table elements without `!important`
|
||||||
|
- **Successful Fix (v1.2.4):**
|
||||||
|
- Added `!important` flags to ALL border removal rules
|
||||||
|
- Added `border-collapse: collapse !important` to force borderless styling
|
||||||
|
- Targeted all table structural elements: `table`, `th`, `td`, `thead`, `tbody`, `tr`
|
||||||
|
- **Lesson:** When overriding WooCommerce core CSS, `!important` is often necessary due to high specificity in core styles
|
||||||
|
|
||||||
|
**Problem:** Help icon positioned at right edge instead of next to label text
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Issue: WooCommerce help-tip uses float: right positioning
|
||||||
|
Location: assets/css/admin.css (checkbox/label layout)
|
||||||
|
Symptom: Help icon appearing far from label text at container edge
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Root Cause:** WooCommerce's default `.woocommerce-help-tip` styling uses `float: right`
|
||||||
|
- **Failed Approach (v1.2.3):** Simple margin adjustments without changing positioning model
|
||||||
|
- **Successful Fix (v1.2.4):**
|
||||||
|
- Removed float positioning: `float: none`
|
||||||
|
- Changed to `display: inline-block` with `vertical-align: middle`
|
||||||
|
- Wrapped label and help-tip in flexbox container: `display: inline-flex; align-items: center`
|
||||||
|
- Controlled precise spacing with margins (checkbox: 12px, help-tip: 6px)
|
||||||
|
- **Lesson:** Overriding float-based layouts often requires changing to flexbox for proper control
|
||||||
|
|
||||||
## Release Process
|
## Release Process
|
||||||
|
|
||||||
### Version Bumping
|
### Version Bumping
|
||||||
@@ -506,6 +541,83 @@ When modifying admin input fields in Twig templates, use WooCommerce's standard
|
|||||||
|
|
||||||
**Location:** `templates/admin/*.twig` for admin UI changes
|
**Location:** `templates/admin/*.twig` for admin UI changes
|
||||||
|
|
||||||
|
#### CSS Specificity and WooCommerce Overrides
|
||||||
|
|
||||||
|
**CRITICAL LESSON from v1.2.4:** WooCommerce's core admin CSS uses high-specificity selectors that require `!important` to override.
|
||||||
|
|
||||||
|
**Problem Symptoms:**
|
||||||
|
- CSS rules not applying despite correct selectors
|
||||||
|
- Styles work in simple cases but fail with WooCommerce elements
|
||||||
|
- Browser DevTools shows rule crossed out or overridden
|
||||||
|
|
||||||
|
**Diagnostic Steps:**
|
||||||
|
1. Inspect element in browser DevTools
|
||||||
|
2. Check "Computed" tab to see which styles are actually applied
|
||||||
|
3. Look for crossed-out rules in "Styles" tab (indicates override)
|
||||||
|
4. Check selector specificity - WooCommerce often uses complex selectors
|
||||||
|
|
||||||
|
**Solution Patterns:**
|
||||||
|
|
||||||
|
**For Table Styling:**
|
||||||
|
```css
|
||||||
|
/* ❌ This will likely be overridden */
|
||||||
|
.wc-tpp-tiers-table {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ✅ Use !important for core WooCommerce overrides */
|
||||||
|
.wc-tpp-tiers-table,
|
||||||
|
.wc-tpp-tiers-table th,
|
||||||
|
.wc-tpp-tiers-table td,
|
||||||
|
.wc-tpp-tiers-table thead,
|
||||||
|
.wc-tpp-tiers-table tbody,
|
||||||
|
.wc-tpp-tiers-table tr {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ✅ Also use border-collapse to prevent cell borders */
|
||||||
|
.wc-tpp-tiers-table {
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**For Float-Based Layouts:**
|
||||||
|
```css
|
||||||
|
/* ❌ Float positioning is hard to control precisely */
|
||||||
|
.woocommerce-help-tip {
|
||||||
|
float: right;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ✅ Use flexbox for precise control */
|
||||||
|
label[for="_wc_tpp_restrict_to_packages"] {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.woocommerce-help-tip {
|
||||||
|
float: none;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 6px;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**General Rules:**
|
||||||
|
1. **Always test in actual WordPress admin** - browser preview may not show WooCommerce's CSS
|
||||||
|
2. **Target all related elements** - tables require styling on `table`, `thead`, `tbody`, `tr`, `th`, `td`
|
||||||
|
3. **Use `!important` sparingly but don't fear it** - sometimes it's the only way to override WooCommerce core
|
||||||
|
4. **Prefer flexbox over floats** - gives better control over alignment and spacing
|
||||||
|
5. **Check across browsers** - table rendering can vary between Chrome/Firefox/Safari
|
||||||
|
|
||||||
|
**When Styles Don't Apply:**
|
||||||
|
- First verify selector is correct (DevTools should show rule, even if crossed out)
|
||||||
|
- If selector is correct but crossed out, increase specificity or add `!important`
|
||||||
|
- If selector doesn't appear at all, check file is enqueued and cache is cleared
|
||||||
|
- Use browser's "Inspect" right-click to see exact element structure
|
||||||
|
|
||||||
#### Git Workflow Issues
|
#### Git Workflow Issues
|
||||||
|
|
||||||
**Problem:** Cannot rebase due to uncommitted changes
|
**Problem:** Cannot rebase due to uncommitted changes
|
||||||
@@ -647,9 +759,11 @@ Roadmap for the upcoming development.
|
|||||||
|
|
||||||
2. ~~Bug 2 in v1.2.3: Increase the margin between checkbox and label and put the help icon right next to the label, not at the right border~~ ✅ **FIXED in v1.2.4** - Increased checkbox right margin from 8px to 12px. Repositioned help tip icon to display inline right next to the label text using flexbox layout with `display: inline-flex`, removing float positioning that caused it to appear at the right edge.
|
2. ~~Bug 2 in v1.2.3: Increase the margin between checkbox and label and put the help icon right next to the label, not at the right border~~ ✅ **FIXED in v1.2.4** - Increased checkbox right margin from 8px to 12px. Repositioned help tip icon to display inline right next to the label text using flexbox layout with `display: inline-flex`, removing float positioning that caused it to appear at the right edge.
|
||||||
|
|
||||||
##### New Features
|
##### Planned Enhancements for v1.2.5+
|
||||||
|
|
||||||
1. Create different, selectable templates for tierprices and packages to use in the frontend. Make the new templates selectable globally on the settings-page, not per product.
|
1. Hide the table-headers in admin area until a tier or respectivly a package price is defined.
|
||||||
|
|
||||||
|
2. Make it possible to define tier or package prices on variable products in the parent product as a default for that product and all variants of it unless a variant has its own tier or package prices.
|
||||||
|
|
||||||
### When Debugging Cart Issues
|
### When Debugging Cart Issues
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,18 @@
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hide table headers when there are no pricing rules */
|
||||||
|
.wc-tpp-tiers-container:empty ~ thead,
|
||||||
|
.wc-tpp-packages-container:empty ~ thead {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alternative approach: hide thead when tbody is empty (more reliable) */
|
||||||
|
.wc-tpp-tiers-table:has(tbody.wc-tpp-tiers-container:empty) thead,
|
||||||
|
.wc-tpp-packages-table:has(tbody.wc-tpp-packages-container:empty) thead {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Checkbox styling improvements */
|
/* Checkbox styling improvements */
|
||||||
#_wc_tpp_restrict_to_packages,
|
#_wc_tpp_restrict_to_packages,
|
||||||
input[id^="wc_tpp_restrict_to_packages_"] {
|
input[id^="wc_tpp_restrict_to_packages_"] {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "magdev/wc-tier-package-prices",
|
"name": "magdev/wc-tier-package-prices",
|
||||||
"description": "WooCommerce plugin for tier pricing and package prices with Twig templates",
|
"description": "WooCommerce plugin for tier pricing and package prices with Twig templates",
|
||||||
"version": "1.2.4",
|
"version": "1.2.5",
|
||||||
"type": "wordpress-plugin",
|
"type": "wordpress-plugin",
|
||||||
"license": "GPL-2.0-or-later",
|
"license": "GPL-2.0-or-later",
|
||||||
"authors": [
|
"authors": [
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ if (!class_exists('WC_TPP_Cart')) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for exact package match first (use effective ID for variations)
|
// Check for exact package match first (pass product_id for parent fallback support)
|
||||||
$package_price = null;
|
$package_price = null;
|
||||||
if (get_option('wc_tpp_enable_package_pricing') === 'yes') {
|
if (get_option('wc_tpp_enable_package_pricing') === 'yes') {
|
||||||
$package_price = WC_TPP_Frontend::get_package_price($effective_id, $quantity, $variation_id);
|
$package_price = WC_TPP_Frontend::get_package_price($product_id, $quantity, $variation_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($package_price !== null) {
|
if ($package_price !== null) {
|
||||||
@@ -64,9 +64,9 @@ if (!class_exists('WC_TPP_Cart')) {
|
|||||||
WC()->cart->cart_contents[$cart_item_key]['wc_tpp_pricing_type'] = 'package';
|
WC()->cart->cart_contents[$cart_item_key]['wc_tpp_pricing_type'] = 'package';
|
||||||
WC()->cart->cart_contents[$cart_item_key]['wc_tpp_total_price'] = $package_price;
|
WC()->cart->cart_contents[$cart_item_key]['wc_tpp_total_price'] = $package_price;
|
||||||
} else {
|
} else {
|
||||||
// Apply tier pricing if no package match (use effective ID for variations)
|
// Apply tier pricing if no package match (pass product_id for parent fallback support)
|
||||||
if (get_option('wc_tpp_enable_tier_pricing') === 'yes') {
|
if (get_option('wc_tpp_enable_tier_pricing') === 'yes') {
|
||||||
$tier_price = WC_TPP_Frontend::get_tier_price($effective_id, $quantity, $variation_id);
|
$tier_price = WC_TPP_Frontend::get_tier_price($product_id, $quantity, $variation_id);
|
||||||
if ($tier_price !== null) {
|
if ($tier_price !== null) {
|
||||||
$product->set_price($tier_price);
|
$product->set_price($tier_price);
|
||||||
// Store pricing information in cart item for display
|
// Store pricing information in cart item for display
|
||||||
@@ -103,20 +103,16 @@ if (!class_exists('WC_TPP_Cart')) {
|
|||||||
public function validate_package_quantity($passed, $product_id, $quantity) {
|
public function validate_package_quantity($passed, $product_id, $quantity) {
|
||||||
// Check for variation ID in request (for variable products)
|
// Check for variation ID in request (for variable products)
|
||||||
$variation_id = isset($_REQUEST['variation_id']) ? absint($_REQUEST['variation_id']) : 0;
|
$variation_id = isset($_REQUEST['variation_id']) ? absint($_REQUEST['variation_id']) : 0;
|
||||||
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
|
||||||
|
|
||||||
// Check if restriction is enabled globally or for this product/variation
|
// Check if restriction is enabled (with parent fallback for variations)
|
||||||
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
if (!$this->is_restriction_enabled($product_id, $variation_id)) {
|
||||||
$product_restrict = get_post_meta($effective_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
|
||||||
|
|
||||||
if (!$global_restrict && !$product_restrict) {
|
|
||||||
return $passed;
|
return $passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get packages for this product/variation
|
// Get packages for this product/variation (with parent fallback)
|
||||||
$packages = get_post_meta($effective_id, '_wc_tpp_packages', true);
|
$packages = $this->get_packages_with_fallback($product_id, $variation_id);
|
||||||
|
|
||||||
if (empty($packages) || !is_array($packages)) {
|
if (!$packages) {
|
||||||
return $passed;
|
return $passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,15 +152,8 @@ if (!class_exists('WC_TPP_Cart')) {
|
|||||||
$variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
|
$variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
|
||||||
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
||||||
|
|
||||||
// Check if restriction is enabled globally or for this product/variation
|
// Check if restriction is enabled (with parent fallback) and packages exist
|
||||||
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
if ($this->is_restriction_enabled($product_id, $variation_id) && $this->get_packages_with_fallback($product_id, $variation_id)) {
|
||||||
$product_restrict = get_post_meta($effective_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
|
||||||
|
|
||||||
// Get packages for this product/variation
|
|
||||||
$packages = get_post_meta($effective_id, '_wc_tpp_packages', true);
|
|
||||||
|
|
||||||
// If restriction is enabled and packages exist, show quantity as text only
|
|
||||||
if (($global_restrict || $product_restrict) && !empty($packages)) {
|
|
||||||
return sprintf('<span class="wc-tpp-cart-quantity wc-tpp-restricted-qty" data-product-id="%d">%s</span>',
|
return sprintf('<span class="wc-tpp-cart-quantity wc-tpp-restricted-qty" data-product-id="%d">%s</span>',
|
||||||
$effective_id,
|
$effective_id,
|
||||||
$cart_item['quantity']
|
$cart_item['quantity']
|
||||||
@@ -179,15 +168,8 @@ if (!class_exists('WC_TPP_Cart')) {
|
|||||||
$variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
|
$variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
|
||||||
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
||||||
|
|
||||||
// Check if restriction is enabled globally or for this product/variation
|
// Check if restriction is enabled (with parent fallback) and packages exist
|
||||||
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
if ($this->is_restriction_enabled($product_id, $variation_id) && $this->get_packages_with_fallback($product_id, $variation_id)) {
|
||||||
$product_restrict = get_post_meta($effective_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
|
||||||
|
|
||||||
// Get packages for this product/variation
|
|
||||||
$packages = get_post_meta($effective_id, '_wc_tpp_packages', true);
|
|
||||||
|
|
||||||
// If restriction is enabled and packages exist, show quantity as text only
|
|
||||||
if (($global_restrict || $product_restrict) && !empty($packages)) {
|
|
||||||
return sprintf('<span class="wc-tpp-cart-quantity wc-tpp-restricted-qty" data-product-id="%d">%s ×</span>',
|
return sprintf('<span class="wc-tpp-cart-quantity wc-tpp-restricted-qty" data-product-id="%d">%s ×</span>',
|
||||||
$effective_id,
|
$effective_id,
|
||||||
$cart_item['quantity']
|
$cart_item['quantity']
|
||||||
@@ -209,11 +191,8 @@ if (!class_exists('WC_TPP_Cart')) {
|
|||||||
$variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
|
$variation_id = isset($cart_item['variation_id']) ? absint($cart_item['variation_id']) : 0;
|
||||||
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
||||||
|
|
||||||
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
// Check if restriction is enabled (with parent fallback) and packages exist
|
||||||
$product_restrict = get_post_meta($effective_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
if ($this->is_restriction_enabled($product_id, $variation_id) && $this->get_packages_with_fallback($product_id, $variation_id)) {
|
||||||
$packages = get_post_meta($effective_id, '_wc_tpp_packages', true);
|
|
||||||
|
|
||||||
if (($global_restrict || $product_restrict) && !empty($packages)) {
|
|
||||||
$restricted_products[] = $effective_id;
|
$restricted_products[] = $effective_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,20 +233,61 @@ if (!class_exists('WC_TPP_Cart')) {
|
|||||||
return $editable;
|
return $editable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For variations, use the variation ID directly (get_id() returns variation ID for WC_Product_Variation)
|
// For variations, get parent product ID and variation ID
|
||||||
$effective_id = $product_id;
|
$variation_id = 0;
|
||||||
|
$parent_id = $product_id;
|
||||||
|
|
||||||
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
if ($product->is_type('variation')) {
|
||||||
$product_restrict = get_post_meta($effective_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
$variation_id = $product_id;
|
||||||
$packages = get_post_meta($effective_id, '_wc_tpp_packages', true);
|
$parent_id = $product->get_parent_id();
|
||||||
|
}
|
||||||
|
|
||||||
// If restriction is enabled and packages exist, make quantity non-editable
|
// Check if restriction is enabled (with parent fallback) and packages exist
|
||||||
if (($global_restrict || $product_restrict) && !empty($packages)) {
|
if ($this->is_restriction_enabled($parent_id, $variation_id) && $this->get_packages_with_fallback($parent_id, $variation_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $editable;
|
return $editable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get packages with parent fallback for variations
|
||||||
|
*
|
||||||
|
* @param int $product_id Parent product ID
|
||||||
|
* @param int $variation_id Variation ID (0 for simple products)
|
||||||
|
* @return array|false Packages array or false if none found
|
||||||
|
*/
|
||||||
|
private function get_packages_with_fallback($product_id, $variation_id = 0) {
|
||||||
|
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
||||||
|
$packages = get_post_meta($effective_id, '_wc_tpp_packages', true);
|
||||||
|
|
||||||
|
// Fall back to parent pricing if variation doesn't have its own pricing
|
||||||
|
if ((empty($packages) || !is_array($packages)) && $variation_id > 0) {
|
||||||
|
$packages = get_post_meta($product_id, '_wc_tpp_packages', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (!empty($packages) && is_array($packages)) ? $packages : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if restriction is enabled for a product/variation with parent fallback
|
||||||
|
*
|
||||||
|
* @param int $product_id Parent product ID
|
||||||
|
* @param int $variation_id Variation ID (0 for simple products)
|
||||||
|
* @return bool Whether restriction is enabled
|
||||||
|
*/
|
||||||
|
private function is_restriction_enabled($product_id, $variation_id = 0) {
|
||||||
|
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
||||||
|
$global_restrict = get_option('wc_tpp_restrict_package_quantities', 'no') === 'yes';
|
||||||
|
$product_restrict = get_post_meta($effective_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
||||||
|
|
||||||
|
// Fall back to parent restriction setting if variation doesn't have its own
|
||||||
|
if (!$product_restrict && $variation_id > 0) {
|
||||||
|
$product_restrict = get_post_meta($product_id, '_wc_tpp_restrict_to_packages', true) === 'yes';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $global_restrict || $product_restrict;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new WC_TPP_Cart();
|
new WC_TPP_Cart();
|
||||||
|
|||||||
@@ -133,6 +133,11 @@ if (!class_exists('WC_TPP_Frontend')) {
|
|||||||
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
||||||
$tiers = get_post_meta($effective_id, '_wc_tpp_tiers', true);
|
$tiers = get_post_meta($effective_id, '_wc_tpp_tiers', true);
|
||||||
|
|
||||||
|
// Fall back to parent pricing if variation doesn't have its own pricing
|
||||||
|
if ((empty($tiers) || !is_array($tiers)) && $variation_id > 0) {
|
||||||
|
$tiers = get_post_meta($product_id, '_wc_tpp_tiers', true);
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($tiers) || !is_array($tiers)) {
|
if (empty($tiers) || !is_array($tiers)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -159,6 +164,11 @@ if (!class_exists('WC_TPP_Frontend')) {
|
|||||||
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
$effective_id = $variation_id > 0 ? $variation_id : $product_id;
|
||||||
$packages = get_post_meta($effective_id, '_wc_tpp_packages', true);
|
$packages = get_post_meta($effective_id, '_wc_tpp_packages', true);
|
||||||
|
|
||||||
|
// Fall back to parent pricing if variation doesn't have its own pricing
|
||||||
|
if ((empty($packages) || !is_array($packages)) && $variation_id > 0) {
|
||||||
|
$packages = get_post_meta($product_id, '_wc_tpp_packages', true);
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($packages) || !is_array($packages)) {
|
if (empty($packages) || !is_array($packages)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
releases/wc-tier-and-package-prices-1.2.4.zip
Normal file
BIN
releases/wc-tier-and-package-prices-1.2.4.zip
Normal file
Binary file not shown.
1
releases/wc-tier-and-package-prices-1.2.4.zip.md5
Normal file
1
releases/wc-tier-and-package-prices-1.2.4.zip.md5
Normal file
@@ -0,0 +1 @@
|
|||||||
|
abd9cb934494f7053c19a0a022d5717f wc-tier-and-package-prices-1.2.4.zip
|
||||||
1
releases/wc-tier-and-package-prices-1.2.4.zip.sha256
Normal file
1
releases/wc-tier-and-package-prices-1.2.4.zip.sha256
Normal file
@@ -0,0 +1 @@
|
|||||||
|
976bd9bf2cdc5bbf34a65160bc1b42f74cbff71d39c634a042efd59aa90a13d0 wc-tier-and-package-prices-1.2.4.zip
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
* Plugin Name: WooCommerce Tier and Package Prices
|
* Plugin Name: WooCommerce Tier and Package Prices
|
||||||
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-tier-package-prices
|
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-tier-package-prices
|
||||||
* Description: Add tier pricing and package prices to WooCommerce products with configurable quantities at fixed prices
|
* Description: Add tier pricing and package prices to WooCommerce products with configurable quantities at fixed prices
|
||||||
* Version: 1.2.4
|
* Version: 1.2.5
|
||||||
* Author: Marco Graetsch
|
* Author: Marco Graetsch
|
||||||
* Author URI: https://src.bundespruefstelle.ch/magdev
|
* Author URI: https://src.bundespruefstelle.ch/magdev
|
||||||
* Text Domain: wc-tier-package-prices
|
* Text Domain: wc-tier-package-prices
|
||||||
@@ -23,7 +23,7 @@ if (!defined('ABSPATH')) {
|
|||||||
|
|
||||||
// Define plugin constants
|
// Define plugin constants
|
||||||
if (!defined('WC_TPP_VERSION')) {
|
if (!defined('WC_TPP_VERSION')) {
|
||||||
define('WC_TPP_VERSION', '1.2.4');
|
define('WC_TPP_VERSION', '1.2.5');
|
||||||
}
|
}
|
||||||
if (!defined('WC_TPP_PLUGIN_DIR')) {
|
if (!defined('WC_TPP_PLUGIN_DIR')) {
|
||||||
define('WC_TPP_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
define('WC_TPP_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||||
|
|||||||
Reference in New Issue
Block a user