Auto-Commit: 2026-07-05 10:51:13
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
error_reporting(0);
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$dataDir = __DIR__ . '/data/';
|
||||
$dataFile = $dataDir . 'feedback.json';
|
||||
|
||||
// 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 === 'delete') {
|
||||
$id = $input['id'] ?? '';
|
||||
$secret = $input['secret'] ?? '';
|
||||
|
||||
// Simple authentication via secret "1234" (as defined in frontend)
|
||||
if ($secret !== '1234') {
|
||||
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 !== '1234') {
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user