3 Commits

Author SHA1 Message Date
dependabot[bot]
82fc64bbc2 Bump phpstan/phpstan-doctrine from 2.0.6 to 2.0.10
Bumps [phpstan/phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine) from 2.0.6 to 2.0.10.
- [Release notes](https://github.com/phpstan/phpstan-doctrine/releases)
- [Commits](https://github.com/phpstan/phpstan-doctrine/compare/2.0.6...2.0.10)

---
updated-dependencies:
- dependency-name: phpstan/phpstan-doctrine
  dependency-version: 2.0.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 23:32:58 +00:00
ca460cca7f - 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.
2025-10-04 12:40:45 +02:00
3e39550c90 Remove EasyAdmin integration
- Removed EasyAdmin controllers and configurations.
- Uninstalled `easycorp/easyadmin-bundle` and related dependencies.
- Cleaned up all associated routes, bundles, and vendor references.
2025-10-03 22:37:45 +02:00
49 changed files with 198 additions and 681 deletions

View File

@@ -116,15 +116,12 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/thecodingmachine/phpstan-safe-rule" />
<excludeFolder url="file://$MODULE_DIR$/vendor/thecodingmachine/safe" />
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/twig" />
<excludeFolder url="file://$MODULE_DIR$/vendor/easycorp/easyadmin-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/intl" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mime" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/ux-twig-component" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/validator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/extra-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/html-extra" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/data-fixtures" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/vincentlanglet/twig-cs-fixer" />

7
.idea/php.xml generated
View File

@@ -68,7 +68,6 @@
<path value="$PROJECT_DIR$/vendor/symfony/form" />
<path value="$PROJECT_DIR$/vendor/runtime/frankenphp-symfony" />
<path value="$PROJECT_DIR$/vendor/symfony/framework-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
<path value="$PROJECT_DIR$/vendor/symfony/cache" />
<path value="$PROJECT_DIR$/vendor/symfony/serializer" />
<path value="$PROJECT_DIR$/vendor/symfony/dotenv" />
@@ -78,7 +77,6 @@
<path value="$PROJECT_DIR$/vendor/symfony/browser-kit" />
<path value="$PROJECT_DIR$/vendor/symfony/config" />
<path value="$PROJECT_DIR$/vendor/symfony/security-http" />
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/symfony/runtime" />
@@ -124,7 +122,6 @@
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
<path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/ux-twig-component" />
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
<path value="$PROJECT_DIR$/vendor/symfony/process" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
@@ -142,7 +139,6 @@
<path value="$PROJECT_DIR$/vendor/doctrine/sql-formatter" />
<path value="$PROJECT_DIR$/vendor/doctrine/orm" />
<path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
<path value="$PROJECT_DIR$/vendor/easycorp/easyadmin-bundle" />
<path value="$PROJECT_DIR$/vendor/evenement/evenement" />
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-bundle" />
@@ -191,13 +187,14 @@
<path value="$PROJECT_DIR$/vendor/clue/ndjson-react" />
<path value="$PROJECT_DIR$/vendor/fidry/cpu-core-counter" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/twig/html-extra" />
<path value="$PROJECT_DIR$/vendor/twig/twig" />
<path value="$PROJECT_DIR$/vendor/symfony/ux-turbo" />
<path value="$PROJECT_DIR$/vendor/symfony/stimulus-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-uuid" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php84" />
<path value="$PROJECT_DIR$/vendor/symfony/brevo-mailer" />
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
</include_path>
</component>
<component name="PhpInterpreters">

View File

@@ -5,13 +5,13 @@ use PhpCsFixer\Config;
use PhpCsFixer\Finder;
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
$finder = (new Finder())
$finder = new Finder()
->in(__DIR__)
->exclude('var')
->exclude('bin')
;
return (new Config())
return new Config()
->setParallelConfig(ParallelConfigFactory::detect())
->setRules([
'@Symfony' => true,
@@ -30,8 +30,9 @@ return (new Config())
'single_line_empty_body' => true,
'strict_comparison' => 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']],
])
->setRiskyAllowed(true)
->setFinder($finder)

View File

@@ -1,8 +1,8 @@
up:
docker compose up -d
up *args:
docker compose up -d {{ args }}
down *args:
docker compose down {{ args }} --remove-orphans
docker compose down --remove-orphans {{ args }}
stop:
docker compose stop

View File

@@ -15,7 +15,6 @@ services:
# See https://xdebug.org/docs/all_settings#mode
XDEBUG_MODE: "${XDEBUG_MODE:-off}"
MAILER_DSN: "smtp://mailer:1025"
PHP_CS_FIXER_IGNORE_ENV: 1
extra_hosts:
# Ensure that host.docker.internal is correctly defined on Linux
- host.docker.internal:host-gateway

View File

@@ -13,7 +13,6 @@
"doctrine/doctrine-bundle": "^2.16.2",
"doctrine/doctrine-migrations-bundle": "^3.4.2",
"doctrine/orm": "^3.5.2",
"easycorp/easyadmin-bundle": "^4.25.1",
"phpdocumentor/reflection-docblock": "^5.6.3",
"phpoffice/phpspreadsheet": "^5.1",
"phpstan/phpdoc-parser": "^2.3",
@@ -34,9 +33,11 @@
"symfony/security-bundle": "7.3.*",
"symfony/security-csrf": "7.3.*",
"symfony/serializer": "7.3.*",
"symfony/translation": "7.3.*",
"symfony/twig-bundle": "7.3.*",
"symfony/uid": "7.3.*",
"symfony/ux-turbo": "^2.30.0",
"symfony/validator": "7.3.*",
"symfony/yaml": "7.3.*",
"symfonycasts/sass-bundle": "^0.8.3",
"symfonycasts/verify-email-bundle": "^1.17.4",
@@ -49,11 +50,11 @@
"doctrine/doctrine-fixtures-bundle": "^4.1",
"friendsofphp/php-cs-fixer": "^3.88.2",
"phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan": "^2.1.29",
"phpstan/phpstan": "^2.1.30",
"phpstan/phpstan-doctrine": "^2.0.6",
"phpstan/phpstan-phpunit": "^2.0.7",
"phpstan/phpstan-symfony": "^2.0.8",
"phpunit/phpunit": "^12.3.15",
"phpunit/phpunit": "^12.4.0",
"rector/rector": "^2.1.7",
"roave/security-advisories": "dev-latest",
"symfony/browser-kit": "7.3.*",

323
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b0035e3726f72e1549e382ed9b170ae3",
"content-hash": "643289575c0db1293c406f8c21a598f3",
"packages": [
{
"name": "composer/pcre",
@@ -1278,108 +1278,6 @@
},
"time": "2025-01-24T11:45:48+00:00"
},
{
"name": "easycorp/easyadmin-bundle",
"version": "v4.25.1",
"source": {
"type": "git",
"url": "https://github.com/EasyCorp/EasyAdminBundle.git",
"reference": "954e88c9cb004c3861b6ec6ae52241642995fb86"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/EasyCorp/EasyAdminBundle/zipball/954e88c9cb004c3861b6ec6ae52241642995fb86",
"reference": "954e88c9cb004c3861b6ec6ae52241642995fb86",
"shasum": ""
},
"require": {
"doctrine/doctrine-bundle": "^2.5",
"doctrine/orm": "^2.12|^3.0",
"ext-json": "*",
"php": ">=8.1",
"symfony/asset": "^5.4|^6.0|^7.0",
"symfony/cache": "^5.4|^6.0|^7.0",
"symfony/config": "^5.4|^6.0|^7.0",
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/deprecation-contracts": "^3.0",
"symfony/doctrine-bridge": "^5.4|^6.0|^7.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/filesystem": "^5.4|^6.0|^7.0",
"symfony/form": "^5.4|^6.0|^7.0",
"symfony/framework-bundle": "^5.4|^6.0|^7.0",
"symfony/http-foundation": "^5.4|^6.0|^7.0",
"symfony/http-kernel": "^5.4|^6.0|^7.0",
"symfony/intl": "^5.4|^6.0|^7.0",
"symfony/property-access": "^5.4|^6.0|^7.0",
"symfony/security-bundle": "^5.4|^6.0|^7.0",
"symfony/string": "^5.4|^6.0|^7.0",
"symfony/translation": "^5.4|^6.0|^7.0",
"symfony/twig-bridge": "^5.4.48|^6.4.16|^7.1.9",
"symfony/twig-bundle": "^5.4|^6.0|^7.0",
"symfony/uid": "^5.4|^6.0|^7.0",
"symfony/ux-twig-component": "^2.21",
"symfony/validator": "^5.4|^6.0|^7.0",
"twig/extra-bundle": "^3.17",
"twig/html-extra": "^3.17",
"twig/twig": "^3.20"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4|3.5.x-dev",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpstan/phpstan-symfony": "^2.0",
"psr/log": "^1.0",
"symfony/browser-kit": "^5.4|^6.0|^7.0",
"symfony/css-selector": "^5.4|^6.0|^7.0",
"symfony/debug-bundle": "^5.4|^6.0|^7.0",
"symfony/dom-crawler": "^5.4|^6.0|^7.0",
"symfony/expression-language": "^5.4|^6.0|^7.0",
"symfony/phpunit-bridge": "^6.1|^7.0",
"symfony/process": "^5.4|^6.0|^7.0",
"symfony/web-link": "^5.4|^6.0|^7.0"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "4.0.x-dev"
}
},
"autoload": {
"psr-4": {
"EasyCorp\\Bundle\\EasyAdminBundle\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Project Contributors",
"homepage": "https://github.com/EasyCorp/EasyAdminBundle/graphs/contributors"
}
],
"description": "Admin generator for Symfony applications",
"homepage": "https://github.com/EasyCorp/EasyAdminBundle",
"keywords": [
"admin",
"backend",
"generator"
],
"support": {
"issues": "https://github.com/EasyCorp/EasyAdminBundle/issues",
"source": "https://github.com/EasyCorp/EasyAdminBundle/tree/v4.25.1"
},
"funding": [
{
"url": "https://github.com/javiereguiluz",
"type": "github"
}
],
"time": "2025-09-10T05:00:12+00:00"
},
{
"name": "egulias/email-validator",
"version": "4.0.4",
@@ -7701,93 +7599,6 @@
],
"time": "2025-08-27T15:25:48+00:00"
},
{
"name": "symfony/ux-twig-component",
"version": "v2.30.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/ux-twig-component.git",
"reference": "2f445efda4d4400d4d1911ddf9710c366f339614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ux-twig-component/zipball/2f445efda4d4400d4d1911ddf9710c366f339614",
"reference": "2f445efda4d4400d4d1911ddf9710c366f339614",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/dependency-injection": "^5.4|^6.0|^7.0|^8.0",
"symfony/deprecation-contracts": "^2.2|^3.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0|^8.0",
"symfony/property-access": "^5.4|^6.0|^7.0|^8.0",
"twig/twig": "^3.10.3"
},
"conflict": {
"symfony/config": "<5.4.0"
},
"require-dev": {
"symfony/console": "^5.4|^6.0|^7.0|^8.0",
"symfony/css-selector": "^5.4|^6.0|^7.0|^8.0",
"symfony/dom-crawler": "^5.4|^6.0|^7.0|^8.0",
"symfony/framework-bundle": "^5.4|^6.0|^7.0|^8.0",
"symfony/phpunit-bridge": "^6.0|^7.0|^8.0",
"symfony/stimulus-bundle": "^2.9.1",
"symfony/twig-bundle": "^5.4|^6.0|^7.0|^8.0",
"symfony/webpack-encore-bundle": "^1.15|^2.3.0"
},
"type": "symfony-bundle",
"extra": {
"thanks": {
"url": "https://github.com/symfony/ux",
"name": "symfony/ux"
}
},
"autoload": {
"psr-4": {
"Symfony\\UX\\TwigComponent\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Twig components for Symfony",
"homepage": "https://symfony.com",
"keywords": [
"components",
"symfony-ux",
"twig"
],
"support": {
"source": "https://github.com/symfony/ux-twig-component/tree/v2.30.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-08-27T15:25:48+00:00"
},
{
"name": "symfony/validator",
"version": "v7.3.4",
@@ -8447,74 +8258,6 @@
],
"time": "2025-02-19T14:29:33+00:00"
},
{
"name": "twig/html-extra",
"version": "v3.21.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/html-extra.git",
"reference": "5442dd707601c83b8cd4233e37bb10ab8489a90f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/html-extra/zipball/5442dd707601c83b8cd4233e37bb10ab8489a90f",
"reference": "5442dd707601c83b8cd4233e37bb10ab8489a90f",
"shasum": ""
},
"require": {
"php": ">=8.1.0",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/mime": "^5.4|^6.4|^7.0",
"twig/twig": "^3.13|^4.0"
},
"require-dev": {
"symfony/phpunit-bridge": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Twig\\Extra\\Html\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
}
],
"description": "A Twig extension for HTML",
"homepage": "https://twig.symfony.com",
"keywords": [
"html",
"twig"
],
"support": {
"source": "https://github.com/twigphp/html-extra/tree/v3.21.0"
},
"funding": [
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
"type": "tidelift"
}
],
"time": "2025-02-19T14:29:33+00:00"
},
{
"name": "twig/intl-extra",
"version": "v3.21.0",
@@ -9582,16 +9325,11 @@
},
{
"name": "phpstan/phpstan",
"version": "2.1.29",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phar-composer-source.git",
"reference": "git"
},
"version": "2.1.30",
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d618573eed4a1b6b75e37b2e0b65ac65c885d88e",
"reference": "d618573eed4a1b6b75e37b2e0b65ac65c885d88e",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/a4a7f159927983dd4f7c8020ed227d80b7f39d7d",
"reference": "a4a7f159927983dd4f7c8020ed227d80b7f39d7d",
"shasum": ""
},
"require": {
@@ -9636,20 +9374,20 @@
"type": "github"
}
],
"time": "2025-09-25T06:58:18+00:00"
"time": "2025-10-02T16:07:52+00:00"
},
{
"name": "phpstan/phpstan-doctrine",
"version": "2.0.6",
"version": "2.0.10",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-doctrine.git",
"reference": "934f5734812341358fc41c44006b30fa00c785f0"
"reference": "5eaf37b87288474051469aee9f937fc9d862f330"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/934f5734812341358fc41c44006b30fa00c785f0",
"reference": "934f5734812341358fc41c44006b30fa00c785f0",
"url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/5eaf37b87288474051469aee9f937fc9d862f330",
"reference": "5eaf37b87288474051469aee9f937fc9d862f330",
"shasum": ""
},
"require": {
@@ -9683,7 +9421,8 @@
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^9.6.20",
"ramsey/uuid": "^4.2",
"symfony/cache": "^5.4"
"symfony/cache": "^5.4",
"symfony/uid": "^5.4 || ^6.4 || ^7.3"
},
"type": "phpstan-extension",
"extra": {
@@ -9706,9 +9445,9 @@
"description": "Doctrine extensions for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-doctrine/issues",
"source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.6"
"source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.10"
},
"time": "2025-09-10T07:06:30+00:00"
"time": "2025-10-06T10:01:02+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
@@ -10170,16 +9909,16 @@
},
{
"name": "phpunit/phpunit",
"version": "12.3.15",
"version": "12.4.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "b035ee2cd8ecad4091885b61017ebb1d80eb0e57"
"reference": "f62aab5794e36ccd26860db2d1bbf89ac19028d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b035ee2cd8ecad4091885b61017ebb1d80eb0e57",
"reference": "b035ee2cd8ecad4091885b61017ebb1d80eb0e57",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f62aab5794e36ccd26860db2d1bbf89ac19028d9",
"reference": "f62aab5794e36ccd26860db2d1bbf89ac19028d9",
"shasum": ""
},
"require": {
@@ -10215,7 +9954,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "12.3-dev"
"dev-main": "12.4-dev"
}
},
"autoload": {
@@ -10247,7 +9986,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.15"
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.0"
},
"funding": [
{
@@ -10271,7 +10010,7 @@
"type": "tidelift"
}
],
"time": "2025-09-28T12:10:54+00:00"
"time": "2025-10-03T04:28:03+00:00"
},
{
"name": "react/cache",
@@ -10865,12 +10604,12 @@
"source": {
"type": "git",
"url": "https://github.com/Roave/SecurityAdvisories.git",
"reference": "684ef27cdce62b6562f77a92dc76bdfb46542a2d"
"reference": "60ac6a710b7b0527786041ba96200bd49aa8de7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/684ef27cdce62b6562f77a92dc76bdfb46542a2d",
"reference": "684ef27cdce62b6562f77a92dc76bdfb46542a2d",
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/60ac6a710b7b0527786041ba96200bd49aa8de7e",
"reference": "60ac6a710b7b0527786041ba96200bd49aa8de7e",
"shasum": ""
},
"conflict": {
@@ -10912,10 +10651,10 @@
"athlon1600/php-proxy-app": "<=3",
"athlon1600/youtube-downloader": "<=4",
"austintoddj/canvas": "<=3.4.2",
"auth0/auth0-php": ">=8.0.0.0-beta1,<8.14",
"auth0/login": "<7.17",
"auth0/symfony": "<5.4",
"auth0/wordpress": "<5.3",
"auth0/auth0-php": ">=3.3,<=8.16",
"auth0/login": "<=7.18",
"auth0/symfony": "<=5.4.1",
"auth0/wordpress": "<=5.3",
"automad/automad": "<2.0.0.0-alpha5",
"automattic/jetpack": "<9.8",
"awesome-support/awesome-support": "<=6.0.7",
@@ -11032,7 +10771,7 @@
"doctrine/mongodb-odm": "<1.0.2",
"doctrine/mongodb-odm-bundle": "<3.0.1",
"doctrine/orm": ">=1,<1.2.4|>=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4",
"dolibarr/dolibarr": "<=21.0.2",
"dolibarr/dolibarr": "<21.0.3",
"dompdf/dompdf": "<2.0.4",
"doublethreedigital/guest-entries": "<3.1.2",
"drupal/admin_audit_trail": "<1.0.5",
@@ -11221,7 +10960,7 @@
"joomla/archive": "<1.1.12|>=2,<2.0.1",
"joomla/database": ">=1,<2.2|>=3,<3.4",
"joomla/filesystem": "<1.6.2|>=2,<2.0.1",
"joomla/filter": "<1.4.4|>=2,<2.0.1",
"joomla/filter": "<2.0.6|>=3,<3.0.5|==4",
"joomla/framework": "<1.5.7|>=2.5.4,<=3.8.12",
"joomla/input": ">=2,<2.0.2",
"joomla/joomla-cms": "<3.9.12|>=4,<4.4.13|>=5,<5.2.6",
@@ -11639,7 +11378,7 @@
"thelia/thelia": ">=2.1,<2.1.3",
"theonedemon/phpwhois": "<=4.2.5",
"thinkcmf/thinkcmf": "<6.0.8",
"thorsten/phpmyfaq": "<=4.0.1",
"thorsten/phpmyfaq": "<=4.0.1|>=4.0.7,<4.0.13",
"tikiwiki/tiki-manager": "<=17.1",
"timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1",
"tinymce/tinymce": "<7.2",
@@ -11831,7 +11570,7 @@
"type": "tidelift"
}
],
"time": "2025-09-24T21:05:21+00:00"
"time": "2025-10-03T15:05:30+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -5,7 +5,6 @@ declare(strict_types=1);
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
use Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle;
use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
use EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle;
use Sentry\SentryBundle\SentryBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\MakerBundle\MakerBundle;
@@ -14,7 +13,6 @@ use Symfony\Bundle\TwigBundle\TwigBundle;
use Symfony\Bundle\WebProfilerBundle\WebProfilerBundle;
use Symfony\UX\StimulusBundle\StimulusBundle;
use Symfony\UX\Turbo\TurboBundle;
use Symfony\UX\TwigComponent\TwigComponentBundle;
use SymfonyCasts\Bundle\VerifyEmail\SymfonyCastsVerifyEmailBundle;
use Symfonycasts\SassBundle\SymfonycastsSassBundle;
use Twig\Extra\TwigExtraBundle\TwigExtraBundle;
@@ -28,8 +26,6 @@ return [
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],
SymfonyCastsVerifyEmailBundle::class => ['all' => true],
SentryBundle::class => ['prod' => true],

View File

@@ -1,5 +0,0 @@
twig_component:
anonymous_template_directory: 'components/'
defaults:
# Namespace & directory for components
Tvdt\Twig\Components\: 'components/'

View File

@@ -1,3 +0,0 @@
easyadmin:
resource: .
type: easyadmin.routes

View File

@@ -18,13 +18,13 @@ final class Version20250420111904 extends AbstractMigration
{
$this->addSql(<<<'SQL'
ALTER TABLE "user" ADD is_verified BOOLEAN NOT NULL
SQL);
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE "user" DROP is_verified
SQL);
SQL);
}
}

View File

@@ -18,13 +18,13 @@ final class Version20250420125040 extends AbstractMigration
{
$this->addSql(<<<'SQL'
ALTER TABLE season DROP preregister_candidates
SQL);
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE season ADD preregister_candidates BOOLEAN NOT NULL DEFAULT true
SQL);
SQL);
}
}

View File

@@ -22,10 +22,10 @@ final class Version20250427174822 extends AbstractMigration
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE answer ADD ordering SMALLINT DEFAULT 0 NOT NULL
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE question ADD ordering SMALLINT DEFAULT 0 NOT NULL
SQL);
SQL);
}
public function down(Schema $schema): void
@@ -33,9 +33,9 @@ final class Version20250427174822 extends AbstractMigration
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE answer DROP ordering
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE question DROP ordering
SQL);
SQL);
}
}

View File

@@ -22,10 +22,10 @@ final class Version20250504101440 extends AbstractMigration
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
CREATE UNIQUE INDEX UNIQ_C8B28E445E237E064EC001D1 ON candidate (name, season_id)
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE UNIQUE INDEX UNIQ_A412FA925E237E064EC001D1 ON quiz (name, season_id)
SQL);
SQL);
}
public function down(Schema $schema): void
@@ -33,9 +33,9 @@ final class Version20250504101440 extends AbstractMigration
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
DROP INDEX UNIQ_A412FA925E237E064EC001D1
SQL);
SQL);
$this->addSql(<<<'SQL'
DROP INDEX UNIQ_C8B28E445E237E064EC001D1
SQL);
SQL);
}
}

View File

@@ -18,37 +18,37 @@ final class Version20250521192752 extends AbstractMigration
{
$this->addSql(<<<'SQL'
ALTER TABLE elimination ADD quiz_id UUID NOT NULL
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE elimination ADD CONSTRAINT FK_5947284F853CD175 FOREIGN KEY (quiz_id) REFERENCES quiz (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE INDEX IDX_5947284F853CD175 ON elimination (quiz_id)
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE quiz ALTER dropouts SET DEFAULT 1
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE quiz ALTER dropouts SET NOT NULL
SQL);
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE quiz ALTER dropouts DROP DEFAULT
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE quiz ALTER dropouts DROP NOT NULL
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE elimination DROP CONSTRAINT FK_5947284F853CD175
SQL);
SQL);
$this->addSql(<<<'SQL'
DROP INDEX IDX_5947284F853CD175
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE elimination DROP quiz_id
SQL);
SQL);
}
}

View File

@@ -18,7 +18,7 @@ final class Version20250521194035 extends AbstractMigration
{
$this->addSql(<<<'SQL'
ALTER TABLE elimination ADD created TIMESTAMP(0) WITHOUT TIME ZONE
SQL);
SQL);
$this->addSql(<<<'SQL'
UPDATE elimination SET created = NOW()
SQL
@@ -33,6 +33,6 @@ final class Version20250521194035 extends AbstractMigration
{
$this->addSql(<<<'SQL'
ALTER TABLE elimination DROP created
SQL);
SQL);
}
}

View File

@@ -18,73 +18,73 @@ final class Version20250606192337 extends AbstractMigration
{
$this->addSql(<<<'SQL'
CREATE TABLE quiz_candidate (id UUID NOT NULL, corrections DOUBLE PRECISION NOT NULL, created TIMESTAMP(0) WITH TIME ZONE NOT NULL, quiz_id UUID NOT NULL, candidate_id UUID NOT NULL, PRIMARY KEY(id))
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE INDEX IDX_CED2FFA2853CD175 ON quiz_candidate (quiz_id)
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE INDEX IDX_CED2FFA291BD8781 ON quiz_candidate (candidate_id)
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE UNIQUE INDEX UNIQ_CED2FFA291BD8781853CD175 ON quiz_candidate (candidate_id, quiz_id)
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE quiz_candidate ADD CONSTRAINT FK_CED2FFA2853CD175 FOREIGN KEY (quiz_id) REFERENCES quiz (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE quiz_candidate ADD CONSTRAINT FK_CED2FFA291BD8781 FOREIGN KEY (candidate_id) REFERENCES candidate (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE correction DROP CONSTRAINT fk_a29da1b891bd8781
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE correction DROP CONSTRAINT fk_a29da1b8853cd175
SQL);
SQL);
$this->addSql(<<<'SQL'
DROP TABLE correction
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE elimination ALTER created TYPE TIMESTAMP(0) WITH TIME ZONE
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE given_answer ALTER created TYPE TIMESTAMP(0) WITH TIME ZONE
SQL);
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE TABLE correction (id UUID NOT NULL, candidate_id UUID NOT NULL, quiz_id UUID NOT NULL, amount DOUBLE PRECISION NOT NULL, PRIMARY KEY(id))
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE UNIQUE INDEX uniq_a29da1b891bd8781853cd175 ON correction (candidate_id, quiz_id)
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE INDEX idx_a29da1b8853cd175 ON correction (quiz_id)
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE INDEX idx_a29da1b891bd8781 ON correction (candidate_id)
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE correction ADD CONSTRAINT fk_a29da1b891bd8781 FOREIGN KEY (candidate_id) REFERENCES candidate (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE correction ADD CONSTRAINT fk_a29da1b8853cd175 FOREIGN KEY (quiz_id) REFERENCES quiz (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE quiz_candidate DROP CONSTRAINT FK_CED2FFA2853CD175
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE quiz_candidate DROP CONSTRAINT FK_CED2FFA291BD8781
SQL);
SQL);
$this->addSql(<<<'SQL'
DROP TABLE quiz_candidate
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE given_answer ALTER created TYPE TIMESTAMP(0) WITHOUT TIME ZONE
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE elimination ALTER created TYPE TIMESTAMP(0) WITHOUT TIME ZONE
SQL);
SQL);
}
}

View File

@@ -21,22 +21,22 @@ final class Version20250606195952 extends AbstractMigration
{
$this->addSql(<<<'SQL'
delete from given_answer where answer_id is null
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE given_answer ALTER answer_id TYPE UUID
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE given_answer ALTER answer_id SET NOT NULL
SQL);
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE given_answer ALTER answer_id TYPE UUID
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE given_answer ALTER answer_id DROP NOT NULL
SQL);
SQL);
}
}

View File

@@ -22,10 +22,10 @@ final class Version20250607154730 extends AbstractMigration
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE season DROP CONSTRAINT FK_F0E45BA96706D6B
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE season ADD CONSTRAINT FK_F0E45BA96706D6B FOREIGN KEY (active_quiz_id) REFERENCES quiz (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
}
public function down(Schema $schema): void
@@ -33,9 +33,9 @@ final class Version20250607154730 extends AbstractMigration
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE season DROP CONSTRAINT fk_f0e45ba96706d6b
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE season ADD CONSTRAINT fk_f0e45ba96706d6b FOREIGN KEY (active_quiz_id) REFERENCES quiz (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
}
}

View File

@@ -22,16 +22,16 @@ final class Version20250607184525 extends AbstractMigration
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE elimination DROP CONSTRAINT FK_5947284F853CD175
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE elimination ADD CONSTRAINT FK_5947284F853CD175 FOREIGN KEY (quiz_id) REFERENCES quiz (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE given_answer DROP CONSTRAINT FK_9AC61A30853CD175
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE given_answer ADD CONSTRAINT FK_9AC61A30853CD175 FOREIGN KEY (quiz_id) REFERENCES quiz (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
}
public function down(Schema $schema): void
@@ -39,15 +39,15 @@ final class Version20250607184525 extends AbstractMigration
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE given_answer DROP CONSTRAINT fk_9ac61a30853cd175
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE given_answer ADD CONSTRAINT fk_9ac61a30853cd175 FOREIGN KEY (quiz_id) REFERENCES quiz (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE elimination DROP CONSTRAINT fk_5947284f853cd175
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE elimination ADD CONSTRAINT fk_5947284f853cd175 FOREIGN KEY (quiz_id) REFERENCES quiz (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
}
}

View File

@@ -18,31 +18,31 @@ final class Version20250610210417 extends AbstractMigration
{
$this->addSql(<<<'SQL'
CREATE TABLE season_settings (id UUID NOT NULL, show_numbers BOOLEAN DEFAULT false NOT NULL, confirm_answers BOOLEAN DEFAULT false NOT NULL, PRIMARY KEY(id))
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE season ADD settings_id UUID DEFAULT NULL
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE season ADD CONSTRAINT FK_F0E45BA959949888 FOREIGN KEY (settings_id) REFERENCES season_settings (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
SQL);
$this->addSql(<<<'SQL'
CREATE UNIQUE INDEX UNIQ_F0E45BA959949888 ON season (settings_id)
SQL);
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
DROP TABLE season_settings
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE season DROP CONSTRAINT FK_F0E45BA959949888
SQL);
SQL);
$this->addSql(<<<'SQL'
DROP INDEX UNIQ_F0E45BA959949888
SQL);
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE season DROP settings_id
SQL);
SQL);
}
}

View File

@@ -8,3 +8,7 @@ parameters:
- src/
- tests/
treatPhpDocTypesAsCertain: false
symfony:
containerXmlPath: var/cache/dev/Tvdt_KernelDevDebugContainer.xml
doctrine:
objectManagerLoader: tests/object-manager.php

View File

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Answer;
/** @extends AbstractCrudController<Answer> */
class AnswerCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Answer::class;
}
}

View File

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Candidate;
/** @extends AbstractCrudController<Candidate> */
class CandidateCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Candidate::class;
}
}

View File

@@ -1,67 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminDashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Symfony\Component\HttpFoundation\Response;
use Tvdt\Entity\Answer;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\GivenAnswer;
use Tvdt\Entity\Question;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\QuizCandidate;
use Tvdt\Entity\Season;
use Tvdt\Entity\User;
#[AdminDashboard(routePath: '/admin', routeName: 'admin')]
class DashboardController extends AbstractDashboardController
{
#[\Override]
public function index(): Response
{
// Option 1. You can make your dashboard redirect to some common page of your backend
//
$adminUrlGenerator = $this->container->get(AdminUrlGenerator::class);
return $this->redirect($adminUrlGenerator->setController(SeasonCrudController::class)->generateUrl());
// Option 2. You can make your dashboard redirect to different pages depending on the user
//
// if ('jane' === $this->getUser()->getUsername()) {
// return $this->redirect('...');
// }
// Option 3. You can render some custom template to display a proper dashboard with widgets, etc.
// (tip: it's easier if your template extends from @EasyAdmin/page/content.html.twig)
//
// 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');
yield MenuItem::linkToCrud('Season', 'fas fa-list', Season::class);
yield MenuItem::linkToCrud('Quiz', 'fas fa-list', Quiz::class);
yield MenuItem::linkToCrud('Question', 'fas fa-list', Question::class);
yield MenuItem::linkToCrud('Candidate', 'fas fa-list', Candidate::class);
yield MenuItem::linkToCrud('Correction', 'fas fa-list', QuizCandidate::class);
yield MenuItem::linkToCrud('User', 'fas fa-list', User::class);
yield MenuItem::linkToCrud('Given Answer', 'fas fa-list', GivenAnswer::class);
yield MenuItem::linkToCrud('Answer', 'fas fa-list', Answer::class);
yield MenuItem::linkToLogout('Logout', 'fas fa-sign-out');
}
}

View File

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\GivenAnswer;
/** @extends AbstractCrudController<GivenAnswer> */
class GivenAnswerCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return GivenAnswer::class;
}
}

View File

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Question;
/** @extends AbstractCrudController<Question> */
class QuestionCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Question::class;
}
}

View File

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\QuizCandidate;
/** @extends AbstractCrudController<QuizCandidate> */
class QuizCorrectionCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return QuizCandidate::class;
}
}

View File

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Quiz;
/** @extends AbstractCrudController<Quiz> */
class QuizCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Quiz::class;
}
}

View File

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Season;
/** @extends AbstractCrudController<Season> */
class SeasonCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Season::class;
}
}

View File

@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Tvdt\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\User;
/** @extends AbstractCrudController<User> */
class UserCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return User::class;
}
}

View File

@@ -33,12 +33,12 @@ class QuizController extends AbstractController
private readonly TranslatorInterface $translator,
) {}
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
#[Route(
'/backoffice/season/{seasonCode:season}/quiz/{quiz}',
name: 'tvdt_backoffice_quiz',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'quiz' => Requirement::UUID],
)]
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
public function index(Season $season, Quiz $quiz): Response
{
return $this->render('backoffice/quiz.html.twig', [
@@ -48,12 +48,12 @@ class QuizController extends AbstractController
]);
}
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
#[Route(
'/backoffice/season/{seasonCode:season}/quiz/{quiz}/enable',
name: 'tvdt_backoffice_enable',
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
{
$season->setActiveQuiz($quiz);
@@ -66,12 +66,12 @@ class QuizController extends AbstractController
return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $season->getSeasonCode()]);
}
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
#[Route(
'/backoffice/quiz/{quiz}/clear',
name: 'tvdt_backoffice_quiz_clear',
requirements: ['quiz' => Requirement::UUID],
)]
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
public function clearQuiz(Quiz $quiz, QuizRepository $quizRepository): RedirectResponse
{
try {
@@ -84,12 +84,12 @@ class QuizController extends AbstractController
return $this->redirectToRoute('tvdt_backoffice_quiz', ['seasonCode' => $quiz->getSeason()->getSeasonCode(), 'quiz' => $quiz->getId()]);
}
#[IsGranted(SeasonVoter::DELETE, subject: 'quiz')]
#[Route(
'/backoffice/quiz/{quiz}/delete',
name: 'tvdt_backoffice_quiz_delete',
requirements: ['quiz' => Requirement::UUID],
)]
#[IsGranted(SeasonVoter::DELETE, subject: 'quiz')]
public function deleteQuiz(Quiz $quiz, QuizRepository $quizRepository): RedirectResponse
{
$quizRepository->deleteQuiz($quiz);
@@ -99,12 +99,12 @@ class QuizController extends AbstractController
return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $quiz->getSeason()->getSeasonCode()]);
}
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
#[Route(
'/backoffice/quiz/{quiz}/candidate/{candidate}/modify_correction',
name: 'tvdt_backoffice_modify_correction',
requirements: ['quiz' => Requirement::UUID, 'candidate' => Requirement::UUID],
)]
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
public function modifyCorrection(Quiz $quiz, Candidate $candidate, QuizCandidateRepository $quizCandidateRepository, Request $request): RedirectResponse
{
if (!$request->isMethod('POST')) {

View File

@@ -32,12 +32,12 @@ class SeasonController extends AbstractController
private readonly EntityManagerInterface $em,
) {}
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
#[Route(
'/backoffice/season/{seasonCode:season}',
name: 'tvdt_backoffice_season',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
)]
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
public function index(Season $season, Request $request): Response
{
$form = $this->createForm(SettingsForm::class, $season->getSettings());
@@ -54,13 +54,13 @@ class SeasonController extends AbstractController
]);
}
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
#[Route(
'/backoffice/season/{seasonCode:season}/add-candidate',
name: 'tvdt_backoffice_add_candidates',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
priority: 10,
)]
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
public function addCandidates(Season $season, Request $request): Response
{
$form = $this->createForm(AddCandidatesFormType::class);
@@ -80,13 +80,13 @@ class SeasonController extends AbstractController
return $this->render('backoffice/season_add_candidates.html.twig', ['form' => $form]);
}
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
#[Route(
'/backoffice/season/{seasonCode:season}/add-quiz',
name: 'tvdt_backoffice_quiz_add',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
priority: 10,
)]
#[IsGranted(SeasonVoter::EDIT, subject: 'season')]
public function addQuiz(Request $request, Season $season, QuizSpreadsheetService $quizSpreadsheet): Response
{
$quiz = new Quiz();

View File

@@ -28,8 +28,8 @@ final class EliminationController extends AbstractController
{
public function __construct(private readonly TranslatorInterface $translator) {}
#[Route('/elimination/{elimination}', name: 'tvdt_elimination', requirements: ['elimination' => Requirement::UUID])]
#[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);
@@ -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')]
#[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
{
$candidate = $candidateRepository->getCandidateByHash($elimination->getQuiz()->getSeason(), $candidateHash);

View File

@@ -16,17 +16,17 @@ use Tvdt\Repository\AnswerRepository;
#[ORM\Entity(repositoryClass: AnswerRepository::class)]
class Answer
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\Column(type: Types::SMALLINT, options: ['default' => 0])]
private int $ordering = 0;
#[ORM\ManyToOne(inversedBy: 'answers')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\ManyToOne(inversedBy: 'answers')]
private Question $question;
/** @var Collection<int, Candidate> */

View File

@@ -17,14 +17,14 @@ use Tvdt\Repository\CandidateRepository;
#[ORM\UniqueConstraint(fields: ['name', 'season'])]
class Candidate
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\ManyToOne(inversedBy: 'candidates')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\ManyToOne(inversedBy: 'candidates')]
private Season $season;
/** @var Collection<int, Answer> */

View File

@@ -21,10 +21,10 @@ class Elimination
public const string SCREEN_RED = 'red';
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
/** @var array<string, mixed> */
@@ -35,8 +35,8 @@ class Elimination
private \DateTimeImmutable $created;
public function __construct(
#[ORM\ManyToOne(inversedBy: 'eliminations')]
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
#[ORM\ManyToOne(inversedBy: 'eliminations')]
private Quiz $quiz,
) {}

View File

@@ -16,26 +16,26 @@ use Tvdt\Repository\GivenAnswerRepository;
#[ORM\HasLifecycleCallbacks]
class GivenAnswer
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\Column(type: Types::DATETIMETZ_IMMUTABLE, nullable: false)]
private \DateTimeImmutable $created;
public function __construct(
#[ORM\ManyToOne(inversedBy: 'givenAnswers')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\ManyToOne(inversedBy: 'givenAnswers')]
private Candidate $candidate,
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
#[ORM\ManyToOne]
private Quiz $quiz,
#[ORM\ManyToOne(inversedBy: 'givenAnswers')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\ManyToOne(inversedBy: 'givenAnswers')]
private Answer $answer,
) {}

View File

@@ -16,10 +16,10 @@ use Tvdt\Repository\QuestionRepository;
#[ORM\Entity(repositoryClass: QuestionRepository::class)]
class Question
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\Column(type: Types::SMALLINT, options: ['default' => 0])]
@@ -28,8 +28,8 @@ class Question
#[ORM\Column(type: Types::STRING, length: 255)]
private string $question;
#[ORM\ManyToOne(inversedBy: 'questions')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\ManyToOne(inversedBy: 'questions')]
private Quiz $quiz;
#[ORM\Column]

View File

@@ -16,17 +16,17 @@ use Tvdt\Repository\QuizRepository;
#[ORM\UniqueConstraint(fields: ['name', 'season'])]
class Quiz
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\Column(length: 64)]
private string $name;
#[ORM\ManyToOne(inversedBy: 'quizzes')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\ManyToOne(inversedBy: 'quizzes')]
private Season $season;
/** @var Collection<int, Question> */

View File

@@ -13,14 +13,14 @@ use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\QuizCandidateRepository;
#[ORM\Entity(repositoryClass: QuizCandidateRepository::class)]
#[ORM\UniqueConstraint(columns: ['candidate_id', 'quiz_id'])]
#[ORM\HasLifecycleCallbacks]
#[ORM\UniqueConstraint(columns: ['candidate_id', 'quiz_id'])]
class QuizCandidate
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\Column]
@@ -30,12 +30,12 @@ class QuizCandidate
private \DateTimeImmutable $created;
public function __construct(
#[ORM\ManyToOne(inversedBy: 'candidateData')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\ManyToOne(inversedBy: 'candidateData')]
private Quiz $quiz,
#[ORM\ManyToOne(inversedBy: 'quizData')]
#[ORM\JoinColumn(nullable: false)]
#[ORM\ManyToOne(inversedBy: 'quizData')]
private Candidate $candidate,
) {}

View File

@@ -17,10 +17,10 @@ class Season
{
private const string SEASON_CODE_CHARACTERS = 'bcdfghjklmnpqrstvwxz';
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\Column(length: 64)]
@@ -42,12 +42,12 @@ class Season
#[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'seasons')]
private Collection $owners;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
#[ORM\ManyToOne]
private ?Quiz $ActiveQuiz = null;
#[ORM\OneToOne(cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(nullable: true)]
#[ORM\OneToOne(cascade: ['persist', 'remove'])]
private ?SeasonSettings $settings = null;
public function __construct()

View File

@@ -14,10 +14,10 @@ use Tvdt\Repository\SeasonSettingsRepository;
#[ORM\Entity(repositoryClass: SeasonSettingsRepository::class)]
class SeasonSettings
{
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UuidType::NAME)]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]

View File

@@ -22,10 +22,10 @@ use Tvdt\Repository\UserRepository;
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\Column(type: UuidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Id]
private Uuid $id;
#[ORM\Column(length: 180)]

View File

@@ -38,7 +38,7 @@ class CandidateRepository extends ServiceEntityRepository
select c from Tvdt\Entity\Candidate c
where c.season = :season
and lower(c.name) = lower(:name)
DQL
DQL
)->setParameter('season', $season)
->setParameter('name', $name)
->getOneOrNullResult();
@@ -57,21 +57,21 @@ class CandidateRepository extends ServiceEntityRepository
public function getScores(Quiz $quiz): array
{
return $this->getEntityManager()->createQuery(<<<DQL
select
c.id,
c.name,
sum(case when a.isRightAnswer = true then 1 else 0 end) as correct,
qc.corrections,
max(ga.created) - qc.created as time,
(sum(case when a.isRightAnswer = true then 1 else 0 end) + qc.corrections) as score
from Tvdt\Entity\Candidate c
join c.givenAnswers ga
join ga.answer a
join c.quizData qc
where qc.quiz = :quiz and ga.quiz = :quiz
group by ga.quiz, c.id, qc.id
order by score desc, time asc
DQL
select
c.id,
c.name,
count(case when a.isRightAnswer = true then 1 else null end) as correct,
qc.corrections,
max(ga.created) - qc.created as time,
(count(case when a.isRightAnswer = true then 1 else null end) + qc.corrections) as score
from Tvdt\Entity\Candidate c
join c.givenAnswers ga
join ga.answer a
join c.quizData qc
where qc.quiz = :quiz and ga.quiz = :quiz
group by ga.quiz, c.id, qc.id
order by score desc, time asc
DQL
)->setParameter('quiz', $quiz)->getResult();
}
}

View File

@@ -32,7 +32,7 @@ class QuestionRepository extends ServiceEntityRepository
and q1.quiz = :quiz
)
and qz = :quiz
DQL)
DQL)
->setMaxResults(1)
->setParameter('candidate', $candidate)
->setParameter('quiz', $candidate->getSeason()->getActiveQuiz())

View File

@@ -24,7 +24,7 @@ class SeasonRepository extends ServiceEntityRepository
{
return $this->getEntityManager()->createQuery(<<<DQL
select s from Tvdt\Entity\Season s where :user member of s.owners order by s.name
DQL
DQL
)->setParameter('user', $user)->getResult();
}
}

View File

@@ -47,15 +47,6 @@
"migrations/.gitignore"
]
},
"easycorp/easyadmin-bundle": {
"version": "4.23",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "b131e6cbfe1b898a508987851963fff485986285"
}
},
"friendsofphp/php-cs-fixer": {
"version": "3.65",
"recipe": {
@@ -276,12 +267,12 @@
]
},
"symfony/translation": {
"version": "7.2",
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b"
"ref": "620a1b84865ceb2ba304c8f8bf2a185fbf32a843"
},
"files": [
"config/packages/translation.yaml",
@@ -319,20 +310,8 @@
"ref": "c85ff94da66841d7ff087c19cbcd97a2df744ef9"
}
},
"symfony/ux-twig-component": {
"version": "2.22",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.13",
"ref": "67814b5f9794798b885cec9d3f48631424449a01"
},
"files": [
"config/packages/twig_component.yaml"
]
},
"symfony/validator": {
"version": "7.2",
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",

15
tests/object-manager.php Normal file
View 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();