feat: Implement notification system with extensible channel architecture

##  Notification System Implementation

Following NOTIFICATION_STRATEGY.md, built on top of WooCommerce email infrastructure.

### Backend (PHP)

**1. NotificationManager** (`includes/Core/Notifications/NotificationManager.php`)
- Central manager for notification system
- Registers email channel (built-in)
- Registers default notification events (orders, products, customers)
- Provides hooks for addon channels
- Maps to WooCommerce email IDs

**2. NotificationSettingsProvider** (`includes/Core/Notifications/NotificationSettingsProvider.php`)
- Manages settings in wp_options
- Per-event channel configuration
- Per-channel recipient settings (admin/customer/both)
- Default settings with email enabled

**3. NotificationsController** (`includes/Api/NotificationsController.php`)
- REST API endpoints:
  - GET /notifications/channels - List available channels
  - GET /notifications/events - List notification events (grouped by category)
  - GET /notifications/settings - Get all settings
  - POST /notifications/settings - Update settings

### Frontend (React)

**Updated Notifications.tsx:**
- Shows available notification channels (email + addons)
- Channel cards with built-in/addon badges
- Event configuration by category (orders, products, customers)
- Toggle channels per event with button UI
- Link to WooCommerce advanced email settings
- Responsive and modern UI

### Key Features

 **Built on WooCommerce Emails**
- Email channel uses existing WC email system
- No reinventing the wheel
- Maps events to WC email IDs

 **Extensible Architecture**
- Addons can register channels via hooks
- `woonoow_notification_channels` filter
- `woonoow_notification_send_{channel}` action
- Per-event channel selection

 **User-Friendly UI**
- Clear channel status (Active/Inactive)
- Per-event channel toggles
- Category grouping (orders, products, customers)
- Addon discovery hints

 **Settings Storage**
- Stored in wp_options (woonoow_notification_settings)
- Per-event configuration
- Per-channel settings
- Default: email enabled for all events

### Addon Integration Example

```php
// Addon registers WhatsApp channel
add_action("woonoow_register_notification_channels", function() {
    NotificationManager::register_channel("whatsapp", [
        "label" => "WhatsApp",
        "icon" => "message-circle",
        "addon" => "woonoow-whatsapp",
    ]);
});

// Addon handles sending
add_action("woonoow_notification_send_whatsapp", function($event_id, $data) {
    // Send WhatsApp message
}, 10, 2);
```

### Files Created
- NotificationManager.php
- NotificationSettingsProvider.php
- NotificationsController.php

### Files Modified
- Routes.php - Register NotificationsController
- Bootstrap.php - Initialize NotificationManager
- Notifications.tsx - New UI with channels and events

---

**Ready for addon development!** 🚀
Next: Build Telegram addon as proof of concept
This commit is contained in:
dwindown
2025-11-11 12:11:08 +07:00
parent 4746834a82
commit 01fc3eb36d
6 changed files with 829 additions and 108 deletions

View File

@@ -0,0 +1,181 @@
<?php
/**
* Notifications REST API Controller
*
* Handles notification settings API endpoints.
*
* @package WooNooW\Api
*/
namespace WooNooW\Api;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use WooNooW\Core\Notifications\NotificationManager;
use WooNooW\Core\Notifications\NotificationSettingsProvider;
class NotificationsController {
/**
* REST API namespace
*/
private $namespace = 'woonoow/v1';
/**
* REST API base
*/
private $rest_base = 'notifications';
/**
* Register routes
*/
public function register_routes() {
// GET /woonoow/v1/notifications/channels
register_rest_route($this->namespace, '/' . $this->rest_base . '/channels', [
[
'methods' => 'GET',
'callback' => [$this, 'get_channels'],
'permission_callback' => [$this, 'check_permission'],
],
]);
// GET /woonoow/v1/notifications/events
register_rest_route($this->namespace, '/' . $this->rest_base . '/events', [
[
'methods' => 'GET',
'callback' => [$this, 'get_events'],
'permission_callback' => [$this, 'check_permission'],
],
]);
// GET /woonoow/v1/notifications/settings
register_rest_route($this->namespace, '/' . $this->rest_base . '/settings', [
[
'methods' => 'GET',
'callback' => [$this, 'get_settings'],
'permission_callback' => [$this, 'check_permission'],
],
]);
// POST /woonoow/v1/notifications/settings
register_rest_route($this->namespace, '/' . $this->rest_base . '/settings', [
[
'methods' => 'POST',
'callback' => [$this, 'update_settings'],
'permission_callback' => [$this, 'check_permission'],
],
]);
}
/**
* Get available notification channels
*
* @param WP_REST_Request $request Request object
* @return WP_REST_Response
*/
public function get_channels(WP_REST_Request $request) {
$channels = NotificationManager::get_channels();
// Add enabled status from settings
$settings = NotificationSettingsProvider::get_settings();
$channel_settings = $settings['channels'] ?? [];
foreach ($channels as $id => &$channel) {
$channel['enabled'] = $channel_settings[$id]['enabled'] ?? $channel['builtin'];
}
return new WP_REST_Response(array_values($channels), 200);
}
/**
* Get notification events
*
* @param WP_REST_Request $request Request object
* @return WP_REST_Response
*/
public function get_events(WP_REST_Request $request) {
$events = NotificationManager::get_events();
$settings = NotificationSettingsProvider::get_settings();
$event_settings = $settings['events'] ?? [];
// Merge event data with settings
foreach ($events as $id => &$event) {
$event_config = $event_settings[$id] ?? [];
$event['enabled'] = $event_config['enabled'] ?? true;
$event['channels'] = $event_config['channels'] ?? ['email'];
$event['recipients'] = $event_config['recipients'] ?? ['email' => 'admin'];
}
// Group by category
$grouped = [
'orders' => [],
'products' => [],
'customers' => [],
];
foreach ($events as $event) {
$category = $event['category'] ?? 'general';
if (!isset($grouped[$category])) {
$grouped[$category] = [];
}
$grouped[$category][] = $event;
}
return new WP_REST_Response($grouped, 200);
}
/**
* Get notification settings
*
* @param WP_REST_Request $request Request object
* @return WP_REST_Response
*/
public function get_settings(WP_REST_Request $request) {
$settings = NotificationSettingsProvider::get_settings();
return new WP_REST_Response($settings, 200);
}
/**
* Update notification settings
*
* @param WP_REST_Request $request Request object
* @return WP_REST_Response|WP_Error
*/
public function update_settings(WP_REST_Request $request) {
$new_settings = $request->get_json_params();
if (empty($new_settings)) {
return new WP_Error(
'invalid_settings',
__('Invalid settings data', 'woonoow'),
['status' => 400]
);
}
$updated = NotificationSettingsProvider::update_settings($new_settings);
if (!$updated) {
return new WP_Error(
'update_failed',
__('Failed to update notification settings', 'woonoow'),
['status' => 500]
);
}
return new WP_REST_Response([
'success' => true,
'message' => __('Notification settings updated successfully', 'woonoow'),
'settings' => NotificationSettingsProvider::get_settings(),
], 200);
}
/**
* Check if user has permission
*
* @return bool
*/
public function check_permission() {
return current_user_can('manage_woocommerce') || current_user_can('manage_options');
}
}