Update admin.php

This commit is contained in:
deepend-tildeclub 2025-01-24 19:01:35 -07:00 committed by GitHub
parent 0f0dea9069
commit ae5b9fc4f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 340 additions and 154 deletions

View File

@ -1,161 +1,347 @@
<?php
header('Content-Type: application/json');
require_once 'db.php';
session_start();
require_once 'db.php'; // Ensure the database and $db PDO instance are available
// Quick helper to send JSON responses and exit
function sendJson($data, $statusCode = 200) {
http_response_code($statusCode);
echo json_encode($data);
// ------------------------------
// Utility Function: Check if admin is logged in
// ------------------------------
function isAdminLoggedIn()
{
return isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true;
}
// ------------------------------
// Handle Admin Login
// ------------------------------
if (isset($_POST['login'])) {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
// Prepare a query to fetch the user
$stmt = $db->prepare("SELECT * FROM users WHERE username = :username LIMIT 1");
$stmt->bindValue(':username', $username, PDO::PARAM_STR);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
// Successful login
$_SESSION['admin_logged_in'] = true;
header('Location: admin.php');
exit;
} else {
$error = "Invalid credentials. Please try again.";
}
}
// ------------------------------
// Handle Admin Logout
// ------------------------------
if (isset($_GET['action']) && $_GET['action'] === 'logout') {
session_destroy();
header('Location: admin.php');
exit;
}
$action = $_GET['action'] ?? ($_POST['action'] ?? null);
// ------------------------------
// Handle Creating a New Poll
// ------------------------------
if (isset($_POST['create_poll']) && isAdminLoggedIn()) {
$questionText = trim($_POST['question_text'] ?? '');
switch ($action) {
// --------------------------------------------------
// 1) List all polls (IDs + questions)
// --------------------------------------------------
case 'list_polls':
try {
$stmt = $db->query("SELECT id, question_text FROM poll_questions ORDER BY id DESC");
$polls = $stmt->fetchAll(PDO::FETCH_ASSOC);
sendJson(['success' => true, 'polls' => $polls]);
} catch (Exception $e) {
sendJson(['success' => false, 'error' => $e->getMessage()], 500);
}
break;
// --------------------------------------------------
// 2) Get a single poll (question + options)
// --------------------------------------------------
case 'get_poll':
$pollId = (int)($_GET['poll_id'] ?? 0);
if ($pollId <= 0) {
sendJson(['success' => false, 'error' => 'Invalid poll_id'], 400);
}
try {
// Fetch poll question
$stmt = $db->prepare("SELECT id, question_text FROM poll_questions WHERE id = :id");
$stmt->execute([':id' => $pollId]);
$poll = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$poll) {
sendJson(['success' => false, 'error' => 'Poll not found'], 404);
}
// Fetch options
$optionsStmt = $db->prepare("
SELECT po.id AS option_id, po.option_text,
IFNULL(pr.vote_count, 0) AS vote_count
FROM poll_options po
LEFT JOIN poll_results pr ON po.id = pr.option_id
WHERE po.question_id = :question_id
ORDER BY po.id ASC
");
$optionsStmt->execute([':question_id' => $pollId]);
$options = $optionsStmt->fetchAll(PDO::FETCH_ASSOC);
sendJson([
'success' => true,
'poll' => [
'id' => $poll['id'],
'question_text' => $poll['question_text'],
'options' => $options
]
]);
} catch (Exception $e) {
sendJson(['success' => false, 'error' => $e->getMessage()], 500);
}
break;
// --------------------------------------------------
// 3) Cast a vote
// Expects: poll_id, option_id, username
// --------------------------------------------------
case 'vote':
// This can come from POST or GET. We'll assume POST for clarity.
$pollId = (int)($_POST['poll_id'] ?? 0);
$optionId = (int)($_POST['option_id'] ?? 0);
$username = trim($_POST['username'] ?? '');
if ($pollId <= 0 || $optionId <= 0 || empty($username)) {
sendJson(['success' => false, 'error' => 'Missing or invalid parameters'], 400);
}
// Check if user already voted on this poll
try {
// 1) Ensure poll & option exist
$checkOption = $db->prepare("
SELECT COUNT(*)
FROM poll_options
WHERE id = :option_id
AND question_id = :poll_id
");
$checkOption->execute([
':option_id' => $optionId,
':poll_id' => $pollId
]);
if (!$checkOption->fetchColumn()) {
sendJson(['success' => false, 'error' => 'Option does not belong to poll or does not exist'], 400);
}
// 2) Check if user already voted
$checkVote = $db->prepare("
SELECT COUNT(*)
FROM user_votes
WHERE question_id = :poll_id
AND user_name = :username
");
$checkVote->execute([
':poll_id' => $pollId,
':username' => $username
]);
if ($checkVote->fetchColumn() > 0) {
// Already voted
sendJson(['success' => false, 'error' => 'Already voted'], 403);
}
// 3) Cast the vote (increment poll_results)
$updateStmt = $db->prepare("
UPDATE poll_results
SET vote_count = vote_count + 1
WHERE question_id = :poll_id
AND option_id = :option_id
");
$updateStmt->execute([
':poll_id' => $pollId,
':option_id' => $optionId
]);
// 4) Record the user vote
// Ensure user_votes table is created:
// CREATE TABLE IF NOT EXISTS user_votes (
// id INTEGER PRIMARY KEY AUTOINCREMENT,
// question_id INTEGER NOT NULL,
// option_id INTEGER NOT NULL,
// user_name TEXT NOT NULL,
// voted_at DATETIME DEFAULT CURRENT_TIMESTAMP
// );
$insertVote = $db->prepare("
INSERT INTO user_votes (question_id, option_id, user_name)
VALUES (:poll_id, :option_id, :username)
");
$insertVote->execute([
':poll_id' => $pollId,
':option_id' => $optionId,
':username' => $username
]);
sendJson(['success' => true, 'message' => 'Vote cast successfully']);
} catch (Exception $e) {
sendJson(['success' => false, 'error' => $e->getMessage()], 500);
}
break;
// --------------------------------------------------
// 4) Unknown / default
// --------------------------------------------------
default:
sendJson(['success' => false, 'error' => 'Unknown action'], 400);
break;
if (!empty($questionText)) {
$stmt = $db->prepare("INSERT INTO poll_questions (question_text) VALUES (:question_text)");
$stmt->bindValue(':question_text', $questionText, PDO::PARAM_STR);
$stmt->execute();
$successMsg = "Poll question created successfully!";
} else {
$errorMsg = "Please enter a question text.";
}
}
// ------------------------------
// Handle Adding Options to an Existing Poll
// ------------------------------
if (isset($_POST['add_option']) && isAdminLoggedIn()) {
$questionId = (int)($_POST['poll_id'] ?? 0);
$optionText = trim($_POST['option_text'] ?? '');
if ($questionId > 0 && !empty($optionText)) {
// Check if poll question exists
$stmt = $db->prepare("SELECT id FROM poll_questions WHERE id = :id");
$stmt->bindValue(':id', $questionId, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->fetchColumn()) {
// Insert the new option
$insertOption = $db->prepare("
INSERT INTO poll_options (question_id, option_text)
VALUES (:question_id, :option_text)
");
$insertOption->bindValue(':question_id', $questionId, PDO::PARAM_INT);
$insertOption->bindValue(':option_text', $optionText, PDO::PARAM_STR);
$insertOption->execute();
// Also initialize poll_results with a 0 vote count for the new option
$optionId = $db->lastInsertId();
$insertResult = $db->prepare("
INSERT INTO poll_results (question_id, option_id, vote_count)
VALUES (:question_id, :option_id, 0)
");
$insertResult->bindValue(':question_id', $questionId, PDO::PARAM_INT);
$insertResult->bindValue(':option_id', $optionId, PDO::PARAM_INT);
$insertResult->execute();
$successMsg = "Option added successfully!";
} else {
$errorMsg = "Poll question does not exist.";
}
} else {
$errorMsg = "Please select a poll and enter an option text.";
}
}
// ------------------------------
// Handle Editing an Existing Poll
// ------------------------------
if (isset($_POST['edit_poll']) && isAdminLoggedIn()) {
$pollId = (int)($_POST['poll_id'] ?? 0);
$newQuestionText = trim($_POST['edit_question_text'] ?? '');
if ($pollId > 0 && !empty($newQuestionText)) {
// Check if poll question exists
$checkStmt = $db->prepare("SELECT id FROM poll_questions WHERE id = :id");
$checkStmt->bindValue(':id', $pollId, PDO::PARAM_INT);
$checkStmt->execute();
if ($checkStmt->fetchColumn()) {
// Update the poll question
$updateStmt = $db->prepare("
UPDATE poll_questions
SET question_text = :question_text
WHERE id = :id
");
$updateStmt->bindValue(':question_text', $newQuestionText, PDO::PARAM_STR);
$updateStmt->bindValue(':id', $pollId, PDO::PARAM_INT);
$updateStmt->execute();
$successMsg = "Poll question updated successfully!";
} else {
$errorMsg = "Poll question does not exist.";
}
} else {
$errorMsg = "Invalid poll ID or question text.";
}
}
// ------------------------------
// Handle Deleting an Existing Poll
// ------------------------------
if (isset($_POST['delete_poll']) && isAdminLoggedIn()) {
$pollId = (int)($_POST['poll_id'] ?? 0);
if ($pollId > 0) {
// Check if poll question exists
$checkStmt = $db->prepare("SELECT id FROM poll_questions WHERE id = :id");
$checkStmt->bindValue(':id', $pollId, PDO::PARAM_INT);
$checkStmt->execute();
if ($checkStmt->fetchColumn()) {
// Delete poll_results
$deleteResults = $db->prepare("DELETE FROM poll_results WHERE question_id = :id");
$deleteResults->bindValue(':id', $pollId, PDO::PARAM_INT);
$deleteResults->execute();
// Delete poll_options
$deleteOptions = $db->prepare("DELETE FROM poll_options WHERE question_id = :id");
$deleteOptions->bindValue(':id', $pollId, PDO::PARAM_INT);
$deleteOptions->execute();
// Finally, delete the poll question
$deletePoll = $db->prepare("DELETE FROM poll_questions WHERE id = :id");
$deletePoll->bindValue(':id', $pollId, PDO::PARAM_INT);
$deletePoll->execute();
$successMsg = "Poll deleted successfully!";
} else {
$errorMsg = "Poll question does not exist.";
}
} else {
$errorMsg = "Invalid poll ID.";
}
}
// ------------------------------
// Fetch All Polls for Display
// ------------------------------
$polls = [];
if (isAdminLoggedIn()) {
$pollsQuery = $db->query("SELECT id, question_text, created_at FROM poll_questions ORDER BY id DESC");
$polls = $pollsQuery->fetchAll(PDO::FETCH_ASSOC);
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Poll Admin</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.login-box, .admin-content { max-width: 600px; margin: 0 auto; }
.error { color: red; }
.success { color: green; }
h2 { border-bottom: 1px solid #ccc; }
form { margin-bottom: 20px; }
label { display: inline-block; width: 100px; }
input[type=text], input[type=password] { width: 200px; }
.poll-item { border: 1px solid #ccc; padding: 10px; margin-bottom: 20px; }
.poll-options { margin-top: 10px; }
.option-result { margin-left: 20px; }
.inline-form { display: inline-block; margin-right: 10px; }
</style>
</head>
<body>
<?php if (!isAdminLoggedIn()): ?>
<div class="login-box">
<h2>Admin Login</h2>
<?php if (!empty($error)): ?>
<div class="error"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>
<form method="post" action="admin.php">
<div>
<label for="username">Username:</label>
<input type="text" name="username" id="username" required />
</div>
<div>
<label for="password">Password:</label>
<input type="password" name="password" id="password" required />
</div>
<div>
<button type="submit" name="login">Login</button>
</div>
</form>
</div>
<?php else: ?>
<div class="admin-content">
<h2>Poll Administration</h2>
<p>
<a href="admin.php?action=logout">Logout</a>
</p>
<!-- Display success or error messages -->
<?php if (!empty($successMsg)): ?>
<div class="success"><?php echo htmlspecialchars($successMsg); ?></div>
<?php endif; ?>
<?php if (!empty($errorMsg)): ?>
<div class="error"><?php echo htmlspecialchars($errorMsg); ?></div>
<?php endif; ?>
<!-- Section: Create a New Poll -->
<h3>Create a New Poll</h3>
<form method="post" action="admin.php">
<div>
<label for="question_text">Question:</label>
<input type="text" name="question_text" id="question_text" required>
</div>
<div>
<button type="submit" name="create_poll">Create Poll</button>
</div>
</form>
<!-- Section: Add Options to Existing Poll -->
<h3>Add Options to a Poll</h3>
<?php if (count($polls) > 0): ?>
<form method="post" action="admin.php">
<div>
<label for="poll_id">Select Poll:</label>
<select name="poll_id" id="poll_id">
<?php foreach ($polls as $poll): ?>
<option value="<?php echo $poll['id']; ?>">
<?php echo htmlspecialchars($poll['question_text']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="option_text">Option:</label>
<input type="text" name="option_text" id="option_text" required>
</div>
<div>
<button type="submit" name="add_option">Add Option</button>
</div>
</form>
<?php else: ?>
<p>No polls available. Create a new poll first.</p>
<?php endif; ?>
<!-- Section: Existing Polls & Results -->
<h3>Existing Polls & Results</h3>
<?php if (count($polls) > 0): ?>
<?php foreach ($polls as $poll): ?>
<div class="poll-item">
<strong>Question:</strong>
<?php echo htmlspecialchars($poll['question_text']); ?><br>
<em>Created at: <?php echo $poll['created_at']; ?></em>
<!-- Edit and Delete forms for the poll -->
<div style="margin-top: 10px;">
<!-- Edit Form (inline) -->
<form method="post" class="inline-form">
<input type="hidden" name="poll_id" value="<?php echo $poll['id']; ?>">
<input type="text" name="edit_question_text" value="<?php echo htmlspecialchars($poll['question_text']); ?>" style="width:250px;">
<button type="submit" name="edit_poll">Save</button>
</form>
<!-- Delete Form (inline) -->
<form method="post" class="inline-form" onsubmit="return confirm('Are you sure you want to delete this poll?');">
<input type="hidden" name="poll_id" value="<?php echo $poll['id']; ?>">
<button type="submit" name="delete_poll">Delete</button>
</form>
</div>
<!-- Display poll options and vote counts -->
<?php
// Fetch options
$optionsStmt = $db->prepare("
SELECT po.id as option_id, po.option_text,
pr.vote_count
FROM poll_options po
LEFT JOIN poll_results pr
ON po.id = pr.option_id
WHERE po.question_id = :question_id
ORDER BY po.id ASC
");
$optionsStmt->bindValue(':question_id', $poll['id'], PDO::PARAM_INT);
$optionsStmt->execute();
$options = $optionsStmt->fetchAll(PDO::FETCH_ASSOC);
?>
<div class="poll-options">
<?php if (!empty($options)): ?>
<ul>
<?php foreach ($options as $opt): ?>
<li>
<?php echo htmlspecialchars($opt['option_text']); ?>
<span class="option-result">
(Votes: <?php echo $opt['vote_count']; ?>)
</span>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>No options for this poll yet.</p>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<p>No polls to display.</p>
<?php endif; ?>
</div>
<?php endif; ?>
</body>
</html>