You've already forked wc-tier-and-package-prices
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b2efb89d59 | |||
| 0f5779dc56 | |||
| d71f2c01dc | |||
| 82c8008fed | |||
| 4871b7957d | |||
| f7508a3d9c | |||
| 23f81ce58c | |||
| 9e96ff3321 | |||
| d7a61f29b4 | |||
| 71ea40598f | |||
| a73ff4926f | |||
| e4747130e4 |
@@ -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
1
.gitignore
vendored
@@ -32,3 +32,4 @@ notes.*
|
|||||||
|
|
||||||
# local code
|
# local code
|
||||||
wordpress
|
wordpress
|
||||||
|
core
|
||||||
74
CHANGELOG.md
74
CHANGELOG.md
@@ -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., "€" 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
116
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-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
|
||||||
|
|||||||
@@ -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": [
|
||||||
|
|||||||
@@ -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') {
|
||||||
|
|||||||
BIN
releases/wc-tier-and-package-prices-1.2.5.zip
Normal file
BIN
releases/wc-tier-and-package-prices-1.2.5.zip
Normal file
Binary file not shown.
1
releases/wc-tier-and-package-prices-1.2.5.zip.md5
Normal file
1
releases/wc-tier-and-package-prices-1.2.5.zip.md5
Normal file
@@ -0,0 +1 @@
|
|||||||
|
61eafd6c2fdd1468c486efe0c6e3bfa4 wc-tier-and-package-prices-1.2.5.zip
|
||||||
1
releases/wc-tier-and-package-prices-1.2.5.zip.sha256
Normal file
1
releases/wc-tier-and-package-prices-1.2.5.zip.sha256
Normal file
@@ -0,0 +1 @@
|
|||||||
|
4f6d637713511db061dd2db5f948b846eb48c343d9b8823299b85038ccca6a6e wc-tier-and-package-prices-1.2.5.zip
|
||||||
BIN
releases/wc-tier-and-package-prices-1.2.8.zip
Normal file
BIN
releases/wc-tier-and-package-prices-1.2.8.zip
Normal file
Binary file not shown.
1
releases/wc-tier-and-package-prices-1.2.8.zip.md5
Normal file
1
releases/wc-tier-and-package-prices-1.2.8.zip.md5
Normal file
@@ -0,0 +1 @@
|
|||||||
|
d412c85ef32b2e79e17227749265919f wc-tier-and-package-prices-1.2.8.zip
|
||||||
1
releases/wc-tier-and-package-prices-1.2.8.zip.sha256
Normal file
1
releases/wc-tier-and-package-prices-1.2.8.zip.sha256
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0c47e2a966c485b377beaffb56703a130158a15e7ffe9d95b43dea84f9229e9c wc-tier-and-package-prices-1.2.8.zip
|
||||||
BIN
releases/wc-tier-and-package-prices-1.2.9.zip
Normal file
BIN
releases/wc-tier-and-package-prices-1.2.9.zip
Normal file
Binary file not shown.
1
releases/wc-tier-and-package-prices-1.2.9.zip.md5
Normal file
1
releases/wc-tier-and-package-prices-1.2.9.zip.md5
Normal file
@@ -0,0 +1 @@
|
|||||||
|
073fbf114a32d99cd8ced683a1efa19c wc-tier-and-package-prices-1.2.9.zip
|
||||||
1
releases/wc-tier-and-package-prices-1.2.9.zip.sha256
Normal file
1
releases/wc-tier-and-package-prices-1.2.9.zip.sha256
Normal file
@@ -0,0 +1 @@
|
|||||||
|
00d2568e9acfd7fc05c88b9048a6a281d007b55dec9c4c7a4a55cb515e013e97 wc-tier-and-package-prices-1.2.9.zip
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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__));
|
||||||
|
|||||||
Reference in New Issue
Block a user