12 Commits

Author SHA1 Message Date
b2efb89d59 Update CLAUDE.md and add v1.2.9 release package
- Updated Current Version to 1.2.9
- Moved v1.2.8 bugs to 'Bugfixes (Completed in v1.2.9)' section
- Added detailed fix descriptions for both bugs:
  * Translation fix with esc_html__() and proper text domain
  * Placeholder encoding fix by removing translation filter
  * Variation save logic refactoring with defensive programming
- Updated roadmap section to v1.2.10+
- Added release package and checksums:
  * wc-tier-and-package-prices-1.2.9.zip (441KB, 383 files)
  * MD5: 073fbf114a32d99cd8ced683a1efa19c
  * SHA256: 00d2568e9acfd7fc05c88b9048a6a281d007b55dec9c4c7a4a55cb515e013e97

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 05:04:20 +01:00
0f5779dc56 Release version 1.2.9 - Translation and deletion fixes
## Bugfixes

1. **Price Header Not Translated**
   - Fixed translation function placement in printf statements
   - Changed from printf(__()) to printf(esc_html__())
   - Headers now display in administrator's configured language

2. **Placeholder HTML Entity Encoding**
   - Currency symbols were showing as HTML entities (e.g., &euro;)
   - Removed translation filter from concatenated placeholder strings
   - Placeholders are example values that should not be translated

3. **Variation Pricing Still Not Deletable (Regression)**
   - Despite v1.2.8 fix, edge cases remained due to conditional branching
   - Refactored save logic to be more defensive
   - Always initializes arrays, then unconditionally updates or deletes
   - Guarantees proper cleanup regardless of POST data structure

## Technical Details

- Updated all 6 table headers: printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), ...)
- Removed |__() filter from Twig placeholder concatenations
- Refactored save_variation_pricing_fields() with simplified logic:
  * Initialize arrays at start
  * Populate only if valid POST data exists
  * Always perform update (if !empty) or delete (if empty)
- Added is_array() check for extra safety

## Changed Files

- includes/class-wc-tpp-product-meta.php
- templates/admin/tier-row.twig
- templates/admin/package-row.twig

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 05:02:50 +01:00
d71f2c01dc fixed markdown syntax 2025-12-30 01:34:46 +01:00
82c8008fed added wp-core symlink 2025-12-30 01:33:24 +01:00
4871b7957d added skills to end sessions 2025-12-30 01:32:03 +01:00
f7508a3d9c Document v1.2.8 learnings in CLAUDE.md
Added two new critical sections documenting lessons learned during v1.2.8 development:

1. Currency Symbol Display
   - Proper pattern for displaying currency in table headers using printf()
   - How to pass currency_symbol to Twig templates
   - Correct concatenation in Twig placeholders
   - List of affected render methods

2. Post Meta Deletion vs. Empty Arrays
   - Explains WordPress distinction between deleted meta and empty arrays
   - Shows wrong pattern (saving empty arrays) vs correct pattern (deleting meta)
   - Why this matters for database cleanliness and bug prevention
   - Affected methods in save_tier_package_fields() and save_variation_pricing_fields()

These patterns prevent future bugs and ensure consistent implementation across the codebase.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 01:31:11 +01:00
23f81ce58c Add v1.2.8 release package and checksums
- Release package: wc-tier-and-package-prices-1.2.8.zip (440KB, 383 files)
- MD5: d412c85ef32b2e79e17227749265919f
- SHA256: 0c47e2a966c485b377beaffb56703a130158a15e7ffe9d95b43dea84f9229e9c

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 01:29:10 +01:00
9e96ff3321 Merge branch 'dev' 2025-12-30 01:28:09 +01:00
d7a61f29b4 Merge branch 'dev' 2025-12-30 01:05:21 +01:00
71ea40598f Merge branch 'dev' 2025-12-30 00:48:46 +01:00
a73ff4926f Merge branch 'dev' 2025-12-30 00:38:33 +01:00
e4747130e4 Add release package for version 1.2.5
Release package includes:
- Parent product default pricing for variable products
- Hide empty table headers in admin area
- Package size: 433KB (383 files)
- Checksums: MD5 and SHA256 generated

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 00:25:14 +01:00
18 changed files with 219 additions and 32 deletions

View File

@@ -40,7 +40,9 @@
"Bash('wc-tier-and-package-prices/templates/cache/*' )", "Bash('wc-tier-and-package-prices/templates/cache/*' )",
"Bash('wc-tier-and-package-prices/composer.lock' )", "Bash('wc-tier-and-package-prices/composer.lock' )",
"Bash('*/wordpress/*')", "Bash('*/wordpress/*')",
"Bash(echo:*)" "Bash(echo:*)",
"Skill(fix-session)",
"Skill(fix-session:*)"
] ]
} }
} }

1
.gitignore vendored
View File

@@ -32,3 +32,4 @@ notes.*
# local code # local code
wordpress wordpress
core

View File

@@ -5,6 +5,80 @@ 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.9] - 2025-12-30
### Fixed
- **Price Header Not Translated**: The "Price (%s)" header in admin tables was not being properly translated because the translation function was placed incorrectly within the printf statement. Changed from `printf(__('Price (%s)', ...), ...)` to `printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), ...)` to ensure proper translation while maintaining the currency placeholder functionality.
- **Placeholder HTML Entity Encoding Issue**: Currency symbols in price input placeholders were being displayed as HTML entities (e.g., "&euro;" instead of "€") because the concatenated string was being passed through the translation filter which was encoding special characters. Removed the unnecessary translation filter from concatenated placeholder strings since they are example values that should not be translated.
- **Variation Pricing Still Not Deletable (Regression from v1.2.8)**: Despite the fix in v1.2.8, variation pricing data was still not being properly deleted in all scenarios. The issue was with the conditional logic structure - the code had separate `if/else` branches that could fail in edge cases. Restructured the save logic to be more defensive: initialize arrays at the start, populate only if valid POST data exists, then unconditionally perform either update (if not empty) or delete (if empty). This guarantees proper cleanup regardless of POST data structure.
### Technical Details
**Translation Fix**:
- Changed all 6 instances of `printf(__('Price (%s)', 'wc-tier-package-prices'), ...)`
- To: `printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), ...)`
- The `__()` function now receives the text domain parameter correctly
- Added `esc_html` for proper output escaping
**Placeholder Encoding Fix**:
- Changed tier-row.twig placeholder from: `{{ ('e.g., 9.99 ' ~ currency_symbol)|__('wc-tier-package-prices') }}`
- To: `{{ 'e.g., 9.99 ' ~ currency_symbol }}`
- Changed package-row.twig placeholder from: `{{ ('e.g., 99.99 ' ~ currency_symbol)|__('wc-tier-package-prices') }}`
- To: `{{ 'e.g., 99.99 ' ~ currency_symbol }}`
- Removed translation filter from concatenated example values to prevent HTML entity encoding
**Variation Save Logic Refactor**:
```php
// Old pattern (v1.2.8):
if (isset($_POST['wc_tpp_tiers'][$loop])) {
$tiers = array();
// ... populate tiers ...
if (!empty($tiers)) {
update_post_meta(...);
} else {
delete_post_meta(...);
}
} else {
delete_post_meta(...);
}
// New pattern (v1.2.9):
$tiers = array();
if (isset($_POST['wc_tpp_tiers'][$loop]) && is_array($_POST['wc_tpp_tiers'][$loop])) {
// ... populate tiers ...
}
// Always perform update or delete based on final state
if (!empty($tiers)) {
update_post_meta(...);
} else {
delete_post_meta(...);
}
```
- Eliminated conditional branching that could miss edge cases
- Added explicit `is_array()` check for extra safety
- Guaranteed that one of update_post_meta() or delete_post_meta() is always called
- Applied to both `save_variation_pricing_fields()` for tier and package pricing
**User Impact**:
- Price headers now display in the administrator's configured language
- Currency symbols display correctly without HTML encoding in placeholders
- Variation pricing deletion now works reliably in all scenarios
- Database remains clean with no orphaned empty arrays
### Changed Files
- `includes/class-wc-tpp-product-meta.php` - Fixed translation function calls in 6 table headers; refactored save_variation_pricing_fields() logic for tiers and packages
- `templates/admin/tier-row.twig` - Removed translation filter from placeholder concatenation
- `templates/admin/package-row.twig` - Removed translation filter from placeholder concatenation
## [1.2.8] - 2025-12-30 ## [1.2.8] - 2025-12-30
### Fixed ### Fixed

116
CLAUDE.md
View File

@@ -1,7 +1,7 @@
# WooCommerce Tier and Package Prices - AI Context Document # WooCommerce Tier and Package Prices - AI Context Document
**Last Updated:** 2025-12-30 **Last Updated:** 2025-12-30
**Current Version:** 1.2.8 **Current Version:** 1.2.9
**Author:** Marco Graetsch **Author:** Marco Graetsch
**Project Status:** Production-ready WordPress plugin **Project Status:** Production-ready WordPress plugin
@@ -355,8 +355,8 @@ Update version in 3 places:
**CRITICAL:** The zip command must be run from the **parent directory** of the plugin folder to create proper archive structure. **CRITICAL:** The zip command must be run from the **parent directory** of the plugin folder to create proper archive structure.
```bash ```bash
# From parent directory (/home/magdev/workspaces/node) # From parent directory (/home/magdev/workspaces/php)
cd /home/magdev/workspaces/node cd /home/magdev/workspaces/php
# Create zip excluding dev files - note the correct path structure # Create zip excluding dev files - note the correct path structure
zip -r wc-tier-and-package-prices/releases/wc-tier-and-package-prices-X.X.X.zip wc-tier-and-package-prices/ \ zip -r wc-tier-and-package-prices/releases/wc-tier-and-package-prices-X.X.X.zip wc-tier-and-package-prices/ \
@@ -546,11 +546,13 @@ When modifying admin input fields in Twig templates, use WooCommerce's standard
**CRITICAL LESSON from v1.2.4:** WooCommerce's core admin CSS uses high-specificity selectors that require `!important` to override. **CRITICAL LESSON from v1.2.4:** WooCommerce's core admin CSS uses high-specificity selectors that require `!important` to override.
**Problem Symptoms:** **Problem Symptoms:**
- CSS rules not applying despite correct selectors - CSS rules not applying despite correct selectors
- Styles work in simple cases but fail with WooCommerce elements - Styles work in simple cases but fail with WooCommerce elements
- Browser DevTools shows rule crossed out or overridden - Browser DevTools shows rule crossed out or overridden
**Diagnostic Steps:** **Diagnostic Steps:**
1. Inspect element in browser DevTools 1. Inspect element in browser DevTools
2. Check "Computed" tab to see which styles are actually applied 2. Check "Computed" tab to see which styles are actually applied
3. Look for crossed-out rules in "Styles" tab (indicates override) 3. Look for crossed-out rules in "Styles" tab (indicates override)
@@ -559,6 +561,7 @@ When modifying admin input fields in Twig templates, use WooCommerce's standard
**Solution Patterns:** **Solution Patterns:**
**For Table Styling:** **For Table Styling:**
```css ```css
/* ❌ This will likely be overridden */ /* ❌ This will likely be overridden */
.wc-tpp-tiers-table { .wc-tpp-tiers-table {
@@ -582,6 +585,7 @@ When modifying admin input fields in Twig templates, use WooCommerce's standard
``` ```
**For Float-Based Layouts:** **For Float-Based Layouts:**
```css ```css
/* ❌ Float positioning is hard to control precisely */ /* ❌ Float positioning is hard to control precisely */
.woocommerce-help-tip { .woocommerce-help-tip {
@@ -606,6 +610,7 @@ label[for="_wc_tpp_restrict_to_packages"] {
``` ```
**General Rules:** **General Rules:**
1. **Always test in actual WordPress admin** - browser preview may not show WooCommerce's CSS 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` 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 3. **Use `!important` sparingly but don't fear it** - sometimes it's the only way to override WooCommerce core
@@ -613,6 +618,7 @@ label[for="_wc_tpp_restrict_to_packages"] {
5. **Check across browsers** - table rendering can vary between Chrome/Firefox/Safari 5. **Check across browsers** - table rendering can vary between Chrome/Firefox/Safari
**When Styles Don't Apply:** **When Styles Don't Apply:**
- First verify selector is correct (DevTools should show rule, even if crossed out) - 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 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 - If selector doesn't appear at all, check file is enqueued and cache is cleared
@@ -781,7 +787,13 @@ Roadmap for the upcoming development.
2. ~~Already stored tier and package prices on the children of a variable product are still available after deletion. Looks like the storage mechanism has an error. This occurs only on the child product, not on the parent product.~~**FIXED in v1.2.8** - Fixed save logic in both `save_tier_package_fields()` and `save_variation_pricing_fields()` methods. Root cause: Empty arrays were being saved via `update_post_meta()` instead of being deleted. Changed logic from "save on isset, delete otherwise" to "filter entries, then save if not empty, delete if empty". Added `if (!empty($tiers))` and `if (!empty($packages))` checks before calling `update_post_meta()`. Now properly calls `delete_post_meta()` when all pricing entries are removed, preventing empty arrays from persisting in database. 2. ~~Already stored tier and package prices on the children of a variable product are still available after deletion. Looks like the storage mechanism has an error. This occurs only on the child product, not on the parent product.~~**FIXED in v1.2.8** - Fixed save logic in both `save_tier_package_fields()` and `save_variation_pricing_fields()` methods. Root cause: Empty arrays were being saved via `update_post_meta()` instead of being deleted. Changed logic from "save on isset, delete otherwise" to "filter entries, then save if not empty, delete if empty". Added `if (!empty($tiers))` and `if (!empty($packages))` checks before calling `update_post_meta()`. Now properly calls `delete_post_meta()` when all pricing entries are removed, preventing empty arrays from persisting in database.
##### Planned Enhancements for v1.2.9+ ##### Bugfixes (Completed in v1.2.9)
1. ~~The Price header in admin tables while configuring tier and package prices is not translated. Also the placeholder on the form elements for prices has the wrong encoding, the special characters on the placeholder are show in html-entity encoding.~~**FIXED in v1.2.9** - Fixed translation function placement in printf statements by changing from `printf(__('Price (%s)', ...), ...)` to `printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), ...)`. This ensures the text domain is passed correctly to the translation function while maintaining the currency placeholder functionality. Also removed the translation filter from concatenated placeholder strings in Twig templates (changed from `{{ ('e.g., 9.99 ' ~ currency_symbol)|__('wc-tier-package-prices') }}` to `{{ 'e.g., 9.99 ' ~ currency_symbol }}`) because example values should not be translated and the filter was causing HTML entity encoding of special characters.
2. ~~The tier and package prices for children of a variable product are still not deletable. After storing the product, the previously deleted rows are back again.~~**FIXED in v1.2.9** - Despite the fix in v1.2.8, edge cases remained due to conditional branching structure. Refactored `save_variation_pricing_fields()` with more defensive logic: initialize arrays at the start ($tiers = array()), populate only if valid POST data exists (with added is_array() check), then unconditionally perform either update_post_meta() (if !empty) or delete_post_meta() (if empty). This guarantees proper cleanup regardless of POST data structure and eliminates the if/else branching that could miss edge cases.
##### Planned Enhancements for v1.2.10+
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. 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.
@@ -809,6 +821,102 @@ WooCommerce has different hooks for different product types in the admin product
**Lesson:** When adding admin UI for variable product parents, use `woocommerce_product_options_general_product_data` and check `$product->is_type('variable')` to conditionally display. Using `woocommerce_product_options_pricing` will cause forms to never appear for variable products (as discovered in v1.2.6 → v1.2.7 fix). **Lesson:** When adding admin UI for variable product parents, use `woocommerce_product_options_general_product_data` and check `$product->is_type('variable')` to conditionally display. Using `woocommerce_product_options_pricing` will cause forms to never appear for variable products (as discovered in v1.2.6 → v1.2.7 fix).
#### CRITICAL: Currency Symbol Display (Learned in v1.2.8)
When displaying currency symbols in admin interface table headers and input placeholders:
**Table Headers:**
```php
// ✅ Correct - Use printf with translation and WooCommerce currency function
<th><?php printf(__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th>
// ❌ Wrong - Hard-coded or missing currency
<th><?php _e('Price', 'wc-tier-package-prices'); ?></th>
<th><?php _e('Price (€)', 'wc-tier-package-prices'); ?></th>
```
**Twig Template Placeholders:**
```twig
{# ✅ Correct - Pass currency_symbol from PHP and concatenate in template #}
placeholder="{{ ('e.g., 9.99 ' ~ currency_symbol)|__('wc-tier-package-prices') }}"
{# ❌ Wrong - Hard-coded or missing currency #}
placeholder="{{ 'e.g., 9.99'|__('wc-tier-package-prices') }}"
placeholder="{{ 'e.g., 9.99 €'|__('wc-tier-package-prices') }}"
```
**Implementation Pattern:**
1. In PHP render methods, pass currency symbol to Twig: `'currency_symbol' => get_woocommerce_currency_symbol()`
2. In Twig templates, concatenate using `~` operator: `'text ' ~ currency_symbol`
3. Always use WooCommerce's `get_woocommerce_currency_symbol()` - never hard-code currency symbols
**Affected Methods:** All template render methods must pass `currency_symbol`:
- `render_tier_row()`
- `render_package_row()`
- `render_variation_tier_row()`
- `render_variation_package_row()`
#### CRITICAL: Post Meta Deletion vs. Empty Arrays (Learned in v1.2.8)
When saving product meta data, WordPress distinguishes between "no data" (deleted meta) and "empty data" (empty array saved as meta):
**Problem Pattern:**
```php
// ❌ WRONG - Saves empty array when all entries removed
if (isset($_POST['_wc_tpp_tiers'])) {
$tiers = array();
foreach ($_POST['_wc_tpp_tiers'] as $tier) {
if (!empty($tier['min_qty']) && !empty($tier['price'])) {
$tiers[] = array(...);
}
}
update_post_meta($post_id, '_wc_tpp_tiers', $tiers); // Saves [] if no valid entries
} else {
delete_post_meta($post_id, '_wc_tpp_tiers');
}
```
**Correct Pattern:**
```php
// ✅ CORRECT - Deletes meta when no valid entries exist
if (isset($_POST['_wc_tpp_tiers'])) {
$tiers = array();
foreach ($_POST['_wc_tpp_tiers'] as $tier) {
if (!empty($tier['min_qty']) && !empty($tier['price'])) {
$tiers[] = array(...);
}
}
// Only save if we have valid entries, otherwise delete
if (!empty($tiers)) {
update_post_meta($post_id, '_wc_tpp_tiers', $tiers);
} else {
delete_post_meta($post_id, '_wc_tpp_tiers');
}
} else {
delete_post_meta($post_id, '_wc_tpp_tiers');
}
```
**Why This Matters:**
- Empty arrays `[]` saved via `update_post_meta()` persist in database as serialized empty arrays
- Frontend/cart code checking `if ($tiers)` will evaluate `[]` as falsy, but meta still exists in database
- Database queries like `get_post_meta()` return `[]` instead of `false`, causing subtle bugs
- Properly deleting meta keeps database clean and prevents "ghost" configurations
**Affected Methods in v1.2.8:**
- `save_tier_package_fields()` - Simple and variable parent products
- `save_variation_pricing_fields()` - Individual variations
**Rule:** Always check `if (!empty($array))` before calling `update_post_meta()` for array data. If empty, call `delete_post_meta()` instead.
### When Adding Features ### When Adding Features
- Follow the existing pattern: add setting → add UI → add logic → add template - Follow the existing pattern: add setting → add UI → add logic → add template

View File

@@ -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.8", "version": "1.2.9",
"type": "wordpress-plugin", "type": "wordpress-plugin",
"license": "GPL-2.0-or-later", "license": "GPL-2.0-or-later",
"authors": [ "authors": [

View File

@@ -55,7 +55,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
<thead> <thead>
<tr> <tr>
<th><?php _e('Min Quantity', 'wc-tier-package-prices'); ?></th> <th><?php _e('Min Quantity', 'wc-tier-package-prices'); ?></th>
<th><?php printf(__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th> <th><?php printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th>
<th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th> <th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th>
<th></th> <th></th>
</tr> </tr>
@@ -85,7 +85,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
<thead> <thead>
<tr> <tr>
<th><?php _e('Quantity', 'wc-tier-package-prices'); ?></th> <th><?php _e('Quantity', 'wc-tier-package-prices'); ?></th>
<th><?php printf(__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th> <th><?php printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th>
<th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th> <th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th>
<th></th> <th></th>
</tr> </tr>
@@ -149,7 +149,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
<thead> <thead>
<tr> <tr>
<th><?php _e('Min Quantity', 'wc-tier-package-prices'); ?></th> <th><?php _e('Min Quantity', 'wc-tier-package-prices'); ?></th>
<th><?php printf(__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th> <th><?php printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th>
<th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th> <th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th>
<th></th> <th></th>
</tr> </tr>
@@ -195,7 +195,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
<thead> <thead>
<tr> <tr>
<th><?php _e('Quantity', 'wc-tier-package-prices'); ?></th> <th><?php _e('Quantity', 'wc-tier-package-prices'); ?></th>
<th><?php printf(__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th> <th><?php printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th>
<th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th> <th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th>
<th></th> <th></th>
</tr> </tr>
@@ -287,7 +287,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
<thead> <thead>
<tr> <tr>
<th><?php _e('Min Quantity', 'wc-tier-package-prices'); ?></th> <th><?php _e('Min Quantity', 'wc-tier-package-prices'); ?></th>
<th><?php printf(__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th> <th><?php printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th>
<th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th> <th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th>
<th></th> <th></th>
</tr> </tr>
@@ -310,7 +310,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
<thead> <thead>
<tr> <tr>
<th><?php _e('Quantity', 'wc-tier-package-prices'); ?></th> <th><?php _e('Quantity', 'wc-tier-package-prices'); ?></th>
<th><?php printf(__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th> <th><?php printf(esc_html__('Price (%s)', 'wc-tier-package-prices'), get_woocommerce_currency_symbol()); ?></th>
<th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th> <th><?php _e('Label (optional)', 'wc-tier-package-prices'); ?></th>
<th></th> <th></th>
</tr> </tr>
@@ -472,8 +472,8 @@ if (!class_exists('WC_TPP_Product_Meta')) {
} }
// Save tier pricing for this variation // Save tier pricing for this variation
if (isset($_POST['wc_tpp_tiers'][$loop])) {
$tiers = array(); $tiers = array();
if (isset($_POST['wc_tpp_tiers'][$loop]) && is_array($_POST['wc_tpp_tiers'][$loop])) {
foreach ($_POST['wc_tpp_tiers'][$loop] as $tier) { foreach ($_POST['wc_tpp_tiers'][$loop] as $tier) {
if (!empty($tier['min_qty']) && !empty($tier['price'])) { if (!empty($tier['min_qty']) && !empty($tier['price'])) {
$tiers[] = array( $tiers[] = array(
@@ -487,19 +487,17 @@ if (!class_exists('WC_TPP_Product_Meta')) {
usort($tiers, function($a, $b) { usort($tiers, function($a, $b) {
return $a['min_qty'] - $b['min_qty']; return $a['min_qty'] - $b['min_qty'];
}); });
// Only save if we have valid tiers, otherwise delete }
// Always update or delete based on whether we have valid tiers
if (!empty($tiers)) { if (!empty($tiers)) {
update_post_meta($variation_id, '_wc_tpp_tiers', $tiers); update_post_meta($variation_id, '_wc_tpp_tiers', $tiers);
} else { } else {
delete_post_meta($variation_id, '_wc_tpp_tiers'); delete_post_meta($variation_id, '_wc_tpp_tiers');
} }
} else {
delete_post_meta($variation_id, '_wc_tpp_tiers');
}
// Save package pricing for this variation // Save package pricing for this variation
if (isset($_POST['wc_tpp_packages'][$loop])) {
$packages = array(); $packages = array();
if (isset($_POST['wc_tpp_packages'][$loop]) && is_array($_POST['wc_tpp_packages'][$loop])) {
foreach ($_POST['wc_tpp_packages'][$loop] as $package) { foreach ($_POST['wc_tpp_packages'][$loop] as $package) {
if (!empty($package['qty']) && !empty($package['price'])) { if (!empty($package['qty']) && !empty($package['price'])) {
$packages[] = array( $packages[] = array(
@@ -513,15 +511,13 @@ if (!class_exists('WC_TPP_Product_Meta')) {
usort($packages, function($a, $b) { usort($packages, function($a, $b) {
return $a['qty'] - $b['qty']; return $a['qty'] - $b['qty'];
}); });
// Only save if we have valid packages, otherwise delete }
// Always update or delete based on whether we have valid packages
if (!empty($packages)) { if (!empty($packages)) {
update_post_meta($variation_id, '_wc_tpp_packages', $packages); update_post_meta($variation_id, '_wc_tpp_packages', $packages);
} else { } else {
delete_post_meta($variation_id, '_wc_tpp_packages'); delete_post_meta($variation_id, '_wc_tpp_packages');
} }
} else {
delete_post_meta($variation_id, '_wc_tpp_packages');
}
// Save restriction setting for this variation // Save restriction setting for this variation
if (isset($_POST['wc_tpp_restrict_to_packages'][$loop]) && $_POST['wc_tpp_restrict_to_packages'][$loop] === 'yes') { if (isset($_POST['wc_tpp_restrict_to_packages'][$loop]) && $_POST['wc_tpp_restrict_to_packages'][$loop] === 'yes') {

Binary file not shown.

View File

@@ -0,0 +1 @@
61eafd6c2fdd1468c486efe0c6e3bfa4 wc-tier-and-package-prices-1.2.5.zip

View File

@@ -0,0 +1 @@
4f6d637713511db061dd2db5f948b846eb48c343d9b8823299b85038ccca6a6e wc-tier-and-package-prices-1.2.5.zip

Binary file not shown.

View File

@@ -0,0 +1 @@
d412c85ef32b2e79e17227749265919f wc-tier-and-package-prices-1.2.8.zip

View File

@@ -0,0 +1 @@
0c47e2a966c485b377beaffb56703a130158a15e7ffe9d95b43dea84f9229e9c wc-tier-and-package-prices-1.2.8.zip

Binary file not shown.

View File

@@ -0,0 +1 @@
073fbf114a32d99cd8ced683a1efa19c wc-tier-and-package-prices-1.2.9.zip

View File

@@ -0,0 +1 @@
00d2568e9acfd7fc05c88b9048a6a281d007b55dec9c4c7a4a55cb515e013e97 wc-tier-and-package-prices-1.2.9.zip

View File

@@ -21,7 +21,7 @@
<input type="text" <input type="text"
name="{{ name_prefix }}[{{ index|esc_attr }}][price]" name="{{ name_prefix }}[{{ index|esc_attr }}][price]"
value="{{ package.price|default('')|esc_attr }}" value="{{ package.price|default('')|esc_attr }}"
placeholder="{{ ('e.g., 99.99 ' ~ currency_symbol)|__('wc-tier-package-prices') }}" placeholder="{{ 'e.g., 99.99 ' ~ currency_symbol }}"
class="short wc_input_price"> class="short wc_input_price">
</td> </td>
<td> <td>

View File

@@ -21,7 +21,7 @@
<input type="text" <input type="text"
name="{{ name_prefix }}[{{ index|esc_attr }}][price]" name="{{ name_prefix }}[{{ index|esc_attr }}][price]"
value="{{ tier.price|default('')|esc_attr }}" value="{{ tier.price|default('')|esc_attr }}"
placeholder="{{ ('e.g., 9.99 ' ~ currency_symbol)|__('wc-tier-package-prices') }}" placeholder="{{ 'e.g., 9.99 ' ~ currency_symbol }}"
class="short wc_input_price"> class="short wc_input_price">
</td> </td>
<td> <td>

View File

@@ -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.8 * Version: 1.2.9
* 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.8'); define('WC_TPP_VERSION', '1.2.9');
} }
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__));