server_key = get_option('twp_fcm_server_key', ''); } /** * Send push notification to user's devices */ public function send_notification($user_id, $title, $body, $data = array()) { if (empty($this->server_key)) { error_log('TWP FCM: Server key not configured'); return false; } // Get user's FCM tokens $tokens = $this->get_user_tokens($user_id); if (empty($tokens)) { error_log("TWP FCM: No tokens found for user $user_id"); return false; } $success_count = 0; $failed_tokens = array(); foreach ($tokens as $token) { $result = $this->send_to_token($token, $title, $body, $data); if ($result['success']) { $success_count++; } else { $failed_tokens[] = $token; // If token is invalid, remove it from database if ($result['error'] === 'invalid_token') { $this->remove_invalid_token($token); } } } error_log("TWP FCM: Sent notification to $success_count/" . count($tokens) . " devices for user $user_id"); return $success_count > 0; } /** * Send notification to specific token */ private function send_to_token($token, $title, $body, $data = array()) { $notification = array( 'title' => $title, 'body' => $body, 'sound' => 'default', 'priority' => 'high', 'click_action' => 'FLUTTER_NOTIFICATION_CLICK' ); $payload = array( 'to' => $token, 'notification' => $notification, 'data' => array_merge($data, array( 'title' => $title, 'body' => $body, 'timestamp' => time() )), 'priority' => 'high' ); $headers = array( 'Authorization: key=' . $this->server_key, 'Content-Type: application/json' ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->fcm_url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http_code !== 200) { error_log("TWP FCM: Failed to send notification. HTTP $http_code: $response"); // Check if token is invalid $response_data = json_decode($response, true); if (isset($response_data['results'][0]['error']) && in_array($response_data['results'][0]['error'], array('InvalidRegistration', 'NotRegistered'))) { return array('success' => false, 'error' => 'invalid_token'); } return array('success' => false, 'error' => 'http_error'); } return array('success' => true); } /** * Get all active FCM tokens for a user */ private function get_user_tokens($user_id) { global $wpdb; $table = $wpdb->prefix . 'twp_mobile_sessions'; return $wpdb->get_col($wpdb->prepare( "SELECT fcm_token FROM $table WHERE user_id = %d AND is_active = 1 AND fcm_token IS NOT NULL AND fcm_token != '' AND expires_at > NOW()", $user_id )); } /** * Remove invalid FCM token from database */ private function remove_invalid_token($token) { global $wpdb; $table = $wpdb->prefix . 'twp_mobile_sessions'; $wpdb->update( $table, array('fcm_token' => null), array('fcm_token' => $token), array('%s'), array('%s') ); error_log("TWP FCM: Removed invalid token from database"); } /** * Send incoming call notification */ public function notify_incoming_call($user_id, $from_number, $queue_name, $call_sid) { $title = 'Incoming Call'; $body = "Call from $from_number in $queue_name queue"; $data = array( 'type' => 'incoming_call', 'call_sid' => $call_sid, 'from_number' => $from_number, 'queue_name' => $queue_name ); return $this->send_notification($user_id, $title, $body, $data); } /** * Send queue timeout notification */ public function notify_queue_timeout($user_id, $queue_name, $waiting_count) { $title = 'Queue Alert'; $body = "$queue_name has $waiting_count waiting call" . ($waiting_count > 1 ? 's' : ''); $data = array( 'type' => 'queue_timeout', 'queue_name' => $queue_name, 'waiting_count' => $waiting_count ); return $this->send_notification($user_id, $title, $body, $data); } /** * Send agent status change notification */ public function notify_status_change($user_id, $old_status, $new_status) { $title = 'Status Changed'; $body = "Your status changed from $old_status to $new_status"; $data = array( 'type' => 'status_change', 'old_status' => $old_status, 'new_status' => $new_status ); return $this->send_notification($user_id, $title, $body, $data); } /** * Test notification (for settings page) */ public function send_test_notification($user_id) { $title = 'Test Notification'; $body = 'This is a test notification from Twilio WordPress Plugin'; $data = array( 'type' => 'test', 'test' => true ); return $this->send_notification($user_id, $title, $body, $data); } }