Add query optimization and reliability improvements

- Consolidate StatsModel queries from 12 to 3 using conditional aggregation
- Add input validation to DashboardController (sort columns, dates, priorities)
- Combine getCategories/getTypes into single query
- Add transaction support to BulkOperationsModel with atomic mode option
- Add depth limit (20) to dependency cycle detection to prevent DoS
- Add caching to UserModel.getAllGroups() with 5-minute TTL
- Improve ticket ID generation with 50 attempts, exponential backoff, and fallback

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 18:31:46 -05:00
parent 7575d6a277
commit 44f2c21f2d
6 changed files with 335 additions and 71 deletions

View File

@@ -271,9 +271,20 @@ class UserModel {
* Get all distinct groups from all users
* Used for visibility group selection UI
*
* Results are cached for 5 minutes to reduce database load
* since group changes are infrequent.
*
* @return array Array of unique group names
*/
public function getAllGroups(): array {
$cacheKey = 'all_groups';
// Check cache first
$cached = self::getCached($cacheKey);
if ($cached !== null) {
return $cached;
}
$stmt = $this->conn->prepare("SELECT DISTINCT groups FROM users WHERE groups IS NOT NULL AND groups != ''");
$stmt->execute();
$result = $stmt->get_result();
@@ -289,6 +300,18 @@ class UserModel {
// Return unique groups sorted alphabetically
$uniqueGroups = array_unique($allGroups);
sort($uniqueGroups);
// Cache the result
self::setCache($cacheKey, $uniqueGroups);
return $uniqueGroups;
}
/**
* Invalidate the groups cache
* Call this when user groups are modified
*/
public static function invalidateGroupsCache(): void {
unset(self::$userCache['all_groups']);
}
}