Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2efb89d59 | ||
|
|
0f5779dc56 |
No files matched your search
@@ -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/),
|
||||
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., "€" 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
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# WooCommerce Tier and Package Prices - AI Context Document
|
||||
|
||||
**Last Updated:** 2025-12-30
|
||||
**Current Version:** 1.2.8
|
||||
**Current Version:** 1.2.9
|
||||
**Author:** Marco Graetsch
|
||||
**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.
|
||||
|
||||
```bash
|
||||
# From parent directory (/home/magdev/workspaces/node)
|
||||
cd /home/magdev/workspaces/node
|
||||
# From parent directory (/home/magdev/workspaces/php)
|
||||
cd /home/magdev/workspaces/php
|
||||
|
||||
# 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/ \
|
||||
@@ -787,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.
|
||||
|
||||
##### 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
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "magdev/wc-tier-package-prices",
|
||||
"description": "WooCommerce plugin for tier pricing and package prices with Twig templates",
|
||||
"version": "1.2.8",
|
||||
"version": "1.2.9",
|
||||
"type": "wordpress-plugin",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"authors": [
|
||||
|
||||
@@ -55,7 +55,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
<thead>
|
||||
<tr>
|
||||
<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></th>
|
||||
</tr>
|
||||
@@ -85,7 +85,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
<thead>
|
||||
<tr>
|
||||
<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></th>
|
||||
</tr>
|
||||
@@ -149,7 +149,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
<thead>
|
||||
<tr>
|
||||
<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></th>
|
||||
</tr>
|
||||
@@ -195,7 +195,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
<thead>
|
||||
<tr>
|
||||
<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></th>
|
||||
</tr>
|
||||
@@ -287,7 +287,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
<thead>
|
||||
<tr>
|
||||
<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></th>
|
||||
</tr>
|
||||
@@ -310,7 +310,7 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
<thead>
|
||||
<tr>
|
||||
<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></th>
|
||||
</tr>
|
||||
@@ -472,8 +472,8 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (!empty($tier['min_qty']) && !empty($tier['price'])) {
|
||||
$tiers[] = array(
|
||||
@@ -487,19 +487,17 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
usort($tiers, function($a, $b) {
|
||||
return $a['min_qty'] - $b['min_qty'];
|
||||
});
|
||||
// Only save if we have valid tiers, otherwise delete
|
||||
if (!empty($tiers)) {
|
||||
update_post_meta($variation_id, '_wc_tpp_tiers', $tiers);
|
||||
} else {
|
||||
delete_post_meta($variation_id, '_wc_tpp_tiers');
|
||||
}
|
||||
}
|
||||
// Always update or delete based on whether we have valid tiers
|
||||
if (!empty($tiers)) {
|
||||
update_post_meta($variation_id, '_wc_tpp_tiers', $tiers);
|
||||
} else {
|
||||
delete_post_meta($variation_id, '_wc_tpp_tiers');
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (!empty($package['qty']) && !empty($package['price'])) {
|
||||
$packages[] = array(
|
||||
@@ -513,12 +511,10 @@ if (!class_exists('WC_TPP_Product_Meta')) {
|
||||
usort($packages, function($a, $b) {
|
||||
return $a['qty'] - $b['qty'];
|
||||
});
|
||||
// Only save if we have valid packages, otherwise delete
|
||||
if (!empty($packages)) {
|
||||
update_post_meta($variation_id, '_wc_tpp_packages', $packages);
|
||||
} else {
|
||||
delete_post_meta($variation_id, '_wc_tpp_packages');
|
||||
}
|
||||
}
|
||||
// Always update or delete based on whether we have valid packages
|
||||
if (!empty($packages)) {
|
||||
update_post_meta($variation_id, '_wc_tpp_packages', $packages);
|
||||
} else {
|
||||
delete_post_meta($variation_id, '_wc_tpp_packages');
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
073fbf114a32d99cd8ced683a1efa19c wc-tier-and-package-prices-1.2.9.zip
|
||||
@@ -0,0 +1 @@
|
||||
00d2568e9acfd7fc05c88b9048a6a281d007b55dec9c4c7a4a55cb515e013e97 wc-tier-and-package-prices-1.2.9.zip
|
||||
@@ -21,7 +21,7 @@
|
||||
<input type="text"
|
||||
name="{{ name_prefix }}[{{ index|esc_attr }}][price]"
|
||||
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">
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<input type="text"
|
||||
name="{{ name_prefix }}[{{ index|esc_attr }}][price]"
|
||||
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">
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Plugin Name: WooCommerce Tier and 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
|
||||
* Version: 1.2.8
|
||||
* Version: 1.2.9
|
||||
* Author: Marco Graetsch
|
||||
* Author URI: https://src.bundespruefstelle.ch/magdev
|
||||
* Text Domain: wc-tier-package-prices
|
||||
@@ -23,7 +23,7 @@ if (!defined('ABSPATH')) {
|
||||
|
||||
// Define plugin constants
|
||||
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')) {
|
||||
define('WC_TPP_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||
|
||||
Reference in new issue
Block a user