231 lines
6.8 KiB
PHP
231 lines
6.8 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* CustomFieldModel - Manages custom field definitions and values
|
||
|
|
*/
|
||
|
|
|
||
|
|
class CustomFieldModel {
|
||
|
|
private $conn;
|
||
|
|
|
||
|
|
public function __construct($conn) {
|
||
|
|
$this->conn = $conn;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========================================
|
||
|
|
// Field Definitions
|
||
|
|
// ========================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get all field definitions
|
||
|
|
*/
|
||
|
|
public function getAllDefinitions($category = null, $activeOnly = true) {
|
||
|
|
$sql = "SELECT * FROM custom_field_definitions WHERE 1=1";
|
||
|
|
$params = [];
|
||
|
|
$types = '';
|
||
|
|
|
||
|
|
if ($activeOnly) {
|
||
|
|
$sql .= " AND is_active = 1";
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($category !== null) {
|
||
|
|
$sql .= " AND (category = ? OR category IS NULL)";
|
||
|
|
$params[] = $category;
|
||
|
|
$types .= 's';
|
||
|
|
}
|
||
|
|
|
||
|
|
$sql .= " ORDER BY display_order ASC, field_id ASC";
|
||
|
|
|
||
|
|
if (!empty($params)) {
|
||
|
|
$stmt = $this->conn->prepare($sql);
|
||
|
|
$stmt->bind_param($types, ...$params);
|
||
|
|
$stmt->execute();
|
||
|
|
$result = $stmt->get_result();
|
||
|
|
} else {
|
||
|
|
$result = $this->conn->query($sql);
|
||
|
|
}
|
||
|
|
|
||
|
|
$fields = [];
|
||
|
|
while ($row = $result->fetch_assoc()) {
|
||
|
|
if ($row['field_options']) {
|
||
|
|
$row['field_options'] = json_decode($row['field_options'], true);
|
||
|
|
}
|
||
|
|
$fields[] = $row;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isset($stmt)) {
|
||
|
|
$stmt->close();
|
||
|
|
}
|
||
|
|
|
||
|
|
return $fields;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get a single field definition
|
||
|
|
*/
|
||
|
|
public function getDefinition($fieldId) {
|
||
|
|
$sql = "SELECT * FROM custom_field_definitions WHERE field_id = ?";
|
||
|
|
$stmt = $this->conn->prepare($sql);
|
||
|
|
$stmt->bind_param('i', $fieldId);
|
||
|
|
$stmt->execute();
|
||
|
|
$result = $stmt->get_result();
|
||
|
|
$row = $result->fetch_assoc();
|
||
|
|
$stmt->close();
|
||
|
|
|
||
|
|
if ($row && $row['field_options']) {
|
||
|
|
$row['field_options'] = json_decode($row['field_options'], true);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $row;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Create a new field definition
|
||
|
|
*/
|
||
|
|
public function createDefinition($data) {
|
||
|
|
$options = null;
|
||
|
|
if (isset($data['field_options']) && !empty($data['field_options'])) {
|
||
|
|
$options = json_encode($data['field_options']);
|
||
|
|
}
|
||
|
|
|
||
|
|
$sql = "INSERT INTO custom_field_definitions
|
||
|
|
(field_name, field_label, field_type, field_options, category, is_required, display_order, is_active)
|
||
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||
|
|
|
||
|
|
$stmt = $this->conn->prepare($sql);
|
||
|
|
$stmt->bind_param('sssssiii',
|
||
|
|
$data['field_name'],
|
||
|
|
$data['field_label'],
|
||
|
|
$data['field_type'],
|
||
|
|
$options,
|
||
|
|
$data['category'],
|
||
|
|
$data['is_required'] ?? 0,
|
||
|
|
$data['display_order'] ?? 0,
|
||
|
|
$data['is_active'] ?? 1
|
||
|
|
);
|
||
|
|
|
||
|
|
if ($stmt->execute()) {
|
||
|
|
$id = $this->conn->insert_id;
|
||
|
|
$stmt->close();
|
||
|
|
return ['success' => true, 'field_id' => $id];
|
||
|
|
}
|
||
|
|
|
||
|
|
$error = $stmt->error;
|
||
|
|
$stmt->close();
|
||
|
|
return ['success' => false, 'error' => $error];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update a field definition
|
||
|
|
*/
|
||
|
|
public function updateDefinition($fieldId, $data) {
|
||
|
|
$options = null;
|
||
|
|
if (isset($data['field_options']) && !empty($data['field_options'])) {
|
||
|
|
$options = json_encode($data['field_options']);
|
||
|
|
}
|
||
|
|
|
||
|
|
$sql = "UPDATE custom_field_definitions SET
|
||
|
|
field_name = ?, field_label = ?, field_type = ?, field_options = ?,
|
||
|
|
category = ?, is_required = ?, display_order = ?, is_active = ?
|
||
|
|
WHERE field_id = ?";
|
||
|
|
|
||
|
|
$stmt = $this->conn->prepare($sql);
|
||
|
|
$stmt->bind_param('sssssiiiii',
|
||
|
|
$data['field_name'],
|
||
|
|
$data['field_label'],
|
||
|
|
$data['field_type'],
|
||
|
|
$options,
|
||
|
|
$data['category'],
|
||
|
|
$data['is_required'] ?? 0,
|
||
|
|
$data['display_order'] ?? 0,
|
||
|
|
$data['is_active'] ?? 1,
|
||
|
|
$fieldId
|
||
|
|
);
|
||
|
|
|
||
|
|
$success = $stmt->execute();
|
||
|
|
$stmt->close();
|
||
|
|
return ['success' => $success];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Delete a field definition
|
||
|
|
*/
|
||
|
|
public function deleteDefinition($fieldId) {
|
||
|
|
// This will cascade delete all values due to FK constraint
|
||
|
|
$sql = "DELETE FROM custom_field_definitions WHERE field_id = ?";
|
||
|
|
$stmt = $this->conn->prepare($sql);
|
||
|
|
$stmt->bind_param('i', $fieldId);
|
||
|
|
$success = $stmt->execute();
|
||
|
|
$stmt->close();
|
||
|
|
return ['success' => $success];
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========================================
|
||
|
|
// Field Values
|
||
|
|
// ========================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get all field values for a ticket
|
||
|
|
*/
|
||
|
|
public function getValuesForTicket($ticketId) {
|
||
|
|
$sql = "SELECT cfv.*, cfd.field_name, cfd.field_label, cfd.field_type, cfd.field_options
|
||
|
|
FROM custom_field_values cfv
|
||
|
|
JOIN custom_field_definitions cfd ON cfv.field_id = cfd.field_id
|
||
|
|
WHERE cfv.ticket_id = ?
|
||
|
|
ORDER BY cfd.display_order ASC";
|
||
|
|
|
||
|
|
$stmt = $this->conn->prepare($sql);
|
||
|
|
$stmt->bind_param('s', $ticketId);
|
||
|
|
$stmt->execute();
|
||
|
|
$result = $stmt->get_result();
|
||
|
|
|
||
|
|
$values = [];
|
||
|
|
while ($row = $result->fetch_assoc()) {
|
||
|
|
if ($row['field_options']) {
|
||
|
|
$row['field_options'] = json_decode($row['field_options'], true);
|
||
|
|
}
|
||
|
|
$values[$row['field_name']] = $row;
|
||
|
|
}
|
||
|
|
|
||
|
|
$stmt->close();
|
||
|
|
return $values;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set a field value for a ticket (insert or update)
|
||
|
|
*/
|
||
|
|
public function setValue($ticketId, $fieldId, $value) {
|
||
|
|
$sql = "INSERT INTO custom_field_values (ticket_id, field_id, field_value)
|
||
|
|
VALUES (?, ?, ?)
|
||
|
|
ON DUPLICATE KEY UPDATE field_value = VALUES(field_value), updated_at = CURRENT_TIMESTAMP";
|
||
|
|
|
||
|
|
$stmt = $this->conn->prepare($sql);
|
||
|
|
$stmt->bind_param('sis', $ticketId, $fieldId, $value);
|
||
|
|
$success = $stmt->execute();
|
||
|
|
$stmt->close();
|
||
|
|
return ['success' => $success];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set multiple field values for a ticket
|
||
|
|
*/
|
||
|
|
public function setValues($ticketId, $values) {
|
||
|
|
$results = [];
|
||
|
|
foreach ($values as $fieldId => $value) {
|
||
|
|
$results[$fieldId] = $this->setValue($ticketId, $fieldId, $value);
|
||
|
|
}
|
||
|
|
return $results;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Delete all field values for a ticket
|
||
|
|
*/
|
||
|
|
public function deleteValuesForTicket($ticketId) {
|
||
|
|
$sql = "DELETE FROM custom_field_values WHERE ticket_id = ?";
|
||
|
|
$stmt = $this->conn->prepare($sql);
|
||
|
|
$stmt->bind_param('s', $ticketId);
|
||
|
|
$success = $stmt->execute();
|
||
|
|
$stmt->close();
|
||
|
|
return ['success' => $success];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
?>
|