prefix; kc_admin_tabs('kc_teilnehmer'); // Alle Wahlen + Workshops für Dropdowns und Validierung $all_wahlen = $wpdb->get_results("SELECT id, name, anzahl_einheiten FROM {$prefix}kc_wahlen WHERE deleted=0 ORDER BY id DESC"); $all_workshops = $wpdb->get_results("SELECT id, name FROM {$prefix}kc_workshops ORDER BY name"); // Map of wahl id => name for quick lookup $wahl_name_map = []; if (!empty($all_wahlen)) { foreach ($all_wahlen as $w) { $wahl_name_map[intval($w->id)] = $w->name; } } // Map of workshop id => name for quick lookup in overview $workshops_map = []; if (!empty($all_workshops)) { foreach ($all_workshops as $ws) { $workshops_map[intval($ws->id)] = $ws->name; } } // CSV-Export (alle Teilnehmer oder gefiltert nach Wahl) if (isset($_GET['export_csv']) && current_user_can('manage_options')) { $export_wahl_id = isset($_GET['wahl_id']) ? intval($_GET['wahl_id']) : 0; $sql = "SELECT * FROM {$prefix}kc_teilnehmer"; if ($export_wahl_id > 0) { $sql .= $wpdb->prepare(" WHERE wahl_id=%d", $export_wahl_id); } $sql .= " ORDER BY wahl_id, phase, nachname, vorname"; $export_rows = $wpdb->get_results($sql); $filename_suffix = $export_wahl_id > 0 ? '_wahl_'.$export_wahl_id : '_alle'; header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename="kc_teilnehmer'.$filename_suffix.'.csv"'); echo "\xEF\xBB\xBF"; $output = fopen('php://output', 'w'); $delimiter = ';'; fputcsv($output, ['Vorname','Nachname','Wahl','Phase','Wunsch 1','Wunsch 2','Wunsch 3'], $delimiter); foreach ($export_rows as $tn) { $w1_id = intval($tn->wunsch1); $w2_id = intval($tn->wunsch2); $w3_id = intval($tn->wunsch3); $w1_disp = $w1_id && isset($workshops_map[$w1_id]) ? $workshops_map[$w1_id] : ($w1_id ? strval($w1_id) : ''); $w2_disp = $w2_id && isset($workshops_map[$w2_id]) ? $workshops_map[$w2_id] : ($w2_id ? strval($w2_id) : ''); $w3_disp = $w3_id && isset($workshops_map[$w3_id]) ? $workshops_map[$w3_id] : ($w3_id ? strval($w3_id) : ''); $wahl_name = isset($wahl_name_map[intval($tn->wahl_id)]) ? $wahl_name_map[intval($tn->wahl_id)] : ''; $vorname = preg_replace('/<[^>]*>/', '', $tn->vorname); $nachname = preg_replace('/<[^>]*>/', '', $tn->nachname); $wahl_name_clean = preg_replace('/<[^>]*>/', '', $wahl_name); $w1_clean = preg_replace('/<[^>]*>/', '', $w1_disp); $w2_clean = preg_replace('/<[^>]*>/', '', $w2_disp); $w3_clean = preg_replace('/<[^>]*>/', '', $w3_disp); fputcsv($output, [ $vorname, $nachname, $wahl_name_clean, intval($tn->phase), $w1_clean, $w2_clean, $w3_clean ], $delimiter); } fclose($output); exit; } // Build map of wahl -> phases + workshops (for JS) $wahl_map = []; foreach($all_wahlen as $w) { $wahl_map[intval($w->id)] = ['phases' => max(1,intval($w->anzahl_einheiten)), 'workshops' => []]; } if (!empty($all_workshops)) { foreach($all_workshops as $ws) { $ww = $wpdb->get_col($wpdb->prepare("SELECT wahl_id FROM {$prefix}kc_wahl_workshops WHERE workshop_id=%d", $ws->id)); if (!empty($ww)) { foreach($ww as $wid) { if (isset($wahl_map[intval($wid)])) { $wahl_map[intval($wid)]['workshops'][] = ['id'=>intval($ws->id),'name'=>$ws->name]; } } } } } // Teilnehmer l�schen if (isset($_GET['delete_teilnehmer'])) { $tid = intval($_GET['delete_teilnehmer']); $wpdb->delete("{$prefix}kc_teilnehmer", ['id' => $tid]); echo '
Teilnehmer gel�scht!
'; } // Teilnehmer speichern (neu/�ndern) if (isset($_POST['kc_teilnehmer_save'])) { // sanitize inputs $vorname = sanitize_text_field($_POST['vorname']); $nachname = sanitize_text_field($_POST['nachname']); $wahl_id_post = intval($_POST['wahl_id']); $phase_post = intval($_POST['phase']); $w1 = intval($_POST['wunsch1']); $w2 = intval($_POST['wunsch2']); $w3 = intval($_POST['wunsch3']); // Server-side validation: duplicate name in same Wahl (exclude self on edit) $norm_v = mb_strtolower(trim($vorname)); $norm_n = mb_strtolower(trim($nachname)); if (!empty($_POST['tid'])) { $exclude_id = intval($_POST['tid']); $exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$prefix}kc_teilnehmer WHERE LOWER(TRIM(vorname))=%s AND LOWER(TRIM(nachname))=%s AND wahl_id=%d AND id<>%d", $norm_v, $norm_n, $wahl_id_post, $exclude_id)); } else { $exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$prefix}kc_teilnehmer WHERE LOWER(TRIM(vorname))=%s AND LOWER(TRIM(nachname))=%s AND wahl_id=%d", $norm_v, $norm_n, $wahl_id_post)); } if ($exists && $exists > 0) { echo '
Diese Kombination aus Vorname und Nachname existiert bereits für diese Wahl.
'; } else { // validate phase within wahl $wahl_row = $wpdb->get_row($wpdb->prepare("SELECT anzahl_einheiten FROM {$prefix}kc_wahlen WHERE id=%d", $wahl_id_post)); $max_ph = $wahl_row ? max(1,intval($wahl_row->anzahl_einheiten)) : 1; if ($phase_post < 1 || $phase_post > $max_ph) { echo '
Ungültige Phase für die gewählte Wahl.
'; } else { // validate that selected workshops belong to the chosen wahl (if mapping exists) $valid_ws = []; $ww_rows = $wpdb->get_col($wpdb->prepare("SELECT workshop_id FROM {$prefix}kc_wahl_workshops WHERE wahl_id=%d", $wahl_id_post)); if (!empty($ww_rows)) foreach($ww_rows as $r) $valid_ws[] = intval($r); // if mapping exists, enforce membership $check_membership = function($wid) use ($valid_ws) { if (empty($valid_ws)) return true; // no mapping -> allow return in_array(intval($wid), $valid_ws); }; if (!$check_membership($w1) || !$check_membership($w2) || !$check_membership($w3)) { echo '
Einer oder mehrere ausgewählte Workshops gehören nicht zur gewählten Wahl.
'; } else { $data = [ 'vorname' => $vorname, 'nachname' => $nachname, 'wahl_id' => $wahl_id_post, 'phase' => $phase_post, 'wunsch1' => $w1, 'wunsch2' => $w2, 'wunsch3' => $w3 ]; if (!empty($_POST['tid'])) { $wpdb->update("{$prefix}kc_teilnehmer", $data, ['id'=>intval($_POST['tid'])]); echo '
Teilnehmer aktualisiert!
'; } else { $wpdb->insert("{$prefix}kc_teilnehmer", $data); echo '
Teilnehmer angelegt!
'; } } } } } // Teilnehmer bearbeiten if (isset($_GET['edit_teilnehmer'])) { $tid = intval($_GET['edit_teilnehmer']); $tn = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$prefix}kc_teilnehmer WHERE id=%d", $tid)); echo '
'; echo '

Teilnehmer bearbeiten

'; echo '
'; echo ''; echo ''; echo ''; // Wahl select echo ''; echo ''; // Phase select (fallback content) echo ''; echo ''; // Wunsch selects for ($k=1;$k<=3;$k++){ $cur = intval($tn->{'wunsch'.$k}); echo ''; echo ''; } echo ''; echo 'Abbrechen'; echo '
'; // Provide JS map and init JS: restrict phases/workshops based on Wahl and init Select2 echo ''; echo ''; echo '
'; return; } // Neuer Teilnehmer anlegen if (isset($_GET['new'])) { echo '
'; echo '

Neuen Teilnehmer anlegen

'; echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; for ($k=1;$k<=3;$k++){ echo ''; echo ''; } echo ''; echo 'Abbrechen'; echo '
'; // Init Select2 for nicer selects if available echo ''; echo '
'; return; } // Übersicht // Map für Wahl-ID => Name ist bereits oben aufgebaut echo '
'; echo '

Alle Teilnehmer

'; echo 'CSV Export'; echo '+ Neuer Teilnehmer'; // Wahl-Filter-Buttons sortiert nach KC1, KC2, KC3, dann Rest $kc_buttons = []; $rest_buttons = []; foreach($all_wahlen as $w) { $name = strtoupper($w->name); if ($name === 'KC1' || $name === 'KC2' || $name === 'KC3') { $kc_buttons[$name] = $w; } else { $rest_buttons[] = $w; } } echo '
' .''; echo ''; foreach(["KC1","KC2","KC3"] as $kc) { if(isset($kc_buttons[$kc])) { $w = $kc_buttons[$kc]; echo ''; } } foreach($rest_buttons as $w) { echo ''; } echo 'Alle anzeigen'; echo '
'; // Platzhalter für Phasen-Filter echo ''; // Teilnehmer laden und gruppieren nach Wahl und Phase $teilnehmer = $wpdb->get_results("SELECT * FROM {$prefix}kc_teilnehmer ORDER BY wahl_id, phase, nachname, vorname"); $gruppen = []; foreach ($teilnehmer as $tn) { $wid = intval($tn->wahl_id); $ph = intval($tn->phase); $gruppen[$wid][$ph][] = $tn; } foreach ($gruppen as $wid => $phasen) { $wahl_disp = isset($wahl_name_map[$wid]) ? esc_html($wahl_name_map[$wid]) : $wid; $csv_wahl_url = add_query_arg([ 'page' => 'kc_teilnehmer', 'export_csv' => 1, 'wahl_id' => intval($wid) ], admin_url('admin.php')); // Gesamtanzahl Teilnehmer für diese Wahl berechnen $gesamt = 0; foreach ($phasen as $tns) $gesamt += count($tns); echo '
'; echo ''. $wahl_disp . ' (' . $gesamt . ' TN)'; echo '
'; echo 'CSV Export dieser Wahl'; echo '
'; foreach ($phasen as $phase => $tns) { echo '
'; echo 'Phase '.intval($phase).' ('.count($tns).' TN)'; echo ''; echo ''; foreach ($tns as $tn) { $w1_id = intval($tn->wunsch1); $w2_id = intval($tn->wunsch2); $w3_id = intval($tn->wunsch3); $w1_disp = $w1_id && isset($workshops_map[$w1_id]) ? esc_html($workshops_map[$w1_id]) : ($w1_id ? intval($w1_id) : 'Keine'); $w2_disp = $w2_id && isset($workshops_map[$w2_id]) ? esc_html($workshops_map[$w2_id]) : ($w2_id ? intval($w2_id) : 'Keine'); $w3_disp = $w3_id && isset($workshops_map[$w3_id]) ? esc_html($workshops_map[$w3_id]) : ($w3_id ? intval($w3_id) : 'Keine'); $wahl_disp = isset($wahl_name_map[intval($tn->wahl_id)]) ? esc_html($wahl_name_map[intval($tn->wahl_id)]) : intval($tn->wahl_id); echo ""; } echo '
VornameNachnameWahlPhaseWunsch 1Wunsch 2Wunsch 3Aktion
".esc_html($tn->vorname)." ".esc_html($tn->nachname)." ".$wahl_disp." ".intval($tn->phase)." ".$w1_disp." ".$w2_disp." ".$w3_disp." Bearbeiten Löschen
'; echo '
'; } echo '
'; } // JS für Wahl- und Phasen-Filter echo ''; echo ''; echo '
'; } ?>