diff --git a/app/actions/membership-submit.php b/app/actions/membership-submit.php new file mode 100644 index 0000000..5764394 --- /dev/null +++ b/app/actions/membership-submit.php @@ -0,0 +1,131 @@ + $ok, 'error' => $error ?: null]); + } else { + header('Location: ' . url('mitglied-werden') . ($ok ? '?sent=1' : '?error=' . $error) . '#anmeldung-fussball', true, 303); + } + exit; +}; + +$field = static fn (string $key): string => trim((string) ($_POST[$key] ?? '')); + +// --- Spam-Checks: Bots bekommen ein stilles "OK" (kein Feedback-Kanal) --- +if ($field('website') !== '' || !form_token_valid($field('ft'))) { + $respond(true); +} + +// --- Eingaben --- +$firstName = $field('first_name'); +$lastName = $field('last_name'); +$birthDate = $field('birth_date'); +$phone = $field('phone'); +$street = $field('street'); +$zip = $field('zip'); +$city = $field('city'); +$email = $field('email'); +$feeClass = $field('fee_class'); + +// Beitragsklassen-Whitelist identisch zur Seite aus data/mitglied-werden.json ableiten. +$data = json_load('mitglied-werden'); +$feeOptions = array_map( + static fn (array $r): string => $r['label'] . ' — ' . $r['price'], + $data['fussball']['fees']['rows'] ?? [] +); + +// --- Validierung (Whitelist-Prinzip) --- +$valid = $firstName !== '' && mb_strlen($firstName) <= 100 + && $lastName !== '' && mb_strlen($lastName) <= 100 + && preg_match('/^\d{4}-\d{2}-\d{2}$/', $birthDate) === 1 + && $phone !== '' && mb_strlen($phone) <= 50 + && $street !== '' && mb_strlen($street) <= 200 + && $zip !== '' && mb_strlen($zip) <= 10 + && $city !== '' && mb_strlen($city) <= 100 + && filter_var($email, FILTER_VALIDATE_EMAIL) !== false + && in_array($feeClass, $feeOptions, true) + && ($_POST['statute'] ?? '') === '1' + && ($_POST['privacy'] ?? '') === '1' + && !preg_match('/[\r\n]/', $firstName . $lastName . $city . $street); + +if (!$valid) { + $respond(false, 'validation'); +} + +// --- Versand --- +$smtp = config('smtp'); + +$body = "Neuer Mitgliedsantrag (Fußball) über tsv08kulmbach.de\n" + . str_repeat('-', 40) . "\n" + . "Vorname: {$firstName}\n" + . "Nachname: {$lastName}\n" + . "Geboren am: {$birthDate}\n" + . "Adresse: {$street}, {$zip} {$city}\n" + . "Telefon: {$phone}\n" + . "E-Mail: {$email}\n" + . "Beitragsklasse: {$feeClass}\n" + . str_repeat('-', 40) . "\n" + . "Satzung anerkannt: ja\n" + . "Datenschutz: ja\n" + . 'Eingegangen: ' . date('d.m.Y H:i') . "\n\n" + . "Hinweis: Bankdaten werden online nicht erhoben – Beitrittserklärung\n" + . "per Post zur Unterschrift zusenden.\n"; + +$buildMailer = static function () use ($smtp): PHPMailer { + $mail = new PHPMailer(true); + $mail->isSMTP(); + $mail->Host = $smtp['host']; + $mail->Port = (int) $smtp['port']; + $mail->SMTPAuth = true; + $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; + $mail->Username = $smtp['username']; + $mail->Password = $smtp['password']; + $mail->CharSet = PHPMailer::CHARSET_UTF8; + return $mail; +}; + +// Mail 1 (intern) — erfolgskritisch. +try { + $mail = $buildMailer(); + $mail->setFrom($smtp['from'], $smtp['from_name']); + $mail->addAddress($smtp['to']); + $mail->addReplyTo($email, $firstName . ' ' . $lastName); + $mail->Subject = 'Mitgliedsantrag Fußball: ' . $firstName . ' ' . $lastName; + $mail->Body = $body; + $mail->send(); +} catch (Throwable $e) { + error_log('[' . date('c') . '] Mitgliedsantrag-Versand fehlgeschlagen: ' . $e->getMessage() . "\n", 3, STORAGE_PATH . '/logs/mail.log'); + $respond(false, 'mail'); +} + +// Mail 2 (Eingangsbestätigung an Antragsteller) — optional, Fehler nicht an Besucher leaken. +$welcome = $data['welcome_mail'] ?? null; +if (is_array($welcome) && !empty($welcome['subject']) && !empty($welcome['body'])) { + try { + $confirm = $buildMailer(); + $confirm->setFrom($smtp['from'], $smtp['from_name']); + $confirm->addAddress($email, $firstName . ' ' . $lastName); + $confirm->Subject = $welcome['subject']; + $confirm->Body = $welcome['body']; + $confirm->send(); + } catch (Throwable $e) { + error_log('[' . date('c') . '] Bestätigungsmail fehlgeschlagen: ' . $e->getMessage() . "\n", 3, STORAGE_PATH . '/logs/mail.log'); + } +} + +$respond(true); diff --git a/app/components/age-groups.php b/app/components/age-groups.php index 4c1f033..bb5d404 100644 --- a/app/components/age-groups.php +++ b/app/components/age-groups.php @@ -20,22 +20,25 @@ if ($groups === []) {

-