34464-vm/admin.php
2025-09-28 22:38:17 +00:00

298 lines
11 KiB
PHP

<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
session_start();
// Gatekeeper: redirect if not logged in
if (!isset($_SESSION['is_admin']) || $_SESSION['is_admin'] !== true) {
header('Location: login.php');
exit;
}
require_once 'db/config.php';
$pdo = db();
// --- IMAGE SLICING FUNCTION ---
function create_puzzle_pieces($source_image_path, $puzzle_id, $pieces_count) {
if (!function_exists('gd_info')) {
// GD library not available
error_log("GD Library is not installed or enabled.");
return false;
}
$image_info = getimagesize($source_image_path);
$source_width = $image_info[0];
$source_height = $image_info[1];
$mime_type = $image_info['mime'];
switch ($mime_type) {
case 'image/jpeg':
$source_image = imagecreatefromjpeg($source_image_path);
break;
case 'image/png':
$source_image = imagecreatefrompng($source_image_path);
break;
case 'image/gif':
$source_image = imagecreatefromgif($source_image_path);
break;
default:
error_log("Unsupported image type: " . $mime_type);
return false;
}
if (!$source_image) {
error_log("Failed to create image from source.");
return false;
}
// Grid dimensions
$cols = 0;
$rows = 0;
if ($pieces_count == 16) { $cols = 4; $rows = 4; }
elseif ($pieces_count == 32) { $cols = 8; $rows = 4; }
elseif ($pieces_count == 64) { $cols = 8; $rows = 8; }
else {
error_log("Invalid pieces count: " . $pieces_count);
return false;
}
$piece_width = floor($source_width / $cols);
$piece_height = floor($source_height / $rows);
$output_dir = __DIR__ . '/puzzles/' . $puzzle_id . '/' . $pieces_count;
if (!is_dir($output_dir)) {
mkdir($output_dir, 0777, true);
}
for ($r = 0; $r < $rows; $r++) {
for ($c = 0; $c < $cols; $c++) {
$piece = imagecreatetruecolor($piece_width, $piece_height);
imagecopy(
$piece,
$source_image,
0, 0, // dest x, y
$c * $piece_width, $r * $piece_height, // source x, y
$piece_width, $piece_height
);
$piece_path = $output_dir . '/piece_' . $r . '_' . $c . '.jpg';
imagejpeg($piece, $piece_path, 90); // Save as JPG with 90% quality
imagedestroy($piece);
}
}
imagedestroy($source_image);
return true;
}
// Handle new puzzle upload
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_puzzle'])) {
$puzzle_name = trim($_POST['puzzle_name'] ?? '');
$pieces = (int)($_POST['pieces'] ?? 16);
$is_public = isset($_POST['is_public']) ? 1 : 0;
$image_file = $_FILES['puzzle_image'] ?? null;
// Basic validation
if (!empty($puzzle_name) && $image_file && $image_file['error'] === UPLOAD_ERR_OK) {
$upload_dir = __DIR__ . '/uploads/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
// Sanitize filename and create a unique name
$original_filename = basename($image_file['name']);
$image_extension = pathinfo($original_filename, PATHINFO_EXTENSION);
$safe_filename = 'puzzle_' . uniqid() . '.' . $image_extension;
$upload_path = $upload_dir . $safe_filename;
// Move the file
if (move_uploaded_file($image_file['tmp_name'], $upload_path)) {
// Insert into database
$stmt = $pdo->prepare('INSERT INTO puzzles (name, original_image, pieces, is_public, created_at) VALUES (?, ?, ?, ?, NOW())');
$stmt->execute([$puzzle_name, $safe_filename, $pieces, $is_public]);
$puzzle_id = $pdo->lastInsertId();
// Create puzzle pieces
create_puzzle_pieces($upload_path, $puzzle_id, $pieces);
header("Location: admin.php?success=1");
exit;
}
}
// Handle error case
header("Location: admin.php?error=1");
exit;
}
// Handle puzzle deletion
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_puzzle'])) {
$puzzle_id_to_delete = $_POST['puzzle_id'];
// First, get the original image filename to delete it
$stmt = $pdo->prepare('SELECT original_image FROM puzzles WHERE id = ?');
$stmt->execute([$puzzle_id_to_delete]);
$puzzle = $stmt->fetch(PDO::FETCH_ASSOC);
if ($puzzle) {
// Delete original image file
$original_image_path = __DIR__ . '/uploads/' . $puzzle['original_image'];
if (file_exists($original_image_path)) {
unlink($original_image_path);
}
}
// Delete from DB
$stmt = $pdo->prepare('DELETE FROM puzzles WHERE id = ?');
$stmt->execute([$puzzle_id_to_delete]);
// Delete puzzle pieces directory
$puzzle_dir = __DIR__ . '/puzzles/' . $puzzle_id_to_delete;
if (is_dir($puzzle_dir)) {
// A simple recursive delete function
function delete_directory($dir) {
if (!is_dir($dir)) return;
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? delete_directory("$dir/$file") : unlink("$dir/$file");
}
rmdir($dir);
}
delete_directory($puzzle_dir);
}
header("Location: admin.php?deleted=1"); // Redirect to avoid re-posting
exit;
}
$puzzles = $pdo->query('SELECT id, name, original_image, pieces, is_public, created_at FROM puzzles ORDER BY created_at DESC')->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pannello di Amministrazione</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.upload-form {
background-color: #f8f9fa;
padding: 2rem;
border-radius: 0.5rem;
margin-bottom: 2rem;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="#">Admin Puzzle</a>
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="logout.php">Logout</a>
</li>
</ul>
</div>
</nav>
<div class="container mt-5">
<?php if (isset($_GET['success'])): ?>
<div class="alert alert-success">Puzzle aggiunto con successo!</div>
<?php endif; ?>
<?php if (isset($_GET['deleted'])): ?>
<div class="alert alert-info">Puzzle eliminato con successo.</div>
<?php endif; ?>
<?php if (isset($_GET['error'])): ?>
<div class="alert alert-danger">Errore durante l'upload. Controlla i dati e riprova.</div>
<?php endif; ?>
<!-- Upload Form -->
<div class="upload-form">
<h2 class="mb-4">Aggiungi Nuovo Puzzle</h2>
<form action="admin.php" method="POST" enctype="multipart/form-data">
<div class="mb-3">
<label for="puzzle_name" class="form-label">Nome del Puzzle</label>
<input type="text" class="form-control" id="puzzle_name" name="puzzle_name" required>
</div>
<div class="mb-3">
<label for="puzzle_image" class="form-label">Immagine</label>
<input type="file" class="form-control" id="puzzle_image" name="puzzle_image" accept="image/jpeg, image/png, image/gif" required>
</div>
<div class="mb-3">
<label for="pieces" class="form-label">Numero di Pezzi</label>
<select class="form-select" id="pieces" name="pieces">
<option value="16">16 (4x4)</option>
<option value="32">32 (8x4)</option>
<option value="64">64 (8x8)</option>
</select>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="is_public" name="is_public" value="1" checked>
<label class="form-check-label" for="is_public">
Rendi Pubblico
</label>
</div>
<button type="submit" name="add_puzzle" class="btn btn-primary">Aggiungi Puzzle</button>
</form>
</div>
<h1 class="mb-4">Gestione Puzzle</h1>
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead class="table-dark">
<tr>
<th>ID</th>
<th>Nome</th>
<th>Immagine</th>
<th>Pezzi</th>
<th>Pubblico</th>
<th>Creato il</th>
<th>Azioni</th>
</tr>
</thead>
<tbody>
<?php if (empty($puzzles)): ?>
<tr>
<td colspan="7" class="text-center">Nessun puzzle trovato.</td>
</tr>
<?php else: ?>
<?php foreach ($puzzles as $puzzle):
$image_path = __DIR__ . '/uploads/' . $puzzle['original_image'];
if (file_exists($image_path)) {
// Cache busting for images
$imageUrl = 'uploads/' . htmlspecialchars($puzzle['original_image']) . '?v=' . filemtime($image_path);
} else {
$imageUrl = 'assets/images/placeholder.png'; // A placeholder if image is missing
}
?>
<tr>
<td><?php echo htmlspecialchars($puzzle['id']); ?></td>
<td><a href="puzzle.php?id=<?php echo htmlspecialchars($puzzle['id']); ?>" target="_blank"><?php echo htmlspecialchars($puzzle['name']); ?></a></td>
<td><img src="<?php echo $imageUrl; ?>" alt="Puzzle" width="100"></td>
<td><?php echo htmlspecialchars($puzzle['pieces']); ?></td>
<td><?php echo $puzzle['is_public'] ? 'Sì' : 'No'; ?></td>
<td><?php echo htmlspecialchars($puzzle['created_at']); ?></td>
<td>
<form method="POST" action="admin.php" onsubmit="return confirm('Sei sicuro di voler eliminare questo puzzle? L'azione è irreversibile.');">
<input type="hidden" name="puzzle_id" value="<?php echo htmlspecialchars($puzzle['id']); ?>">
<button type="submit" name="delete_puzzle" class="btn btn-danger btn-sm">Elimina</button>
</form>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<footer class="text-center mt-5 py-3 bg-light">
<p>&copy; <?php echo date("Y"); ?> Puzzle Game</p>
</footer>
</body>
</html>