## Task 7 Complete: Default Email Content ✅ ### New File Created: **`DefaultEmailTemplates.php`** - Comprehensive default templates for all 9 events - Separate templates for staff vs customer recipients - Professional, well-structured HTML with card blocks - All use modern card-based email builder syntax ### Email Templates Included: **Order Events:** 1. **Order Placed** (Staff) - Hero card with order notification - Order details, customer info, items list - View order button 2. **Order Processing** (Customer) - Success card confirmation - Order summary with status - What's next information - Track order button 3. **Order Completed** (Customer) - Success card celebration - Order details with completion date - Thank you message - View order + Continue shopping buttons 4. **Order Cancelled** (Staff) - Warning card notification - Order and customer details - View order button 5. **Order Refunded** (Customer) - Info card with refund notification - Refund details and amount - Timeline expectations - View order button **Product Events:** 6. **Low Stock Alert** (Staff) - Warning card - Product details with stock levels - Action required message - View product button 7. **Out of Stock Alert** (Staff) - Warning card - Product details - Immediate action required - Manage product button **Customer Events:** 8. **New Customer** (Customer) - Hero welcome card - Account details - Feature list (order history, tracking, etc.) - My Account + Start Shopping buttons 9. **Customer Note** (Customer) - Info card - Order details - Note content display - View order button ### Integration: - Updated `TemplateProvider.php` to use DefaultEmailTemplates - Automatic template generation for all events - Push notification templates also complete - Proper variable mapping per event type ### Features: - Card-based modern design - Hero/Success/Warning/Info card types - Multiple buttons with solid/outline styles - Proper variable placeholders - Professional copy for all scenarios - Consistent branding throughout All 7 tasks now complete! 🎉
325 lines
9.0 KiB
PHP
325 lines
9.0 KiB
PHP
<?php
|
|
/**
|
|
* Notification Template Provider
|
|
*
|
|
* Manages notification templates for all channels.
|
|
*
|
|
* @package WooNooW\Core\Notifications
|
|
*/
|
|
|
|
namespace WooNooW\Core\Notifications;
|
|
|
|
class TemplateProvider {
|
|
|
|
/**
|
|
* Option key for storing templates
|
|
*/
|
|
const OPTION_KEY = 'woonoow_notification_templates';
|
|
|
|
/**
|
|
* Get all templates
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_templates() {
|
|
$templates = get_option(self::OPTION_KEY, []);
|
|
|
|
// Merge with defaults
|
|
$defaults = self::get_default_templates();
|
|
|
|
return array_merge($defaults, $templates);
|
|
}
|
|
|
|
/**
|
|
* Get template for specific event and channel
|
|
*
|
|
* @param string $event_id Event ID
|
|
* @param string $channel_id Channel ID
|
|
* @return array|null
|
|
*/
|
|
public static function get_template($event_id, $channel_id) {
|
|
$templates = self::get_templates();
|
|
|
|
$key = "{$event_id}_{$channel_id}";
|
|
|
|
if (isset($templates[$key])) {
|
|
return $templates[$key];
|
|
}
|
|
|
|
// Return default if exists
|
|
$defaults = self::get_default_templates();
|
|
return $defaults[$key] ?? null;
|
|
}
|
|
|
|
/**
|
|
* Save template
|
|
*
|
|
* @param string $event_id Event ID
|
|
* @param string $channel_id Channel ID
|
|
* @param array $template Template data
|
|
* @return bool
|
|
*/
|
|
public static function save_template($event_id, $channel_id, $template) {
|
|
$templates = get_option(self::OPTION_KEY, []);
|
|
|
|
$key = "{$event_id}_{$channel_id}";
|
|
|
|
$templates[$key] = [
|
|
'event_id' => $event_id,
|
|
'channel_id' => $channel_id,
|
|
'subject' => $template['subject'] ?? '',
|
|
'body' => $template['body'] ?? '',
|
|
'variables' => $template['variables'] ?? [],
|
|
'updated_at' => current_time('mysql'),
|
|
];
|
|
|
|
return update_option(self::OPTION_KEY, $templates);
|
|
}
|
|
|
|
/**
|
|
* Delete template (revert to default)
|
|
*
|
|
* @param string $event_id Event ID
|
|
* @param string $channel_id Channel ID
|
|
* @return bool
|
|
*/
|
|
public static function delete_template($event_id, $channel_id) {
|
|
$templates = get_option(self::OPTION_KEY, []);
|
|
|
|
$key = "{$event_id}_{$channel_id}";
|
|
|
|
if (isset($templates[$key])) {
|
|
unset($templates[$key]);
|
|
return update_option(self::OPTION_KEY, $templates);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get WooCommerce email template content
|
|
*
|
|
* @param string $email_id WooCommerce email ID
|
|
* @return array|null
|
|
*/
|
|
private static function get_wc_email_template($email_id) {
|
|
if (!function_exists('WC')) {
|
|
return null;
|
|
}
|
|
|
|
$mailer = WC()->mailer();
|
|
$emails = $mailer->get_emails();
|
|
|
|
if (isset($emails[$email_id])) {
|
|
$email = $emails[$email_id];
|
|
return [
|
|
'subject' => $email->get_subject(),
|
|
'heading' => $email->get_heading(),
|
|
'enabled' => $email->is_enabled(),
|
|
];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get default templates
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_default_templates() {
|
|
$templates = [];
|
|
|
|
// Define all events with their recipient types
|
|
$events = [
|
|
'order_placed' => 'staff',
|
|
'order_processing' => 'customer',
|
|
'order_completed' => 'customer',
|
|
'order_cancelled' => 'staff',
|
|
'order_refunded' => 'customer',
|
|
'low_stock' => 'staff',
|
|
'out_of_stock' => 'staff',
|
|
'new_customer' => 'customer',
|
|
'customer_note' => 'customer',
|
|
];
|
|
|
|
// Generate email templates from DefaultEmailTemplates
|
|
foreach ($events as $event_id => $recipient_type) {
|
|
$default = DefaultEmailTemplates::get_template($event_id, $recipient_type);
|
|
|
|
$templates["{$event_id}_email"] = [
|
|
'event_id' => $event_id,
|
|
'channel_id' => 'email',
|
|
'subject' => $default['subject'],
|
|
'body' => $default['body'],
|
|
'variables' => self::get_variables_for_event($event_id),
|
|
];
|
|
}
|
|
|
|
// Add push notification templates
|
|
$templates['order_placed_push'] = [
|
|
'event_id' => 'order_placed',
|
|
'channel_id' => 'push',
|
|
'subject' => __('New Order #{order_number}', 'woonoow'),
|
|
'body' => __('New order from {customer_name} - {order_total}', 'woonoow'),
|
|
'variables' => self::get_order_variables(),
|
|
];
|
|
$templates['order_processing_push'] = [
|
|
'event_id' => 'order_processing',
|
|
'channel_id' => 'push',
|
|
'subject' => __('Order Processing', 'woonoow'),
|
|
'body' => __('Your order #{order_number} is being processed', 'woonoow'),
|
|
'variables' => self::get_order_variables(),
|
|
];
|
|
$templates['order_completed_push'] = [
|
|
'event_id' => 'order_completed',
|
|
'channel_id' => 'push',
|
|
'subject' => __('Order Completed', 'woonoow'),
|
|
'body' => __('Your order #{order_number} has been completed!', 'woonoow'),
|
|
'variables' => self::get_order_variables(),
|
|
];
|
|
$templates['order_cancelled_push'] = [
|
|
'event_id' => 'order_cancelled',
|
|
'channel_id' => 'push',
|
|
'subject' => __('Order Cancelled', 'woonoow'),
|
|
'body' => __('Order #{order_number} has been cancelled', 'woonoow'),
|
|
'variables' => self::get_order_variables(),
|
|
];
|
|
$templates['order_refunded_push'] = [
|
|
'event_id' => 'order_refunded',
|
|
'channel_id' => 'push',
|
|
'subject' => __('Order Refunded', 'woonoow'),
|
|
'body' => __('Your order #{order_number} has been refunded', 'woonoow'),
|
|
'variables' => self::get_order_variables(),
|
|
];
|
|
$templates['low_stock_push'] = [
|
|
'event_id' => 'low_stock',
|
|
'channel_id' => 'push',
|
|
'subject' => __('Low Stock Alert', 'woonoow'),
|
|
'body' => __('{product_name} is running low on stock', 'woonoow'),
|
|
'variables' => self::get_product_variables(),
|
|
];
|
|
$templates['out_of_stock_push'] = [
|
|
'event_id' => 'out_of_stock',
|
|
'channel_id' => 'push',
|
|
'subject' => __('Out of Stock Alert', 'woonoow'),
|
|
'body' => __('{product_name} is now out of stock', 'woonoow'),
|
|
'variables' => self::get_product_variables(),
|
|
];
|
|
$templates['new_customer_push'] = [
|
|
'event_id' => 'new_customer',
|
|
'channel_id' => 'push',
|
|
'subject' => __('Welcome!', 'woonoow'),
|
|
'body' => __('Welcome to {store_name}, {customer_name}!', 'woonoow'),
|
|
'variables' => self::get_customer_variables(),
|
|
];
|
|
$templates['customer_note_push'] = [
|
|
'event_id' => 'customer_note',
|
|
'channel_id' => 'push',
|
|
'subject' => __('Order Note Added', 'woonoow'),
|
|
'body' => __('A note has been added to order #{order_number}', 'woonoow'),
|
|
'variables' => self::get_order_variables(),
|
|
];
|
|
|
|
return $templates;
|
|
}
|
|
|
|
/**
|
|
* Get variables for a specific event
|
|
*
|
|
* @param string $event_id Event ID
|
|
* @return array
|
|
*/
|
|
private static function get_variables_for_event($event_id) {
|
|
// Product events
|
|
if (in_array($event_id, ['low_stock', 'out_of_stock'])) {
|
|
return self::get_product_variables();
|
|
}
|
|
|
|
// Customer events (but not order-related)
|
|
if ($event_id === 'new_customer') {
|
|
return self::get_customer_variables();
|
|
}
|
|
|
|
// All other events are order-related
|
|
return self::get_order_variables();
|
|
}
|
|
|
|
/**
|
|
* Get available order variables
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_order_variables() {
|
|
return [
|
|
'order_number' => __('Order Number', 'woonoow'),
|
|
'order_total' => __('Order Total', 'woonoow'),
|
|
'order_status' => __('Order Status', 'woonoow'),
|
|
'order_date' => __('Order Date', 'woonoow'),
|
|
'order_url' => __('Order URL', 'woonoow'),
|
|
'order_items_list' => __('Order Items (formatted list)', 'woonoow'),
|
|
'order_items_table' => __('Order Items (formatted table)', 'woonoow'),
|
|
'payment_method' => __('Payment Method', 'woonoow'),
|
|
'payment_url' => __('Payment URL (for pending payments)', 'woonoow'),
|
|
'shipping_method' => __('Shipping Method', 'woonoow'),
|
|
'tracking_number' => __('Tracking Number', 'woonoow'),
|
|
'refund_amount' => __('Refund Amount', 'woonoow'),
|
|
'customer_name' => __('Customer Name', 'woonoow'),
|
|
'customer_email' => __('Customer Email', 'woonoow'),
|
|
'customer_phone' => __('Customer Phone', 'woonoow'),
|
|
'billing_address' => __('Billing Address', 'woonoow'),
|
|
'shipping_address' => __('Shipping Address', 'woonoow'),
|
|
'store_name' => __('Store Name', 'woonoow'),
|
|
'store_url' => __('Store URL', 'woonoow'),
|
|
'store_email' => __('Store Email', 'woonoow'),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get available product variables
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_product_variables() {
|
|
return [
|
|
'product_name' => __('Product Name', 'woonoow'),
|
|
'product_sku' => __('Product SKU', 'woonoow'),
|
|
'product_url' => __('Product URL', 'woonoow'),
|
|
'stock_quantity' => __('Stock Quantity', 'woonoow'),
|
|
'store_name' => __('Store Name', 'woonoow'),
|
|
'store_url' => __('Store URL', 'woonoow'),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get available customer variables
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_customer_variables() {
|
|
return [
|
|
'customer_name' => __('Customer Name', 'woonoow'),
|
|
'customer_email' => __('Customer Email', 'woonoow'),
|
|
'customer_phone' => __('Customer Phone', 'woonoow'),
|
|
'store_name' => __('Store Name', 'woonoow'),
|
|
'store_url' => __('Store URL', 'woonoow'),
|
|
'store_email' => __('Store Email', 'woonoow'),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Replace variables in template
|
|
*
|
|
* @param string $content Content with variables
|
|
* @param array $data Data to replace variables
|
|
* @return string
|
|
*/
|
|
public static function replace_variables($content, $data) {
|
|
foreach ($data as $key => $value) {
|
|
$content = str_replace('{' . $key . '}', $value, $content);
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
}
|