← Back
mainapp/controllers/IssueController.php
<?php

class IssueController
{
  public function list(int $repoId): void {
    $db = db();
    $uid = auth_user_id();

    if (!repo_can_read($db, $repoId, $uid)) { http_response_code(403); exit("403"); }
    $repo = repo_get($db, $repoId);

    $st = $db->prepare("SELECT i.*, u.username as author_name
                        FROM issues i
                        JOIN users u ON u.id=i.author_id
                        WHERE i.repo_id=?
                        ORDER BY i.id DESC");
    $st->execute([$repoId]);
    $issues = $st->fetchAll();

    $canWrite = repo_can_write($db, $repoId, $uid);

    $title = $repo['owner_username'] . "/" . $repo['name'] . " / Issues";
    require __DIR__ . '/../views/issues/list.php';
  }

  public function showCreate(int $repoId): void {
    $db = db();
    $uid = require_auth();
    if (!repo_can_write($db, $repoId, $uid)) { http_response_code(403); exit("403"); }

    $repo = repo_get($db, $repoId);
    $title = $repo['owner_username'] . "/" . $repo['name'] . " / New Issue";
    require __DIR__ . '/../views/issues/create.php';
  }

  public function create(int $repoId): void {
    $db = db();
    $uid = require_auth();
    csrf_verify();
    if (!repo_can_write($db, $repoId, $uid)) { http_response_code(403); exit("403"); }

    $title = trim($_POST['title'] ?? '');
    $body = trim($_POST['body'] ?? '');

    if ($title === '' || strlen($title) > 255) {
      flash_set('err','Title required (max 255).');
      redirect("/r/$repoId/issues/new");
    }

    $st = $db->prepare("SELECT COALESCE(MAX(number),0)+1 as nextn FROM issues WHERE repo_id=?");
    $st->execute([$repoId]);
    $num = (int)($st->fetch()['nextn'] ?? 1);

    $st = $db->prepare("INSERT INTO issues (repo_id,number,title,body,state,author_id,created_at,updated_at)
                        VALUES (?,?,?,?,'open',?,?,?)");
    $st->execute([$repoId,$num,$title,$body,$uid,now(),now()]);

    flash_set('ok',"Issue created (#$num).");
    redirect("/r/$repoId/issues/$num");
  }

  public function show(int $repoId, int $number): void {
    $db = db();
    $uid = auth_user_id();
    if (!repo_can_read($db, $repoId, $uid)) { http_response_code(403); exit("403"); }

    $repo = repo_get($db, $repoId);

    $st = $db->prepare("SELECT i.*, u.username as author_name
                        FROM issues i JOIN users u ON u.id=i.author_id
                        WHERE i.repo_id=? AND i.number=? LIMIT 1");
    $st->execute([$repoId,$number]);
    $issue = $st->fetch();
    if (!$issue) { http_response_code(404); exit("Issue not found"); }

    $st = $db->prepare("SELECT c.*, u.username as user_name
                        FROM issue_comments c JOIN users u ON u.id=c.user_id
                        WHERE c.issue_id=? ORDER BY c.id ASC");
    $st->execute([(int)$issue['id']]);
    $comments = $st->fetchAll();

    $canWrite = repo_can_write($db, $repoId, $uid);

    $title = $repo['owner_username'] . "/" . $repo['name'] . " / Issue #" . $number;
    require __DIR__ . '/../views/issues/show.php';
  }

  public function comment(int $repoId, int $number): void {
    $db = db();
    $uid = require_auth();
    csrf_verify();
    if (!repo_can_write($db, $repoId, $uid)) { http_response_code(403); exit("403"); }

    $st = $db->prepare("SELECT id FROM issues WHERE repo_id=? AND number=? LIMIT 1");
    $st->execute([$repoId,$number]);
    $row = $st->fetch();
    if (!$row) { http_response_code(404); exit("Issue not found"); }

    $body = trim($_POST['body'] ?? '');
    if ($body === '') { flash_set('err','Comment cannot be empty.'); redirect("/r/$repoId/issues/$number"); }

    $st = $db->prepare("INSERT INTO issue_comments (issue_id,user_id,body,created_at) VALUES (?,?,?,?)");
    $st->execute([(int)$row['id'], $uid, $body, now()]);

    $st = $db->prepare("UPDATE issues SET updated_at=? WHERE id=?");
    $st->execute([now(), (int)$row['id']]);

    flash_set('ok','Comment added.');
    redirect("/r/$repoId/issues/$number");
  }

  public function toggleState(int $repoId, int $number): void {
    $db = db();
    $uid = require_auth();
    csrf_verify();
    if (!repo_can_write($db, $repoId, $uid)) { http_response_code(403); exit("403"); }

    $st = $db->prepare("SELECT id, state FROM issues WHERE repo_id=? AND number=? LIMIT 1");
    $st->execute([$repoId,$number]);
    $issue = $st->fetch();
    if (!$issue) { http_response_code(404); exit("Issue not found"); }

    $new = ($issue['state'] === 'open') ? 'closed' : 'open';
    $st = $db->prepare("UPDATE issues SET state=?, updated_at=? WHERE id=?");
    $st->execute([$new, now(), (int)$issue['id']]);

    flash_set('ok', "Issue $new.");
    redirect("/r/$repoId/issues/$number");
  }
}