2 Commits

Author SHA1 Message Date
0319224979 Dependey updates 2025-09-28 21:19:01 +02:00
81e471a760 Change namespace to Tvdt 2025-09-28 18:14:58 +02:00
102 changed files with 981 additions and 860 deletions

View File

@@ -1,6 +0,0 @@
{
"image": "mcr.microsoft.com/devcontainers/universal:2",
"features": {"ghcr.io/devcontainers/features/php:1": {
"version": "8.3"
}}
}

View File

@@ -35,6 +35,9 @@ indent_size = 4
trim_trailing_whitespace = false trim_trailing_whitespace = false
indent_size = 2 indent_size = 2
[config/**/*.{yaml,yml}]
indent_size = 4
[.github/workflows/*.yml] [.github/workflows/*.yml]
indent_size = 2 indent_size = 2

View File

@@ -1,4 +1,4 @@
# define your env variables for the test env here # define your env variables for the test env here
KERNEL_CLASS='App\Kernel' KERNEL_CLASS='Tvdt\Kernel'
APP_SECRET='$ecretf0rt3st' APP_SECRET='$ecretf0rt3st'
SYMFONY_DEPRECATIONS_HELPER=999999 SYMFONY_DEPRECATIONS_HELPER=999999

View File

@@ -2,8 +2,8 @@
<module type="WEB_MODULE" version="4"> <module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="Tvdt\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" /> <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tvdt\Tests\" />
<excludeFolder url="file://$MODULE_DIR$/vendor/clue/ndjson-react" /> <excludeFolder url="file://$MODULE_DIR$/vendor/clue/ndjson-react" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" /> <excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/collections" /> <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/collections" />
@@ -166,6 +166,7 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stimulus-bundle" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stimulus-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/ux-turbo" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/ux-turbo" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-uuid" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-uuid" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/brevo-mailer" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

1
.idea/php.xml generated
View File

@@ -197,6 +197,7 @@
<path value="$PROJECT_DIR$/vendor/symfony/stimulus-bundle" /> <path value="$PROJECT_DIR$/vendor/symfony/stimulus-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-uuid" /> <path value="$PROJECT_DIR$/vendor/symfony/polyfill-uuid" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php84" /> <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php84" />
<path value="$PROJECT_DIR$/vendor/symfony/brevo-mailer" />
</include_path> </include_path>
</component> </component>
<component name="PhpInterpreters"> <component name="PhpInterpreters">

View File

@@ -1,15 +1,15 @@
{ {
"controllers": { "controllers": {
"@symfony/ux-turbo": { "@symfony/ux-turbo": {
"turbo-core": { "turbo-core": {
"enabled": false, "enabled": false,
"fetch": "eager" "fetch": "eager"
}, },
"mercure-turbo-stream": { "mercure-turbo-stream": {
"enabled": false, "enabled": false,
"fetch": "eager" "fetch": "eager"
} }
} }
}, },
"entrypoints": [] "entrypoints": []
} }

View File

@@ -3,7 +3,7 @@
declare(strict_types=1); declare(strict_types=1);
use App\Kernel; use Tvdt\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_dir(dirname(__DIR__).'/vendor')) { if (!is_dir(dirname(__DIR__).'/vendor')) {

View File

@@ -10,17 +10,18 @@
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"doctrine/dbal": "^4.3.3", "doctrine/dbal": "^4.3.3",
"doctrine/doctrine-bundle": "^2.16.1", "doctrine/doctrine-bundle": "^2.16.2",
"doctrine/doctrine-migrations-bundle": "^3.4.2", "doctrine/doctrine-migrations-bundle": "^3.4.2",
"doctrine/orm": "^3.5.2", "doctrine/orm": "^3.5.2",
"easycorp/easyadmin-bundle": "^4.25.0", "easycorp/easyadmin-bundle": "^4.25.1",
"phpdocumentor/reflection-docblock": "^5.6.3", "phpdocumentor/reflection-docblock": "^5.6.3",
"phpoffice/phpspreadsheet": "^5.1", "phpoffice/phpspreadsheet": "^5.1",
"phpstan/phpdoc-parser": "^2.3", "phpstan/phpdoc-parser": "^2.3",
"runtime/frankenphp-symfony": "^0.2.0", "runtime/frankenphp-symfony": "^0.2.0",
"sentry/sentry-symfony": "^5.4", "sentry/sentry-symfony": "^5.6",
"symfony/asset": "7.3.*", "symfony/asset": "7.3.*",
"symfony/asset-mapper": "7.3.*", "symfony/asset-mapper": "7.3.*",
"symfony/brevo-mailer": "7.3.*",
"symfony/console": "7.3.*", "symfony/console": "7.3.*",
"symfony/dotenv": "7.3.*", "symfony/dotenv": "7.3.*",
"symfony/flex": "^2.8.2", "symfony/flex": "^2.8.2",
@@ -46,14 +47,14 @@
}, },
"require-dev": { "require-dev": {
"doctrine/doctrine-fixtures-bundle": "^4.1", "doctrine/doctrine-fixtures-bundle": "^4.1",
"friendsofphp/php-cs-fixer": "^3.87.1", "friendsofphp/php-cs-fixer": "^3.88.2",
"phpstan/extension-installer": "^1.4.3", "phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan": "^2.1.22", "phpstan/phpstan": "^2.1.29",
"phpstan/phpstan-doctrine": "^2.0.5", "phpstan/phpstan-doctrine": "^2.0.6",
"phpstan/phpstan-phpunit": "^2.0.7", "phpstan/phpstan-phpunit": "^2.0.7",
"phpstan/phpstan-symfony": "^2.0.8", "phpstan/phpstan-symfony": "^2.0.8",
"phpunit/phpunit": "^12.3.8", "phpunit/phpunit": "^12.3.15",
"rector/rector": "^2.1.6", "rector/rector": "^2.1.7",
"roave/security-advisories": "dev-latest", "roave/security-advisories": "dev-latest",
"symfony/browser-kit": "7.3.*", "symfony/browser-kit": "7.3.*",
"symfony/css-selector": "7.3.*", "symfony/css-selector": "7.3.*",
@@ -62,7 +63,7 @@
"symfony/stopwatch": "7.3.*", "symfony/stopwatch": "7.3.*",
"symfony/web-profiler-bundle": "7.3.*", "symfony/web-profiler-bundle": "7.3.*",
"thecodingmachine/phpstan-safe-rule": "^1.4.1", "thecodingmachine/phpstan-safe-rule": "^1.4.1",
"vincentlanglet/twig-cs-fixer": "^3.9.0" "vincentlanglet/twig-cs-fixer": "^3.10.0"
}, },
"config": { "config": {
"allow-plugins": { "allow-plugins": {
@@ -76,12 +77,12 @@
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"App\\": "src/" "Tvdt\\": "src/"
} }
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"App\\Tests\\": "tests/" "Tvdt\\Tests\\": "tests/"
} }
}, },
"replace": { "replace": {

720
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,15 @@
framework: framework:
asset_mapper: asset_mapper:
# The paths to make available to the asset mapper. # The paths to make available to the asset mapper.
paths: paths:
- assets/ - assets/
excluded_patterns: excluded_patterns:
- '*/assets/styles/_*.scss' - '*/assets/styles/_*.scss'
- '*/assets/styles/**/_*.scss' - '*/assets/styles/**/_*.scss'
missing_import_mode: strict missing_import_mode: strict
when@prod: when@prod:
framework: framework:
asset_mapper: asset_mapper:
missing_import_mode: warn missing_import_mode: warn

View File

@@ -1,54 +1,54 @@
doctrine: doctrine:
dbal: dbal:
url: '%env(resolve:DATABASE_URL)%' url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version, # IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file) # either here or in the DATABASE_URL env var (see .env file)
#server_version: '16' #server_version: '16'
profiling_collect_backtrace: '%kernel.debug%' profiling_collect_backtrace: '%kernel.debug%'
use_savepoints: true use_savepoints: true
orm: orm:
auto_generate_proxy_classes: true auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true enable_lazy_ghost_objects: true
report_fields_where_declared: true report_fields_where_declared: true
validate_xml_mapping: true validate_xml_mapping: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
identity_generation_preferences: identity_generation_preferences:
Doctrine\DBAL\Platforms\PostgreSQLPlatform: identity Doctrine\DBAL\Platforms\PostgreSQLPlatform: identity
auto_mapping: true auto_mapping: true
mappings: mappings:
App: Tvdt:
type: attribute type: attribute
is_bundle: false is_bundle: false
dir: '%kernel.project_dir%/src/Entity' dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity' prefix: 'Tvdt\Entity'
alias: App alias: Tvdt
controller_resolver: controller_resolver:
auto_mapping: false auto_mapping: false
when@test: when@test:
doctrine: doctrine:
dbal: dbal:
# "TEST_TOKEN" is typically set by ParaTest # "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%' dbname_suffix: '_test%env(default::TEST_TOKEN)%'
when@prod: when@prod:
doctrine: doctrine:
orm: orm:
auto_generate_proxy_classes: false auto_generate_proxy_classes: false
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
query_cache_driver: query_cache_driver:
type: pool type: pool
pool: doctrine.system_cache_pool pool: doctrine.system_cache_pool
result_cache_driver: result_cache_driver:
type: pool type: pool
pool: doctrine.result_cache_pool pool: doctrine.result_cache_pool
framework: framework:
cache: cache:
pools: pools:
doctrine.result_cache_pool: doctrine.result_cache_pool:
adapter: cache.app adapter: cache.app
doctrine.system_cache_pool: doctrine.system_cache_pool:
adapter: cache.system adapter: cache.system

View File

@@ -1,6 +1,6 @@
doctrine_migrations: doctrine_migrations:
migrations_paths: migrations_paths:
# namespace is arbitrary but should be different from App\Migrations # namespace is arbitrary but should be different from Tvdt\Migrations
# as migrations classes should NOT be autoloaded # as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/migrations' 'DoctrineMigrations': '%kernel.project_dir%/migrations'
enable_profiler: false enable_profiler: false

View File

@@ -1,23 +1,23 @@
# see https://symfony.com/doc/current/reference/configuration/framework.html # see https://symfony.com/doc/current/reference/configuration/framework.html
framework: framework:
secret: '%env(APP_SECRET)%' secret: '%env(APP_SECRET)%'
# Note that the session will be started ONLY if you read or write from it. # Note that the session will be started ONLY if you read or write from it.
session: true session: true
form: form:
csrf_protection: csrf_protection:
enabled: true enabled: true
#esi: true #esi: true
#fragments: true #fragments: true
when@prod: when@prod:
framework: framework:
# shortcut for private IP address ranges of your proxy # shortcut for private IP address ranges of your proxy
trusted_proxies: 'private_ranges' trusted_proxies: 'private_ranges'
# or, if your proxy instead uses the "Forwarded" header # or, if your proxy instead uses the "Forwarded" header
trusted_headers: [ 'forwarded' ] trusted_headers: [ 'forwarded' ]
when@test: when@test:
framework: framework:
test: true test: true
session: session:
storage_factory_id: session.storage.factory.mock_file storage_factory_id: session.storage.factory.mock_file

View File

@@ -1,7 +1,7 @@
framework: framework:
mailer: mailer:
dsn: '%env(MAILER_DSN)%' dsn: '%env(MAILER_DSN)%'
envelope: envelope:
sender: '%env(MAILER_SENDER)%' sender: '%env(MAILER_SENDER)%'
headers: headers:
From: 'Tijd voor de test <%env(MAILER_SENDER)%>' From: 'Tijd voor de test <%env(MAILER_SENDER)%>'

View File

@@ -1,10 +1,10 @@
framework: framework:
router: router:
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands. # Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
#default_uri: http://localhost #default_uri: http://localhost
when@prod: when@prod:
framework: framework:
router: router:
strict_requirements: null strict_requirements: null

View File

@@ -1,53 +1,53 @@
security: security:
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers: password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers: providers:
# used to reload user from session & other features (e.g. switch_user) # used to reload user from session & other features (e.g. switch_user)
app_user_provider: tvdt_user_provider:
entity: entity:
class: App\Entity\User class: Tvdt\Entity\User
property: email property: email
# used to reload user from session & other features (e.g. switch_user) # used to reload user from session & other features (e.g. switch_user)
firewalls: firewalls:
dev: dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/ pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false security: false
main: main:
lazy: true lazy: true
provider: app_user_provider provider: tvdt_user_provider
form_login: form_login:
login_path: app_login_login login_path: tvdt_login_login
check_path: app_login_login check_path: tvdt_login_login
enable_csrf: true enable_csrf: true
default_target_path: app_backoffice_index default_target_path: tvdt_backoffice_index
logout: logout:
path: app_login_logout path: tvdt_login_logout
# where to redirect after logout # where to redirect after logout
# target: app_any_route # target: tvdt_any_route
# activate different ways to authenticate # activate different ways to authenticate
# https://symfony.com/doc/current/security.html#the-firewall # https://symfony.com/doc/current/security.html#the-firewall
# https://symfony.com/doc/current/security/impersonating_user.html # https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true # switch_user: true
# Easy way to control access for large sections of your site # Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used # Note: Only the *first* access control that matches will be used
access_control: access_control:
- { path: ^/admin, roles: ROLE_ADMIN } - { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/backoffice, roles: ROLE_USER } - { path: ^/backoffice, roles: ROLE_USER }
when@test: when@test:
security: security:
password_hashers: password_hashers:
# By default, password hashers are resource intensive and take time. This is # By default, password hashers are resource intensive and take time. This is
# important to generate secure password hashes. In tests however, secure hashes # important to generate secure password hashes. In tests however, secure hashes
# are not important, waste resources and increase test times. The following # are not important, waste resources and increase test times. The following
# reduces the work factor to the lowest possible values. # reduces the work factor to the lowest possible values.
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto algorithm: auto
cost: 4 # Lowest possible value for bcrypt cost: 4 # Lowest possible value for bcrypt
time_cost: 3 # Lowest possible value for argon time_cost: 3 # Lowest possible value for argon
memory_cost: 10 # Lowest possible value for argon memory_cost: 10 # Lowest possible value for argon

View File

@@ -1,16 +1,16 @@
when@prod: when@prod:
sentry: sentry:
dsn: '%env(SENTRY_DSN)%' dsn: '%env(SENTRY_DSN)%'
# Add request headers, cookies, IP address and the authenticated user # Add request headers, cookies, IP address and the authenticated user
# see https://docs.sentry.io/platforms/php/data-management/data-collected/ for more info # see https://docs.sentry.io/platforms/php/data-management/data-collected/ for more info
# send_default_pii: true # send_default_pii: true
options: options:
traces_sample_rate: 1.0 traces_sample_rate: 1.0
profiles_sample_rate: 1.0 profiles_sample_rate: 1.0
ignore_exceptions: ignore_exceptions:
- 'Symfony\Component\ErrorHandler\Error\FatalError' - 'Symfony\Component\ErrorHandler\Error\FatalError'
- 'Symfony\Component\Debug\Exception\FatalErrorException' - 'Symfony\Component\Debug\Exception\FatalErrorException'
# If you are using Monolog, you also need this additional configuration to log the errors correctly: # If you are using Monolog, you also need this additional configuration to log the errors correctly:
# https://docs.sentry.io/platforms/php/guides/symfony/#monolog-integration # https://docs.sentry.io/platforms/php/guides/symfony/#monolog-integration

View File

@@ -1,7 +1,7 @@
framework: framework:
default_locale: nl default_locale: nl
translator: translator:
default_path: '%kernel.project_dir%/translations' default_path: '%kernel.project_dir%/translations'
fallbacks: fallbacks:
- en - en
providers: providers:

View File

@@ -1,7 +1,7 @@
twig: twig:
file_name_pattern: '*.twig' file_name_pattern: '*.twig'
form_themes: [ 'bootstrap_5_layout.html.twig' ] form_themes: [ 'bootstrap_5_layout.html.twig' ]
when@test: when@test:
twig: twig:
strict_variables: true strict_variables: true

View File

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

View File

@@ -1,4 +1,4 @@
framework: framework:
uid: uid:
default_uuid_version: 7 default_uuid_version: 7
time_based_uuid_version: 7 time_based_uuid_version: 7

View File

@@ -1,11 +1,11 @@
framework: framework:
validation: validation:
# Enables validator auto-mapping support. # Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata. # For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping: #auto_mapping:
# App\Entity\: [] # Tvdt\Entity\: []
when@test: when@test:
framework: framework:
validation: validation:
not_compromised_password: false not_compromised_password: false

View File

@@ -1,17 +1,17 @@
when@dev: when@dev:
web_profiler: web_profiler:
toolbar: true toolbar: true
intercept_redirects: false intercept_redirects: false
framework: framework:
profiler: profiler:
only_exceptions: false only_exceptions: false
collect_serializer_data: true collect_serializer_data: true
when@test: when@test:
web_profiler: web_profiler:
toolbar: false toolbar: false
intercept_redirects: false intercept_redirects: false
framework: framework:
profiler: { collect: false } profiler: { collect: false }

View File

@@ -1,5 +1,5 @@
controllers: controllers:
resource: resource:
path: ../src/Controller/ path: ../src/Controller/
namespace: App\Controller namespace: Tvdt\Controller
type: attribute type: attribute

View File

@@ -1,9 +1,9 @@
controllers: controllers:
resource: resource:
path: ../../src/Controller/ path: ../../src/Controller/
namespace: App\Controller namespace: Tvdt\Controller
type: attribute type: attribute
kernel: kernel:
resource: App\Kernel resource: Tvdt\Kernel
type: attribute type: attribute

View File

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

View File

@@ -1,4 +1,4 @@
when@dev: when@dev:
_errors: _errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.php' resource: '@FrameworkBundle/Resources/config/routing/errors.php'
prefix: /_error prefix: /_error

View File

@@ -1,3 +1,3 @@
_security_logout: _security_logout:
resource: security.route_loader.logout resource: security.route_loader.logout
type: service type: service

View File

@@ -1,8 +1,8 @@
when@dev: when@dev:
web_profiler_wdt: web_profiler_wdt:
resource: '@WebProfilerBundle/Resources/config/routing/wdt.php' resource: '@WebProfilerBundle/Resources/config/routing/wdt.php'
prefix: /_wdt prefix: /_wdt
web_profiler_profiler: web_profiler_profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.php' resource: '@WebProfilerBundle/Resources/config/routing/profiler.php'
prefix: /_profiler prefix: /_profiler

View File

@@ -6,19 +6,19 @@
parameters: parameters:
services: services:
# default configuration for services in *this* file # default configuration for services in *this* file
_defaults: _defaults:
autowire: true # Automatically injects dependencies in your services. autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services # makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name # this creates a service per class whose id is the fully-qualified class name
App\: Tvdt\:
resource: '../src/' resource: '../src/'
exclude: exclude:
- '../src/DependencyInjection/' - '../src/DependencyInjection/'
- '../src/Entity/' - '../src/Entity/'
- '../src/Kernel.php' - '../src/Kernel.php'
# add more service definitions when explicit configuration is needed # add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones # please note that last definitions always *replace* previous ones

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
use App\Kernel; use Tvdt\Kernel;
require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; require_once dirname(__DIR__).'/vendor/autoload_runtime.php';

View File

@@ -2,19 +2,19 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Command; namespace Tvdt\Command;
use App\Entity\SeasonSettings;
use App\Repository\SeasonRepository;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Tvdt\Entity\SeasonSettings;
use Tvdt\Repository\SeasonRepository;
#[AsCommand( #[AsCommand(
name: 'app:add-settings', name: 'tvdt:add-settings',
description: 'Add a short description for your command', description: 'Add a short description for your command',
)] )]
readonly class AddSettingsCommand readonly class AddSettingsCommand

View File

@@ -2,10 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Command; namespace Tvdt\Command;
use App\Repository\SeasonRepository;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\Argument; use Symfony\Component\Console\Attribute\Argument;
use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\AsCommand;
@@ -13,9 +11,11 @@ use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Tvdt\Repository\SeasonRepository;
use Tvdt\Repository\UserRepository;
#[AsCommand( #[AsCommand(
name: 'app:claim-season', name: 'tvdt:claim-season',
description: 'Give a user owner rights on a season', description: 'Give a user owner rights on a season',
)] )]
readonly class ClaimSeasonCommand readonly class ClaimSeasonCommand

View File

@@ -2,18 +2,18 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Command; namespace Tvdt\Command;
use App\Repository\UserRepository;
use Symfony\Component\Console\Attribute\Argument; use Symfony\Component\Console\Attribute\Argument;
use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use Tvdt\Repository\UserRepository;
#[AsCommand( #[AsCommand(
name: 'app:make-admin', name: 'tvdt:make-admin',
description: 'Give a user the role admin', description: 'Give a user the role admin',
)] )]
readonly class MakeAdminCommand readonly class MakeAdminCommand

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller; namespace Tvdt\Controller;
use App\Enum\FlashType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as AbstractBaseController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as AbstractBaseController;
use Tvdt\Enum\FlashType;
abstract class AbstractController extends AbstractBaseController abstract class AbstractController extends AbstractBaseController
{ {

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\Answer;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Answer;
/** @extends AbstractCrudController<Answer> */ /** @extends AbstractCrudController<Answer> */
class AnswerCrudController extends AbstractCrudController class AnswerCrudController extends AbstractCrudController

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\Candidate;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Candidate;
/** @extends AbstractCrudController<Candidate> */ /** @extends AbstractCrudController<Candidate> */
class CandidateCrudController extends AbstractCrudController class CandidateCrudController extends AbstractCrudController

View File

@@ -2,22 +2,22 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\Answer;
use App\Entity\Candidate;
use App\Entity\GivenAnswer;
use App\Entity\Question;
use App\Entity\Quiz;
use App\Entity\QuizCandidate;
use App\Entity\Season;
use App\Entity\User;
use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminDashboard; use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminDashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard; use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem; use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Symfony\Component\HttpFoundation\Response; 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')] #[AdminDashboard(routePath: '/admin', routeName: 'admin')]
class DashboardController extends AbstractDashboardController class DashboardController extends AbstractDashboardController

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\GivenAnswer;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\GivenAnswer;
/** @extends AbstractCrudController<GivenAnswer> */ /** @extends AbstractCrudController<GivenAnswer> */
class GivenAnswerCrudController extends AbstractCrudController class GivenAnswerCrudController extends AbstractCrudController

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\Question;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Question;
/** @extends AbstractCrudController<Question> */ /** @extends AbstractCrudController<Question> */
class QuestionCrudController extends AbstractCrudController class QuestionCrudController extends AbstractCrudController

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\QuizCandidate;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\QuizCandidate;
/** @extends AbstractCrudController<QuizCandidate> */ /** @extends AbstractCrudController<QuizCandidate> */
class QuizCorrectionCrudController extends AbstractCrudController class QuizCorrectionCrudController extends AbstractCrudController

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\Quiz;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Quiz;
/** @extends AbstractCrudController<Quiz> */ /** @extends AbstractCrudController<Quiz> */
class QuizCrudController extends AbstractCrudController class QuizCrudController extends AbstractCrudController

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\Season;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\Season;
/** @extends AbstractCrudController<Season> */ /** @extends AbstractCrudController<Season> */
class SeasonCrudController extends AbstractCrudController class SeasonCrudController extends AbstractCrudController

View File

@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Admin; namespace Tvdt\Controller\Admin;
use App\Entity\User;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Tvdt\Entity\User;
/** @extends AbstractCrudController<User> */ /** @extends AbstractCrudController<User> */
class UserCrudController extends AbstractCrudController class UserCrudController extends AbstractCrudController

View File

@@ -2,14 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Backoffice; namespace Tvdt\Controller\Backoffice;
use App\Controller\AbstractController;
use App\Entity\Season;
use App\Entity\User;
use App\Form\CreateSeasonFormType;
use App\Repository\SeasonRepository;
use App\Service\QuizSpreadsheetService;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\SecurityBundle\Security; use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@@ -18,6 +12,12 @@ use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Attribute\AsController; use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
use Tvdt\Controller\AbstractController;
use Tvdt\Entity\Season;
use Tvdt\Entity\User;
use Tvdt\Form\CreateSeasonFormType;
use Tvdt\Repository\SeasonRepository;
use Tvdt\Service\QuizSpreadsheetService;
#[AsController] #[AsController]
#[IsGranted('ROLE_USER')] #[IsGranted('ROLE_USER')]
@@ -28,7 +28,7 @@ final class BackofficeController extends AbstractController
private readonly Security $security, private readonly Security $security,
) {} ) {}
#[Route('/backoffice/', name: 'app_backoffice_index')] #[Route('/backoffice/', name: 'tvdt_backoffice_index')]
public function index(): Response public function index(): Response
{ {
$user = $this->getUser(); $user = $this->getUser();
@@ -43,7 +43,7 @@ final class BackofficeController extends AbstractController
]); ]);
} }
#[Route('/backoffice/season/add', name: 'app_backoffice_season_add', priority: 10)] #[Route('/backoffice/season/add', name: 'tvdt_backoffice_season_add', priority: 10)]
public function addSeason(Request $request, EntityManagerInterface $em): Response public function addSeason(Request $request, EntityManagerInterface $em): Response
{ {
$season = new Season(); $season = new Season();
@@ -61,13 +61,13 @@ final class BackofficeController extends AbstractController
$em->persist($season); $em->persist($season);
$em->flush(); $em->flush();
return $this->redirectToRoute('app_backoffice_season', ['seasonCode' => $season->getSeasonCode()]); return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $season->getSeasonCode()]);
} }
return $this->render('backoffice/season_add.html.twig', ['form' => $form]); return $this->render('backoffice/season_add.html.twig', ['form' => $form]);
} }
#[Route('/backoffice/template', name: 'app_backoffice_template', priority: 10)] #[Route('/backoffice/template', name: 'tvdt_backoffice_template', priority: 10)]
public function getTemplate(QuizSpreadsheetService $excel): Response public function getTemplate(QuizSpreadsheetService $excel): Response
{ {
$response = new StreamedResponse($excel->generateTemplate()); $response = new StreamedResponse($excel->generateTemplate());

View File

@@ -2,36 +2,36 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Backoffice; namespace Tvdt\Controller\Backoffice;
use App\Controller\AbstractController;
use App\Entity\Elimination;
use App\Entity\Quiz;
use App\Entity\Season;
use App\Factory\EliminationFactory;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Requirement\Requirement; use Symfony\Component\Routing\Requirement\Requirement;
use Tvdt\Controller\AbstractController;
use Tvdt\Entity\Elimination;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\Season;
use Tvdt\Factory\EliminationFactory;
final class PrepareEliminationController extends AbstractController final class PrepareEliminationController extends AbstractController
{ {
#[Route( #[Route(
'/backoffice/season/{seasonCode:season}/quiz/{quiz}/elimination/prepare', '/backoffice/season/{seasonCode:season}/quiz/{quiz}/elimination/prepare',
name: 'app_prepare_elimination', name: 'tvdt_prepare_elimination',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'quiz' => Requirement::UUID], requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'quiz' => Requirement::UUID],
)] )]
public function index(Season $season, Quiz $quiz, EliminationFactory $eliminationFactory): Response public function index(Season $season, Quiz $quiz, EliminationFactory $eliminationFactory): Response
{ {
$elimination = $eliminationFactory->createEliminationFromQuiz($quiz); $elimination = $eliminationFactory->createEliminationFromQuiz($quiz);
return $this->redirectToRoute('app_prepare_elimination_view', ['elimination' => $elimination->getId()]); return $this->redirectToRoute('tvdt_prepare_elimination_view', ['elimination' => $elimination->getId()]);
} }
#[Route( #[Route(
'/backoffice/elimination/{elimination}', '/backoffice/elimination/{elimination}',
name: 'app_prepare_elimination_view', name: 'tvdt_prepare_elimination_view',
requirements: ['elimination' => Requirement::UUID], requirements: ['elimination' => Requirement::UUID],
)] )]
public function viewElimination(Elimination $elimination, Request $request, EntityManagerInterface $em): Response public function viewElimination(Elimination $elimination, Request $request, EntityManagerInterface $em): Response
@@ -41,7 +41,7 @@ final class PrepareEliminationController extends AbstractController
$em->flush(); $em->flush();
if ($request->request->getBoolean('start')) { if ($request->request->getBoolean('start')) {
return $this->redirectToRoute('app_elimination', ['elimination' => $elimination->getId()]); return $this->redirectToRoute('tvdt_elimination', ['elimination' => $elimination->getId()]);
} }
$this->addFlash('success', 'Elimination updated'); $this->addFlash('success', 'Elimination updated');

View File

@@ -2,17 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Backoffice; namespace Tvdt\Controller\Backoffice;
use App\Controller\AbstractController;
use App\Entity\Candidate;
use App\Entity\Quiz;
use App\Entity\Season;
use App\Exception\ErrorClearingQuizException;
use App\Repository\CandidateRepository;
use App\Repository\QuizCandidateRepository;
use App\Repository\QuizRepository;
use App\Security\Voter\SeasonVoter;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@@ -23,6 +14,15 @@ use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Requirement\Requirement; use Symfony\Component\Routing\Requirement\Requirement;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Tvdt\Controller\AbstractController;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\Season;
use Tvdt\Exception\ErrorClearingQuizException;
use Tvdt\Repository\CandidateRepository;
use Tvdt\Repository\QuizCandidateRepository;
use Tvdt\Repository\QuizRepository;
use Tvdt\Security\Voter\SeasonVoter;
#[AsController] #[AsController]
#[IsGranted('ROLE_USER')] #[IsGranted('ROLE_USER')]
@@ -35,7 +35,7 @@ class QuizController extends AbstractController
#[Route( #[Route(
'/backoffice/season/{seasonCode:season}/quiz/{quiz}', '/backoffice/season/{seasonCode:season}/quiz/{quiz}',
name: 'app_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')] #[IsGranted(SeasonVoter::EDIT, subject: 'season')]
@@ -50,7 +50,7 @@ class QuizController extends AbstractController
#[Route( #[Route(
'/backoffice/season/{seasonCode:season}/quiz/{quiz}/enable', '/backoffice/season/{seasonCode:season}/quiz/{quiz}/enable',
name: 'app_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')] #[IsGranted(SeasonVoter::EDIT, subject: 'season')]
@@ -60,15 +60,15 @@ class QuizController extends AbstractController
$em->flush(); $em->flush();
if ($quiz instanceof Quiz) { if ($quiz instanceof Quiz) {
return $this->redirectToRoute('app_backoffice_quiz', ['seasonCode' => $season->getSeasonCode(), 'quiz' => $quiz->getId()]); return $this->redirectToRoute('tvdt_backoffice_quiz', ['seasonCode' => $season->getSeasonCode(), 'quiz' => $quiz->getId()]);
} }
return $this->redirectToRoute('app_backoffice_season', ['seasonCode' => $season->getSeasonCode()]); return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $season->getSeasonCode()]);
} }
#[Route( #[Route(
'/backoffice/quiz/{quiz}/clear', '/backoffice/quiz/{quiz}/clear',
name: 'app_backoffice_quiz_clear', name: 'tvdt_backoffice_quiz_clear',
requirements: ['quiz' => Requirement::UUID], requirements: ['quiz' => Requirement::UUID],
)] )]
#[IsGranted(SeasonVoter::EDIT, subject: 'quiz')] #[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
@@ -81,12 +81,12 @@ class QuizController extends AbstractController
$this->addFlash('error', $this->translator->trans('Error clearing quiz')); $this->addFlash('error', $this->translator->trans('Error clearing quiz'));
} }
return $this->redirectToRoute('app_backoffice_quiz', ['seasonCode' => $quiz->getSeason()->getSeasonCode(), 'quiz' => $quiz->getId()]); return $this->redirectToRoute('tvdt_backoffice_quiz', ['seasonCode' => $quiz->getSeason()->getSeasonCode(), 'quiz' => $quiz->getId()]);
} }
#[Route( #[Route(
'/backoffice/quiz/{quiz}/delete', '/backoffice/quiz/{quiz}/delete',
name: 'app_backoffice_quiz_delete', name: 'tvdt_backoffice_quiz_delete',
requirements: ['quiz' => Requirement::UUID], requirements: ['quiz' => Requirement::UUID],
)] )]
#[IsGranted(SeasonVoter::DELETE, subject: 'quiz')] #[IsGranted(SeasonVoter::DELETE, subject: 'quiz')]
@@ -96,12 +96,12 @@ class QuizController extends AbstractController
$this->addFlash('success', $this->translator->trans('Quiz deleted')); $this->addFlash('success', $this->translator->trans('Quiz deleted'));
return $this->redirectToRoute('app_backoffice_season', ['seasonCode' => $quiz->getSeason()->getSeasonCode()]); return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $quiz->getSeason()->getSeasonCode()]);
} }
#[Route( #[Route(
'/backoffice/quiz/{quiz}/candidate/{candidate}/modify_correction', '/backoffice/quiz/{quiz}/candidate/{candidate}/modify_correction',
name: 'app_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')] #[IsGranted(SeasonVoter::EDIT, subject: 'quiz')]
@@ -115,6 +115,6 @@ class QuizController extends AbstractController
$quizCandidateRepository->setCorrectionsForCandidate($quiz, $candidate, $corrections); $quizCandidateRepository->setCorrectionsForCandidate($quiz, $candidate, $corrections);
return $this->redirectToRoute('app_backoffice_quiz', ['seasonCode' => $quiz->getSeason()->getSeasonCode(), 'quiz' => $quiz->getId()]); return $this->redirectToRoute('tvdt_backoffice_quiz', ['seasonCode' => $quiz->getSeason()->getSeasonCode(), 'quiz' => $quiz->getId()]);
} }
} }

View File

@@ -2,18 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Backoffice; namespace Tvdt\Controller\Backoffice;
use App\Controller\AbstractController;
use App\Entity\Candidate;
use App\Entity\Quiz;
use App\Entity\Season;
use App\Enum\FlashType;
use App\Form\AddCandidatesFormType;
use App\Form\SettingsForm;
use App\Form\UploadQuizFormType;
use App\Security\Voter\SeasonVoter;
use App\Service\QuizSpreadsheetService;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@@ -22,6 +12,16 @@ use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Tvdt\Controller\AbstractController;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\Season;
use Tvdt\Enum\FlashType;
use Tvdt\Form\AddCandidatesFormType;
use Tvdt\Form\SettingsForm;
use Tvdt\Form\UploadQuizFormType;
use Tvdt\Security\Voter\SeasonVoter;
use Tvdt\Service\QuizSpreadsheetService;
#[AsController] #[AsController]
#[IsGranted('ROLE_USER')] #[IsGranted('ROLE_USER')]
@@ -34,7 +34,7 @@ class SeasonController extends AbstractController
#[Route( #[Route(
'/backoffice/season/{seasonCode:season}', '/backoffice/season/{seasonCode:season}',
name: 'app_backoffice_season', name: 'tvdt_backoffice_season',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX], requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
)] )]
#[IsGranted(SeasonVoter::EDIT, subject: 'season')] #[IsGranted(SeasonVoter::EDIT, subject: 'season')]
@@ -56,7 +56,7 @@ class SeasonController extends AbstractController
#[Route( #[Route(
'/backoffice/season/{seasonCode:season}/add-candidate', '/backoffice/season/{seasonCode:season}/add-candidate',
name: 'app_backoffice_add_candidates', name: 'tvdt_backoffice_add_candidates',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX], requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
priority: 10, priority: 10,
)] )]
@@ -74,7 +74,7 @@ class SeasonController extends AbstractController
$this->em->flush(); $this->em->flush();
return $this->redirectToRoute('app_backoffice_season', ['seasonCode' => $season->getSeasonCode()]); return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $season->getSeasonCode()]);
} }
return $this->render('backoffice/season_add_candidates.html.twig', ['form' => $form]); return $this->render('backoffice/season_add_candidates.html.twig', ['form' => $form]);
@@ -82,7 +82,7 @@ class SeasonController extends AbstractController
#[Route( #[Route(
'/backoffice/season/{seasonCode:season}/add-quiz', '/backoffice/season/{seasonCode:season}/add-quiz',
name: 'app_backoffice_quiz_add', name: 'tvdt_backoffice_quiz_add',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX], requirements: ['seasonCode' => self::SEASON_CODE_REGEX],
priority: 10, priority: 10,
)] )]
@@ -106,7 +106,7 @@ class SeasonController extends AbstractController
$this->addFlash(FlashType::Success, $this->translator->trans('Quiz Added!')); $this->addFlash(FlashType::Success, $this->translator->trans('Quiz Added!'));
return $this->redirectToRoute('app_backoffice_season', ['seasonCode' => $season->getSeasonCode()]); return $this->redirectToRoute('tvdt_backoffice_season', ['seasonCode' => $season->getSeasonCode()]);
} }
return $this->render('/backoffice/quiz_add.html.twig', ['form' => $form, 'season' => $season]); return $this->render('/backoffice/quiz_add.html.twig', ['form' => $form, 'season' => $season]);

View File

@@ -2,15 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller; namespace Tvdt\Controller;
use App\Entity\Candidate;
use App\Entity\Elimination;
use App\Enum\FlashType;
use App\Form\EliminationEnterNameType;
use App\Helpers\Base64;
use App\Repository\CandidateRepository;
use App\Security\Voter\SeasonVoter;
use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@@ -19,6 +12,13 @@ use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Requirement\Requirement; use Symfony\Component\Routing\Requirement\Requirement;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\Elimination;
use Tvdt\Enum\FlashType;
use Tvdt\Form\EliminationEnterNameType;
use Tvdt\Helpers\Base64;
use Tvdt\Repository\CandidateRepository;
use Tvdt\Security\Voter\SeasonVoter;
use function Symfony\Component\Translation\t; use function Symfony\Component\Translation\t;
@@ -28,7 +28,7 @@ final class EliminationController extends AbstractController
{ {
public function __construct(private readonly TranslatorInterface $translator) {} public function __construct(private readonly TranslatorInterface $translator) {}
#[Route('/elimination/{elimination}', name: 'app_elimination', requirements: ['elimination' => Requirement::UUID])] #[Route('/elimination/{elimination}', name: 'tvdt_elimination', requirements: ['elimination' => Requirement::UUID])]
#[IsGranted(SeasonVoter::ELIMINATION, 'elimination')] #[IsGranted(SeasonVoter::ELIMINATION, 'elimination')]
public function index(#[MapEntity] Elimination $elimination, Request $request): Response public function index(#[MapEntity] Elimination $elimination, Request $request): Response
{ {
@@ -39,7 +39,7 @@ final class EliminationController extends AbstractController
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$name = $form->get('name')->getData(); $name = $form->get('name')->getData();
return $this->redirectToRoute('app_elimination_candidate', ['elimination' => $elimination->getId(), 'candidateHash' => Base64::base64UrlEncode($name)]); return $this->redirectToRoute('tvdt_elimination_candidate', ['elimination' => $elimination->getId(), 'candidateHash' => Base64::base64UrlEncode($name)]);
} }
return $this->render('quiz/elimination/index.html.twig', [ return $this->render('quiz/elimination/index.html.twig', [
@@ -48,7 +48,7 @@ final class EliminationController extends AbstractController
]); ]);
} }
#[Route('/elimination/{elimination}/{candidateHash}', name: 'app_elimination_candidate', requirements: ['elimination' => Requirement::UUID, 'candidateHash' => self::CANDIDATE_HASH_REGEX])] #[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')]
public function candidateScreen(Elimination $elimination, string $candidateHash, CandidateRepository $candidateRepository): Response public function candidateScreen(Elimination $elimination, string $candidateHash, CandidateRepository $candidateRepository): Response
{ {
@@ -58,7 +58,7 @@ final class EliminationController extends AbstractController
t('Cound not find candidate with name %name%', ['%name%' => Base64::base64UrlDecode($candidateHash)])->trans($this->translator), t('Cound not find candidate with name %name%', ['%name%' => Base64::base64UrlDecode($candidateHash)])->trans($this->translator),
); );
return $this->redirectToRoute('app_elimination', ['elimination' => $elimination->getId()]); return $this->redirectToRoute('tvdt_elimination', ['elimination' => $elimination->getId()]);
} }
$screenColour = $elimination->getScreenColour($candidate->getName()); $screenColour = $elimination->getScreenColour($candidate->getName());
@@ -66,7 +66,7 @@ final class EliminationController extends AbstractController
if (null === $screenColour) { if (null === $screenColour) {
$this->addFlash(FlashType::Warning, $this->translator->trans('Cound not find candidate with name %name% in elimination.', ['%name%' => $candidate->getName()])); $this->addFlash(FlashType::Warning, $this->translator->trans('Cound not find candidate with name %name% in elimination.', ['%name%' => $candidate->getName()]));
return $this->redirectToRoute('app_elimination', ['elimination' => $elimination->getId()]); return $this->redirectToRoute('tvdt_elimination', ['elimination' => $elimination->getId()]);
} }
return $this->render('quiz/elimination/candidate.html.twig', [ return $this->render('quiz/elimination/candidate.html.twig', [

View File

@@ -2,20 +2,20 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller; namespace Tvdt\Controller;
use App\Enum\FlashType;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController; use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Tvdt\Enum\FlashType;
#[AsController] #[AsController]
final class LoginController extends AbstractController final class LoginController extends AbstractController
{ {
#[Route(path: '/login', name: 'app_login_login')] #[Route(path: '/login', name: 'tvdt_login_login')]
public function login(AuthenticationUtils $authenticationUtils, TranslatorInterface $translator): Response public function login(AuthenticationUtils $authenticationUtils, TranslatorInterface $translator): Response
{ {
// get the login error if there is one // get the login error if there is one
@@ -34,7 +34,7 @@ final class LoginController extends AbstractController
]); ]);
} }
#[Route(path: '/logout', name: 'app_login_logout')] #[Route(path: '/logout', name: 'tvdt_login_logout')]
public function logout(): never public function logout(): never
{ {
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.'); throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');

View File

@@ -2,37 +2,37 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller; namespace Tvdt\Controller;
use App\Entity\Answer;
use App\Entity\Candidate;
use App\Entity\GivenAnswer;
use App\Entity\Question;
use App\Entity\Quiz;
use App\Entity\Season;
use App\Enum\FlashType;
use App\Form\EnterNameType;
use App\Form\SelectSeasonType;
use App\Helpers\Base64;
use App\Repository\AnswerRepository;
use App\Repository\CandidateRepository;
use App\Repository\GivenAnswerRepository;
use App\Repository\QuestionRepository;
use App\Repository\QuizCandidateRepository;
use App\Repository\SeasonRepository;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController; use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Tvdt\Entity\Answer;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\GivenAnswer;
use Tvdt\Entity\Question;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\Season;
use Tvdt\Enum\FlashType;
use Tvdt\Form\EnterNameType;
use Tvdt\Form\SelectSeasonType;
use Tvdt\Helpers\Base64;
use Tvdt\Repository\AnswerRepository;
use Tvdt\Repository\CandidateRepository;
use Tvdt\Repository\GivenAnswerRepository;
use Tvdt\Repository\QuestionRepository;
use Tvdt\Repository\QuizCandidateRepository;
use Tvdt\Repository\SeasonRepository;
#[AsController] #[AsController]
final class QuizController extends AbstractController final class QuizController extends AbstractController
{ {
public function __construct(private readonly TranslatorInterface $translator) {} public function __construct(private readonly TranslatorInterface $translator) {}
#[Route(path: '/', name: 'app_quiz_select_season', methods: ['GET', 'POST'])] #[Route(path: '/', name: 'tvdt_quiz_select_season', methods: ['GET', 'POST'])]
public function selectSeason(Request $request, SeasonRepository $seasonRepository): Response public function selectSeason(Request $request, SeasonRepository $seasonRepository): Response
{ {
$form = $this->createForm(SelectSeasonType::class); $form = $this->createForm(SelectSeasonType::class);
@@ -44,16 +44,16 @@ final class QuizController extends AbstractController
if ([] === $seasonRepository->findBy(['seasonCode' => $seasonCode])) { if ([] === $seasonRepository->findBy(['seasonCode' => $seasonCode])) {
$this->addFlash(FlashType::Warning, $this->translator->trans('Invalid season code')); $this->addFlash(FlashType::Warning, $this->translator->trans('Invalid season code'));
return $this->redirectToRoute('app_quiz_select_season'); return $this->redirectToRoute('tvdt_quiz_select_season');
} }
return $this->redirectToRoute('app_quiz_enter_name', ['seasonCode' => $seasonCode]); return $this->redirectToRoute('tvdt_quiz_enter_name', ['seasonCode' => $seasonCode]);
} }
return $this->render('quiz/select_season.html.twig', ['form' => $form]); return $this->render('quiz/select_season.html.twig', ['form' => $form]);
} }
#[Route(path: '/{seasonCode:season}', name: 'app_quiz_enter_name', requirements: ['seasonCode' => self::SEASON_CODE_REGEX])] #[Route(path: '/{seasonCode:season}', name: 'tvdt_quiz_enter_name', requirements: ['seasonCode' => self::SEASON_CODE_REGEX])]
public function enterName( public function enterName(
Request $request, Request $request,
Season $season, Season $season,
@@ -65,7 +65,7 @@ final class QuizController extends AbstractController
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$name = $form->get('name')->getData(); $name = $form->get('name')->getData();
return $this->redirectToRoute('app_quiz_quiz_page', ['seasonCode' => $season->getSeasonCode(), 'nameHash' => Base64::base64UrlEncode($name)]); return $this->redirectToRoute('tvdt_quiz_quiz_page', ['seasonCode' => $season->getSeasonCode(), 'nameHash' => Base64::base64UrlEncode($name)]);
} }
return $this->render('quiz/enter_name.twig', ['season' => $season, 'form' => $form]); return $this->render('quiz/enter_name.twig', ['season' => $season, 'form' => $form]);
@@ -73,7 +73,7 @@ final class QuizController extends AbstractController
#[Route( #[Route(
path: '/{seasonCode:season}/{nameHash}', path: '/{seasonCode:season}/{nameHash}',
name: 'app_quiz_quiz_page', name: 'tvdt_quiz_quiz_page',
requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'nameHash' => self::CANDIDATE_HASH_REGEX], requirements: ['seasonCode' => self::SEASON_CODE_REGEX, 'nameHash' => self::CANDIDATE_HASH_REGEX],
)] )]
public function quizPage( public function quizPage(
@@ -91,7 +91,7 @@ final class QuizController extends AbstractController
if (!$candidate instanceof Candidate) { if (!$candidate instanceof Candidate) {
$this->addFlash(FlashType::Danger, $this->translator->trans('Candidate not found')); $this->addFlash(FlashType::Danger, $this->translator->trans('Candidate not found'));
return $this->redirectToRoute('app_quiz_enter_name', ['seasonCode' => $season->getSeasonCode()]); return $this->redirectToRoute('tvdt_quiz_enter_name', ['seasonCode' => $season->getSeasonCode()]);
} }
$quiz = $season->getActiveQuiz(); $quiz = $season->getActiveQuiz();
@@ -99,7 +99,7 @@ final class QuizController extends AbstractController
if (!$quiz instanceof Quiz) { if (!$quiz instanceof Quiz) {
$this->addFlash(FlashType::Warning, $this->translator->trans('There is no active quiz')); $this->addFlash(FlashType::Warning, $this->translator->trans('There is no active quiz'));
return $this->redirectToRoute('app_quiz_enter_name', ['seasonCode' => $season->getSeasonCode()]); return $this->redirectToRoute('tvdt_quiz_enter_name', ['seasonCode' => $season->getSeasonCode()]);
} }
if ('POST' === $request->getMethod()) { if ('POST' === $request->getMethod()) {
@@ -112,7 +112,7 @@ final class QuizController extends AbstractController
$givenAnswer = new GivenAnswer($candidate, $answer->getQuestion()->getQuiz(), $answer); $givenAnswer = new GivenAnswer($candidate, $answer->getQuestion()->getQuiz(), $answer);
$givenAnswerRepository->save($givenAnswer); $givenAnswerRepository->save($givenAnswer);
return $this->redirectToRoute('app_quiz_quiz_page', ['seasonCode' => $season->getSeasonCode(), 'nameHash' => $nameHash]); return $this->redirectToRoute('tvdt_quiz_quiz_page', ['seasonCode' => $season->getSeasonCode(), 'nameHash' => $nameHash]);
} }
$question = $questionRepository->findNextQuestionForCandidate($candidate); $question = $questionRepository->findNextQuestionForCandidate($candidate);
@@ -120,7 +120,7 @@ final class QuizController extends AbstractController
if (!$question instanceof Question) { if (!$question instanceof Question) {
$this->addFlash(FlashType::Success, $this->translator->trans('Quiz completed')); $this->addFlash(FlashType::Success, $this->translator->trans('Quiz completed'));
return $this->redirectToRoute('app_quiz_enter_name', ['seasonCode' => $season->getSeasonCode()]); return $this->redirectToRoute('tvdt_quiz_enter_name', ['seasonCode' => $season->getSeasonCode()]);
} }
$quizCandidateRepository->createIfNotExist($quiz, $candidate); $quizCandidateRepository->createIfNotExist($quiz, $candidate);

View File

@@ -2,12 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller; namespace Tvdt\Controller;
use App\Entity\User;
use App\Form\RegistrationFormType;
use App\Repository\UserRepository;
use App\Security\EmailVerifier;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Bridge\Twig\Mime\TemplatedEmail;
@@ -20,12 +16,16 @@ use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface; use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
use Tvdt\Entity\User;
use Tvdt\Form\RegistrationFormType;
use Tvdt\Repository\UserRepository;
use Tvdt\Security\EmailVerifier;
final class RegistrationController extends AbstractController final class RegistrationController extends AbstractController
{ {
public function __construct(private readonly EmailVerifier $emailVerifier, private readonly TranslatorInterface $translator) {} public function __construct(private readonly EmailVerifier $emailVerifier, private readonly TranslatorInterface $translator) {}
#[Route('/register', name: 'app_register')] #[Route('/register', name: 'tvdt_register')]
public function register( public function register(
Request $request, Request $request,
UserPasswordHasherInterface $userPasswordHasher, UserPasswordHasherInterface $userPasswordHasher,
@@ -48,7 +48,7 @@ final class RegistrationController extends AbstractController
try { try {
// generate a signed url and email it to the user // generate a signed url and email it to the user
$this->emailVerifier->sendEmailConfirmation('app_verify_email', $user, $this->emailVerifier->sendEmailConfirmation('tvdt_verify_email', $user,
new TemplatedEmail() new TemplatedEmail()
->to((string) $user->getEmail()) ->to((string) $user->getEmail())
->subject($this->translator->trans('Please Confirm your Email')) ->subject($this->translator->trans('Please Confirm your Email'))
@@ -69,19 +69,19 @@ final class RegistrationController extends AbstractController
]); ]);
} }
#[Route('/verify/email', name: 'app_verify_email')] #[Route('/verify/email', name: 'tvdt_verify_email')]
public function verifyUserEmail(Request $request, TranslatorInterface $translator, UserRepository $userRepository): Response public function verifyUserEmail(Request $request, TranslatorInterface $translator, UserRepository $userRepository): Response
{ {
$id = $request->query->get('id'); $id = $request->query->get('id');
if (null === $id) { if (null === $id) {
return $this->redirectToRoute('app_register'); return $this->redirectToRoute('tvdt_register');
} }
$user = $userRepository->find($id); $user = $userRepository->find($id);
if (null === $user) { if (null === $user) {
return $this->redirectToRoute('app_register'); return $this->redirectToRoute('tvdt_register');
} }
// validate email confirmation link, sets User::isVerified=true and persists // validate email confirmation link, sets User::isVerified=true and persists
@@ -90,11 +90,11 @@ final class RegistrationController extends AbstractController
} catch (VerifyEmailExceptionInterface $verifyEmailException) { } catch (VerifyEmailExceptionInterface $verifyEmailException) {
$this->addFlash('verify_email_error', $translator->trans($verifyEmailException->getReason(), [], 'VerifyEmailBundle')); $this->addFlash('verify_email_error', $translator->trans($verifyEmailException->getReason(), [], 'VerifyEmailBundle'));
return $this->redirectToRoute('app_register'); return $this->redirectToRoute('tvdt_register');
} }
$this->addFlash('success', $this->translator->trans('Your email address has been verified.')); $this->addFlash('success', $this->translator->trans('Your email address has been verified.'));
return $this->redirectToRoute('app_backoffice_index'); return $this->redirectToRoute('tvdt_backoffice_index');
} }
} }

View File

@@ -2,15 +2,15 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\DataFixtures; namespace Tvdt\DataFixtures;
use App\Entity\Answer;
use App\Entity\Candidate;
use App\Entity\Question;
use App\Entity\Quiz;
use App\Entity\Season;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectManager;
use Tvdt\Entity\Answer;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\Question;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\Season;
class KrtekFixtures extends Fixture class KrtekFixtures extends Fixture
{ {

View File

@@ -2,9 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\AnswerRepository;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
@@ -12,6 +11,7 @@ use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\AnswerRepository;
#[ORM\Entity(repositoryClass: AnswerRepository::class)] #[ORM\Entity(repositoryClass: AnswerRepository::class)]
class Answer class Answer

View File

@@ -2,16 +2,16 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Helpers\Base64;
use App\Repository\CandidateRepository;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Helpers\Base64;
use Tvdt\Repository\CandidateRepository;
#[ORM\Entity(repositoryClass: CandidateRepository::class)] #[ORM\Entity(repositoryClass: CandidateRepository::class)]
#[ORM\UniqueConstraint(fields: ['name', 'season'])] #[ORM\UniqueConstraint(fields: ['name', 'season'])]

View File

@@ -2,9 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\EliminationRepository;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Safe\DateTimeImmutable; use Safe\DateTimeImmutable;
@@ -12,6 +11,7 @@ use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\HttpFoundation\InputBag; use Symfony\Component\HttpFoundation\InputBag;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\EliminationRepository;
#[ORM\Entity(repositoryClass: EliminationRepository::class)] #[ORM\Entity(repositoryClass: EliminationRepository::class)]
#[ORM\HasLifecycleCallbacks] #[ORM\HasLifecycleCallbacks]

View File

@@ -2,15 +2,15 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\GivenAnswerRepository;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Safe\DateTimeImmutable; use Safe\DateTimeImmutable;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\GivenAnswerRepository;
#[ORM\Entity(repositoryClass: GivenAnswerRepository::class)] #[ORM\Entity(repositoryClass: GivenAnswerRepository::class)]
#[ORM\HasLifecycleCallbacks] #[ORM\HasLifecycleCallbacks]

View File

@@ -2,9 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\QuestionRepository;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
@@ -12,6 +11,7 @@ use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\QuestionRepository;
#[ORM\Entity(repositoryClass: QuestionRepository::class)] #[ORM\Entity(repositoryClass: QuestionRepository::class)]
class Question class Question

View File

@@ -2,15 +2,15 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\QuizRepository;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\QuizRepository;
#[ORM\Entity(repositoryClass: QuizRepository::class)] #[ORM\Entity(repositoryClass: QuizRepository::class)]
#[ORM\UniqueConstraint(fields: ['name', 'season'])] #[ORM\UniqueConstraint(fields: ['name', 'season'])]

View File

@@ -2,15 +2,15 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\QuizCandidateRepository;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Safe\DateTimeImmutable; use Safe\DateTimeImmutable;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\QuizCandidateRepository;
#[ORM\Entity(repositoryClass: QuizCandidateRepository::class)] #[ORM\Entity(repositoryClass: QuizCandidateRepository::class)]
#[ORM\UniqueConstraint(columns: ['candidate_id', 'quiz_id'])] #[ORM\UniqueConstraint(columns: ['candidate_id', 'quiz_id'])]

View File

@@ -2,15 +2,15 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\SeasonRepository;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\SeasonRepository;
#[ORM\Entity(repositoryClass: SeasonRepository::class)] #[ORM\Entity(repositoryClass: SeasonRepository::class)]
class Season class Season

View File

@@ -2,14 +2,14 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\SeasonSettingsRepository;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator; use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Bridge\Doctrine\Types\UuidType; use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\SeasonSettingsRepository;
#[ORM\Entity(repositoryClass: SeasonSettingsRepository::class)] #[ORM\Entity(repositoryClass: SeasonSettingsRepository::class)]
class SeasonSettings class SeasonSettings

View File

@@ -2,9 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Entity; namespace Tvdt\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
@@ -15,6 +14,7 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Repository\UserRepository;
#[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`')] #[ORM\Table(name: '`user`')]

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Enum; namespace Tvdt\Enum;
enum FlashType: string enum FlashType: string
{ {

View File

@@ -2,6 +2,6 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Exception; namespace Tvdt\Exception;
class ErrorClearingQuizException extends \Exception {} class ErrorClearingQuizException extends \Exception {}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Exception; namespace Tvdt\Exception;
class SpreadsheetDataException extends SpreadsheetException class SpreadsheetDataException extends SpreadsheetException
{ {

View File

@@ -2,6 +2,6 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Exception; namespace Tvdt\Exception;
class SpreadsheetException extends \Exception {} class SpreadsheetException extends \Exception {}

View File

@@ -2,12 +2,12 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Factory; namespace Tvdt\Factory;
use App\Entity\Elimination;
use App\Entity\Quiz;
use App\Repository\CandidateRepository;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Tvdt\Entity\Elimination;
use Tvdt\Entity\Quiz;
use Tvdt\Repository\CandidateRepository;
final readonly class EliminationFactory final readonly class EliminationFactory
{ {

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Form; namespace Tvdt\Form;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextareaType;

View File

@@ -2,14 +2,14 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Form; namespace Tvdt\Form;
use App\Entity\Season;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Tvdt\Entity\Season;
/** @extends AbstractType<Season> */ /** @extends AbstractType<Season> */
class CreateSeasonFormType extends AbstractType class CreateSeasonFormType extends AbstractType

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Form; namespace Tvdt\Form;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Form; namespace Tvdt\Form;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;

View File

@@ -2,9 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Form; namespace Tvdt\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType; use Symfony\Component\Form\Extension\Core\Type\PasswordType;
@@ -14,6 +13,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Tvdt\Entity\User;
/** /**
* @extends AbstractType<User> * @extends AbstractType<User>

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Form; namespace Tvdt\Form;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;

View File

@@ -2,13 +2,13 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Form; namespace Tvdt\Form;
use App\Entity\SeasonSettings;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Tvdt\Entity\SeasonSettings;
/** @extends AbstractType<SeasonSettings> */ /** @extends AbstractType<SeasonSettings> */
class SettingsForm extends AbstractType class SettingsForm extends AbstractType

View File

@@ -2,9 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Form; namespace Tvdt\Form;
use App\Entity\Quiz;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
@@ -12,6 +11,7 @@ use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Constraints\File;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
use Tvdt\Entity\Quiz;
/** @extends AbstractType<Quiz> */ /** @extends AbstractType<Quiz> */
class UploadQuizFormType extends AbstractType class UploadQuizFormType extends AbstractType

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Helpers; namespace Tvdt\Helpers;
use Safe\Exceptions\UrlException; use Safe\Exceptions\UrlException;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App; namespace Tvdt;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel; use Symfony\Component\HttpKernel\Kernel as BaseKernel;

View File

@@ -2,11 +2,11 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\Answer;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Tvdt\Entity\Answer;
/** /**
* @extends ServiceEntityRepository<Answer> * @extends ServiceEntityRepository<Answer>

View File

@@ -2,16 +2,16 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\Candidate;
use App\Entity\Quiz;
use App\Entity\Season;
use App\Helpers\Base64;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Safe\Exceptions\UrlException; use Safe\Exceptions\UrlException;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\Season;
use Tvdt\Helpers\Base64;
/** /**
* @extends ServiceEntityRepository<Candidate> * @extends ServiceEntityRepository<Candidate>
@@ -35,7 +35,7 @@ class CandidateRepository extends ServiceEntityRepository
} }
return $this->getEntityManager()->createQuery(<<<DQL return $this->getEntityManager()->createQuery(<<<DQL
select c from App\Entity\Candidate c select c from Tvdt\Entity\Candidate c
where c.season = :season where c.season = :season
and lower(c.name) = lower(:name) and lower(c.name) = lower(:name)
DQL DQL
@@ -64,7 +64,7 @@ class CandidateRepository extends ServiceEntityRepository
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 (sum(case when a.isRightAnswer = true then 1 else 0 end) + qc.corrections) as score
from App\Entity\Candidate c from Tvdt\Entity\Candidate c
join c.givenAnswers ga join c.givenAnswers ga
join ga.answer a join ga.answer a
join c.quizData qc join c.quizData qc

View File

@@ -2,11 +2,11 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\Elimination;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Tvdt\Entity\Elimination;
/** /**
* @extends ServiceEntityRepository<Elimination> * @extends ServiceEntityRepository<Elimination>

View File

@@ -2,11 +2,11 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\GivenAnswer;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Tvdt\Entity\GivenAnswer;
/** /**
* @extends ServiceEntityRepository<GivenAnswer> * @extends ServiceEntityRepository<GivenAnswer>

View File

@@ -2,12 +2,12 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\Candidate;
use App\Entity\Question;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\Question;
/** /**
* @extends ServiceEntityRepository<Question> * @extends ServiceEntityRepository<Question>
@@ -22,10 +22,10 @@ class QuestionRepository extends ServiceEntityRepository
public function findNextQuestionForCandidate(Candidate $candidate): ?Question public function findNextQuestionForCandidate(Candidate $candidate): ?Question
{ {
return $this->getEntityManager()->createQuery(<<<DQL return $this->getEntityManager()->createQuery(<<<DQL
select q from App\Entity\Question q select q from Tvdt\Entity\Question q
join q.quiz qz join q.quiz qz
where q.id not in ( where q.id not in (
select q1.id from App\Entity\GivenAnswer ga select q1.id from Tvdt\Entity\GivenAnswer ga
join ga.answer a join ga.answer a
join a.question q1 join a.question q1
where ga.candidate = :candidate where ga.candidate = :candidate

View File

@@ -2,13 +2,13 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\Candidate;
use App\Entity\Quiz;
use App\Entity\QuizCandidate;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\QuizCandidate;
/** /**
* @extends ServiceEntityRepository<QuizCandidate> * @extends ServiceEntityRepository<QuizCandidate>

View File

@@ -2,16 +2,16 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\Elimination;
use App\Entity\GivenAnswer;
use App\Entity\Quiz;
use App\Entity\QuizCandidate;
use App\Exception\ErrorClearingQuizException;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Tvdt\Entity\Elimination;
use Tvdt\Entity\GivenAnswer;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\QuizCandidate;
use Tvdt\Exception\ErrorClearingQuizException;
/** /**
* @extends ServiceEntityRepository<Quiz> * @extends ServiceEntityRepository<Quiz>

View File

@@ -2,12 +2,12 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\Season;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Tvdt\Entity\Season;
use Tvdt\Entity\User;
/** /**
* @extends ServiceEntityRepository<Season> * @extends ServiceEntityRepository<Season>
@@ -23,7 +23,7 @@ class SeasonRepository extends ServiceEntityRepository
public function getSeasonsForUser(User $user): array public function getSeasonsForUser(User $user): array
{ {
return $this->getEntityManager()->createQuery(<<<DQL return $this->getEntityManager()->createQuery(<<<DQL
select s from App\Entity\Season s where :user member of s.owners order by s.name select s from Tvdt\Entity\Season s where :user member of s.owners order by s.name
DQL DQL
)->setParameter('user', $user)->getResult(); )->setParameter('user', $user)->getResult();
} }

View File

@@ -2,11 +2,11 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\SeasonSettings;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Tvdt\Entity\SeasonSettings;
/** /**
* @extends ServiceEntityRepository<SeasonSettings> * @extends ServiceEntityRepository<SeasonSettings>

View File

@@ -2,13 +2,13 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Repository; namespace Tvdt\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface; use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Tvdt\Entity\User;
/** @extends ServiceEntityRepository<User> */ /** @extends ServiceEntityRepository<User> */
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface

View File

@@ -2,15 +2,15 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Security; namespace Tvdt\Security;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Mailer\MailerInterface;
use SymfonyCasts\Bundle\VerifyEmail\VerifyEmailHelperInterface; use SymfonyCasts\Bundle\VerifyEmail\VerifyEmailHelperInterface;
use Tvdt\Entity\User;
readonly class EmailVerifier readonly class EmailVerifier
{ {

View File

@@ -2,18 +2,18 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Security\Voter; namespace Tvdt\Security\Voter;
use App\Entity\Answer;
use App\Entity\Candidate;
use App\Entity\Elimination;
use App\Entity\Question;
use App\Entity\Quiz;
use App\Entity\Season;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Vote; use Symfony\Component\Security\Core\Authorization\Voter\Vote;
use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Tvdt\Entity\Answer;
use Tvdt\Entity\Candidate;
use Tvdt\Entity\Elimination;
use Tvdt\Entity\Question;
use Tvdt\Entity\Quiz;
use Tvdt\Entity\Season;
use Tvdt\Entity\User;
/** @extends Voter<string, Season> */ /** @extends Voter<string, Season> */
final class SeasonVoter extends Voter final class SeasonVoter extends Voter

View File

@@ -2,9 +2,9 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Service; namespace Tvdt\Service;
use App\Repository\CandidateRepository; use Tvdt\Repository\CandidateRepository;
/** /**
* @phpstan-import-type ResultList from CandidateRepository * @phpstan-import-type ResultList from CandidateRepository

View File

@@ -2,16 +2,16 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Service; namespace Tvdt\Service;
use App\Entity\Answer;
use App\Entity\Question;
use App\Entity\Quiz;
use App\Exception\SpreadsheetDataException;
use PhpOffice\PhpSpreadsheet\Reader; use PhpOffice\PhpSpreadsheet\Reader;
use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer; use PhpOffice\PhpSpreadsheet\Writer;
use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\File;
use Tvdt\Entity\Answer;
use Tvdt\Entity\Question;
use Tvdt\Entity\Quiz;
use Tvdt\Exception\SpreadsheetDataException;
class QuizSpreadsheetService class QuizSpreadsheetService
{ {

View File

@@ -121,6 +121,15 @@
"importmap.php" "importmap.php"
] ]
}, },
"symfony/brevo-mailer": {
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "7c1038ceb733175f610a913a885a7c8b552b703a"
}
},
"symfony/console": { "symfony/console": {
"version": "7.2", "version": "7.2",
"recipe": { "recipe": {

View File

@@ -7,7 +7,7 @@
<h2 class="py-2 pe-2"> <h2 class="py-2 pe-2">
{{ is_granted('ROLE_ADMIN') ? 'All Seasons'|trans : 'Your Seasons'|trans }} {{ is_granted('ROLE_ADMIN') ? 'All Seasons'|trans : 'Your Seasons'|trans }}
</h2> </h2>
<a class="link" href="{{ path('app_backoffice_season_add') }}"> <a class="link" href="{{ path('tvdt_backoffice_season_add') }}">
{{ 'Add'|trans }} {{ 'Add'|trans }}
</a> </a>
</div> </div>
@@ -39,11 +39,11 @@
{% endif %} {% endif %}
</td> </td>
<td> <td>
<a {% if season.activeQuiz %}href="{{ path('app_quiz_enter_name', {seasonCode: season.seasonCode}) }}" <a {% if season.activeQuiz %}href="{{ path('tvdt_quiz_enter_name', {seasonCode: season.seasonCode}) }}"
{% else %}class="disabled" {% endif %}>{{ season.seasonCode }}</a> {% else %}class="disabled" {% endif %}>{{ season.seasonCode }}</a>
</td> </td>
<td> <td>
<a href="{{ path('app_backoffice_season', {seasonCode: season.seasonCode}) }}">{{ 'Manage'|trans }}</a> <a href="{{ path('tvdt_backoffice_season', {seasonCode: season.seasonCode}) }}">{{ 'Manage'|trans }}</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@@ -5,7 +5,7 @@
{% block body %} {% block body %}
{% if app.user %} {% if app.user %}
<div class="mb-3"> <div class="mb-3">
You are logged in as {{ app.user.userIdentifier }}, <a href="{{ path('app_login_logout') }}">Logout</a> You are logged in as {{ app.user.userIdentifier }}, <a href="{{ path('tvdt_login_logout') }}">Logout</a>
</div> </div>
{% else %} {% else %}
<form method="post"> <form method="post">
@@ -34,7 +34,7 @@
<button class="btn btn-lg btn-primary" type="submit"> <button class="btn btn-lg btn-primary" type="submit">
{{ 'Sign in'|trans }} {{ 'Sign in'|trans }}
</button> </button>
<a href="{{ path('app_register') }}" <a href="{{ path('tvdt_register') }}"
class="btn btn-link">{{ 'Create an account'|trans }}</a> class="btn btn-link">{{ 'Create an account'|trans }}</a>
</form> </form>
{% endif %} {% endif %}

View File

@@ -1,6 +1,6 @@
<nav class="navbar navbar-expand-lg bg-body-tertiary"> <nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="{{ path('app_backoffice_index') }}">Tijd voor de test</a> <a class="navbar-brand" href="{{ path('tvdt_backoffice_index') }}">Tijd voor de test</a>
<button class="navbar-toggler" <button class="navbar-toggler"
type="button" type="button"
data-bs-toggle="collapse" data-bs-toggle="collapse"
@@ -14,18 +14,18 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> <ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link{% if 'app_backoffice_index' == app.current_route() %} active{% endif %}" <a class="nav-link{% if 'tvdt_backoffice_index' == app.current_route() %} active{% endif %}"
href="{{ path('app_backoffice_index') }}">{{ 'Seasons'|trans }}</a> href="{{ path('tvdt_backoffice_index') }}">{{ 'Seasons'|trans }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" <a class="nav-link"
href="{{ path('app_backoffice_template') }}">{{ 'Download Template'|trans }}</a> href="{{ path('tvdt_backoffice_template') }}">{{ 'Download Template'|trans }}</a>
</li> </li>
</ul> </ul>
<ul class="navbar-nav mb-auto me-2 me-lg-0"> <ul class="navbar-nav mb-auto me-2 me-lg-0">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" <a class="nav-link"
href="{{ path('app_login_logout') }}">{{ 'Logout'|trans }}</a> href="{{ path('tvdt_login_logout') }}">{{ 'Logout'|trans }}</a>
</li> </li>
</ul> </ul>
</div> </div>

View File

@@ -3,12 +3,12 @@
<div class="row"> <div class="row">
<nav aria-label="breadcrumb"> <nav aria-label="breadcrumb">
<ol class="breadcrumb"> <ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ path('app_backoffice_index') }}">Home</a></li> <li class="breadcrumb-item"><a href="{{ path('tvdt_backoffice_index') }}">Home</a></li>
<li class="breadcrumb-item"><a <li class="breadcrumb-item"><a
href="{{ path('app_backoffice_season', {seasonCode: elimination.quiz.season.seasonCode}) }}">{{ elimination.quiz.season.name }}</a> href="{{ path('tvdt_backoffice_season', {seasonCode: elimination.quiz.season.seasonCode}) }}">{{ elimination.quiz.season.name }}</a>
</li> </li>
<li class="breadcrumb-item"><a <li class="breadcrumb-item"><a
href="{{ path('app_backoffice_quiz', {seasonCode: elimination.quiz.season.seasonCode, quiz: elimination.quiz.id}) }}">{{ elimination.quiz.name }}</a> href="{{ path('tvdt_backoffice_quiz', {seasonCode: elimination.quiz.season.seasonCode, quiz: elimination.quiz.id}) }}">{{ elimination.quiz.name }}</a>
</li> </li>
<li class="breadcrumb-item active" aria-current="page">Prepare Elimination</li> <li class="breadcrumb-item active" aria-current="page">Prepare Elimination</li>
@@ -36,7 +36,7 @@
<button type="submit" class="btn btn-primary" name="start" value="0">{{ 'Save'|trans }}</button> <button type="submit" class="btn btn-primary" name="start" value="0">{{ 'Save'|trans }}</button>
<button type="submit" class="btn btn-success" name="start" <button type="submit" class="btn btn-success" name="start"
value="1">{{ 'Save and start elimination'|trans }}</button> value="1">{{ 'Save and start elimination'|trans }}</button>
<a href="{{ path('app_backoffice_quiz', {seasonCode: elimination.quiz.season.seasonCode, quiz: elimination.quiz.id}) }}" <a href="{{ path('tvdt_backoffice_quiz', {seasonCode: elimination.quiz.season.seasonCode, quiz: elimination.quiz.id}) }}"
class="btn btn-secondary">{{ 'Back'|trans }}</a> class="btn btn-secondary">{{ 'Back'|trans }}</a>
</div> </div>
</form> </form>

View File

@@ -6,10 +6,10 @@
<h2 class="py-2">{{ 'Quiz'|trans }}: {{ quiz.season.name }} - {{ quiz.name }}</h2> <h2 class="py-2">{{ 'Quiz'|trans }}: {{ quiz.season.name }} - {{ quiz.name }}</h2>
<div class="py-2 btn-group" data-controller="bo--quiz"> <div class="py-2 btn-group" data-controller="bo--quiz">
<a class="btn btn-primary {% if quiz is same as(season.activeQuiz) %}disabled{% endif %}" <a class="btn btn-primary {% if quiz is same as(season.activeQuiz) %}disabled{% endif %}"
href="{{ path('app_backoffice_enable', {seasonCode: season.seasonCode, quiz: quiz.id}) }}">{{ 'Make active'|trans }}</a> href="{{ path('tvdt_backoffice_enable', {seasonCode: season.seasonCode, quiz: quiz.id}) }}">{{ 'Make active'|trans }}</a>
{% if quiz is same as (season.activeQuiz) %} {% if quiz is same as (season.activeQuiz) %}
<a class="btn btn-secondary" <a class="btn btn-secondary"
href="{{ path('app_backoffice_enable', {seasonCode: season.seasonCode, quiz: 'null'}) }}">{{ 'Deactivate Quiz'|trans }}</a> href="{{ path('tvdt_backoffice_enable', {seasonCode: season.seasonCode, quiz: 'null'}) }}">{{ 'Deactivate Quiz'|trans }}</a>
{% endif %} {% endif %}
<button class="btn btn-danger" data-action="click->bo--quiz#clearQuiz"> <button class="btn btn-danger" data-action="click->bo--quiz#clearQuiz">
{{ 'Clear quiz...'|trans }} {{ 'Clear quiz...'|trans }}
@@ -62,7 +62,7 @@
<div class="btn-toolbar" role="toolbar"> <div class="btn-toolbar" role="toolbar">
<div class="btn-group btn-group-lg me-2"> <div class="btn-group btn-group-lg me-2">
{# <a class="btn btn-primary">{{ 'Start Elimination'|trans }}</a> #} {# <a class="btn btn-primary">{{ 'Start Elimination'|trans }}</a> #}
<a href="{{ path('app_prepare_elimination', {seasonCode: season.seasonCode, quiz: quiz.id}) }}" <a href="{{ path('tvdt_prepare_elimination', {seasonCode: season.seasonCode, quiz: quiz.id}) }}"
class="btn btn-secondary">{{ 'Prepare Custom Elimination'|trans }}</a> class="btn btn-secondary">{{ 'Prepare Custom Elimination'|trans }}</a>
{%~ if not quiz.eliminations.empty %} {%~ if not quiz.eliminations.empty %}
<button class="btn btn-secondary dropdown-toggle" <button class="btn btn-secondary dropdown-toggle"
@@ -70,7 +70,7 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{%~ for elimination in quiz.eliminations %} {%~ for elimination in quiz.eliminations %}
<li><a class="dropdown-item" <li><a class="dropdown-item"
href="{{ path('app_prepare_elimination_view', {elimination: elimination.id}) }}">{{ elimination.created|format_datetime() }}</a> href="{{ path('tvdt_prepare_elimination_view', {elimination: elimination.id}) }}">{{ elimination.created|format_datetime() }}</a>
</li> </li>
{%~ endfor %} {%~ endfor %}
</ul> </ul>
@@ -95,7 +95,7 @@
<td>{{ candidate.correct|default('0') }}</td> <td>{{ candidate.correct|default('0') }}</td>
<td> <td>
<form method="post" <form method="post"
action="{{ path('app_backoffice_modify_correction', {quiz: quiz.id, candidate: candidate.id}) }}"> action="{{ path('tvdt_backoffice_modify_correction', {quiz: quiz.id, candidate: candidate.id}) }}">
<div class="row"> <div class="row">
<div class="col-8"> <div class="col-8">
<input class="form-control form-control-sm" type="number" <input class="form-control form-control-sm" type="number"
@@ -135,7 +135,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ 'No'|trans }}</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ 'No'|trans }}</button>
<a href="{{ path('app_backoffice_quiz_clear', {quiz: quiz.id}) }}" <a href="{{ path('tvdt_backoffice_quiz_clear', {quiz: quiz.id}) }}"
class="btn btn-danger">{{ 'Yes'|trans }}</a> class="btn btn-danger">{{ 'Yes'|trans }}</a>
</div> </div>
</div> </div>
@@ -157,7 +157,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ 'No'|trans }}</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ 'No'|trans }}</button>
<a href="{{ path('app_backoffice_quiz_delete', {quiz: quiz.id}) }}" <a href="{{ path('tvdt_backoffice_quiz_delete', {quiz: quiz.id}) }}"
class="btn btn-danger">{{ 'Yes'|trans }}</a> class="btn btn-danger">{{ 'Yes'|trans }}</a>
</div> </div>
</div> </div>

View File

@@ -11,7 +11,7 @@
{{ form_row(registrationForm.plainPassword) }} {{ form_row(registrationForm.plainPassword) }}
<button type="submit" class="btn btn-primary">Register</button> <button type="submit" class="btn btn-primary">Register</button>
<a href="{{ path('app_login_login') }}" class="btn btn-link">{{ 'Already have an account? Log in'|trans }}</a> <a href="{{ path('tvdt_login_login') }}" class="btn btn-link">{{ 'Already have an account? Log in'|trans }}</a>
{{ form_end(registrationForm) }} {{ form_end(registrationForm) }}
{% endblock %} {% endblock %}

View File

@@ -7,12 +7,12 @@
<div class="d-flex flex-row align-items-center"> <div class="d-flex flex-row align-items-center">
<h4 class="py-2 pe-2">{{ 'Quizzes'|trans }}</h4> <h4 class="py-2 pe-2">{{ 'Quizzes'|trans }}</h4>
<a class="link" <a class="link"
href="{{ path('app_backoffice_quiz_add', {seasonCode: season.seasonCode}) }}">{{ 'Add'|trans }}</a> href="{{ path('tvdt_backoffice_quiz_add', {seasonCode: season.seasonCode}) }}">{{ 'Add'|trans }}</a>
</div> </div>
<div class="list-group"> <div class="list-group">
{% for quiz in season.quizzes %} {% for quiz in season.quizzes %}
<a class="list-group-item list-group-item-action{% if season.activeQuiz == quiz %} active{% endif %}" <a class="list-group-item list-group-item-action{% if season.activeQuiz == quiz %} active{% endif %}"
href="{{ path('app_backoffice_quiz', {seasonCode: season.seasonCode, quiz: quiz.id}) }}">{{ quiz.name }}</a> href="{{ path('tvdt_backoffice_quiz', {seasonCode: season.seasonCode, quiz: quiz.id}) }}">{{ quiz.name }}</a>
{% else %} {% else %}
No quizzes No quizzes
{% endfor %} {% endfor %}
@@ -22,7 +22,7 @@
<div class="d-flex flex-row align-items-center"> <div class="d-flex flex-row align-items-center">
<h4 class="py-2 pe-2">{{ 'Candidates'|trans }}</h4> <h4 class="py-2 pe-2">{{ 'Candidates'|trans }}</h4>
<a class="link" <a class="link"
href="{{ path('app_backoffice_add_candidates', {seasonCode: season.seasonCode}) }}">{{ 'Add Candidate'|trans }} href="{{ path('tvdt_backoffice_add_candidates', {seasonCode: season.seasonCode}) }}">{{ 'Add Candidate'|trans }}
</a> </a>
</div> </div>
<ul> <ul>

Some files were not shown because too many files have changed in this diff Show More