Files
WooNooW/includes/Api/NewsletterController.php
Dwindi Ramadhana 0b2c8a56d6 feat: Newsletter system improvements and validation framework
- Fix: Marketing events now display in Staff notifications tab
- Reorganize: Move Coupons to Marketing/Coupons for better organization
- Add: Comprehensive email/phone validation with extensible filter hooks
  - Email validation with regex pattern (xxxx@xxxx.xx)
  - Phone validation with WhatsApp verification support
  - Filter hooks for external API integration (QuickEmailVerification, etc.)
- Fix: Newsletter template routes now use centralized notification email builder
- Add: Validation.php class for reusable validation logic
- Add: VALIDATION_HOOKS.md documentation with integration examples
- Add: NEWSLETTER_CAMPAIGN_PLAN.md architecture for future campaign system
- Fix: API delete method call in Newsletter.tsx (delete -> del)
- Remove: Duplicate EmailTemplates.tsx (using notification system instead)
- Update: Newsletter controller to use centralized Validation class

Breaking changes:
- Coupons routes moved from /routes/Coupons to /routes/Marketing/Coupons
- Legacy /coupons routes maintained for backward compatibility
2025-12-26 10:59:48 +07:00

201 lines
7.4 KiB
PHP

<?php
namespace WooNooW\API;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use WooNooW\Core\Validation;
class NewsletterController {
const API_NAMESPACE = 'woonoow/v1';
public static function register_routes() {
register_rest_route(self::API_NAMESPACE, '/newsletter/subscribe', [
'methods' => 'POST',
'callback' => [__CLASS__, 'subscribe'],
'permission_callback' => '__return_true',
'args' => [
'email' => [
'required' => true,
'type' => 'string',
'validate_callback' => function($param) {
return is_email($param);
},
],
],
]);
register_rest_route(self::API_NAMESPACE, '/newsletter/subscribers', [
'methods' => 'GET',
'callback' => [__CLASS__, 'get_subscribers'],
'permission_callback' => function() {
return current_user_can('manage_options');
},
]);
register_rest_route(self::API_NAMESPACE, '/newsletter/subscribers/(?P<email>[^/]+)', [
'methods' => 'DELETE',
'callback' => [__CLASS__, 'delete_subscriber'],
'permission_callback' => function() {
return current_user_can('manage_options');
},
]);
register_rest_route(self::API_NAMESPACE, '/newsletter/template/(?P<template>[^/]+)', [
'methods' => 'GET',
'callback' => [__CLASS__, 'get_template'],
'permission_callback' => function() {
return current_user_can('manage_options');
},
]);
register_rest_route(self::API_NAMESPACE, '/newsletter/template/(?P<template>[^/]+)', [
'methods' => 'POST',
'callback' => [__CLASS__, 'save_template'],
'permission_callback' => function() {
return current_user_can('manage_options');
},
]);
}
public static function get_template(WP_REST_Request $request) {
$template = $request->get_param('template');
$option_key = "woonoow_newsletter_{$template}_template";
$data = get_option($option_key, [
'subject' => $template === 'welcome' ? 'Welcome to {site_name} Newsletter!' : 'Confirm your newsletter subscription',
'content' => $template === 'welcome'
? "Thank you for subscribing to our newsletter!\n\nYou'll receive updates about our latest products and offers.\n\nBest regards,\n{site_name}"
: "Please confirm your newsletter subscription by clicking the link below:\n\n{confirmation_url}\n\nBest regards,\n{site_name}",
]);
return new WP_REST_Response([
'success' => true,
'subject' => $data['subject'] ?? '',
'content' => $data['content'] ?? '',
], 200);
}
public static function save_template(WP_REST_Request $request) {
$template = $request->get_param('template');
$subject = sanitize_text_field($request->get_param('subject'));
$content = wp_kses_post($request->get_param('content'));
$option_key = "woonoow_newsletter_{$template}_template";
update_option($option_key, [
'subject' => $subject,
'content' => $content,
]);
return new WP_REST_Response([
'success' => true,
'message' => 'Template saved successfully',
], 200);
}
public static function delete_subscriber(WP_REST_Request $request) {
$email = urldecode($request->get_param('email'));
$subscribers = get_option('woonoow_newsletter_subscribers', []);
$subscribers = array_filter($subscribers, function($sub) use ($email) {
return isset($sub['email']) && $sub['email'] !== $email;
});
update_option('woonoow_newsletter_subscribers', array_values($subscribers));
return new WP_REST_Response([
'success' => true,
'message' => 'Subscriber removed successfully',
], 200);
}
public static function subscribe(WP_REST_Request $request) {
$email = sanitize_email($request->get_param('email'));
// Use centralized validation with extensible filter hooks
$validation = Validation::validate_email($email, 'newsletter_subscribe');
if (is_wp_error($validation)) {
return $validation;
}
// Get existing subscribers (now stored as objects with metadata)
$subscribers = get_option('woonoow_newsletter_subscribers', []);
// Check if already subscribed
$existing = array_filter($subscribers, function($sub) use ($email) {
return isset($sub['email']) && $sub['email'] === $email;
});
if (!empty($existing)) {
return new WP_REST_Response([
'success' => true,
'message' => 'You are already subscribed to our newsletter!',
], 200);
}
// Check if email belongs to a WP user
$user = get_user_by('email', $email);
$user_id = $user ? $user->ID : null;
// Add new subscriber with metadata
$subscribers[] = [
'email' => $email,
'user_id' => $user_id,
'status' => 'active',
'subscribed_at' => current_time('mysql'),
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
];
update_option('woonoow_newsletter_subscribers', $subscribers);
// Trigger notification events
do_action('woonoow_newsletter_subscribed', $email, $user_id);
// Trigger notification system events (uses email builder)
do_action('woonoow/notification/event', 'newsletter_welcome', 'customer', [
'email' => $email,
'user_id' => $user_id,
'subscribed_at' => current_time('mysql'),
]);
do_action('woonoow/notification/event', 'newsletter_subscribed_admin', 'staff', [
'email' => $email,
'user_id' => $user_id,
'subscribed_at' => current_time('mysql'),
]);
return new WP_REST_Response([
'success' => true,
'message' => 'Successfully subscribed! Check your email for confirmation.',
], 200);
}
private static function send_welcome_email($email) {
$site_name = get_bloginfo('name');
$template = get_option('woonoow_newsletter_welcome_template', '');
if (empty($template)) {
$template = "Thank you for subscribing to our newsletter!\n\nYou'll receive updates about our latest products and offers.\n\nBest regards,\n{site_name}";
}
$subject = sprintf('Welcome to %s Newsletter!', $site_name);
$message = str_replace('{site_name}', $site_name, $template);
wp_mail($email, $subject, $message);
}
public static function get_subscribers(WP_REST_Request $request) {
$subscribers = get_option('woonoow_newsletter_subscribers', []);
return new WP_REST_Response([
'success' => true,
'data' => [
'subscribers' => $subscribers,
'count' => count($subscribers),
],
], 200);
}
}