photos and comments functionality for contributions, moderation page functionality pending
This commit is contained in:
@@ -47,13 +47,22 @@ switch ($action) {
|
||||
case 'delete_news':
|
||||
handle_delete_news($input);
|
||||
break;
|
||||
case 'read_comments':
|
||||
handle_read_comments($input);
|
||||
break;
|
||||
case 'create_comment':
|
||||
handle_create_comment($input);
|
||||
break;
|
||||
case 'delete_comment':
|
||||
handle_delete_comment($input);
|
||||
break;
|
||||
default:
|
||||
error_response('Unknown Action. Supported Actions are read, create, update, delete, vote.');
|
||||
}
|
||||
|
||||
|
||||
// =====================================================================
|
||||
// Action Handlers
|
||||
// Action Handlers for Contributions
|
||||
// =====================================================================
|
||||
|
||||
|
||||
@@ -152,6 +161,11 @@ function handle_read($input) {
|
||||
// Required: municipality_id, geom, geom_type, category, title, author_name
|
||||
// Optional: description
|
||||
// ---------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
// CREATE: Inserts new Contributions with optional Photo Upload
|
||||
// Required: municipality_id, geom, geom_type, category, title, author_name
|
||||
// Optional: description, browser_id, photo (File Upload)
|
||||
// ---------------------------------------------------------------------
|
||||
function handle_create($input) {
|
||||
$pdo = get_db();
|
||||
|
||||
@@ -175,14 +189,23 @@ function handle_create($input) {
|
||||
error_response('Invalid GeoJSON in Geometry Field.');
|
||||
}
|
||||
|
||||
// Handles Photo Upload
|
||||
$photo_path = null;
|
||||
if (isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK) {
|
||||
$photo_path = handle_photo_upload($_FILES['photo']);
|
||||
if (!$photo_path) {
|
||||
error_response('Photo Upload failed. JPG, PNG, GIF and WebP up to 5 MB are allowed.');
|
||||
}
|
||||
}
|
||||
|
||||
// Prepared SQL Statement
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO contributions
|
||||
(municipality_id, geom, geom_type, category, title, description, author_name, browser_id)
|
||||
(municipality_id, geom, geom_type, category, title, description, author_name, browser_id, photo_path)
|
||||
VALUES
|
||||
(:mid, ST_SetSRID(ST_GeomFromGeoJSON(:geom), 4326), :geom_type,
|
||||
:category, :title, :description, :author_name, :browser_id)
|
||||
:category, :title, :description, :author_name, :browser_id, :photo_path)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
@@ -193,7 +216,8 @@ function handle_create($input) {
|
||||
':title' => $input['title'],
|
||||
':description' => $input['description'] ?? '',
|
||||
':author_name' => $input['author_name'],
|
||||
':browser_id' => $input['browser_id'] ?? null
|
||||
':browser_id' => $input['browser_id'] ?? null,
|
||||
':photo_path' => $photo_path
|
||||
]);
|
||||
|
||||
json_response([
|
||||
@@ -394,6 +418,10 @@ function handle_vote($input) {
|
||||
}
|
||||
|
||||
|
||||
// =====================================================================
|
||||
// Action Handlers for News
|
||||
// =====================================================================
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// CREATE NEWS: Inserts new News Entry
|
||||
// Required: municipality_id, title, content
|
||||
@@ -475,4 +503,162 @@ function handle_delete_news($input) {
|
||||
} catch (PDOException $e) {
|
||||
error_response('Database Error: ' . $e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// =====================================================================
|
||||
// Action Handlers for Photos
|
||||
// =====================================================================
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// PHOTO UPLOAD: Validates and Saves uploaded Photo Files
|
||||
// Returns relative Path on Success, null on Failure.
|
||||
// Allowed: JPG, PNG, GIF, WebP. with maximum Size of 5 MB.
|
||||
// ---------------------------------------------------------------------
|
||||
function handle_photo_upload($file) {
|
||||
// Validates File Size
|
||||
$max_size = 5 * 1024 * 1024;
|
||||
if ($file['size'] > $max_size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Validates MIME Type
|
||||
$allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime = finfo_file($finfo, $file['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
|
||||
if (!in_array($mime, $allowed_types)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Generates unique Filename
|
||||
$ext = [
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/gif' => 'gif',
|
||||
'image/webp' => 'webp'
|
||||
][$mime];
|
||||
|
||||
$filename = uniqid('photo_', true) . '.' . $ext;
|
||||
$upload_dir = __DIR__ . '/../uploads/photos/';
|
||||
$target_path = $upload_dir . $filename;
|
||||
|
||||
// Creates Upload Directory
|
||||
if (!is_dir($upload_dir)) {
|
||||
mkdir($upload_dir, 0755, true);
|
||||
}
|
||||
|
||||
// Moves uploaded File
|
||||
if (move_uploaded_file($file['tmp_name'], $target_path)) {
|
||||
return 'uploads/photos/' . $filename;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// =====================================================================
|
||||
// Action Handlers for Comments
|
||||
// =====================================================================
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// READ COMMENTS: Loads Comments for a Contribution
|
||||
// Returns Comments sorted by Date (newest first)
|
||||
// Required: contribution_id
|
||||
// ---------------------------------------------------------------------
|
||||
function handle_read_comments($input) {
|
||||
$pdo = get_db();
|
||||
|
||||
$missing = validate_required($input, ['contribution_id']);
|
||||
if (!empty($missing)) {
|
||||
error_response('Missing Fields: ' . implode(', ', $missing));
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT comment_id, contribution_id, author_name, browser_id, content, created_at
|
||||
FROM comments
|
||||
WHERE contribution_id = :cid
|
||||
ORDER BY created_at ASC
|
||||
");
|
||||
$stmt->execute([':cid' => $input['contribution_id']]);
|
||||
$comments = $stmt->fetchAll();
|
||||
|
||||
json_response(['comments' => $comments, 'count' => count($comments)]);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_response('Database Error: ' . $e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// CREATE COMMENT: Adds Comments to Contributions
|
||||
// Required: contribution_id, author_name, content
|
||||
// Optional: browser_id
|
||||
// ---------------------------------------------------------------------
|
||||
function handle_create_comment($input) {
|
||||
$pdo = get_db();
|
||||
|
||||
$missing = validate_required($input, ['contribution_id', 'author_name', 'content']);
|
||||
if (!empty($missing)) {
|
||||
error_response('Missing Fields: ' . implode(', ', $missing));
|
||||
}
|
||||
|
||||
// Validates Content Length
|
||||
if (strlen($input['content']) > 1000) {
|
||||
error_response('Comment too long. Maximum 1000 Characters.');
|
||||
}
|
||||
|
||||
// Checks if Contribution exists
|
||||
$stmt = $pdo->prepare("SELECT contribution_id FROM contributions WHERE contribution_id = :id");
|
||||
$stmt->execute([':id' => $input['contribution_id']]);
|
||||
if (!$stmt->fetch()) {
|
||||
error_response('Contribution not found.', 404);
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO comments (contribution_id, author_name, browser_id, content)
|
||||
VALUES (:cid, :author, :bid, :content)
|
||||
");
|
||||
$stmt->execute([
|
||||
':cid' => $input['contribution_id'],
|
||||
':author' => $input['author_name'],
|
||||
':bid' => $input['browser_id'] ?? null,
|
||||
':content' => $input['content']
|
||||
]);
|
||||
|
||||
json_response([
|
||||
'message' => 'Comment created successfully.',
|
||||
'comment_id' => (int) $pdo->lastInsertId()
|
||||
], 201);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_response('Database Error: ' . $e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// DELETE COMMENT: Removes a Comment
|
||||
// Required: comment_id
|
||||
// ---------------------------------------------------------------------
|
||||
function handle_delete_comment($input) {
|
||||
$pdo = get_db();
|
||||
|
||||
$missing = validate_required($input, ['comment_id']);
|
||||
if (!empty($missing)) {
|
||||
error_response('Missing Fields: ' . implode(', ', $missing));
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM comments WHERE comment_id = :id");
|
||||
$stmt->execute([':id' => $input['comment_id']]);
|
||||
|
||||
json_response(['message' => 'Comment deleted successfully.']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_response('Database Error: ' . $e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user