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:
2025-12-30 01:31:11 +01:00
parent 23f81ce58c
commit f7508a3d9c

View File

@@ -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). **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