Files
Workshop-Wahlen/includes/frontend-form.php

351 lines
16 KiB
PHP

<?php
add_shortcode('konficastle_workshopwahl', function($atts) {
$atts = shortcode_atts(['wahl'=>null], $atts);
$wahl_id = intval($atts['wahl']);
global $wpdb;
// Optionales Debug-Ausgabe-Fragment (standardmäßig leer, um Warnungen zu vermeiden)
$debug_output = '';
$wahl = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}kc_wahlen WHERE id=%d", $wahl_id));
if(!$wahl || !$wahl->freigegeben) {
// Keine Fehlermeldung im Frontend anzeigen; Formular ausblenden
return '';
}
// Ermittle erlaubte Workshops pro Phase für diese Wahl.
$phasen = (int)$wahl->anzahl_einheiten;
$workshops_by_phase = [];
$mapping_candidates = [
"{$wpdb->prefix}kc_wahl_workshops",
"{$wpdb->prefix}kc_workshop_wahlen",
"{$wpdb->prefix}kc_wahl_workshop"
];
$mapping_table = null;
foreach ($mapping_candidates as $t) {
$found = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $t));
if ($found === $t) { $mapping_table = $t; break; }
}
if ($mapping_table) {
$has_phase_col = (bool) $wpdb->get_var("SHOW COLUMNS FROM {$mapping_table} LIKE 'phase'");
for ($phase = 1; $phase <= $phasen; $phase++) {
if ($has_phase_col) {
$workshops_by_phase[$phase] = $wpdb->get_results($wpdb->prepare(
"SELECT w.* FROM {$wpdb->prefix}kc_workshops w
JOIN {$mapping_table} m ON w.id = m.workshop_id
WHERE m.wahl_id = %d AND m.phase = %d
ORDER BY w.name",
$wahl_id, $phase
));
} else {
$workshops_by_phase[$phase] = $wpdb->get_results($wpdb->prepare(
"SELECT w.* FROM {$wpdb->prefix}kc_workshops w
JOIN {$mapping_table} m ON w.id = m.workshop_id
WHERE m.wahl_id = %d
ORDER BY w.name",
$wahl_id
));
}
}
} else {
$all = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}kc_workshops ORDER BY name");
for ($phase = 1; $phase <= $phasen; $phase++) $workshops_by_phase[$phase] = $all;
}
// POST Verarbeitung
$error_message = null;
$success_redirect = false;
if($_SERVER['REQUEST_METHOD']=='POST' && isset($_POST['kc_workshop_submit'])) {
//$debug_output .= '<div style="background:lime;padding:10px;">POST WIRD VERARBEITET!</div>';
if(empty($_POST['vorname']) || empty($_POST['nachname'])) {
$error_message = 'Bitte Vor- und Nachname ausfüllen.';
} else {
$inserted_ids = [];
$vorname = sanitize_text_field($_POST['vorname']);
$nachname = sanitize_text_field($_POST['nachname']);
$norm_v = mb_strtolower(trim($vorname));
$norm_n = mb_strtolower(trim($nachname));
// Duplikatsprüfung
$exists = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$wpdb->prefix}kc_teilnehmer WHERE LOWER(TRIM(vorname))=%s AND LOWER(TRIM(nachname))=%s AND wahl_id=%d",
$norm_v, $norm_n, $wahl_id
));
if ($exists && $exists > 0) {
$error_message = 'Diese Kombination aus Vorname und Nachname existiert bereits für diese Wahl.';
} else {
// Validierung und Insert
$validation_passed = true;
for ($phase = 1; $phase <= $phasen; $phase++) {
$allowed = array_map('intval', wp_list_pluck($workshops_by_phase[$phase] ?? [], 'id'));
$w1 = intval($_POST["phase{$phase}_wunsch1"] ?? 0);
$w2 = intval($_POST["phase{$phase}_wunsch2"] ?? 0);
$w3 = intval($_POST["phase{$phase}_wunsch3"] ?? 0);
if (empty($allowed) || !in_array($w1, $allowed, true) || !in_array($w2, $allowed, true) || !in_array($w3, $allowed, true)) {
$error_message = "Ungültige Workshop-Auswahl für Phase {$phase}.";
$validation_passed = false;
break;
}
// Ensure the three wishes in this phase are not duplicates
$selected = [$w1, $w2, $w3];
if (count(array_unique($selected)) !== count($selected)) {
$error_message = "Bitte wähle in Phase {$phase} drei verschiedene Workshops (keine Duplikate).";
$validation_passed = false;
break;
}
}
if ($validation_passed) {
for ($phase = 1; $phase <= $phasen; $phase++) {
$w1 = intval($_POST["phase{$phase}_wunsch1"]);
$w2 = intval($_POST["phase{$phase}_wunsch2"]);
$w3 = intval($_POST["phase{$phase}_wunsch3"]);
$result = $wpdb->insert("{$wpdb->prefix}kc_teilnehmer", [
'vorname' => $vorname,
'nachname' => $nachname,
'wahl_id' => $wahl_id,
'phase' => $phase,
'wunsch1' => $w1,
'wunsch2' => $w2,
'wunsch3' => $w3,
'deleted' => 0
]);
if ($result === false) {
$error_message = 'Datenbankfehler: ' . $wpdb->last_error;
break;
} else {
$inserted_ids[] = intval($wpdb->insert_id);
}
}
if (empty($error_message)) {
// Cookie setzen
$cookie_name = 'kc_my_part_' . intval($wahl_id);
$existing = [];
if (!empty($_COOKIE[$cookie_name])) {
$dec = json_decode(stripslashes($_COOKIE[$cookie_name]), true);
if (is_array($dec)) $existing = array_map('intval', $dec);
}
$all_ids = array_values(array_unique(array_merge($existing, $inserted_ids)));
@setcookie($cookie_name, wp_json_encode($all_ids), time() + 30*24*3600, '/');
// Erfolg
$success_redirect = true;
}
}
}
}
}
ob_start();
?>
<style>
.kc-form-container {background:#f8fbe7; border-left:8px solid #b6d333; max-width:600px; margin:40px auto; padding:32px 28px; border-radius:14px; box-shadow:0 2px 8px #b6d33322;}
.kc-form-container h2 {margin-top:0; font-size:2em; font-weight:700;}
.kc-form-container label {font-weight:600;}
.kc-form-row {margin-bottom:20px;}
.kc-form-row input[type="text"], .kc-form-row select {
width:100%; padding:10px 12px; border-radius:7px; border:1.2px solid #aac484; background:#fafcf6; font-size:1.09em;
transition:border 0.17s;
}
.kc-form-row input[type="text"]:focus, .kc-form-row select:focus {border:1.8px solid #b6d333;}
.kc-form-row input[type="submit"] {
background:#326dd2; color:#fff; font-weight:600; font-size:1.15em;
padding:11px 30px; border:0; border-radius:8px; cursor:pointer; margin-top:5px; box-shadow:0 2px 6px #aac48422;
}
.kc-form-row input[type="submit"]:hover {background:#2559a2;}
.kc-required {color:#d82626; font-weight:bold;}
.kc-success-msg {color:#21952c; background:#e3f7e4; padding:16px 20px; border-radius:8px; font-weight:600; margin-bottom:15px; text-align:center;}
.kc-error-msg {color:#a80000; background:#ffeaea; padding:16px 20px; border-radius:8px; font-weight:600; margin-bottom:15px; text-align:center;}
@media (max-width: 700px) {.kc-form-container {padding:17px 7px;}}
</style>
<?php echo $debug_output; ?>
<div class="kc-form-container">
<h2><?= esc_html($wahl->name) ?></h2>
<?php if($wahl->beschreibung): ?>
<div style="margin-bottom:12px; color:#3b3b3b;"><?= nl2br(esc_html($wahl->beschreibung)) ?></div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="kc-error-msg"><?= esc_html($error_message) ?></div>
<?php endif; ?>
<?php if ($success_redirect): ?>
<div class="kc-success-msg">
Danke! Deine Wünsche wurden gespeichert.<br>
Erfolgreich eingefügte IDs: <?= implode(', ', $inserted_ids) ?>
</div>
<?php else: ?>
<form method="post" autocomplete="off">
<input type="hidden" name="kc_workshop_submit" value="1">
<div class="kc-form-row">
<label>Vorname <span class="kc-required">*</span></label>
<input type="text" name="vorname" required>
</div>
<div class="kc-form-row">
<label>Nachname <span class="kc-required">*</span></label>
<input type="text" name="nachname" required>
</div>
<?php for($phase=1; $phase<=$phasen; $phase++): ?>
<div class="kc-form-row"><b>
<?php if($phasen>1): ?>Phase <?= $phase ?><?php endif; ?>
</b></div>
<?php for($w=1; $w<=3; $w++): ?>
<div class="kc-form-row">
<label>
<span style="font-weight:bold;color:#2355be;"><?= $phase ?>. Phase; <?= $w ?>. Wunsch</span> <span class="kc-required">*</span>
</label>
<select name="phase<?= $phase ?>_wunsch<?= $w ?>" required>
<option value="">Bitte wähle einen Workshop aus</option>
<?php foreach(($workshops_by_phase[$phase] ?? []) as $ws): ?>
<option value="<?= esc_attr($ws->id) ?>"><?= esc_html($ws->name) ?></option>
<?php endforeach; ?>
</select>
</div>
<?php endfor; ?>
<script>
(function(){
// Disable already selected options within this phase and validate on submit
var phase = <?= json_encode($phase) ?>;
document.addEventListener('DOMContentLoaded', function(){
var selector = 'select[name^="phase' + phase + '_wunsch"]';
var selects = Array.prototype.slice.call(document.querySelectorAll(selector));
if (!selects.length) return;
function refresh(){
var values = selects.map(function(s){ return s.value; }).filter(function(v){ return v !== ''; });
selects.forEach(function(s){
Array.prototype.slice.call(s.options).forEach(function(opt){
if (opt.value === '') { opt.disabled = false; return; }
// disable option if selected in another select
var usedElsewhere = values.indexOf(opt.value) !== -1 && s.value !== opt.value;
opt.disabled = usedElsewhere;
});
});
}
selects.forEach(function(s){ s.addEventListener('change', refresh); });
// initial
refresh();
// Add submit-time validation to prevent duplicates (safety)
var form = selects[0] && selects[0].form;
if (form) {
form.addEventListener('submit', function(e){
var vals = selects.map(function(s){ return s.value; }).filter(function(v){ return v !== ''; });
var unique = vals.filter(function(v,i,a){ return a.indexOf(v) === i; });
if (vals.length !== unique.length) {
e.preventDefault();
alert('Bitte wähle in Phase ' + phase + ' drei verschiedene Workshops (keine Duplikate).');
}
});
}
});
})();
</script>
<?php endfor; ?>
<div class="kc-form-row">
<input type="submit" name="submit_finish" value="Senden" />
</div>
</form>
<?php endif; ?>
</div>
<?php
return ob_get_clean();
});
// Shortcode: allow teamers to create a workshop after entering password
add_shortcode('konficastle_teamer_create', function($atts) {
global $wpdb;
$prefix = $wpdb->prefix;
$msg = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['kc_teamer_create_nonce'])) {
if (empty($_POST['kc_teamer_create_nonce']) || !wp_verify_nonce($_POST['kc_teamer_create_nonce'], 'kc_teamer_create_action')) {
$msg = '<div class="kc-error-msg">Ungültiger Request.</div>';
} else {
$pw = trim($_POST['kc_teamer_pw'] ?? '');
$saved_hash = get_option('kc_teamer_password_hash', '');
if (empty($saved_hash) || !wp_check_password($pw, $saved_hash)) {
$msg = '<div class="kc-error-msg">Falsches Passwort.</div>';
} else {
$vorname = sanitize_text_field($_POST['vorname'] ?? '');
$nachname = sanitize_text_field($_POST['nachname'] ?? '');
$ws_name = sanitize_text_field($_POST['workshop_name'] ?? '');
if ($vorname === '' || $nachname === '' || $ws_name === '') {
$msg = '<div class="kc-error-msg">Bitte alle Felder ausfüllen.</div>';
} else {
$existing = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$prefix}kc_teamer WHERE vorname=%s AND nachname=%s", $vorname, $nachname));
if ($existing) {
$tid = intval($existing->id);
} else {
$wpdb->insert("{$prefix}kc_teamer", ['vorname'=>$vorname,'nachname'=>$nachname]);
$tid = intval($wpdb->insert_id);
}
$min_t = max(0, intval($_POST['min_teilnehmer'] ?? 0));
$max_t = max(1, intval($_POST['max_teilnehmer'] ?? 10));
if ($min_t > $max_t) {
$msg = '<div class="kc-error-msg">Die minimale Teilnehmerzahl darf nicht größer als die maximale sein.</div>';
} else {
$col = $wpdb->get_var("SHOW COLUMNS FROM {$prefix}kc_workshops LIKE 'min_teilnehmer'");
if (empty($col)) {
$wpdb->query("ALTER TABLE {$prefix}kc_workshops ADD COLUMN min_teilnehmer INT NOT NULL DEFAULT 0");
}
$wpdb->insert("{$prefix}kc_workshops", ['name'=>$ws_name, 'beschreibung'=>'', 'max_teilnehmer'=>$max_t, 'min_teilnehmer'=>$min_t]);
$wid = intval($wpdb->insert_id);
if ($wid) {
$wpdb->insert("{$prefix}kc_workshop_teamer", ['workshop_id'=>$wid, 'teamer_id'=>$tid]);
$msg = '<div class="kc-success-msg">Workshop angelegt und Teamer zugeordnet.</div>';
} else {
$msg = '<div class="kc-error-msg">Fehler beim Anlegen des Workshops.</div>';
}
}
}
}
}
}
ob_start();
$nonce = wp_create_nonce('kc_teamer_create_action');
?>
<div class="kc-form-container">
<h2>Teamer: Workshop erstellen</h2>
<?php echo $msg; ?>
<form method="post">
<input type="hidden" name="kc_teamer_create_nonce" value="<?= esc_attr($nonce) ?>">
<div class="kc-form-row">
<label>Passwort</label>
<input type="password" name="kc_teamer_pw" required />
</div>
<div class="kc-form-row">
<label>Vorname</label>
<input type="text" name="vorname" required />
</div>
<div class="kc-form-row">
<label>Nachname</label>
<input type="text" name="nachname" required />
</div>
<div class="kc-form-row">
<label>Workshop-Name</label>
<input type="text" name="workshop_name" required />
</div>
<div class="kc-form-row" style="display:flex;gap:8px;">
<div style="flex:1"><label>Min. Teilnehmer</label><input type="number" name="min_teilnehmer" value="0" required /></div>
<div style="flex:1"><label>Max. Teilnehmer</label><input type="number" name="max_teilnehmer" value="10" required /></div>
</div>
<div class="kc-form-row">
<input type="submit" value="Erstellen" />
</div>
</form>
</div>
<?php
return ob_get_clean();
});