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'], ], ]); // POST /woonoow/v1/notifications/events/update register_rest_route($this->namespace, '/' . $this->rest_base . '/events/update', [ [ 'methods' => 'POST', 'callback' => [$this, 'update_event'], 'permission_callback' => [$this, 'check_permission'], ], ]); // GET /woonoow/v1/notifications/templates register_rest_route($this->namespace, '/' . $this->rest_base . '/templates', [ [ 'methods' => 'GET', 'callback' => [$this, 'get_templates'], 'permission_callback' => [$this, 'check_permission'], ], ]); // GET /woonoow/v1/notifications/templates/:eventId/:channelId register_rest_route($this->namespace, '/' . $this->rest_base . '/templates/(?P[a-zA-Z0-9_-]+)/(?P[a-zA-Z0-9_-]+)', [ [ 'methods' => 'GET', 'callback' => [$this, 'get_template'], 'permission_callback' => [$this, 'check_permission'], ], ]); // POST /woonoow/v1/notifications/templates register_rest_route($this->namespace, '/' . $this->rest_base . '/templates', [ [ 'methods' => 'POST', 'callback' => [$this, 'save_template'], 'permission_callback' => [$this, 'check_permission'], ], ]); // DELETE /woonoow/v1/notifications/templates/:eventId/:channelId register_rest_route($this->namespace, '/' . $this->rest_base . '/templates/(?P[a-zA-Z0-9_-]+)/(?P[a-zA-Z0-9_-]+)', [ [ 'methods' => 'DELETE', 'callback' => [$this, 'delete_template'], 'permission_callback' => [$this, 'check_permission'], ], ]); // GET /woonoow/v1/notifications/push/vapid-key register_rest_route($this->namespace, '/' . $this->rest_base . '/push/vapid-key', [ [ 'methods' => 'GET', 'callback' => [$this, 'get_vapid_key'], 'permission_callback' => '__return_true', ], ]); // POST /woonoow/v1/notifications/push/subscribe register_rest_route($this->namespace, '/' . $this->rest_base . '/push/subscribe', [ [ 'methods' => 'POST', 'callback' => [$this, 'push_subscribe'], 'permission_callback' => '__return_true', ], ]); // POST /woonoow/v1/notifications/push/unsubscribe register_rest_route($this->namespace, '/' . $this->rest_base . '/push/unsubscribe', [ [ 'methods' => 'POST', 'callback' => [$this, 'push_unsubscribe'], 'permission_callback' => '__return_true', ], ]); } /** * Get available notification channels * * @param WP_REST_Request $request Request object * @return WP_REST_Response */ public function get_channels(WP_REST_Request $request) { $channels = [ [ 'id' => 'email', 'label' => __('Email', 'woonoow'), 'icon' => 'mail', 'enabled' => true, 'builtin' => true, ], [ 'id' => 'push', 'label' => __('Push Notifications', 'woonoow'), 'icon' => 'bell', 'enabled' => true, 'builtin' => true, ], ]; // Allow addons to register their channels $channels = apply_filters('woonoow_notification_channels', $channels); return new WP_REST_Response($channels, 200); } /** * Get notification events * * @param WP_REST_Request $request Request object * @return WP_REST_Response */ public function get_events(WP_REST_Request $request) { // Get saved settings $settings = get_option('woonoow_notification_settings', []); // Define default events (maps to WooCommerce emails) $events = [ 'orders' => [ [ 'id' => 'order_placed', 'label' => __('Order Placed', 'woonoow'), 'description' => __('When a new order is placed', 'woonoow'), 'category' => 'orders', 'wc_email' => 'new_order', 'enabled' => true, 'channels' => $settings['order_placed'] ?? ['email' => ['enabled' => true, 'recipient' => 'admin']], ], [ 'id' => 'order_processing', 'label' => __('Order Processing', 'woonoow'), 'description' => __('When order status changes to processing', 'woonoow'), 'category' => 'orders', 'wc_email' => 'customer_processing_order', 'enabled' => true, 'channels' => $settings['order_processing'] ?? ['email' => ['enabled' => true, 'recipient' => 'customer']], ], [ 'id' => 'order_completed', 'label' => __('Order Completed', 'woonoow'), 'description' => __('When order is marked as completed', 'woonoow'), 'category' => 'orders', 'wc_email' => 'customer_completed_order', 'enabled' => true, 'channels' => $settings['order_completed'] ?? ['email' => ['enabled' => true, 'recipient' => 'customer']], ], [ 'id' => 'order_cancelled', 'label' => __('Order Cancelled', 'woonoow'), 'description' => __('When order is cancelled', 'woonoow'), 'category' => 'orders', 'wc_email' => 'cancelled_order', 'enabled' => true, 'channels' => $settings['order_cancelled'] ?? ['email' => ['enabled' => true, 'recipient' => 'admin']], ], [ 'id' => 'order_refunded', 'label' => __('Order Refunded', 'woonoow'), 'description' => __('When order is refunded', 'woonoow'), 'category' => 'orders', 'wc_email' => 'customer_refunded_order', 'enabled' => true, 'channels' => $settings['order_refunded'] ?? ['email' => ['enabled' => true, 'recipient' => 'customer']], ], ], 'products' => [ [ 'id' => 'low_stock', 'label' => __('Low Stock Alert', 'woonoow'), 'description' => __('When product stock is low', 'woonoow'), 'category' => 'products', 'wc_email' => 'low_stock', 'enabled' => true, 'channels' => $settings['low_stock'] ?? ['email' => ['enabled' => true, 'recipient' => 'admin']], ], [ 'id' => 'out_of_stock', 'label' => __('Out of Stock Alert', 'woonoow'), 'description' => __('When product is out of stock', 'woonoow'), 'category' => 'products', 'wc_email' => 'no_stock', 'enabled' => true, 'channels' => $settings['out_of_stock'] ?? ['email' => ['enabled' => true, 'recipient' => 'admin']], ], ], 'customers' => [ [ 'id' => 'new_customer', 'label' => __('New Customer', 'woonoow'), 'description' => __('When a new customer registers', 'woonoow'), 'category' => 'customers', 'wc_email' => 'customer_new_account', 'enabled' => true, 'channels' => $settings['new_customer'] ?? ['email' => ['enabled' => true, 'recipient' => 'customer']], ], [ 'id' => 'customer_note', 'label' => __('Customer Note Added', 'woonoow'), 'description' => __('When a note is added to customer order', 'woonoow'), 'category' => 'customers', 'wc_email' => 'customer_note', 'enabled' => true, 'channels' => $settings['customer_note'] ?? ['email' => ['enabled' => true, 'recipient' => 'customer']], ], ], ]; // Allow addons to add custom events $events = apply_filters('woonoow_notification_events', $events); return new WP_REST_Response($events, 200); } /** * Update event settings * * @param WP_REST_Request $request Request object * @return WP_REST_Response|WP_Error */ public function update_event(WP_REST_Request $request) { $event_id = $request->get_param('eventId'); $channel_id = $request->get_param('channelId'); $enabled = $request->get_param('enabled'); $recipient = $request->get_param('recipient'); if (empty($event_id) || empty($channel_id)) { return new WP_Error( 'invalid_params', __('Event ID and Channel ID are required', 'woonoow'), ['status' => 400] ); } // Get current settings $settings = get_option('woonoow_notification_settings', []); // Update settings if (!isset($settings[$event_id])) { $settings[$event_id] = []; } $settings[$event_id][$channel_id] = [ 'enabled' => $enabled, 'recipient' => $recipient ?? 'admin', ]; // Save settings update_option('woonoow_notification_settings', $settings); // Fire action for addons to react do_action('woonoow_notification_event_updated', $event_id, $channel_id, $enabled, $recipient); return new WP_REST_Response([ 'success' => true, 'message' => __('Event settings updated successfully', 'woonoow'), ], 200); } /** * Check if user has permission * * @return bool */ public function check_permission() { return current_user_can('manage_woocommerce') || current_user_can('manage_options'); } /** * Get all templates * * @param WP_REST_Request $request Request object * @return WP_REST_Response */ public function get_templates(WP_REST_Request $request) { $templates = TemplateProvider::get_templates(); return new WP_REST_Response($templates, 200); } /** * Get single template * * @param WP_REST_Request $request Request object * @return WP_REST_Response|WP_Error */ public function get_template(WP_REST_Request $request) { $event_id = $request->get_param('eventId'); $channel_id = $request->get_param('channelId'); $template = TemplateProvider::get_template($event_id, $channel_id); if (!$template) { return new WP_Error( 'template_not_found', __('Template not found', 'woonoow'), ['status' => 404] ); } return new WP_REST_Response($template, 200); } /** * Save template * * @param WP_REST_Request $request Request object * @return WP_REST_Response|WP_Error */ public function save_template(WP_REST_Request $request) { $event_id = $request->get_param('eventId'); $channel_id = $request->get_param('channelId'); $subject = $request->get_param('subject'); $body = $request->get_param('body'); if (empty($event_id) || empty($channel_id)) { return new WP_Error( 'invalid_params', __('Event ID and Channel ID are required', 'woonoow'), ['status' => 400] ); } $success = TemplateProvider::save_template($event_id, $channel_id, [ 'subject' => $subject, 'body' => $body, ]); if (!$success) { return new WP_Error( 'save_failed', __('Failed to save template', 'woonoow'), ['status' => 500] ); } return new WP_REST_Response([ 'success' => true, 'message' => __('Template saved successfully', 'woonoow'), ], 200); } /** * Delete template (revert to default) * * @param WP_REST_Request $request Request object * @return WP_REST_Response */ public function delete_template(WP_REST_Request $request) { $event_id = $request->get_param('eventId'); $channel_id = $request->get_param('channelId'); TemplateProvider::delete_template($event_id, $channel_id); return new WP_REST_Response([ 'success' => true, 'message' => __('Template reverted to default', 'woonoow'), ], 200); } /** * Get VAPID public key for push notifications * * @param WP_REST_Request $request Request object * @return WP_REST_Response */ public function get_vapid_key(WP_REST_Request $request) { $public_key = PushNotificationHandler::get_public_key(); return new WP_REST_Response([ 'publicKey' => $public_key, ], 200); } /** * Subscribe to push notifications * * @param WP_REST_Request $request Request object * @return WP_REST_Response|WP_Error */ public function push_subscribe(WP_REST_Request $request) { $subscription = $request->get_param('subscription'); $user_id = get_current_user_id(); if (empty($subscription)) { return new WP_Error( 'invalid_subscription', __('Subscription data is required', 'woonoow'), ['status' => 400] ); } $success = PushNotificationHandler::subscribe($subscription, $user_id); if (!$success) { return new WP_Error( 'subscribe_failed', __('Failed to subscribe to push notifications', 'woonoow'), ['status' => 500] ); } return new WP_REST_Response([ 'success' => true, 'message' => __('Subscribed to push notifications', 'woonoow'), ], 200); } /** * Unsubscribe from push notifications * * @param WP_REST_Request $request Request object * @return WP_REST_Response */ public function push_unsubscribe(WP_REST_Request $request) { $subscription_id = $request->get_param('subscriptionId'); PushNotificationHandler::unsubscribe($subscription_id); return new WP_REST_Response([ 'success' => true, 'message' => __('Unsubscribed from push notifications', 'woonoow'), ], 200); } }