1
0
Fork 0

Redesign leaderboard entities to support game periods and better match DTOs

This commit is contained in:
Krzysztof Sikorski 2022-04-18 03:39:10 +02:00
parent 579d2047d8
commit dd4ee4579a
Signed by: krzysztof-sikorski
GPG Key ID: 4EB564BD08FE8476
6 changed files with 279 additions and 73 deletions

117
migrations/Version0007.php Normal file
View File

@ -0,0 +1,117 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version0007 extends AbstractMigration
{
public function getDescription(): string
{
return 'Redesign leaderboard tables to support game periods and better match DTOs';
}
private function checkLeaderboardCount(): void
{
$sql = 'SELECT COUNT(*) FROM nexus_leaderboard';
$leaderboardCount = $this->connection->executeQuery(sql: $sql)->fetchOne();
$this->abortIf(
condition: $leaderboardCount > 0,
message: 'This migration can only be executed on empty leaderboard tables!',
);
}
public function preUp(Schema $schema): void
{
$this->checkLeaderboardCount();
}
public function up(Schema $schema): void
{
// create table nexus_leaderboard_category
$this->addSql(
<<<'SQL'
CREATE TABLE nexus_leaderboard_category (
id UUID NOT NULL,
name TEXT NOT NULL,
score_label TEXT NOT NULL,
career BOOLEAN NOT NULL,
PRIMARY KEY(id)
)
SQL
);
$this->addSql(
'CREATE UNIQUE INDEX nexus_leaderboard_category_uniq ON nexus_leaderboard_category (name, career)'
);
$this->addSql("COMMENT ON COLUMN nexus_leaderboard_category.id IS '(DC2Type:uuid)'");
// update nexus_leaderboard table
$this->addSql('DROP INDEX nexus_leaderboard_uniq');
$this->addSql("ALTER TABLE nexus_leaderboard ADD category_id UUID NOT NULL");
$this->addSql('ALTER TABLE nexus_leaderboard ADD game_period_id INT NOT NULL');
$this->addSql('ALTER TABLE nexus_leaderboard DROP title');
$this->addSql('ALTER TABLE nexus_leaderboard DROP value_title');
$this->addSql('ALTER TABLE nexus_leaderboard DROP career');
$this->addSql("COMMENT ON COLUMN nexus_leaderboard.category_id IS '(DC2Type:uuid)'");
$this->addSql(
<<<'SQL'
ALTER TABLE nexus_leaderboard ADD CONSTRAINT FK_2557F33F6140100F
FOREIGN KEY (category_id) REFERENCES nexus_leaderboard_category (id)
NOT DEFERRABLE INITIALLY IMMEDIATE
SQL
);
$this->addSql(
<<<'SQL'
ALTER TABLE nexus_leaderboard ADD CONSTRAINT FK_2557F33F3E2DBBDC
FOREIGN KEY (game_period_id) REFERENCES nexus_game_period (id)
NOT DEFERRABLE INITIALLY IMMEDIATE
SQL
);
$this->addSql('CREATE INDEX nexus_leaderboard_category_idx ON nexus_leaderboard (category_id)');
$this->addSql('CREATE INDEX nexus_leaderboard_game_period_idx ON nexus_leaderboard (game_period_id)');
$this->addSql('CREATE UNIQUE INDEX nexus_leaderboard_uniq ON nexus_leaderboard (category_id, game_period_id)');
// update nexus_leaderboard_entry table
$this->addSql('DROP INDEX nexus_leaderboard_entry_uniq');
$this->addSql('ALTER TABLE nexus_leaderboard_entry DROP CONSTRAINT nexus_leaderboard_entry_pkey');
$this->addSql('ALTER TABLE nexus_leaderboard_entry DROP id');
$this->addSql('ALTER TABLE nexus_leaderboard_entry DROP created_at');
$this->addSql('ALTER TABLE nexus_leaderboard_entry DROP last_modified_at');
$this->addSql('ALTER TABLE nexus_leaderboard_entry RENAME COLUMN value TO score');
$this->addSql('ALTER TABLE nexus_leaderboard_entry ADD PRIMARY KEY (leaderboard_id, position)');
}
public function preDown(Schema $schema): void
{
$this->checkLeaderboardCount();
}
public function down(Schema $schema): void
{
// update nexus_leaderboard_entry table
$this->addSql('ALTER TABLE nexus_leaderboard_entry DROP CONSTRAINT nexus_leaderboard_entry_pkey');
$this->addSql('ALTER TABLE nexus_leaderboard_entry RENAME COLUMN score TO value');
$this->addSql('ALTER TABLE nexus_leaderboard_entry ADD id UUID NOT NULL');
$this->addSql('ALTER TABLE nexus_leaderboard_entry ADD created_at TIMESTAMP(0) WITH TIME ZONE NOT NULL');
$this->addSql('ALTER TABLE nexus_leaderboard_entry ADD last_modified_at TIMESTAMP(0) WITH TIME ZONE NOT NULL');
$this->addSql("COMMENT ON COLUMN nexus_leaderboard_entry.id IS '(DC2Type:uuid)'");
$this->addSql("COMMENT ON COLUMN nexus_leaderboard_entry.created_at IS '(DC2Type:datetimetz_immutable)'");
$this->addSql("COMMENT ON COLUMN nexus_leaderboard_entry.last_modified_at IS '(DC2Type:datetimetz_immutable)'");
$this->addSql('CREATE UNIQUE INDEX nexus_leaderboard_entry_uniq ON nexus_leaderboard_entry (position)');
$this->addSql('ALTER TABLE nexus_leaderboard_entry ADD PRIMARY KEY (id)');
// update nexus_leaderboard table
$this->addSql('ALTER TABLE nexus_leaderboard DROP category_id');
$this->addSql('ALTER TABLE nexus_leaderboard DROP game_period_id');
$this->addSql('ALTER TABLE nexus_leaderboard ADD title TEXT NOT NULL');
$this->addSql('ALTER TABLE nexus_leaderboard ADD value_title TEXT NOT NULL');
$this->addSql('ALTER TABLE nexus_leaderboard ADD career BOOLEAN NOT NULL');
$this->addSql('CREATE UNIQUE INDEX nexus_leaderboard_uniq ON nexus_leaderboard (title)');
// drop table nexus_leaderboard_category
$this->addSql('DROP TABLE nexus_leaderboard_category');
}
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\Contract\Doctrine\Entity;
use App\Contract\Entity\Nexus\GamePeriodInterface;
interface GamePeriodReferenceInterface
{
public function getGamePeriod(): ?GamePeriodInterface;
public function setGamePeriod(GamePeriodInterface $gamePeriod): void;
}

View File

@ -5,8 +5,9 @@ declare(strict_types=1);
namespace App\Doctrine\Entity\Nexus;
use App\Contract\Doctrine\Entity\DatedEntityInterface;
use App\Contract\Doctrine\Entity\GamePeriodReferenceInterface;
use App\Contract\Doctrine\Entity\UuidPrimaryKeyInterface;
use App\Contract\Entity\LeaderboardTypes;
use App\Contract\Entity\Nexus\GamePeriodInterface;
use App\Doctrine\Entity\DatedEntityTrait;
use App\Doctrine\Entity\UuidPrimaryKeyTrait;
use App\Doctrine\Repository\Nexus\LeaderboardRepository;
@ -15,66 +16,49 @@ use Doctrine\ORM\Mapping as ORM;
#[
ORM\Entity(repositoryClass: LeaderboardRepository::class),
ORM\Table(name: 'nexus_leaderboard'),
ORM\UniqueConstraint(name: 'nexus_leaderboard_uniq', fields: ['title']),
ORM\UniqueConstraint(name: 'nexus_leaderboard_uniq', fields: ['category', 'gamePeriod']),
ORM\Index(fields: ['category'], name: 'nexus_leaderboard_category_idx'),
ORM\Index(fields: ['gamePeriod'], name: 'nexus_leaderboard_game_period_idx'),
]
class Leaderboard implements UuidPrimaryKeyInterface, DatedEntityInterface
class Leaderboard implements UuidPrimaryKeyInterface, GamePeriodReferenceInterface, DatedEntityInterface
{
use UuidPrimaryKeyTrait;
use DatedEntityTrait;
#[ORM\Column(name: 'title', type: 'text', nullable: false)]
private ?string $title = null;
#[
ORM\ManyToOne(targetEntity: LeaderboardCategory::class),
ORM\JoinColumn(name: 'category_id', referencedColumnName: 'id', nullable: false),
]
private ?LeaderboardCategory $category = null;
#[ORM\Column(name: 'value_title', type: 'text', nullable: false)]
private ?string $valueTitle = null;
#[ORM\Column(name: 'career', type: 'boolean', nullable: false)]
private bool $career = false;
#[
ORM\ManyToOne(targetEntity: GamePeriod::class),
ORM\JoinColumn(name: 'game_period_id', referencedColumnName: 'id', nullable: false),
]
protected ?GamePeriodInterface $gamePeriod = null;
public function __construct()
{
$this->generateId();
}
public function getTitle(): ?string
public function getCategory(): ?LeaderboardCategory
{
return $this->title;
return $this->category;
}
public function setTitle(string $title): void
public function setCategory(LeaderboardCategory $category): void
{
$this->title = $title;
$this->category = $category;
}
public function getValueTitle(): ?string
public function getGamePeriod(): ?GamePeriodInterface
{
return $this->valueTitle;
return $this->gamePeriod;
}
public function setValueTitle(string $valueTitle): void
public function setGamePeriod(GamePeriodInterface $gamePeriod): void
{
$this->valueTitle = $valueTitle;
}
public function getType(): ?string
{
return $this->career ? LeaderboardTypes::CAREER : LeaderboardTypes::BREATH;
}
public function setType(string $type): void
{
$this->career = LeaderboardTypes::CAREER === $type;
}
public function getCareer(): bool
{
return $this->career;
}
public function setCareer(bool $career): self
{
$this->career = $career;
return $this;
$this->gamePeriod = $gamePeriod;
}
}

View File

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace App\Doctrine\Entity\Nexus;
use App\Contract\Doctrine\Entity\UuidPrimaryKeyInterface;
use App\Contract\Entity\LeaderboardTypes;
use App\Doctrine\Entity\UuidPrimaryKeyTrait;
use App\Doctrine\Repository\Nexus\LeaderboardCategoryRepository;
use Doctrine\ORM\Mapping as ORM;
#[
ORM\Entity(repositoryClass: LeaderboardCategoryRepository::class),
ORM\Table(name: 'nexus_leaderboard_category'),
ORM\UniqueConstraint(name: 'nexus_leaderboard_category_uniq', fields: ['name', 'career']),
]
class LeaderboardCategory implements UuidPrimaryKeyInterface
{
use UuidPrimaryKeyTrait;
#[ORM\Column(name: 'name', type: 'text', nullable: false)]
private ?string $name = null;
#[ORM\Column(name: 'score_label', type: 'text', nullable: false)]
private ?string $scoreLabel = null;
#[ORM\Column(name: 'career', type: 'boolean', nullable: false)]
private bool $career = false;
public function __construct()
{
$this->generateId();
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getScoreLabel(): ?string
{
return $this->scoreLabel;
}
public function setScoreLabel(string $scoreLabel): void
{
$this->scoreLabel = $scoreLabel;
}
public function getType(): ?string
{
return $this->career ? LeaderboardTypes::CAREER : LeaderboardTypes::BREATH;
}
public function setType(string $type): void
{
$this->career = LeaderboardTypes::CAREER === $type;
}
public function getCareer(): bool
{
return $this->career;
}
public function setCareer(bool $career): self
{
$this->career = $career;
return $this;
}
}

View File

@ -4,43 +4,34 @@ declare(strict_types=1);
namespace App\Doctrine\Entity\Nexus;
use App\Contract\Doctrine\Entity\DatedEntityInterface;
use App\Contract\Doctrine\Entity\UuidPrimaryKeyInterface;
use App\Doctrine\Entity\DatedEntityTrait;
use App\Doctrine\Entity\UuidPrimaryKeyTrait;
use App\Doctrine\Repository\Nexus\LeaderboardEntryRepository;
use Doctrine\ORM\Mapping as ORM;
#[
ORM\Entity(repositoryClass: LeaderboardEntryRepository::class),
ORM\Table(name: 'nexus_leaderboard_entry'),
ORM\UniqueConstraint(name: 'nexus_leaderboard_entry_uniq', fields: ['position']),
ORM\Index(fields: ['leaderboard'], name: 'nexus_leaderboard_entry_leaderboard_idx'),
]
class LeaderboardEntry implements UuidPrimaryKeyInterface, DatedEntityInterface
class LeaderboardEntry
{
use UuidPrimaryKeyTrait;
use DatedEntityTrait;
#[
ORM\Id,
ORM\ManyToOne(targetEntity: Leaderboard::class),
ORM\JoinColumn(name: 'leaderboard_id', referencedColumnName: 'id', nullable: false),
]
private ?Leaderboard $leaderboard = null;
#[
ORM\Id,
ORM\Column(name: 'position', type: 'integer', nullable: false),
]
private ?int $position = null;
#[ORM\Column(name: 'character_name', type: 'text', nullable: false)]
private ?string $characterName = null;
#[ORM\Column(name: 'position', type: 'integer', nullable: false)]
private ?int $position = null;
#[ORM\Column(name: 'value', type: 'integer', nullable: false)]
private ?int $value = null;
public function __construct()
{
$this->generateId();
}
#[ORM\Column(name: 'score', type: 'integer', nullable: false)]
private ?int $score = null;
public function getLeaderboard(): ?Leaderboard
{
@ -52,16 +43,6 @@ class LeaderboardEntry implements UuidPrimaryKeyInterface, DatedEntityInterface
$this->leaderboard = $leaderboard;
}
public function getCharacterName(): ?string
{
return $this->characterName;
}
public function setCharacterName(string $characterName): void
{
$this->characterName = $characterName;
}
public function getPosition(): ?int
{
return $this->position;
@ -72,13 +53,23 @@ class LeaderboardEntry implements UuidPrimaryKeyInterface, DatedEntityInterface
$this->position = $position;
}
public function getValue(): ?int
public function getCharacterName(): ?string
{
return $this->value;
return $this->characterName;
}
public function setValue(int $value): void
public function setCharacterName(string $characterName): void
{
$this->value = $value;
$this->characterName = $characterName;
}
public function getScore(): ?int
{
return $this->score;
}
public function setScore(int $score): void
{
$this->score = $score;
}
}

View File

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