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>
This commit is contained in:
148
api/export_tickets.php
Normal file
148
api/export_tickets.php
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
/**
|
||||
* Export Tickets API
|
||||
*
|
||||
* Exports tickets to CSV format with optional filtering
|
||||
*/
|
||||
|
||||
// Disable error display in the output
|
||||
ini_set('display_errors', 0);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
// Apply rate limiting
|
||||
require_once dirname(__DIR__) . '/middleware/RateLimitMiddleware.php';
|
||||
RateLimitMiddleware::apply('api');
|
||||
|
||||
try {
|
||||
// Include required files
|
||||
require_once dirname(__DIR__) . '/config/config.php';
|
||||
require_once dirname(__DIR__) . '/models/TicketModel.php';
|
||||
|
||||
// Check authentication via session
|
||||
session_start();
|
||||
if (!isset($_SESSION['user']) || !isset($_SESSION['user']['user_id'])) {
|
||||
header('Content-Type: application/json');
|
||||
http_response_code(401);
|
||||
echo json_encode(['success' => false, 'error' => 'Authentication required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$currentUser = $_SESSION['user'];
|
||||
|
||||
// Create database connection
|
||||
$conn = new mysqli(
|
||||
$GLOBALS['config']['DB_HOST'],
|
||||
$GLOBALS['config']['DB_USER'],
|
||||
$GLOBALS['config']['DB_PASS'],
|
||||
$GLOBALS['config']['DB_NAME']
|
||||
);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
throw new Exception("Database connection failed");
|
||||
}
|
||||
|
||||
// Get filter parameters
|
||||
$status = isset($_GET['status']) ? $_GET['status'] : null;
|
||||
$category = isset($_GET['category']) ? $_GET['category'] : null;
|
||||
$type = isset($_GET['type']) ? $_GET['type'] : null;
|
||||
$search = isset($_GET['search']) ? trim($_GET['search']) : null;
|
||||
$format = isset($_GET['format']) ? $_GET['format'] : 'csv';
|
||||
|
||||
// Initialize model
|
||||
$ticketModel = new TicketModel($conn);
|
||||
|
||||
// Get all tickets (no pagination for export)
|
||||
$result = $ticketModel->getAllTickets(1, 10000, $status, 'created_at', 'desc', $category, $type, $search);
|
||||
$tickets = $result['tickets'];
|
||||
|
||||
if ($format === 'csv') {
|
||||
// CSV Export
|
||||
header('Content-Type: text/csv; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="tickets_export_' . date('Y-m-d_His') . '.csv"');
|
||||
header('Cache-Control: no-cache, must-revalidate');
|
||||
header('Pragma: no-cache');
|
||||
|
||||
// Create output stream
|
||||
$output = fopen('php://output', 'w');
|
||||
|
||||
// Add BOM for Excel UTF-8 compatibility
|
||||
fprintf($output, chr(0xEF) . chr(0xBB) . chr(0xBF));
|
||||
|
||||
// CSV Headers
|
||||
$headers = [
|
||||
'Ticket ID',
|
||||
'Title',
|
||||
'Status',
|
||||
'Priority',
|
||||
'Category',
|
||||
'Type',
|
||||
'Created By',
|
||||
'Assigned To',
|
||||
'Created At',
|
||||
'Updated At',
|
||||
'Description'
|
||||
];
|
||||
fputcsv($output, $headers);
|
||||
|
||||
// CSV Data
|
||||
foreach ($tickets as $ticket) {
|
||||
$row = [
|
||||
$ticket['ticket_id'],
|
||||
$ticket['title'],
|
||||
$ticket['status'],
|
||||
'P' . $ticket['priority'],
|
||||
$ticket['category'],
|
||||
$ticket['type'],
|
||||
$ticket['creator_display_name'] ?? $ticket['creator_username'] ?? 'System',
|
||||
$ticket['assigned_display_name'] ?? $ticket['assigned_username'] ?? 'Unassigned',
|
||||
$ticket['created_at'],
|
||||
$ticket['updated_at'],
|
||||
$ticket['description']
|
||||
];
|
||||
fputcsv($output, $row);
|
||||
}
|
||||
|
||||
fclose($output);
|
||||
exit;
|
||||
|
||||
} elseif ($format === 'json') {
|
||||
// JSON Export
|
||||
header('Content-Type: application/json');
|
||||
header('Content-Disposition: attachment; filename="tickets_export_' . date('Y-m-d_His') . '.json"');
|
||||
|
||||
echo json_encode([
|
||||
'exported_at' => date('c'),
|
||||
'total_tickets' => count($tickets),
|
||||
'tickets' => array_map(function($t) {
|
||||
return [
|
||||
'ticket_id' => $t['ticket_id'],
|
||||
'title' => $t['title'],
|
||||
'status' => $t['status'],
|
||||
'priority' => $t['priority'],
|
||||
'category' => $t['category'],
|
||||
'type' => $t['type'],
|
||||
'description' => $t['description'],
|
||||
'created_by' => $t['creator_display_name'] ?? $t['creator_username'],
|
||||
'assigned_to' => $t['assigned_display_name'] ?? $t['assigned_username'],
|
||||
'created_at' => $t['created_at'],
|
||||
'updated_at' => $t['updated_at']
|
||||
];
|
||||
}, $tickets)
|
||||
], JSON_PRETTY_PRINT);
|
||||
exit;
|
||||
|
||||
} else {
|
||||
header('Content-Type: application/json');
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Invalid format. Use csv or json.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
header('Content-Type: application/json');
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user