322 lines
12 KiB
PHP
322 lines
12 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')) {
|
|
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;
|
|
|
|
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);
|
|
}
|
|
|
|
$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;
|
|
|
|
if (move_uploaded_file($image_file['tmp_name'], $upload_path)) {
|
|
$stmt = $pdo->prepare('INSERT INTO puzzles (name, original_image, file_name, pieces, is_public, created_at) VALUES (?, ?, ?, ?, ?, NOW())');
|
|
$stmt->execute([$puzzle_name, $safe_filename, $safe_filename, $pieces, $is_public]);
|
|
$puzzle_id = $pdo->lastInsertId();
|
|
|
|
create_puzzle_pieces($upload_path, $puzzle_id, $pieces);
|
|
|
|
header("Location: admin.php?success=1");
|
|
exit;
|
|
}
|
|
}
|
|
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'];
|
|
|
|
$stmt = $pdo->prepare('SELECT original_image FROM puzzles WHERE id = ?');
|
|
$stmt->execute([$puzzle_id_to_delete]);
|
|
$puzzle = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($puzzle) {
|
|
$original_image_path = __DIR__ . '/uploads/' . $puzzle['original_image'];
|
|
if (file_exists($original_image_path)) {
|
|
unlink($original_image_path);
|
|
}
|
|
}
|
|
|
|
$stmt = $pdo->prepare('DELETE FROM puzzles WHERE id = ?');
|
|
$stmt->execute([$puzzle_id_to_delete]);
|
|
|
|
$puzzle_dir = __DIR__ . '/puzzles/' . $puzzle_id_to_delete;
|
|
if (is_dir($puzzle_dir)) {
|
|
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");
|
|
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);
|
|
|
|
// Fetch users
|
|
$users = $pdo->query('SELECT id, username, email, created_at FROM users 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)) {
|
|
$imageUrl = 'uploads/' . htmlspecialchars($puzzle['original_image']) . '?v=' . filemtime($image_path);
|
|
} else {
|
|
$imageUrl = 'assets/images/placeholder.png';
|
|
}
|
|
?>
|
|
<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>
|
|
|
|
<!-- User Management Section -->
|
|
<div class="mt-5">
|
|
<h1 class="mb-4">Gestione Utenti</h1>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-bordered">
|
|
<thead class="table-dark">
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Username</th>
|
|
<th>Email</th>
|
|
<th>Registrato il</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($users)): ?>
|
|
<tr>
|
|
<td colspan="4" class="text-center">Nessun utente trovato.</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php foreach ($users as $user): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($user['id']); ?></td>
|
|
<td><?php echo htmlspecialchars($user['username']); ?></td>
|
|
<td><?php echo htmlspecialchars($user['email']); ?></td>
|
|
<td><?php echo htmlspecialchars($user['created_at']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<footer class="text-center mt-5 py-3 bg-light">
|
|
<p>© <?php echo date("Y"); ?> Puzzle Game</p>
|
|
</footer>
|
|
</body>
|
|
</html>
|