prefix . 'twp_call_log'; $data = array( 'call_sid' => sanitize_text_field($call_data['call_sid']), 'from_number' => sanitize_text_field($call_data['from_number'] ?? ''), 'to_number' => sanitize_text_field($call_data['to_number'] ?? ''), 'status' => sanitize_text_field($call_data['status'] ?? 'initiated'), 'duration' => intval($call_data['duration'] ?? 0), 'workflow_id' => intval($call_data['workflow_id'] ?? 0), 'workflow_name' => sanitize_text_field($call_data['workflow_name'] ?? ''), 'queue_time' => intval($call_data['queue_time'] ?? 0), 'actions_taken' => sanitize_textarea_field($call_data['actions_taken'] ?? ''), 'call_data' => json_encode($call_data) ); $format = array('%s', '%s', '%s', '%s', '%d', '%d', '%s', '%d', '%s', '%s'); return $wpdb->insert($table_name, $data, $format); } /** * Update call log */ public static function update_call($call_sid, $updates) { global $wpdb; $table_name = $wpdb->prefix . 'twp_call_log'; $update_data = array(); $format = array(); if (isset($updates['status'])) { $update_data['status'] = sanitize_text_field($updates['status']); $format[] = '%s'; } if (isset($updates['duration'])) { $update_data['duration'] = intval($updates['duration']); $format[] = '%d'; } if (isset($updates['queue_time'])) { $update_data['queue_time'] = intval($updates['queue_time']); $format[] = '%d'; } if (isset($updates['actions_taken'])) { // Append to existing actions $existing = $wpdb->get_var($wpdb->prepare( "SELECT actions_taken FROM $table_name WHERE call_sid = %s", $call_sid )); $new_action = sanitize_textarea_field($updates['actions_taken']); $update_data['actions_taken'] = $existing ? $existing . '; ' . $new_action : $new_action; $format[] = '%s'; } if (isset($updates['call_data'])) { // Merge with existing call data $existing_data = $wpdb->get_var($wpdb->prepare( "SELECT call_data FROM $table_name WHERE call_sid = %s", $call_sid )); $existing_array = $existing_data ? json_decode($existing_data, true) : array(); $new_data = array_merge($existing_array, $updates['call_data']); $update_data['call_data'] = json_encode($new_data); $format[] = '%s'; } if (empty($update_data)) { return false; } return $wpdb->update( $table_name, $update_data, array('call_sid' => $call_sid), $format, array('%s') ); } /** * Get call log by SID */ public static function get_call_log($call_sid) { global $wpdb; $table_name = $wpdb->prefix . 'twp_call_log'; return $wpdb->get_row($wpdb->prepare( "SELECT * FROM $table_name WHERE call_sid = %s", $call_sid )); } /** * Get call logs with filtering */ public static function get_call_logs($filters = array(), $limit = 100, $offset = 0) { global $wpdb; $table_name = $wpdb->prefix . 'twp_call_log'; $where_clauses = array(); $where_values = array(); if (!empty($filters['from_number'])) { $where_clauses[] = "from_number = %s"; $where_values[] = $filters['from_number']; } if (!empty($filters['status'])) { $where_clauses[] = "status = %s"; $where_values[] = $filters['status']; } if (!empty($filters['date_from'])) { $where_clauses[] = "DATE(created_at) >= %s"; $where_values[] = $filters['date_from']; } if (!empty($filters['date_to'])) { $where_clauses[] = "DATE(created_at) <= %s"; $where_values[] = $filters['date_to']; } $where_sql = ''; if (!empty($where_clauses)) { $where_sql = 'WHERE ' . implode(' AND ', $where_clauses); } $sql = "SELECT * FROM $table_name $where_sql ORDER BY created_at DESC LIMIT %d OFFSET %d"; $where_values[] = $limit; $where_values[] = $offset; return $wpdb->get_results($wpdb->prepare($sql, $where_values)); } /** * Get call statistics */ public static function get_call_statistics($period = 'today') { global $wpdb; $table_name = $wpdb->prefix . 'twp_call_log'; $where_clause = ''; switch ($period) { case 'today': $where_clause = "WHERE DATE(created_at) = CURDATE()"; break; case 'week': $where_clause = "WHERE YEARWEEK(created_at) = YEARWEEK(NOW())"; break; case 'month': $where_clause = "WHERE YEAR(created_at) = YEAR(NOW()) AND MONTH(created_at) = MONTH(NOW())"; break; } $stats = array(); // Total calls $stats['total_calls'] = $wpdb->get_var("SELECT COUNT(*) FROM $table_name $where_clause"); // Answered calls $stats['answered_calls'] = $wpdb->get_var("SELECT COUNT(*) FROM $table_name $where_clause AND status = 'completed' AND duration > 0"); // Average duration $avg_duration = $wpdb->get_var("SELECT AVG(duration) FROM $table_name $where_clause AND duration > 0"); $stats['avg_duration'] = $avg_duration ? round($avg_duration) : 0; // Average queue time $avg_queue_time = $wpdb->get_var("SELECT AVG(queue_time) FROM $table_name $where_clause AND queue_time > 0"); $stats['avg_queue_time'] = $avg_queue_time ? round($avg_queue_time) : 0; // Call status breakdown $status_breakdown = $wpdb->get_results(" SELECT status, COUNT(*) as count FROM $table_name $where_clause GROUP BY status ", ARRAY_A); $stats['status_breakdown'] = array(); foreach ($status_breakdown as $status) { $stats['status_breakdown'][$status['status']] = $status['count']; } return $stats; } /** * Log action taken during call */ public static function log_action($call_sid, $action) { $timestamp = current_time('mysql'); $action_with_time = "[{$timestamp}] {$action}"; return self::update_call($call_sid, array( 'actions_taken' => $action_with_time )); } /** * Get call timeline */ public static function get_call_timeline($call_sid) { $log = self::get_call_log($call_sid); if (!$log) { return array(); } $timeline = array(); $call_data = json_decode($log->call_data, true) ?: array(); // Parse actions taken if ($log->actions_taken) { $actions = explode(';', $log->actions_taken); foreach ($actions as $action) { $action = trim($action); if (preg_match('/\[(.*?)\] (.*)/', $action, $matches)) { $timeline[] = array( 'time' => $matches[1], 'event' => $matches[2], 'type' => 'action' ); } } } // Add status changes from call data if (isset($call_data['status_changes'])) { foreach ($call_data['status_changes'] as $change) { $timeline[] = array( 'time' => $change['timestamp'], 'event' => 'Call status changed to: ' . $change['status'], 'type' => 'status' ); } } // Sort by time usort($timeline, function($a, $b) { return strtotime($a['time']) - strtotime($b['time']); }); return $timeline; } }