237 lines
11 KiB
PHP
237 lines
11 KiB
PHP
<?php
|
|
session_start();
|
|
require_once 'db/config.php';
|
|
|
|
// --- DATABASE SETUP ---
|
|
function setup_database() {
|
|
try {
|
|
$pdo = db();
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS puzzles (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) DEFAULT 'Senza Nome',
|
|
file_name VARCHAR(255) NOT NULL UNIQUE,
|
|
is_public BOOLEAN DEFAULT FALSE,
|
|
is_admin_upload BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)");
|
|
// Attempt to add 'name' column, ignore error if it already exists
|
|
try {
|
|
$pdo->exec("ALTER TABLE puzzles ADD COLUMN name VARCHAR(255) DEFAULT 'Senza Nome'");
|
|
} catch (PDOException $e) {
|
|
// Ignore error, likely "Duplicate column name"
|
|
}
|
|
} catch (PDOException $e) {
|
|
// In a real app, log this error instead of displaying it
|
|
die("Errore di connessione al database: " . $e->getMessage());
|
|
}
|
|
}
|
|
setup_database();
|
|
|
|
// --- GLOBAL VARIABLES ---
|
|
$uploaded_image = null;
|
|
$error_message = null;
|
|
$gallery_images = [];
|
|
|
|
// --- DATA FETCHING ---
|
|
try {
|
|
$pdo = db();
|
|
$stmt = $pdo->query("SELECT id, file_name, name FROM puzzles WHERE is_public = 1 OR is_admin_upload = 1 ORDER BY created_at DESC");
|
|
$gallery_images = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (PDOException $e) {
|
|
$error_message = "Impossibile caricare la galleria.";
|
|
}
|
|
|
|
|
|
// --- POST REQUEST: IMAGE UPLOAD ---
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['puzzle_image'])) {
|
|
$target_dir = 'uploads/';
|
|
$max_file_size = 5 * 1024 * 1024; // 5 MB
|
|
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
|
|
$file = $_FILES['puzzle_image'];
|
|
|
|
if ($file['error'] !== UPLOAD_ERR_OK) {
|
|
$error_message = 'Si è verificato un errore durante il caricamento.';
|
|
} else {
|
|
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
|
$mime_type = $finfo->file($file['tmp_name']);
|
|
|
|
if ($file['size'] > $max_file_size) {
|
|
$error_message = 'Il file è troppo grande. La dimensione massima è 5MB.';
|
|
} elseif (!in_array($mime_type, $allowed_types)) {
|
|
$error_message = 'Tipo di file non valido. Sono ammessi solo JPG, PNG, GIF.';
|
|
} else {
|
|
$file_extension = pathinfo($file['name'], PATHINFO_EXTENSION);
|
|
$safe_filename = uniqid('puzzle_', true) . '.' . strtolower($file_extension);
|
|
$target_file = $target_dir . $safe_filename;
|
|
|
|
if (move_uploaded_file($file['tmp_name'], $target_file)) {
|
|
// Save to database
|
|
try {
|
|
$is_public = isset($_POST['share_puzzle']) ? 1 : 0; // Ensure 1 or 0
|
|
$puzzle_name = !empty($_POST['puzzle_name']) ? trim($_POST['puzzle_name']) : 'Senza Nome';
|
|
$pdo = db();
|
|
$stmt = $pdo->prepare("INSERT INTO puzzles (name, file_name, is_public, is_admin_upload) VALUES (?, ?, ?, ?)");
|
|
$is_admin_upload = 0; // Always false for user uploads
|
|
$stmt->execute([$puzzle_name, $safe_filename, $is_public, $is_admin_upload]);
|
|
$new_puzzle_id = $pdo->lastInsertId();
|
|
} catch (PDOException $e) {
|
|
// Error saving to DB, delete file
|
|
unlink($target_file);
|
|
// Log the detailed error for developers: error_log($e->getMessage());
|
|
$error_message = "Si è verificato un errore nel salvataggio dei dati del puzzle: " . $e->getMessage();
|
|
}
|
|
|
|
if (!$error_message) {
|
|
// Redirect to the new puzzle page
|
|
header('Location: puzzle.php?id=' . $new_puzzle_id);
|
|
exit;
|
|
}
|
|
} else {
|
|
$error_message = 'Si è verificato un errore durante il salvataggio del file.';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- GET REQUESTS ---
|
|
// Handle New Game
|
|
if (isset($_GET['action']) && $_GET['action'] === 'new') {
|
|
unset($_SESSION['selected_puzzle']);
|
|
header('Location: ' . $_SERVER['PHP_SELF']);
|
|
exit;
|
|
}
|
|
|
|
|
|
// --- SET CURRENT IMAGE FOR DISPLAY ---
|
|
if (isset($_SESSION['selected_puzzle'])) {
|
|
$uploaded_image = $_SESSION['selected_puzzle'];
|
|
}
|
|
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="it">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Photo Puzzle</title>
|
|
<meta name="description" content="Crea e risolvi puzzle fotografici direttamente nel tuo browser. Scegli dalla nostra galleria o carica la tua immagine.">
|
|
|
|
<!-- Open Graph -->
|
|
<meta property="og:title" content="Photo Puzzle - Gioca Ora!">
|
|
<meta property="og:description" content="Un gioco di puzzle moderno dove puoi usare le tue immagini o scegliere dalla galleria.">
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:url" content=""> <!-- Add site URL here -->
|
|
<meta property="og:image" content="https://picsum.photos/1200/630?random=1">
|
|
|
|
<!-- Bootstrap CSS -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
|
|
|
<!-- Custom CSS -->
|
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
</head>
|
|
<body class="d-flex flex-column min-vh-100">
|
|
|
|
<!-- Sticky Header -->
|
|
<header class="navbar navbar-expand-lg sticky-top">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand fw-bold text-cyan" href="index.php">Photo Puzzle</a>
|
|
|
|
<div class="d-flex align-items-center ms-auto">
|
|
<div class="me-2 me-md-3">
|
|
<label for="difficulty" class="form-label visually-hidden">Difficoltà</label>
|
|
<select class="form-select form-select-sm" id="difficulty">
|
|
<option value="32">Facile</option>
|
|
<option value="48">Medio</option>
|
|
<option value="64">Difficile</option>
|
|
</select>
|
|
</div>
|
|
<a href="?action=new" class="btn btn-cyan btn-sm">Nuova Partita</a>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<main class="container-fluid my-3 my-md-4 flex-grow-1">
|
|
|
|
<!-- Gallery Section -->
|
|
<?php if (!empty($gallery_images)): ?>
|
|
<section class="mb-4" aria-labelledby="gallery-heading">
|
|
<h2 id="gallery-heading" class="h4 text-cyan">Galleria Pubblica</h2>
|
|
<div class="gallery-scroll-container d-flex gap-3 pb-3">
|
|
<?php foreach ($gallery_images as $img): ?>
|
|
<a href="puzzle.php?id=<?php echo $img['id']; ?>" class="gallery-item" title="<?php echo htmlspecialchars($img['name']); ?>">
|
|
<img src="uploads/<?php echo htmlspecialchars($img['file_name']); ?>" alt="<?php echo htmlspecialchars($img['name']); ?>" loading="lazy" class="rounded-xl">
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</section>
|
|
<?php endif; ?>
|
|
|
|
<div class="row g-3 g-md-4">
|
|
<!-- Puzzle Board -->
|
|
<section class="col-lg-8" aria-labelledby="puzzle-board-heading">
|
|
<div class="puzzle-board rounded-xl d-flex align-items-center justify-content-center p-3">
|
|
<div class="text-center w-100">
|
|
<h1 id="puzzle-board-heading" class="visually-hidden">Tavola del Puzzle</h1>
|
|
|
|
<?php if ($error_message): ?>
|
|
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($uploaded_image && file_exists($uploaded_image)): ?>
|
|
<img src="<?php echo htmlspecialchars($uploaded_image); ?>" alt="Immagine del puzzle caricata" class="img-fluid rounded-xl">
|
|
<?php else: ?>
|
|
<h2 class="h4 text-cyan">Crea un nuovo Puzzle</h2>
|
|
<p class="text-slate-400 mb-4">Carica un'immagine per iniziare.</p>
|
|
|
|
<form action="index.php" method="post" enctype="multipart/form-data" style="max-width: 500px; margin: auto;">
|
|
<div class="mb-3 text-start">
|
|
<label for="puzzle_name" class="form-label">Nome del Puzzle</label>
|
|
<input type="text" class="form-control" id="puzzle_name" name="puzzle_name" placeholder="Es: Tramonto a Venezia" required>
|
|
</div>
|
|
|
|
<div class="mb-3 text-start">
|
|
<label for="puzzle_image_upload" class="form-label">Seleziona immagine</label>
|
|
<input class="form-control" type="file" name="puzzle_image" id="puzzle_image_upload" accept="image/jpeg,image/png,image/gif" required>
|
|
</div>
|
|
|
|
<div class="form-check form-switch mb-3 text-start">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="share_puzzle" name="share_puzzle" value="1" checked>
|
|
<label class="form-check-label" for="share_puzzle">Condividi nella galleria pubblica</label>
|
|
</div>
|
|
|
|
<div class="text-center">
|
|
<button type="submit" class="btn btn-cyan">Crea Puzzle</button>
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Pieces Tray -->
|
|
<aside class="col-lg-4" aria-labelledby="pieces-tray-heading">
|
|
<div class="pieces-tray p-3">
|
|
<h2 id="pieces-tray-heading" class="h4 text-cyan mb-3">Pezzi</h2>
|
|
<div class="d-flex justify-content-center align-items-center" style="min-height: 200px;">
|
|
<p class="text-slate-400">I pezzi del puzzle appariranno qui.</p>
|
|
</div>
|
|
<!-- Pieces will be dynamically added here -->
|
|
</div>
|
|
</aside>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Footer -->
|
|
<footer class="text-center text-slate-400 py-3 mt-auto">
|
|
<small>© <?php echo date("Y"); ?> Photo Puzzle. Creato con ❤️.</small>
|
|
<small class="d-block"><a href="admin.php" class="text-slate-400">Admin</a></small>
|
|
</footer>
|
|
|
|
<!-- Bootstrap JS -->
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
|
<!-- Custom JS -->
|
|
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
|
</body>
|
|
</html>
|