Fix type safety and TDS class naming issues
- bulk_operation.php: replace is_numeric() with strict int cast+equality to reject scientific notation - AttachmentModel.php: fix bind_param type strings (s→i for integer ticket IDs) - CommentModel.php: use strict !== comparison with (int) cast for user_id ownership checks - ticket.js: replace all non-TDS class names (text-amber→lt-text-amber, btn→lt-btn variants, etc.) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -50,13 +50,15 @@ if (!$operationType || empty($ticketIds)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validate ticket IDs are integers
|
||||
foreach ($ticketIds as $ticketId) {
|
||||
if (!is_numeric($ticketId)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Invalid ticket ID format']);
|
||||
// Validate ticket IDs are positive integers
|
||||
$ticketIds = array_values(array_filter(array_map(function($id) {
|
||||
$int = (int)$id;
|
||||
return ($int > 0 && (string)$int === (string)$id) ? $int : null;
|
||||
}, $ticketIds)));
|
||||
if (empty($ticketIds)) {
|
||||
echo json_encode(['success' => false, 'error' => 'No valid ticket IDs provided']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Use centralized database connection
|
||||
$conn = Database::getConnection();
|
||||
|
||||
+14
-14
@@ -475,10 +475,10 @@ function showDependencyError(message) {
|
||||
const dependentsList = document.getElementById('dependentsList');
|
||||
|
||||
if (dependenciesList) {
|
||||
dependenciesList.innerHTML = `<p class="text-amber">${lt.escHtml(message)}</p>`;
|
||||
dependenciesList.innerHTML = `<p class="lt-text-amber">${lt.escHtml(message)}</p>`;
|
||||
}
|
||||
if (dependentsList) {
|
||||
dependentsList.innerHTML = `<p class="text-amber">${lt.escHtml(message)}</p>`;
|
||||
dependentsList.innerHTML = `<p class="lt-text-amber">${lt.escHtml(message)}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ function renderDependencies(dependencies) {
|
||||
<span class="dependency-title">${lt.escHtml(dep.title)}</span>
|
||||
<span class="status-badge ${statusClass}">${lt.escHtml(dep.status)}</span>
|
||||
</div>
|
||||
<button data-action="remove-dependency" data-dependency-id="${dep.dependency_id}" class="btn btn-small">REMOVE</button>
|
||||
<button data-action="remove-dependency" data-dependency-id="${dep.dependency_id}" class="lt-btn lt-btn-sm">REMOVE</button>
|
||||
</div>`;
|
||||
});
|
||||
|
||||
@@ -521,7 +521,7 @@ function renderDependencies(dependencies) {
|
||||
}
|
||||
|
||||
if (!hasAny) {
|
||||
html = '<p class="text-muted-green">No dependencies configured.</p>';
|
||||
html = '<p class="lt-text-muted">No dependencies configured.</p>';
|
||||
}
|
||||
|
||||
container.innerHTML = html;
|
||||
@@ -532,7 +532,7 @@ function renderDependents(dependents) {
|
||||
if (!container) return;
|
||||
|
||||
if (dependents.length === 0) {
|
||||
container.innerHTML = '<p class="text-muted-green">No tickets depend on this one.</p>';
|
||||
container.innerHTML = '<p class="lt-text-muted">No tickets depend on this one.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -546,7 +546,7 @@ function renderDependents(dependents) {
|
||||
</a>
|
||||
<span class="dependency-title">${lt.escHtml(dep.title)}</span>
|
||||
<span class="status-badge ${statusClass}">${lt.escHtml(dep.status)}</span>
|
||||
<span class="dependency-title text-amber">(${lt.escHtml(dep.dependency_type)})</span>
|
||||
<span class="dependency-title lt-text-amber">(${lt.escHtml(dep.dependency_type)})</span>
|
||||
</div>
|
||||
</div>`;
|
||||
});
|
||||
@@ -756,11 +756,11 @@ function loadAttachments() {
|
||||
if (data.success) {
|
||||
renderAttachments(data.attachments || []);
|
||||
} else {
|
||||
container.innerHTML = '<p class="text-muted-green">Error loading attachments.</p>';
|
||||
container.innerHTML = '<p class="lt-text-muted">Error loading attachments.</p>';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
container.innerHTML = '<p class="text-muted-green">Error loading attachments.</p>';
|
||||
container.innerHTML = '<p class="lt-text-muted">Error loading attachments.</p>';
|
||||
});
|
||||
}
|
||||
|
||||
@@ -769,7 +769,7 @@ function renderAttachments(attachments) {
|
||||
if (!container) return;
|
||||
|
||||
if (attachments.length === 0) {
|
||||
container.innerHTML = '<p class="text-muted-green">No files attached to this ticket.</p>';
|
||||
container.innerHTML = '<p class="lt-text-muted">No files attached to this ticket.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -799,8 +799,8 @@ function renderAttachments(attachments) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="attachment-actions">
|
||||
<a href="/api/download_attachment.php?id=${att.attachment_id}" class="btn btn-small" title="Download">⬇</a>
|
||||
<button data-action="delete-attachment" data-attachment-id="${att.attachment_id}" class="btn btn-small btn-danger" title="Delete">✕</button>
|
||||
<a href="/api/download_attachment.php?id=${att.attachment_id}" class="lt-btn lt-btn-sm" title="Download">⬇</a>
|
||||
<button data-action="delete-attachment" data-attachment-id="${att.attachment_id}" class="lt-btn lt-btn-sm lt-btn-danger" title="Delete">✕</button>
|
||||
</div>
|
||||
</div>`;
|
||||
});
|
||||
@@ -1123,8 +1123,8 @@ function editComment(commentId) {
|
||||
Markdown
|
||||
</label>
|
||||
<div class="comment-edit-buttons">
|
||||
<button type="button" class="btn btn-small" data-action="save-edit-comment" data-comment-id="${commentId}">SAVE</button>
|
||||
<button type="button" class="btn btn-secondary btn-small" data-action="cancel-edit-comment" data-comment-id="${commentId}">CANCEL</button>
|
||||
<button type="button" class="lt-btn lt-btn-sm" data-action="save-edit-comment" data-comment-id="${commentId}">SAVE</button>
|
||||
<button type="button" class="lt-btn lt-btn-ghost lt-btn-sm" data-action="cancel-edit-comment" data-comment-id="${commentId}">CANCEL</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -1279,7 +1279,7 @@ function showReplyForm(commentId, userName) {
|
||||
<span>Markdown</span>
|
||||
</label>
|
||||
<div class="reply-buttons">
|
||||
<button type="button" class="btn btn-small" data-action="submit-reply" data-parent-id="${commentId}">REPLY</button>
|
||||
<button type="button" class="lt-btn lt-btn-sm" data-action="submit-reply" data-parent-id="${commentId}">REPLY</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@ class AttachmentModel {
|
||||
ORDER BY a.uploaded_at DESC";
|
||||
|
||||
$stmt = $this->conn->prepare($sql);
|
||||
$stmt->bind_param("s", $ticketId);
|
||||
$stmt->bind_param("i", $ticketId);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
@@ -61,7 +61,7 @@ class AttachmentModel {
|
||||
VALUES (?, ?, ?, ?, ?, ?)";
|
||||
|
||||
$stmt = $this->conn->prepare($sql);
|
||||
$stmt->bind_param("sssisi", $ticketId, $filename, $originalFilename, $fileSize, $mimeType, $uploadedBy);
|
||||
$stmt->bind_param("issisi", $ticketId, $filename, $originalFilename, $fileSize, $mimeType, $uploadedBy);
|
||||
$result = $stmt->execute();
|
||||
|
||||
if ($result) {
|
||||
@@ -97,7 +97,7 @@ class AttachmentModel {
|
||||
WHERE ticket_id = ?";
|
||||
|
||||
$stmt = $this->conn->prepare($sql);
|
||||
$stmt->bind_param("s", $ticketId);
|
||||
$stmt->bind_param("i", $ticketId);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$row = $result->fetch_assoc();
|
||||
@@ -113,7 +113,7 @@ class AttachmentModel {
|
||||
$sql = "SELECT COUNT(*) as count FROM ticket_attachments WHERE ticket_id = ?";
|
||||
|
||||
$stmt = $this->conn->prepare($sql);
|
||||
$stmt->bind_param("s", $ticketId);
|
||||
$stmt->bind_param("i", $ticketId);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$row = $result->fetch_assoc();
|
||||
|
||||
@@ -240,7 +240,7 @@ class CommentModel {
|
||||
return ['success' => false, 'error' => 'Comment not found'];
|
||||
}
|
||||
|
||||
if ($comment['user_id'] != $userId && !$isAdmin) {
|
||||
if ($comment['user_id'] !== (int)$userId && !$isAdmin) {
|
||||
return ['success' => false, 'error' => 'You do not have permission to edit this comment'];
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ class CommentModel {
|
||||
return ['success' => false, 'error' => 'Comment not found'];
|
||||
}
|
||||
|
||||
if ($comment['user_id'] != $userId && !$isAdmin) {
|
||||
if ($comment['user_id'] !== (int)$userId && !$isAdmin) {
|
||||
return ['success' => false, 'error' => 'You do not have permission to delete this comment'];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user