mirror of
https://github.com/MarijnDoeve/TijdVoorDeTest.git
synced 2026-07-05 07:00:14 +02:00
281462fab8
* Added Gedmo stuff, fix translations * Add CSRF token validation across backoffice forms - Added CSRF validations to candidate correction, penalty, answer saving, and elimination forms. - Updated corresponding Twig templates to include CSRF token inputs. - Adjusted column count in `tab_result` template to maintain layout consistency. * Add unique index constraint for `quiz_candidate` with soft delete support - Updated migration to include a unique index on `quiz_candidate` table that excludes soft-deleted records. - Adjusted `QuizCandidate` entity to reflect the new unique constraint with `deleted_at` condition. * Add CSRF token validation for quiz-related actions - Added CSRF validation to `enableQuiz`, `clearQuiz`, `deleteQuiz`, `toggleCandidate`, and `prepareElimination` actions. - Updated Twig templates to replace links with POST forms to include CSRF tokens. - Set HTTP method restrictions for related endpoints to `POST`. * Fix unique index condition for `quiz_candidate` with soft deletes - Updated condition in unique index definition of `quiz_candidate` to add parentheses for clarity. - Adjusted related migration to reflect the revised condition. * Remove if for post an use methods in Route instead * Refactor CSRF token validation in backoffice controllers - Applied `#[IsCsrfTokenValid]` attribute for CSRF checks to simplify and standardize validation. - Removed manual `isCsrfTokenValid` calls and associated exception throwing. - Updated method signatures across affected endpoints to remove unnecessary `Request` dependency. - Ensured consistency in route HTTP method restrictions where applicable. * Add rector and phpstan * Add validation for answering incorrect quiz question - Added logic to prevent candidates from answering questions out of sequence in `QuizController`. - Updated Dutch translations to include the new error message. * Things
78 lines
3.2 KiB
PHP
78 lines
3.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tvdt\Controller;
|
|
|
|
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpKernel\Attribute\AsController;
|
|
use Symfony\Component\Routing\Attribute\Route;
|
|
use Symfony\Component\Routing\Requirement\Requirement;
|
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
|
use Tvdt\Entity\Candidate;
|
|
use Tvdt\Entity\Elimination;
|
|
use Tvdt\Enum\FlashType;
|
|
use Tvdt\Form\EliminationEnterNameType;
|
|
use Tvdt\Helpers\Base64;
|
|
use Tvdt\Repository\CandidateRepository;
|
|
use Tvdt\Security\Voter\SeasonVoter;
|
|
|
|
use function Symfony\Component\Translation\t;
|
|
|
|
#[AsController]
|
|
#[IsGranted('ROLE_USER')]
|
|
final class EliminationController extends AbstractController
|
|
{
|
|
public function __construct(private readonly TranslatorInterface $translator, private readonly CandidateRepository $candidateRepository) {}
|
|
|
|
#[IsGranted(SeasonVoter::ELIMINATION, 'elimination')]
|
|
#[Route('/elimination/{elimination}', name: 'tvdt_elimination', requirements: ['elimination' => Requirement::UUID])]
|
|
public function index(#[MapEntity] Elimination $elimination, Request $request): Response
|
|
{
|
|
$form = $this->createForm(EliminationEnterNameType::class);
|
|
|
|
$form->handleRequest($request);
|
|
|
|
if ($form->isSubmitted() && $form->isValid()) {
|
|
$name = $form->get('name')->getData();
|
|
|
|
return $this->redirectToRoute('tvdt_elimination_candidate', ['elimination' => $elimination->id, 'candidateHash' => Base64::base64UrlEncode($name)]);
|
|
}
|
|
|
|
return $this->render('quiz/elimination/index.html.twig', [
|
|
'form' => $form,
|
|
'controller_name' => 'EliminationController',
|
|
]);
|
|
}
|
|
|
|
#[IsGranted(SeasonVoter::ELIMINATION, 'elimination')]
|
|
#[Route('/elimination/{elimination}/{candidateHash}', name: 'tvdt_elimination_candidate', requirements: ['elimination' => Requirement::UUID, 'candidateHash' => self::CANDIDATE_HASH_REGEX])]
|
|
public function candidateScreen(Elimination $elimination, string $candidateHash): Response
|
|
{
|
|
$candidate = $this->candidateRepository->getCandidateByHash($elimination->quiz->season, $candidateHash);
|
|
if (!$candidate instanceof Candidate) {
|
|
$this->addFlash(FlashType::Warning,
|
|
t('Could not find candidate with name {name}', ['name' => Base64::base64UrlDecode($candidateHash)])->trans($this->translator),
|
|
);
|
|
|
|
return $this->redirectToRoute('tvdt_elimination', ['elimination' => $elimination->id]);
|
|
}
|
|
|
|
$screenColour = $elimination->getScreenColour($candidate->name);
|
|
|
|
if (null === $screenColour) {
|
|
$this->addFlash(FlashType::Warning, $this->translator->trans('Could not find candidate with name {name} in elimination.', ['name' => $candidate->name]));
|
|
|
|
return $this->redirectToRoute('tvdt_elimination', ['elimination' => $elimination->id]);
|
|
}
|
|
|
|
return $this->render('quiz/elimination/candidate.html.twig', [
|
|
'candidate' => $candidate,
|
|
'colour' => $screenColour,
|
|
]);
|
|
}
|
|
}
|