3 Commity 5c18d25e00 ... 000715182f

Autor SHA1 Wiadomość Data
  olinox14 000715182f add GalaxyFactory service (skeleton) 2 miesięcy temu
  olinox14 b66e52c01b complete entities relations 2 miesięcy temu
  olinox14 a29aae32b3 Configures EasyAdmin for core entities 2 miesięcy temu

+ 14 - 2
api/src/Controller/Admin/DashboardController.php

@@ -13,7 +13,10 @@ class DashboardController extends AbstractDashboardController
 {
     public function index(): Response
     {
-        return parent::index();
+        // Redirect to Games CRUD index by default
+        $adminUrlGenerator = $this->container->get(\EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator::class);
+        $url = $adminUrlGenerator->setController(\App\Controller\Admin\GameCrudController::class)->generateUrl();
+        return $this->redirect($url);
 
         // Option 1. You can make your dashboard redirect to some common page of your backend
         //
@@ -45,6 +48,15 @@ class DashboardController extends AbstractDashboardController
     public function configureMenuItems(): iterable
     {
         yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
-        // yield MenuItem::linkToCrud('The Label', 'fas fa-list', EntityClass::class);
+        yield MenuItem::section('Game Management');
+        yield MenuItem::linkToCrud('Games', 'fas fa-gamepad', \App\Entity\Game::class);
+        yield MenuItem::section('Universe');
+        yield MenuItem::linkToCrud('Galaxies', 'fas fa-galactic-republic', \App\Entity\Galaxy::class);
+        yield MenuItem::linkToCrud('Sectors', 'fas fa-project-diagram', \App\Entity\Sector::class);
+        yield MenuItem::linkToCrud('Systems', 'fas fa-sun', \App\Entity\System::class);
+        yield MenuItem::linkToCrud('Planets', 'fas fa-globe', \App\Entity\Planet::class);
+        yield MenuItem::section('Accounts');
+        yield MenuItem::linkToCrud('Users', 'fas fa-user', \App\Entity\User::class);
+        yield MenuItem::linkToCrud('Players', 'fas fa-users', \App\Entity\Player::class);
     }
 }

+ 24 - 0
api/src/Controller/Admin/GalaxyCrudController.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\Galaxy;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+
+class GalaxyCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return Galaxy::class;
+    }
+
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id')->onlyOnIndex(),
+            TextField::new('name'),
+        ];
+    }
+}

+ 42 - 0
api/src/Controller/Admin/GameCrudController.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\Game;
+use App\Enum\GameStatusEnum;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+
+class GameCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return Game::class;
+    }
+
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id')->onlyOnIndex(),
+            TextField::new('name'),
+            ChoiceField::new('status')->setChoices($this->enumChoices(GameStatusEnum::class))->renderAsBadges(),
+            DateTimeField::new('openedAt')->setFormTypeOptions(['html5' => true, 'widget' => 'single_text'])->hideOnIndex(),
+        ];
+    }
+
+    /**
+     * @param class-string $enumClass
+     * @return array<string, string>
+     */
+    private function enumChoices(string $enumClass): array
+    {
+        $choices = [];
+        foreach ($enumClass::cases() as $case) {
+            $choices[$case->name] = $case;
+        }
+        return $choices;
+    }
+}

+ 44 - 0
api/src/Controller/Admin/PlanetCrudController.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\Planet;
+use App\Enum\CelestialBodySizeEnum;
+use App\Enum\PlanetTypeEnum;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+
+class PlanetCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return Planet::class;
+    }
+
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id')->onlyOnIndex(),
+            TextField::new('name'),
+            ChoiceField::new('type')->setChoices($this->enumChoices(PlanetTypeEnum::class))->renderAsBadges(),
+            IntegerField::new('position'),
+            ChoiceField::new('size')->setChoices($this->enumChoices(CelestialBodySizeEnum::class))->renderAsBadges(),
+        ];
+    }
+
+    /**
+     * @param class-string $enumClass
+     * @return array<string, string>
+     */
+    private function enumChoices(string $enumClass): array
+    {
+        $choices = [];
+        foreach ($enumClass::cases() as $case) {
+            $choices[$case->name] = $case;
+        }
+        return $choices;
+    }
+}

+ 50 - 0
api/src/Controller/Admin/PlayerCrudController.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\Player;
+use App\Enum\CareerEnum;
+use App\Enum\PlayerStatusEnum;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+
+class PlayerCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return Player::class;
+    }
+
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id')->onlyOnIndex(),
+            AssociationField::new('user'),
+            AssociationField::new('game'),
+            TextField::new('name'),
+            ChoiceField::new('career')->setChoices($this->enumChoices(CareerEnum::class))->renderAsBadges(),
+            DateTimeField::new('joinedAt')->setFormTypeOptions(['html5' => true, 'widget' => 'single_text'])->hideOnIndex(),
+            ChoiceField::new('status')->setChoices($this->enumChoices(PlayerStatusEnum::class))->renderAsBadges(),
+            IntegerField::new('score')->hideOnIndex(),
+            DateTimeField::new('lastPlayedAt')->setFormTypeOptions(['html5' => true, 'widget' => 'single_text'])->hideOnIndex(),
+        ];
+    }
+
+    /**
+     * @param class-string $enumClass
+     * @return array<string, string>
+     */
+    private function enumChoices(string $enumClass): array
+    {
+        $choices = [];
+        foreach ($enumClass::cases() as $case) {
+            $choices[$case->name] = $case;
+        }
+        return $choices;
+    }
+}

+ 43 - 0
api/src/Controller/Admin/SectorCrudController.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\Sector;
+use App\Enum\SectorStatusEnum;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+
+class SectorCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return Sector::class;
+    }
+
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id')->onlyOnIndex(),
+            TextField::new('name'),
+            ChoiceField::new('status')
+                ->setChoices($this->enumChoices(SectorStatusEnum::class))
+                ->renderExpanded(false)
+                ->renderAsBadges(),
+        ];
+    }
+
+    /**
+     * @param class-string $enumClass
+     * @return array<string, string>
+     */
+    private function enumChoices(string $enumClass): array
+    {
+        $choices = [];
+        foreach ($enumClass::cases() as $case) {
+            $choices[$case->name] = $case;
+        }
+        return $choices;
+    }
+}

+ 44 - 0
api/src/Controller/Admin/SystemCrudController.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\System;
+use App\Enum\CelestialBodySizeEnum;
+use App\Enum\StarTypeEnum;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+
+class SystemCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return System::class;
+    }
+
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id')->onlyOnIndex(),
+            TextField::new('name'),
+            ChoiceField::new('starType')->setChoices($this->enumChoices(StarTypeEnum::class))->renderAsBadges(),
+            ChoiceField::new('starSize')->setChoices($this->enumChoices(CelestialBodySizeEnum::class))->renderAsBadges(),
+            IntegerField::new('asteroidBeltPosition'),
+        ];
+    }
+
+    /**
+     * @param class-string $enumClass
+     * @return array<string, string>
+     */
+    private function enumChoices(string $enumClass): array
+    {
+        $choices = [];
+        foreach ($enumClass::cases() as $case) {
+            $choices[$case->name] = $case;
+        }
+        return $choices;
+    }
+}

+ 27 - 0
api/src/Controller/Admin/UserCrudController.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\User;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+
+class UserCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return User::class;
+    }
+
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id')->onlyOnIndex(),
+            TextField::new('username'),
+            EmailField::new('email'),
+            TextField::new('password')->hideOnIndex(),
+        ];
+    }
+}

+ 37 - 2
api/src/Entity/Galaxy.php

@@ -24,6 +24,10 @@ class Galaxy
     #[ORM\OneToMany(targetEntity: Sector::class, mappedBy: 'galaxy', orphanRemoval: true)]
     private Collection $sectors;
 
+    #[ORM\OneToOne(inversedBy: 'galaxy', targetEntity: Game::class)]
+    #[ORM\JoinColumn(nullable: true)]
+    private ?Game $game = null;
+
     public function __construct()
     {
         $this->sectors = new ArrayCollection();
@@ -56,9 +60,40 @@ class Galaxy
         return $this->sectors;
     }
 
-    public function setSectors(Collection $sectors): self
+    public function addSector(Sector $sector): self
+    {
+        if (!$this->sectors->contains($sector)) {
+            $this->sectors->add($sector);
+            $sector->setGalaxy($this);
+        }
+
+        return $this;
+    }
+
+    public function removeSector(Sector $sector): self
+    {
+        if ($this->sectors->removeElement($sector)) {
+            // Set the owning side to null (unless already changed)
+            if ($sector->getGalaxy() === $this) {
+                $sector->setGalaxy(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getGame(): ?Game
+    {
+        return $this->game;
+    }
+
+    public function setGame(?Game $game): self
     {
-        $this->sectors = $sectors;
+        $this->game = $game;
+        // ensure inverse side is synced
+        if ($game && $game->getGalaxy() !== $this) {
+            $game->setGalaxy($this);
+        }
         return $this;
     }
 }

+ 18 - 0
api/src/Entity/Planet.php

@@ -24,6 +24,10 @@ class Planet
     #[ORM\Column(length: 100, nullable: false)]
     private string $name;
 
+    #[ORM\ManyToOne(targetEntity: System::class, inversedBy: 'planets')]
+    #[ORM\JoinColumn(nullable: true)]
+    private ?System $system = null;
+
     #[ORM\Column(length: 24, enumType: PlanetTypeEnum::class, options: ['default' => PlanetTypeEnum::UNINHABITABLE])]
     private PlanetTypeEnum $type;
 
@@ -56,6 +60,20 @@ class Planet
         return $this;
     }
 
+    public function getSystem(): ?System
+    {
+        return $this->system;
+    }
+
+    public function setSystem(?System $system): self
+    {
+        $this->system = $system;
+        if ($system && !$system->getPlanets()->contains($this)) {
+            $system->addPlanet($this);
+        }
+        return $this;
+    }
+
     public function getType(): PlanetTypeEnum
     {
         return $this->type;

+ 4 - 4
api/src/Entity/Player.php

@@ -20,11 +20,11 @@ class Player
     #[ORM\Column]
     private ?int $id = null;
 
-    #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'gameParticipations')]
+    #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'players')]
     #[ORM\JoinColumn(nullable: false)]
     private User $user;
 
-    #[ORM\ManyToOne(targetEntity: Game::class, inversedBy: 'gameParticipations')]
+    #[ORM\ManyToOne(targetEntity: Game::class, inversedBy: 'players')]
     #[ORM\JoinColumn(nullable: false)]
     private Game $game;
 
@@ -111,12 +111,12 @@ class Player
         return $this;
     }
 
-    public function getStatus(): string
+    public function getStatus(): PlayerStatusEnum
     {
         return $this->status;
     }
 
-    public function setStatus(string $status): self
+    public function setStatus(PlayerStatusEnum $status): self
     {
         $this->status = $status;
         return $this;

+ 37 - 0
api/src/Entity/Sector.php

@@ -27,6 +27,10 @@ class Sector
     #[ORM\OneToMany(targetEntity: System::class, mappedBy: 'sector', orphanRemoval: true)]
     private Collection $systems;
 
+    #[ORM\ManyToOne(targetEntity: Galaxy::class, inversedBy: 'sectors')]
+    #[ORM\JoinColumn(nullable: true)]
+    private ?Galaxy $galaxy = null;
+
     #[ORM\Column(length: 24, enumType: SectorStatusEnum::class, options: ['default' => SectorStatusEnum::UNEXPLORED])]
     private SectorStatusEnum $status = SectorStatusEnum::UNEXPLORED;
 
@@ -68,6 +72,39 @@ class Sector
         return $this;
     }
 
+    public function addSystem(System $system): self
+    {
+        if (!$this->systems->contains($system)) {
+            $this->systems->add($system);
+            $system->setSector($this);
+        }
+        return $this;
+    }
+
+    public function removeSystem(System $system): self
+    {
+        if ($this->systems->removeElement($system)) {
+            if ($system->getSector() === $this) {
+                $system->setSector(null);
+            }
+        }
+        return $this;
+    }
+
+    public function getGalaxy(): ?Galaxy
+    {
+        return $this->galaxy;
+    }
+
+    public function setGalaxy(?Galaxy $galaxy): self
+    {
+        $this->galaxy = $galaxy;
+        if ($galaxy && !$galaxy->getSectors()->contains($this)) {
+            $galaxy->addSector($this);
+        }
+        return $this;
+    }
+
     public function getStatus(): SectorStatusEnum
     {
         return $this->status;

+ 37 - 0
api/src/Entity/System.php

@@ -28,6 +28,10 @@ class System
     #[ORM\OneToMany(targetEntity: Planet::class, mappedBy: 'system', orphanRemoval: true)]
     private Collection $planets;
 
+    #[ORM\ManyToOne(targetEntity: Sector::class, inversedBy: 'systems')]
+    #[ORM\JoinColumn(nullable: true)]
+    private ?Sector $sector = null;
+
     #[ORM\Column(length: 20, enumType: StarTypeEnum::class, options: ['default' => StarTypeEnum::RED_DWARF])]
     private StarTypeEnum $starType = StarTypeEnum::RED_DWARF;
 
@@ -76,6 +80,39 @@ class System
         return $this;
     }
 
+    public function addPlanet(Planet $planet): self
+    {
+        if (!$this->planets->contains($planet)) {
+            $this->planets->add($planet);
+            $planet->setSystem($this);
+        }
+        return $this;
+    }
+
+    public function removePlanet(Planet $planet): self
+    {
+        if ($this->planets->removeElement($planet)) {
+            if ($planet->getSystem() === $this) {
+                $planet->setSystem(null);
+            }
+        }
+        return $this;
+    }
+
+    public function getSector(): ?Sector
+    {
+        return $this->sector;
+    }
+
+    public function setSector(?Sector $sector): self
+    {
+        $this->sector = $sector;
+        if ($sector && !$sector->getSystems()->contains($this)) {
+            $sector->addSystem($this);
+        }
+        return $this;
+    }
+
     public function getStarType(): StarTypeEnum
     {
         return $this->starType;

+ 28 - 0
api/src/Services/GalaxyFactory.php

@@ -0,0 +1,28 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Services;
+
+use App\Entity\Galaxy;
+use App\Entity\Sector;
+
+class GalaxyFactory
+{
+    public function createGalaxy(int $nbSectors = 1000): Galaxy
+    {
+        $galaxy = new Galaxy();
+
+        for ($i = 0; $i < $nbSectors; $i++) {
+            $sector = $this->createSector();
+            $galaxy->addSector($sector);
+        }
+
+        return $galaxy;
+    }
+
+    protected function createSector(): Sector {
+        $sector = new Sector();
+
+        return $sector;
+    }
+}

+ 3 - 2
docker/api/Dockerfile

@@ -1,11 +1,12 @@
 FROM php:8.2.27-apache
 
 RUN apt-get update && apt-get install -y --fix-missing \
-    apt-utils build-essential xorg wget bash gnupg zip nano git;
+    apt-utils build-essential xorg wget bash gnupg zip nano git libicu-dev;
 
 COPY /docker/api/vhost.conf /etc/apache2/sites-available/vhost.conf
 
-RUN docker-php-ext-install pdo pdo_mysql
+RUN docker-php-ext-configure intl \
+    && docker-php-ext-install pdo pdo_mysql intl
 
 RUN a2ensite vhost.conf; \
     a2enmod rewrite; \