mirror of
https://github.com/MarijnDoeve/TijdVoorDeTest.git
synced 2026-03-05 20:44:19 +01:00
- Refactor ORM annotations across entities for consistency.
- Adjusted migrations to align with refactored ORM annotations. - Added new PHPStan and PHP-CS-Fixer configurations, including stricter rules. - Introduced `tests/object-manager.php` to improve test environment setup.
This commit is contained in:
@@ -5,13 +5,13 @@ use PhpCsFixer\Config;
|
|||||||
use PhpCsFixer\Finder;
|
use PhpCsFixer\Finder;
|
||||||
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
|
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
|
||||||
|
|
||||||
$finder = (new Finder())
|
$finder = new Finder()
|
||||||
->in(__DIR__)
|
->in(__DIR__)
|
||||||
->exclude('var')
|
->exclude('var')
|
||||||
->exclude('bin')
|
->exclude('bin')
|
||||||
;
|
;
|
||||||
|
|
||||||
return (new Config())
|
return new Config()
|
||||||
->setParallelConfig(ParallelConfigFactory::detect())
|
->setParallelConfig(ParallelConfigFactory::detect())
|
||||||
->setRules([
|
->setRules([
|
||||||
'@Symfony' => true,
|
'@Symfony' => true,
|
||||||
@@ -30,8 +30,9 @@ return (new Config())
|
|||||||
'single_line_empty_body' => true,
|
'single_line_empty_body' => true,
|
||||||
'strict_comparison' => true,
|
'strict_comparison' => true,
|
||||||
'strict_param' => true,
|
'strict_param' => true,
|
||||||
|
'ordered_attributes' => true,
|
||||||
|
'heredoc_indentation' => ['indentation' => 'start_plus_one'],
|
||||||
'trailing_comma_in_multiline' => ['after_heredoc' => true, 'elements' => ['arguments', 'array_destructuring', 'arrays', 'match', 'parameters']],
|
'trailing_comma_in_multiline' => ['after_heredoc' => true, 'elements' => ['arguments', 'array_destructuring', 'arrays', 'match', 'parameters']],
|
||||||
|
|
||||||
])
|
])
|
||||||
->setRiskyAllowed(true)
|
->setRiskyAllowed(true)
|
||||||
->setFinder($finder)
|
->setFinder($finder)
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ services:
|
|||||||
# See https://xdebug.org/docs/all_settings#mode
|
# See https://xdebug.org/docs/all_settings#mode
|
||||||
XDEBUG_MODE: "${XDEBUG_MODE:-off}"
|
XDEBUG_MODE: "${XDEBUG_MODE:-off}"
|
||||||
MAILER_DSN: "smtp://mailer:1025"
|
MAILER_DSN: "smtp://mailer:1025"
|
||||||
PHP_CS_FIXER_IGNORE_ENV: 1
|
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
# Ensure that host.docker.internal is correctly defined on Linux
|
# Ensure that host.docker.internal is correctly defined on Linux
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|||||||
@@ -8,3 +8,7 @@ parameters:
|
|||||||
- src/
|
- src/
|
||||||
- tests/
|
- tests/
|
||||||
treatPhpDocTypesAsCertain: false
|
treatPhpDocTypesAsCertain: false
|
||||||
|
symfony:
|
||||||
|
containerXmlPath: var/cache/dev/Tvdt_KernelDevDebugContainer.xml
|
||||||
|
doctrine:
|
||||||
|
objectManagerLoader: tests/object-manager.php
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ class QuizController extends AbstractController
|
|||||||
private readonly TranslatorInterface $translator,
|
private readonly TranslatorInterface $translator,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
||||||
#[Route(
|
#[Route(
|
||||||
'/backoffice/season/{seasonCode:season}/quiz/{quiz}',
|
'/backoffice/season/{seasonCode:season}/quiz/{quiz}',
|
||||||
name: 'tvdt_backoffice_quiz',
|
name: 'tvdt_backoffice_quiz',
|
||||||
requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'quiz' => Requirement::UUID],
|
requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'quiz' => Requirement::UUID],
|
||||||
)]
|
)]
|
||||||
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
|
||||||
public function index(Season $season, Quiz $quiz): Response
|
public function index(Season $season, Quiz $quiz): Response
|
||||||
{
|
{
|
||||||
return $this->render('backoffice/quiz.html.twig', [
|
return $this->render('backoffice/quiz.html.twig', [
|
||||||
@@ -48,12 +48,12 @@ class QuizController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
||||||
#[Route(
|
#[Route(
|
||||||
'/backoffice/season/{seasonCode:season}/quiz/{quiz}/enable',
|
'/backoffice/season/{seasonCode:season}/quiz/{quiz}/enable',
|
||||||
name: 'tvdt_backoffice_enable',
|
name: 'tvdt_backoffice_enable',
|
||||||
requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'quiz' => Requirement::UUID.'|null'],
|
requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'quiz' => Requirement::UUID.'|null'],
|
||||||
)]
|
)]
|
||||||
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
|
||||||
public function enableQuiz(Season $season, ?Quiz $quiz, EntityManagerInterface $em): RedirectResponse
|
public function enableQuiz(Season $season, ?Quiz $quiz, EntityManagerInterface $em): RedirectResponse
|
||||||
{
|
{
|
||||||
$season->setActiveQuiz($quiz);
|
$season->setActiveQuiz($quiz);
|
||||||
@@ -66,12 +66,12 @@ class QuizController extends AbstractController
|
|||||||
return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $season->getSeasonCode()]);
|
return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $season->getSeasonCode()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
|
||||||
#[Route(
|
#[Route(
|
||||||
'/backoffice/quiz/{quiz}/clear',
|
'/backoffice/quiz/{quiz}/clear',
|
||||||
name: 'tvdt_backoffice_quiz_clear',
|
name: 'tvdt_backoffice_quiz_clear',
|
||||||
requirements: ['quiz' => Requirement::UUID],
|
requirements: ['quiz' => Requirement::UUID],
|
||||||
)]
|
)]
|
||||||
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
|
|
||||||
public function clearQuiz(Quiz $quiz, QuizRepository $quizRepository): RedirectResponse
|
public function clearQuiz(Quiz $quiz, QuizRepository $quizRepository): RedirectResponse
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -84,12 +84,12 @@ class QuizController extends AbstractController
|
|||||||
return $this->redirectToRoute('tvdt_backoffice_quiz', ['seasonCode' => $quiz->getSeason()->getSeasonCode(), 'quiz' => $quiz->getId()]);
|
return $this->redirectToRoute('tvdt_backoffice_quiz', ['seasonCode' => $quiz->getSeason()->getSeasonCode(), 'quiz' => $quiz->getId()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::DELETE, subject: 'quiz')]
|
||||||
#[Route(
|
#[Route(
|
||||||
'/backoffice/quiz/{quiz}/delete',
|
'/backoffice/quiz/{quiz}/delete',
|
||||||
name: 'tvdt_backoffice_quiz_delete',
|
name: 'tvdt_backoffice_quiz_delete',
|
||||||
requirements: ['quiz' => Requirement::UUID],
|
requirements: ['quiz' => Requirement::UUID],
|
||||||
)]
|
)]
|
||||||
#[IsGranted(SeasonVoter::DELETE, subject: 'quiz')]
|
|
||||||
public function deleteQuiz(Quiz $quiz, QuizRepository $quizRepository): RedirectResponse
|
public function deleteQuiz(Quiz $quiz, QuizRepository $quizRepository): RedirectResponse
|
||||||
{
|
{
|
||||||
$quizRepository->deleteQuiz($quiz);
|
$quizRepository->deleteQuiz($quiz);
|
||||||
@@ -99,12 +99,12 @@ class QuizController extends AbstractController
|
|||||||
return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $quiz->getSeason()->getSeasonCode()]);
|
return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $quiz->getSeason()->getSeasonCode()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
|
||||||
#[Route(
|
#[Route(
|
||||||
'/backoffice/quiz/{quiz}/candidate/{candidate}/modify_correction',
|
'/backoffice/quiz/{quiz}/candidate/{candidate}/modify_correction',
|
||||||
name: 'tvdt_backoffice_modify_correction',
|
name: 'tvdt_backoffice_modify_correction',
|
||||||
requirements: ['quiz' => Requirement::UUID, 'candidate' => Requirement::UUID],
|
requirements: ['quiz' => Requirement::UUID, 'candidate' => Requirement::UUID],
|
||||||
)]
|
)]
|
||||||
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
|
|
||||||
public function modifyCorrection(Quiz $quiz, Candidate $candidate, QuizCandidateRepository $quizCandidateRepository, Request $request): RedirectResponse
|
public function modifyCorrection(Quiz $quiz, Candidate $candidate, QuizCandidateRepository $quizCandidateRepository, Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
if (!$request->isMethod('POST')) {
|
if (!$request->isMethod('POST')) {
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ class SeasonController extends AbstractController
|
|||||||
private readonly EntityManagerInterface $em,
|
private readonly EntityManagerInterface $em,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
||||||
#[Route(
|
#[Route(
|
||||||
'/backoffice/season/{seasonCode:season}',
|
'/backoffice/season/{seasonCode:season}',
|
||||||
name: 'tvdt_backoffice_season',
|
name: 'tvdt_backoffice_season',
|
||||||
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
|
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
|
||||||
)]
|
)]
|
||||||
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
|
||||||
public function index(Season $season, Request $request): Response
|
public function index(Season $season, Request $request): Response
|
||||||
{
|
{
|
||||||
$form = $this->createForm(SettingsForm::class, $season->getSettings());
|
$form = $this->createForm(SettingsForm::class, $season->getSettings());
|
||||||
@@ -54,13 +54,13 @@ class SeasonController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
||||||
#[Route(
|
#[Route(
|
||||||
'/backoffice/season/{seasonCode:season}/add-candidate',
|
'/backoffice/season/{seasonCode:season}/add-candidate',
|
||||||
name: 'tvdt_backoffice_add_candidates',
|
name: 'tvdt_backoffice_add_candidates',
|
||||||
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
|
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
|
||||||
priority: 10,
|
priority: 10,
|
||||||
)]
|
)]
|
||||||
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
|
||||||
public function addCandidates(Season $season, Request $request): Response
|
public function addCandidates(Season $season, Request $request): Response
|
||||||
{
|
{
|
||||||
$form = $this->createForm(AddCandidatesFormType::class);
|
$form = $this->createForm(AddCandidatesFormType::class);
|
||||||
@@ -80,13 +80,13 @@ class SeasonController extends AbstractController
|
|||||||
return $this->render('backoffice/season_add_candidates.html.twig', ['form' => $form]);
|
return $this->render('backoffice/season_add_candidates.html.twig', ['form' => $form]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
||||||
#[Route(
|
#[Route(
|
||||||
'/backoffice/season/{seasonCode:season}/add-quiz',
|
'/backoffice/season/{seasonCode:season}/add-quiz',
|
||||||
name: 'tvdt_backoffice_quiz_add',
|
name: 'tvdt_backoffice_quiz_add',
|
||||||
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
|
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
|
||||||
priority: 10,
|
priority: 10,
|
||||||
)]
|
)]
|
||||||
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
|
|
||||||
public function addQuiz(Request $request, Season $season, QuizSpreadsheetService $quizSpreadsheet): Response
|
public function addQuiz(Request $request, Season $season, QuizSpreadsheetService $quizSpreadsheet): Response
|
||||||
{
|
{
|
||||||
$quiz = new Quiz();
|
$quiz = new Quiz();
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ final class EliminationController extends AbstractController
|
|||||||
{
|
{
|
||||||
public function __construct(private readonly TranslatorInterface $translator) {}
|
public function __construct(private readonly TranslatorInterface $translator) {}
|
||||||
|
|
||||||
#[Route('/elimination/{elimination}', name: 'tvdt_elimination', requirements: ['elimination' => Requirement::UUID])]
|
|
||||||
#[IsGranted(SeasonVoter::ELIMINATION, 'elimination')]
|
#[IsGranted(SeasonVoter::ELIMINATION, 'elimination')]
|
||||||
|
#[Route('/elimination/{elimination}', name: 'tvdt_elimination', requirements: ['elimination' => Requirement::UUID])]
|
||||||
public function index(#[MapEntity] Elimination $elimination, Request $request): Response
|
public function index(#[MapEntity] Elimination $elimination, Request $request): Response
|
||||||
{
|
{
|
||||||
$form = $this->createForm(EliminationEnterNameType::class);
|
$form = $this->createForm(EliminationEnterNameType::class);
|
||||||
@@ -48,8 +48,8 @@ final class EliminationController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/elimination/{elimination}/{candidateHash}', name: 'tvdt_elimination_candidate', requirements: ['elimination' => Requirement::UUID, 'candidateHash' => self::CANDIDATE_HASH_REGEX])]
|
|
||||||
#[IsGranted(SeasonVoter::ELIMINATION, 'elimination')]
|
#[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, CandidateRepository $candidateRepository): Response
|
public function candidateScreen(Elimination $elimination, string $candidateHash, CandidateRepository $candidateRepository): Response
|
||||||
{
|
{
|
||||||
$candidate = $candidateRepository->getCandidateByHash($elimination->getQuiz()->getSeason(), $candidateHash);
|
$candidate = $candidateRepository->getCandidateByHash($elimination->getQuiz()->getSeason(), $candidateHash);
|
||||||
|
|||||||
@@ -16,17 +16,17 @@ use Tvdt\Repository\AnswerRepository;
|
|||||||
#[ORM\Entity(repositoryClass: AnswerRepository::class)]
|
#[ORM\Entity(repositoryClass: AnswerRepository::class)]
|
||||||
class Answer
|
class Answer
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME)]
|
#[ORM\Column(type: UuidType::NAME)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::SMALLINT, options: ['default' => 0])]
|
#[ORM\Column(type: Types::SMALLINT, options: ['default' => 0])]
|
||||||
private int $ordering = 0;
|
private int $ordering = 0;
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'answers')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'answers')]
|
||||||
private Question $question;
|
private Question $question;
|
||||||
|
|
||||||
/** @var Collection<int, Candidate> */
|
/** @var Collection<int, Candidate> */
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ use Tvdt\Repository\CandidateRepository;
|
|||||||
#[ORM\UniqueConstraint(fields: ['name', 'season'])]
|
#[ORM\UniqueConstraint(fields: ['name', 'season'])]
|
||||||
class Candidate
|
class Candidate
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'candidates')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'candidates')]
|
||||||
private Season $season;
|
private Season $season;
|
||||||
|
|
||||||
/** @var Collection<int, Answer> */
|
/** @var Collection<int, Answer> */
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ class Elimination
|
|||||||
|
|
||||||
public const string SCREEN_RED = 'red';
|
public const string SCREEN_RED = 'red';
|
||||||
|
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
/** @var array<string, mixed> */
|
/** @var array<string, mixed> */
|
||||||
@@ -35,8 +35,8 @@ class Elimination
|
|||||||
private \DateTimeImmutable $created;
|
private \DateTimeImmutable $created;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[ORM\ManyToOne(inversedBy: 'eliminations')]
|
|
||||||
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'eliminations')]
|
||||||
private Quiz $quiz,
|
private Quiz $quiz,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -16,26 +16,26 @@ use Tvdt\Repository\GivenAnswerRepository;
|
|||||||
#[ORM\HasLifecycleCallbacks]
|
#[ORM\HasLifecycleCallbacks]
|
||||||
class GivenAnswer
|
class GivenAnswer
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::DATETIMETZ_IMMUTABLE, nullable: false)]
|
#[ORM\Column(type: Types::DATETIMETZ_IMMUTABLE, nullable: false)]
|
||||||
private \DateTimeImmutable $created;
|
private \DateTimeImmutable $created;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[ORM\ManyToOne(inversedBy: 'givenAnswers')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'givenAnswers')]
|
||||||
private Candidate $candidate,
|
private Candidate $candidate,
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
||||||
|
#[ORM\ManyToOne]
|
||||||
private Quiz $quiz,
|
private Quiz $quiz,
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'givenAnswers')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'givenAnswers')]
|
||||||
private Answer $answer,
|
private Answer $answer,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ use Tvdt\Repository\QuestionRepository;
|
|||||||
#[ORM\Entity(repositoryClass: QuestionRepository::class)]
|
#[ORM\Entity(repositoryClass: QuestionRepository::class)]
|
||||||
class Question
|
class Question
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME)]
|
#[ORM\Column(type: UuidType::NAME)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::SMALLINT, options: ['default' => 0])]
|
#[ORM\Column(type: Types::SMALLINT, options: ['default' => 0])]
|
||||||
@@ -28,8 +28,8 @@ class Question
|
|||||||
#[ORM\Column(type: Types::STRING, length: 255)]
|
#[ORM\Column(type: Types::STRING, length: 255)]
|
||||||
private string $question;
|
private string $question;
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'questions')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'questions')]
|
||||||
private Quiz $quiz;
|
private Quiz $quiz;
|
||||||
|
|
||||||
#[ORM\Column]
|
#[ORM\Column]
|
||||||
|
|||||||
@@ -16,17 +16,17 @@ use Tvdt\Repository\QuizRepository;
|
|||||||
#[ORM\UniqueConstraint(fields: ['name', 'season'])]
|
#[ORM\UniqueConstraint(fields: ['name', 'season'])]
|
||||||
class Quiz
|
class Quiz
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME)]
|
#[ORM\Column(type: UuidType::NAME)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\Column(length: 64)]
|
#[ORM\Column(length: 64)]
|
||||||
private string $name;
|
private string $name;
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'quizzes')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'quizzes')]
|
||||||
private Season $season;
|
private Season $season;
|
||||||
|
|
||||||
/** @var Collection<int, Question> */
|
/** @var Collection<int, Question> */
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ use Symfony\Component\Uid\Uuid;
|
|||||||
use Tvdt\Repository\QuizCandidateRepository;
|
use Tvdt\Repository\QuizCandidateRepository;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: QuizCandidateRepository::class)]
|
#[ORM\Entity(repositoryClass: QuizCandidateRepository::class)]
|
||||||
#[ORM\UniqueConstraint(columns: ['candidate_id', 'quiz_id'])]
|
|
||||||
#[ORM\HasLifecycleCallbacks]
|
#[ORM\HasLifecycleCallbacks]
|
||||||
|
#[ORM\UniqueConstraint(columns: ['candidate_id', 'quiz_id'])]
|
||||||
class QuizCandidate
|
class QuizCandidate
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\Column]
|
#[ORM\Column]
|
||||||
@@ -30,12 +30,12 @@ class QuizCandidate
|
|||||||
private \DateTimeImmutable $created;
|
private \DateTimeImmutable $created;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[ORM\ManyToOne(inversedBy: 'candidateData')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'candidateData')]
|
||||||
private Quiz $quiz,
|
private Quiz $quiz,
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'quizData')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[ORM\ManyToOne(inversedBy: 'quizData')]
|
||||||
private Candidate $candidate,
|
private Candidate $candidate,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ class Season
|
|||||||
{
|
{
|
||||||
private const string SEASON_CODE_CHARACTERS = 'bcdfghjklmnpqrstvwxz';
|
private const string SEASON_CODE_CHARACTERS = 'bcdfghjklmnpqrstvwxz';
|
||||||
|
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME)]
|
#[ORM\Column(type: UuidType::NAME)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\Column(length: 64)]
|
#[ORM\Column(length: 64)]
|
||||||
@@ -42,12 +42,12 @@ class Season
|
|||||||
#[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'seasons')]
|
#[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'seasons')]
|
||||||
private Collection $owners;
|
private Collection $owners;
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
|
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
|
||||||
|
#[ORM\ManyToOne]
|
||||||
private ?Quiz $ActiveQuiz = null;
|
private ?Quiz $ActiveQuiz = null;
|
||||||
|
|
||||||
#[ORM\OneToOne(cascade: ['persist', 'remove'])]
|
|
||||||
#[ORM\JoinColumn(nullable: true)]
|
#[ORM\JoinColumn(nullable: true)]
|
||||||
|
#[ORM\OneToOne(cascade: ['persist', 'remove'])]
|
||||||
private ?SeasonSettings $settings = null;
|
private ?SeasonSettings $settings = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ use Tvdt\Repository\SeasonSettingsRepository;
|
|||||||
#[ORM\Entity(repositoryClass: SeasonSettingsRepository::class)]
|
#[ORM\Entity(repositoryClass: SeasonSettingsRepository::class)]
|
||||||
class SeasonSettings
|
class SeasonSettings
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\Column(type: UuidType::NAME)]
|
#[ORM\Column(type: UuidType::NAME)]
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
|
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ use Tvdt\Repository\UserRepository;
|
|||||||
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
|
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
|
||||||
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Id]
|
||||||
private Uuid $id;
|
private Uuid $id;
|
||||||
|
|
||||||
#[ORM\Column(length: 180)]
|
#[ORM\Column(length: 180)]
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ class CandidateRepository extends ServiceEntityRepository
|
|||||||
select
|
select
|
||||||
c.id,
|
c.id,
|
||||||
c.name,
|
c.name,
|
||||||
sum(case when a.isRightAnswer = true then 1 else 0 end) as correct,
|
count(case when a.isRightAnswer = true then 1 else null end) as correct,
|
||||||
qc.corrections,
|
qc.corrections,
|
||||||
max(ga.created) - qc.created as time,
|
max(ga.created) - qc.created as time,
|
||||||
(sum(case when a.isRightAnswer = true then 1 else 0 end) + qc.corrections) as score
|
(count(case when a.isRightAnswer = true then 1 else null end) + qc.corrections) as score
|
||||||
from Tvdt\Entity\Candidate c
|
from Tvdt\Entity\Candidate c
|
||||||
join c.givenAnswers ga
|
join c.givenAnswers ga
|
||||||
join ga.answer a
|
join ga.answer a
|
||||||
|
|||||||
15
tests/object-manager.php
Normal file
15
tests/object-manager.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Symfony\Component\Dotenv\Dotenv;
|
||||||
|
use Tvdt\Kernel;
|
||||||
|
|
||||||
|
require __DIR__.'/../vendor/autoload.php';
|
||||||
|
|
||||||
|
new Dotenv()->bootEnv(__DIR__.'/../.env');
|
||||||
|
|
||||||
|
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
|
||||||
|
$kernel->boot();
|
||||||
|
|
||||||
|
return $kernel->getContainer()->get('doctrine')->getManager();
|
||||||
Reference in New Issue
Block a user