diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php
index 90c648c..bf379e0 100644
--- a/.php-cs-fixer.dist.php
+++ b/.php-cs-fixer.dist.php
@@ -1,17 +1,20 @@
in(__DIR__)
->exclude('var')
;
-return (new PhpCsFixer\Config())
+return (new Config())
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true,
'declare_strict_types' => true,
+ 'fully_qualified_strict_types' => ['import_symbols' => true],
'linebreak_after_opening_tag' => true,
'mb_str_functions' => true,
'no_php4_constructor' => true,
@@ -19,11 +22,11 @@ return (new PhpCsFixer\Config())
'no_useless_else' => true,
'no_useless_return' => true,
'php_unit_strict' => true,
+ 'phpdoc_line_span' => ['const' => 'single', 'method' => 'single', 'property' => 'single'],
'phpdoc_order' => true,
+ 'single_line_empty_body' => true,
'strict_comparison' => true,
'strict_param' => true,
- 'blank_line_between_import_groups' => false,
- 'phpdoc_line_span' => ['const' => 'single', 'method' => 'single', 'property' => 'single'],
])
->setRiskyAllowed(true)
->setFinder($finder)
diff --git a/config/bundles.php b/config/bundles.php
index 8de0245..42d43d0 100644
--- a/config/bundles.php
+++ b/config/bundles.php
@@ -1,17 +1,28 @@
['all' => true],
- Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
- Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
- Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
- Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
- Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
- Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
- Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
- Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
- EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
- Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
+ FrameworkBundle::class => ['all' => true],
+ DoctrineBundle::class => ['all' => true],
+ DoctrineMigrationsBundle::class => ['all' => true],
+ MakerBundle::class => ['dev' => true],
+ TwigBundle::class => ['all' => true],
+ SecurityBundle::class => ['all' => true],
+ WebProfilerBundle::class => ['dev' => true, 'test' => true],
+ TwigExtraBundle::class => ['all' => true],
+ TwigComponentBundle::class => ['all' => true],
+ EasyAdminBundle::class => ['all' => true],
+ DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
];
diff --git a/public/index.php b/public/index.php
index 12db4f8..3555cc2 100644
--- a/public/index.php
+++ b/public/index.php
@@ -7,8 +7,8 @@ use App\Kernel;
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return static function (array $context): Kernel {
- $appEnv = !empty($context['APP_ENV']) ? (string) $context['APP_ENV'] : 'prod';
- $appDebug = !empty($context['APP_DEBUG']) ? filter_var($context['APP_DEBUG'], \FILTER_VALIDATE_BOOL) : 'prod' !== $appEnv;
+ $appEnv = empty($context['APP_ENV']) ? 'prod' : (string) $context['APP_ENV'];
+ $appDebug = empty($context['APP_DEBUG']) ? 'prod' !== $appEnv : filter_var($context['APP_DEBUG'], \FILTER_VALIDATE_BOOL);
return new Kernel($appEnv, $appDebug);
};
diff --git a/src/Command/TestCommand.php b/src/Command/TestCommand.php
new file mode 100644
index 0000000..b6f3349
--- /dev/null
+++ b/src/Command/TestCommand.php
@@ -0,0 +1,34 @@
+candidateRepository->getScores($this->quizRepository->find('1effa06a-8aca-6c52-b52b-3974eda7eed7')));
+
+ return Command::SUCCESS;
+ }
+}
diff --git a/src/Controller/AbstractController.php b/src/Controller/AbstractController.php
index 1853af9..347eccf 100644
--- a/src/Controller/AbstractController.php
+++ b/src/Controller/AbstractController.php
@@ -9,11 +9,13 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as AbstractBase
abstract class AbstractController extends AbstractBaseController
{
+ #[\Override]
protected function addFlash(FlashType|string $type, mixed $message): void
{
if ($type instanceof FlashType) {
$type = $type->value;
}
+
parent::addFlash($type, $message);
}
}
diff --git a/src/Controller/Admin/DashboardController.php b/src/Controller/Admin/DashboardController.php
index 2886c50..de1bc3e 100644
--- a/src/Controller/Admin/DashboardController.php
+++ b/src/Controller/Admin/DashboardController.php
@@ -22,6 +22,7 @@ use Symfony\Component\Routing\Attribute\Route;
class DashboardController extends AbstractDashboardController
{
#[Route('/admin', name: 'admin')]
+ #[\Override]
public function index(): Response
{
// return parent::index();
@@ -44,12 +45,14 @@ class DashboardController extends AbstractDashboardController
// return $this->render('some/path/my-dashboard.html.twig');
}
+ #[\Override]
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->setTitle('TijdVoorDeTest');
}
+ #[\Override]
public function configureMenuItems(): iterable
{
yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
diff --git a/src/Controller/BackofficeController.php b/src/Controller/BackofficeController.php
index fbd8999..e972bd4 100644
--- a/src/Controller/BackofficeController.php
+++ b/src/Controller/BackofficeController.php
@@ -6,6 +6,7 @@ namespace App\Controller;
use App\Entity\Quiz;
use App\Entity\Season;
+use App\Repository\CandidateRepository;
use App\Repository\SeasonRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
@@ -13,14 +14,14 @@ use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route;
#[AsController]
-#[Route('/backoffice', name: 'backoffice_')]
final class BackofficeController extends AbstractController
{
- public function __construct(private readonly SeasonRepository $seasonRepository)
- {
- }
+ public function __construct(
+ private readonly SeasonRepository $seasonRepository,
+ private readonly CandidateRepository $candidateRepository,
+ ) {}
- #[Route('/', name: 'index')]
+ #[Route('/backoffice/', name: 'index')]
public function index(): Response
{
$seasons = $this->seasonRepository->findAll();
@@ -30,7 +31,7 @@ final class BackofficeController extends AbstractController
]);
}
- #[Route('/{seasonCode}', name: 'season')]
+ #[Route('/backoffice/{seasonCode}', name: 'season')]
public function season(Season $season): Response
{
return $this->render('backoffice/season.html.twig', [
@@ -38,12 +39,13 @@ final class BackofficeController extends AbstractController
]);
}
- #[Route('/{seasonCode}/{quiz}', name: 'quiz')]
+ #[Route('/backoffice/{seasonCode}/{quiz}', name: 'quiz')]
public function quiz(Season $season, Quiz $quiz): Response
{
return $this->render('backoffice/quiz.html.twig', [
'season' => $season,
'quiz' => $quiz,
+ 'result' => $this->candidateRepository->getScores($quiz),
]);
}
}
diff --git a/src/Controller/QuizController.php b/src/Controller/QuizController.php
index bf5e28c..7e483dd 100644
--- a/src/Controller/QuizController.php
+++ b/src/Controller/QuizController.php
@@ -28,6 +28,7 @@ use Symfony\Component\Routing\Attribute\Route;
final class QuizController extends AbstractController
{
public const string SEASON_CODE_REGEX = '[A-Za-z\d]{5}';
+
private const string CANDIDATE_HASH_REGEX = '[\w\-=]+';
#[Route(path: '/', name: 'select_season', methods: ['GET', 'POST'])]
@@ -83,7 +84,7 @@ final class QuizController extends AbstractController
$candidate = $candidateRepository->getCandidateByHash($season, $nameHash);
if (!$candidate instanceof Candidate) {
- if (true === $season->isPreregisterCandidates()) {
+ if ($season->isPreregisterCandidates()) {
$this->addFlash(FlashType::Danger, 'Candidate not found');
return $this->redirectToRoute('enter_name', ['seasonCode' => $season->getSeasonCode()]);
diff --git a/src/Entity/Elimination.php b/src/Entity/Elimination.php
new file mode 100644
index 0000000..ec47233
--- /dev/null
+++ b/src/Entity/Elimination.php
@@ -0,0 +1,42 @@
+id;
+ }
+
+ public function getData(): array
+ {
+ return $this->data;
+ }
+
+ public function setData(array $data): static
+ {
+ $this->data = $data;
+
+ return $this;
+ }
+}
diff --git a/src/Entity/Question.php b/src/Entity/Question.php
index 9ea7020..cddcd36 100644
--- a/src/Entity/Question.php
+++ b/src/Entity/Question.php
@@ -96,4 +96,23 @@ class Question
return $this;
}
+
+ public function getErrors(): ?string
+ {
+ if (0 === \count($this->answers)) {
+ return 'This question has no answers';
+ }
+
+ $correctAnswers = $this->answers->filter(static fn (Answer $answer): ?bool => $answer->isRightAnswer())->count();
+
+ if (0 === $correctAnswers) {
+ return 'This question has no correct answers';
+ }
+
+ if ($correctAnswers > 1) {
+ return 'This question has multiple correct answers';
+ }
+
+ return null;
+ }
}
diff --git a/src/Form/EnterNameType.php b/src/Form/EnterNameType.php
index b130296..f3c3373 100644
--- a/src/Form/EnterNameType.php
+++ b/src/Form/EnterNameType.php
@@ -11,9 +11,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
class EnterNameType extends AbstractType
{
- public function __construct(private TranslatorInterface $translator)
- {
- }
+ public function __construct(private readonly TranslatorInterface $translator) {}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
diff --git a/src/Helpers/Base64.php b/src/Helpers/Base64.php
index 991c9e5..8fbba4e 100644
--- a/src/Helpers/Base64.php
+++ b/src/Helpers/Base64.php
@@ -8,9 +8,7 @@ use Safe\Exceptions\UrlException;
class Base64
{
- private function __construct()
- {
- }
+ private function __construct() {}
public static function base64_url_encode(string $input): string
{
diff --git a/src/Repository/CandidateRepository.php b/src/Repository/CandidateRepository.php
index cda370c..fdf622c 100644
--- a/src/Repository/CandidateRepository.php
+++ b/src/Repository/CandidateRepository.php
@@ -5,14 +5,20 @@ declare(strict_types=1);
namespace App\Repository;
use App\Entity\Candidate;
+use App\Entity\Correction;
+use App\Entity\Quiz;
use App\Entity\Season;
use App\Helpers\Base64;
+use DateInterval;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\ORM\Query\Expr\Join;
use Doctrine\Persistence\ManagerRegistry;
use Safe\Exceptions\UrlException;
/**
* @extends ServiceEntityRepository
- {{ t('Quiz') }}: {{ quiz.season.name }} - {{ quiz.name }}
+ {{ 'Quiz'|trans }}: {{ quiz.season.name }} - {{ quiz.name }}
-
-
{{ t('Number of dropouts:') }} {{ quiz.dropouts }}
+{{ 'Number of dropouts:'|trans }} {{ quiz.dropouts }}
| {{ t('Candidate') }} | -{{ t('Correct Answers') }} | -{{ t('Corrections') }} | -{{ t('Score') }} | -{{ t('Time') }} | +{{ 'Candidate'|trans }} | +{{ 'Correct Answers'|trans }} | +{{ 'Corrections'|trans }} | +{{ 'Score'|trans }} | +{{ 'Time'|trans }} |
|---|---|---|---|---|---|---|---|---|---|
| {{ candidate.name }} | #} - {#{{ candidate.correct }} | #} - {#{{ candidate.corrections }} | #} - {#{{ candidate.score }} | #} - {#{{ candidate.time }} | #} - {#|||||
| {{ candidate.0.name }} | +{{ candidate.correct|default('0') }} | +{{ candidate.corrections|default('0') }} | +{{ candidate.score|default('x') }} | +{{ candidate.time }} | +|||||
| {{ 'No results'|trans }} | +|||||||||
-