| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- <?php
- declare(strict_types=1);
- use App\App\Bootstrap;
- use App\Form\FormSchema;
- use App\Security\Csrf;
- use App\Security\FormAccess;
- use App\Storage\FileUploadStore;
- use App\Storage\JsonStore;
- require dirname(__DIR__) . '/src/autoload.php';
- Bootstrap::init();
- if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- Bootstrap::jsonResponse([
- 'ok' => false,
- 'message' => Bootstrap::appMessage('common.method_not_allowed'),
- ], 405);
- }
- $csrf = $_POST['csrf'] ?? '';
- if (!Csrf::validate(is_string($csrf) ? $csrf : null)) {
- Bootstrap::jsonResponse([
- 'ok' => false,
- 'message' => Bootstrap::appMessage('common.invalid_csrf'),
- ], 419);
- }
- if (trim((string) ($_POST['website'] ?? '')) !== '') {
- Bootstrap::jsonResponse([
- 'ok' => false,
- 'message' => Bootstrap::appMessage('common.request_blocked'),
- ], 400);
- }
- $email = strtolower(trim((string) ($_POST['email'] ?? '')));
- if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
- Bootstrap::jsonResponse([
- 'ok' => false,
- 'message' => Bootstrap::appMessage('common.invalid_email'),
- ], 422);
- }
- $activityRaw = $_POST['last_user_activity_at'] ?? null;
- $lastUserActivityAt = is_scalar($activityRaw) ? (int) $activityRaw : null;
- $formAccess = new FormAccess();
- $auth = $formAccess->assertVerifiedForEmail($email, $lastUserActivityAt);
- if (($auth['ok'] ?? false) !== true) {
- $reason = (string) ($auth['reason'] ?? '');
- Bootstrap::jsonResponse([
- 'ok' => false,
- 'message' => (string) ($auth['message'] ?? 'Bitte E-Mail erneut verifizieren.'),
- 'auth_required' => $reason === 'auth_required',
- 'auth_expired' => $reason === 'auth_expired',
- ], (int) ($auth['status_code'] ?? 401));
- }
- $step = (int) ($_POST['step'] ?? 1);
- $formDataRaw = $_POST['form_data'] ?? [];
- $formData = [];
- if (is_array($formDataRaw)) {
- foreach ($formDataRaw as $key => $value) {
- if (!is_string($key)) {
- continue;
- }
- $formData[$key] = is_array($value) ? '' : trim((string) $value);
- }
- }
- $store = new JsonStore();
- try {
- $result = $store->withEmailLock($email, static function () use ($store, $email, $step, $formData): array {
- if ($store->hasSubmission($email)) {
- return [
- 'blocked' => true,
- 'message' => Bootstrap::appMessage('save_draft.already_submitted'),
- ];
- }
- return [
- 'blocked' => false,
- 'draft' => $store->saveDraft($email, [
- 'step' => max(1, $step),
- 'form_data' => $formData,
- 'uploads' => [],
- ]),
- ];
- });
- } catch (Throwable $e) {
- Bootstrap::log('app', 'save-draft lock error: ' . $e->getMessage());
- Bootstrap::jsonResponse([
- 'ok' => false,
- 'message' => Bootstrap::appMessage('save_draft.lock_error'),
- ], 500);
- }
- if (($result['blocked'] ?? false) === true) {
- Bootstrap::jsonResponse([
- 'ok' => false,
- 'already_submitted' => true,
- 'message' => (string) ($result['message'] ?? Bootstrap::appMessage('save_draft.blocked_fallback')),
- ], 409);
- }
- $schema = new FormSchema();
- $uploadStore = new FileUploadStore();
- $uploadResult = $uploadStore->processUploads($_FILES, $schema->getUploadFields(), $store->emailKey($email));
- if (!empty($uploadResult['uploads'])) {
- try {
- $store->withEmailLock($email, static function () use ($store, $email, $step, $formData, $uploadResult): void {
- if ($store->hasSubmission($email)) {
- return;
- }
- $store->saveDraft($email, [
- 'step' => max(1, $step),
- 'form_data' => $formData,
- 'uploads' => $uploadResult['uploads'],
- ]);
- });
- } catch (Throwable $e) {
- Bootstrap::log('app', 'save-draft upload merge error: ' . $e->getMessage());
- }
- }
- $draft = $store->getDraft($email);
- Bootstrap::jsonResponse([
- 'ok' => true,
- 'message' => Bootstrap::appMessage('save_draft.success'),
- 'updated_at' => $draft['updated_at'] ?? null,
- 'upload_errors' => $uploadResult['errors'],
- 'uploads' => $draft['uploads'] ?? [],
- ]);
|