diff --git a/public/api/contributions.php b/public/api/contributions.php index ffd673f..568dc66 100644 --- a/public/api/contributions.php +++ b/public/api/contributions.php @@ -356,8 +356,8 @@ function handle_delete($input) { // --------------------------------------------------------------------- -// VOTE: Likes or Dislikes a Contribution -// Required: contribution_id, voter_name, vote_type +// VOTE: Likes or Dislikes Contributions or Tasks +// Required: contribution_id or task_id, voter_name, vote_type // Database Trigger automatically updates Likes and Dislikes Count // UNIQUE Constraint prevents duplicate Votes per Voter. // --------------------------------------------------------------------- @@ -365,7 +365,7 @@ function handle_vote($input) { $pdo = get_db(); // Validates Input - $missing = validate_required($input, ['contribution_id', 'voter_name', 'vote_type']); + $missing = validate_required($input, ['voter_name', 'vote_type']); if (!empty($missing)) { error_response('Missing Fields: ' . implode(', ', $missing)); } @@ -376,13 +376,6 @@ function handle_vote($input) { error_response('Invalid vote_type. Must be: ' . implode(', ', $valid_vote_types)); } - // 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); - } - // Prepared SQL Statement try { // Checks if Voter already voted on this Contribution @@ -391,11 +384,39 @@ function handle_vote($input) { error_response('Browser ID required for Voting.'); } - $stmt = $pdo->prepare(" - SELECT vote_id, vote_type FROM votes - WHERE contribution_id = :cid AND browser_id = :bid - "); - $stmt->execute([':cid' => $input['contribution_id'], ':bid' => $browser_id]); + // Determines Vote Type + $is_task = isset($input['task_id']) && $input['task_id'] !== ''; + + if ($is_task) { + // Checks for Tasks + $stmt = $pdo->prepare("SELECT task_id FROM tasks WHERE task_id = :id"); + $stmt->execute([':id' => $input['task_id']]); + if (!$stmt->fetch()) { + error_response('Task not found.', 404); + } + + // Checks if Browser already voted on Task + $stmt = $pdo->prepare(" + SELECT vote_id, vote_type FROM votes + WHERE task_id = :id AND browser_id = :bid + "); + $stmt->execute([':id' => $input['task_id'], ':bid' => $browser_id]); + } else { + // Checks for Contributions + $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); + } + + // Checks if Browser already voted on Contribution + $stmt = $pdo->prepare(" + SELECT vote_id, vote_type FROM votes + WHERE contribution_id = :id AND browser_id = :bid + "); + $stmt->execute([':id' => $input['contribution_id'], ':bid' => $browser_id]); + } + $existing = $stmt->fetch(); if ($existing) { @@ -405,35 +426,47 @@ function handle_vote($input) { $stmt->execute([':vid' => $existing['vote_id']]); json_response(['message' => 'Vote removed.', 'action' => 'removed']); } else { - // Different Vote Type — Switches Vote + // Different Vote Type — Removes old Vote before Inserting new one $stmt = $pdo->prepare("DELETE FROM votes WHERE vote_id = :vid"); $stmt->execute([':vid' => $existing['vote_id']]); - - $stmt = $pdo->prepare(" - INSERT INTO votes (contribution_id, voter_name, vote_type, browser_id) - VALUES (:cid, :voter, :vtype, :bid) - "); - $stmt->execute([ - ':cid' => $input['contribution_id'], - ':voter' => $input['voter_name'], - ':vtype' => $input['vote_type'], - ':bid' => $browser_id - ]); - json_response(['message' => 'Vote changed.', 'action' => 'changed'], 200); + $this_insert = true; } } else { // No existing Vote — Inserts Vote - $stmt = $pdo->prepare(" - INSERT INTO votes (contribution_id, voter_name, vote_type, browser_id) - VALUES (:cid, :voter, :vtype, :bid) + $this_insert = true; + } + + if (!empty($this_insert)) { + if ($is_task) { + $stmt = $pdo->prepare(" + INSERT INTO votes (task_id, voter_name, vote_type, browser_id) + VALUES (:id, :voter, :vtype, :bid) "); $stmt->execute([ - ':cid' => $input['contribution_id'], + ':id' => $input['task_id'], ':voter' => $input['voter_name'], ':vtype' => $input['vote_type'], ':bid' => $browser_id ]); - json_response(['message' => 'Vote recorded.', 'action' => 'created'], 201); + } else { + $stmt = $pdo->prepare(" + INSERT INTO votes (contribution_id, voter_name, vote_type, browser_id) + VALUES (:id, :voter, :vtype, :bid) + "); + $stmt->execute([ + ':id' => $input['contribution_id'], + ':voter' => $input['voter_name'], + ':vtype' => $input['vote_type'], + ':bid' => $browser_id + ]); + } + + // Returns changed or created + if ($existing) { + json_response(['message' => 'Vote changed.', 'action' => 'changed'], 200); + } else { + json_response(['message' => 'Vote recorded.', 'action' => 'created'], 201); + } } } catch (PDOException $e) { @@ -586,26 +619,40 @@ function handle_photo_upload($file) { // ===================================================================== // --------------------------------------------------------------------- -// READ COMMENTS: Loads Comments for a Contribution -// Returns Comments sorted by Date (newest first) -// Required: contribution_id +// READ COMMENTS: Loads Comments for Contributions or Tasks +// Returns Comments sorted by Date (oldest first) +// Required: contribution_id or task_id // --------------------------------------------------------------------- function handle_read_comments($input) { $pdo = get_db(); - $missing = validate_required($input, ['contribution_id']); - if (!empty($missing)) { - error_response('Missing Fields: ' . implode(', ', $missing)); + // Checks for contribution_id or task_id + if (empty($input['contribution_id']) && empty($input['task_id'])) { + error_response('Either contribution_id or task_id is required.'); } + // Determines Vote Type + $is_task = isset($input['task_id']) && $input['task_id'] !== ''; + try { - $stmt = $pdo->prepare(" - SELECT comment_id, contribution_id, author_name, browser_id, content, status, created_at - FROM comments - WHERE contribution_id = :cid AND status = 'approved' - ORDER BY created_at ASC - "); - $stmt->execute([':cid' => $input['contribution_id']]); + if ($is_task) { + $stmt = $pdo->prepare(" + SELECT comment_id, task_id, author_name, browser_id, content, status, created_at + FROM comments + WHERE task_id = :id AND status = 'approved' + ORDER BY created_at ASC + "); + } else { + $stmt = $pdo->prepare(" + SELECT comment_id, contribution_id, author_name, browser_id, content, status, created_at + FROM comments + WHERE contribution_id = :id AND status = 'approved' + ORDER BY created_at ASC + "); + } + + // Prepared Statement + $stmt->execute([':id' => $is_task ? $input['task_id'] : $input['contribution_id']]); $comments = $stmt->fetchAll(); json_response(['comments' => $comments, 'count' => count($comments)]); @@ -617,37 +664,56 @@ function handle_read_comments($input) { // --------------------------------------------------------------------- -// CREATE COMMENT: Adds Comments to Contributions -// Required: contribution_id, author_name, content +// CREATE COMMENT: Adds Comments Contributions or Tasks +// Required: author_name, content, contribution_id or task_id // Optional: browser_id // --------------------------------------------------------------------- function handle_create_comment($input) { $pdo = get_db(); - $missing = validate_required($input, ['contribution_id', 'author_name', 'content']); + $missing = validate_required($input, ['author_name', 'content']); if (!empty($missing)) { error_response('Missing Fields: ' . implode(', ', $missing)); } - // Validates Content Length + // Checks for contribution_id or task_id + if (empty($input['contribution_id']) && empty($input['task_id'])) { + error_response('Either contribution_id or task_id is required.'); + } + + // Validates 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); - } + // Determines Comment Type + $is_task = isset($input['task_id']) && $input['task_id'] !== ''; + if ($is_task) { + // Checks for Tasks + $stmt = $pdo->prepare("SELECT task_id FROM tasks WHERE task_id = :id"); + $stmt->execute([':id' => $input['task_id']]); + if (!$stmt->fetch()) { + error_response('Task not found.', 404); + } + } else { + // Checks for Contributions + $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); + } + } + + // Prepared Statement try { $stmt = $pdo->prepare(" - INSERT INTO comments (contribution_id, author_name, browser_id, content) - VALUES (:cid, :author, :bid, :content) + INSERT INTO comments (contribution_id, task_id, author_name, browser_id, content) + VALUES (:cid, :tid, :author, :bid, :content) "); $stmt->execute([ - ':cid' => $input['contribution_id'], + ':cid' => $is_task ? null : $input['contribution_id'], + ':tid' => $is_task ? $input['task_id'] : null, ':author' => $input['author_name'], ':bid' => $input['browser_id'] ?? null, ':content' => $input['content']