Files
easystream-main/admin/includes/data_providers.php
SamiAhmed7777 0b7e2d0a5b feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory
- Added PROJECT_OVERVIEW.md with feature highlights and getting started guide
- Added ARCHITECTURE.md with system design and technical details
- Added SECURITY.md with comprehensive security implementation guide
- Added DEVELOPMENT.md with development workflows and best practices
- Added DEPLOYMENT.md with production deployment instructions
- Added API.md with complete REST API documentation
- Added CONTRIBUTING.md with contribution guidelines
- Added CHANGELOG.md with version history and migration notes
- Reorganized all documentation files into docs/ directory for better organization
- Updated README.md with proper documentation links and quick navigation
- Enhanced project structure with professional documentation standards
2025-10-21 00:39:45 -07:00

1042 lines
32 KiB
PHP

<?php
/**
* Data providers for the lightweight admin panel.
*/
declare(strict_types=1);
require_once __DIR__ . '/bootstrap.php';
function admin_fetch_user_stats(PDO $pdo): array
{
$defaults = ['total' => 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'
];
}