parent
d76534d6a3
commit
6ba77d3cec
@ -1,112 +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 Version20240219220159 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE "character" (id UUID NOT NULL, dojo_id UUID DEFAULT NULL, name VARCHAR(255) NOT NULL, strength INT NOT NULL, constitution INT NOT NULL, agility INT NOT NULL, chi INT NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_937AB03432F09E9C ON "character" (dojo_id)');
|
||||
$this->addSql('COMMENT ON COLUMN "character".id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN "character".dojo_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE character_technique (character_id UUID NOT NULL, technique_id UUID NOT NULL, PRIMARY KEY(character_id, technique_id))');
|
||||
$this->addSql('CREATE INDEX IDX_506B3A7A1136BE75 ON character_technique (character_id)');
|
||||
$this->addSql('CREATE INDEX IDX_506B3A7A1F8ACB26 ON character_technique (technique_id)');
|
||||
$this->addSql('COMMENT ON COLUMN character_technique.character_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN character_technique.technique_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE city (id UUID NOT NULL, dungeon_id UUID NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_2D5B0234B606863 ON city (dungeon_id)');
|
||||
$this->addSql('COMMENT ON COLUMN city.id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN city.dungeon_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE country (id UUID NOT NULL, capital_id UUID NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_5373C966FC2D9FF7 ON country (capital_id)');
|
||||
$this->addSql('COMMENT ON COLUMN country.id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN country.capital_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE dojo (id UUID NOT NULL, village_id UUID DEFAULT NULL, owner_id UUID NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_9494CCB15E237E06 ON dojo (name)');
|
||||
$this->addSql('CREATE INDEX IDX_9494CCB15E0D5582 ON dojo (village_id)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_9494CCB17E3C61F9 ON dojo (owner_id)');
|
||||
$this->addSql('COMMENT ON COLUMN dojo.id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN dojo.village_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN dojo.owner_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE dungeon (id UUID NOT NULL, city_id UUID NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_3FFA1F908BAC62AF ON dungeon (city_id)');
|
||||
$this->addSql('COMMENT ON COLUMN dungeon.id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN dungeon.city_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE prefecture (id UUID NOT NULL, capital_id UUID NOT NULL, country_id UUID NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_ABE6511AFC2D9FF7 ON prefecture (capital_id)');
|
||||
$this->addSql('CREATE INDEX IDX_ABE6511AF92F3E70 ON prefecture (country_id)');
|
||||
$this->addSql('COMMENT ON COLUMN prefecture.id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN prefecture.capital_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN prefecture.country_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE technique (id UUID NOT NULL, prerequisite_id UUID DEFAULT NULL, costs INT NOT NULL, damage VARCHAR(255) NOT NULL, energy VARCHAR(255) NOT NULL, accuracy VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_D73B9841276AF86B ON technique (prerequisite_id)');
|
||||
$this->addSql('COMMENT ON COLUMN technique.id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN technique.prerequisite_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE "user" (id UUID NOT NULL, dojo_id UUID DEFAULT NULL, auth_name VARCHAR(255) NOT NULL, properties JSON NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D64932F09E9C ON "user" (dojo_id)');
|
||||
$this->addSql('COMMENT ON COLUMN "user".id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN "user".dojo_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('CREATE TABLE village (id UUID NOT NULL, prefecture_id UUID NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_4E6C7FAA9D39C865 ON village (prefecture_id)');
|
||||
$this->addSql('COMMENT ON COLUMN village.id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('COMMENT ON COLUMN village.prefecture_id IS \'(DC2Type:ulid)\'');
|
||||
$this->addSql('ALTER TABLE "character" ADD CONSTRAINT FK_937AB03432F09E9C FOREIGN KEY (dojo_id) REFERENCES dojo (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE character_technique ADD CONSTRAINT FK_506B3A7A1136BE75 FOREIGN KEY (character_id) REFERENCES "character" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE character_technique ADD CONSTRAINT FK_506B3A7A1F8ACB26 FOREIGN KEY (technique_id) REFERENCES technique (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE city ADD CONSTRAINT FK_2D5B0234B606863 FOREIGN KEY (dungeon_id) REFERENCES dungeon (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE country ADD CONSTRAINT FK_5373C966FC2D9FF7 FOREIGN KEY (capital_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE dojo ADD CONSTRAINT FK_9494CCB15E0D5582 FOREIGN KEY (village_id) REFERENCES village (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE dojo ADD CONSTRAINT FK_9494CCB17E3C61F9 FOREIGN KEY (owner_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE dungeon ADD CONSTRAINT FK_3FFA1F908BAC62AF FOREIGN KEY (city_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE prefecture ADD CONSTRAINT FK_ABE6511AFC2D9FF7 FOREIGN KEY (capital_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE prefecture ADD CONSTRAINT FK_ABE6511AF92F3E70 FOREIGN KEY (country_id) REFERENCES country (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE technique ADD CONSTRAINT FK_D73B9841276AF86B FOREIGN KEY (prerequisite_id) REFERENCES technique (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE "user" ADD CONSTRAINT FK_8D93D64932F09E9C FOREIGN KEY (dojo_id) REFERENCES dojo (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE village ADD CONSTRAINT FK_4E6C7FAA9D39C865 FOREIGN KEY (prefecture_id) REFERENCES prefecture (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SCHEMA public');
|
||||
$this->addSql('ALTER TABLE "character" DROP CONSTRAINT FK_937AB03432F09E9C');
|
||||
$this->addSql('ALTER TABLE character_technique DROP CONSTRAINT FK_506B3A7A1136BE75');
|
||||
$this->addSql('ALTER TABLE character_technique DROP CONSTRAINT FK_506B3A7A1F8ACB26');
|
||||
$this->addSql('ALTER TABLE city DROP CONSTRAINT FK_2D5B0234B606863');
|
||||
$this->addSql('ALTER TABLE country DROP CONSTRAINT FK_5373C966FC2D9FF7');
|
||||
$this->addSql('ALTER TABLE dojo DROP CONSTRAINT FK_9494CCB15E0D5582');
|
||||
$this->addSql('ALTER TABLE dojo DROP CONSTRAINT FK_9494CCB17E3C61F9');
|
||||
$this->addSql('ALTER TABLE dungeon DROP CONSTRAINT FK_3FFA1F908BAC62AF');
|
||||
$this->addSql('ALTER TABLE prefecture DROP CONSTRAINT FK_ABE6511AFC2D9FF7');
|
||||
$this->addSql('ALTER TABLE prefecture DROP CONSTRAINT FK_ABE6511AF92F3E70');
|
||||
$this->addSql('ALTER TABLE technique DROP CONSTRAINT FK_D73B9841276AF86B');
|
||||
$this->addSql('ALTER TABLE "user" DROP CONSTRAINT FK_8D93D64932F09E9C');
|
||||
$this->addSql('ALTER TABLE village DROP CONSTRAINT FK_4E6C7FAA9D39C865');
|
||||
$this->addSql('DROP TABLE "character"');
|
||||
$this->addSql('DROP TABLE character_technique');
|
||||
$this->addSql('DROP TABLE city');
|
||||
$this->addSql('DROP TABLE country');
|
||||
$this->addSql('DROP TABLE dojo');
|
||||
$this->addSql('DROP TABLE dungeon');
|
||||
$this->addSql('DROP TABLE prefecture');
|
||||
$this->addSql('DROP TABLE technique');
|
||||
$this->addSql('DROP TABLE "user"');
|
||||
$this->addSql('DROP TABLE village');
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Fight;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
|
||||
#[AsController]
|
||||
class GetTournamentFights
|
||||
{
|
||||
|
||||
public function __invoke($tournamentId, EntityManagerInterface $em): iterable
|
||||
{
|
||||
return $em->getRepository(Fight::class)->findBy([
|
||||
'tournament' => $tournamentId
|
||||
], [
|
||||
'startDate' => 'ASC'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\FightRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: FightRepository::class)]
|
||||
class Fight extends Thing
|
||||
{
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Character::class)]
|
||||
private Collection $characters;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
|
||||
private ?\DateTimeInterface $startDate = null;
|
||||
|
||||
#[ORM\Column()]
|
||||
private array $events = [];
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?Character $winner = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'fights')]
|
||||
#[ORM\JoinColumn(nullable: false, onDelete: 'cascade')]
|
||||
private ?Tournament $tournament = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->characters = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Collection<int, Character>
|
||||
*/
|
||||
public function getCharacters(): Collection
|
||||
{
|
||||
return $this->characters;
|
||||
}
|
||||
|
||||
public function addCharacter(Character $character): static
|
||||
{
|
||||
if (! $this->characters->contains($character)) {
|
||||
$this->characters->add($character);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeCharacter(Character $character): static
|
||||
{
|
||||
$this->characters->removeElement($character);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStartDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
public function setStartDate(\DateTimeInterface $startDate): static
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEvents(): array
|
||||
{
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
public function setEvents(array $events): static
|
||||
{
|
||||
$this->events = $events;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getWinner(): ?Character
|
||||
{
|
||||
return $this->winner;
|
||||
}
|
||||
|
||||
public function setWinner(?Character $winner): static
|
||||
{
|
||||
$this->winner = $winner;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTournament(): ?Tournament
|
||||
{
|
||||
return $this->tournament;
|
||||
}
|
||||
|
||||
public function setTournament(?Tournament $tournament): static
|
||||
{
|
||||
$this->tournament = $tournament;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\TournamentRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: TournamentRepository::class)]
|
||||
class Tournament extends Thing
|
||||
{
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
public string $name;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Character::class)]
|
||||
public Collection $characters;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
|
||||
private ?\DateTimeInterface $startDate = null;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'tournament', targetEntity: Fight::class)]
|
||||
private Collection $fights;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->characters = new ArrayCollection();
|
||||
$this->fights = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Collection<int, Character>
|
||||
*/
|
||||
public function getCharacters(): Collection
|
||||
{
|
||||
return $this->characters;
|
||||
}
|
||||
|
||||
public function addCharacter(Character $character): static
|
||||
{
|
||||
if (! $this->characters->contains($character)) {
|
||||
$this->characters->add($character);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeCharacter(Character $character): static
|
||||
{
|
||||
$this->characters->removeElement($character);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStartDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
public function setStartDate(\DateTimeInterface $startDate): static
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Collection<int, Fight>
|
||||
*/
|
||||
public function getFights(): Collection
|
||||
{
|
||||
return $this->fights;
|
||||
}
|
||||
|
||||
public function addFight(Fight $fight): static
|
||||
{
|
||||
if (! $this->fights->contains($fight)) {
|
||||
$this->fights->add($fight);
|
||||
$fight->setTournament($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeFight(Fight $fight): static
|
||||
{
|
||||
if ($this->fights->removeElement($fight)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($fight->getTournament() === $this) {
|
||||
$fight->setTournament(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
namespace App\Entity;
|
||||
|
||||
class TournamentRegistration
|
||||
{
|
||||
|
||||
public Tournament $tournament;
|
||||
|
||||
public Character $character;
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Entity\Fight;
|
||||
use App\Repository\FightRepository;
|
||||
use Zenstruck\Foundry\ModelFactory;
|
||||
use Zenstruck\Foundry\Proxy;
|
||||
use Zenstruck\Foundry\RepositoryProxy;
|
||||
|
||||
/**
|
||||
* @extends ModelFactory<Fight>
|
||||
*
|
||||
* @method Fight|Proxy create(array|callable $attributes = [])
|
||||
* @method static Fight|Proxy createOne(array $attributes = [])
|
||||
* @method static Fight|Proxy find(object|array|mixed $criteria)
|
||||
* @method static Fight|Proxy findOrCreate(array $attributes)
|
||||
* @method static Fight|Proxy first(string $sortedField = 'id')
|
||||
* @method static Fight|Proxy last(string $sortedField = 'id')
|
||||
* @method static Fight|Proxy random(array $attributes = [])
|
||||
* @method static Fight|Proxy randomOrCreate(array $attributes = [])
|
||||
* @method static FightRepository|RepositoryProxy repository()
|
||||
* @method static Fight[]|Proxy[] all()
|
||||
* @method static Fight[]|Proxy[] createMany(int $number, array|callable $attributes = [])
|
||||
* @method static Fight[]|Proxy[] createSequence(iterable|callable $sequence)
|
||||
* @method static Fight[]|Proxy[] findBy(array $attributes)
|
||||
* @method static Fight[]|Proxy[] randomRange(int $min, int $max, array $attributes = [])
|
||||
* @method static Fight[]|Proxy[] randomSet(int $number, array $attributes = [])
|
||||
*/
|
||||
final class FightFactory extends ModelFactory
|
||||
{
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services
|
||||
*
|
||||
* @todo inject services if required
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories
|
||||
*
|
||||
* @todo add your default values here
|
||||
*/
|
||||
protected function getDefaults(): array
|
||||
{
|
||||
return [
|
||||
'events' => [],
|
||||
'startDate' => self::faker()->dateTime(),
|
||||
'tournament' => TournamentFactory::new(),
|
||||
'winner' => CharacterFactory::new(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
|
||||
*/
|
||||
protected function initialize(): self
|
||||
{
|
||||
return $this
|
||||
// ->afterInstantiate(function(Fight $fight): void {})
|
||||
;
|
||||
}
|
||||
|
||||
protected static function getClass(): string
|
||||
{
|
||||
return Fight::class;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Entity\Tournament;
|
||||
use App\Repository\TournamentRepository;
|
||||
use Zenstruck\Foundry\ModelFactory;
|
||||
use Zenstruck\Foundry\Proxy;
|
||||
use Zenstruck\Foundry\RepositoryProxy;
|
||||
|
||||
/**
|
||||
* @extends ModelFactory<Tournament>
|
||||
*
|
||||
* @method Tournament|Proxy create(array|callable $attributes = [])
|
||||
* @method static Tournament|Proxy createOne(array $attributes = [])
|
||||
* @method static Tournament|Proxy find(object|array|mixed $criteria)
|
||||
* @method static Tournament|Proxy findOrCreate(array $attributes)
|
||||
* @method static Tournament|Proxy first(string $sortedField = 'id')
|
||||
* @method static Tournament|Proxy last(string $sortedField = 'id')
|
||||
* @method static Tournament|Proxy random(array $attributes = [])
|
||||
* @method static Tournament|Proxy randomOrCreate(array $attributes = [])
|
||||
* @method static TournamentRepository|RepositoryProxy repository()
|
||||
* @method static Tournament[]|Proxy[] all()
|
||||
* @method static Tournament[]|Proxy[] createMany(int $number, array|callable $attributes = [])
|
||||
* @method static Tournament[]|Proxy[] createSequence(iterable|callable $sequence)
|
||||
* @method static Tournament[]|Proxy[] findBy(array $attributes)
|
||||
* @method static Tournament[]|Proxy[] randomRange(int $min, int $max, array $attributes = [])
|
||||
* @method static Tournament[]|Proxy[] randomSet(int $number, array $attributes = [])
|
||||
*/
|
||||
final class TournamentFactory extends ModelFactory
|
||||
{
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services
|
||||
*
|
||||
* @todo inject services if required
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories
|
||||
*
|
||||
* @todo add your default values here
|
||||
*/
|
||||
protected function getDefaults(): array
|
||||
{
|
||||
return [
|
||||
'name' => self::faker()->text(255),
|
||||
'startDate' => self::faker()->dateTime(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
|
||||
*/
|
||||
protected function initialize(): self
|
||||
{
|
||||
return $this
|
||||
// ->afterInstantiate(function(Tournament $tournament): void {})
|
||||
;
|
||||
}
|
||||
|
||||
protected static function getClass(): string
|
||||
{
|
||||
return Tournament::class;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Fight;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Fight>
|
||||
*
|
||||
* @method Fight|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Fight|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Fight[] findAll()
|
||||
* @method Fight[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class FightRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Fight::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Fight[] Returns an array of Fight objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('f')
|
||||
// ->andWhere('f.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('f.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?Fight
|
||||
// {
|
||||
// return $this->createQueryBuilder('f')
|
||||
// ->andWhere('f.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Tournament;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Tournament>
|
||||
*
|
||||
* @method Tournament|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Tournament|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Tournament[] findAll()
|
||||
* @method Tournament[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class TournamentRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Tournament::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Tournament[] Returns an array of Tournament objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('t')
|
||||
// ->andWhere('t.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('t.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?Tournament
|
||||
// {
|
||||
// return $this->createQueryBuilder('t')
|
||||
// ->andWhere('t.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
<?php
|
||||
namespace App\Security;
|
||||
|
||||
use App\Repository\UserRepository;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
|
||||
class ApiKeyAuthenticator extends AbstractAuthenticator
|
||||
{
|
||||
|
||||
public function __construct(private UserRepository $userRepository, private LoggerInterface $logger)
|
||||
{}
|
||||
|
||||
/**
|
||||
* 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): ?bool
|
||||
{
|
||||
return $request->headers->has('X-AUTH-TOKEN');
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): Passport
|
||||
{
|
||||
$apiToken = $request->headers->get('X-AUTH-TOKEN');
|
||||
if (null === $apiToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$userIdentifier = $apiToken;
|
||||
|
||||
return new SelfValidatingPassport(
|
||||
new UserBadge($userIdentifier,
|
||||
function (string $userIdentifier): ?UserInterface {
|
||||
return $this->userRepository->findOneBy([
|
||||
'authName' => $userIdentifier
|
||||
]);
|
||||
}));
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
// on success, let the request continue
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
$this->logger->critical("YYY");
|
||||
$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);
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
namespace App\Tests;
|
||||
|
||||
use App\Factory\TechniqueFactory;
|
||||
|
||||
class TechniqueTest extends AbstractTest
|
||||
{
|
||||
|
||||
public function testListTechniques(): void
|
||||
{
|
||||
TechniqueFactory::createMany(10, [
|
||||
'prerequisite' => NULL
|
||||
]);
|
||||
|
||||
$response = static::createClientWithToken()->request('GET', '/api/techniques');
|
||||
$this->assertEquals(10, count($response->toArray()));
|
||||
}
|
||||
|
||||
public function testListTechniquesWithPrerequisite(): void
|
||||
{
|
||||
$prerequisite = TechniqueFactory::createOne([
|
||||
'prerequisite' => NULL
|
||||
]);
|
||||
|
||||
TechniqueFactory::createMany(2, [
|
||||
'prerequisite' => $prerequisite
|
||||
]);
|
||||
|
||||
$response = static::createClientWithToken()->request('GET', '/api/techniques');
|
||||
$this->assertEquals(3, count($response->toArray()));
|
||||
}
|
||||
|
||||
public function testShowTechnique(): void
|
||||
{
|
||||
$technique = TechniqueFactory::createOne([
|
||||
'prerequisite' => NULL
|
||||
]);
|
||||
|
||||
$response = static::createClientWithToken()->request('GET',
|
||||
'/api/techniques/' . $technique->getId()
|
||||
->toBase32());
|
||||
|
||||
$this->assertJsonEquals(
|
||||
[
|
||||
'id' => $technique->getId()
|
||||
->toBase32(),
|
||||
'name' => $technique->getName(),
|
||||
'costs' => $technique->getCosts(),
|
||||
'damage' => $technique->getDamage(),
|
||||
'energy' => $technique->getEnergy(),
|
||||
'accuracy' => $technique->getAccuracy()
|
||||
], $response->getContent());
|
||||
}
|
||||
|
||||
public function testShowTechniqueWithPrerequisite(): void
|
||||
{
|
||||
$prerequisite = TechniqueFactory::createOne([
|
||||
'prerequisite' => NULL
|
||||
]);
|
||||
|
||||
$technique = TechniqueFactory::createOne([
|
||||
'prerequisite' => $prerequisite
|
||||
]);
|
||||
|
||||
$response = static::createClientWithToken()->request('GET',
|
||||
'/api/techniques/' . $technique->getId()
|
||||
->toBase32());
|
||||
|
||||
$this->assertJsonEquals(
|
||||
[
|
||||
'id' => $technique->getId()
|
||||
->toBase32(),
|
||||
'name' => $technique->getName(),
|
||||
'costs' => $technique->getCosts(),
|
||||
'damage' => $technique->getDamage(),
|
||||
'energy' => $technique->getEnergy(),
|
||||
'accuracy' => $technique->getAccuracy(),
|
||||
'prerequisite' => '/api/techniques/' . $prerequisite->getId()
|
||||
->toBase32()
|
||||
], $response->getContent());
|
||||
}
|
||||
|
||||
public function testCreateTechniqueAsAdmin(): void
|
||||
{
|
||||
$response = static::createClientWithToken("dehecht")->request('POST', '/api/techniques',
|
||||
[
|
||||
'json' => [
|
||||
'name' => 'Drei-Schwert-Style',
|
||||
'costs' => 2,
|
||||
'damage' => '3 * strength',
|
||||
'energy' => '1.5 * constitution + 2 * strength',
|
||||
'accuracy' => '2 * agility'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(201);
|
||||
|
||||
$this->assertArrayHasKey('id', $response->toArray());
|
||||
}
|
||||
|
||||
public function testCreateTechniqueFailsAsUser(): void
|
||||
{
|
||||
static::createClientWithToken()->request('POST', '/api/techniques',
|
||||
[
|
||||
'json' => [
|
||||
'name' => 'Drei-Schwert-Style',
|
||||
'costs' => 2,
|
||||
'damage' => '3 * strength',
|
||||
'energy' => '1.5 * constitution + 2 * strength',
|
||||
'accuracy' => '2 * agility'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(403);
|
||||
}
|
||||
|
||||
public function testFailToCreateTechniqueWithNonExistentPrerequisite(): void
|
||||
{
|
||||
$response = static::createClientWithToken("dehecht")->request('POST', '/api/techniques',
|
||||
[
|
||||
'json' => [
|
||||
'name' => 'Drei-Schwert-Style',
|
||||
'costs' => 2,
|
||||
'damage' => '3 * strength',
|
||||
'energy' => '1.5 * constitution + 2 * strength',
|
||||
'accuracy' => '2 * agility',
|
||||
'prerequisite' => '/api/techniques/01ARZ3NDEKTSV4RRFFQ69G5FAV'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertTrue($response->getStatusCode() / 100 != 2);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace App\Tests;
|
||||
|
||||
use App\Factory\CharacterFactory;
|
||||
use App\Factory\DojoFactory;
|
||||
use App\Factory\TournamentFactory;
|
||||
use App\Factory\UserFactory;
|
||||
|
||||
class TournamentTest extends AbstractTest
|
||||
{
|
||||
|
||||
// No need to create tournaments via API Endpoint ... will be done in cronjob
|
||||
public function testRegisterCharacter(): void
|
||||
{
|
||||
$tournament = TournamentFactory::createOne();
|
||||
|
||||
$dojo = DojoFactory::createOne([
|
||||
'owner' => UserFactory::createOne()
|
||||
]);
|
||||
|
||||
$character = CharacterFactory::createOne([
|
||||
'dojo' => $dojo
|
||||
]);
|
||||
|
||||
$response = static::createClientWithToken($dojo->getOwner()->authName)->request('POST',
|
||||
'/api/tournament_registrations',
|
||||
[
|
||||
'json' => [
|
||||
'tournament' => $this->getIri($tournament),
|
||||
'character' => $this->getIri($character)
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(201);
|
||||
|
||||
$this->assertArrayHasKey('id', $response->toArray());
|
||||
}
|
||||
|
||||
public function testRegisterCharacterNotPossibleTwice(): void
|
||||
{}
|
||||
|
||||
public function testRegisterCharacterOnPastTournament(): void
|
||||
{}
|
||||
|
||||
public function testShowRegisteredCharacters(): void
|
||||
{}
|
||||
|
||||
public function testListTournaments(): void
|
||||
{}
|
||||
|
||||
/**
|
||||
* Status is ...
|
||||
* meta data like when it is starting, name, "location", Winner (nullable), etc.
|
||||
*/
|
||||
public function testTournamentStatus(): void
|
||||
{}
|
||||
|
||||
// /api/tournament/{id}/fights
|
||||
// readableLink: true -> participant ids and winner
|
||||
public function testTournamentFights(): void
|
||||
{}
|
||||
|
||||
// /api/tournament/{id}/character/{id}/fights
|
||||
public function testTournamentFightsForCharacter(): void
|
||||
{}
|
||||
|
||||
// /api/tournament/{id}/ranking
|
||||
public function testTournamentRanking(): void
|
||||
{}
|
||||
}
|
||||
|
Loading…
Reference in new issue