Files
tinker_tickets/api/ticket_custom_fields.php
T

88 lines
2.8 KiB
PHP
Raw Normal View History

<?php
/**
* Save custom field values for a ticket.
*
* POST { ticket_id, values: { [field_id]: value, ... } }
*
* Only fields applicable to the ticket's current category (or category-less
* fields) are considered; anything else in `values` is ignored rather than
* persisted, so a value typed for a field that no longer applies (e.g. the
* category changed) can't linger as orphaned/misleading data.
*/
require_once __DIR__ . '/bootstrap.php';
require_once dirname(__DIR__) . '/models/TicketModel.php';
require_once dirname(__DIR__) . '/models/CustomFieldModel.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
apiRespond(['success' => false, 'error' => 'Method not allowed']);
}
$data = json_decode(file_get_contents('php://input'), true);
$ticketId = isset($data['ticket_id']) ? trim((string)$data['ticket_id']) : '';
$values = is_array($data['values'] ?? null) ? $data['values'] : [];
if ($ticketId === '') {
http_response_code(400);
apiRespond(['success' => false, 'error' => 'ticket_id required']);
}
$ticketModel = new TicketModel($conn);
$ticket = $ticketModel->getTicketById($ticketId);
if (!$ticket || !$ticketModel->canUserAccessTicket($ticket, $currentUser)) {
http_response_code(404);
apiRespond(['success' => false, 'error' => 'Ticket not found']);
}
$fieldModel = new CustomFieldModel($conn);
$definitions = $fieldModel->getAllDefinitions($ticket['category'], true);
$errors = [];
$toSave = [];
foreach ($definitions as $def) {
$fieldId = (int)$def['field_id'];
$raw = $values[$fieldId] ?? ($values[(string)$fieldId] ?? null);
if ($def['field_type'] === 'checkbox') {
$normalized = !empty($raw) ? '1' : '0';
} else {
$normalized = is_scalar($raw) ? trim((string)$raw) : '';
}
if (!empty($def['is_required']) && $def['field_type'] !== 'checkbox' && $normalized === '') {
$errors[] = $def['field_label'] . ' is required';
continue;
}
if ($def['field_type'] === 'select' && $normalized !== '') {
$allowedOptions = $def['field_options']['options'] ?? [];
if (!in_array($normalized, $allowedOptions, true)) {
$errors[] = $def['field_label'] . ' has an invalid selection';
continue;
}
}
if ($def['field_type'] === 'number' && $normalized !== '' && !is_numeric($normalized)) {
$errors[] = $def['field_label'] . ' must be a number';
continue;
}
$toSave[$fieldId] = $normalized;
}
if (!empty($errors)) {
http_response_code(422);
apiRespond(['success' => false, 'error' => implode('; ', $errors)]);
}
$fieldModel->setValues($ticketId, $toSave);
require_once dirname(__DIR__) . '/models/AuditLogModel.php';
(new AuditLogModel($conn))->log($userId, 'update', 'ticket', $ticketId, [
'reason' => 'custom fields updated',
]);
apiRespond(['success' => true]);