430 lines
16 KiB
PHP
430 lines
16 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers;
|
|
|
|
use App\Core\Controller;
|
|
use App\Services\ApkService;
|
|
|
|
class AdminController extends Controller {
|
|
|
|
private function checkAuth() {
|
|
if (!isset($_SESSION['user_id']) || ($_SESSION['role'] ?? '') !== 'admin') {
|
|
$this->redirect('/admin/login');
|
|
}
|
|
}
|
|
|
|
public function loginForm() {
|
|
if (isset($_SESSION['user_id']) && ($_SESSION['role'] ?? '') === 'admin') {
|
|
$this->redirect('/admin/dashboard');
|
|
}
|
|
$this->view('admin/login');
|
|
}
|
|
|
|
public function login() {
|
|
$username = $_POST['username'] ?? '';
|
|
$password = $_POST['password'] ?? '';
|
|
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("SELECT * FROM users WHERE username = ? AND role = 'admin'");
|
|
$stmt->execute([$username]);
|
|
$user = $stmt->fetch();
|
|
|
|
if ($user && password_verify($password, $user['password'])) {
|
|
$_SESSION['user_id'] = $user['id'];
|
|
$_SESSION['username'] = $user['username'];
|
|
$_SESSION['role'] = $user['role'];
|
|
$this->redirect('/admin/dashboard');
|
|
} else {
|
|
$error = "Invalid username or password, or you are not an admin";
|
|
$this->view('admin/login', ['error' => $error]);
|
|
}
|
|
}
|
|
|
|
public function logout() {
|
|
session_destroy();
|
|
$this->redirect('/admin/login');
|
|
}
|
|
|
|
public function dashboard() {
|
|
$this->checkAuth();
|
|
$apkService = new ApkService();
|
|
$db = db_pdo();
|
|
$stats = [
|
|
'total_apks' => count($apkService->getAllApks()),
|
|
'total_downloads' => $this->getTotalDownloads(),
|
|
'total_users' => $db->query("SELECT COUNT(*) FROM users")->fetchColumn(),
|
|
'pending_withdrawals' => $db->query("SELECT COUNT(*) FROM withdrawals WHERE status = 'pending'")->fetchColumn(),
|
|
'recent_apks' => array_slice($apkService->getAllApks(), 0, 5),
|
|
'referral_stats' => $this->getReferralStats()
|
|
];
|
|
$this->view('admin/dashboard', $stats);
|
|
}
|
|
|
|
private function getReferralStats() {
|
|
$db = db_pdo();
|
|
$stmt = $db->query("SELECT DATE(created_at) as date, COUNT(*) as count FROM referral_downloads WHERE created_at > DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY DATE(created_at) ORDER BY date ASC");
|
|
return $stmt->fetchAll();
|
|
}
|
|
|
|
private function getTotalDownloads() {
|
|
$db = db_pdo();
|
|
return $db->query("SELECT SUM(total_downloads) FROM apks")->fetchColumn() ?: 0;
|
|
}
|
|
|
|
// Member Management
|
|
public function users() {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$users = $db->query("SELECT * FROM users ORDER BY created_at DESC")->fetchAll();
|
|
$this->view('admin/users/index', ['users' => $users]);
|
|
}
|
|
|
|
public function toggleBan($params) {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("UPDATE users SET is_banned = NOT is_banned WHERE id = ? AND role != 'admin'");
|
|
$stmt->execute([$params['id']]);
|
|
$this->redirect('/admin/users');
|
|
}
|
|
|
|
// APK Management
|
|
public function apks() {
|
|
$this->checkAuth();
|
|
$search = $_GET['search'] ?? null;
|
|
$apkService = new ApkService();
|
|
$apks = $apkService->getAllApks(null, $search);
|
|
$this->view('admin/apks/index', ['apks' => $apks]);
|
|
}
|
|
|
|
public function addApkForm() {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$categories = $db->query("SELECT * FROM categories")->fetchAll();
|
|
$this->view('admin/apks/form', ['action' => 'add', 'categories' => $categories]);
|
|
}
|
|
|
|
public function addApk() {
|
|
$this->checkAuth();
|
|
$title = $_POST['title'];
|
|
$slug = $this->slugify($title);
|
|
$description = $_POST['description'];
|
|
$version = $_POST['version'];
|
|
$image_url = $_POST['image_url'];
|
|
$download_url = $_POST['download_url'];
|
|
$category_id = !empty($_POST['category_id']) ? $_POST['category_id'] : null;
|
|
$status = $_POST['status'] ?? 'published';
|
|
$is_vip = isset($_POST['is_vip']) ? 1 : 0;
|
|
|
|
$icon_path = $this->handleUpload('icon_file', 'icons');
|
|
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("INSERT INTO apks (title, slug, description, version, image_url, icon_path, download_url, category_id, status, is_vip, display_order) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)");
|
|
$stmt->execute([$title, $slug, $description, $version, $image_url, $icon_path, $download_url, $category_id, $status, $is_vip]);
|
|
|
|
$this->redirect('/admin/apks');
|
|
}
|
|
|
|
public function massUploadForm() {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$categories = $db->query("SELECT * FROM categories")->fetchAll();
|
|
$this->view('admin/apks/mass_upload', ['categories' => $categories]);
|
|
}
|
|
|
|
public function massUpload() {
|
|
$this->checkAuth();
|
|
$titles = $_POST['titles'] ?? [];
|
|
$versions = $_POST['versions'] ?? [];
|
|
$download_urls = $_POST['download_urls'] ?? [];
|
|
$category_id = !empty($_POST['category_id']) ? $_POST['category_id'] : null;
|
|
$status = $_POST['status'] ?? 'published';
|
|
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("INSERT INTO apks (title, slug, description, version, icon_path, download_url, category_id, status, is_vip, display_order) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, 0)");
|
|
|
|
foreach ($titles as $index => $title) {
|
|
if (empty($title)) continue;
|
|
$slug = $this->slugify($title);
|
|
$version = $versions[$index] ?? '';
|
|
$download_url = $download_urls[$index] ?? '';
|
|
$description = $title; // Default description to title for mass upload
|
|
|
|
$icon_path = $this->handleMassUploadFile('icon_files', $index, 'icons');
|
|
|
|
$stmt->execute([$title, $slug, $description, $version, $icon_path, $download_url, $category_id, $status]);
|
|
}
|
|
|
|
$this->redirect('/admin/apks');
|
|
}
|
|
|
|
private function handleMassUploadFile($field, $index, $dir = 'icons') {
|
|
if (!isset($_FILES[$field]['name'][$index]) || $_FILES[$field]['error'][$index] !== UPLOAD_ERR_OK) {
|
|
return null;
|
|
}
|
|
|
|
$uploadDir = 'assets/uploads/' . $dir . '/';
|
|
if (!is_dir($uploadDir)) {
|
|
mkdir($uploadDir, 0775, true);
|
|
}
|
|
|
|
$ext = pathinfo($_FILES[$field]['name'][$index], PATHINFO_EXTENSION);
|
|
$fileName = uniqid() . '.' . $ext;
|
|
$targetPath = $uploadDir . $fileName;
|
|
|
|
if (compress_image($_FILES[$field]['tmp_name'][$index], $targetPath, 75)) {
|
|
return $targetPath;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function editApkForm($params) {
|
|
$this->checkAuth();
|
|
$apkService = new ApkService();
|
|
$apk = $apkService->getApkById($params['id']);
|
|
$db = db_pdo();
|
|
$categories = $db->query("SELECT * FROM categories")->fetchAll();
|
|
$this->view('admin/apks/form', ['action' => 'edit', 'apk' => $apk, 'categories' => $categories]);
|
|
}
|
|
|
|
public function editApk($params) {
|
|
$this->checkAuth();
|
|
$title = $_POST['title'];
|
|
$description = $_POST['description'];
|
|
$version = $_POST['version'];
|
|
$image_url = $_POST['image_url'];
|
|
$download_url = $_POST['download_url'];
|
|
$category_id = !empty($_POST['category_id']) ? $_POST['category_id'] : null;
|
|
$status = $_POST['status'];
|
|
$is_vip = isset($_POST['is_vip']) ? 1 : 0;
|
|
|
|
$db = db_pdo();
|
|
$apk = $db->query("SELECT * FROM apks WHERE id = " . $params['id'])->fetch();
|
|
$icon_path = $this->handleUpload('icon_file', 'icons') ?: $apk['icon_path'];
|
|
|
|
$stmt = $db->prepare("UPDATE apks SET title = ?, description = ?, version = ?, image_url = ?, icon_path = ?, download_url = ?, category_id = ?, status = ?, is_vip = ? WHERE id = ?");
|
|
$stmt->execute([$title, $description, $version, $image_url, $icon_path, $download_url, $category_id, $status, $is_vip, $params['id']]);
|
|
|
|
$this->redirect('/admin/apks');
|
|
}
|
|
|
|
public function updateOrder() {
|
|
$this->checkAuth();
|
|
$order = $_POST['order'] ?? [];
|
|
$db = db_pdo();
|
|
foreach ($order as $index => $id) {
|
|
$stmt = $db->prepare("UPDATE apks SET display_order = ? WHERE id = ?");
|
|
$stmt->execute([$index, $id]);
|
|
}
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['success' => true]);
|
|
}
|
|
|
|
private function handleUpload($field, $dir = 'icons') {
|
|
if (!isset($_FILES[$field]) || $_FILES[$field]['error'] !== UPLOAD_ERR_OK) {
|
|
return null;
|
|
}
|
|
|
|
$uploadDir = 'assets/uploads/' . $dir . '/';
|
|
if (!is_dir($uploadDir)) {
|
|
mkdir($uploadDir, 0775, true);
|
|
}
|
|
|
|
$ext = pathinfo($_FILES[$field]['name'], PATHINFO_EXTENSION);
|
|
$fileName = uniqid() . '.' . $ext;
|
|
$targetPath = $uploadDir . $fileName;
|
|
|
|
if (compress_image($_FILES[$field]['tmp_name'], $targetPath, 75)) {
|
|
return $targetPath;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// Settings Management
|
|
public function settingsForm() {
|
|
$this->checkAuth();
|
|
$settings = [
|
|
'site_name' => get_setting('site_name'),
|
|
'contact_email' => get_setting('contact_email'),
|
|
'site_icon' => get_setting('site_icon'),
|
|
'site_favicon' => get_setting('site_favicon'),
|
|
'meta_description' => get_setting('meta_description'),
|
|
'meta_keywords' => get_setting('meta_keywords'),
|
|
'head_js' => get_setting('head_js'),
|
|
'body_js' => get_setting('body_js'),
|
|
'facebook_url' => get_setting('facebook_url'),
|
|
'twitter_url' => get_setting('twitter_url'),
|
|
'instagram_url' => get_setting('instagram_url'),
|
|
'github_url' => get_setting('github_url'),
|
|
'telegram_url' => get_setting('telegram_url'),
|
|
'whatsapp_url' => get_setting('whatsapp_url'),
|
|
'maintenance_mode' => get_setting('maintenance_mode'),
|
|
];
|
|
$this->view('admin/settings', ['settings' => $settings]);
|
|
}
|
|
|
|
public function saveSettings() {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
|
|
$fields = [
|
|
'site_name', 'contact_email', 'meta_description', 'meta_keywords', 'head_js', 'body_js',
|
|
'facebook_url', 'twitter_url', 'instagram_url', 'github_url', 'telegram_url', 'whatsapp_url'
|
|
];
|
|
foreach ($fields as $field) {
|
|
if (isset($_POST[$field])) {
|
|
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = ?");
|
|
$stmt->execute([$_POST[$field], $field]);
|
|
}
|
|
}
|
|
|
|
$site_icon = $this->handleUpload('site_icon_file', 'settings');
|
|
if ($site_icon) {
|
|
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = 'site_icon'");
|
|
$stmt->execute([$site_icon]);
|
|
}
|
|
|
|
$site_favicon = $this->handleUpload('site_favicon_file', 'settings');
|
|
if ($site_favicon) {
|
|
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = 'site_favicon'");
|
|
$stmt->execute([$site_favicon]);
|
|
}
|
|
|
|
$this->redirect('/admin/settings');
|
|
}
|
|
|
|
// Blog Management
|
|
public function posts() {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$posts = $db->query("SELECT * FROM posts ORDER BY created_at DESC")->fetchAll();
|
|
$this->view('admin/posts/index', ['posts' => $posts]);
|
|
}
|
|
|
|
public function addPostForm() {
|
|
$this->checkAuth();
|
|
$this->view('admin/posts/form', ['action' => 'add']);
|
|
}
|
|
|
|
public function addPost() {
|
|
$this->checkAuth();
|
|
$title = $_POST['title'];
|
|
$slug = $this->slugify($title);
|
|
$content = $_POST['content'];
|
|
$status = $_POST['status'] ?? 'published';
|
|
|
|
$image_path = $this->handleUpload('image_file', 'blog');
|
|
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("INSERT INTO posts (title, slug, content, image_path, status) VALUES (?, ?, ?, ?, ?)");
|
|
$stmt->execute([$title, $slug, $content, $image_path, $status]);
|
|
|
|
$this->redirect('/admin/posts');
|
|
}
|
|
|
|
public function editPostForm($params) {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$post = $db->query("SELECT * FROM posts WHERE id = " . $params['id'])->fetch();
|
|
$this->view('admin/posts/form', ['action' => 'edit', 'post' => $post]);
|
|
}
|
|
|
|
public function editPost($params) {
|
|
$this->checkAuth();
|
|
$title = $_POST['title'];
|
|
$content = $_POST['content'];
|
|
$status = $_POST['status'];
|
|
|
|
$db = db_pdo();
|
|
$post = $db->query("SELECT * FROM posts WHERE id = " . $params['id'])->fetch();
|
|
$image_path = $this->handleUpload('image_file', 'blog') ?: $post['image_path'];
|
|
|
|
$stmt = $db->prepare("UPDATE posts SET title = ?, content = ?, image_path = ?, status = ? WHERE id = ?");
|
|
$stmt->execute([$title, $content, $image_path, $status, $params['id']]);
|
|
|
|
$this->redirect('/admin/posts');
|
|
}
|
|
|
|
public function deletePost($params) {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("DELETE FROM posts WHERE id = ?");
|
|
$stmt->execute([$params['id']]);
|
|
$this->redirect('/admin/posts');
|
|
}
|
|
|
|
// Category Management
|
|
public function categories() {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$categories = $db->query("SELECT * FROM categories")->fetchAll();
|
|
$this->view('admin/categories/index', ['categories' => $categories]);
|
|
}
|
|
|
|
public function addCategory() {
|
|
$this->checkAuth();
|
|
$name = $_POST['name'];
|
|
$slug = $this->slugify($name);
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("INSERT INTO categories (name, slug) VALUES (?, ?)");
|
|
$stmt->execute([$name, $slug]);
|
|
$this->redirect('/admin/categories');
|
|
}
|
|
|
|
public function deleteCategory($params) {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("DELETE FROM categories WHERE id = ?");
|
|
$stmt->execute([$params['id']]);
|
|
$this->redirect('/admin/categories');
|
|
}
|
|
|
|
// Withdrawal Management
|
|
public function withdrawals() {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$withdrawals = $db->query("SELECT w.*, u.username FROM withdrawals w JOIN users u ON w.user_id = u.id ORDER BY w.created_at DESC")->fetchAll();
|
|
$this->view('admin/withdrawals/index', ['withdrawals' => $withdrawals]);
|
|
}
|
|
|
|
public function approveWithdrawal($params) {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("UPDATE withdrawals SET status = 'approved' WHERE id = ?");
|
|
$stmt->execute([$params['id']]);
|
|
$this->redirect('/admin/withdrawals');
|
|
}
|
|
|
|
public function rejectWithdrawal($params) {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$wd = $db->query("SELECT * FROM withdrawals WHERE id = " . $params['id'])->fetch();
|
|
if ($wd && $wd['status'] === 'pending') {
|
|
$stmt = $db->prepare("UPDATE users SET balance = balance + ? WHERE id = ?");
|
|
$stmt->execute([$wd['amount'], $wd['user_id']]);
|
|
|
|
$stmt = $db->prepare("UPDATE withdrawals SET status = 'rejected' WHERE id = ?");
|
|
$stmt->execute([$params['id']]);
|
|
}
|
|
$this->redirect('/admin/withdrawals');
|
|
}
|
|
|
|
public function deleteApk($params) {
|
|
$this->checkAuth();
|
|
$db = db_pdo();
|
|
$stmt = $db->prepare("DELETE FROM apks WHERE id = ?");
|
|
$stmt->execute([$params['id']]);
|
|
$this->redirect('/admin/apks');
|
|
}
|
|
|
|
private function slugify($text) {
|
|
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
|
|
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
|
|
$text = preg_replace('~[^-\w]+~', '', $text);
|
|
$text = trim($text, '-');
|
|
$text = preg_replace('~-+~', '-', $text);
|
|
$text = strtolower($text);
|
|
return empty($text) ? 'n-a' : $text;
|
|
}
|
|
} |