You've already forked wc-tier-and-package-prices
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>
This commit is contained in:
96
CLAUDE.md
96
CLAUDE.md
@@ -809,6 +809,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).
|
||||
|
||||
#### 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
|
||||
|
||||
- Follow the existing pattern: add setting → add UI → add logic → add template
|
||||
|
||||
Reference in New Issue
Block a user