db = VDatabase::getInstance(); $this->logger = VLogger::getInstance(); $this->cache = VRedis::getInstance(); $this->rbac = VRBAC::getInstance(); } /** * Get platform overview statistics * @param array $filters Date range and other filters * @return array Platform statistics */ public function getPlatformOverview($filters = []) { $dateRange = $this->getDateRange($filters); $cacheKey = "analytics_overview_" . md5(serialize($filters)); // Try cache first if ($this->cache->isConnected()) { $cached = $this->cache->get($cacheKey); if ($cached !== false) { return $cached; } } try { $overview = [ 'users' => $this->getUserStatistics($dateRange), 'content' => $this->getContentStatistics($dateRange), 'engagement' => $this->getEngagementStatistics($dateRange), 'streaming' => $this->getStreamingStatistics($dateRange), 'revenue' => $this->getRevenueStatistics($dateRange), 'performance' => $this->getPerformanceStatistics($dateRange), 'growth' => $this->getGrowthStatistics($dateRange) ]; // Cache for 15 minutes if ($this->cache->isConnected()) { $this->cache->set($cacheKey, $overview, 900); } return $overview; } catch (Exception $e) { $this->logger->error('Failed to get platform overview', [ 'error' => $e->getMessage(), 'filters' => $filters ]); return []; } } /** * Get user analytics * @param int $userId User ID * @param array $filters Filters * @return array User analytics */ public function getUserAnalytics($userId, $filters = []) { // Check permissions if (!$this->rbac->hasPermission($userId, 'analytics.view')) { throw new Exception('User does not have analytics permission'); } $dateRange = $this->getDateRange($filters); $cacheKey = "user_analytics_{$userId}_" . md5(serialize($filters)); // Try cache first if ($this->cache->isConnected()) { $cached = $this->cache->get($cacheKey); if ($cached !== false) { return $cached; } } try { $analytics = [ 'overview' => $this->getUserOverview($userId, $dateRange), 'videos' => $this->getUserVideoAnalytics($userId, $dateRange), 'audience' => $this->getUserAudienceAnalytics($userId, $dateRange), 'engagement' => $this->getUserEngagementAnalytics($userId, $dateRange), 'revenue' => $this->getUserRevenueAnalytics($userId, $dateRange), 'growth' => $this->getUserGrowthAnalytics($userId, $dateRange) ]; // Cache for 10 minutes if ($this->cache->isConnected()) { $this->cache->set($cacheKey, $analytics, 600); } return $analytics; } catch (Exception $e) { $this->logger->error('Failed to get user analytics', [ 'user_id' => $userId, 'error' => $e->getMessage(), 'filters' => $filters ]); return []; } } /** * Get video analytics * @param string $videoKey Video key * @param int $userId User ID (for permission check) * @param array $filters Filters * @return array Video analytics */ public function getVideoAnalytics($videoKey, $userId, $filters = []) { // Check if user owns video or has permission if (!$this->canViewVideoAnalytics($videoKey, $userId)) { throw new Exception('Permission denied'); } $dateRange = $this->getDateRange($filters); $cacheKey = "video_analytics_{$videoKey}_" . md5(serialize($filters)); // Try cache first if ($this->cache->isConnected()) { $cached = $this->cache->get($cacheKey); if ($cached !== false) { return $cached; } } try { $analytics = [ 'overview' => $this->getVideoOverview($videoKey, $dateRange), 'views' => $this->getVideoViewAnalytics($videoKey, $dateRange), 'engagement' => $this->getVideoEngagementAnalytics($videoKey, $dateRange), 'audience' => $this->getVideoAudienceAnalytics($videoKey, $dateRange), 'performance' => $this->getVideoPerformanceAnalytics($videoKey, $dateRange), 'retention' => $this->getVideoRetentionAnalytics($videoKey, $dateRange) ]; // Cache for 5 minutes if ($this->cache->isConnected()) { $this->cache->set($cacheKey, $analytics, 300); } return $analytics; } catch (Exception $e) { $this->logger->error('Failed to get video analytics', [ 'video_key' => $videoKey, 'user_id' => $userId, 'error' => $e->getMessage(), 'filters' => $filters ]); return []; } } /** * Track video view * @param string $videoKey Video key * @param array $viewData View data * @return bool Success status */ public function trackVideoView($videoKey, $viewData) { try { $trackingData = [ 'video_key' => $videoKey, 'user_id' => $viewData['user_id'] ?? null, 'ip_address' => $viewData['ip_address'] ?? $_SERVER['REMOTE_ADDR'], 'user_agent' => $viewData['user_agent'] ?? $_SERVER['HTTP_USER_AGENT'], 'referrer' => $viewData['referrer'] ?? $_SERVER['HTTP_REFERER'] ?? '', 'country' => $viewData['country'] ?? $this->getCountryFromIP($viewData['ip_address'] ?? $_SERVER['REMOTE_ADDR']), 'device_type' => $viewData['device_type'] ?? $this->getDeviceType($_SERVER['HTTP_USER_AGENT'] ?? ''), 'watch_duration' => $viewData['watch_duration'] ?? 0, 'quality' => $viewData['quality'] ?? 'auto', 'created_at' => date('Y-m-d H:i:s') ]; $this->db->doInsert('db_video_analytics', $trackingData); // Update video view count $this->db->doQuery("UPDATE db_videofiles SET file_views = file_views + 1 WHERE file_key = ?", [$videoKey]); // Queue analytics processing job $queue = new VQueue(); $queue->enqueue('AnalyticsProcessingJob', [ 'type' => 'video_view', 'video_key' => $videoKey, 'data' => $trackingData ], 'analytics'); return true; } catch (Exception $e) { $this->logger->error('Failed to track video view', [ 'video_key' => $videoKey, 'error' => $e->getMessage() ]); return false; } } /** * Track user engagement * @param string $eventType Event type (like, comment, share, etc.) * @param array $eventData Event data * @return bool Success status */ public function trackEngagement($eventType, $eventData) { try { $trackingData = [ 'event_type' => $eventType, 'user_id' => $eventData['user_id'] ?? null, 'target_type' => $eventData['target_type'] ?? 'video', 'target_id' => $eventData['target_id'] ?? '', 'ip_address' => $eventData['ip_address'] ?? $_SERVER['REMOTE_ADDR'], 'user_agent' => $eventData['user_agent'] ?? $_SERVER['HTTP_USER_AGENT'], 'data' => json_encode($eventData['additional_data'] ?? []), 'created_at' => date('Y-m-d H:i:s') ]; $this->db->doInsert('db_engagement_analytics', $trackingData); // Queue analytics processing job $queue = new VQueue(); $queue->enqueue('AnalyticsProcessingJob', [ 'type' => 'engagement', 'event_type' => $eventType, 'data' => $trackingData ], 'analytics'); return true; } catch (Exception $e) { $this->logger->error('Failed to track engagement', [ 'event_type' => $eventType, 'error' => $e->getMessage() ]); return false; } } /** * Get real-time statistics * @return array Real-time stats */ public function getRealTimeStats() { $cacheKey = "realtime_stats"; // Try cache first (very short cache) if ($this->cache->isConnected()) { $cached = $this->cache->get($cacheKey); if ($cached !== false) { return $cached; } } try { $stats = [ 'active_users' => $this->getActiveUsers(), 'live_streams' => $this->getLiveStreamCount(), 'current_viewers' => $this->getCurrentViewers(), 'recent_uploads' => $this->getRecentUploads(), 'server_load' => $this->getServerLoad(), 'bandwidth_usage' => $this->getBandwidthUsage() ]; // Cache for 30 seconds if ($this->cache->isConnected()) { $this->cache->set($cacheKey, $stats, 30); } return $stats; } catch (Exception $e) { $this->logger->error('Failed to get real-time stats', [ 'error' => $e->getMessage() ]); return []; } } /** * Generate analytics report * @param string $reportType Report type * @param array $parameters Report parameters * @param int $userId User ID (for permission check) * @return array Report data */ public function generateReport($reportType, $parameters, $userId) { // Check permissions if (!$this->rbac->hasPermission($userId, 'analytics.reports')) { throw new Exception('User does not have report generation permission'); } try { switch ($reportType) { case 'user_growth': return $this->generateUserGrowthReport($parameters); case 'content_performance': return $this->generateContentPerformanceReport($parameters); case 'engagement_trends': return $this->generateEngagementTrendsReport($parameters); case 'revenue_analysis': return $this->generateRevenueAnalysisReport($parameters); case 'platform_health': return $this->generatePlatformHealthReport($parameters); default: throw new Exception("Unknown report type: {$reportType}"); } } catch (Exception $e) { $this->logger->error('Failed to generate report', [ 'report_type' => $reportType, 'user_id' => $userId, 'error' => $e->getMessage() ]); throw $e; } } /** * Get user statistics * @param array $dateRange Date range * @return array User statistics */ private function getUserStatistics($dateRange) { $query = "SELECT COUNT(*) as total_users, COUNT(CASE WHEN usr_status = 'active' THEN 1 END) as active_users, COUNT(CASE WHEN DATE(usr_joindate) >= ? THEN 1 END) as new_users, COUNT(CASE WHEN usr_lastlogin >= ? THEN 1 END) as recent_active FROM db_accountuser WHERE usr_joindate <= ?"; $result = $this->db->doQuery($query, [ $dateRange['start'], $dateRange['start'], $dateRange['end'] ]); return $this->db->doFetch($result) ?: []; } /** * Get content statistics * @param array $dateRange Date range * @return array Content statistics */ private function getContentStatistics($dateRange) { $query = "SELECT COUNT(*) as total_videos, COUNT(CASE WHEN DATE(upload_date) >= ? THEN 1 END) as new_videos, SUM(file_views) as total_views, SUM(CASE WHEN DATE(upload_date) >= ? THEN file_views ELSE 0 END) as period_views, AVG(file_rating) as average_rating, SUM(file_size) as total_storage FROM db_videofiles WHERE upload_date <= ? AND file_type = 'video'"; $result = $this->db->doQuery($query, [ $dateRange['start'], $dateRange['start'], $dateRange['end'] ]); return $this->db->doFetch($result) ?: []; } /** * Get engagement statistics * @param array $dateRange Date range * @return array Engagement statistics */ private function getEngagementStatistics($dateRange) { $query = "SELECT COUNT(CASE WHEN event_type = 'like' THEN 1 END) as total_likes, COUNT(CASE WHEN event_type = 'comment' THEN 1 END) as total_comments, COUNT(CASE WHEN event_type = 'share' THEN 1 END) as total_shares, COUNT(CASE WHEN event_type = 'subscribe' THEN 1 END) as total_subscriptions FROM db_engagement_analytics WHERE created_at BETWEEN ? AND ?"; $result = $this->db->doQuery($query, [ $dateRange['start'], $dateRange['end'] ]); return $this->db->doFetch($result) ?: []; } /** * Get streaming statistics * @param array $dateRange Date range * @return array Streaming statistics */ private function getStreamingStatistics($dateRange) { $query = "SELECT COUNT(*) as total_streams, COUNT(CASE WHEN status = 'live' THEN 1 END) as live_streams, SUM(max_viewers) as total_max_viewers, AVG(max_viewers) as avg_max_viewers, SUM(duration) as total_duration FROM db_live_streams WHERE created_at BETWEEN ? AND ?"; $result = $this->db->doQuery($query, [ $dateRange['start'], $dateRange['end'] ]); return $this->db->doFetch($result) ?: []; } /** * Get revenue statistics * @param array $dateRange Date range * @return array Revenue statistics */ private function getRevenueStatistics($dateRange) { // This would integrate with your monetization system return [ 'total_revenue' => 0, 'period_revenue' => 0, 'transactions' => 0, 'average_transaction' => 0 ]; } /** * Get performance statistics * @param array $dateRange Date range * @return array Performance statistics */ private function getPerformanceStatistics($dateRange) { // Get from job statistics and system metrics $query = "SELECT COUNT(*) as total_jobs, COUNT(CASE WHEN status = 'completed' THEN 1 END) as completed_jobs, COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed_jobs, AVG(processing_time) as avg_processing_time FROM db_job_statistics WHERE created_at BETWEEN ? AND ?"; $result = $this->db->doQuery($query, [ $dateRange['start'], $dateRange['end'] ]); return $this->db->doFetch($result) ?: []; } /** * Get growth statistics * @param array $dateRange Date range * @return array Growth statistics */ private function getGrowthStatistics($dateRange) { // Calculate growth rates $currentPeriod = $this->getUserStatistics($dateRange); // Get previous period for comparison $previousStart = date('Y-m-d', strtotime($dateRange['start'] . ' -30 days')); $previousEnd = date('Y-m-d', strtotime($dateRange['end'] . ' -30 days')); $previousPeriod = $this->getUserStatistics(['start' => $previousStart, 'end' => $previousEnd]); $userGrowth = $this->calculateGrowthRate( $previousPeriod['new_users'] ?? 0, $currentPeriod['new_users'] ?? 0 ); return [ 'user_growth_rate' => $userGrowth, 'content_growth_rate' => 0, // Calculate similarly 'engagement_growth_rate' => 0 // Calculate similarly ]; } /** * Get date range from filters * @param array $filters Filters * @return array Date range */ private function getDateRange($filters) { $end = $filters['end_date'] ?? date('Y-m-d'); $start = $filters['start_date'] ?? date('Y-m-d', strtotime('-30 days')); return [ 'start' => $start, 'end' => $end ]; } /** * Check if user can view video analytics * @param string $videoKey Video key * @param int $userId User ID * @return bool True if allowed */ private function canViewVideoAnalytics($videoKey, $userId) { // Check if user owns the video $query = "SELECT usr_id FROM db_videofiles WHERE file_key = ?"; $result = $this->db->doQuery($query, [$videoKey]); $video = $this->db->doFetch($result); if ($video && $video['usr_id'] == $userId) { return true; } // Check if user has admin permissions return $this->rbac->hasPermission($userId, 'admin.analytics.view'); } /** * Calculate growth rate * @param float $previous Previous value * @param float $current Current value * @return float Growth rate percentage */ private function calculateGrowthRate($previous, $current) { if ($previous == 0) { return $current > 0 ? 100 : 0; } return round((($current - $previous) / $previous) * 100, 2); } /** * Get country from IP address * @param string $ip IP address * @return string Country code */ private function getCountryFromIP($ip) { // Implement IP geolocation (use service like MaxMind GeoIP) return 'US'; // Placeholder } /** * Get device type from user agent * @param string $userAgent User agent string * @return string Device type */ private function getDeviceType($userAgent) { if (preg_match('/Mobile|Android|iPhone|iPad/', $userAgent)) { return 'mobile'; } elseif (preg_match('/Tablet/', $userAgent)) { return 'tablet'; } else { return 'desktop'; } } /** * Get active users count * @return int Active users */ private function getActiveUsers() { $query = "SELECT COUNT(DISTINCT user_id) as count FROM db_video_analytics WHERE created_at >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)"; $result = $this->db->doQuery($query); $row = $this->db->doFetch($result); return (int)($row['count'] ?? 0); } /** * Get live stream count * @return int Live stream count */ private function getLiveStreamCount() { $query = "SELECT COUNT(*) as count FROM db_live_streams WHERE status = 'live'"; $result = $this->db->doQuery($query); $row = $this->db->doFetch($result); return (int)($row['count'] ?? 0); } /** * Get current viewers * @return int Current viewers */ private function getCurrentViewers() { $query = "SELECT SUM(viewer_count) as count FROM db_live_streams WHERE status = 'live'"; $result = $this->db->doQuery($query); $row = $this->db->doFetch($result); return (int)($row['count'] ?? 0); } /** * Get recent uploads count * @return int Recent uploads */ private function getRecentUploads() { $query = "SELECT COUNT(*) as count FROM db_videofiles WHERE upload_date >= DATE_SUB(NOW(), INTERVAL 1 HOUR)"; $result = $this->db->doQuery($query); $row = $this->db->doFetch($result); return (int)($row['count'] ?? 0); } /** * Get server load * @return array Server load metrics */ private function getServerLoad() { return [ 'cpu_usage' => sys_getloadavg()[0] ?? 0, 'memory_usage' => memory_get_usage(true), 'disk_usage' => disk_free_space('.') ? (disk_total_space('.') - disk_free_space('.')) / disk_total_space('.') * 100 : 0 ]; } /** * Get bandwidth usage * @return array Bandwidth metrics */ private function getBandwidthUsage() { // This would typically come from server monitoring tools return [ 'incoming' => 0, 'outgoing' => 0, 'total' => 0 ]; } }