execute($sql); if ($result && $result->RecordCount() > 0) { self::$active_cdn = $result->FetchRow(); } } /** * Get CDN URL for file * @param string $file_path Original file path * @param string $file_type Type (video, image, audio, etc.) * @return string CDN URL or original path */ public static function getCDNUrl($file_path, $file_type = 'video') { self::init(); if (!self::$active_cdn || empty(self::$active_cdn['base_url'])) { return $file_path; // Return original if no CDN } $base_url = rtrim(self::$active_cdn['base_url'], '/'); $file_path = ltrim($file_path, '/'); return "$base_url/$file_path"; } /** * Purge cache for specific file * @param string $file_path File path to purge * @return bool Success */ public static function purgeCache($file_path) { self::init(); if (!self::$active_cdn) { return false; } $provider = self::$active_cdn['provider']; switch ($provider) { case 'cloudflare': return self::purgeCloudflare($file_path); case 'bunny': return self::purgeBunny($file_path); case 'aws': return self::purgeAWS($file_path); default: return false; } } /** * Purge Cloudflare cache */ private static function purgeCloudflare($file_path) { $zone_id = self::$active_cdn['zone_id']; $api_key = self::$active_cdn['api_key']; if (empty($zone_id) || empty($api_key)) { return false; } $url = "https://api.cloudflare.com/client/v4/zones/$zone_id/purge_cache"; $cdn_url = self::getCDNUrl($file_path); $data = json_encode(['files' => [$cdn_url]]); $ch = curl_init($url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $api_key, 'Content-Type: application/json', 'Content-Length: ' . strlen($data) ]); $result = curl_exec($ch); $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return $status_code == 200; } /** * Purge Bunny CDN cache */ private static function purgeBunny($file_path) { $api_key = self::$active_cdn['api_key']; $zone_id = self::$active_cdn['zone_id']; // Pull zone ID if (empty($api_key) || empty($zone_id)) { return false; } $cdn_url = self::getCDNUrl($file_path); $url = "https://api.bunny.net/pullzone/$zone_id/purgeCache"; $data = json_encode(['url' => $cdn_url]); $ch = curl_init($url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'AccessKey: ' . $api_key, 'Content-Type: application/json' ]); $result = curl_exec($ch); $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return $status_code == 200 || $status_code == 204; } /** * Purge AWS CloudFront cache */ private static function purgeAWS($file_path) { // AWS CloudFront invalidation would require AWS SDK // For now, return false (implement if AWS SDK available) return false; } /** * Track CDN statistics * @param string $file_key File key * @param int $bandwidth Bandwidth in MB * @param int $requests Number of requests */ public static function trackStats($file_key, $bandwidth, $requests) { self::init(); if (!self::$active_cdn) { return; } $file_key_safe = VDatabase::escape($file_key); $provider = VDatabase::escape(self::$active_cdn['provider']); $bandwidth = (float)$bandwidth; $requests = (int)$requests; $date = date('Y-m-d'); $sql = "INSERT INTO db_cdn_stats (file_key, cdn_provider, bandwidth_mb, requests, date) VALUES ('$file_key_safe', '$provider', $bandwidth, $requests, '$date') ON DUPLICATE KEY UPDATE bandwidth_mb = bandwidth_mb + $bandwidth, requests = requests + $requests"; self::$db->execute($sql); } /** * Get CDN statistics * @param string $file_key File key * @param string $date_from Start date * @param string $date_to End date * @return array Stats */ public static function getStats($file_key, $date_from, $date_to) { self::init(); $file_key_safe = VDatabase::escape($file_key); $date_from_safe = VDatabase::escape($date_from); $date_to_safe = VDatabase::escape($date_to); $sql = "SELECT cdn_provider, SUM(bandwidth_mb) as total_bandwidth, SUM(requests) as total_requests FROM db_cdn_stats WHERE file_key = '$file_key_safe' AND date BETWEEN '$date_from_safe' AND '$date_to_safe' GROUP BY cdn_provider"; $result = self::$db->execute($sql); $stats = []; if ($result) { while ($row = $result->FetchRow()) { $stats[] = $row; } } return $stats; } }