Compare commits

...

9 Commits

42
.env

@ -1,26 +1,32 @@
# This file defines all environment variables that the application needs.
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE.
# Use ".env.local" for local overrides during development.
# Use real environment variables when deploying to production.
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
# * .env contains default values for the environment variables needed by the app
# * .env.local uncommitted file with local overrides
# * .env.$APP_ENV committed environment-specific defaults
# * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=879a6adeceeccbdc835a19f7e3aad7e8
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
#TRUSTED_HOSTS='^localhost|example\.com$'
APP_SECRET=296bba2d9c7a4f6eee2c7611d66a8aec
#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
#TRUSTED_HOSTS='^(localhost|example\.com)$'
###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
# Configure your db driver and server_version in config/packages/doctrine.yaml
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data.db
# For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=utf8"
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7
###< doctrine/doctrine-bundle ###
###> symfony/swiftmailer-bundle ###
# For Gmail as a transport, use: "gmail://username:password@localhost"
# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
# Delivery is disabled by default via "null://localhost"
MAILER_URL=null://localhost
###< symfony/swiftmailer-bundle ###
###> symfony/mailer ###
# MAILER_DSN=smtp://localhost
###< symfony/mailer ###

@ -1,24 +0,0 @@
# This file is a "template" of which env vars need to be defined for your application
# Copy this file to .env file for development, create environment variables when deploying to production
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=9d74944d92d8155f1c870695def94464
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
#TRUSTED_HOSTS=localhost,example.com
###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
# Configure your db driver and server_version in config/packages/doctrine.yaml
DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
###< doctrine/doctrine-bundle ###
###> symfony/swiftmailer-bundle ###
# For Gmail as a transport, use: "gmail://username:password@localhost"
# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
# Delivery is disabled by default via "null://localhost"
MAILER_URL=null://localhost
###< symfony/swiftmailer-bundle ###

@ -1,4 +1,6 @@
# define your env variables for the test env here
KERNEL_CLASS='App\Kernel'
APP_SECRET='s$cretf0rt3st'
APP_SECRET='$ecretf0rt3st'
SYMFONY_DEPRECATIONS_HELPER=999999
PANTHER_APP_ENV=panther
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data_test.db

12
.gitignore vendored

@ -1,7 +1,8 @@
###> symfony/framework-bundle ###
/.env.local
/.env.local.php
/.env.*.local
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
@ -9,9 +10,12 @@
###> symfony/phpunit-bridge ###
.phpunit
.phpunit.result.cache
/phpunit.xml
###< symfony/phpunit-bridge ###
###> symfony/web-server-bundle ###
/.web-server-pid
###< symfony/web-server-bundle ###
###> Eclipse ###
.project
.buildpath
.settings
###< Eclipse ###

21
Jenkinsfile vendored

@ -0,0 +1,21 @@
pipeline {
agent any
stages {
stage('Build') {
agent any
steps {
sh 'composer install'
}
}
stage('Test') {
steps {
sh 'php ./bin/phpunit --coverage-clover=\'reports/coverage/coverage.xml\' --coverage-html=\'reports/coverage\''
}
}
stage('Coverage') {
steps {
step([$class: 'CloverPublisher', cloverReportDir: '/reports/coverage', cloverReportFileName: 'coverage.xml'])
}
}
}
}

@ -4,28 +4,31 @@
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\ErrorHandler\Debug;
if (!in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
}
set_time_limit(0);
require dirname(__DIR__).'/vendor/autoload.php';
if (!class_exists(Application::class)) {
throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
if (!class_exists(Application::class) || !class_exists(Dotenv::class)) {
throw new LogicException('You need to add "symfony/framework-bundle" and "symfony/dotenv" as Composer dependencies.');
}
$input = new ArgvInput();
if (null !== $_ENV['APP_ENV'] = $input->getParameterOption(['--env', '-e'], null, true)) {
putenv('APP_ENV='.$_ENV['APP_ENV']);
// force loading .env files when --env is defined
$_SERVER['APP_ENV'] = null;
if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) {
putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
}
if ($input->hasParameterOption('--no-debug', true)) {
putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
}
require dirname(__DIR__).'/src/.bootstrap.php';
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
if ($_SERVER['APP_DEBUG']) {
umask(0000);
@ -35,6 +38,6 @@ if ($_SERVER['APP_DEBUG']) {
}
}
$kernel = new Kernel($_SERVER['APP_ENV'], $_SERVER['APP_DEBUG']);
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
$application = new Application($kernel);
$application->run($input);

@ -1,19 +1,13 @@
#!/usr/bin/env php
<?php
if (!file_exists(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) {
echo "Unable to find the `simple-phpunit` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
if (!file_exists(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
exit(1);
}
if (false === getenv('SYMFONY_PHPUNIT_VERSION')) {
putenv('SYMFONY_PHPUNIT_VERSION=6.5');
}
if (false === getenv('SYMFONY_PHPUNIT_REMOVE')) {
putenv('SYMFONY_PHPUNIT_REMOVE=');
}
if (false === getenv('SYMFONY_PHPUNIT_DIR')) {
putenv('SYMFONY_PHPUNIT_DIR='.__DIR__.'/.phpunit');
}
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit';
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';

@ -2,39 +2,57 @@
"type": "project",
"license": "proprietary",
"require": {
"php": "^7.1.3",
"php": ">=7.2.5",
"ext-ctype": "*",
"ext-iconv": "*",
"friendsofsymfony/rest-bundle": "^2.4",
"sensio/framework-extra-bundle": "^5.1",
"symfony/asset": "4.1.*",
"symfony/console": "4.1.*",
"symfony/expression-language": "4.1.*",
"symfony/flex": "^1.1",
"symfony/form": "4.1.*",
"symfony/framework-bundle": "4.1.*",
"composer/package-versions-deprecated": "^1.11",
"doctrine/annotations": "^1.0",
"doctrine/doctrine-bundle": "^2.1",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7",
"friendsofsymfony/rest-bundle": "^3.0",
"phpdocumentor/reflection-docblock": "^5.2",
"sensio/framework-extra-bundle": "^5.3",
"symfony/asset": "5.3.*",
"symfony/console": "5.3.*",
"symfony/dotenv": "5.3.*",
"symfony/expression-language": "5.3.*",
"symfony/flex": "^1.3.1",
"symfony/form": "5.3.*",
"symfony/framework-bundle": "5.3.*",
"symfony/http-client": "5.3.*",
"symfony/intl": "5.3.*",
"symfony/mailer": "5.3.*",
"symfony/mime": "5.3.*",
"symfony/monolog-bundle": "^3.1",
"symfony/orm-pack": "*",
"symfony/process": "4.1.*",
"symfony/security-bundle": "4.1.*",
"symfony/serializer-pack": "*",
"symfony/swiftmailer-bundle": "^3.1",
"symfony/translation": "4.1.*",
"symfony/twig-bundle": "4.1.*",
"symfony/validator": "4.1.*",
"symfony/web-link": "4.1.*",
"symfony/yaml": "4.1.*"
"symfony/notifier": "5.3.*",
"symfony/process": "5.3.*",
"symfony/property-access": "5.3.*",
"symfony/property-info": "5.3.*",
"symfony/security-bundle": "5.3.*",
"symfony/serializer": "5.3.*",
"symfony/string": "5.3.*",
"symfony/translation": "5.3.*",
"symfony/twig-bundle": "^5.3",
"symfony/validator": "5.3.*",
"symfony/web-link": "5.3.*",
"symfony/yaml": "5.3.*",
"twig/extra-bundle": "^2.12|^3.0",
"twig/twig": "^2.12|^3.0"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0",
"symfony/debug-pack": "*",
"symfony/dotenv": "4.1.*",
"doctrine/doctrine-fixtures-bundle": "^3.3",
"symfony/browser-kit": "^5.3",
"symfony/css-selector": "^5.3",
"symfony/debug-bundle": "^5.3",
"symfony/maker-bundle": "^1.0",
"symfony/profiler-pack": "*",
"symfony/test-pack": "*",
"symfony/web-server-bundle": "4.1.*"
"symfony/phpunit-bridge": "^5.3",
"symfony/stopwatch": "^5.3",
"symfony/var-dumper": "^5.3",
"symfony/web-profiler-bundle": "^5.3"
},
"config": {
"optimize-autoloader": true,
"preferred-install": {
"*": "dist"
},
@ -54,6 +72,7 @@
"paragonie/random_compat": "2.*",
"symfony/polyfill-ctype": "*",
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php72": "*",
"symfony/polyfill-php71": "*",
"symfony/polyfill-php70": "*",
"symfony/polyfill-php56": "*"
@ -76,7 +95,7 @@
"extra": {
"symfony": {
"allow-contrib": false,
"require": "4.1.*"
"require": "5.3.*"
}
}
}

8007
composer.lock generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,23 @@
<?php
use Symfony\Component\Dotenv\Dotenv;
require dirname(__DIR__).'/vendor/autoload.php';
if (!class_exists(Dotenv::class)) {
throw new LogicException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
}
// Load cached env vars if the .env.local.php file exists
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) {
(new Dotenv(false))->populate($env);
} else {
// load all the .env files
(new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
}
$_SERVER += $_ENV;
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';

@ -2,18 +2,16 @@
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
FOS\RestBundle\FOSRestBundle::class => ['all' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
];

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping ../../vendor/doctrine/orm/doctrine-mapping.xsd ">
<entity name="App\Entity\Event" repository-class="App\Repository\EventRepository">
<id name="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="type" type="integer" nullable="false" />
<field name="version" type="integer" nullable="false" />
<one-to-many field="battles" mapped-by="event" target-entity="EventBattle">
<cascade>
<cascade-persist />
<cascade-merge />
</cascade>
</one-to-many>
<one-to-many field="teams" mapped-by="event" target-entity="EventTeam">
<cascade>
<cascade-persist />
<cascade-merge />
</cascade>
</one-to-many>
</entity>
</doctrine-mapping>

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping
xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping ../../vendor/doctrine/orm/doctrine-mapping.xsd ">
<entity name="App\Entity\EventBattle" repository-class="App\Repository\EventBattleRepository">
<id name="event" association-key="true" />
<id name="event_battle_id" type="integer" />
<field name="value" type="json" />
<many-to-one field="event" target-entity="Event" inversed-by="battles">
<join-column on-delete="CASCADE" />
</many-to-one>
<many-to-many field="heroes" target-entity="EventHero">
<join-table name="event_battle_hero">
<join-columns>
<join-column name="event_id" referenced-column-name="event_id" on-delete="CASCADE"/>
<join-column name="event_battle_id" referenced-column-name="event_battle_id" on-delete="CASCADE"/>
</join-columns>
<inverse-join-columns>
<join-column name="event_id" referenced-column-name="event_id" on-delete="CASCADE" />
<join-column name="event_hero_id" referenced-column-name="event_hero_id" on-delete="CASCADE" />
</inverse-join-columns>
</join-table>
</many-to-many>
<many-to-one field="winningTeam" target-entity="EventTeam">
<join-columns>
<join-column name="event_id" referenced-column-name="event_id" on-delete="CASCADE" />
<join-column name="winning_team_id" referenced-column-name="event_team_id" on-delete="CASCADE" />
</join-columns>
</many-to-one>
</entity>
</doctrine-mapping>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping ../../vendor/doctrine/orm/doctrine-mapping.xsd ">
<entity name="App\Entity\EventHero" repository-class="App\Repository\EventHeroRepository">
<id name="event" association-key="true" />
<id name="event_hero_id" type="integer" />
<embedded name="skills" class="Skillz" />
<field name="name" type="string" length="32" unique="true" />
<many-to-one field="user" target-entity="User">
<join-column on-delete="SET NULL" />
</many-to-one>
<many-to-one field="hero" target-entity="Hero">
<join-column on-delete="SET NULL" />
</many-to-one>
<many-to-one field="event" target-entity="Event">
<join-column on-delete="CASCADE" />
</many-to-one>
<many-to-one field="team" target-entity="EventTeam" inversed-by="heroes">
<join-columns>
<join-column name="event_id" referenced-column-name="event_id" on-delete="CASCADE "/>
<join-column name="event_team_id" referenced-column-name="event_team_id" on-delete="CASCADE" />
</join-columns>
</many-to-one>
</entity>
</doctrine-mapping>

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping ../../vendor/doctrine/orm/doctrine-mapping.xsd ">
<entity name="App\Entity\EventTeam" repository-class="App\Repository\EventTeamRepository">
<id name="event" association-key="true" />
<id name="event_team_id" type="integer" />
<field name="name" type="string" length="32" unique="true" />
<!-- TODO: many-to-one referencing clan (nullable) -->
<one-to-many field="heroes" mapped-by="team" target-entity="EventHero">
<cascade>
<cascade-persist />
<cascade-merge />
</cascade>
</one-to-many>
<many-to-one field="event" target-entity="Event" inversed-by="teams">
<join-column on-delete="CASCADE" />
</many-to-one>
</entity>
</doctrine-mapping>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping ../../vendor/doctrine/orm/doctrine-mapping.xsd ">
<entity name="App\Entity\Hero" repository-class="App\Repository\HeroRepository">
<id name="id" type="integer">
<generator strategy="AUTO" />
</id>
<embedded name="skills" class="Skillz" />
<field name="name" type="string" length="32" unique="true" />
<many-to-one field="user" target-entity="User">
<join-column on-delete="CASCADE" />
</many-to-one>
</entity>
</doctrine-mapping>

@ -1,21 +0,0 @@
App\Entity\Hero:
type: entity
repositoryClass: App\Repository\HeroRepository
table: hero
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
name:
type: string
length: 32
unique: true
manyToOne:
user:
targetEntity: User
inversedBy: heroes
joinColumn:
onDelete: CASCADE
nullable: false

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping ../../vendor/doctrine/orm/doctrine-mapping.xsd ">
<embeddable name="App\Entity\Skillz">
<!-- basically the HP -->
<field name="constitution" type="integer" />
<!-- former MP! Some moves will require KI to function -->
<field name="ki" type="integer" />
<!-- damage dealer / block skill -->
<field name="strength" type="integer" />
<!-- evade / hit chance skill -->
<field name="agility" type="integer" />
<!-- if low => one is vulnerable for critical hits or slow attack speed / low damage -->
<field name="stamina" type="integer" />
</embeddable>
</doctrine-mapping>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping ../../vendor/doctrine/orm/doctrine-mapping.xsd ">
<entity name="App\Entity\User" repository-class="App\Repository\UserRepository">
<id name="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="username" type="string" length="32" unique="true" />
<field name="password" />
<field name="apiToken" unique="true" nullable="true" />
<field name="roles" type="json" />
<one-to-many field="heroes" mapped-by="user" target-entity="Hero">
<cascade>
<cascade-persist />
<cascade-merge />
</cascade>
</one-to-many>
</entity>
</doctrine-mapping>

@ -1,26 +0,0 @@
App\Entity\User:
type: entity
repositoryClass: App\Repository\UserRepository
table: user
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
username:
type: string
length: 32
unique: true
password: # the hashed password
type: string
apiToken:
type: string
unique: true
nullable: true
roles:
type: json
oneToMany:
heroes:
targetEntity: Hero
mappedBy: user
cascade: ["persist", "merge"]

@ -0,0 +1,19 @@
framework:
cache:
# Unique name of your app: used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The "app" cache stores to the filesystem by default.
# The data in this cache should persist between deploys.
# Other options include:
# Redis
#app: cache.adapter.redis
#default_redis_provider: redis://localhost
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu
# Namespaced pools use the above "app" backend by default
#pools:
#my.dedicated.cache: null

@ -1,4 +0,0 @@
# See https://symfony.com/doc/current/email/dev_environment.html
swiftmailer:
# send all emails to a specific address
#delivery_addresses: ['me@example.com']

@ -1,25 +1,18 @@
parameters:
# Adds a fallback DATABASE_URL if the env var is not set.
# This allows you to run cache:warmup even if your
# environment variables are not available yet.
# You should not need to change this value.
env(DATABASE_URL): ''
doctrine:
dbal:
# configure these for your database server
driver: 'pdo_sqlite'
charset: utf8
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '5.7'
orm:
auto_generate_proxy_classes: true
naming_strategy: doctrine.orm.naming_strategy.underscore
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
is_bundle: false
type: yml
type: xml
dir: '%kernel.project_dir%/config/orm'
prefix: 'App\Entity'
alias: App

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

@ -9,7 +9,6 @@ fos_rest:
view_response_listener: force
exception:
enabled: true
exception_controller: 'fos_rest.exception.controller:showAction'
codes:
'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
@ -21,4 +20,3 @@ fos_rest:
- { path: ^/, prefer_extension: true, fallback_format: html, priorities: [ html ] }
serializer:
groups: ['Default']

@ -1,34 +1,17 @@
# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
secret: '%env(APP_SECRET)%'
#default_locale: en
#csrf_protection: true
#http_method_override: true
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: ~
handler_id: null
cookie_secure: auto
cookie_samesite: lax
#esi: true
#fragments: true
php_errors:
log: true
cache:
# Put the unique name of your app here: the prefix seed
# is used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The app cache caches to the filesystem by default.
# Other options include:
# Redis
#app: cache.adapter.redis
#default_redis_provider: redis://localhost
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu
serializer: { enable_annotations: true }
templating:
engines: ['twig']

@ -0,0 +1,3 @@
framework:
mailer:
dsn: '%env(MAILER_DSN)%'

@ -0,0 +1,16 @@
framework:
notifier:
#chatter_transports:
# slack: '%env(SLACK_DSN)%'
# telegram: '%env(TELEGRAM_DSN)%'
#texter_transports:
# twilio: '%env(TWILIO_DSN)%'
# nexmo: '%env(NEXMO_DSN)%'
channel_policy:
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
urgent: ['email']
high: ['email']
medium: ['email']
low: ['email']
admin_recipients:
- { email: admin@example.com }

@ -0,0 +1,8 @@
# As of Symfony 5.1, deprecations are logged in the dedicated "deprecation" channel when it exists
#monolog:
# channels: [deprecation]
# handlers:
# deprecation:
# type: stream
# channels: [deprecation]
# path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log"

@ -2,26 +2,14 @@ doctrine:
orm:
auto_generate_proxy_classes: false
metadata_cache_driver:
type: service
id: doctrine.system_cache_provider
type: pool
pool: doctrine.system_cache_pool
query_cache_driver:
type: service
id: doctrine.system_cache_provider
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: service
id: doctrine.result_cache_provider
services:
doctrine.result_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.result_cache_pool'
doctrine.system_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.system_cache_pool'
type: pool
pool: doctrine.result_cache_pool
framework:
cache:

@ -4,9 +4,8 @@ monolog:
type: fingers_crossed
action_level: error
handler: nested
excluded_404s:
# regex: exclude all 404 errors from the logs
- ^/
excluded_http_codes: [404, 405]
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
@ -15,11 +14,3 @@ monolog:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine"]
deprecation:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log"
deprecation_filter:
type: filter
handler: deprecation
max_level: info
channels: ["php"]

@ -0,0 +1,3 @@
framework:
router:
strict_requirements: null

@ -1,3 +1,7 @@
framework:
router:
strict_requirements: ~
utf8: true
# 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
#default_uri: http://localhost

@ -5,7 +5,7 @@ security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
in_memory: { memory: ~ }
users_in_memory: { memory: null }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
@ -16,16 +16,29 @@ security:
authenticators:
- App\Security\TokenAuthenticator
stateless: true
anonymous: true
lazy: true
logout: ~
std:
pattern: ^/main/
guard:
authenticators:
- App\Security\UrlAuthenticator
stateless: true
anonymous: true
lazy: true
logout: ~
main:
stateless: true
anonymous: true
lazy: true
provider: users_in_memory
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# http_basic: true
# https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
# form_login: true
# https://symfony.com/doc/current/security/form_login_setup.html
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used

@ -1,3 +0,0 @@
swiftmailer:
url: '%env(MAILER_URL)%'
spool: { type: 'memory' }

@ -1,7 +1,12 @@
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
channels: ["!event"]
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]

@ -1,2 +0,0 @@
swiftmailer:
disable_delivery: true

@ -0,0 +1,2 @@
twig:
strict_variables: true

@ -0,0 +1,3 @@
framework:
validation:
not_compromised_password: false

@ -1,6 +1,6 @@
framework:
default_locale: '%locale%'
default_locale: en
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:
- '%locale%'
- en

@ -1,5 +1,2 @@
twig:
default_path: '%kernel.project_dir%/templates'
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
exception_controller: 'FOS\RestBundle\Controller\ExceptionController::showAction'

@ -1,3 +1,8 @@
framework:
validation:
email_validation_mode: html5
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping:
# App\Entity\: []

@ -0,0 +1,5 @@
<?php
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
}

@ -1,13 +1,3 @@
#index:
# path: /
# controller: App\Controller\DefaultController::index
user:
prefix: /api
type: rest
resource: App\Controller\UserController
hero:
prefix: /api
type: rest
resource: App\Controller\HeroController

@ -1,3 +1,13 @@
api_controllers:
prefix: api/
resource: ../../src/Controller/Api
type: annotation
controllers:
resource: ../../src/Controller/
prefix: main/{slug}/
resource: ../../src/Controller/Std
type: annotation
kernel:
resource: ../../src/Kernel.php
type: annotation

@ -0,0 +1,3 @@
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error

@ -1,3 +0,0 @@
_errors:
resource: '@TwigBundle/Resources/config/routing/errors.xml'
prefix: /_error

@ -0,0 +1,12 @@
App\Entity\Event:
attributes:
id:
groups: ['Default']
type:
groups: ['event_list', 'event_show']
version:
groups: ['event_list', 'event_show']
battles:
groups: ['event_show']
teams:
groups: ['event_show']

@ -0,0 +1,10 @@
App\Entity\EventBattle:
attributes:
eid:
groups: ['Default']
heroes:
groups: ['event_battle_list', 'event_battle_show']
winningTeam:
groups: ['event_battle_list']
value:
groups: ['event_battle_show']

@ -0,0 +1,14 @@
App\Entity\EventHero:
attributes:
eid:
groups: ['Default']
name:
groups: ['event_hero_list']
skills:
groups: ['event_hero_show']
user:
groups: ['event_hero_show']
hero:
groups: ['event_hero_show']
team:
groups: ['event_hero_show']

@ -0,0 +1,8 @@
App\Entity\EventTeam:
attributes:
eid:
groups: ['Default']
name:
groups: ['event_team_list', 'event_team_show']
heroes:
groups: ['event_team_list', 'event_team_show']

@ -4,5 +4,6 @@ App\Entity\Hero:
groups: ['Default']
name:
groups: ['Default']
heros:
groups: ['UserWithHeroes']
skills:
groups: ['hero_show']

@ -0,0 +1,12 @@
App\Entity\Skillz:
attributes:
constitution:
groups: ['Default']
ki:
groups: ['Default']
strength:
groups: ['Default']
agility:
groups: ['Default']
stamina:
groups: ['Default']

@ -4,27 +4,27 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: 'en'
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
resource: '../src/Controller/'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed

@ -1,17 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.5/phpunit.xsd"
xsi:noNamespaceSchemaLocation="bin/.phpunit/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="src/.bootstrap.php"
bootstrap="tests/bootstrap.php"
>
<php>
<ini name="error_reporting" value="-1" />
<env name="APP_ENV" value="test" />
<env name="SHELL_VERBOSITY" value="-1" />
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak_vendors" />
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
<server name="SYMFONY_PHPUNIT_VERSION" value="7.5" />
</php>
<testsuites>
@ -21,8 +22,8 @@
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>

@ -1,10 +1,13 @@
<?php
use App\Kernel;
use Symfony\Component\Debug\Debug;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\HttpFoundation\Request;
require dirname(__DIR__).'/src/.bootstrap.php';
require dirname(__DIR__).'/vendor/autoload.php';
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
if ($_SERVER['APP_DEBUG']) {
umask(0000);
@ -12,15 +15,15 @@ if ($_SERVER['APP_DEBUG']) {
Debug::enable();
}
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) {
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
}
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? $_ENV['TRUSTED_HOSTS'] ?? false) {
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
Request::setTrustedHosts([$trustedHosts]);
}
$kernel = new Kernel($_SERVER['APP_ENV'], $_SERVER['APP_DEBUG']);
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();

@ -0,0 +1,50 @@
<?php
namespace App\Controller\Api;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use App\Repository\EventRepository;
use App\Entity\Event;
use App\Repository\EventBattleRepository;
use App\Entity\EventBattle;
/**
*
* @Rest\Route("event/{eventId}/battle")
*/
class EventBattleController extends AbstractFOSRestController
{
protected EventBattleRepository $repository;
public function __construct(EventBattleRepository $repository)
{
$this->repository = $repository;
}
/**
*
* @Rest\Route("s")
* @Rest\View(serializerGroups={"Default", "event_battle_list"})
*/
public function cgetAction(int $eventId): array
{
return $this->repository->findBy([
'event' => $eventId
]);
}
/**
*
* @Rest\Route("/{eid}"))
* @Rest\View(serializerGroups={"Default", "event_battle_show"})
*/
public function getAction(int $eventId, int $eid): ?EventBattle
{
return $this->repository->findOneBy([
'event' => $eventId,
'eid' => $eid
]);
}
}

@ -0,0 +1,43 @@
<?php
namespace App\Controller\Api;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use App\Repository\EventRepository;
use App\Entity\Event;
/**
*
* @Rest\Route("event")
*/
class EventController extends AbstractFOSRestController
{
protected EventRepository $eventRepository;
public function __construct(EventRepository $eventRepository)
{
$this->eventRepository = $eventRepository;
}
/**
*
* @Rest\Route("s")
* @Rest\View(serializerGroups={"Default", "event_list"})
*/
public function cgetAction(): array
{
return $this->eventRepository->findAll();
}
/**
*
* @Rest\Route("/{id}"))
* @Rest\View(serializerGroups={"Default", "event_show"})
*/
public function getAction(int $id): ?Event
{
return $this->eventRepository->find($id);
}
}

@ -0,0 +1,50 @@
<?php
namespace App\Controller\Api;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use App\Repository\EventRepository;
use App\Entity\Event;
use App\Repository\EventHeroRepository;
use App\Entity\EventHero;
/**
*
* @Rest\Route("event/{eventId}/hero")
*/
class EventHeroController extends AbstractFOSRestController
{
protected EventHeroRepository $repository;
public function __construct(EventHeroRepository $repository)
{
$this->repository = $repository;
}
/**
*
* @Rest\Route("s")
* @Rest\View(serializerGroups={"Default", "event_hero_list"})
*/
public function cgetAction(int $eventId): array
{
return $this->repository->findBy([
'event' => $eventId
]);
}
/**
*
* @Rest\Route("/{eid}"))
* @Rest\View(serializerGroups={"Default", "event_hero_show"})
*/
public function getAction(int $eventId, int $eid): ?EventHero
{
return $this->repository->findOneBy([
'event' => $eventId,
'eid' => $eid
]);
}
}

@ -0,0 +1,50 @@
<?php
namespace App\Controller\Api;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use App\Repository\EventRepository;
use App\Entity\Event;
use App\Repository\EventTeamRepository;
use App\Entity\EventTeam;
/**
*
* @Rest\Route("event/{eventId}/team")
*/
class EventTeamController extends AbstractFOSRestController
{
protected EventTeamRepository $repository;
public function __construct(EventTeamRepository $repository)
{
$this->repository = $repository;
}
/**
*
* @Rest\Route("s")
* @Rest\View(serializerGroups={"Default", "event_team_list"})
*/
public function cgetAction(int $eventId): array
{
return $this->repository->findBy([
'event' => $eventId
]);
}
/**
*
* @Rest\Route("/{eid}"))
* @Rest\View(serializerGroups={"Default", "event_team_show"})
*/
public function getAction(int $eventId, int $eid): ?EventTeam
{
return $this->repository->findOneBy([
'event' => $eventId,
'eid' => $eid
]);
}
}

@ -0,0 +1,42 @@
<?php
namespace App\Controller\Api;
use App\Repository\HeroRepository;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use App\Entity\Hero;
/**
*
* @Rest\Route("hero")
*/
class HeroController extends AbstractFOSRestController
{
protected HeroRepository $heroRepository;
public function __construct(HeroRepository $heroRepository)
{
$this->heroRepository = $heroRepository;
}
/**
*
* @Rest\Route("es")
* @Rest\View()
*/
public function cgetAction(): array
{
return $this->heroRepository->findAll();
}
/**
*
* @Rest\Route("/{id}"))
* @Rest\View()
*/
public function getAction(int $id): ?Hero
{
return $this->heroRepository->find($id);
}
}

@ -0,0 +1,42 @@
<?php
namespace App\Controller\Api;
use App\Repository\UserRepository;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use App\Entity\User;
/**
*
* @Rest\Route("api/user")
*/
class UserController extends AbstractFOSRestController
{
protected UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
/**
*
* @Rest\Route("s")
* @Rest\View()
*/
public function cgetAction(): array
{
return $this->userRepository->findAll();
}
/**
*
* @Rest\Route("/{id}"))
* @Rest\View()
*/
public function getAction(int $id): ?User
{
return $this->userRepository->find($id);
}
}

@ -1,30 +0,0 @@
<?php
namespace App\Controller;
use App\Repository\HeroRepository;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\Response;
/**
* @Rest\RouteResource("Hero")
*/
class HeroController extends FOSRestController
{
protected $heroRepository;
public function __construct(HeroRepository $heroRepository)
{
$this->heroRepository = $heroRepository;
}
/**
* @Rest\View()
*/
public function cgetAction()
{
$heroes = $this->heroRepository->findAll();
return $this->view($heroes, Response::HTTP_OK);
}
}

@ -0,0 +1,19 @@
<?php
namespace App\Controller\Std;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class LandingController extends AbstractController
{
/**
* @Route("/", name="landing")
*/
public function index()
{
return $this->render('landing/index.html.twig', [
'controller_name' => 'LandingController',
]);
}
}

@ -1,31 +0,0 @@
<?php
namespace App\Controller;
use App\Repository\UserRepository;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\Response;
/**
* @Rest\RouteResource("User")
*/
class UserController extends FOSRestController
{
protected $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* @Rest\View()
*/
public function cgetAction()
{
$users = $this->userRepository->findAll();
return $this->view($users, Response::HTTP_OK);
}
}

@ -0,0 +1,36 @@
<?php
namespace App\DataFixtures;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use App\Entity\EventBattle;
class EventBattleFixtures extends Fixture implements DependentFixtureInterface
{
public function load(ObjectManager $manager)
{
$event1 = $this->getReference(EventFixtures::REF_1);
$eventTeam1 = $this->getReference(EventFixtures::REF_EVENT1_TEAM1);
$eventHero1 = $this->getReference(EventFixtures::REF_EVENT1_CHAR1);
$eventHero2 = $this->getReference(EventFixtures::REF_EVENT1_CHAR2);
$eventBattle = new EventBattle($event1, 1);
$eventBattle->addHero($eventHero1);
$eventBattle->addHero($eventHero2);
$eventBattle->setWinningTeam($eventTeam1);
$manager->persist($eventBattle);
$manager->flush();
}
public function getDependencies()
{
return array(
EventFixtures::class
);
}
}

@ -0,0 +1,66 @@
<?php
namespace App\DataFixtures;
use App\Entity\Event;
use App\Entity\EventTeam;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use App\Entity\EventHero;
class EventFixtures extends Fixture implements DependentFixtureInterface
{
public const REF_1 = 'event-1-reference';
public const REF_2 = 'event-2-reference';
public const REF_EVENT1_CHAR1 = 'event-1-char-1-reference';
public const REF_EVENT1_TEAM1 = 'event-1-team-1-reference';
public const REF_EVENT1_CHAR2 = 'event-1-char-2-reference';
public const REF_EVENT1_TEAM2 = 'event-1-team-2-reference';
public function load(ObjectManager $manager)
{
$heroUser1 = $this->getReference(UserFixtures::ADMIN_USER_REFERENCE)->getHeroes()[0];
$heroUser2 = $this->getReference(UserFixtures::DUDE_USER_REFERENCE)->getHeroes()[0];
$event1 = new Event(Event::FREE_BATTLE);
$manager->persist($event1);
$event2 = new Event(Event::TOURNAMENT);
$manager->persist($event2);
$eventTeam1 = new EventTeam($event1, 1, "A Team");
$eventTeam2 = new EventTeam($event1, 2, "B Team");
$manager->persist($eventTeam1);
$manager->persist($eventTeam2);
$eventHero1 = new EventHero($event1, $heroUser1, $eventTeam1);
$eventHero2 = new EventHero($event1, $heroUser2, $eventTeam2);
$manager->persist($eventHero1);
$manager->persist($eventHero2);
$manager->flush();
$this->addReference(self::REF_1, $event1);
$this->addReference(self::REF_2, $event2);
$this->addReference(self::REF_EVENT1_CHAR1, $eventHero1);
$this->addReference(self::REF_EVENT1_CHAR2, $eventHero2);
$this->addReference(self::REF_EVENT1_TEAM1, $eventTeam1);
$this->addReference(self::REF_EVENT1_TEAM2, $eventTeam2);
}
public function getDependencies()
{
return array(
UserFixtures::class,
HeroFixtures::class
);
}
}

@ -1,29 +1,34 @@
<?php
namespace App\DataFixtures;
use App\Entity\Hero;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
class HeroFixtures extends Fixture implements DependentFixtureInterface
{
public function load(ObjectManager $manager)
{
$hero = new Hero();
$hero->setName('ruffy');
$hero->setUser($this->getReference(UserFixtures::ADMIN_USER_REFERENCE));
$manager->persist($hero);
$hero = new Hero();
$hero->setName('goku');
$hero->setUser($this->getReference(UserFixtures::DUDE_USER_REFERENCE));
$manager->persist($hero);
$manager->flush();
}
public function getDependencies()
{
return array(
UserFixtures::class,
UserFixtures::class
);
}
}

@ -3,19 +3,17 @@ namespace App\DataFixtures;
use App\Entity\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserFixtures extends Fixture
{
public const ADMIN_USER_REFERENCE = 'admin-user';
public const ADMIN_USER_TOKEN = 'ItsHammerTime!';
public const DUDE_USER_REFERENCE = 'dummy-user';
public const DUDE_USER_TOKEN = 'ItsDuderzeit!';
private $passwordEncoder;
private UserPasswordEncoderInterface $passwordEncoder;
public function __construct(UserPasswordEncoderInterface $passwordEncoder)
{
@ -27,13 +25,13 @@ class UserFixtures extends Fixture
$userAdmin = new User();
$userAdmin->setUsername('admin');
$this->setPassword($userAdmin, '123456789');
$userAdmin->setApiToken(self::ADMIN_USER_TOKEN);
$userAdmin->setApiToken(self::ADMIN_USER_REFERENCE);
$manager->persist($userAdmin);
$userDude = new User();
$userDude->setUsername('dude');
$this->setPassword($userDude, '1234');
$userDude->setApiToken(self::DUDE_USER_TOKEN);
$userDude->setApiToken(self::DUDE_USER_REFERENCE);
$manager->persist($userDude);
$manager->flush();
@ -46,4 +44,5 @@ class UserFixtures extends Fixture
{
$user->setPassword($this->passwordEncoder->encodePassword($user, $plainPassword));
}
}

@ -0,0 +1,131 @@
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
class Event
{
const QUEST = 1;
const TOURNAMENT = 2;
const FREE_BATTLE = 3;
const LEAGUE_MATCHDAY = 4;
const RESERVED_5 = 5;
const CLAN_BATTLE = 6;
private ?int $id;
private int $type = self::QUEST;
private int $version = 1;
private Collection $battles;
private Collection $teams;
public function __construct(int $type = self::QUEST)
{
$this->heroes = new ArrayCollection();
$this->battles = new ArrayCollection();
$this->type = $type;
$this->teams = new ArrayCollection();
}
public function getType(): ?int
{
return $this->type;
}
public function setType(int $type): self
{
$this->type = $type;
return $this;
}
public function getVersion(): ?int
{
return $this->version;
}
public function setVersion(int $version): self
{
$this->version = $version;
return $this;
}
public function getId(): ?int
{
return $this->id;
}
/**
* @return Collection|EventBattle[]
*/
public function getBattles(): Collection
{
return $this->battles;
}
public function addBattle(EventBattle $battle): self
{
if (!$this->battles->contains($battle)) {
$this->battles[] = $battle;
$battle->setEvent($this);
}
return $this;
}
public function removeBattle(EventBattle $battle): self
{
if ($this->battles->contains($battle)) {
$this->battles->removeElement($battle);
// set the owning side to null (unless already changed)
if ($battle->getEvent() === $this) {
$battle->setEvent(null);
}
}
return $this;
}
/**
* @return Collection|EventTeam[]
*/
public function getTeams(): Collection
{
return $this->teams;
}
public function addTeam(EventTeam $team): self
{
if (!$this->teams->contains($team)) {
$this->teams[] = $team;
$team->setEvent($this);
}
return $this;
}
public function removeTeam(EventTeam $team): self
{
if ($this->teams->contains($team)) {
$this->teams->removeElement($team);
// set the owning side to null (unless already changed)
if ($team->getEvent() === $this) {
$team->setEvent(null);
}
}
return $this;
}
}

@ -0,0 +1,103 @@
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
class EventBattle
{
/**
*
* @var Event
*/
private $event = null;
private int $event_battle_id = 0;
private array $value = [];
private Collection $heroes;
/**
*
* @var EventTeam
*/
private $winningTeam;
public function __construct(Event $event, int $event_battle_id)
{
$this->event = $event;
$this->event_battle_id = $event_battle_id;
$this->heroes = new ArrayCollection();
}
public function getValue(): ?array
{
return $this->value;
}
public function setValue(array $value): self
{
$this->value = $value;
return $this;
}
public function getEvent(): ?Event
{
return $this->event;
}
public function setEvent(?Event $event): self
{
$this->event = $event;
return $this;
}
/**
*
* @return Collection|EventHero[]
*/
public function getHeroes(): Collection
{
return $this->heroes;
}
public function addHero(EventHero $hero): self
{
if (! $this->heroes->contains($hero)) {
$this->heroes[] = $hero;
}
return $this;
}
public function removeHero(EventHero $hero): self
{
if ($this->heroes->contains($hero)) {
$this->heroes->removeElement($hero);
}
return $this;
}
public function getWinningTeam(): ?EventTeam
{
return $this->winningTeam;
}
public function setWinningTeam(?EventTeam $winningTeam): self
{
$this->winningTeam = $winningTeam;
return $this;
}
public function getEventBattleId(): ?int
{
return $this->event_battle_id;
}
}

@ -0,0 +1,125 @@
<?php
namespace App\Entity;
class EventHero
{
private int $event_hero_id = 0;
private string $name;
private Skillz $skills;
/**
*
* @var Hero
*/
private $hero;
/**
*
* @var User
*/
private $user;
/**
*
* @var Event
*/
private $event;
/**
*
* @var EventTeam
*/
private $team;
public function __construct(Event $event, Hero $hero, EventTeam $team)
{
$this->event = $event;
$this->event_hero_id = $hero->getId();
$this->name = $hero->getName();
$this->skills = $hero->getSkills();
$this->team = $team;
$this->hero = $hero;
$this->user = $hero->getUser();
}
public function getSkills(): Skillz
{
return $this->skills;
}
public function setSkills(Skillz $skills): self
{
$this->skills = $skills;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getHero(): ?Hero
{
return $this->hero;
}
public function setHero(?Hero $hero): self
{
$this->hero = $hero;
return $this;
}
public function getEvent(): ?Event
{
return $this->event;
}
public function setEvent(?Event $event): self
{
$this->event = $event;
return $this;
}
public function getTeam(): ?EventTeam
{
return $this->team;
}
public function setTeam(?EventTeam $team): self
{
$this->team = $team;
return $this;
}
public function getEventHeroId(): ?int
{
return $this->event_hero_id;
}
}

@ -0,0 +1,91 @@
<?php
namespace App\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
class EventTeam
{
/**
*
* @var Event
*/
private $event = null;
private int $event_team_id = 0;
private string $name = "";
private Collection $heroes;
public function __construct(Event $event, int $team_id, string $name)
{
$this->event = $event;
$this->event_team_id = $team_id;
$this->name = $name;
$this->heroes = new ArrayCollection();
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
*
* @return Collection|EventHero[]
*/
public function getHeroes(): Collection
{
return $this->heroes;
}
public function addHero(EventHero $hero): self
{
if (! $this->heroes->contains($hero)) {
$this->heroes[] = $hero;
$hero->setTeam($this);
}
return $this;
}
public function removeHero(EventHero $hero): self
{
if ($this->heroes->contains($hero)) {
$this->heroes->removeElement($hero);
// set the owning side to null (unless already changed)
if ($hero->getTeam() === $this) {
$hero->setTeam(null);
}
}
return $this;
}
public function getEvent(): ?Event
{
return $this->event;
}
public function setEvent(?Event $event): self
{
$this->event = $event;
return $this;
}
public function getEventTeamId(): ?int
{
return $this->event_team_id;
}
}

@ -1,18 +1,36 @@
<?php
namespace App\Entity;
class Hero
{
private $id;
private $name;
private ?int $id;
private ?string $name;
/**
*
* @var User
*/
private $user;
public function getId(): ?int
private Skillz $skills;
public function __construct()
{
return $this->id;
$this->skills = new Skillz();
}
public function getSkills(): Skillz
{
return $this->skills;
}
public function setSkills(Skillz $skills): self
{
$this->skills = $skills;
return $this;
}
public function getName(): ?string
@ -27,6 +45,11 @@ class Hero
return $this;
}
public function getId(): ?int
{
return $this->id;
}
public function getUser(): ?User
{
return $this->user;

@ -0,0 +1,72 @@
<?php
namespace App\Entity;
class Skillz
{
private int $constitution = 0;
private int $ki = 0;
private int $strength = 0;
private int $agility = 0;
private int $stamina = 0;
public function getStrength(): ?int
{
return $this->strength;
}
public function setStrength(int $strength): self
{
$this->strength = $strength;
return $this;
}
public function getAgility(): ?int
{
return $this->agility;
}
public function setAgility(int $agility): self
{
$this->agility = $agility;
return $this;
}
public function getStamina(): ?int
{
return $this->stamina;
}
public function setStamina(int $stamina): self
{
$this->stamina = $stamina;
return $this;
}
public function getConstitution(): ?int
{
return $this->constitution;
}
public function setConstitution(int $constitution): self
{
$this->constitution = $constitution;
return $this;
}
public function getKi(): ?int
{
return $this->ki;
}
public function setKi(int $ki): self
{
$this->ki = $ki;
return $this;
}
}

@ -8,17 +8,17 @@ use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
{
private $id;
private ?int $id;
private $username;
private ?string $username;
private $password;
private ?string $password;
private $apiToken;
private ?string $apiToken;
private $roles = [];
private array $roles = [];
private $heroes;
private Collection $heroes;
public function __construct()
{
@ -29,10 +29,7 @@ class User implements UserInterface
{
return $this->id;
}
/**
* @see UserInterface
*/
public function getUsername(): ?string
{
return $this->username;

@ -3,59 +3,36 @@
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\RouteCollectionBuilder;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
const CONFIG_EXTS = '.{php,xml,yaml,yml}';
public function getCacheDir()
{
return $this->getProjectDir().'/var/cache/'.$this->environment;
}
public function getLogDir()
{
return $this->getProjectDir().'/var/log';
}
public function registerBundles()
protected function configureContainer(ContainerConfigurator $container): void
{
$contents = require $this->getProjectDir().'/config/bundles.php';
foreach ($contents as $class => $envs) {
if ($envs[$this->environment] ?? $envs['all'] ?? false) {
yield new $class();
}
$container->import('../config/{packages}/*.yaml');
$container->import('../config/{packages}/'.$this->environment.'/*.yaml');
if (is_file(\dirname(__DIR__).'/config/services.yaml')) {
$container->import('../config/services.yaml');
$container->import('../config/{services}_'.$this->environment.'.yaml');
} elseif (is_file($path = \dirname(__DIR__).'/config/services.php')) {
(require $path)($container->withPath($path), $this);
}
}
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
{
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
// Feel free to remove the "container.autowiring.strict_mode" parameter
// if you are using symfony/dependency-injection 4.0+ as it's the default behavior
$container->setParameter('container.autowiring.strict_mode', true);
$container->setParameter('container.dumper.inline_class_loader', true);
$confDir = $this->getProjectDir().'/config';
$loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
}
protected function configureRoutes(RouteCollectionBuilder $routes)
protected function configureRoutes(RoutingConfigurator $routes): void
{
$confDir = $this->getProjectDir().'/config';
$routes->import('../config/{routes}/'.$this->environment.'/*.yaml');
$routes->import('../config/{routes}/*.yaml');
$routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
if (is_file(\dirname(__DIR__).'/config/routes.yaml')) {
$routes->import('../config/routes.yaml');
} elseif (is_file($path = \dirname(__DIR__).'/config/routes.php')) {
(require $path)($routes->withPath($path), $this);
}
}
}

@ -1,35 +0,0 @@
<?php declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20181118195745 extends AbstractMigration
{
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'sqlite', 'Migration can only be executed safely on \'sqlite\'.');
$this->addSql('CREATE TABLE hero (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, user_id INTEGER NOT NULL, name VARCHAR(32) NOT NULL)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_51CE6E865E237E06 ON hero (name)');
$this->addSql('CREATE INDEX IDX_51CE6E86A76ED395 ON hero (user_id)');
$this->addSql('CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username VARCHAR(32) NOT NULL, password VARCHAR(255) NOT NULL, api_token VARCHAR(255) DEFAULT NULL, roles CLOB NOT NULL --(DC2Type:json)
)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D649F85E0677 ON user (username)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D6497BA2F5EB ON user (api_token)');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'sqlite', 'Migration can only be executed safely on \'sqlite\'.');
$this->addSql('DROP TABLE hero');
$this->addSql('DROP TABLE user');
}
}

@ -0,0 +1,22 @@
<?php
namespace App\Repository;
use App\Entity\EventBattle;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
*
* @method EventBattle|null find($id, $lockMode = null, $lockVersion = null)
* @method EventBattle|null findOneBy(array $criteria, array $orderBy = null)
* @method EventBattle[] findAll()
* @method EventBattle[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class EventBattleRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, EventBattle::class);
}
}

@ -0,0 +1,22 @@
<?php
namespace App\Repository;
use App\Entity\EventHero;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
*
* @method EventHero|null find($id, $lockMode = null, $lockVersion = null)
* @method EventHero|null findOneBy(array $criteria, array $orderBy = null)
* @method EventHero[] findAll()
* @method EventHero[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class EventHeroRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, EventHero::class);
}
}

@ -0,0 +1,22 @@
<?php
namespace App\Repository;
use App\Entity\Event;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
*
* @method Event|null find($id, $lockMode = null, $lockVersion = null)
* @method Event|null findOneBy(array $criteria, array $orderBy = null)
* @method Event[] findAll()
* @method Event[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class EventRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Event::class);
}
}

@ -0,0 +1,22 @@
<?php
namespace App\Repository;
use App\Entity\EventTeam;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
*
* @method EventTeam|null find($id, $lockMode = null, $lockVersion = null)
* @method EventTeam|null findOneBy(array $criteria, array $orderBy = null)
* @method EventTeam[] findAll()
* @method EventTeam[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class EventTeamRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, EventTeam::class);
}
}

@ -1,50 +1,22 @@
<?php
namespace App\Repository;
use App\Entity\Hero;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Doctrine\Persistence\ManagerRegistry;
/**
*
* @method Hero|null find($id, $lockMode = null, $lockVersion = null)
* @method Hero|null findOneBy(array $criteria, array $orderBy = null)
* @method Hero[] findAll()
* @method Hero[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @method Hero[] findAll()
* @method Hero[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class HeroRepository extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, Hero::class);
}
// /**
// * @return Hero[] Returns an array of Hero objects
// */
/*
public function findByExampleField($value)
public function __construct(ManagerRegistry $registry)
{
return $this->createQueryBuilder('h')
->andWhere('h.exampleField = :val')
->setParameter('val', $value)
->orderBy('h.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?Hero
{
return $this->createQueryBuilder('h')
->andWhere('h.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
parent::__construct($registry, Hero::class);
}
*/
}

@ -1,50 +1,22 @@
<?php
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Doctrine\Persistence\ManagerRegistry;
/**
*
* @method User|null find($id, $lockMode = null, $lockVersion = null)
* @method User|null findOneBy(array $criteria, array $orderBy = null)
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, User::class);
}
// /**
// * @return User[] Returns an array of User objects
// */
/*
public function findByExampleField($value)
public function __construct(ManagerRegistry $registry)
{
return $this->createQueryBuilder('u')
->andWhere('u.exampleField = :val')
->setParameter('val', $value)
->orderBy('u.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?User
{
return $this->createQueryBuilder('u')
->andWhere('u.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
parent::__construct($registry, User::class);
}
*/
}

@ -14,10 +14,7 @@ use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class TokenAuthenticator extends AbstractGuardAuthenticator
{
/**
* @var UserRepository
*/
private $userRepository;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
@ -40,21 +37,17 @@ class TokenAuthenticator extends AbstractGuardAuthenticator
*/
public function getCredentials(Request $request)
{
return array(
'token' => $request->headers->get('X-AUTH-TOKEN'),
);
return $request->headers->get('X-AUTH-TOKEN');
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$apiToken = $credentials['token'];
if (null === $apiToken) {
return;
if (null === $credentials) {
return null;
}
// if a User object, checkCredentials() is called
return $this->userRepository->findOneBy(['apiToken' => $apiToken]);
return $this->userRepository->findOneBy(['apiToken' => $credentials]);
}
public function checkCredentials($credentials, UserInterface $user)
@ -89,8 +82,9 @@ class TokenAuthenticator extends AbstractGuardAuthenticator
{
throw new UnauthorizedHttpException('', 'Authentication Required');
}
public function supportsRememberMe()
public function supportsRememberMe() : bool
{
return false;
}

@ -0,0 +1,88 @@
<?php
namespace App\Security;
use App\Repository\UserRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use App\Entity\User;
class UrlAuthenticator extends AbstractGuardAuthenticator
{
/**
* Called on every request to decide if this authenticator should be
* used for the request.
* Returning false will cause this authenticator
* to be skipped.
*/
public function supports(Request $request)
{
return str_starts_with($request->getPathInfo(), "/main/");
}
/**
* Called on every request.
* Return whatever credentials you want to
* be passed to getUser() as $credentials.
*/
public function getCredentials(Request $request)
{
$result = preg_replace('#/main/([^/]+)/#i', '$1', $request->getPathInfo());
return $result === $request->getPathInfo() ? null : $result;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
if (null === $credentials) {
return null;
}
$user = new User();
$user->setUsername($credentials);
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
// check credentials - e.g. make sure the password is valid
// no credential check is needed in this case
// return true to cause authentication success
return true;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
// on success, let the request continue
return null;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$message = strtr($exception->getMessageKey(), $exception->getMessageData());
// or to translate this message
// $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
// This should translated by FOSRestBundle!
throw new AccessDeniedHttpException($message);
}
/**
* Called when authentication is needed, but it's not sent
*/
public function start(Request $request, AuthenticationException $authException = null)
{
throw new UnauthorizedHttpException('', 'Authentication Required');
}
public function supportsRememberMe(): bool
{
return false;
}
}

@ -5,8 +5,11 @@
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.0",
"ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672"
}
"ref": "a2759dd6123694c8d901d0ec80006e044c2e6457"
},
"files": [
"config/routes/annotations.yaml"
]
},
"doctrine/cache": {
"version": "v1.8.0"
@ -23,17 +26,23 @@
"doctrine/dbal": {
"version": "v2.8.0"
},
"doctrine/deprecations": {
"version": "v0.5.3"
},
"doctrine/doctrine-bundle": {
"version": "1.6",
"version": "2.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.6",
"ref": "453e89b78ded666f351617baca5ae40d20622351"
}
},
"doctrine/doctrine-cache-bundle": {
"version": "1.3.5"
"version": "2.0",
"ref": "a9f2463b9f73efe74482f831f03a204a41328555"
},
"files": [
"config/packages/doctrine.yaml",
"config/packages/prod/doctrine.yaml",
"src/Entity/.gitignore",
"src/Repository/.gitignore"
]
},
"doctrine/doctrine-fixtures-bundle": {
"version": "3.0",
@ -41,17 +50,24 @@
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.0",
"ref": "fc52d86631a6dfd9fdf3381d0b7e3df2069e51b3"
}
"ref": "e5b542d4ef47d8a003c91beb35650c76907f7e53"
},
"files": [
"src/DataFixtures/AppFixtures.php"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "1.2",
"version": "2.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.2",
"ref": "c1431086fec31f17fbcfe6d6d7e92059458facc1"
}
"version": "2.2",
"ref": "baaa439e3e3179e69e3da84b671f0a3e4a2f56ad"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"doctrine/event-manager": {
"version": "v1.0.0"
@ -77,6 +93,9 @@
"doctrine/reflection": {
"version": "v1.0.0"
},
"doctrine/sql-formatter": {
"version": "1.1.1"
},
"easycorp/easy-log-handler": {
"version": "1.0",
"recipe": {
@ -92,8 +111,8 @@
"facebook/webdriver": {
"version": "1.6.0"
},
"fig/link-util": {
"version": "1.0.0"
"friendsofphp/proxy-manager-lts": {
"version": "v1.0.5"
},
"friendsofsymfony/rest-bundle": {
"version": "2.2",
@ -101,11 +120,20 @@
"repo": "github.com/symfony/recipes-contrib",
"branch": "master",
"version": "2.2",
"ref": "258300d52be6ad59b32a888d5ddafbf9638540ff"
}
"ref": "cad41ef93d6150067ae2bb3c7fd729492dff6f0a"
},
"files": [
"config/packages/fos_rest.yaml"
]
},
"jdorn/sql-formatter": {
"version": "v1.2.17"
"laminas/laminas-code": {
"version": "3.4.1"
},
"laminas/laminas-eventmanager": {
"version": "3.3.0"
},
"laminas/laminas-zendframework-bridge": {
"version": "1.1.1"
},
"monolog/monolog": {
"version": "1.24.0"
@ -119,6 +147,9 @@
"ocramius/proxy-manager": {
"version": "2.1.1"
},
"php": {
"version": "7.4"
},
"phpdocumentor/reflection-common": {
"version": "1.0.1"
},
@ -134,15 +165,15 @@
"psr/container": {
"version": "1.0.0"
},
"psr/event-dispatcher": {
"version": "1.0.0"
},
"psr/link": {
"version": "1.0.0"
},
"psr/log": {
"version": "1.0.2"
},
"psr/simple-cache": {
"version": "1.0.1"
},
"sensio/framework-extra-bundle": {
"version": "5.2",
"recipe": {
@ -152,9 +183,6 @@
"ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
}
},
"swiftmailer/swiftmailer": {
"version": "v6.1.3"
},
"symfony/asset": {
"version": "v4.1.7"
},
@ -164,24 +192,27 @@
"symfony/cache": {
"version": "v4.1.7"
},
"symfony/cache-contracts": {
"version": "v2.2.0"
},
"symfony/config": {
"version": "v4.1.7"
},
"symfony/console": {
"version": "3.3",
"version": "5.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.3",
"ref": "181d766db0eb468f41337f9b2d9d5b61ba1ee441"
}
"version": "5.1",
"ref": "c6d02bdfba9da13c22157520e32a602dbee8a75c"
},
"files": [
"bin/console"
]
},
"symfony/css-selector": {
"version": "v4.1.7"
},
"symfony/debug": {
"version": "v4.1.7"
},
"symfony/debug-bundle": {
"version": "4.1",
"recipe": {
@ -191,12 +222,12 @@
"ref": "f8863cbad2f2e58c4b65fa1eac892ab189971bea"
}
},
"symfony/debug-pack": {
"version": "v1.0.6"
},
"symfony/dependency-injection": {
"version": "v4.1.7"
},
"symfony/deprecation-contracts": {
"version": "v2.2.0"
},
"symfony/doctrine-bridge": {
"version": "v4.1.7"
},
@ -206,9 +237,15 @@
"symfony/dotenv": {
"version": "v4.1.7"
},
"symfony/error-handler": {
"version": "v4.4.15"
},
"symfony/event-dispatcher": {
"version": "v4.1.7"
},
"symfony/event-dispatcher-contracts": {
"version": "v1.1.9"
},
"symfony/expression-language": {
"version": "v4.1.7"
},
@ -224,20 +261,40 @@
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.0",
"ref": "5f8a51c0fad684396f6b6c0fd770e043439cb632"
}
"ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e"
},
"files": [
".env"
]
},
"symfony/form": {
"version": "v4.1.7"
},
"symfony/framework-bundle": {
"version": "3.3",
"version": "5.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.3",
"ref": "9ec493d6f3575c54671493d635fa4b68658022ab"
}
"version": "5.1",
"ref": "6ee1194b036378b21884e7f57b6a2ac721167f16"
},
"files": [
"config/packages/cache.yaml",
"config/packages/framework.yaml",
"config/packages/test/framework.yaml",
"config/preload.php",
"config/routes/dev/framework.yaml",
"config/services.yaml",
"public/index.php",
"src/Controller/.gitignore",
"src/Kernel.php"
]
},
"symfony/http-client": {
"version": "v5.1.7"
},
"symfony/http-client-contracts": {
"version": "v2.3.1"
},
"symfony/http-foundation": {
"version": "v4.1.7"
@ -245,12 +302,21 @@
"symfony/http-kernel": {
"version": "v4.1.7"
},
"symfony/inflector": {
"version": "v4.1.7"
},
"symfony/intl": {
"version": "v4.1.7"
},
"symfony/mailer": {
"version": "4.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "4.3",
"ref": "15658c2a0176cda2e7dba66276a2030b52bd81b2"
},
"files": [
"config/packages/mailer.yaml"
]
},
"symfony/maker-bundle": {
"version": "1.0",
"recipe": {
@ -260,51 +326,90 @@
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
"symfony/mime": {
"version": "v4.4.15"
},
"symfony/monolog-bridge": {
"version": "v4.1.7"
},
"symfony/monolog-bundle": {
"version": "3.1",
"version": "3.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.1",
"ref": "18ebf5a940573a20de06f9c4060101eeb438cf3d"
}
"version": "3.3",
"ref": "d7249f7d560f6736115eee1851d02a65826f0a56"
},
"files": [
"config/packages/dev/monolog.yaml",
"config/packages/prod/deprecations.yaml",
"config/packages/prod/monolog.yaml",
"config/packages/test/monolog.yaml"
]
},
"symfony/notifier": {
"version": "5.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "5.0",
"ref": "c31585e252b32fe0e1f30b1f256af553f4a06eb9"
},
"files": [
"config/packages/notifier.yaml"
]
},
"symfony/options-resolver": {
"version": "v4.1.7"
},
"symfony/orm-pack": {
"version": "v1.0.5"
},
"symfony/panther": {
"version": "v0.2.0"
},
"symfony/password-hasher": {
"version": "v5.3.8"
},
"symfony/phpunit-bridge": {
"version": "4.1",
"version": "4.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "4.1",
"ref": "b4c7d939cac9a67e02366fa7971746e9cbf1dad0"
}
"version": "4.3",
"ref": "6d0e35f749d5f4bfe1f011762875275cd3f9874f"
},
"files": [
".env.test",
"bin/phpunit",
"phpunit.xml.dist",
"tests/bootstrap.php"
]
},
"symfony/polyfill-intl-grapheme": {
"version": "v1.18.1"
},
"symfony/polyfill-intl-icu": {
"version": "v1.10.0"
},
"symfony/polyfill-intl-idn": {
"version": "v1.18.1"
},
"symfony/polyfill-intl-normalizer": {
"version": "v1.18.1"
},
"symfony/polyfill-mbstring": {
"version": "v1.10.0"
},
"symfony/polyfill-php72": {
"version": "v1.10.0"
"symfony/polyfill-php73": {
"version": "v1.18.1"
},
"symfony/polyfill-php80": {
"version": "v1.18.1"
},
"symfony/polyfill-php81": {
"version": "v1.23.0"
},
"symfony/process": {
"version": "v4.1.7"
},
"symfony/profiler-pack": {
"version": "v1.0.3"
},
"symfony/property-access": {
"version": "v4.1.7"
},
@ -312,49 +417,54 @@
"version": "v4.1.7"
},
"symfony/routing": {
"version": "4.0",
"version": "5.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "4.0",
"ref": "5f514d9d3b8a8aac3d62ae6a86b18b90ed0c7826"
}
},
"symfony/security": {
"version": "v4.1.7"
"version": "5.1",
"ref": "b4f3e7c95e38b606eef467e8a42a8408fc460c43"
},
"files": [
"config/packages/prod/routing.yaml",
"config/packages/routing.yaml",
"config/routes.yaml"
]
},
"symfony/security-bundle": {
"version": "3.3",
"version": "5.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.3",
"ref": "f8a63faa0d9521526499c0a8f403c9964ecb0527"
}
"version": "5.1",
"ref": "0a4bae19389d3b9cba1ca0102e3b2bccea724603"
},
"files": [
"config/packages/security.yaml"
]
},
"symfony/serializer": {
"version": "v4.1.7"
"symfony/security-core": {
"version": "v4.4.15"
},
"symfony/serializer-pack": {
"version": "v1.0.1"
"symfony/security-csrf": {
"version": "v4.4.15"
},
"symfony/stopwatch": {
"symfony/security-guard": {
"version": "v4.4.15"
},
"symfony/security-http": {
"version": "v4.4.15"
},
"symfony/serializer": {
"version": "v4.1.7"
},
"symfony/swiftmailer-bundle": {
"version": "2.5",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "2.5",
"ref": "3db029c03e452b4a23f7fc45cec7c922c2247eb8"
}
"symfony/service-contracts": {
"version": "v2.2.0"
},
"symfony/templating": {
"symfony/stopwatch": {
"version": "v4.1.7"
},
"symfony/test-pack": {
"version": "v1.0.4"
"symfony/string": {
"version": "v5.1.7"
},
"symfony/translation": {
"version": "3.3",
@ -362,33 +472,52 @@
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.3",
"ref": "1fb02a6e1c8f3d4232cce485c9afa868d63b115a"
}
"ref": "2ad9d2545bce8ca1a863e50e92141f0b9d87ffcd"
},
"files": [
"config/packages/translation.yaml",
"translations/.gitignore"
]
},
"symfony/translation-contracts": {
"version": "v2.3.0"
},
"symfony/twig-bridge": {
"version": "v4.1.7"
},
"symfony/twig-bundle": {
"version": "3.3",
"version": "5.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.3",
"ref": "369b5b29dc52b2c190002825ae7ec24ab6f962dd"
}
"version": "5.0",
"ref": "fab9149bbaa4d5eca054ed93f9e1b66cc500895d"
},
"files": [
"config/packages/test/twig.yaml",
"config/packages/twig.yaml",
"templates/base.html.twig"
]
},
"symfony/validator": {
"version": "4.1",
"version": "4.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "4.1",
"ref": "0cdc982334f45d554957a6167e030482795bf9d7"
}
"version": "4.3",
"ref": "d902da3e4952f18d3bf05aab29512eb61cabd869"
},
"files": [
"config/packages/test/validator.yaml",
"config/packages/validator.yaml"
]
},
"symfony/var-dumper": {
"version": "v4.1.7"
},
"symfony/var-exporter": {
"version": "v4.4.15"
},
"symfony/web-link": {
"version": "v4.1.7"
},
@ -401,21 +530,18 @@
"ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6"
}
},
"symfony/web-server-bundle": {
"version": "3.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "3.3",
"ref": "dae9b39fd6717970be7601101ce5aa960bf53d9a"
}
},
"symfony/yaml": {
"version": "v4.1.7"
},
"twig/extra-bundle": {
"version": "v3.0.5"
},
"twig/twig": {
"version": "v2.5.0"
},
"webimpress/safe-writer": {
"version": "2.1.0"
},
"webmozart/assert": {
"version": "1.3.0"
},

@ -0,0 +1,20 @@
{% extends 'base.html.twig' %}
{% block title %}Hello LandingController!{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code><a href="{{ '/home/pascal/git/animegame/src/Controller/Std/LandingController.php'|file_link(0) }}">src/Controller/Std/LandingController.php</a></code></li>
<li>Your template at <code><a href="{{ '/home/pascal/git/animegame/templates/landing/index.html.twig'|file_link(0) }}">templates/landing/index.html.twig</a></code></li>
</ul>
</div>
{% endblock %}

@ -2,18 +2,14 @@
namespace App\Tests\Controller;
use Symfony\Component\BrowserKit\Client;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
class ClientRequestBuilder
{
/**
*
* @var Client
*/
private $client;
protected KernelBrowser $client;
/**
*
* @var string
@ -44,7 +40,7 @@ class ClientRequestBuilder
*/
private $acceptType;
public function __construct(Client $client)
public function __construct(KernelBrowser $client)
{
$this->client = $client;
$this->parameters = [];
@ -52,7 +48,7 @@ class ClientRequestBuilder
$this->acceptType = 'application/json';
}
public static function create(Client $client): ClientRequestBuilder
public static function create(KernelBrowser $client): ClientRequestBuilder
{
return new ClientRequestBuilder($client);
}

@ -0,0 +1,34 @@
<?php
namespace App\Tests\Controller;
use App\DataFixtures\UserFixtures;
class EventControllerTest extends RestTestBase
{
/**
* This test verifies that requesting
*/
public function testRetrieveUser()
{
$this->createRequestBuilder()
->setMethod('GET')
->setUri('/api/events')
->setAcceptType('application/json')
->addServerParameter('HTTP_X-AUTH-TOKEN', UserFixtures::ADMIN_USER_REFERENCE)
->request();
$response = $this->client->getResponse();
$this->assertTrue($response->headers->contains('Content-Type', 'application/json'), 'the "Content-Type" header is "' . $response->headers->get('Content-Type') . '"' // optional message shown on failure
);
$this->assertEquals(200, $response->getStatusCode(), 'Status code was ' . $response->getStatusCode() . ' but expected 200: ' . $response->getContent());
$data = json_decode($response->getContent());
// Expect two events
$this->assertEquals(2, count($data));
}
}

@ -1,20 +1,17 @@
<?php
namespace App\Tests\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Client;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
class RestTestBase extends WebTestCase
{
/**
* @var Client
*/
protected $client;
protected KernelBrowser $client;
protected function setUp()
{
@ -26,10 +23,13 @@ class RestTestBase extends WebTestCase
protected function reloadDoctrineFixtures()
{
self::runCommand('doctrine:migration:migrate');
// we need our fixtures to be stateless, so remove everything and recreate to get the same
// index values all along the tests
self::runCommand('doctrine:schema:drop --force -n');
self::runCommand('doctrine:schema:create -n');
self::runCommand('doctrine:fixtures:load --purge-with-truncate -n');
}
protected function runCommand($command)
{
$application = new Application($this->client->getKernel());
@ -43,7 +43,7 @@ class RestTestBase extends WebTestCase
$builder->setAcceptType($acceptType);
return $builder;
}
protected function retrieveEntityManager(): EntityManagerInterface
{
return $this->client->getContainer()->get('doctrine.orm.entity_manager');

@ -15,7 +15,7 @@ class UserControllerTest extends RestTestBase
->setMethod('GET')
->setUri('/api/users')
->setAcceptType('application/json')
->addServerParameter('HTTP_X-AUTH-TOKEN', UserFixtures::ADMIN_USER_TOKEN)
->addServerParameter('HTTP_X-AUTH-TOKEN', UserFixtures::ADMIN_USER_REFERENCE)
->request();
$response = $this->client->getResponse();
@ -28,4 +28,26 @@ class UserControllerTest extends RestTestBase
$this->assertEquals(200, $response->getStatusCode(), 'Status code was ' . $response->getStatusCode() . ' but expected 200: ' . $response->getContent());
}
/**
* This test verifies that requesting
*/
public function testRetrieveUserWithID1()
{
$this->createRequestBuilder()
->setMethod('GET')
->setUri('/api/user/1')
->setAcceptType('application/json')
->addServerParameter('HTTP_X-AUTH-TOKEN', UserFixtures::ADMIN_USER_REFERENCE)
->request();
$response = $this->client->getResponse();
$this->assertTrue(
$response->headers->contains('Content-Type', 'application/json'),
'the "Content-Type" header is "' . $response->headers->get('Content-Type') . '"' // optional message shown on failure
);
$this->assertEquals(200, $response->getStatusCode(), 'Status code was ' . $response->getStatusCode() . ' but expected 200: ' . $response->getContent());
}
}

@ -0,0 +1,11 @@
<?php
use Symfony\Component\Dotenv\Dotenv;
require dirname(__DIR__).'/vendor/autoload.php';
if (file_exists(dirname(__DIR__).'/config/bootstrap.php')) {
require dirname(__DIR__).'/config/bootstrap.php';
} elseif (method_exists(Dotenv::class, 'bootEnv')) {
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
}
Loading…
Cancel
Save