594 lines
24 KiB
PHP
594 lines
24 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace Mummert\SurveyBundle\Controller\FrontendModule;
|
||
|
||
use Contao\Config;
|
||
use Contao\CoreBundle\Controller\FrontendModule\AbstractFrontendModuleController;
|
||
use Contao\CoreBundle\DependencyInjection\Attribute\AsFrontendModule;
|
||
use Contao\CoreBundle\Twig\FragmentTemplate;
|
||
use Contao\FrontendUser;
|
||
use Contao\ModuleModel;
|
||
use Contao\PageModel;
|
||
use Mummert\SurveyBundle\Form\Model\SurveyEditorData;
|
||
use Mummert\SurveyBundle\Form\Model\SurveyQuestionData;
|
||
use Mummert\SurveyBundle\Form\SurveyEditorType;
|
||
use Mummert\SurveyBundle\Form\SurveyQuestionEditorType;
|
||
use Mummert\SurveyBundle\Model\SurveyModel;
|
||
use Mummert\SurveyBundle\Repository\SurveyConditionRepository;
|
||
use Mummert\SurveyBundle\Repository\SurveyEditorRepository;
|
||
use Mummert\SurveyBundle\Repository\SurveyQuestionRepository;
|
||
use Mummert\SurveyBundle\Repository\SurveyRepository;
|
||
use Mummert\SurveyBundle\Service\SurveyEditorService;
|
||
use Mummert\SurveyBundle\Service\SurveyLoginInfoService;
|
||
use Mummert\SurveyBundle\Service\SurveyStructureService;
|
||
use Mummert\SurveyBundle\Service\SurveySubmissionService;
|
||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||
use Symfony\Component\Form\FormFactoryInterface;
|
||
use Symfony\Component\Form\FormInterface;
|
||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||
use Symfony\Component\HttpFoundation\Request;
|
||
use Symfony\Component\HttpFoundation\Response;
|
||
|
||
#[AsFrontendModule(type: 'member_survey_edit', category: 'survey', template: 'member_survey_edit')]
|
||
final class MemberSurveyEditController extends AbstractFrontendModuleController
|
||
{
|
||
public function __construct(
|
||
private readonly SurveyRepository $surveyRepository,
|
||
private readonly SurveyQuestionRepository $surveyQuestionRepository,
|
||
private readonly SurveyConditionRepository $surveyConditionRepository,
|
||
private readonly SurveyEditorRepository $surveyEditorRepository,
|
||
private readonly SurveyEditorService $surveyEditorService,
|
||
private readonly SurveySubmissionService $surveySubmissionService,
|
||
private readonly SurveyStructureService $surveyStructureService,
|
||
private readonly SurveyLoginInfoService $surveyLoginInfoService,
|
||
private readonly FormFactoryInterface $formFactory,
|
||
#[Autowire('%kernel.debug%')]
|
||
private readonly bool $kernelDebug = false,
|
||
) {
|
||
}
|
||
|
||
protected function getResponse(FragmentTemplate $template, ModuleModel $model, Request $request): Response
|
||
{
|
||
$memberId = $this->resolveEditorMemberId($request);
|
||
|
||
if ($memberId <= 0) {
|
||
$template->set('loginRequired', true);
|
||
$template->set('loginUrl', $this->resolveLoginUrl());
|
||
$template->set('sessionMinutes', $this->surveyLoginInfoService->getSessionLifetimeMinutes());
|
||
$template->set('entryNotAllowed', false);
|
||
$template->set('backUrl', $this->resolveListUrl($model));
|
||
$template->set('createQuestionMode', false);
|
||
|
||
return $template->getResponse();
|
||
}
|
||
|
||
if (!$this->isEditorEntryAllowed($request)) {
|
||
$template->set('loginRequired', false);
|
||
$template->set('entryNotAllowed', true);
|
||
$template->set('createMode', false);
|
||
$template->set('survey', null);
|
||
$template->set('backUrl', $this->resolveListUrl($model));
|
||
$template->set('createQuestionMode', false);
|
||
|
||
return $template->getResponse();
|
||
}
|
||
|
||
$survey = $this->resolveSurvey($request, $memberId);
|
||
$createQuestionMode = $this->isCreateQuestionRequested($request);
|
||
|
||
if ($survey instanceof SurveyModel && $request->isMethod('POST') && $request->request->has('_survey_action')) {
|
||
return $this->handleAction($survey, $request, $model, $memberId);
|
||
}
|
||
|
||
$surveyForm = $this->formFactory->createNamed('survey_meta', SurveyEditorType::class, $survey instanceof SurveyModel ? SurveyEditorData::fromModel($survey) : new SurveyEditorData());
|
||
$surveyForm->handleRequest($request);
|
||
|
||
if ($surveyForm->isSubmitted() && $surveyForm->isValid() && (!$survey instanceof SurveyModel || '1' !== (string) $survey->published)) {
|
||
try {
|
||
if ($survey instanceof SurveyModel) {
|
||
$this->surveyEditorService->updateSurvey($survey, $memberId, $surveyForm->getData());
|
||
$this->addFlash('success', 'Die Umfrage wurde gespeichert.');
|
||
|
||
return new RedirectResponse($this->buildEditUrl($model, $request, (int) $survey->id));
|
||
}
|
||
|
||
$createdSurvey = $this->surveyEditorService->createSurvey($memberId, $surveyForm->getData());
|
||
$this->addFlash('success', 'Die Umfrage wurde angelegt.');
|
||
|
||
return new RedirectResponse($this->buildEditUrl($model, $request, (int) $createdSurvey->id));
|
||
} catch (\Throwable $exception) {
|
||
$this->addFlash('error', $exception->getMessage());
|
||
}
|
||
} elseif ($surveyForm->isSubmitted() && $survey instanceof SurveyModel && '1' === (string) $survey->published) {
|
||
$this->addFlash('error', 'Die Metadaten können nach der Veröffentlichung im Frontend nicht mehr geändert werden.');
|
||
}
|
||
|
||
if (!$survey instanceof SurveyModel) {
|
||
$template->set('loginRequired', false);
|
||
$template->set('entryNotAllowed', false);
|
||
$template->set('createMode', true);
|
||
$template->set('structureLocked', false);
|
||
$template->set('surveyForm', $surveyForm->createView());
|
||
$template->set('backUrl', $this->resolveListUrl($model));
|
||
$template->set('publicUrl', null);
|
||
$template->set('survey', null);
|
||
$template->set('outline', []);
|
||
$template->set('conditions', []);
|
||
$template->set('editors', []);
|
||
$template->set('submissions', []);
|
||
$template->set('activeQuestionId', 0);
|
||
$template->set('createQuestionMode', false);
|
||
|
||
return $template->getResponse();
|
||
}
|
||
|
||
$structureLocked = $this->surveyEditorService->isStructureLocked($survey);
|
||
$surveyId = (int) $survey->id;
|
||
|
||
$content = $this->surveyQuestionRepository->findAllBySurvey($surveyId);
|
||
$outline = $this->surveyStructureService->buildOutline($content);
|
||
$questions = array_values(array_filter($content, static fn ($item): bool => !SurveyQuestionRepository::isSection($item)));
|
||
$activeQuestion = $this->resolveActiveQuestion($request, $surveyId);
|
||
$activeQuestionId = $activeQuestion ? (int) $activeQuestion->id : 0;
|
||
$questionFormViews = [];
|
||
$newQuestionFormView = null;
|
||
$newQuestionContext = $this->resolveNewQuestionContext($request, $outline);
|
||
|
||
if (!$structureLocked) {
|
||
foreach ($content as $item) {
|
||
$itemId = (int) $item->id;
|
||
$questionForm = $this->formFactory->createNamed('survey_question_'.$itemId, SurveyQuestionEditorType::class, SurveyQuestionData::fromModel($item), [
|
||
'question_choices' => $this->buildQuestionChoices($questions, $itemId),
|
||
]);
|
||
$questionForm->handleRequest($request);
|
||
|
||
if ($questionForm->isSubmitted()) {
|
||
$activeQuestionId = $itemId;
|
||
$createQuestionMode = false;
|
||
|
||
if ($questionForm->isValid()) {
|
||
try {
|
||
$this->surveyEditorService->saveQuestion($survey, $questionForm->getData(), $itemId);
|
||
$this->addFlash('success', SurveyQuestionRepository::isSection($item) ? 'Der Themenbereich wurde aktualisiert.' : 'Die Frage wurde aktualisiert.');
|
||
|
||
return new RedirectResponse($this->buildEditUrl($model, $request, $surveyId));
|
||
} catch (\Throwable $exception) {
|
||
$this->addFlash('error', $exception->getMessage());
|
||
}
|
||
} else {
|
||
$this->addFlash('error', 'Frage konnte nicht gespeichert werden: '.$this->describeFormErrors($questionForm));
|
||
}
|
||
}
|
||
|
||
$questionFormViews[$itemId] = $questionForm->createView();
|
||
}
|
||
|
||
$newQuestionData = new SurveyQuestionData();
|
||
$newQuestionData->type = $newQuestionContext['type'];
|
||
$newQuestionData->insertAfter = $newQuestionContext['insertAfter'];
|
||
|
||
$newQuestionForm = $this->formFactory->createNamed('survey_question_new', SurveyQuestionEditorType::class, $newQuestionData, [
|
||
'question_choices' => $this->buildQuestionChoices($questions),
|
||
]);
|
||
$newQuestionForm->handleRequest($request);
|
||
|
||
if ($newQuestionForm->isSubmitted()) {
|
||
$activeQuestionId = 0;
|
||
$createQuestionMode = true;
|
||
|
||
if ($newQuestionForm->isValid()) {
|
||
try {
|
||
/** @var SurveyQuestionData $data */
|
||
$data = $newQuestionForm->getData();
|
||
$insertAfterId = (int) ($data->insertAfter ?? 0);
|
||
$this->surveyEditorService->saveQuestion($survey, $data, 0, $insertAfterId > 0 ? $insertAfterId : null);
|
||
$this->addFlash('success', SurveyQuestionRepository::TYPE_SECTION === $data->type ? 'Der Themenbereich wurde angelegt.' : 'Die Frage wurde angelegt.');
|
||
|
||
return new RedirectResponse($this->buildEditUrl($model, $request, $surveyId));
|
||
} catch (\Throwable $exception) {
|
||
$this->addFlash('error', $exception->getMessage());
|
||
}
|
||
} else {
|
||
$this->addFlash('error', 'Neue Frage konnte nicht gespeichert werden: '.$this->describeFormErrors($newQuestionForm));
|
||
}
|
||
}
|
||
|
||
$newQuestionFormView = $newQuestionForm->createView();
|
||
}
|
||
|
||
$template->set('loginRequired', false);
|
||
$template->set('entryNotAllowed', false);
|
||
$template->set('createMode', false);
|
||
$template->set('structureLocked', $structureLocked);
|
||
$template->set('createQuestionMode', $createQuestionMode);
|
||
$template->set('newQuestionContext', $newQuestionContext);
|
||
$template->set('survey', $survey);
|
||
$template->set('surveyForm', $surveyForm->createView());
|
||
$template->set('questionForms', $questionFormViews);
|
||
$template->set('newQuestionForm', $newQuestionFormView);
|
||
$template->set('outline', $outline);
|
||
$template->set('hasSections', count($outline) !== count($questions));
|
||
$template->set('canQuestionReorder', !$structureLocked && count($content) > 1);
|
||
$conditionOverview = $this->surveyConditionRepository->findOverviewBySurvey($surveyId);
|
||
|
||
$template->set('conditions', $this->buildJumpRuleOverview($questions, $conditionOverview));
|
||
$template->set('editors', $this->surveyEditorRepository->findEditorsBySurvey($surveyId));
|
||
$template->set('submissions', $this->surveySubmissionService->getSubmissionOverview($survey));
|
||
$template->set('activeQuestionId', $activeQuestionId);
|
||
$template->set('backUrl', $this->resolveListUrl($model));
|
||
$template->set('publicUrl', $this->resolveReaderUrl($model, (string) $survey->alias));
|
||
$template->set('metadataFormActionUrl', $this->buildEditUrl($model, $request, $surveyId));
|
||
$template->set('editBaseUrl', $this->buildEditUrl($model, $request, $surveyId));
|
||
|
||
return $template->getResponse();
|
||
}
|
||
|
||
private function resolveSurvey(Request $request, int $memberId): ?SurveyModel
|
||
{
|
||
$surveyId = (int) $request->query->get('survey', 0);
|
||
|
||
if ($surveyId <= 0) {
|
||
return null;
|
||
}
|
||
|
||
$survey = $this->surveyRepository->findById($surveyId);
|
||
|
||
if (!$survey instanceof SurveyModel) {
|
||
throw new \RuntimeException('Die Umfrage wurde nicht gefunden.');
|
||
}
|
||
|
||
if (!$this->surveyEditorRepository->isEditor((int) $survey->id, $memberId)) {
|
||
throw new \RuntimeException('Sie dürfen diese Umfrage nicht bearbeiten.');
|
||
}
|
||
|
||
return $survey;
|
||
}
|
||
|
||
private function resolveEditorMemberId(Request $request): int
|
||
{
|
||
$user = $this->getUser();
|
||
|
||
if ($user instanceof FrontendUser) {
|
||
return (int) $user->id;
|
||
}
|
||
|
||
return $this->isDebugAccessAllowed($request) ? $this->resolveDebugMemberId($request) : 0;
|
||
}
|
||
|
||
private function resolveDebugMemberId(Request $request): int
|
||
{
|
||
$memberId = (int) $request->query->get('debugMember', 0);
|
||
|
||
if ($memberId > 0) {
|
||
return $memberId;
|
||
}
|
||
|
||
$surveyId = (int) $request->query->get('survey', 0);
|
||
|
||
if ($surveyId <= 0) {
|
||
return 0;
|
||
}
|
||
|
||
$memberIds = $this->surveyEditorRepository->findMemberIdsBySurvey($surveyId);
|
||
|
||
return $memberIds[0] ?? 0;
|
||
}
|
||
|
||
/**
|
||
* Debug-Zugang ohne Login: ausschließlich im Debug-Modus des Kernels (ddev/lokal)
|
||
* und nur auf lokalen Hosts. In Produktion (kernel.debug = false) ist er tot –
|
||
* unabhängig vom Host-Header.
|
||
*/
|
||
private function isDebugAccessAllowed(Request $request): bool
|
||
{
|
||
if (!$this->kernelDebug || !$request->query->getBoolean('debugAccess')) {
|
||
return false;
|
||
}
|
||
|
||
$host = strtolower($request->getHost());
|
||
|
||
return 'localhost' === $host
|
||
|| '127.0.0.1' === $host
|
||
|| str_ends_with($host, '.ddev.site');
|
||
}
|
||
|
||
private function handleAction(SurveyModel $survey, Request $request, ModuleModel $model, int $memberId): Response
|
||
{
|
||
$action = (string) $request->request->get('_survey_action');
|
||
$itemId = (int) $request->request->get('item_id', 0);
|
||
$token = (string) $request->request->get('_token');
|
||
|
||
if (!$this->isCsrfTokenValid($action.'-'.$itemId, $token)) {
|
||
throw new \RuntimeException('Ungültiger CSRF-Token.');
|
||
}
|
||
|
||
try {
|
||
if ('delete-question' === $action) {
|
||
$item = $this->surveyQuestionRepository->findByIdForSurvey((int) $survey->id, $itemId);
|
||
$this->surveyEditorService->deleteQuestion($survey, $itemId);
|
||
$this->addFlash('success', SurveyQuestionRepository::isSection($item) ? 'Der Themenbereich wurde gelöscht. Die zugehörigen Fragen bleiben erhalten.' : 'Die Frage wurde gelöscht.');
|
||
}
|
||
|
||
if ('reorder-questions' === $action) {
|
||
$this->surveyEditorService->reorderQuestions($survey, $this->parseQuestionOrder($request));
|
||
$this->addFlash('success', 'Die neue Reihenfolge der Fragen wurde gespeichert.');
|
||
}
|
||
|
||
if ('delete-condition' === $action) {
|
||
$this->surveyEditorService->deleteCondition($survey, $itemId);
|
||
$this->addFlash('success', 'Die Bedingung wurde gelöscht.');
|
||
}
|
||
} catch (\Throwable $exception) {
|
||
$this->addFlash('error', $exception->getMessage());
|
||
}
|
||
|
||
return new RedirectResponse($this->buildEditUrl($model, $request, (int) $survey->id));
|
||
}
|
||
|
||
/**
|
||
* @return list<int>
|
||
*/
|
||
private function parseQuestionOrder(Request $request): array
|
||
{
|
||
$rawOrder = trim((string) $request->request->get('question_order', ''));
|
||
|
||
if ('' === $rawOrder) {
|
||
throw new \RuntimeException('Die neue Reihenfolge der Fragen fehlt.');
|
||
}
|
||
|
||
return array_values(array_filter(
|
||
array_map('intval', explode(',', $rawOrder)),
|
||
static fn (int $questionId): bool => $questionId > 0,
|
||
));
|
||
}
|
||
|
||
private function resolveActiveQuestion(Request $request, int $surveyId): mixed
|
||
{
|
||
$questionId = (int) $request->query->get('question', 0);
|
||
|
||
return $questionId > 0 ? $this->surveyQuestionRepository->findByIdForSurvey($surveyId, $questionId) : null;
|
||
}
|
||
|
||
private function isCreateQuestionRequested(Request $request): bool
|
||
{
|
||
return 'new' === trim((string) $request->query->get('question', ''));
|
||
}
|
||
|
||
/**
|
||
* Kontext für das "Neu anlegen"-Panel: gewünschter Typ (Frage/Themenbereich)
|
||
* und die Position ("hinter Inhalt X" = am Ende eines Themenbereichs).
|
||
*
|
||
* @param list<array<string, mixed>> $outline
|
||
*
|
||
* @return array{type:string,insertAfter:int|null,sectionTitle:string|null}
|
||
*/
|
||
private function resolveNewQuestionContext(Request $request, array $outline): array
|
||
{
|
||
$type = trim((string) $request->query->get('newType', ''));
|
||
$insertAfter = (int) $request->query->get('after', 0);
|
||
$sectionTitle = null;
|
||
|
||
if (SurveyQuestionRepository::TYPE_SECTION !== $type) {
|
||
$type = 'yes_no_maybe';
|
||
}
|
||
|
||
if ($insertAfter > 0) {
|
||
$found = false;
|
||
|
||
foreach ($outline as $entry) {
|
||
if ($entry['id'] === $insertAfter) {
|
||
$found = true;
|
||
$sectionTitle = $entry['sectionTitle'];
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!$found) {
|
||
$insertAfter = 0;
|
||
}
|
||
}
|
||
|
||
return [
|
||
'type' => $type,
|
||
'insertAfter' => $insertAfter > 0 ? $insertAfter : null,
|
||
'sectionTitle' => $sectionTitle,
|
||
];
|
||
}
|
||
|
||
private function isEditorEntryAllowed(Request $request): bool
|
||
{
|
||
if ((int) $request->query->get('survey', 0) > 0) {
|
||
return true;
|
||
}
|
||
|
||
return $request->query->getBoolean('create');
|
||
}
|
||
|
||
/**
|
||
* Sprungziel-Auswahl: nur Fragen (keine Themenbereiche), mit Positionsnummern.
|
||
*
|
||
* @param list<\Mummert\SurveyBundle\Model\SurveyContentModel> $questions
|
||
*
|
||
* @return array<int, string>
|
||
*/
|
||
private function buildQuestionChoices(array $questions, int $excludeQuestionId = 0): array
|
||
{
|
||
$choices = [];
|
||
$position = 1;
|
||
|
||
foreach ($questions as $question) {
|
||
if ($excludeQuestionId > 0 && (int) $question->id === $excludeQuestionId) {
|
||
++$position;
|
||
continue;
|
||
}
|
||
|
||
$choices[(int) $question->id] = sprintf('%d. %s', $position++, (string) $question->question);
|
||
}
|
||
|
||
return $choices;
|
||
}
|
||
|
||
/**
|
||
* @param array<int, mixed> $questions
|
||
* @param list<array<string, mixed>> $conditionOverview
|
||
*
|
||
* @return list<array<string, mixed>>
|
||
*/
|
||
private function buildJumpRuleOverview(array $questions, array $conditionOverview): array
|
||
{
|
||
$questionLabels = [];
|
||
$questionSortings = [];
|
||
$questionPositions = [];
|
||
$rules = [];
|
||
$position = 1;
|
||
|
||
foreach ($questions as $question) {
|
||
$questionId = (int) ($question->id ?? 0);
|
||
|
||
if ($questionId <= 0) {
|
||
continue;
|
||
}
|
||
|
||
$questionLabels[$questionId] = (string) ($question->question ?? '');
|
||
$questionSortings[$questionId] = (int) ($question->sorting ?? 0);
|
||
$questionPositions[$questionId] = $position++;
|
||
}
|
||
|
||
foreach ($questions as $question) {
|
||
$questionId = (int) ($question->id ?? 0);
|
||
|
||
if ($questionId <= 0) {
|
||
continue;
|
||
}
|
||
|
||
if ('yes_no_maybe' !== (string) ($question->type ?? '')) {
|
||
continue;
|
||
}
|
||
|
||
foreach (['Ja' => (int) ($question->jumpOnYes ?? 0), 'Nein' => (int) ($question->jumpOnNo ?? 0)] as $answerValue => $targetQuestionId) {
|
||
if ($targetQuestionId <= 0 || !isset($questionLabels[$targetQuestionId])) {
|
||
continue;
|
||
}
|
||
|
||
$rules[] = [
|
||
'id' => 'question-'.$questionId.'-'.$targetQuestionId.'-'.$answerValue,
|
||
'answerValue' => $answerValue,
|
||
'sourceQuestion' => $questionId,
|
||
'targetQuestion' => $targetQuestionId,
|
||
'sourcePosition' => $questionPositions[$questionId] ?? 0,
|
||
'targetPosition' => $questionPositions[$targetQuestionId] ?? 0,
|
||
'sourceQuestionLabel' => (string) ($question->question ?? ''),
|
||
'targetQuestionLabel' => $questionLabels[$targetQuestionId] ?? '',
|
||
'sourceSorting' => $questionSortings[$questionId] ?? 0,
|
||
];
|
||
}
|
||
}
|
||
|
||
foreach ($conditionOverview as $condition) {
|
||
$sourceQuestionId = (int) ($condition['sourceQuestion'] ?? 0);
|
||
|
||
$rules[] = [
|
||
'id' => $condition['id'] ?? 0,
|
||
'answerValue' => (string) ($condition['answerValue'] ?? ''),
|
||
'sourceQuestion' => $sourceQuestionId,
|
||
'targetQuestion' => (int) ($condition['targetQuestion'] ?? 0),
|
||
'sourcePosition' => $questionPositions[$sourceQuestionId] ?? 0,
|
||
'targetPosition' => $questionPositions[(int) ($condition['targetQuestion'] ?? 0)] ?? 0,
|
||
'sourceQuestionLabel' => (string) ($condition['sourceQuestionLabel'] ?? ''),
|
||
'targetQuestionLabel' => (string) ($condition['targetQuestionLabel'] ?? ''),
|
||
'sourceSorting' => $questionSortings[$sourceQuestionId] ?? 0,
|
||
];
|
||
}
|
||
|
||
usort($rules, static function (array $left, array $right): int {
|
||
$sortingComparison = ((int) ($left['sourceSorting'] ?? 0)) <=> ((int) ($right['sourceSorting'] ?? 0));
|
||
|
||
if (0 !== $sortingComparison) {
|
||
return $sortingComparison;
|
||
}
|
||
|
||
return ((int) ($left['targetQuestion'] ?? 0)) <=> ((int) ($right['targetQuestion'] ?? 0));
|
||
});
|
||
|
||
return $rules;
|
||
}
|
||
|
||
private function resolveListUrl(ModuleModel $model): string
|
||
{
|
||
$page = $this->resolvePage((int) ($model->surveyListPage ?? 0)) ?? $this->getPageModel();
|
||
|
||
return $page instanceof PageModel ? $this->generateContentUrl($page) : '/';
|
||
}
|
||
|
||
private function resolveReaderUrl(ModuleModel $model, string $publicAlias): ?string
|
||
{
|
||
$page = $this->resolvePage((int) $this->getContaoAdapter(Config::class)->get('surveyReaderPage'));
|
||
|
||
if (!$page instanceof PageModel) {
|
||
return null;
|
||
}
|
||
|
||
return $this->generateContentUrl($page, ['auto_item' => $publicAlias]);
|
||
}
|
||
|
||
private function buildEditUrl(ModuleModel $model, Request $request, int $surveyId): string
|
||
{
|
||
$parameters = ['survey' => $surveyId];
|
||
|
||
if ($request->query->getBoolean('debugAccess') && $this->isDebugAccessAllowed($request)) {
|
||
$parameters['debugAccess'] = '1';
|
||
}
|
||
|
||
$debugMemberId = (int) $request->query->get('debugMember', 0);
|
||
|
||
if ($debugMemberId > 0) {
|
||
$parameters['debugMember'] = (string) $debugMemberId;
|
||
}
|
||
|
||
$basePath = $request->getBaseUrl().$request->getPathInfo();
|
||
|
||
if ('' !== $basePath) {
|
||
$queryString = http_build_query($parameters);
|
||
$url = $basePath.('' !== $queryString ? '?'.$queryString : '');
|
||
} else {
|
||
$page = $this->getPageModel();
|
||
$url = $page instanceof PageModel ? $this->generateContentUrl($page, $parameters) : $this->resolveListUrl($model);
|
||
}
|
||
|
||
return $url;
|
||
}
|
||
|
||
private function describeFormErrors(FormInterface $form): string
|
||
{
|
||
$messages = [];
|
||
|
||
foreach ($form->getErrors(true, true) as $error) {
|
||
$origin = $error->getOrigin();
|
||
$name = $origin instanceof FormInterface ? $origin->getName() : 'form';
|
||
$messages[] = sprintf('%s: %s', $name, $error->getMessage());
|
||
}
|
||
|
||
return [] !== $messages ? implode(' | ', array_unique($messages)) : 'Unbekannter Formularfehler.';
|
||
}
|
||
|
||
private function resolvePage(int $pageId): ?PageModel
|
||
{
|
||
if ($pageId <= 0) {
|
||
return null;
|
||
}
|
||
|
||
$page = $this->getContaoAdapter(PageModel::class)->findById($pageId);
|
||
|
||
return $page instanceof PageModel ? $page : null;
|
||
}
|
||
|
||
private function resolveLoginUrl(): ?string
|
||
{
|
||
$page = $this->surveyLoginInfoService->findLoginPage();
|
||
|
||
return $page instanceof PageModel ? $this->generateContentUrl($page) : null;
|
||
}
|
||
}
|