feat: Complete markdown syntax refinement and variable protection

 New cleaner syntax implemented:
- [card:type] instead of [card type='type']
- [button:style](url)Text[/button] instead of [button url='...' style='...']
- Standard markdown images: ![alt](url)

 Variable protection from markdown parsing:
- Variables with underscores (e.g., {order_items_table}) now protected
- HTML comment placeholders prevent italic/bold parsing
- All variables render correctly in preview

 Button rendering fixes:
- Buttons work in Visual mode inside cards
- Buttons work in Preview mode
- Button clicks prevented in visual editor
- Proper styling for solid and outline buttons

 Backward compatibility:
- Old syntax still supported
- No breaking changes

 Bug fixes:
- Fixed order_item_table → order_items_table naming
- Fixed button regex to match across newlines
- Added button/image parsing to parseMarkdownBasics
- Prevented button clicks on .button and .button-outline classes

📚 Documentation:
- NEW_MARKDOWN_SYNTAX.md - Complete user guide
- MARKDOWN_SYNTAX_AND_VARIABLES.md - Technical analysis
This commit is contained in:
dwindown
2025-11-15 20:05:50 +07:00
parent 550b3b69ef
commit 4471cd600f
45 changed files with 9194 additions and 508 deletions

162
SINGLE_SOURCE_OF_TRUTH.md Normal file
View File

@@ -0,0 +1,162 @@
# Single Source of Truth - Event Registry
## Problem Solved
Previously, events were hardcoded in multiple places:
-`NotificationsController.php` - hardcoded 9 events
-`TemplateProvider.php` - hardcoded 9 events
-`DefaultTemplates.php` - had 15 templates (8 customer + 7 staff)
**Result:** Mismatches, confusion, missing templates
## Solution: EventRegistry
Created `/includes/Core/Notifications/EventRegistry.php` as the **SINGLE SOURCE OF TRUTH**.
### How It Works
```php
// Get all events
$events = EventRegistry::get_all_events();
// Get by recipient
$staff_events = EventRegistry::get_events_by_recipient('staff');
$customer_events = EventRegistry::get_events_by_recipient('customer');
// Get by category
$order_events = EventRegistry::get_events_by_category('orders');
// Check if exists
if (EventRegistry::event_exists('order_placed', 'staff')) {
// ...
}
```
### Current Event List
**Staff Events (7):**
1. `order_placed` - New order notification
2. `order_processing` - Order confirmed, ready to process
3. `order_shipped` - Order shipped
4. `order_completed` - Order completed
5. `order_cancelled` - Order cancelled
6. `payment_received` - Payment confirmed
7. `payment_failed` - Payment failed
**Customer Events (8):**
1. `order_placed` - Order placed confirmation
2. `order_processing` - Order being processed
3. `order_shipped` - Order shipped with tracking
4. `order_completed` - Order delivered
5. `order_cancelled` - Order cancelled
6. `payment_received` - Payment confirmed
7. `payment_failed` - Payment failed, retry
8. `new_customer` - Welcome email
**Total: 15 events** (7 staff + 8 customer)
### Filter Hook
```php
add_filter('woonoow_notification_events_registry', function($events) {
// Add custom event
$events['custom_event'] = [
'id' => 'custom_event',
'label' => 'Custom Event',
'description' => 'My custom notification',
'category' => 'custom',
'recipient_type' => 'customer',
'wc_email' => '',
'enabled' => true,
];
return $events;
});
```
## Components Updated
### 1. NotificationsController.php
```php
// OLD - Hardcoded
$events = [
'orders' => [
['id' => 'order_placed', ...],
// ... 100+ lines
]
];
// NEW - Uses Registry
$all_events = EventRegistry::get_all_events();
foreach ($all_events as $event) {
// Group by category
}
```
### 2. TemplateProvider.php
```php
// OLD - Hardcoded
$events = [
'order_placed' => 'staff',
'order_processing' => 'customer',
// ...
];
// NEW - Uses Registry
$all_events = EventRegistry::get_all_events();
foreach ($all_events as $event) {
$event_id = $event['id'];
$recipient_type = $event['recipient_type'];
// Generate templates
}
```
### 3. DefaultTemplates.php
**No changes needed** - Already has all 15 templates matching the registry!
## Benefits
**Single source of truth** - One place to add/remove events
**No hardcoding** - All components query the registry
**Extensible** - Filter hook for custom events
**Type-safe** - Consistent event structure
**No mismatches** - Events and templates always aligned
**Easy maintenance** - Add event once, works everywhere
## Adding New Events
1. **Add to EventRegistry.php:**
```php
'low_stock' => [
'id' => 'low_stock',
'label' => __('Low Stock Alert', 'woonoow'),
'description' => __('When product stock is low', 'woonoow'),
'category' => 'products',
'recipient_type' => 'staff',
'wc_email' => 'low_stock',
'enabled' => true,
],
```
2. **Add template to DefaultTemplates.php:**
```php
'staff' => [
// ...
'low_stock' => self::staff_low_stock(),
],
private static function staff_low_stock() {
return '[card type="warning"]...';
}
```
3. **Done!** API and UI automatically show the new event.
## Testing
After refresh:
- ✅ Events API returns 15 events (7 staff + 8 customer)
- ✅ Templates API returns 15 templates
- ✅ UI shows correct counts
- ✅ All templates load without errors
- ✅ No hardcoded lists anywhere