editable {key, value} rows. */ function itmed_attr_rows(array $attributes): array { $rows = array(); foreach ($attributes as $key => $value) { $rows[] = array('key' => (string)$key, 'value' => is_scalar($value) ? (string)$value : ''); } return $rows; } /** Posted {key, value} rows -> attribute map, blank/duplicate keys dropped. */ function itmed_attr_map_from_post(array $rowsRaw): array { $map = array(); foreach ($rowsRaw as $row) { if (!is_array($row)) continue; $key = trim((string)($row['key'] ?? '')); if ($key === '') continue; $map[$key] = trim((string)($row['value'] ?? '')); } return $map; } $items = serverdata_load('items'); $items = is_array($items) ? $items : array(); if (!$items && !serverdata_override_table_exists()) { acp_flash_error(t_default('acp.itmed.no_data', 'Upload an items.xml on Server Info first - there is nothing published to edit yet.')); acp_redirect('serverinfo'); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $adminName = (string)($GLOBALS['user_data']['name'] ?? ''); $action = (string)($_POST['itmed_action'] ?? ''); if ($action === 'save') { $id = intv($_POST['id'] ?? 0); $name = trim((string)($_POST['name'] ?? '')); if ($id <= 0 || $name === '') { acp_flash_error(t_default('acp.itmed.missing_fields', 'ID and name are required.')); acp_redirect('items_editor'); } $record = array( 'id' => (string)$id, 'name' => $name, 'attributes' => itmed_attr_map_from_post((array)($_POST['attr'] ?? array())), ); if (serverdata_override_set('items', ITMED_TYPE . ':' . $id, $record, $adminName)) { acp_log('serverdata.item_save', $name, ['type' => ITMED_TYPE, 'id' => $id]); acp_flash_success(t_default('acp.itmed.saved', 'Item #{id} saved.', ['id' => $id])); } else { acp_flash_error(t_default('acp.itmed.save_failed', 'Could not save - run the pending database migration first (Admin Panel > Migrations).')); } acp_redirect('items_editor'); } if ($action === 'delete') { $id = intv($_POST['id'] ?? 0); if (serverdata_override_delete('items', ITMED_TYPE . ':' . $id, $adminName)) { acp_log('serverdata.item_delete', '#' . $id, ['type' => ITMED_TYPE, 'id' => $id]); acp_flash_success(t_default('acp.itmed.removed', 'Item #{id} removed.', ['id' => $id])); } else { acp_flash_error(t_default('acp.itmed.remove_failed', 'Could not remove that item.')); } acp_redirect('items_editor'); } } $editId = intv($_GET['edit'] ?? 0); $editing = null; if ($editId > 0 && isset($items[ITMED_TYPE][(string)$editId])) { $editing = $items[ITMED_TYPE][(string)$editId]; } $attrRows = itmed_attr_rows($editing['attributes'] ?? array()); $attrColumns = array( 'key' => array('label' => t_default('acp.itmed.col_attr_key', 'Attribute'), 'type' => 'text'), 'value' => array('label' => t_default('acp.itmed.col_attr_value', 'Value'), 'type' => 'text'), ); $list = $items[ITMED_TYPE] ?? array(); ksort($list, SORT_NUMERIC); ?>

$editId])) : h(t_default('acp.itmed.add_title', 'Add an item')) ?>

required>
$row): ?> $colDef): ?>

8): ?>
$rec): ?>
ID