Compare commits

...

31 Commits

Author SHA1 Message Date
4ab28370bc Update KC Wahlen Button Reihenfolge
Some checks failed
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Has been cancelled
2026-02-26 22:58:11 +00:00
c56aa70617 Update README.md
Some checks failed
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Failing after 2m29s
2026-02-19 09:50:08 +00:00
21553050f8 Update README.md
Some checks failed
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Failing after 2m30s
2026-02-19 08:43:37 +00:00
f18664251e Update README.md
Some checks failed
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Failing after 2m31s
update Readme
2026-02-19 08:35:05 +00:00
1a090dd8dc Update README.md
Some checks failed
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Has been cancelled
2026-02-19 08:23:53 +00:00
82f2af7e7a Update install.php
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 15s
2026-02-06 18:45:45 +00:00
bbfa923c9d Merge pull request 'update deploy workflow' (#6) from develop into main
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 16s
Reviewed-on: #6
2026-02-06 18:43:57 +00:00
ProgrammGamer
58c70908c6 update deploy workflow
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 15s
2026-02-06 19:42:40 +01:00
8827e5b324 Merge pull request 'develop' (#5) from develop into main
Some checks failed
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Failing after 4s
Reviewed-on: #5
2026-02-06 18:41:46 +00:00
ProgrammGamer
a65651358a upstream develop
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 33s
2026-02-06 19:40:17 +01:00
ProgrammGamer
077ba03a3f update deploy.yml to implement new wp host
Some checks failed
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Has been cancelled
2026-02-06 19:39:35 +01:00
ProgrammGamer
271af99fad deleted: CHANGELOG.md 2026-02-06 15:51:51 +01:00
ProgrammGamer
3f207a3612 0# Git commit message
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 12s
2026-02-01 19:28:52 +01:00
ProgrammGamer
92c4023fff Move CHANGELOG to Notes/CHANGELOG.md and update README link 2026-02-01 19:28:37 +01:00
ProgrammGamer
a3c08127f8 Release 1.0 notes + fixes: remove kc_phasen query, init $debug_output; add CHANGELOG and link from README 2026-02-01 19:26:18 +01:00
f1fb4cd4ea Merge pull request 'develop' (#4) from develop into main
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 13s
Reviewed-on: #4
2026-01-31 13:26:30 +00:00
ProgrammGamer
7184d64116 Merge branch 'develop' of https://git.konfi-castle.com/linus/Workshop-Wahlen into develop
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 13s
2026-01-31 14:16:18 +01:00
ProgrammGamer
5c9c00b48e csv anpassungen 2026-01-31 14:16:06 +01:00
a827275995 Merge pull request 'develop loesung zu Lösung' (#3) from develop into main
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 14s
Reviewed-on: #3
2026-01-31 10:56:48 +00:00
Blitz08
49621a4423 admin: collapse participant groups (Wahl & Phase) by default
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 12s
2026-01-31 11:48:51 +01:00
Blitz08
67222fc6f9 admin: add AJAX fallback for wahl phase count; use ajax in force-zuteilung JS
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 11s
2026-01-31 11:45:36 +01:00
Blitz08
eb7afe06ff admin: read phase-count from Wahl option data-einheiten; fallback to mapping
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 12s
2026-01-31 11:42:46 +01:00
Blitz08
b312cae473 admin: make phase a select and let JS populate options per Wahl
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 11s
2026-01-31 11:39:54 +01:00
Blitz08
e34ce64906 force zuteilung form anpassung
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 12s
2026-01-31 11:37:11 +01:00
Blitz08
8fca38f6fe admin: make phase select dependent on chosen Wahl (dynamic phases)
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 12s
2026-01-31 11:23:23 +01:00
Blitz08
1c08324b24 admin: improve force-zuteilung create/edit form UI
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 13s
2026-01-31 11:19:05 +01:00
Blitz08
a4719e9c58 loeschen zu löschen geändert
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 13s
2026-01-31 11:15:34 +01:00
Blitz08
c33eb3eaac Rechtschribfelher Korigiert
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 14s
2026-01-31 11:02:25 +01:00
cd5a0f72de Merge pull request 'frontend: hide results when wahl is freigegeben in shortcode' (#2) from to-main/frontend-ergebnis-hide-results into main
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 12s
Reviewed-on: #2
2026-01-31 09:56:01 +00:00
Blitz08
b77b1fe0fb frontend: hide results when wahl is freigegeben in shortcode
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 14s
2026-01-31 10:53:03 +01:00
8029ebfb27 Merge pull request 'develop' (#1) from develop into main
All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 12s
Reviewed-on: #1
2026-01-30 21:54:02 +00:00
12 changed files with 451 additions and 281 deletions

View File

@@ -35,6 +35,7 @@ jobs:
# ===================== # =====================
- name: Deploy to DEV via FTP - name: Deploy to DEV via FTP
if: github.ref == 'refs/heads/develop' if: github.ref == 'refs/heads/develop'
shell: bash
run: | run: |
apt-get update apt-get update
apt-get install -y lftp apt-get install -y lftp
@@ -51,17 +52,68 @@ jobs:
# ===================== # =====================
# PROD DEPLOY (FTP) # PROD DEPLOY (FTP)
# ===================== # =====================
- name: Deploy to PROD via FTP - name: Deploy to PROD via SSH
if: github.ref == 'refs/heads/main' if: github.ref == 'refs/heads/main'
env:
SSH_HOST: ${{ secrets.PROD_SSH_HOST }}
SSH_USER: ${{ secrets.PROD_SSH_USER }}
SSH_PORT: ${{ secrets.PROD_SSH_PORT }}
SSH_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
HOST_WP_ROOT: ${{ secrets.PROD_HOST_WP_ROOT }}
HOST_ABS_PLUGIN_PATH: ${{ secrets.PROD_HOST_ABS_PLUGIN_PATH }}
shell: bash
run: | run: |
set -euo pipefail
apt-get update apt-get update
apt-get install -y lftp # openssh-client to auth; tar for packaging with excludes
apt-get install -y openssh-client tar
lftp -u "${{ secrets.FTP_USER }},${{ secrets.FTP_PASS }}" ftp://${{ secrets.FTP_HOST }}:${{ secrets.FTP_PORT }} <<EOF # Prepare SSH key
set ftp:ssl-allow no mkdir -p ~/.ssh
set net:timeout 20 # Write the multiline private key exactly as provided
set net:max-retries 2 printf "%s\n" "$SSH_KEY" > ~/.ssh/prod_docker_key
set mirror:parallel-transfer-count 2 chmod 600 ~/.ssh/prod_docker_key
mirror -R --delete --verbose ./ /httpdocs/wp-content/plugins/konficastle-workshopwahl/
quit # Write SSH config so DOCKER_HOST can reference a named host
EOF cat > ~/.ssh/config <<CFG
Host prod-docker
HostName ${SSH_HOST}
User ${SSH_USER}
Port ${SSH_PORT}
IdentityFile ~/.ssh/prod_docker_key
IdentitiesOnly yes
PubkeyAuthentication yes
StrictHostKeyChecking accept-new
CFG
# Prime known_hosts (optional, StrictHostKeyChecking accept-new will handle first connect)
ssh-keyscan -p "$SSH_PORT" "$SSH_HOST" >> ~/.ssh/known_hosts || true
# Create a tarball with excludes to avoid copying VCS and CI folders
TAR_FILE="/tmp/kc-plugin.tar.gz"
tar -czf "$TAR_FILE" \
--exclude .git \
--exclude .gitea \
--exclude .github \
--exclude Notes \
--exclude "*.yml" \
--exclude "*.yaml" \
--exclude "*.md" \
.
# Choose target path: prefer absolute plugin path; otherwise derive from HOST_WP_ROOT
if [ -n "${HOST_ABS_PLUGIN_PATH}" ]; then
echo "Deploying to absolute host path: ${HOST_ABS_PLUGIN_PATH}"
REMOTE_PATH_DECL="PLUGIN_PATH=\"${HOST_ABS_PLUGIN_PATH%/}\""
elif [ -n "${HOST_WP_ROOT}" ]; then
echo "Deploying to host path relative to remote home: \$HOME/${HOST_WP_ROOT%/}/wp-content/plugins/konficastle-workshopwahl"
REMOTE_PATH_DECL="PLUGIN_PATH=\$HOME/${HOST_WP_ROOT%/}/wp-content/plugins/konficastle-workshopwahl"
else
echo "Error: set PROD_HOST_ABS_PLUGIN_PATH (absolute) or PROD_HOST_WP_ROOT (relative)" >&2
exit 1
fi
# Upload tarball to host home and extract
scp -o StrictHostKeyChecking=accept-new -o IdentitiesOnly=yes -i ~/.ssh/prod_docker_key "$TAR_FILE" prod-docker:~/kc-plugin.tar.gz
# Use \$HOME for remote expansion (tilde does not expand inside quotes)
ssh prod-docker "$REMOTE_PATH_DECL; mkdir -p \"\$PLUGIN_PATH\" && rm -rf \"\$PLUGIN_PATH\"/* && tar -xzf \"\$HOME/kc-plugin.tar.gz\" -C \"\$PLUGIN_PATH\" && rm -f \"\$HOME/kc-plugin.tar.gz\" && ls -la \"\$PLUGIN_PATH\" | head -n 50"

View File

@@ -47,4 +47,3 @@ Dieses WordPress-Plugin ermöglicht die Verwaltung und Durchführung von Worksho
--- ---
Für Detailfragen zu Datenbankstruktur, Shortcodes oder Zuteilungslogik siehe die jeweiligen Dateien im `includes/`-Verzeichnis. Für Detailfragen zu Datenbankstruktur, Shortcodes oder Zuteilungslogik siehe die jeweiligen Dateien im `includes/`-Verzeichnis.

View File

@@ -131,7 +131,7 @@ function kc_teamer_page() {
<td>".esc_html($tm->nachname)."</td> <td>".esc_html($tm->nachname)."</td>
<td class='kc-actions'> <td class='kc-actions'>
<a class='kc-btn edit' href='?page=kc_teamer&edit_teamer={$tm->id}'>Bearbeiten</a> <a class='kc-btn edit' href='?page=kc_teamer&edit_teamer={$tm->id}'>Bearbeiten</a>
<a class='kc-btn del' href='?page=kc_teamer&delete_teamer={$tm->id}' onclick=\"return confirm('Wirklich loeschen?');\">Loeschen</a> <a class='kc-btn del' href='?page=kc_teamer&delete_teamer={$tm->id}' onclick=\"return confirm('Wirklich löschen?');\">Löschen</a>
</td> </td>
</tr>"; </tr>";
} }

View File

@@ -274,10 +274,10 @@ function kc_teilnehmer_page() {
// Gesamtanzahl Teilnehmer für diese Wahl berechnen // Gesamtanzahl Teilnehmer für diese Wahl berechnen
$gesamt = 0; $gesamt = 0;
foreach ($phasen as $tns) $gesamt += count($tns); foreach ($phasen as $tns) $gesamt += count($tns);
echo '<details open style="margin:10px 0 18px 0;border:1px solid #eaeaea;border-radius:6px;padding:8px;">'; echo '<details style="margin:10px 0 18px 0;border:1px solid #eaeaea;border-radius:6px;padding:8px;">';
echo '<summary style="font-weight:700;cursor:pointer;">'. $wahl_disp . ' <span style="color:#555;font-weight:600;">(' . $gesamt . ' TN)</span></summary>'; echo '<summary style="font-weight:700;cursor:pointer;">'. $wahl_disp . ' <span style="color:#555;font-weight:600;">(' . $gesamt . ' TN)</span></summary>';
foreach ($phasen as $phase => $tns) { foreach ($phasen as $phase => $tns) {
echo '<details open style="margin:10px 0 10px 0;border:1px solid #f0f0f0;border-radius:6px;padding:8px;">'; echo '<details style="margin:10px 0 10px 0;border:1px solid #f0f0f0;border-radius:6px;padding:8px;">';
echo '<summary style="font-weight:600;">Phase '.intval($phase).' <span style="color:#555;font-weight:600;">('.count($tns).' TN)</span></summary>'; echo '<summary style="font-weight:600;">Phase '.intval($phase).' <span style="color:#555;font-weight:600;">('.count($tns).' TN)</span></summary>';
echo '<table class="kc-admin-table" style="margin:8px 0;">'; echo '<table class="kc-admin-table" style="margin:8px 0;">';
echo '<thead><tr><th>Vorname</th><th>Nachname</th><th>Wahl</th><th>Phase</th><th>Wunsch 1</th><th>Wunsch 2</th><th>Wunsch 3</th><th>Aktion</th></tr></thead><tbody>'; echo '<thead><tr><th>Vorname</th><th>Nachname</th><th>Wahl</th><th>Phase</th><th>Wunsch 1</th><th>Wunsch 2</th><th>Wunsch 3</th><th>Aktion</th></tr></thead><tbody>';
@@ -299,7 +299,7 @@ function kc_teilnehmer_page() {
<td>".$w3_disp."</td> <td>".$w3_disp."</td>
<td class='kc-actions'> <td class='kc-actions'>
<a class='kc-btn edit' href='?page=kc_teilnehmer&edit_teilnehmer={$tn->id}'>Bearbeiten</a> <a class='kc-btn edit' href='?page=kc_teilnehmer&edit_teilnehmer={$tn->id}'>Bearbeiten</a>
<a class='kc-btn del' href='?page=kc_teilnehmer&delete_teilnehmer={$tn->id}' onclick=\"return confirm('Wirklich loeschen?');\">Loeschen</a> <a class='kc-btn del' href='?page=kc_teilnehmer&delete_teilnehmer={$tn->id}' onclick=\"return confirm('Wirklich löschen?');\">Löschen</a>
</td> </td>
</tr>"; </tr>";
} }

View File

@@ -352,7 +352,7 @@ function kc_wahlen_page() {
echo '<td>'; echo '<td>';
echo "<form method='post' style='display:inline'>"; echo "<form method='post' style='display:inline'>";
echo "<input type='hidden' name='wahl_id' value='".intval($wahl->id)."'>"; echo "<input type='hidden' name='wahl_id' value='".intval($wahl->id)."'>";
echo "<button name='kc_wahl_freigabe' value='".($wahl->freigegeben?"0":"1")."' class='kc-btn edit' type='submit' style='background:".($wahl->freigegeben?"#e12b2b":"#b6d333").";color:#fff;font-weight:bold;'>".($wahl->freigegeben?"Schlie<EFBFBD>en":"Freigeben (zum eintragen)")."</button>"; echo "<button name='kc_wahl_freigabe' value='".($wahl->freigegeben?"0":"1")."' class='kc-btn edit' type='submit' style='background:".($wahl->freigegeben?"#e12b2b":"#b6d333").";color:#fff;font-weight:bold;'>".($wahl->freigegeben?"Schließen":"Freigeben (zum eintragen)")."</button>";
echo "</form>"; echo "</form>";
echo '<span style="color:'.($wahl->freigegeben?"#4176be":"#d40000").';margin-left:6px;font-size:90%;font-weight:bold;">'.($wahl->freigegeben ? "freigegeben" : "geschlossen").'</span>'; echo '<span style="color:'.($wahl->freigegeben?"#4176be":"#d40000").';margin-left:6px;font-size:90%;font-weight:bold;">'.($wahl->freigegeben ? "freigegeben" : "geschlossen").'</span>';
echo '</td>'; echo '</td>';
@@ -360,10 +360,10 @@ function kc_wahlen_page() {
echo '<td class="kc-actions">'; echo '<td class="kc-actions">';
echo '<a class="kc-btn" href="?page=kc_wahlen&zuweisen='.intval($wahl->id).'">Workshops zuweisen</a>'; echo '<a class="kc-btn" href="?page=kc_wahlen&zuweisen='.intval($wahl->id).'">Workshops zuweisen</a>';
echo '<a class="kc-btn" href="?page=kc_wahlen&edit_wahl='.intval($wahl->id).'">Bearbeiten</a>'; echo '<a class="kc-btn" href="?page=kc_wahlen&edit_wahl='.intval($wahl->id).'">Bearbeiten</a>';
echo '<a class="kc-btn" href="?page=kc_wahlen&show_zuteilung='.intval($wahl->id).'">Zuteilung anzeigen</a>';
$nonce = wp_create_nonce('kc_run_zuteilung_' . intval($wahl->id)); $nonce = wp_create_nonce('kc_run_zuteilung_' . intval($wahl->id));
echo '<a class="kc-btn" href="?page=kc_wahlen&run_zuteilung='.intval($wahl->id).'&_wpnonce='.$nonce.'" onclick="return confirm(\'Zuteilung wirklich starten? Dies überschreibt vorhandene Zuteilungen.\');">Zuteilung starten</a>'; echo '<a class="kc-btn" href="?page=kc_wahlen&run_zuteilung='.intval($wahl->id).'&_wpnonce='.$nonce.'" onclick="return confirm(\'Zuteilung wirklich starten? Dies überschreibt vorhandene Zuteilungen.\');">Zuteilung starten</a>';
echo '<a href="?page=kc_wahlen&delete_wahl='.intval($wahl->id).'" class="kc-btn del" onclick="return confirm(\'Wirklich loeschen?\');">Loeschen</a>'; echo '<a class="kc-btn" href="?page=kc_wahlen&show_zuteilung='.intval($wahl->id).'">Zuteilung anzeigen</a>';
echo '<a href="?page=kc_wahlen&delete_wahl='.intval($wahl->id).'" class="kc-btn del" onclick="return confirm(\'Wirklich löschen?\');">Löschen</a>';
echo '</td>'; echo '</td>';
echo '</tr>'; echo '</tr>';
} }

View File

@@ -10,8 +10,9 @@ function kc_workshops_page() {
// Liste aller Wahlen für Auswahl // Liste aller Wahlen für Auswahl
$wahlen_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_wahlen ORDER BY id DESC"); $wahlen_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_wahlen ORDER BY id DESC");
// Liste aller Phasen für Auswahl // Phasen werden pro Wahl über die Spalte `anzahl_einheiten` in `kc_wahlen` bestimmt.
$phasen_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_phasen ORDER BY nummer"); // Eine separate Tabelle `kc_phasen` wird nicht benötigt.
$phasen_liste = [];
// Workshop löschen // Workshop löschen
if (isset($_GET['delete_workshop'])) { if (isset($_GET['delete_workshop'])) {
@@ -542,7 +543,7 @@ function kc_workshops_page() {
<td>". $wahl_str ."</td> <td>". $wahl_str ."</td>
<td class='kc-actions'> <td class='kc-actions'>
<a class='kc-btn edit' href='?page=kc_workshops&edit_workshop={$ws->id}'>Bearbeiten</a> <a class='kc-btn edit' href='?page=kc_workshops&edit_workshop={$ws->id}'>Bearbeiten</a>
<a class='kc-btn del' href='?page=kc_workshops&delete_workshop={$ws->id}' onclick=\"return confirm('Wirklich loeschen?');\">Loeschen</a> <a class='kc-btn del' href='?page=kc_workshops&delete_workshop={$ws->id}' onclick=\"return confirm('Wirklich löschen?');\">Löschen</a>
</td> </td>
</tr>"; </tr>";
} }

View File

@@ -86,7 +86,8 @@ if (isset($_GET['export_csv']) && current_user_can('manage_options')) {
$output = fopen('php://output', 'w'); $output = fopen('php://output', 'w');
// Excel erwartet in DE meist ; als Trennzeichen // Excel erwartet in DE meist ; als Trennzeichen
$delimiter = ';'; $delimiter = ';';
fputcsv($output, ['Phase','Workshop','Teamer','Teilnehmer'], $delimiter); // Kopfzeile mit separaten Namensspalten und Wunsch
fputcsv($output, ['Phase','Workshop','Teamer','Nachname','Vorname','Wunsch'], $delimiter);
foreach($phases as $phase) { foreach($phases as $phase) {
if (empty($workshop_groups[$phase])) continue; if (empty($workshop_groups[$phase])) continue;
$display = []; $display = [];
@@ -114,14 +115,27 @@ if (isset($_GET['export_csv']) && current_user_can('manage_options')) {
foreach($teilnehmer as $t) { foreach($teilnehmer as $t) {
$vorname = preg_replace('/<[^>]*>/', '', $t->vorname); $vorname = preg_replace('/<[^>]*>/', '', $t->vorname);
$nachname = preg_replace('/<[^>]*>/', '', $t->nachname); $nachname = preg_replace('/<[^>]*>/', '', $t->nachname);
$teilnehmer_name = trim($vorname . ', ' . $nachname);
$ws_name_clean = preg_replace('/<[^>]*>/', '', $ws_name); $ws_name_clean = preg_replace('/<[^>]*>/', '', $ws_name);
$teamer_str_clean = preg_replace('/<[^>]*>/', '', $teamer_str); $teamer_str_clean = preg_replace('/<[^>]*>/', '', $teamer_str);
// Wunsch-Text ermitteln
if ($t->wunsch_rang == 0) {
$wunsch = 'Vorzuteilung';
} elseif ($t->wunsch_rang == -1) {
$wunsch = 'zugelost';
} elseif ($t->wunsch_rang == 99) {
$wunsch = 'Zulosung';
} elseif ($t->wunsch_rang > 0) {
$wunsch = intval($t->wunsch_rang) . '.';
} else {
$wunsch = '';
}
fputcsv($output, [ fputcsv($output, [
$phase, $phase,
$ws_name_clean, $ws_name_clean,
$teamer_str_clean, $teamer_str_clean,
$teilnehmer_name, $nachname,
$vorname,
$wunsch $wunsch
], $delimiter); ], $delimiter);
} }

View File

@@ -4,14 +4,14 @@ function kc_force_zuteilung_page() {
$prefix = $wpdb->prefix; $prefix = $wpdb->prefix;
kc_admin_tabs('kc_force_zuteilung'); kc_admin_tabs('kc_force_zuteilung');
// Force-Zuteilung löschen // Force-Zuteilung l<EFBFBD>schen
if (isset($_GET['delete_force'])) { if (isset($_GET['delete_force'])) {
$fid = intval($_GET['delete_force']); $fid = intval($_GET['delete_force']);
$wpdb->delete("{$prefix}kc_force_zuteilung", ['id' => $fid]); $wpdb->delete("{$prefix}kc_force_zuteilung", ['id' => $fid]);
echo '<div class="notice notice-success">Force-Zuteilung gelöscht!</div>'; echo '<div class="notice notice-success">Force-Zuteilung gel<EFBFBD>scht!</div>';
} }
// Force speichern (neu/ändern) // Force speichern (neu/<EFBFBD>ndern)
if (isset($_POST['kc_force_save'])) { if (isset($_POST['kc_force_save'])) {
$data = [ $data = [
'teilnehmer_id' => intval($_POST['teilnehmer_id']), 'teilnehmer_id' => intval($_POST['teilnehmer_id']),
@@ -29,69 +29,143 @@ function kc_force_zuteilung_page() {
} }
} }
// Listen für Dropdowns // Listen f<EFBFBD>r Dropdowns
$teilnehmer_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_teilnehmer ORDER BY nachname, vorname"); $teilnehmer_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_teilnehmer ORDER BY nachname, vorname");
$workshop_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_workshops ORDER BY name"); $workshop_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_workshops ORDER BY name");
$wahlen = $wpdb->get_results("SELECT id, name FROM {$prefix}kc_wahlen WHERE deleted=0 ORDER BY name"); $wahlen = $wpdb->get_results("SELECT id, name, COALESCE(anzahl_einheiten,1) AS anzahl_einheiten FROM {$prefix}kc_wahlen WHERE deleted=0 ORDER BY name");
// Bearbeiten // Bearbeiten
if (isset($_GET['edit_force'])) { if (isset($_GET['edit_force'])) {
$fid = intval($_GET['edit_force']); $fid = intval($_GET['edit_force']);
$fz = $wpdb->get_row("SELECT * FROM {$prefix}kc_force_zuteilung WHERE id=$fid"); $fz = $wpdb->get_row("SELECT * FROM {$prefix}kc_force_zuteilung WHERE id=$fid");
echo '<div class="kc-admin-table-wrap">'; echo '<div class="kc-admin-table-wrap">';
echo '<h2>Force-Zuteilung bearbeiten</h2> echo '<h2>Force-Zuteilung bearbeiten</h2>';
<form method="post"> echo '<div class="kc-form-container" style="max-width:880px;padding:18px 20px;border-radius:10px;background:#fff;border:1px solid #eef3f2;">';
<input type="hidden" name="fid" value="'.intval($fz->id).'"> echo '<form method="post">';
<div class="kc-form-row"> echo '<input type="hidden" name="fid" value="'.intval($fz->id).'">';
<label>Teilnehmer <span class="kc-required">*</span></label> echo '<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start">';
<select name="teilnehmer_id" id="kc-force-teilnehmer-dropdown" style="width:100%">
<option value="">Teilnehmer auswählen…</option>'; // Teilnehmer
foreach($teilnehmer_liste as $t) { echo '<div class="kc-form-row" style="min-width:0">';
echo '<option value="'.esc_attr($t->id).'"'.($fz->teilnehmer_id==$t->id?' selected':'').'>' echo '<label>Teilnehmer <span class="kc-required">*</span></label>';
.esc_html($t->vorname.' '.$t->nachname.' (ID: '.$t->id.')') echo '<select name="teilnehmer_id" id="kc-force-teilnehmer-dropdown" style="width:100%">';
.'</option>'; echo '<option value="">Teilnehmer auswählen…</option>';
} foreach($teilnehmer_liste as $t) {
echo ' </select> echo '<option value="'.esc_attr($t->id).'"'.($fz->teilnehmer_id==$t->id?' selected':'').'>'
</div> .esc_html($t->vorname.' '.$t->nachname.' (ID: '.$t->id.')')
<div class="kc-form-row"> .'</option>';
<label>Wahl <span class="kc-required">*</span></label> }
<select name="wahl_id" id="kc-force-wahl-dropdown" style="width:100%"> echo '</select>';
<option value="">Wahl auswählen…</option>'; echo '</div>';
foreach($wahlen as $w) {
echo '<option value="'.intval($w->id).'"'.($fz->wahl_id==$w->id?' selected':'').'>' // Wahl
.esc_html($w->name.' (ID '.$w->id.')').'</option>'; echo '<div class="kc-form-row" style="min-width:0">';
} echo '<label>Wahl <span class="kc-required">*</span></label>';
echo ' </select> echo '<select name="wahl_id" id="kc-force-wahl-dropdown" style="width:100%">';
</div> echo '<option value="">Wahl auswählen…</option>';
<div class="kc-form-row"> foreach($wahlen as $w) {
<label>Phase</label> echo '<option value="'.intval($w->id).'" data-einheiten="'.intval($w->anzahl_einheiten).'"'.($fz->wahl_id==$w->id?' selected':'').'>'.esc_html($w->name.' (ID '.$w->id.')').'</option>';
<input type="number" name="phase" value="'.intval($fz->phase).'" style="width:100%"> }
</div> echo '</select>';
<div class="kc-form-row"> echo '</div>';
<label>Workshop <span class="kc-required">*</span></label>
<select name="workshop_id" id="kc-force-workshop-dropdown" style="width:100%"> // Phase (select so JS can populate based on Wahl)
<option value="">Workshop auswählen…</option>'; echo '<div class="kc-form-row" style="min-width:0">';
foreach($workshop_liste as $ws) { echo '<label>Phase</label>';
echo '<option value="'.esc_attr($ws->id).'"'.($fz->workshop_id==$ws->id?' selected':'').'>' echo '<select name="phase" style="width:100%;padding:8px;border-radius:6px;border:1px solid #ddd">';
.esc_html($ws->name) echo '<option value="'.intval($fz->phase).'">'.intval($fz->phase).'</option>';
.'</option>'; echo '</select>';
} echo '</div>';
echo ' </select>
</div> // Workshop
<div class="kc-form-row"> echo '<div class="kc-form-row" style="min-width:0">';
<label>Kommentar</label> echo '<label>Workshop <span class="kc-required">*</span></label>';
<input type="text" name="kommentar" value="'.esc_attr($fz->kommentar).'" style="width:100%"> echo '<select name="workshop_id" id="kc-force-workshop-dropdown" style="width:100%">';
</div> echo '<option value="">Workshop auswählen…</option>';
<button name="kc_force_save" class="kc-btn">Speichern</button> foreach($workshop_liste as $ws) {
<a href="?page=kc_force_zuteilung" class="kc-btn del" style="margin-left:24px;">Abbrechen</a> echo '<option value="'.esc_attr($ws->id).'"'.($fz->workshop_id==$ws->id?' selected':'').'>'
</form> .esc_html($ws->name)
<script> .'</option>';
jQuery(function($){ }
$("#kc-force-teilnehmer-dropdown").select2({placeholder:"Teilnehmer auswählen…",allowClear:true}); echo '</select>';
$("#kc-force-wahl-dropdown").select2({placeholder:"Wahl auswählen…",allowClear:true}); echo '</div>';
$("#kc-force-workshop-dropdown").select2({placeholder:"Workshop auswählen…",allowClear:true});
}); // Kommentar (full width)
</script>'; echo '<div style="grid-column:1/ -1">';
echo '<div class="kc-form-row">';
echo '<label>Kommentar</label>';
echo '<input type="text" name="kommentar" value="'.esc_attr($fz->kommentar).'" style="width:100%;padding:8px;border-radius:6px;border:1px solid #ddd">';
echo '</div>';
echo '</div>';
echo '</div>'; // grid
echo '<div style="margin-top:12px;display:flex;gap:10px;justify-content:flex-start">';
echo '<button name="kc_force_save" class="kc-btn" style="padding:8px 16px;">Speichern</button>';
echo '<a href="?page=kc_force_zuteilung" class="kc-btn del" style="padding:8px 16px;">Abbrechen</a>';
echo '</div>';
echo '</form>';
echo '</div>';
// Prepare JS mapping of wahl_id -> number of phases
$wahl_phases = [];
foreach ($wahlen as $w) $wahl_phases[intval($w->id)] = intval($w->anzahl_einheiten);
echo '<script>var kcWahlPhases = ' . wp_json_encode($wahl_phases) . ';</script>';
echo <<<'JS'
<script>
jQuery(function($){
$("#kc-force-teilnehmer-dropdown").select2({placeholder:"Teilnehmer auswählen…",allowClear:true});
$("#kc-force-wahl-dropdown").select2({placeholder:"Wahl auswählen…",allowClear:true});
$("#kc-force-workshop-dropdown").select2({placeholder:"Workshop auswählen…",allowClear:true});
function refreshPhaseSelect($wahlSelect, $phaseSelect, current) {
// prefer data attribute on the selected option; fall back to kcWahlPhases mapping
var selOpt = $wahlSelect.find('option:selected');
var max = parseInt(selOpt.data('einheiten') || kcWahlPhases[parseInt($wahlSelect.val(),10)] || 1, 10);
$phaseSelect.empty();
for(var i=1;i<=max;i++){
var opt = $("<option>").val(i).text(i + (i===1? " (Phase)":" (Phase)"));
$phaseSelect.append(opt);
}
if (current) {
$phaseSelect.val(current);
}
$phaseSelect.prop("disabled", false);
}
// Bind change for all existing wahl selects on the page
$(document).on("change", "#kc-force-wahl-dropdown", function(){
var $w = $(this);
var $phase = $w.closest("form").find("[name='phase']");
// try immediate refresh; if no data found, fallback to AJAX
var sel = $w.find('option:selected');
var einheiten = sel.data('einheiten') || kcWahlPhases[parseInt($w.val(),10)];
if (einheiten) {
refreshPhaseSelect($w, $phase);
} else {
// AJAX fallback to ask server for anzahl_einheiten
$.get(ajaxurl, {action: 'kc_get_wahl', id: $w.val()}).done(function(r){
if (r && r.success && r.data && r.data.anzahl_einheiten) {
// set data attribute so future reads find it
sel.data('einheiten', parseInt(r.data.anzahl_einheiten,10));
}
refreshPhaseSelect($w, $phase);
}).fail(function(){ refreshPhaseSelect($w, $phase); });
}
});
// Initialize existing phase selects based on their selected wahl
$("[name='phase']").each(function(){
var $phase = $(this);
var $form = $phase.closest("form");
var $wahl = $form.find("#kc-force-wahl-dropdown");
var current = $phase.val();
refreshPhaseSelect($wahl, $phase, current);
});
});
</script>
JS;
echo '</div>'; echo '</div>';
return; return;
} }
@@ -99,63 +173,82 @@ function kc_force_zuteilung_page() {
// Neu anlegen // Neu anlegen
if (isset($_GET['new'])) { if (isset($_GET['new'])) {
echo '<div class="kc-admin-table-wrap">'; echo '<div class="kc-admin-table-wrap">';
echo '<h2>Neue Force-Zuteilung</h2> echo '<h2>Neue Force-Zuteilung</h2>';
<form method="post"> echo '<div class="kc-form-container" style="max-width:880px;padding:18px 20px;border-radius:10px;background:#fff;border:1px solid #eef3f2;">';
<div class="kc-form-row"> echo '<form method="post">';
<label>Teilnehmer <span class="kc-required">*</span></label>
<select name="teilnehmer_id" id="kc-force-teilnehmer-dropdown" style="width:100%"> echo '<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start">';
<option value="">Teilnehmer auswählen…</option>';
foreach($teilnehmer_liste as $t) { // Teilnehmer
echo '<option value="'.esc_attr($t->id).'">' echo '<div class="kc-form-row" style="min-width:0">';
.esc_html($t->vorname.' '.$t->nachname.' (ID: '.$t->id.')') echo '<label>Teilnehmer <span class="kc-required">*</span></label>';
.'</option>'; echo '<select name="teilnehmer_id" id="kc-force-teilnehmer-dropdown" style="width:100%">';
} echo '<option value="">Teilnehmer auswählen…</option>';
echo ' </select> foreach($teilnehmer_liste as $t) {
</div> echo '<option value="'.esc_attr($t->id).'">'.esc_html($t->vorname.' '.$t->nachname.' (ID: '.$t->id.')').'</option>';
<div class="kc-form-row"> }
<label>Wahl <span class="kc-required">*</span></label> echo '</select>';
<select name="wahl_id" id="kc-force-wahl-dropdown" style="width:100%"> echo '</div>';
<option value="">Wahl auswählen…</option>';
foreach($wahlen as $w) { // Wahl
echo '<option value="'.intval($w->id).'">' echo '<div class="kc-form-row" style="min-width:0">';
.esc_html($w->name.' (ID '.$w->id.')').'</option>'; echo '<label>Wahl <span class="kc-required">*</span></label>';
} echo '<select name="wahl_id" id="kc-force-wahl-dropdown" style="width:100%">';
echo ' </select> echo '<option value="">Wahl auswählen…</option>';
</div> foreach($wahlen as $w) {
<div class="kc-form-row"> echo '<option value="'.intval($w->id).'" data-einheiten="'.intval($w->anzahl_einheiten).'">'.esc_html($w->name.' (ID '.$w->id.')').'</option>';
<label>Phase</label> }
<input type="number" name="phase" value="1" style="width:100%"> echo '</select>';
</div> echo '</div>';
<div class="kc-form-row">
<label>Workshop <span class="kc-required">*</span></label> // Phase (select so JS can populate based on Wahl)
<select name="workshop_id" id="kc-force-workshop-dropdown" style="width:100%"> echo '<div class="kc-form-row" style="min-width:0">';
<option value="">Workshop auswählen…</option>'; echo '<label>Phase</label>';
foreach($workshop_liste as $ws) { echo '<select name="phase" style="width:100%;padding:8px;border-radius:6px;border:1px solid #ddd">';
echo '<option value="'.esc_attr($ws->id).'">' echo '<option value="1">1</option>';
.esc_html($ws->name) echo '</select>';
.'</option>'; echo '</div>';
}
echo ' </select> // Workshop
</div> echo '<div class="kc-form-row" style="min-width:0">';
<div class="kc-form-row"> echo '<label>Workshop <span class="kc-required">*</span></label>';
<label>Kommentar</label> echo '<select name="workshop_id" id="kc-force-workshop-dropdown" style="width:100%">';
<input type="text" name="kommentar" style="width:100%"> echo '<option value="">Workshop auswählen…</option>';
</div> foreach($workshop_liste as $ws) {
<button name="kc_force_save" class="kc-btn">Speichern</button> echo '<option value="'.esc_attr($ws->id).'">'.esc_html($ws->name).'</option>';
<a href="?page=kc_force_zuteilung" class="kc-btn del" style="margin-left:24px;">Abbrechen</a> }
</form> echo '</select>';
<script> echo '</div>';
// Kommentar full width
echo '<div style="grid-column:1/ -1">';
echo '<div class="kc-form-row">';
echo '<label>Kommentar</label>';
echo '<input type="text" name="kommentar" style="width:100%;padding:8px;border-radius:6px;border:1px solid #ddd">';
echo '</div>';
echo '</div>';
echo '</div>'; // grid
echo '<div style="margin-top:12px;display:flex;gap:10px;justify-content:flex-start">';
echo '<button name="kc_force_save" class="kc-btn" style="padding:8px 16px;">Speichern</button>';
echo '<a href="?page=kc_force_zuteilung" class="kc-btn del" style="padding:8px 16px;">Abbrechen</a>';
echo '</div>';
echo '</form>';
echo '</div>';
echo '<script>
jQuery(function($){ jQuery(function($){
$("#kc-force-teilnehmer-dropdown").select2({placeholder:"Teilnehmer auswählen…",allowClear:true}); $("#kc-force-teilnehmer-dropdown").select2({placeholder:"Teilnehmer auswählen…",allowClear:true});
$("#kc-force-wahl-dropdown").select2({placeholder:"Wahl auswählen…",allowClear:true}); $("#kc-force-wahl-dropdown").select2({placeholder:"Wahl auswählen…",allowClear:true});
$("#kc-force-workshop-dropdown").select2({placeholder:"Workshop auswählen…",allowClear:true}); $("#kc-force-workshop-dropdown").select2({placeholder:"Workshop auswählen…",allowClear:true});
}); });
</script>'; </script>';
echo '</div>'; echo '</div>';
return; return;
} }
// Übersicht // <EFBFBD>bersicht
echo '<div class="kc-admin-table-wrap">'; echo '<div class="kc-admin-table-wrap">';
echo '<h2 style="margin-top:0;">Alle Force-Zuteilungen</h2>'; echo '<h2 style="margin-top:0;">Alle Force-Zuteilungen</h2>';
echo '<a class="kc-btn" style="float:right;margin-bottom:12px;" href="?page=kc_force_zuteilung&new=1">+ Neue Force-Zuteilung</a>'; echo '<a class="kc-btn" style="float:right;margin-bottom:12px;" href="?page=kc_force_zuteilung&new=1">+ Neue Force-Zuteilung</a>';
@@ -176,7 +269,7 @@ function kc_force_zuteilung_page() {
<td>".esc_html($f->kommentar)."</td> <td>".esc_html($f->kommentar)."</td>
<td class='kc-actions'> <td class='kc-actions'>
<a class='kc-btn edit' href='?page=kc_force_zuteilung&edit_force={$f->id}'>Bearbeiten</a> <a class='kc-btn edit' href='?page=kc_force_zuteilung&edit_force={$f->id}'>Bearbeiten</a>
<a class='kc-btn del' href='?page=kc_force_zuteilung&delete_force={$f->id}' onclick=\"return confirm('Wirklich loeschen?');\">Loeschen</a> <a class='kc-btn del' href='?page=kc_force_zuteilung&delete_force={$f->id}' onclick=\"return confirm('Wirklich löschen?');\">schen</a>
</td> </td>
</tr>"; </tr>";
} }

View File

@@ -6,7 +6,11 @@ add_shortcode('konficastle_workshop_ergebnis', function($atts) {
global $wpdb; global $wpdb;
$wahl = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}kc_wahlen WHERE id=$wahl_id"); $wahl = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}kc_wahlen WHERE id=$wahl_id");
if(!$wahl) return ''; if(!$wahl) return '';
// Keine Warnmeldung im Frontend anzeigen, Ergebnisse weiterhin darstellen // Zeige Ergebnisse nur, wenn die Wahl NICHT freigegeben ist.
// Ist die Wahl freigegeben, soll das Ergebnis-Shortcode nichts ausgeben (Formular wird stattdessen angezeigt).
if (!empty($wahl->freigegeben)) {
return '';
}
// Workshops für diese Wahl holen // Workshops für diese Wahl holen
$workshops = $wpdb->get_results( $workshops = $wpdb->get_results(

View File

@@ -5,14 +5,8 @@ add_shortcode('konficastle_workshopwahl', function($atts) {
global $wpdb; global $wpdb;
// KRITISCHER TEST: Ausgabe ganz am Anfang // Optionales Debug-Ausgabe-Fragment (standardmäßig leer, um Warnungen zu vermeiden)
//$debug_output = '<div style="background:yellow;padding:20px;margin:20px 0;border:3px solid red;">'; $debug_output = '';
//$debug_output .= '<h3>DEBUG INFO</h3>';
//$debug_output .= 'Shortcode läuft!<br>';
//$debug_output .= 'REQUEST_METHOD: ' . ($_SERVER['REQUEST_METHOD'] ?? 'NICHT GESETZT') . '<br>';
//$debug_output .= 'POST vorhanden: ' . (empty($_POST) ? 'NEIN' : 'JA') . '<br>';
//$debug_output .= 'POST Inhalt: <pre>' . print_r($_POST, true) . '</pre>';
//$debug_output .= '</div>';
$wahl = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}kc_wahlen WHERE id=%d", $wahl_id)); $wahl = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}kc_wahlen WHERE id=%d", $wahl_id));
if(!$wahl || !$wahl->freigegeben) { if(!$wahl || !$wahl->freigegeben) {

View File

@@ -1,139 +1,140 @@
<?php <?php
if (!defined('ABSPATH')) exit; if (!defined('ABSPATH')) exit;
/** /**
* Create plugin database tables on activation and remove them on deactivation. * Create plugin database tables on activation and remove them on deactivation.
*/
function kc_install_tables() { */
global $wpdb; function kc_install_tables() {
$prefix = $wpdb->prefix; global $wpdb;
$charset_collate = $wpdb->get_charset_collate(); $prefix = $wpdb->prefix;
$charset_collate = $wpdb->get_charset_collate();
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
// Tables definitions
$tables_sql = []; // Tables definitions
$tables_sql = [];
$tables_sql[] = "CREATE TABLE {$prefix}kc_wahlen (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT, $tables_sql[] = "CREATE TABLE {$prefix}kc_wahlen (
name varchar(191) NOT NULL, id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
beschreibung text DEFAULT NULL, name varchar(191) NOT NULL,
anzahl_einheiten tinyint NOT NULL DEFAULT 1, beschreibung text DEFAULT NULL,
min_kapazitaet int NOT NULL DEFAULT 0, anzahl_einheiten tinyint NOT NULL DEFAULT 1,
max_kapazitaet int NOT NULL DEFAULT 0, min_kapazitaet int NOT NULL DEFAULT 0,
freigegeben tinyint(1) NOT NULL DEFAULT 0, max_kapazitaet int NOT NULL DEFAULT 0,
deleted tinyint(1) NOT NULL DEFAULT 0, freigegeben tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id) deleted tinyint(1) NOT NULL DEFAULT 0,
) $charset_collate"; PRIMARY KEY (id)
) $charset_collate";
$tables_sql[] = "CREATE TABLE {$prefix}kc_workshops (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT, $tables_sql[] = "CREATE TABLE {$prefix}kc_workshops (
name varchar(191) NOT NULL, id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
beschreibung text DEFAULT NULL, name varchar(191) NOT NULL,
max_teilnehmer int NOT NULL DEFAULT 0, beschreibung text DEFAULT NULL,
min_teilnehmer int NOT NULL DEFAULT 0, max_teilnehmer int NOT NULL DEFAULT 0,
PRIMARY KEY (id) min_teilnehmer int NOT NULL DEFAULT 0,
) $charset_collate"; PRIMARY KEY (id)
) $charset_collate";
$tables_sql[] = "CREATE TABLE {$prefix}kc_teamer (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT, $tables_sql[] = "CREATE TABLE {$prefix}kc_teamer (
vorname varchar(191) DEFAULT NULL, id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
nachname varchar(191) DEFAULT NULL, vorname varchar(191) DEFAULT NULL,
PRIMARY KEY (id) nachname varchar(191) DEFAULT NULL,
) $charset_collate"; PRIMARY KEY (id)
) $charset_collate";
$tables_sql[] = "CREATE TABLE {$prefix}kc_teilnehmer (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT, $tables_sql[] = "CREATE TABLE {$prefix}kc_teilnehmer (
vorname varchar(191) DEFAULT NULL, id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
nachname varchar(191) DEFAULT NULL, vorname varchar(191) DEFAULT NULL,
wahl_id bigint(20) unsigned NOT NULL DEFAULT 0, nachname varchar(191) DEFAULT NULL,
phase tinyint NOT NULL DEFAULT 1, wahl_id bigint(20) unsigned NOT NULL DEFAULT 0,
wunsch1 bigint(20) unsigned DEFAULT NULL, phase tinyint NOT NULL DEFAULT 1,
wunsch2 bigint(20) unsigned DEFAULT NULL, wunsch1 bigint(20) unsigned DEFAULT NULL,
wunsch3 bigint(20) unsigned DEFAULT NULL, wunsch2 bigint(20) unsigned DEFAULT NULL,
deleted tinyint(1) NOT NULL DEFAULT 0, wunsch3 bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (id) deleted tinyint(1) NOT NULL DEFAULT 0,
) $charset_collate"; PRIMARY KEY (id)
) $charset_collate";
$tables_sql[] = "CREATE TABLE {$prefix}kc_wahl_workshops (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT, $tables_sql[] = "CREATE TABLE {$prefix}kc_wahl_workshops (
wahl_id bigint(20) unsigned NOT NULL DEFAULT 0, id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
workshop_id bigint(20) unsigned NOT NULL DEFAULT 0, wahl_id bigint(20) unsigned NOT NULL DEFAULT 0,
phase tinyint NOT NULL DEFAULT 1, workshop_id bigint(20) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id) phase tinyint NOT NULL DEFAULT 1,
) $charset_collate"; PRIMARY KEY (id)
) $charset_collate";
$tables_sql[] = "CREATE TABLE {$prefix}kc_force_zuteilung (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT, $tables_sql[] = "CREATE TABLE {$prefix}kc_force_zuteilung (
teilnehmer_id bigint(20) unsigned NOT NULL DEFAULT 0, id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
wahl_id bigint(20) unsigned NOT NULL DEFAULT 0, teilnehmer_id bigint(20) unsigned NOT NULL DEFAULT 0,
phase tinyint NOT NULL DEFAULT 1, wahl_id bigint(20) unsigned NOT NULL DEFAULT 0,
workshop_id bigint(20) unsigned DEFAULT NULL, phase tinyint NOT NULL DEFAULT 1,
kommentar text DEFAULT NULL, workshop_id bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (id) kommentar text DEFAULT NULL,
) $charset_collate"; PRIMARY KEY (id)
) $charset_collate";
$tables_sql[] = "CREATE TABLE {$prefix}kc_zuteilung (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT, $tables_sql[] = "CREATE TABLE {$prefix}kc_zuteilung (
teilnehmer_id bigint(20) unsigned NOT NULL DEFAULT 0, id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
vorname varchar(191) DEFAULT NULL, teilnehmer_id bigint(20) unsigned NOT NULL DEFAULT 0,
nachname varchar(191) DEFAULT NULL, vorname varchar(191) DEFAULT NULL,
wahl_id bigint(20) unsigned NOT NULL DEFAULT 0, nachname varchar(191) DEFAULT NULL,
phase tinyint NOT NULL DEFAULT 1, wahl_id bigint(20) unsigned NOT NULL DEFAULT 0,
workshop_id bigint(20) unsigned DEFAULT NULL, phase tinyint NOT NULL DEFAULT 1,
wunsch_rang tinyint DEFAULT NULL, workshop_id bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (id) wunsch_rang tinyint DEFAULT NULL,
) $charset_collate"; PRIMARY KEY (id)
) $charset_collate";
$tables_sql[] = "CREATE TABLE {$prefix}kc_workshop_teamer (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT, $tables_sql[] = "CREATE TABLE {$prefix}kc_workshop_teamer (
workshop_id bigint(20) unsigned DEFAULT NULL, id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
teamer_id bigint(20) unsigned DEFAULT NULL, workshop_id bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (id) teamer_id bigint(20) unsigned DEFAULT NULL,
) $charset_collate"; PRIMARY KEY (id)
) $charset_collate";
foreach ($tables_sql as $sql) {
dbDelta($sql); foreach ($tables_sql as $sql) {
} dbDelta($sql);
}
// Post-creation migration guard: ensure min_teilnehmer exists for older installs
$col = $wpdb->get_var($wpdb->prepare("SHOW COLUMNS FROM {$prefix}kc_workshops LIKE %s", 'min_teilnehmer')); // Post-creation migration guard: ensure min_teilnehmer exists for older installs
if (empty($col)) { $col = $wpdb->get_var($wpdb->prepare("SHOW COLUMNS FROM {$prefix}kc_workshops LIKE %s", 'min_teilnehmer'));
// try to add the column (no-op on newer installs) if (empty($col)) {
$wpdb->query("ALTER TABLE {$prefix}kc_workshops ADD COLUMN min_teilnehmer INT NOT NULL DEFAULT 0"); // try to add the column (no-op on newer installs)
} $wpdb->query("ALTER TABLE {$prefix}kc_workshops ADD COLUMN min_teilnehmer INT NOT NULL DEFAULT 0");
}
// Optionally store plugin version
add_option('kc_workshopwahl_db_version', '1.0'); // Optionally store plugin version
} add_option('kc_workshopwahl_db_version', '1.0');
}
function kc_uninstall_tables() {
global $wpdb; function kc_uninstall_tables() {
$prefix = $wpdb->prefix; global $wpdb;
$prefix = $wpdb->prefix;
$tables = [
"{$prefix}kc_zuteilung", $tables = [
"{$prefix}kc_force_zuteilung", "{$prefix}kc_zuteilung",
"{$prefix}kc_wahl_workshops", "{$prefix}kc_force_zuteilung",
"{$prefix}kc_teilnehmer", "{$prefix}kc_wahl_workshops",
"{$prefix}kc_teamer", "{$prefix}kc_teilnehmer",
"{$prefix}kc_workshops", "{$prefix}kc_teamer",
"{$prefix}kc_wahlen", "{$prefix}kc_workshops",
"{$prefix}kc_workshop_teamer" "{$prefix}kc_wahlen",
]; "{$prefix}kc_workshop_teamer"
];
foreach ($tables as $t) {
$wpdb->query("DROP TABLE IF EXISTS $t"); foreach ($tables as $t) {
} $wpdb->query("DROP TABLE IF EXISTS $t");
}
delete_option('kc_workshopwahl_db_version');
} delete_option('kc_workshopwahl_db_version');
}
// Backwards-compat wrapper for register_activation_hook usage
if (!function_exists('kc_register_hooks_internal')) { // Backwards-compat wrapper for register_activation_hook usage
function kc_register_hooks_internal() { if (!function_exists('kc_register_hooks_internal')) {
// intentionally left blank function kc_register_hooks_internal() {
} // intentionally left blank
} }
}
?>
?>

View File

@@ -1,4 +1,16 @@
<?php <?php
// AJAX endpoint to return wahl details (anzahl_einheiten)
add_action('wp_ajax_kc_get_wahl', function(){
global $wpdb;
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$id) {
wp_send_json_error('missing id');
}
$row = $wpdb->get_row($wpdb->prepare("SELECT id, COALESCE(anzahl_einheiten,1) as anzahl_einheiten FROM {$wpdb->prefix}kc_wahlen WHERE id=%d", $id));
if (!$row) wp_send_json_error('not found');
wp_send_json_success(['id'=>intval($row->id),'anzahl_einheiten'=>intval($row->anzahl_einheiten)]);
});
/** /**
* Plugin Name: Workshop-Wahlen * Plugin Name: Workshop-Wahlen
* Description: Workshop-Wahl-System für Konfi-Castle.com * Description: Workshop-Wahl-System für Konfi-Castle.com