getUser(); $backUrl = $this->resolveBackUrl($request, $model); $eventParam = $request->query->get('event'); $isCreateMode = '1' === (string) $request->query->get('create', '0') && (null === $eventParam || (int) $eventParam <= 0); if (!$user instanceof FrontendUser) { $template->set('error', 'Bitte zuerst als Mitglied einloggen.'); $template->set('backUrl', $backUrl); return $template->getResponse(); } $eventId = $isCreateMode ? 0 : (int) $eventParam; $event = null; if (!$isCreateMode) { if ($eventId <= 0 || !$this->eventRepository->memberHasEvent((int) $user->id, $eventId)) { $template->set('error', 'Keine Berechtigung für diese Veranstaltung oder ungültige ID.'); $template->set('backUrl', $backUrl); return $template->getResponse(); } $event = $this->eventRepository->findById($eventId); if (null === $event) { $template->set('error', 'Veranstaltung nicht gefunden.'); $template->set('backUrl', $backUrl); return $template->getResponse(); } } if ($isCreateMode) { $event = [ 'title' => '', 'startDate' => null, 'endDate' => null, 'addTime' => '', 'startTime' => null, 'endTime' => null, 'location_id' => 0, 'tags' => null, 'teaser' => '', 'description' => '', 'url' => '', 'photographer' => '', 'addImage' => '', 'termsAccepted' => '', 'isSoldOut' => '', 'isCanceled' => '', 'published' => '', 'singleSRC' => null, ]; } $memberOrganizationIds = $this->eventRepository->getOrganizationIdsForMember((int) $user->id); $allowedEventTagIds = array_values(array_unique(array_map('intval', StringUtil::deserialize($model->eventTypeTags ?? null, true)))); $organizationChoices = $this->eventRepository->getOrganizationChoicesForMember((int) $user->id); $showOrganization = count($memberOrganizationIds) > 1; $currentOrganizationIds = $this->eventRepository->getOrganizationIdsForEvent($eventId); $currentTagIds = $this->eventRepository->getTagIdsForEvent($eventId); $formData = [ 'title' => (string) ($event['title'] ?? ''), 'startDate' => !empty($event['startDate']) ? date('Y-m-d', (int) $event['startDate']) : '', 'endDate' => !empty($event['endDate']) ? date('Y-m-d', (int) $event['endDate']) : '', 'addTime' => '1' === (string) ($event['addTime'] ?? ''), 'startTime' => ('1' === (string) ($event['addTime'] ?? '') && !empty($event['startTime'])) ? date('H:i', (int) $event['startTime']) : '', 'endTime' => $this->resolveFormEndTime($event), 'location_id' => (int) ($event['location_id'] ?? 0), 'tags' => $currentTagIds, 'teaser' => '' !== trim((string) ($event['teaser'] ?? '')) ? (string) ($event['teaser'] ?? '') : (string) ($event['description'] ?? ''), 'url' => (string) ($event['url'] ?? ''), 'photographer' => (string) ($event['photographer'] ?? ''), 'addImage' => '1' === (string) ($event['addImage'] ?? ''), 'termsAccepted' => '1' === (string) ($event['termsAccepted'] ?? ''), 'isSoldOut' => '1' === (string) ($event['isSoldOut'] ?? ''), 'isCanceled' => '1' === (string) ($event['isCanceled'] ?? ''), 'published' => '1' === (string) ($event['published'] ?? ''), ]; if ($showOrganization) { $allowedOrganizationIds = array_values(array_unique(array_map('intval', $memberOrganizationIds))); $selectedOrganizationIds = array_values(array_intersect($currentOrganizationIds, $allowedOrganizationIds)); if ([] === $selectedOrganizationIds && [] !== $allowedOrganizationIds) { $selectedOrganizationIds = [(int) $allowedOrganizationIds[0]]; } $formData['organization_ids'] = $selectedOrganizationIds; } $currentImagePath = null; if (!empty($event['singleSRC'])) { $imageModel = FilesModel::findByUuid((string) $event['singleSRC']); if (null !== $imageModel) { $currentImagePath = $imageModel->path; } } $form = $this->createForm(EventType::class, $formData, [ 'location_choices' => $this->eventRepository->getLocationChoices(), 'tag_choices' => $this->eventRepository->getTagChoicesForEventType($allowedEventTagIds), 'organization_choices' => $organizationChoices, 'selected_organization_ids' => $showOrganization ? ($formData['organization_ids'] ?? []) : [], 'show_organization' => $showOrganization, 'terms_page_url' => $this->resolveTermsPageUrl($model), ]); $form->handleRequest($request); if ($form->isSubmitted()) { $submittedData = (array) $form->getData(); if (!empty($submittedData['addImage']) && '' === trim((string) ($submittedData['photographer'] ?? ''))) { $form->get('photographer')->addError(new FormError('Die Angabe des Urhebers ist notwendig. Ihnen muss eine Genehmigung zur Verwendung des Bildes vorliegen.')); } if (!empty($submittedData['addTime']) && '' === trim((string) ($submittedData['startTime'] ?? ''))) { $form->get('startTime')->addError(new FormError('Bitte geben Sie eine Startzeit an.')); } } if ($form->isSubmitted() && $form->isValid()) { $submittedData = (array) $form->getData(); $selectedOrganizationIds = []; if ($showOrganization) { $selectedOrganizationIds = array_map('intval', (array) $form->get('organization_ids')->getData()); } elseif ([] !== $memberOrganizationIds) { $selectedOrganizationIds = [(int) $memberOrganizationIds[0]]; } $allowedOrganizationIds = array_values(array_unique(array_map('intval', $memberOrganizationIds))); $selectedOrganizationIds = array_values(array_intersect($selectedOrganizationIds, $allowedOrganizationIds)); if ([] === $selectedOrganizationIds) { if ($showOrganization) { $form->get('organization_ids')->addError(new FormError('Bitte mindestens eine Organisation auswählen.')); } else { $form->addError(new FormError('Keine gültige Veranstalter-Zuordnung vorhanden.')); } } if ($form->isSubmitted() && !$form->isValid()) { $template->set('form', $form->createView()); $template->set('backUrl', $backUrl); $template->set('requestToken', $this->container->get('contao.csrf.token_manager')->getDefaultTokenValue()); $template->set('currentImagePath', $currentImagePath); return $template->getResponse(); } if ($isCreateMode) { $createdEventId = $this->eventRepository->createForMember( (int) $user->id, (int) ($model->frontendAuthorId ?? 0), (int) ($model->frontendArchiveId ?? 0), $submittedData, $selectedOrganizationIds, ); if (null === $createdEventId) { $form->addError(new FormError('Die Veranstaltung konnte nicht erstellt werden.')); $template->set('form', $form->createView()); $template->set('backUrl', $backUrl); $template->set('requestToken', $this->container->get('contao.csrf.token_manager')->getDefaultTokenValue()); $template->set('currentImagePath', $currentImagePath); return $template->getResponse(); } $eventId = $createdEventId; } else { if ($showOrganization) { $this->eventRepository->assignEventToOrganizations($eventId, $selectedOrganizationIds); } $this->eventRepository->update($eventId, $submittedData); } $selectedTagIds = array_values(array_unique(array_map('intval', (array) ($submittedData['tags'] ?? [])))); if ([] !== $allowedEventTagIds) { $selectedTagIds = array_values(array_intersect($selectedTagIds, $allowedEventTagIds)); } $this->eventRepository->assignTagsToEvent($eventId, $selectedTagIds); $useImage = !empty($submittedData['addImage']); $removeImage = '1' === (string) $request->request->get('remove_image', '0'); $uploadedImage = $form->get('eventUpload')->getData(); if (!$useImage) { $this->eventRepository->updateImageFields($eventId, false, null); } elseif ($uploadedImage instanceof UploadedFile) { $newImageUuid = $this->storeEventImage($uploadedImage, $model, $eventId); if (null !== $newImageUuid) { $this->eventRepository->updateImageFields($eventId, true, $newImageUuid); } } elseif ($removeImage) { $this->eventRepository->updateImageFields($eventId, true, null); } if ($request->request->has('save_back')) { return new RedirectResponse($backUrl); } if ($isCreateMode) { return new RedirectResponse($this->buildEventEditUrl($eventId, $backUrl)); } return new RedirectResponse($request->getUri()); } $template->set('form', $form->createView()); $template->set('backUrl', $backUrl); $template->set('requestToken', $this->container->get('contao.csrf.token_manager')->getDefaultTokenValue()); $template->set('currentImagePath', $currentImagePath); return $template->getResponse(); } private function storeEventImage(UploadedFile $uploadedFile, ModuleModel $model, int $eventId): ?string { if (empty($model->eventFolder)) { return null; } $folderModel = FilesModel::findByUuid((string) $model->eventFolder); if (null === $folderModel) { return null; } $organization = $this->eventRepository->findPrimaryOrganizationForEvent($eventId); if (null === $organization) { return null; } $titleSlug = strtolower(StringUtil::generateAlias((string) $organization['title'])); $titleSlug = preg_replace('/[^a-z0-9-]+/', '-', $titleSlug ?? '') ?? ''; $titleSlug = trim($titleSlug, '-'); $titleSlug = substr($titleSlug, 0, 12); if ('' === $titleSlug) { $titleSlug = 'organization'; } $uploadBasePath = trim((string) $folderModel->path, '/'); if ('' === $uploadBasePath) { return null; } $targetRelativeDir = sprintf('%s/org-%d-%s', $uploadBasePath, (int) $organization['id'], $titleSlug); $projectDir = (string) $this->getParameter('kernel.project_dir'); $targetAbsoluteDir = rtrim($projectDir, '/').'/'.$targetRelativeDir; if (!is_dir($targetAbsoluteDir) && !mkdir($targetAbsoluteDir, 0775, true) && !is_dir($targetAbsoluteDir)) { return null; } $originalName = pathinfo($uploadedFile->getClientOriginalName(), PATHINFO_FILENAME); $safeName = preg_replace('/[^a-zA-Z0-9_-]+/', '-', (string) $originalName); $safeName = trim((string) $safeName, '-'); if ('' === $safeName) { $safeName = 'event-image'; } $extension = $uploadedFile->guessExtension() ?: $uploadedFile->getClientOriginalExtension() ?: 'bin'; $filename = sprintf('%s-%s.%s', $safeName, uniqid('', true), strtolower((string) $extension)); $uploadedFile->move($targetAbsoluteDir, $filename); $relativePath = $targetRelativeDir.'/'.$filename; $fileModel = Dbafs::addResource($relativePath); return null !== $fileModel ? (string) $fileModel->uuid : null; } private function resolveBackUrl(Request $request, ModuleModel $model): string { if ((int) ($model->listPage ?? 0) > 0) { $listPage = $this->getContaoAdapter(PageModel::class)->findById((int) $model->listPage); if ($listPage instanceof PageModel) { return $this->generateContentUrl($listPage); } } $ref = (string) $request->query->get('ref', ''); if ('' !== $ref) { $decoded = base64_decode($ref, true); if (false !== $decoded && str_starts_with($decoded, '/')) { return $decoded; } } $page = $this->getPageModel(); return $page instanceof PageModel ? $this->generateContentUrl($page) : '/'; } private function resolveTermsPageUrl(ModuleModel $model): ?string { if ((int) ($model->termsPage ?? 0) <= 0) { return null; } $termsPage = $this->getContaoAdapter(PageModel::class)->findById((int) $model->termsPage); if (!$termsPage instanceof PageModel) { return null; } return $this->generateContentUrl($termsPage); } private function buildEventEditUrl(int $eventId, string $backUrl): string { $page = $this->getPageModel(); if (!$page instanceof PageModel) { return '/'; } return $this->generateContentUrl($page, [ 'event' => (string) $eventId, 'ref' => base64_encode($backUrl), ]); } private function resolveFormEndTime(array $event): string { if ('1' !== (string) ($event['addTime'] ?? '')) { return ''; } $startTime = (int) ($event['startTime'] ?? 0); $endTime = (int) ($event['endTime'] ?? 0); if ($endTime <= 0 || $startTime <= 0) { return ''; } if ($endTime === $startTime || $endTime - $startTime === 86399) { return ''; } return date('H:i', $endTime); } }