diff --git a/api/add_comment.php b/api/add_comment.php
index 8737dae..cc306c5 100644
--- a/api/add_comment.php
+++ b/api/add_comment.php
@@ -65,8 +65,8 @@ try {
throw new Exception("Invalid JSON data received");
}
- $ticketId = isset($data['ticket_id']) ? (int)$data['ticket_id'] : 0;
- if ($ticketId <= 0) {
+ $ticketId = isset($data['ticket_id']) ? trim((string)$data['ticket_id']) : '';
+ if (!ctype_digit($ticketId) || (int)$ticketId <= 0) {
http_response_code(400);
ob_end_clean();
header('Content-Type: application/json');
diff --git a/api/export_tickets.php b/api/export_tickets.php
index 5c8d1b7..e6eec31 100644
--- a/api/export_tickets.php
+++ b/api/export_tickets.php
@@ -43,7 +43,8 @@ try {
$search = isset($_GET['search']) ? trim($_GET['search']) : null;
$format = isset($_GET['format']) ? $_GET['format'] : 'csv';
$ticketIds = isset($_GET['ticket_ids']) ? $_GET['ticket_ids'] : null;
- $singleId = isset($_GET['ticket_id']) ? (int)$_GET['ticket_id'] : null;
+ $singleIdRaw = isset($_GET['ticket_id']) ? trim($_GET['ticket_id']) : null;
+ $singleId = ($singleIdRaw !== null && ctype_digit($singleIdRaw) && (int)$singleIdRaw > 0) ? $singleIdRaw : null;
// Initialize model
$ticketModel = new TicketModel($conn);
diff --git a/api/notifications.php b/api/notifications.php
index f3afd22..b32a21e 100644
--- a/api/notifications.php
+++ b/api/notifications.php
@@ -75,7 +75,7 @@ $stmt = $conn->prepare($myTicketsSql);
$stmt->bind_param('ii', $userId, $userId);
$stmt->execute();
$mtResult = $stmt->get_result();
-while ($mtRow = $mtResult->fetch_assoc()) { $myTicketIds[(int)$mtRow['ticket_id']] = true; }
+while ($mtRow = $mtResult->fetch_assoc()) { $myTicketIds[(int)$mtRow['ticket_id']] = true; $myTicketIds[$mtRow['ticket_id']] = true; }
$stmt->close();
$watchedSql = "SELECT ticket_id FROM ticket_watchers WHERE user_id = ?";
@@ -83,7 +83,7 @@ $stmt = $conn->prepare($watchedSql);
$stmt->bind_param('i', $userId);
$stmt->execute();
$wResult = $stmt->get_result();
-while ($wRow = $wResult->fetch_assoc()) { $myTicketIds[(int)$wRow['ticket_id']] = true; }
+while ($wRow = $wResult->fetch_assoc()) { $myTicketIds[(int)$wRow['ticket_id']] = true; $myTicketIds[$wRow['ticket_id']] = true; }
$stmt->close();
// Step B: fetch recent comment audit events not by the current user
@@ -109,8 +109,9 @@ $stmt->close();
$commentRows = [];
foreach ($rawCommentRows as $rawRow) {
$d = json_decode($rawRow['details'] ?? '{}', true) ?? [];
- $tid = (int)($d['ticket_id'] ?? 0);
- if ($tid > 0 && isset($myTicketIds[$tid])) {
+ $tidRaw = $d['ticket_id'] ?? 0;
+ $tid = (int)$tidRaw;
+ if ($tid > 0 && (isset($myTicketIds[$tid]) || isset($myTicketIds[$tidRaw]))) {
$commentRows[] = $rawRow;
if (count($commentRows) >= 15) break;
}
@@ -158,8 +159,8 @@ foreach ($all as $row) {
? 'comment'
: $row['action_type'];
$ticketId = ($actionType === 'comment')
- ? (int)($details['ticket_id'] ?? 0)
- : (int)$row['entity_id'];
+ ? ($details['ticket_id'] ?? 0)
+ : $row['entity_id'];
$isRead = $lastSeen && $row['created_at'] <= $lastSeen;
// Build human-readable title
diff --git a/api/update_ticket.php b/api/update_ticket.php
index ccc76bb..29c32c7 100644
--- a/api/update_ticket.php
+++ b/api/update_ticket.php
@@ -252,7 +252,7 @@ try {
throw new Exception("Missing ticket_id parameter");
}
- $ticketId = (int)$data['ticket_id'];
+ $ticketId = trim((string)$data['ticket_id']);
// Initialize controller
$controller = new ApiTicketController($conn, $userId, $isAdmin, $currentUser);
diff --git a/assets/js/dashboard.js b/assets/js/dashboard.js
index b81fcae..06887e5 100644
--- a/assets/js/dashboard.js
+++ b/assets/js/dashboard.js
@@ -497,7 +497,7 @@ function updateSelectionCount() {
function getSelectedTicketIds() {
const checkboxes = document.querySelectorAll('.ticket-checkbox:checked');
- return Array.from(checkboxes).map(cb => parseInt(cb.value));
+ return Array.from(checkboxes).map(cb => String(cb.value));
}
function clearSelection() {
diff --git a/controllers/TicketController.php b/controllers/TicketController.php
index 9405f89..5172336 100644
--- a/controllers/TicketController.php
+++ b/controllers/TicketController.php
@@ -126,12 +126,12 @@ class TicketController {
}
// Auto-link as duplicate if requested from create form
- $linkDupOf = isset($_POST['link_duplicate_of']) ? (int)$_POST['link_duplicate_of'] : 0;
- if ($linkDupOf > 0) {
- $depSql = "INSERT IGNORE INTO ticket_dependencies (ticket_id, depends_on_ticket_id, dependency_type, created_by)
+ $linkDupOfRaw = trim($_POST['link_duplicate_of'] ?? '');
+ if ($linkDupOfRaw !== '' && ctype_digit($linkDupOfRaw)) {
+ $depSql = "INSERT IGNORE INTO ticket_dependencies (ticket_id, depends_on_id, dependency_type, created_by)
VALUES (?, ?, 'duplicates', ?)";
$depStmt = $this->conn->prepare($depSql);
- $depStmt->bind_param("iii", $result['ticket_id'], $linkDupOf, $userId);
+ $depStmt->bind_param("ssi", $result['ticket_id'], $linkDupOfRaw, $userId);
$depStmt->execute();
$depStmt->close();
}
diff --git a/views/DashboardView.php b/views/DashboardView.php
index 79a3251..50a7991 100644
--- a/views/DashboardView.php
+++ b/views/DashboardView.php
@@ -762,7 +762,7 @@ include __DIR__ . '/layout_header.php';
aria-label="View ticket = htmlspecialchars($row['ticket_id']) ?>">View
EXPORT