style: auto-fix 1340 phpcs PSR-12 violations via phpcbf; exclude MissingNamespace and SideEffects
This commit is contained in:
+47
-27
@@ -1,12 +1,16 @@
|
||||
<?php
|
||||
class TicketModel {
|
||||
|
||||
class TicketModel
|
||||
{
|
||||
private mysqli $conn;
|
||||
|
||||
public function __construct(mysqli $conn) {
|
||||
public function __construct(mysqli $conn)
|
||||
{
|
||||
$this->conn = $conn;
|
||||
}
|
||||
|
||||
public function getTicketById(int $id): ?array {
|
||||
public function getTicketById(int $id): ?array
|
||||
{
|
||||
$sql = "SELECT t.*,
|
||||
u_created.username as creator_username,
|
||||
u_created.display_name as creator_display_name,
|
||||
@@ -30,8 +34,9 @@ class TicketModel {
|
||||
|
||||
return $result->fetch_assoc();
|
||||
}
|
||||
|
||||
public function getAllTickets(int $page = 1, int $limit = 15, ?string $status = 'Open', string $sortColumn = 'ticket_id', string $sortDirection = 'desc', ?string $category = null, ?string $type = null, ?string $search = null, array $filters = [], ?array $user = null): array {
|
||||
|
||||
public function getAllTickets(int $page = 1, int $limit = 15, ?string $status = 'Open', string $sortColumn = 'ticket_id', string $sortDirection = 'desc', ?string $category = null, ?string $type = null, ?string $search = null, array $filters = [], ?array $user = null): array
|
||||
{
|
||||
// Calculate offset
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
@@ -162,12 +167,12 @@ class TicketModel {
|
||||
$paramTypes .= 'i';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$whereClause = '';
|
||||
if (!empty($whereConditions)) {
|
||||
$whereClause = 'WHERE ' . implode(' AND ', $whereConditions);
|
||||
}
|
||||
|
||||
|
||||
// Validate sort column to prevent SQL injection
|
||||
$allowedColumns = ['ticket_id', 'title', 'status', 'priority', 'category', 'type', 'created_at', 'updated_at', 'created_by', 'assigned_to'];
|
||||
if (!in_array($sortColumn, $allowedColumns)) {
|
||||
@@ -230,7 +235,7 @@ class TicketModel {
|
||||
'current_page' => $page
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update a ticket with optional optimistic locking
|
||||
*
|
||||
@@ -239,7 +244,8 @@ class TicketModel {
|
||||
* @param string|null $expectedUpdatedAt If provided, update will fail if ticket was modified since this timestamp
|
||||
* @return array ['success' => bool, 'error' => string|null, 'conflict' => bool]
|
||||
*/
|
||||
public function updateTicket(array $ticketData, ?int $updatedBy = null, ?string $expectedUpdatedAt = null): array {
|
||||
public function updateTicket(array $ticketData, ?int $updatedBy = null, ?string $expectedUpdatedAt = null): array
|
||||
{
|
||||
// closed_at: set on close (preserve if already set), clear on reopen
|
||||
$closedAtClause = "closed_at = CASE WHEN ? = 'Closed' THEN COALESCE(closed_at, NOW()) ELSE NULL END";
|
||||
|
||||
@@ -332,8 +338,9 @@ class TicketModel {
|
||||
|
||||
return ['success' => true, 'error' => null, 'conflict' => false];
|
||||
}
|
||||
|
||||
public function createTicket(array $ticketData, ?int $createdBy = null): array {
|
||||
|
||||
public function createTicket(array $ticketData, ?int $createdBy = null): array
|
||||
{
|
||||
// Generate unique ticket ID (9-digit format with leading zeros)
|
||||
// Uses cryptographically secure random numbers for better distribution
|
||||
// Includes exponential backoff and fallback for reliability under high load
|
||||
@@ -486,16 +493,17 @@ class TicketModel {
|
||||
}
|
||||
}
|
||||
|
||||
public function addComment(int $ticketId, array $commentData): array {
|
||||
public function addComment(int $ticketId, array $commentData): array
|
||||
{
|
||||
$sql = "INSERT INTO ticket_comments (ticket_id, user_name, comment_text, markdown_enabled)
|
||||
VALUES (?, ?, ?, ?)";
|
||||
|
||||
|
||||
$stmt = $this->conn->prepare($sql);
|
||||
|
||||
|
||||
// Set default username
|
||||
$username = $commentData['user_name'] ?? 'User';
|
||||
$markdownEnabled = $commentData['markdown_enabled'] ? 1 : 0;
|
||||
|
||||
|
||||
$stmt->bind_param(
|
||||
"issi",
|
||||
$ticketId,
|
||||
@@ -503,7 +511,7 @@ class TicketModel {
|
||||
$commentData['comment_text'],
|
||||
$markdownEnabled
|
||||
);
|
||||
|
||||
|
||||
if ($stmt->execute()) {
|
||||
return [
|
||||
'success' => true,
|
||||
@@ -526,7 +534,8 @@ class TicketModel {
|
||||
* @param int $assignedBy User ID performing the assignment
|
||||
* @return bool Success status
|
||||
*/
|
||||
public function assignTicket(int $ticketId, int $userId, int $assignedBy): bool {
|
||||
public function assignTicket(int $ticketId, int $userId, int $assignedBy): bool
|
||||
{
|
||||
$sql = "UPDATE tickets SET assigned_to = ?, updated_by = ?, updated_at = NOW() WHERE ticket_id = ?";
|
||||
$stmt = $this->conn->prepare($sql);
|
||||
$stmt->bind_param("iii", $userId, $assignedBy, $ticketId);
|
||||
@@ -542,7 +551,8 @@ class TicketModel {
|
||||
* @param int $updatedBy User ID performing the unassignment
|
||||
* @return bool Success status
|
||||
*/
|
||||
public function unassignTicket(int $ticketId, int $updatedBy): bool {
|
||||
public function unassignTicket(int $ticketId, int $updatedBy): bool
|
||||
{
|
||||
$sql = "UPDATE tickets SET assigned_to = NULL, updated_by = ?, updated_at = NOW() WHERE ticket_id = ?";
|
||||
$stmt = $this->conn->prepare($sql);
|
||||
$stmt->bind_param("ii", $updatedBy, $ticketId);
|
||||
@@ -558,7 +568,8 @@ class TicketModel {
|
||||
* @param array $ticketIds Array of ticket IDs
|
||||
* @return array Associative array keyed by ticket_id
|
||||
*/
|
||||
public function getTicketsByIds(array $ticketIds): array {
|
||||
public function getTicketsByIds(array $ticketIds): array
|
||||
{
|
||||
if (empty($ticketIds)) {
|
||||
return [];
|
||||
}
|
||||
@@ -604,7 +615,8 @@ class TicketModel {
|
||||
* @param array $user The user data (must include user_id, is_admin, groups)
|
||||
* @return bool True if user can access the ticket
|
||||
*/
|
||||
public function canUserAccessTicket(array $ticket, array $user): bool {
|
||||
public function canUserAccessTicket(array $ticket, array $user): bool
|
||||
{
|
||||
// Admins can access all tickets
|
||||
if (!empty($user['is_admin'])) {
|
||||
return true;
|
||||
@@ -644,7 +656,8 @@ class TicketModel {
|
||||
* @param array $user The current user
|
||||
* @return array ['sql' => string, 'params' => array, 'types' => string]
|
||||
*/
|
||||
public function getVisibilityFilter(array $user): array {
|
||||
public function getVisibilityFilter(array $user): array
|
||||
{
|
||||
// Admins see all tickets
|
||||
if (!empty($user['is_admin'])) {
|
||||
return ['sql' => '1=1', 'params' => [], 'types' => ''];
|
||||
@@ -697,7 +710,8 @@ class TicketModel {
|
||||
* @param int $updatedBy User ID
|
||||
* @return bool
|
||||
*/
|
||||
public function updateVisibility(int $ticketId, string $visibility, ?string $visibilityGroups, int $updatedBy): bool {
|
||||
public function updateVisibility(int $ticketId, string $visibility, ?string $visibilityGroups, int $updatedBy): bool
|
||||
{
|
||||
$allowedVisibilities = ['public', 'internal', 'confidential'];
|
||||
if (!in_array($visibility, $allowedVisibilities)) {
|
||||
$visibility = 'public';
|
||||
@@ -728,7 +742,8 @@ class TicketModel {
|
||||
* @param string $ticketId Ticket ID
|
||||
* @return bool Success status
|
||||
*/
|
||||
public function deleteTicket(string $ticketId): bool {
|
||||
public function deleteTicket(string $ticketId): bool
|
||||
{
|
||||
// Collect attachment filenames before deleting DB rows
|
||||
$attachmentFiles = [];
|
||||
$attStmt = $this->conn->prepare("SELECT filename FROM ticket_attachments WHERE ticket_id = ?");
|
||||
@@ -754,7 +769,9 @@ class TicketModel {
|
||||
foreach ($children as $sql) {
|
||||
try {
|
||||
$stmt = $this->conn->prepare($sql);
|
||||
if (!$stmt) continue;
|
||||
if (!$stmt) {
|
||||
continue;
|
||||
}
|
||||
// ticket_dependencies uses two placeholders
|
||||
if (strpos($sql, 'depends_on_id') !== false) {
|
||||
$stmt->bind_param('ss', $ticketId, $ticketId);
|
||||
@@ -772,7 +789,9 @@ class TicketModel {
|
||||
}
|
||||
|
||||
$stmt = $this->conn->prepare("DELETE FROM tickets WHERE ticket_id = ?");
|
||||
if (!$stmt) return false;
|
||||
if (!$stmt) {
|
||||
return false;
|
||||
}
|
||||
$stmt->bind_param('s', $ticketId);
|
||||
$result = $stmt->execute();
|
||||
$affected = $stmt->affected_rows;
|
||||
@@ -802,7 +821,8 @@ class TicketModel {
|
||||
* Check whether the FULLTEXT index on tickets(title, description) exists.
|
||||
* Result is cached for the process lifetime (static).
|
||||
*/
|
||||
private function hasFulltextIndex(): bool {
|
||||
private function hasFulltextIndex(): bool
|
||||
{
|
||||
static $result = null;
|
||||
if ($result !== null) {
|
||||
return $result;
|
||||
@@ -817,4 +837,4 @@ class TicketModel {
|
||||
$result = $r && (int)$r->fetch_assoc()['cnt'] > 0;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user