204 lines
6.9 KiB
PHP
204 lines
6.9 KiB
PHP
<?php
|
|
error_reporting(0);
|
|
header('Content-Type: application/json');
|
|
|
|
$dataDir = __DIR__ . '/data/';
|
|
$dataFile = $dataDir . 'feedback.json';
|
|
|
|
function getAdminPassword() {
|
|
$envFile = __DIR__ . '/.env';
|
|
if (file_exists($envFile)) {
|
|
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
foreach ($lines as $line) {
|
|
if (strpos(trim($line), '#') === 0) continue;
|
|
$parts = explode('=', $line, 2);
|
|
if (count($parts) === 2) {
|
|
if (trim($parts[0]) === 'ADMIN_PASSWORD') {
|
|
return trim($parts[1]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return '1234';
|
|
}
|
|
$adminPassword = getAdminPassword();
|
|
|
|
// Create data directory if not exists
|
|
if (!is_dir($dataDir)) {
|
|
@mkdir($dataDir, 0755, true);
|
|
}
|
|
|
|
// Default Seed Data
|
|
$defaultFeedback = [
|
|
[
|
|
'id' => 'fb-1',
|
|
'author' => 'Markus T.',
|
|
'type' => 'feature',
|
|
'title' => 'QR-Code Download für Gäste',
|
|
'text' => 'Es wäre super cool, wenn nach der Aufnahme ein QR-Code angezeigt wird, über den sich die Gäste das Foto direkt auf das Handy laden können.',
|
|
'upvotes' => 42,
|
|
'answer' => null
|
|
],
|
|
[
|
|
'id' => 'fb-2',
|
|
'author' => 'Sabrina',
|
|
'type' => 'love',
|
|
'title' => 'Sticker-Editor ist genial!',
|
|
'text' => 'Unsere Hochzeitsgäste haben stundenlang Emojis und Eventtexte verschoben. Die Bedienung ist wirklich super intuitiv und einfach.',
|
|
'upvotes' => 28,
|
|
'answer' => 'Vielen Dank für das tolle Feedback! Freut uns, dass es euch gefallen hat.'
|
|
],
|
|
[
|
|
'id' => 'fb-3',
|
|
'author' => 'EventTech GmbH',
|
|
'type' => 'bug',
|
|
'title' => 'Drucker-Timeout bei schlechtem WLAN',
|
|
'text' => 'Manchmal meldet die App einen Fehler, wenn der Drucker im lokalen Netzwerk kurz die Verbindung verliert. Ein automatischer Retry wäre hilfreich.',
|
|
'upvotes' => 15,
|
|
'answer' => null
|
|
]
|
|
];
|
|
|
|
// Initialize JSON file if it doesn't exist
|
|
if (!file_exists($dataFile)) {
|
|
file_put_contents($dataFile, json_encode($defaultFeedback, JSON_PRETTY_PRINT));
|
|
}
|
|
|
|
// Read data
|
|
$feedbackData = json_decode(file_get_contents($dataFile), true);
|
|
if (!$feedbackData) {
|
|
$feedbackData = [];
|
|
}
|
|
|
|
$action = isset($_GET['action']) ? $_GET['action'] : '';
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
// For POST requests, we might get the action from the body or query param
|
|
$inputJSON = file_get_contents('php://input');
|
|
$input = json_decode($inputJSON, true);
|
|
$action = isset($input['action']) ? $input['action'] : $action;
|
|
}
|
|
|
|
switch ($_SERVER['REQUEST_METHOD']) {
|
|
case 'GET':
|
|
// Return all feedback
|
|
echo json_encode(['success' => true, 'data' => $feedbackData]);
|
|
break;
|
|
|
|
case 'POST':
|
|
if (!$input) {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Invalid JSON']);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'add') {
|
|
$newFb = [
|
|
'id' => 'fb-' . time() . rand(100, 999),
|
|
'author' => htmlspecialchars($input['author'] ?? 'Anonym'),
|
|
'type' => htmlspecialchars($input['type'] ?? 'feature'),
|
|
'title' => htmlspecialchars($input['title'] ?? 'Kein Titel'),
|
|
'text' => htmlspecialchars($input['text'] ?? ''),
|
|
'upvotes' => 1,
|
|
'answer' => null
|
|
];
|
|
|
|
array_push($feedbackData, $newFb);
|
|
file_put_contents($dataFile, json_encode($feedbackData, JSON_PRETTY_PRINT));
|
|
|
|
echo json_encode(['success' => true, 'data' => $newFb]);
|
|
}
|
|
elseif ($action === 'upvote') {
|
|
$id = $input['id'] ?? '';
|
|
$undo = isset($input['undo']) && $input['undo'] === true;
|
|
$found = false;
|
|
|
|
foreach ($feedbackData as &$item) {
|
|
if ($item['id'] === $id) {
|
|
if ($undo) {
|
|
$item['upvotes'] = max(0, $item['upvotes'] - 1);
|
|
} else {
|
|
$item['upvotes']++;
|
|
}
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($found) {
|
|
file_put_contents($dataFile, json_encode($feedbackData, JSON_PRETTY_PRINT));
|
|
echo json_encode(['success' => true]);
|
|
} else {
|
|
http_response_code(404);
|
|
echo json_encode(['error' => 'Feedback not found']);
|
|
}
|
|
}
|
|
elseif ($action === 'verify_password') {
|
|
$secret = $input['secret'] ?? '';
|
|
if ($secret === $adminPassword) {
|
|
echo json_encode(['success' => true]);
|
|
} else {
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Unauthorized']);
|
|
}
|
|
exit;
|
|
}
|
|
elseif ($action === 'delete') {
|
|
$id = $input['id'] ?? '';
|
|
$secret = $input['secret'] ?? '';
|
|
|
|
if ($secret !== $adminPassword) {
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Unauthorized']);
|
|
exit;
|
|
}
|
|
|
|
$filteredData = array_filter($feedbackData, function($item) use ($id) {
|
|
return $item['id'] !== $id;
|
|
});
|
|
|
|
// Re-index array
|
|
$feedbackData = array_values($filteredData);
|
|
file_put_contents($dataFile, json_encode($feedbackData, JSON_PRETTY_PRINT));
|
|
echo json_encode(['success' => true]);
|
|
}
|
|
elseif ($action === 'answer') {
|
|
$id = $input['id'] ?? '';
|
|
$answer = $input['answer'] ?? '';
|
|
$secret = $input['secret'] ?? '';
|
|
|
|
if ($secret !== $adminPassword) {
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Unauthorized']);
|
|
exit;
|
|
}
|
|
|
|
$found = false;
|
|
foreach ($feedbackData as &$item) {
|
|
if ($item['id'] === $id) {
|
|
// Save htmlspecialchars to avoid XSS but allow simple answers
|
|
$item['answer'] = $answer === '' ? null : htmlspecialchars($answer);
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($found) {
|
|
file_put_contents($dataFile, json_encode($feedbackData, JSON_PRETTY_PRINT));
|
|
echo json_encode(['success' => true]);
|
|
} else {
|
|
http_response_code(404);
|
|
echo json_encode(['error' => 'Feedback not found']);
|
|
}
|
|
}
|
|
else {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Unknown action']);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
http_response_code(405);
|
|
echo json_encode(['error' => 'Method not allowed']);
|
|
break;
|
|
}
|