201 lines
7.7 KiB
PHP
201 lines
7.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Association Profile — POST Handlers
|
|
* Handles all form submissions from the /manage interface.
|
|
* Called via require_once in assoc_profile.php.
|
|
*/
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// POST DISPATCHER
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function assoc_handle_post() {
|
|
// Verify CSRF then dispatch to the appropriate handler.
|
|
if (!assoc_verify_csrf()) {
|
|
return '<div class="civicinfra-notice civicinfra-warning">Invalid form token.</div>';
|
|
}
|
|
|
|
$action = $_POST['assoc_action'] ?? '';
|
|
|
|
switch ($action) {
|
|
case 'save_association': return assoc_save_association();
|
|
case 'add_association': return assoc_add_association();
|
|
case 'delete_association':return assoc_delete_association();
|
|
case 'save_fields': return assoc_save_fields();
|
|
case 'add_field': return assoc_add_field();
|
|
case 'remove_field': return assoc_remove_field();
|
|
case 'export_selected': return assoc_handle_export($_POST['export_slugs'] ?? '');
|
|
case 'import_upload': return assoc_handle_import_upload();
|
|
case 'import_confirm': return assoc_handle_import_confirm();
|
|
default:
|
|
return '<div class="civicinfra-notice civicinfra-warning">Unknown action.</div>';
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ASSOCIATION HANDLERS
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function assoc_save_association() {
|
|
// Save edited fields for an existing association.
|
|
$slug = substr(strip_tags($_POST['assoc_slug'] ?? ''), 0, 128);
|
|
if (!$slug) return '<div class="civicinfra-notice civicinfra-warning">Missing slug.</div>';
|
|
|
|
$registry = assoc_load_registry();
|
|
if (!isset($registry[$slug])) {
|
|
return '<div class="civicinfra-notice civicinfra-warning">Association not found.</div>';
|
|
}
|
|
|
|
$field_map = assoc_field_map();
|
|
foreach ($field_map as $nick => $fdef) {
|
|
if (($fdef['type'] ?? '') === 'readonly') continue;
|
|
if (!isset($_POST[$nick])) continue;
|
|
$val = substr(strip_tags((string)$_POST[$nick]), 0, 1024);
|
|
if (isset($fdef['options']) && !in_array($val, $fdef['options'], true)) continue;
|
|
$registry[$slug][$nick] = $val;
|
|
}
|
|
$registry[$slug]['assoc_updated'] = date('Y-m-d');
|
|
|
|
if (assoc_write_registry($registry)) {
|
|
goaway(z_root() . '/assoc_profile/manage/assoc/' . $slug);
|
|
}
|
|
return '<div class="civicinfra-notice civicinfra-warning">Save failed. Check server logs.</div>';
|
|
}
|
|
|
|
function assoc_add_association() {
|
|
// Create a new blank association entry with the given slug.
|
|
$slug = strtolower(trim($_POST['new_slug'] ?? ''));
|
|
$slug = preg_replace('/[^a-z0-9\-]/', '', $slug);
|
|
if (!$slug) return '<div class="civicinfra-notice civicinfra-warning">Invalid slug.</div>';
|
|
|
|
$registry = assoc_load_registry();
|
|
if (isset($registry[$slug])) {
|
|
return '<div class="civicinfra-notice civicinfra-warning">Slug already exists: ' . assoc_h($slug) . '</div>';
|
|
}
|
|
|
|
$entry = assoc_blank_entry();
|
|
$entry['assoc_registered'] = date('Y-m-d');
|
|
$entry['assoc_updated'] = date('Y-m-d');
|
|
$registry[$slug] = $entry;
|
|
|
|
if (assoc_write_registry($registry)) {
|
|
goaway(z_root() . '/assoc_profile/manage/assoc/' . $slug);
|
|
}
|
|
return '<div class="civicinfra-notice civicinfra-warning">Failed to create association.</div>';
|
|
}
|
|
|
|
function assoc_delete_association() {
|
|
// Permanently remove an association from the registry.
|
|
$slug = substr(strip_tags($_POST['assoc_slug'] ?? ''), 0, 128);
|
|
if (!$slug) return '<div class="civicinfra-notice civicinfra-warning">Missing slug.</div>';
|
|
|
|
$registry = assoc_load_registry();
|
|
if (!isset($registry[$slug])) {
|
|
return '<div class="civicinfra-notice civicinfra-warning">Association not found.</div>';
|
|
}
|
|
|
|
unset($registry[$slug]);
|
|
|
|
if (assoc_write_registry($registry)) {
|
|
goaway(z_root() . '/assoc_profile/manage');
|
|
}
|
|
return '<div class="civicinfra-notice civicinfra-warning">Delete failed. Check server logs.</div>';
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// FIELD HANDLERS
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function assoc_save_fields() {
|
|
// Save label, group, and help text changes; optionally reorder groups.
|
|
$def = assoc_load_fields();
|
|
$fields = &$def['fields'];
|
|
|
|
foreach ($fields as &$f) {
|
|
$nick = $f['nickname'];
|
|
if (isset($_POST['label_' . $nick])) {
|
|
$f['label'] = substr(strip_tags($_POST['label_' . $nick]), 0, 128);
|
|
}
|
|
if (isset($_POST['group_' . $nick])) {
|
|
$f['group'] = substr(strip_tags($_POST['group_' . $nick]), 0, 64);
|
|
}
|
|
if (isset($_POST['help_' . $nick])) {
|
|
$f['help'] = substr(strip_tags($_POST['help_' . $nick]), 0, 256);
|
|
}
|
|
}
|
|
unset($f);
|
|
|
|
if (!empty($_POST['groups'])) {
|
|
$groups = array_map(function($g) { return substr(strip_tags($g), 0, 64); },
|
|
explode("\n", $_POST['groups']));
|
|
$def['groups'] = array_values(array_filter(array_map('trim', $groups)));
|
|
}
|
|
|
|
if (assoc_write_fields($def)) {
|
|
goaway(z_root() . '/assoc_profile/manage/fields');
|
|
}
|
|
return '<div class="civicinfra-notice civicinfra-warning">Save failed.</div>';
|
|
}
|
|
|
|
function assoc_add_field() {
|
|
// Add a new field definition and backfill all existing associations.
|
|
$nick = strtolower(preg_replace('/[^a-z0-9_]/', '', $_POST['new_nickname'] ?? ''));
|
|
$label = substr(strip_tags($_POST['new_label'] ?? ''), 0, 128);
|
|
$type = in_array($_POST['new_type'] ?? '', ['text','select','readonly']) ? $_POST['new_type'] : 'text';
|
|
$group = substr(strip_tags($_POST['new_group'] ?? ''), 0, 64);
|
|
$default = substr(strip_tags($_POST['new_default'] ?? ''), 0, 128);
|
|
$help = substr(strip_tags($_POST['new_help'] ?? ''), 0, 256);
|
|
|
|
if (!$nick || !$label) {
|
|
return '<div class="civicinfra-notice civicinfra-warning">Nickname and label are required.</div>';
|
|
}
|
|
|
|
$def = assoc_load_fields();
|
|
foreach ($def['fields'] as $f) {
|
|
if ($f['nickname'] === $nick) {
|
|
return '<div class="civicinfra-notice civicinfra-warning">Field already exists: ' . assoc_h($nick) . '</div>';
|
|
}
|
|
}
|
|
|
|
$new_field = [
|
|
'nickname' => $nick,
|
|
'label' => $label,
|
|
'type' => $type,
|
|
'group' => $group,
|
|
'default' => $default,
|
|
'required' => false,
|
|
'help' => $help,
|
|
];
|
|
|
|
if ($type === 'select' && !empty($_POST['new_options'])) {
|
|
$opts = array_map('trim', explode("\n", $_POST['new_options']));
|
|
$new_field['options'] = array_values(array_filter($opts));
|
|
}
|
|
|
|
$def['fields'][] = $new_field;
|
|
assoc_write_fields($def);
|
|
|
|
$registry = assoc_backfill_all($new_field);
|
|
assoc_write_registry($registry);
|
|
|
|
goaway(z_root() . '/assoc_profile/manage/fields');
|
|
}
|
|
|
|
function assoc_remove_field() {
|
|
// Remove a field from the definition and from all registry entries.
|
|
$nick = preg_replace('/[^a-z0-9_]/', '', $_POST['remove_nickname'] ?? '');
|
|
if (!$nick) return '<div class="civicinfra-notice civicinfra-warning">Missing nickname.</div>';
|
|
|
|
$def = assoc_load_fields();
|
|
$def['fields'] = array_values(array_filter($def['fields'], function($f) use ($nick) {
|
|
return $f['nickname'] !== $nick;
|
|
}));
|
|
assoc_write_fields($def);
|
|
|
|
$registry = assoc_remove_field_from_all($nick);
|
|
assoc_write_registry($registry);
|
|
|
|
goaway(z_root() . '/assoc_profile/manage/fields');
|
|
}
|