0, 'today' => 0, 'active' => 0, 'verified' => 0]; try { $stmt = $pdo->query(" SELECT COUNT(*) AS total, COUNT(CASE WHEN DATE(usr_joindate) = CURDATE() THEN 1 END) AS today, COUNT(CASE WHEN usr_active = 1 AND usr_deleted = 0 THEN 1 END) AS active, COUNT(CASE WHEN usr_verified = 1 THEN 1 END) AS verified FROM db_accountuser "); $row = $stmt->fetch() ?: []; return array_merge($defaults, [ 'total' => (int) ($row['total'] ?? 0), 'today' => (int) ($row['today'] ?? 0), 'active' => (int) ($row['active'] ?? 0), 'verified' => (int) ($row['verified'] ?? 0), ]); } catch (Throwable) { return $defaults; } } function admin_fetch_video_stats(PDO $pdo): array { $defaults = ['total' => 0, 'today' => 0, 'approved' => 0, 'pending' => 0, 'processing' => 0]; try { $stmt = $pdo->query(" SELECT COUNT(*) AS total, COUNT(CASE WHEN DATE(upload_date) = CURDATE() THEN 1 END) AS today, COUNT(CASE WHEN approved = '1' THEN 1 END) AS approved, COUNT(CASE WHEN approved = '0' THEN 1 END) AS pending, COUNT(CASE WHEN processing_status IN ('queued','processing') THEN 1 END) AS processing FROM db_videofiles WHERE deleted = '0' "); $row = $stmt->fetch() ?: []; return array_merge($defaults, [ 'total' => (int) ($row['total'] ?? 0), 'today' => (int) ($row['today'] ?? 0), 'approved' => (int) ($row['approved'] ?? 0), 'pending' => (int) ($row['pending'] ?? 0), 'processing' => (int) ($row['processing'] ?? 0), ]); } catch (Throwable) { return $defaults; } } function admin_fetch_stream_stats(PDO $pdo): array { $defaults = ['total' => 0, 'active' => 0, 'today' => 0]; try { $stmt = $pdo->query(" SELECT COUNT(*) AS total, COUNT(CASE WHEN live_status = 'live' THEN 1 END) AS active, COUNT(CASE WHEN DATE(date_created) = CURDATE() THEN 1 END) AS today FROM db_livefiles WHERE deleted = '0' "); $row = $stmt->fetch() ?: []; return array_merge($defaults, [ 'total' => (int) ($row['total'] ?? 0), 'active' => (int) ($row['active'] ?? 0), 'today' => (int) ($row['today'] ?? 0), ]); } catch (Throwable) { return $defaults; } } function admin_fetch_total_views(PDO $pdo): int { try { $stmt = $pdo->query("SELECT COALESCE(SUM(file_views), 0) AS total_views FROM db_videofiles WHERE deleted = '0'"); return (int) ($stmt->fetchColumn() ?: 0); } catch (Throwable) { return 0; } } function admin_fetch_system_health(PDO $pdo): array { $health = [ 'database' => ['status' => 'unknown', 'details' => null], 'storage' => ['status' => 'unknown', 'details' => null], ]; try { $stmt = $pdo->query("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE()"); $count = (int) $stmt->fetchColumn(); $health['database'] = [ 'status' => 'healthy', 'details' => sprintf('%d tables accessible', $count), ]; } catch (Throwable $e) { $health['database'] = [ 'status' => 'error', 'details' => $e->getMessage(), ]; } $storagePath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'f_data' . DIRECTORY_SEPARATOR . 'data_userfiles'; if (is_dir($storagePath) && is_writable($storagePath)) { $health['storage'] = [ 'status' => 'healthy', 'details' => 'Storage writable', ]; } elseif (is_dir($storagePath)) { $health['storage'] = [ 'status' => 'warning', 'details' => 'Directory exists but is not writable', ]; } else { $health['storage'] = [ 'status' => 'error', 'details' => 'Storage directory missing', ]; } return $health; } function admin_fetch_recent_activity(PDO $pdo, int $limit = 10): array { try { $stmt = $pdo->prepare(" SELECT ip_address, user_agent, timestamp, request_uri FROM db_ip_tracking ORDER BY timestamp DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_pending_videos(PDO $pdo, int $limit = 5): array { try { $stmt = $pdo->prepare(" SELECT file_key, file_title, usr_id, upload_date, processing_status FROM db_videofiles WHERE approved = '0' AND deleted = '0' ORDER BY upload_date DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_recent_users(PDO $pdo, int $limit = 15): array { try { $stmt = $pdo->prepare(" SELECT usr_id, usr_user, usr_email, usr_joindate, usr_active, usr_verified, token_balance FROM db_accountuser ORDER BY usr_joindate DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_role_distribution(PDO $pdo): array { try { $stmt = $pdo->query(" SELECT usr_role AS role, COUNT(*) AS total FROM db_accountuser GROUP BY usr_role ORDER BY total DESC "); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_user_growth(PDO $pdo, int $days = 7): array { try { $stmt = $pdo->prepare(" SELECT DATE(usr_joindate) AS date, COUNT(*) AS total FROM db_accountuser WHERE usr_joindate >= DATE_SUB(CURDATE(), INTERVAL :days DAY) GROUP BY DATE(usr_joindate) ORDER BY DATE(usr_joindate) ASC "); $stmt->bindValue(':days', $days, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_top_creators(PDO $pdo, int $limit = 10): array { try { $stmt = $pdo->prepare(" SELECT usr_id, usr_user, usr_dname, usr_v_count, token_balance, total_tokens_earned FROM db_accountuser ORDER BY usr_v_count DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_content_overview(PDO $pdo): array { $overview = [ 'videos' => admin_fetch_video_stats($pdo), 'live' => admin_fetch_stream_stats($pdo), 'shorts' => 0, 'images' => 0, 'audio' => 0, 'documents' => 0, 'blogs' => 0, ]; $tables = [ 'shorts' => 'db_shortfiles', 'images' => 'db_imagefiles', 'audio' => 'db_audiofiles', 'documents' => 'db_documentfiles', 'blogs' => 'db_blogfiles', ]; foreach ($tables as $key => $table) { try { $stmt = $pdo->query("SELECT COUNT(*) FROM {$table}"); $overview[$key] = (int) $stmt->fetchColumn(); } catch (Throwable) { $overview[$key] = 0; } } return $overview; } function admin_fetch_recent_uploads(PDO $pdo, int $limit = 10): array { try { $stmt = $pdo->prepare(" SELECT file_key, file_title, usr_id, upload_date, approved, processing_status, file_views FROM db_videofiles WHERE deleted = '0' ORDER BY upload_date DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_processing_queue(PDO $pdo, int $limit = 10): array { try { $stmt = $pdo->prepare(" SELECT file_key, file_title, usr_id, processing_status, updated_at FROM db_videofiles WHERE processing_status IN ('queued','processing') ORDER BY updated_at DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_live_stream_list(PDO $pdo, int $limit = 10): array { try { $stmt = $pdo->prepare(" SELECT stream_key, usr_id, stream_title, live_status, viewers, updated_at FROM db_livefiles ORDER BY updated_at DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_token_summary(PDO $pdo): array { $summary = [ 'total_balance' => 0, 'total_earned' => 0, 'total_spent' => 0, 'purchase_count' => 0, 'purchase_volume' => 0, 'transactions_today' => 0, ]; try { $stmt = $pdo->query(" SELECT SUM(token_balance) AS total_balance, SUM(total_tokens_earned) AS total_earned, SUM(total_tokens_spent) AS total_spent FROM db_accountuser "); $row = $stmt->fetch() ?: []; $summary['total_balance'] = (float) ($row['total_balance'] ?? 0); $summary['total_earned'] = (float) ($row['total_earned'] ?? 0); $summary['total_spent'] = (float) ($row['total_spent'] ?? 0); } catch (Throwable) { // ignore } try { $stmt = $pdo->query(" SELECT COUNT(*) AS purchase_count, SUM(usd_amount) AS purchase_volume FROM token_purchases WHERE status = 'completed' "); $row = $stmt->fetch() ?: []; $summary['purchase_count'] = (int) ($row['purchase_count'] ?? 0); $summary['purchase_volume'] = (float) ($row['purchase_volume'] ?? 0); } catch (Throwable) { // ignore } try { $stmt = $pdo->query(" SELECT COUNT(*) FROM token_transactions WHERE DATE(created_at) = CURDATE() "); $summary['transactions_today'] = (int) ($stmt->fetchColumn() ?: 0); } catch (Throwable) { // ignore } return $summary; } function admin_fetch_top_token_users(PDO $pdo, int $limit = 10): array { try { $stmt = $pdo->prepare("SELECT * FROM token_user_summary ORDER BY total_tokens_earned DESC LIMIT :limit"); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { // Fallback if view not available try { $stmt = $pdo->prepare(" SELECT usr_id AS user_id, usr_user AS username, token_balance, total_tokens_earned, total_tokens_spent FROM db_accountuser ORDER BY token_balance DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } } function admin_fetch_token_daily_stats(PDO $pdo, int $limit = 14): array { try { $stmt = $pdo->prepare("SELECT * FROM token_daily_stats ORDER BY date DESC LIMIT :limit"); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { try { $stmt = $pdo->prepare(" SELECT DATE(created_at) AS date, COUNT(*) AS total_transactions, SUM(amount) AS tokens_purchased FROM token_transactions WHERE status = 'completed' GROUP BY DATE(created_at) ORDER BY DATE(created_at) DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } } function admin_fetch_recent_token_activity(PDO $pdo, int $limit = 12): array { try { $stmt = $pdo->prepare(" SELECT id, user_id, amount, transaction_type, status, created_at FROM token_transactions ORDER BY created_at DESC LIMIT :limit "); $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Throwable) { return []; } } function admin_fetch_token_packages(PDO $pdo): array { try { $stmt = $pdo->prepare(" SELECT cfg_name, cfg_data FROM db_settings WHERE cfg_name LIKE 'token_package_%' ORDER BY cfg_name ASC "); $stmt->execute(); $packages = []; foreach ($stmt->fetchAll() as $row) { $decoded = json_decode($row['cfg_data'], true); if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) { $packages[] = array_merge(['key' => $row['cfg_name']], $decoded); } } return $packages; } catch (Throwable) { return []; } } function admin_get_token_settings(PDO $pdo): array { $defaults = [ 'name' => 'EasyCoins', 'symbol' => 'EC', 'plural' => 'EasyCoins', 'description' => 'Platform currency for tips and donations', 'icon' => '/f_templates/tpl_frontend/img/default-token.png', 'color_primary' => '#FFD700', 'color_secondary' => '#FFA500', ]; try { $stmt = $pdo->query("SELECT cfg_name, cfg_data FROM db_settings WHERE cfg_name LIKE 'token_%'"); $settings = $defaults; foreach ($stmt->fetchAll() as $row) { $key = str_replace('token_', '', $row['cfg_name']); if (array_key_exists($key, $defaults)) { $settings[$key] = $row['cfg_data']; } } return $settings; } catch (Throwable) { return $defaults; } } function admin_update_token_settings(PDO $pdo, array $settings): void { $stmt = $pdo->prepare(" INSERT INTO db_settings (cfg_name, cfg_data, cfg_info) VALUES (:name, :value, :info) ON DUPLICATE KEY UPDATE cfg_data = :value, cfg_info = :info "); foreach ($settings as $key => $value) { $cfgName = str_starts_with($key, 'token_') ? $key : "token_{$key}"; $info = ucfirst(str_replace('_', ' ', str_replace('token_', '', $cfgName))); $stmt->execute([ ':name' => $cfgName, ':value' => $value, ':info' => $info, ]); } } function admin_handle_token_icon_upload(PDO $pdo, array $file): array { if (!isset($file['tmp_name']) || $file['error'] !== UPLOAD_ERR_OK) { return ['success' => false, 'message' => 'No file uploaded or upload error']; } $allowedMime = [ 'image/png' => 'png', 'image/jpeg' => 'jpg', 'image/gif' => 'gif', 'image/svg+xml' => 'svg', ]; $mime = $file['type'] ?? ''; if (!isset($allowedMime[$mime])) { return ['success' => false, 'message' => 'Invalid file type. Allowed: PNG, JPG, GIF, SVG']; } if (($file['size'] ?? 0) > 2 * 1024 * 1024) { return ['success' => false, 'message' => 'File too large. Maximum size is 2MB']; } $extension = $allowedMime[$mime]; $uploadDir = dirname(__DIR__, 2) . '/f_templates/tpl_frontend/img/tokens/'; if (!is_dir($uploadDir) && !mkdir($uploadDir, 0755, true) && !is_dir($uploadDir)) { return ['success' => false, 'message' => 'Failed to create upload directory']; } $filename = 'token_icon_' . time() . '_' . bin2hex(random_bytes(4)) . '.' . $extension; $destination = $uploadDir . $filename; if (!move_uploaded_file($file['tmp_name'], $destination)) { return ['success' => false, 'message' => 'Failed to store uploaded file']; } $publicPath = '/f_templates/tpl_frontend/img/tokens/' . $filename; admin_update_token_settings($pdo, ['icon' => $publicPath]); return ['success' => true, 'message' => 'Token icon uploaded successfully', 'path' => $publicPath]; } function admin_fetch_all_roles(PDO $pdo): array { try { $stmt = $pdo->query(" SELECT role_name, display_name, description, status FROM db_roles ORDER BY display_name ASC "); return $stmt->fetchAll() ?: []; } catch (Throwable) { return []; } } function admin_prepare_user_filters(array $filters, array &$params): array { $wheres = ['u.usr_deleted = 0']; if (!empty($filters['q'])) { $params['search'] = '%' . $filters['q'] . '%'; $wheres[] = '(u.usr_user LIKE :search OR u.usr_email LIKE :search)'; } if (!empty($filters['status'])) { if ($filters['status'] === 'active') { $wheres[] = 'u.usr_active = 1'; } elseif ($filters['status'] === 'inactive') { $wheres[] = 'u.usr_active = 0'; } } if (!empty($filters['verified'])) { if ($filters['verified'] === 'yes') { $wheres[] = 'u.usr_verified = 1'; } elseif ($filters['verified'] === 'no') { $wheres[] = 'u.usr_verified = 0'; } } if (!empty($filters['streaming'])) { if ($filters['streaming'] === 'enabled') { $wheres[] = 'u.streaming_enabled = 1'; } elseif ($filters['streaming'] === 'disabled') { $wheres[] = '(u.streaming_enabled IS NULL OR u.streaming_enabled = 0)'; } } if (!empty($filters['role'])) { $params['filter_role'] = $filters['role']; $wheres[] = "EXISTS ( SELECT 1 FROM db_user_roles ur WHERE ur.user_id = u.usr_id AND ur.role_name = :filter_role AND ur.status = 'active' )"; } return $wheres; } function admin_search_users(PDO $pdo, array $filters, int $limit = 25, int $offset = 0): array { $params = []; $wheres = admin_prepare_user_filters($filters, $params); $sql = " SELECT u.usr_id, u.usr_user, u.usr_email, u.usr_joindate, u.usr_lastlogin, u.usr_active, u.usr_verified, u.streaming_enabled, u.live_key, u.stream_key_regenerated_at, u.usr_tokencount, u.usr_logins, COALESCE(active_streams.active_count, 0) AS active_streams, COALESCE(total_streams.total_count, 0) AS total_streams, GROUP_CONCAT(DISTINCT roles.role_name ORDER BY roles.role_name SEPARATOR ',') AS roles FROM db_accountuser u LEFT JOIN db_user_roles roles ON roles.user_id = u.usr_id AND roles.status = 'active' LEFT JOIN ( SELECT user_id, COUNT(*) AS active_count FROM db_live_streams WHERE status = 'live' GROUP BY user_id ) active_streams ON active_streams.user_id = u.usr_id LEFT JOIN ( SELECT user_id, COUNT(*) AS total_count FROM db_live_streams GROUP BY user_id ) total_streams ON total_streams.user_id = u.usr_id "; if (!empty($wheres)) { $sql .= ' WHERE ' . implode(' AND ', $wheres); } $sql .= ' GROUP BY u.usr_id ORDER BY u.usr_joindate DESC LIMIT :limit OFFSET :offset '; try { $stmt = $pdo->prepare($sql); foreach ($params as $key => $value) { $stmt->bindValue(':' . $key, $value); } $stmt->bindValue(':limit', max(1, $limit), PDO::PARAM_INT); $stmt->bindValue(':offset', max(0, $offset), PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll() ?: []; } catch (Throwable) { return []; } } function admin_count_users(PDO $pdo, array $filters): int { $params = []; $wheres = admin_prepare_user_filters($filters, $params); $sql = ' SELECT COUNT(DISTINCT u.usr_id) FROM db_accountuser u '; if (!empty($wheres)) { $sql .= ' WHERE ' . implode(' AND ', $wheres); } try { $stmt = $pdo->prepare($sql); foreach ($params as $key => $value) { $stmt->bindValue(':' . $key, $value); } $stmt->execute(); return (int) ($stmt->fetchColumn() ?: 0); } catch (Throwable) { return 0; } } function admin_set_user_active(PDO $pdo, int $userId, bool $active): bool { try { $stmt = $pdo->prepare(" UPDATE db_accountuser SET usr_active = :active WHERE usr_id = :user_id LIMIT 1 "); $stmt->bindValue(':active', $active ? 1 : 0, PDO::PARAM_INT); $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT); $stmt->execute(); return $stmt->rowCount() > 0; } catch (Throwable) { return false; } } function admin_get_user_roles(PDO $pdo, int $userId): array { try { $stmt = $pdo->prepare(" SELECT role_name FROM db_user_roles WHERE user_id = :user_id AND status = 'active' ORDER BY role_name ASC "); $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT); $stmt->execute(); return array_column($stmt->fetchAll(), 'role_name'); } catch (Throwable) { return []; } } function admin_user_exists(PDO $pdo, int $userId): bool { try { $stmt = $pdo->prepare("SELECT 1 FROM db_accountuser WHERE usr_id = :user_id LIMIT 1"); $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT); $stmt->execute(); return (bool) $stmt->fetchColumn(); } catch (Throwable) { return false; } } // ============================================================================ // SETTINGS MANAGEMENT DATA PROVIDERS // ============================================================================ /** * Fetch all settings grouped by category * @param PDO $pdo Database connection * @return array Settings grouped by category */ function admin_fetch_all_settings(PDO $pdo): array { $defaults = [ 'general' => [], 'modules' => [], 'branding' => [], 'payment' => [], 'email' => [], 'token' => [], 'security' => [], 'seo' => [], 'social' => [], 'other' => [] ]; try { $stmt = $pdo->query("SELECT cfg_name, cfg_data, cfg_info FROM db_settings ORDER BY cfg_name"); $settings = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($settings as $setting) { $key = $setting['cfg_name']; $category = 'other'; // Categorize settings based on prefix if (strpos($key, 'backend_') === 0) { $category = 'general'; } elseif (strpos($key, 'mail_') === 0) { $category = 'email'; } elseif (strpos($key, 'paypal_') === 0 || strpos($key, 'stripe_') === 0 || strpos($key, 'payment_') === 0) { $category = 'payment'; } elseif (strpos($key, 'token_') === 0) { $category = 'token'; } elseif (strpos($key, 'branding_') === 0 || strpos($key, 'color_') === 0 || strpos($key, 'logo_') === 0 || $key === 'website_shortname' || $key === 'head_title') { $category = 'branding'; } elseif (strpos($key, 'signup_') === 0 || strpos($key, 'login_') === 0 || strpos($key, 'username_') === 0) { $category = 'security'; } elseif (strpos($key, 'head_') === 0 || strpos($key, 'metaname_') === 0) { $category = 'seo'; } elseif (strpos($key, '_module') !== false || $key === 'paid_memberships') { $category = 'modules'; } elseif (strpos($key, 'fb_') === 0 || strpos($key, 'google_') === 0 || strpos($key, 'twitter_') === 0) { $category = 'social'; } $defaults[$category][] = [ 'name' => $key, 'value' => $setting['cfg_data'], 'info' => $setting['cfg_info'] ]; } return $defaults; } catch (Throwable $e) { error_log("Error fetching settings: " . $e->getMessage()); return $defaults; } } /** * Get a specific setting value * @param PDO $pdo Database connection * @param string $key Setting name * @return string|null Setting value or null */ function admin_get_setting(PDO $pdo, string $key): ?string { try { $stmt = $pdo->prepare("SELECT cfg_data FROM db_settings WHERE cfg_name = :key LIMIT 1"); $stmt->bindValue(':key', $key, PDO::PARAM_STR); $stmt->execute(); $result = $stmt->fetchColumn(); return $result !== false ? (string)$result : null; } catch (Throwable $e) { error_log("Error getting setting: " . $e->getMessage()); return null; } } /** * Update or insert a setting * @param PDO $pdo Database connection * @param string $key Setting name * @param string $value Setting value * @param string $info Setting description * @return bool Success status */ function admin_save_setting(PDO $pdo, string $key, string $value, string $info = ''): bool { try { // Check if exists $stmt = $pdo->prepare("SELECT id FROM db_settings WHERE cfg_name = :key LIMIT 1"); $stmt->bindValue(':key', $key, PDO::PARAM_STR); $stmt->execute(); $exists = $stmt->fetchColumn(); if ($exists) { // Update existing $stmt = $pdo->prepare("UPDATE db_settings SET cfg_data = :value, cfg_info = :info WHERE cfg_name = :key"); } else { // Insert new $stmt = $pdo->prepare("INSERT INTO db_settings (cfg_name, cfg_data, cfg_info) VALUES (:key, :value, :info)"); } $stmt->bindValue(':key', $key, PDO::PARAM_STR); $stmt->bindValue(':value', $value, PDO::PARAM_STR); $stmt->bindValue(':info', $info, PDO::PARAM_STR); return $stmt->execute(); } catch (Throwable $e) { error_log("Error saving setting: " . $e->getMessage()); return false; } } /** * Save multiple settings at once * @param PDO $pdo Database connection * @param array $settings Array of ['key' => 'value'] pairs * @return bool Success status */ function admin_save_multiple_settings(PDO $pdo, array $settings): bool { try { $pdo->beginTransaction(); foreach ($settings as $key => $value) { admin_save_setting($pdo, $key, (string)$value); } $pdo->commit(); return true; } catch (Throwable $e) { $pdo->rollBack(); error_log("Error saving multiple settings: " . $e->getMessage()); return false; } } /** * Delete a setting * @param PDO $pdo Database connection * @param string $key Setting name * @return bool Success status */ function admin_delete_setting(PDO $pdo, string $key): bool { try { $stmt = $pdo->prepare("DELETE FROM db_settings WHERE cfg_name = :key"); $stmt->bindValue(':key', $key, PDO::PARAM_STR); return $stmt->execute(); } catch (Throwable $e) { error_log("Error deleting setting: " . $e->getMessage()); return false; } } /** * Get module status * @param PDO $pdo Database connection * @return array Module enabled/disabled status */ function admin_fetch_module_status(PDO $pdo): array { $modules = [ 'video_module' => 'Videos', 'live_module' => 'Live Streaming', 'short_module' => 'Shorts', 'image_module' => 'Images', 'audio_module' => 'Audio', 'document_module' => 'Documents', 'blog_module' => 'Blogs', 'paid_memberships' => 'Paid Memberships', 'token_system_enabled' => 'Token Economy' ]; $result = []; foreach ($modules as $key => $label) { $value = admin_get_setting($pdo, $key); $result[] = [ 'key' => $key, 'label' => $label, 'enabled' => $value === '1' ]; } return $result; } /** * Toggle module status * @param PDO $pdo Database connection * @param string $module Module key * @param bool $enabled New status * @return bool Success status */ function admin_toggle_module(PDO $pdo, string $module, bool $enabled): bool { return admin_save_setting($pdo, $module, $enabled ? '1' : '0'); } /** * Get branding settings * @param PDO $pdo Database connection * @return array Branding configuration */ function admin_fetch_branding_settings(PDO $pdo): array { return [ 'site_name' => admin_get_setting($pdo, 'website_shortname') ?? 'EasyStream', 'site_title' => admin_get_setting($pdo, 'head_title') ?? 'EasyStream', 'primary_color' => admin_get_setting($pdo, 'branding_primary_color') ?? '#1a73e8', 'secondary_color' => admin_get_setting($pdo, 'branding_secondary_color') ?? '#34a853', 'logo_url' => admin_get_setting($pdo, 'branding_logo_url') ?? '', 'favicon_url' => admin_get_setting($pdo, 'branding_favicon_url') ?? '', 'footer_text' => admin_get_setting($pdo, 'branding_footer_text') ?? '' ]; } /** * Get payment gateway settings * @param PDO $pdo Database connection * @return array Payment configuration */ function admin_fetch_payment_settings(PDO $pdo): array { return [ 'payment_methods' => admin_get_setting($pdo, 'payment_methods') ?? 'Paypal', 'paypal_email' => admin_get_setting($pdo, 'paypal_email') ?? '', 'paypal_test' => admin_get_setting($pdo, 'paypal_test') === '1', 'paypal_client_id' => admin_get_setting($pdo, 'paypal_client_id') ?? '', 'paypal_secret' => admin_get_setting($pdo, 'paypal_secret') ?? '', 'stripe_enabled' => admin_get_setting($pdo, 'stripe_enabled') === '1', 'stripe_publishable_key' => admin_get_setting($pdo, 'stripe_publishable_key') ?? '', 'stripe_secret_key' => admin_get_setting($pdo, 'stripe_secret_key') ?? '', 'stripe_webhook_secret' => admin_get_setting($pdo, 'stripe_webhook_secret') ?? '' ]; } /** * Get email/SMTP settings * @param PDO $pdo Database connection * @return array Email configuration */ function admin_fetch_email_settings(PDO $pdo): array { return [ 'mail_type' => admin_get_setting($pdo, 'mail_type') ?? 'smtp', 'backend_email' => admin_get_setting($pdo, 'backend_email') ?? '', 'backend_email_fromname' => admin_get_setting($pdo, 'backend_email_fromname') ?? 'Webmaster', 'mail_smtp_host' => admin_get_setting($pdo, 'mail_smtp_host') ?? 'smtp.gmail.com', 'mail_smtp_port' => admin_get_setting($pdo, 'mail_smtp_port') ?? '587', 'mail_smtp_username' => admin_get_setting($pdo, 'mail_smtp_username') ?? '', 'mail_smtp_password' => admin_get_setting($pdo, 'mail_smtp_password') ?? '', 'mail_smtp_auth' => admin_get_setting($pdo, 'mail_smtp_auth') === 'true', 'mail_smtp_prefix' => admin_get_setting($pdo, 'mail_smtp_prefix') ?? 'tls' ]; } /** * Get creator payout settings * @param PDO $pdo Database connection * @return array Payout configuration */ function admin_fetch_payout_settings(PDO $pdo): array { return [ 'creator_payout_enabled' => admin_get_setting($pdo, 'creator_payout_enabled') === '1', 'creator_payout_percentage' => (int)(admin_get_setting($pdo, 'creator_payout_percentage') ?? '70'), 'minimum_payout_amount' => (float)(admin_get_setting($pdo, 'minimum_payout_amount') ?? '50.00'), 'payout_schedule' => admin_get_setting($pdo, 'payout_schedule') ?? 'monthly', 'payout_method' => admin_get_setting($pdo, 'payout_method') ?? 'paypal' ]; }