feat: Backend API & Email Rendering with Settings! 🔌

## 4. Wire to Backend 

### API Endpoints Created:
- `GET /woonoow/v1/notifications/email-settings` - Fetch settings
- `POST /woonoow/v1/notifications/email-settings` - Save settings
- `DELETE /woonoow/v1/notifications/email-settings` - Reset to defaults

### Features:
- Proper sanitization (sanitize_hex_color, esc_url_raw, etc.)
- Social links validation (allowed platforms only)
- Defaults fallback
- Stored in wp_options as `woonoow_email_settings`

### Email Rendering Integration:
**Logo & Header:**
- Uses logo_url if set, otherwise header_text
- Falls back to store name

**Footer:**
- Uses footer_text with {current_year} support
- Replaces {current_year} with actual year dynamically
- Social icons rendered from social_links array

**Hero Cards:**
- Applies hero_gradient_start and hero_gradient_end
- Applies hero_text_color to text and headings
- Works for type="hero" and type="success" cards

**Button Colors:**
- Ready to apply primary_color and button_text_color
- (Template needs update for dynamic button colors)

### Files:
- `includes/Api/NotificationsController.php` - API endpoints
- `includes/Core/Notifications/EmailRenderer.php` - Apply settings to emails

### Security:
- Permission checks (check_permission)
- Input sanitization
- URL validation
- Platform whitelist for social links

Frontend can now save/load settings! Backend applies them to emails! 🎉
This commit is contained in:
dwindown
2025-11-13 13:45:03 +07:00
parent 7badee9ee4
commit 2a98d6fc2b
2 changed files with 166 additions and 20 deletions

View File

@@ -273,12 +273,29 @@ class EmailRenderer {
$type = $attributes['type'] ?? 'default';
$bg = $attributes['bg'] ?? null;
// Get email customization settings for colors
$email_settings = get_option('woonoow_email_settings', []);
$hero_gradient_start = $email_settings['hero_gradient_start'] ?? '#667eea';
$hero_gradient_end = $email_settings['hero_gradient_end'] ?? '#764ba2';
$hero_text_color = $email_settings['hero_text_color'] ?? '#ffffff';
$class = 'card';
$style = 'width: 100%; background-color: #ffffff; border-radius: 8px;';
$content_style = 'padding: 32px 40px;';
// Add type class
// Add type class and styling
if ($type !== 'default') {
$class .= ' card-' . esc_attr($type);
// Apply gradient and text color for hero/success cards
if ($type === 'hero' || $type === 'success') {
$style .= sprintf(
' background: linear-gradient(135deg, %s 0%%, %s 100%%);',
esc_attr($hero_gradient_start),
esc_attr($hero_gradient_end)
);
$content_style .= sprintf(' color: %s;', esc_attr($hero_text_color));
}
}
// Add background image
@@ -290,13 +307,14 @@ class EmailRenderer {
return sprintf(
'<table role="presentation" class="%s" border="0" cellpadding="0" cellspacing="0" style="%s">
<tr>
<td class="content" style="padding: 32px 40px;">
<td class="content" style="%s">
%s
</td>
</tr>
</table>',
$class,
$style,
$content_style,
$content
);
}
@@ -366,23 +384,21 @@ class EmailRenderer {
$html = file_get_contents($template_path);
// Get email customization settings
$settings = get_option('woonoow_notification_settings', []);
$email_settings = $settings['email_appearance'] ?? [];
$email_settings = get_option('woonoow_email_settings', []);
// Email body background
$body_bg = $email_settings['body_bg'] ?? '#f8f8f8';
$body_bg = '#f8f8f8';
// Email header (logo or text)
$header_type = $email_settings['header_type'] ?? 'text';
if ($header_type === 'logo' && !empty($email_settings['header_logo'])) {
if (!empty($email_settings['logo_url'])) {
$header = sprintf(
'<a href="%s"><img src="%s" alt="%s" style="max-width: 140px;"></a>',
'<a href="%s"><img src="%s" alt="%s" style="max-width: 200px; max-height: 60px;"></a>',
esc_url($variables['store_url']),
esc_url($email_settings['header_logo']),
esc_url($email_settings['logo_url']),
esc_attr($variables['store_name'])
);
} else {
$header_text = $email_settings['header_text'] ?? $variables['store_name'];
$header_text = !empty($email_settings['header_text']) ? $email_settings['header_text'] : $variables['store_name'];
$header = sprintf(
'<a href="%s" style="font-size: 24px; font-weight: 700; color: #333; text-decoration: none;">%s</a>',
esc_url($variables['store_url']),
@@ -390,24 +406,27 @@ class EmailRenderer {
);
}
// Email footer
$footer_text = $email_settings['footer_text'] ?? sprintf(
// Email footer with {current_year} variable support
$footer_text = !empty($email_settings['footer_text']) ? $email_settings['footer_text'] : sprintf(
'© %s %s. All rights reserved.',
date('Y'),
$variables['store_name']
);
// Replace {current_year} with actual year
$footer_text = str_replace('{current_year}', date('Y'), $footer_text);
// Social icons
$social_html = '';
if (!empty($email_settings['social_links'])) {
$social_html = '<div class="social-icons" style="margin-top: 16px;">';
foreach ($email_settings['social_links'] as $platform => $url) {
if (!empty($url)) {
if (!empty($email_settings['social_links']) && is_array($email_settings['social_links'])) {
$social_html = '<div class="social-icons" style="margin-top: 16px; text-align: center;">';
foreach ($email_settings['social_links'] as $link) {
if (!empty($link['url']) && !empty($link['platform'])) {
$social_html .= sprintf(
'<a href="%s" style="display: inline-block; margin: 0 8px;"><img src="%s" alt="%s" style="width: 24px; height: 24px;"></a>',
esc_url($url),
$this->get_social_icon_url($platform),
esc_attr(ucfirst($platform))
esc_url($link['url']),
$this->get_social_icon_url($link['platform']),
esc_attr(ucfirst($link['platform']))
);
}
}
@@ -415,7 +434,7 @@ class EmailRenderer {
}
$footer = sprintf(
'<p style="font-family: \'Inter\', Arial, sans-serif; font-size: 13px; line-height: 1.5; color: #888888; margin: 0 0 8px 0;">%s</p>%s',
'<p style="font-family: \'Inter\', Arial, sans-serif; font-size: 13px; line-height: 1.5; color: #888888; margin: 0 0 8px 0; text-align: center;">%s</p>%s',
nl2br(esc_html($footer_text)),
$social_html
);