2025-05-16 20:02:49 -04:00
|
|
|
<?php
|
|
|
|
|
require_once 'models/TicketModel.php';
|
2026-01-08 23:05:03 -05:00
|
|
|
require_once 'models/UserPreferencesModel.php';
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
require_once 'models/StatsModel.php';
|
2025-05-16 20:02:49 -04:00
|
|
|
|
|
|
|
|
class DashboardController {
|
|
|
|
|
private $ticketModel;
|
2026-01-08 23:05:03 -05:00
|
|
|
private $prefsModel;
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
private $statsModel;
|
2025-09-05 11:08:56 -04:00
|
|
|
private $conn;
|
2026-01-08 23:05:03 -05:00
|
|
|
|
2026-01-30 18:31:46 -05:00
|
|
|
/** Valid sort columns (whitelist) */
|
|
|
|
|
private const VALID_SORT_COLUMNS = [
|
|
|
|
|
'ticket_id', 'title', 'status', 'priority', 'category', 'type',
|
|
|
|
|
'created_at', 'updated_at', 'assigned_to', 'created_by'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
/** Valid statuses */
|
|
|
|
|
private const VALID_STATUSES = ['Open', 'Pending', 'In Progress', 'Closed'];
|
|
|
|
|
|
2025-05-16 20:02:49 -04:00
|
|
|
public function __construct($conn) {
|
2025-09-05 11:08:56 -04:00
|
|
|
$this->conn = $conn;
|
2025-05-16 20:02:49 -04:00
|
|
|
$this->ticketModel = new TicketModel($conn);
|
2026-01-08 23:05:03 -05:00
|
|
|
$this->prefsModel = new UserPreferencesModel($conn);
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
$this->statsModel = new StatsModel($conn);
|
2025-05-16 20:02:49 -04:00
|
|
|
}
|
2026-01-30 18:31:46 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Validate and sanitize a date string
|
|
|
|
|
*/
|
|
|
|
|
private function validateDate(?string $date): ?string {
|
|
|
|
|
if (empty($date)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
// Check if it's a valid date format (YYYY-MM-DD)
|
|
|
|
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) && strtotime($date) !== false) {
|
|
|
|
|
return $date;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Validate priority value (1-5)
|
|
|
|
|
*/
|
|
|
|
|
private function validatePriority($priority): ?int {
|
|
|
|
|
if ($priority === null || $priority === '') {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
$val = (int)$priority;
|
|
|
|
|
return ($val >= 1 && $val <= 5) ? $val : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Validate user ID
|
|
|
|
|
*/
|
|
|
|
|
private function validateUserId($userId): ?int {
|
|
|
|
|
if ($userId === null || $userId === '') {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
$val = (int)$userId;
|
|
|
|
|
return ($val > 0) ? $val : null;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-16 20:02:49 -04:00
|
|
|
public function index() {
|
2026-01-08 23:05:03 -05:00
|
|
|
// Get user ID for preferences
|
|
|
|
|
$userId = isset($_SESSION['user']['user_id']) ? $_SESSION['user']['user_id'] : null;
|
|
|
|
|
|
2026-01-30 18:31:46 -05:00
|
|
|
// Validate and sanitize page parameter
|
|
|
|
|
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
|
2026-01-08 23:05:03 -05:00
|
|
|
|
|
|
|
|
// Get rows per page from user preferences, fallback to cookie, then default
|
2026-01-30 18:31:46 -05:00
|
|
|
// Clamp to reasonable range (1-100)
|
2026-01-08 23:05:03 -05:00
|
|
|
$limit = 15;
|
|
|
|
|
if ($userId) {
|
|
|
|
|
$limit = (int)$this->prefsModel->getPreference($userId, 'rows_per_page', 15);
|
|
|
|
|
} else if (isset($_COOKIE['ticketsPerPage'])) {
|
|
|
|
|
$limit = (int)$_COOKIE['ticketsPerPage'];
|
|
|
|
|
}
|
2026-01-30 18:31:46 -05:00
|
|
|
$limit = max(1, min(100, $limit));
|
2026-01-08 23:05:03 -05:00
|
|
|
|
2026-01-30 18:31:46 -05:00
|
|
|
// Validate sort column against whitelist
|
|
|
|
|
$sortColumn = isset($_GET['sort']) && in_array($_GET['sort'], self::VALID_SORT_COLUMNS, true)
|
|
|
|
|
? $_GET['sort']
|
|
|
|
|
: 'ticket_id';
|
|
|
|
|
|
|
|
|
|
// Validate sort direction
|
|
|
|
|
$sortDirection = isset($_GET['dir']) && strtolower($_GET['dir']) === 'asc' ? 'asc' : 'desc';
|
|
|
|
|
|
|
|
|
|
// Category and type are validated by the model (uses prepared statements)
|
|
|
|
|
$category = isset($_GET['category']) ? trim($_GET['category']) : null;
|
|
|
|
|
$type = isset($_GET['type']) ? trim($_GET['type']) : null;
|
|
|
|
|
|
|
|
|
|
// Sanitize search - limit length to prevent abuse
|
|
|
|
|
$search = isset($_GET['search']) ? substr(trim($_GET['search']), 0, 255) : null;
|
2026-01-08 23:05:03 -05:00
|
|
|
|
|
|
|
|
// Handle status filtering with user preferences
|
2025-09-05 11:08:56 -04:00
|
|
|
$status = null;
|
|
|
|
|
if (isset($_GET['status']) && !empty($_GET['status'])) {
|
2026-01-30 18:31:46 -05:00
|
|
|
// Validate each status in the comma-separated list
|
|
|
|
|
$requestedStatuses = array_map('trim', explode(',', $_GET['status']));
|
|
|
|
|
$validStatuses = array_filter($requestedStatuses, function($s) {
|
|
|
|
|
return in_array($s, self::VALID_STATUSES, true);
|
|
|
|
|
});
|
|
|
|
|
$status = !empty($validStatuses) ? implode(',', $validStatuses) : null;
|
2025-09-05 11:08:56 -04:00
|
|
|
} else if (!isset($_GET['show_all'])) {
|
2026-01-08 23:05:03 -05:00
|
|
|
// Get default status filters from user preferences
|
|
|
|
|
if ($userId) {
|
|
|
|
|
$status = $this->prefsModel->getPreference($userId, 'default_status_filters', 'Open,Pending,In Progress');
|
|
|
|
|
} else {
|
|
|
|
|
// Default: show Open, Pending, and In Progress (exclude Closed)
|
|
|
|
|
$status = 'Open,Pending,In Progress';
|
|
|
|
|
}
|
2025-09-05 11:08:56 -04:00
|
|
|
}
|
|
|
|
|
// If $_GET['show_all'] exists or no status param with show_all, show all tickets (status = null)
|
2026-01-09 11:20:27 -05:00
|
|
|
|
2026-01-30 18:31:46 -05:00
|
|
|
// Build and validate advanced search filters
|
2026-01-09 11:20:27 -05:00
|
|
|
$filters = [];
|
2026-01-30 18:31:46 -05:00
|
|
|
|
|
|
|
|
// Validate date filters
|
|
|
|
|
$createdFrom = $this->validateDate($_GET['created_from'] ?? null);
|
|
|
|
|
$createdTo = $this->validateDate($_GET['created_to'] ?? null);
|
|
|
|
|
$updatedFrom = $this->validateDate($_GET['updated_from'] ?? null);
|
|
|
|
|
$updatedTo = $this->validateDate($_GET['updated_to'] ?? null);
|
|
|
|
|
|
|
|
|
|
if ($createdFrom) $filters['created_from'] = $createdFrom;
|
|
|
|
|
if ($createdTo) $filters['created_to'] = $createdTo;
|
|
|
|
|
if ($updatedFrom) $filters['updated_from'] = $updatedFrom;
|
|
|
|
|
if ($updatedTo) $filters['updated_to'] = $updatedTo;
|
|
|
|
|
|
|
|
|
|
// Validate priority filters
|
|
|
|
|
$priorityMin = $this->validatePriority($_GET['priority_min'] ?? null);
|
|
|
|
|
$priorityMax = $this->validatePriority($_GET['priority_max'] ?? null);
|
|
|
|
|
|
|
|
|
|
if ($priorityMin !== null) $filters['priority_min'] = $priorityMin;
|
|
|
|
|
if ($priorityMax !== null) $filters['priority_max'] = $priorityMax;
|
|
|
|
|
|
|
|
|
|
// Validate user ID filters
|
|
|
|
|
$createdBy = $this->validateUserId($_GET['created_by'] ?? null);
|
|
|
|
|
$assignedTo = $this->validateUserId($_GET['assigned_to'] ?? null);
|
|
|
|
|
|
|
|
|
|
if ($createdBy !== null) $filters['created_by'] = $createdBy;
|
|
|
|
|
if ($assignedTo !== null) $filters['assigned_to'] = $assignedTo;
|
2026-01-09 11:20:27 -05:00
|
|
|
|
|
|
|
|
// Get tickets with pagination, sorting, search, and advanced filters
|
|
|
|
|
$result = $this->ticketModel->getAllTickets($page, $limit, $status, $sortColumn, $sortDirection, $category, $type, $search, $filters);
|
2026-01-30 18:31:46 -05:00
|
|
|
|
|
|
|
|
// Get categories and types for filters (single query)
|
|
|
|
|
$filterOptions = $this->getCategoriesAndTypes();
|
|
|
|
|
$categories = $filterOptions['categories'];
|
|
|
|
|
$types = $filterOptions['types'];
|
2025-05-16 20:02:49 -04:00
|
|
|
|
|
|
|
|
// Extract data for the view
|
|
|
|
|
$tickets = $result['tickets'];
|
|
|
|
|
$totalTickets = $result['total'];
|
|
|
|
|
$totalPages = $result['pages'];
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
|
|
|
|
|
// Load dashboard statistics
|
|
|
|
|
$stats = $this->statsModel->getAllStats();
|
|
|
|
|
|
2025-05-16 20:02:49 -04:00
|
|
|
// Load the dashboard view
|
|
|
|
|
include 'views/DashboardView.php';
|
|
|
|
|
}
|
2025-09-05 11:08:56 -04:00
|
|
|
|
2026-01-30 18:31:46 -05:00
|
|
|
/**
|
|
|
|
|
* Get categories and types in a single query
|
|
|
|
|
*
|
|
|
|
|
* @return array ['categories' => [...], 'types' => [...]]
|
|
|
|
|
*/
|
|
|
|
|
private function getCategoriesAndTypes(): array {
|
|
|
|
|
$sql = "SELECT 'category' as field, category as value FROM tickets WHERE category IS NOT NULL
|
|
|
|
|
UNION
|
|
|
|
|
SELECT 'type' as field, type as value FROM tickets WHERE type IS NOT NULL
|
|
|
|
|
ORDER BY field, value";
|
|
|
|
|
|
|
|
|
|
$result = $this->conn->query($sql);
|
2025-09-05 11:08:56 -04:00
|
|
|
$categories = [];
|
2026-01-30 18:31:46 -05:00
|
|
|
$types = [];
|
|
|
|
|
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
while ($row = $result->fetch_assoc()) {
|
2026-01-30 18:31:46 -05:00
|
|
|
if ($row['field'] === 'category' && !in_array($row['value'], $categories, true)) {
|
|
|
|
|
$categories[] = $row['value'];
|
|
|
|
|
} elseif ($row['field'] === 'type' && !in_array($row['value'], $types, true)) {
|
|
|
|
|
$types[] = $row['value'];
|
|
|
|
|
}
|
2025-09-05 11:08:56 -04:00
|
|
|
}
|
2026-01-30 18:31:46 -05:00
|
|
|
|
|
|
|
|
return ['categories' => $categories, 'types' => $types];
|
2025-09-05 11:08:56 -04:00
|
|
|
}
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
|
2026-01-30 18:31:46 -05:00
|
|
|
private function getCategories(): array {
|
|
|
|
|
return $this->getCategoriesAndTypes()['categories'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function getTypes(): array {
|
|
|
|
|
return $this->getCategoriesAndTypes()['types'];
|
2025-09-05 11:08:56 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
?>
|