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);
?>
= h(t_default('acp.itmed.sub', 'Saved separately from items.xml - a later re-upload will not overwrite this.')) ?>= $editing ? h(t_default('acp.itmed.edit_title', 'Edit item #{id}', ['id' => $editId])) : h(t_default('acp.itmed.add_title', 'Add an item')) ?>
= t_default('acp.itmed.list_title', 'Published items') ?>