From 58d075ee46b9639b042e27dac210e1a1a8d7aa8d Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Thu, 13 Jun 2024 15:15:01 +0200 Subject: [PATCH] refs #423. New table and Endpoint Menu --- config/api_platform/Menu.yaml | 30 +++++ config/api_platform/User.yaml | 1 - config/services.yaml | 5 + migrations/Version20240613090444.php | 43 +++++++ src/Dto/Input/ClientInput.php | 8 ++ src/Dto/Input/MenuInput.php | 69 +++++++++++ src/Dto/Output/ClientOutput.php | 14 ++- src/Dto/Output/HardwareProfileOutput.php | 8 +- src/Dto/Output/MenuOutput.php | 50 ++++++++ src/Dto/Output/NetworkSettingsOutput.php | 8 +- src/Dto/Output/OrganizationalUnitOutput.php | 1 - src/Entity/Client.php | 15 +++ src/Entity/Menu.php | 131 ++++++++++++++++++++ src/Repository/MenuRepository.php | 18 +++ src/State/Processor/MenuProcessor.php | 71 +++++++++++ src/State/Provider/MenuProvider.php | 75 +++++++++++ 16 files changed, 533 insertions(+), 14 deletions(-) create mode 100644 config/api_platform/Menu.yaml create mode 100644 migrations/Version20240613090444.php create mode 100644 src/Dto/Input/MenuInput.php create mode 100644 src/Dto/Output/MenuOutput.php create mode 100644 src/Entity/Menu.php create mode 100644 src/Repository/MenuRepository.php create mode 100644 src/State/Processor/MenuProcessor.php create mode 100644 src/State/Provider/MenuProvider.php diff --git a/config/api_platform/Menu.yaml b/config/api_platform/Menu.yaml new file mode 100644 index 0000000..1fac788 --- /dev/null +++ b/config/api_platform/Menu.yaml @@ -0,0 +1,30 @@ +resources: + App\Entity\Menu: + processor: App\State\Processor\MenuProcessor + input: App\Dto\Input\MenuInput + output: App\Dto\Output\MenuOutput + normalization_context: + groups: ['default', 'menu:read'] + denormalization_context: + groups: ['menu:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\MenuProvider + filters: + - 'api_platform.filter.menu.order' + - 'api_platform.filter.menu.search' + ApiPlatform\Metadata\Get: + provider: App\State\Provider\MenuProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\MenuProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\MenuProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + +properties: + App\Entity\Menu: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/User.yaml b/config/api_platform/User.yaml index 8f58ad6..427c416 100644 --- a/config/api_platform/User.yaml +++ b/config/api_platform/User.yaml @@ -1,6 +1,5 @@ resources: App\Entity\User: - security: 'is_granted("ROLE_SUPER_ADMIN")' input: App\Dto\Input\UserInput output: App\Dto\Output\UserOutput processor: App\State\Processor\UserProcessor diff --git a/config/services.yaml b/config/services.yaml index 124187d..3e2e835 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -51,6 +51,11 @@ services: $itemProvider: '@api_platform.doctrine.orm.state.item_provider' App\State\Provider\HardwareProfileProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\MenuProvider: bind: $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' $itemProvider: '@api_platform.doctrine.orm.state.item_provider' \ No newline at end of file diff --git a/migrations/Version20240613090444.php b/migrations/Version20240613090444.php new file mode 100644 index 0000000..45413e4 --- /dev/null +++ b/migrations/Version20240613090444.php @@ -0,0 +1,43 @@ +addSql('CREATE TABLE menu (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, title VARCHAR(255) NOT NULL, resolution VARCHAR(255) NOT NULL, comments VARCHAR(255) DEFAULT NULL, public_url VARCHAR(255) DEFAULT NULL, private_url VARCHAR(255) DEFAULT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_7D053A93D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE client ADD menu_id INT DEFAULT NULL, CHANGE name name VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE client ADD CONSTRAINT FK_C7440455CCD7E912 FOREIGN KEY (menu_id) REFERENCES menu (id)'); + $this->addSql('CREATE INDEX IDX_C7440455CCD7E912 ON client (menu_id)'); + $this->addSql('ALTER TABLE hardware CHANGE name name VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE organizational_unit CHANGE name name VARCHAR(255) NOT NULL'); + $this->addSql('ALTER TABLE user_group CHANGE name name VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE client DROP FOREIGN KEY FK_C7440455CCD7E912'); + $this->addSql('DROP TABLE menu'); + $this->addSql('ALTER TABLE hardware CHANGE name name VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE user_group CHANGE name name VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE organizational_unit CHANGE name name VARCHAR(255) DEFAULT NULL'); + $this->addSql('DROP INDEX IDX_C7440455CCD7E912 ON client'); + $this->addSql('ALTER TABLE client DROP menu_id, CHANGE name name VARCHAR(255) DEFAULT NULL'); + } +} diff --git a/src/Dto/Input/ClientInput.php b/src/Dto/Input/ClientInput.php index 06938d6..366aa43 100644 --- a/src/Dto/Input/ClientInput.php +++ b/src/Dto/Input/ClientInput.php @@ -4,6 +4,7 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\HardwareProfileOutput; +use App\Dto\Output\MenuOutput; use App\Dto\Output\OrganizationalUnitOutput; use App\Entity\Client; use Symfony\Component\Serializer\Annotation\Groups; @@ -50,6 +51,11 @@ final class ClientInput #[ApiProperty(description: 'The hardware profile of the client')] public ?HardwareProfileOutput $hardwareProfile = null; + #[Assert\NotNull] + #[Groups(['client:write'])] + #[ApiProperty(description: 'The menu of the client')] + public ?MenuOutput $menu = null; + public function __construct(?Client $client = null) { if (!$client) { @@ -61,6 +67,7 @@ final class ClientInput $this->netiface = $client->getNetiface(); $this->organizationalUnit = new OrganizationalUnitOutput($client->getOrganizationalUnit()); $this->hardwareProfile = new HardwareProfileOutput($client->getHardwareProfile()); + $this->menu = new MenuOutput($client->getMenu()); $this->netDriver = $client->getNetDriver(); $this->mac = $client->getMac(); $this->ip = $client->getIp(); @@ -78,6 +85,7 @@ final class ClientInput $client->setNetiface($this->netiface); $client->setOrganizationalUnit($this->organizationalUnit->getEntity()); $client->setHardwareProfile($this->hardwareProfile->getEntity()); + $client->setMenu($this->menu->getEntity()); $client->setNetDriver($this->netDriver); $client->setMac($this->mac); $client->setIp($this->ip); diff --git a/src/Dto/Input/MenuInput.php b/src/Dto/Input/MenuInput.php new file mode 100644 index 0000000..03631ee --- /dev/null +++ b/src/Dto/Input/MenuInput.php @@ -0,0 +1,69 @@ +name = $menu->getName(); + $this->title = $menu->getTitle(); + $this->comments = $menu->getComments(); + $this->resolution = $menu->getResolution(); + $this->publicUrl = $menu->getPublicUrl(); + $this->privateUrl = $menu->getPrivateUrl(); + } + + public function createOrUpdateEntity(?Menu $menu = null): Menu + { + if (!$menu) { + $menu = new Menu(); + } + + $menu->setName($this->name); + $menu->setTitle($this->title); + $menu->setComments($this->comments); + $menu->setResolution($this->resolution); + $menu->setPublicUrl($this->publicUrl); + $menu->setPrivateUrl($this->privateUrl); + + return $menu; + } +} \ No newline at end of file diff --git a/src/Dto/Output/ClientOutput.php b/src/Dto/Output/ClientOutput.php index 6961c0b..34c5b3c 100644 --- a/src/Dto/Output/ClientOutput.php +++ b/src/Dto/Output/ClientOutput.php @@ -25,10 +25,13 @@ final class ClientOutput extends AbstractOutput public ?HardwareProfileOutput $hardwareProfile = null; #[Groups(['client:read'])] - public \DateTime $createAt; + public ?MenuOutput $menu = null; #[Groups(['client:read'])] - public ?string $createBy = null; + public \DateTime $createdAt; + + #[Groups(['client:read'])] + public ?string $createdBy = null; public function __construct(Client $client) { @@ -43,7 +46,10 @@ final class ClientOutput extends AbstractOutput if($client->getHardwareProfile()) { $this->hardwareProfile = new HardwareProfileOutput($client->getHardwareProfile()); } - $this->createAt = $client->getCreatedAt(); - $this->createBy = $client->getCreatedBy(); + if($client->getMenu()) { + $this->menu = new MenuOutput($client->getMenu()); + } + $this->createdAt = $client->getCreatedAt(); + $this->createdBy = $client->getCreatedBy(); } } \ No newline at end of file diff --git a/src/Dto/Output/HardwareProfileOutput.php b/src/Dto/Output/HardwareProfileOutput.php index ed2315d..66a91ce 100644 --- a/src/Dto/Output/HardwareProfileOutput.php +++ b/src/Dto/Output/HardwareProfileOutput.php @@ -19,10 +19,10 @@ final class HardwareProfileOutput extends AbstractOutput public ?OrganizationalUnitOutput $organizationalUnit = null; #[Groups(['hardware-profile:read'])] - public \DateTime $createAt; + public \DateTime $createdAt; #[Groups(['hardware-profile:read'])] - public ?string $createBy = null; + public ?string $createdBy = null; public function __construct(HardwareProfile $hardwareProfile) { @@ -33,7 +33,7 @@ final class HardwareProfileOutput extends AbstractOutput if($hardwareProfile->getOrganizationalUnit()) { $this->organizationalUnit = new OrganizationalUnitOutput($hardwareProfile->getOrganizationalUnit()); } - $this->createAt = $hardwareProfile->getCreatedAt(); - $this->createBy = $hardwareProfile->getCreatedBy(); + $this->createdAt = $hardwareProfile->getCreatedAt(); + $this->createdBy = $hardwareProfile->getCreatedBy(); } } \ No newline at end of file diff --git a/src/Dto/Output/MenuOutput.php b/src/Dto/Output/MenuOutput.php new file mode 100644 index 0000000..0c55133 --- /dev/null +++ b/src/Dto/Output/MenuOutput.php @@ -0,0 +1,50 @@ +name = $menu->getName(); + $this->title = $menu->getTitle(); + $this->resolution = $menu->getResolution(); + $this->comments = $menu->getComments(); + $this->publicUrl = $menu->getPublicUrl(); + $this->privateUrl = $menu->getPrivateUrl(); + $this->createdAt = $menu->getCreatedAt(); + $this->createdBy = $menu->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/NetworkSettingsOutput.php b/src/Dto/Output/NetworkSettingsOutput.php index 082d26b..b1148b9 100644 --- a/src/Dto/Output/NetworkSettingsOutput.php +++ b/src/Dto/Output/NetworkSettingsOutput.php @@ -41,10 +41,10 @@ final class NetworkSettingsOutput public ?string $mcastMode = null; #[Groups(['organizational-unit:read'])] - public \DateTime $createAt; + public \DateTime $createdAt; #[Groups(['organizational-unit:read'])] - public ?string $createBy = null; + public ?string $createdBy = null; public function __construct(NetworkSettings $networkSettings) { @@ -59,7 +59,7 @@ final class NetworkSettingsOutput $this->mcastSpeed = $networkSettings->getMcastSpeed(); $this->mcastPort = $networkSettings->getMcastPort(); $this->mcastMode = $networkSettings->getMcastMode(); - $this->createAt = $networkSettings->getCreatedAt(); - $this->createBy = $networkSettings->getCreatedBy(); + $this->createdAt = $networkSettings->getCreatedAt(); + $this->createdBy = $networkSettings->getCreatedBy(); } } \ No newline at end of file diff --git a/src/Dto/Output/OrganizationalUnitOutput.php b/src/Dto/Output/OrganizationalUnitOutput.php index bb0ee2c..3499bdf 100644 --- a/src/Dto/Output/OrganizationalUnitOutput.php +++ b/src/Dto/Output/OrganizationalUnitOutput.php @@ -36,7 +36,6 @@ final class OrganizationalUnitOutput extends AbstractOutput #[Groups(['organizational-unit:read'])] public ?string $createdBy = null; - public function __construct(OrganizationalUnit $organizationalUnit) { parent::__construct($organizationalUnit); diff --git a/src/Entity/Client.php b/src/Entity/Client.php index 6aba709..f632a8f 100644 --- a/src/Entity/Client.php +++ b/src/Entity/Client.php @@ -34,6 +34,9 @@ class Client extends AbstractEntity #[ORM\ManyToOne(inversedBy: 'clients')] private ?HardwareProfile $hardwareProfile = null; + #[ORM\ManyToOne(inversedBy: 'clients')] + private ?Menu $menu = null; + public function getSerialNumber(): ?string { return $this->serialNumber; @@ -129,4 +132,16 @@ class Client extends AbstractEntity return $this; } + + public function getMenu(): ?Menu + { + return $this->menu; + } + + public function setMenu(?Menu $menu): static + { + $this->menu = $menu; + + return $this; + } } diff --git a/src/Entity/Menu.php b/src/Entity/Menu.php new file mode 100644 index 0000000..a0107cb --- /dev/null +++ b/src/Entity/Menu.php @@ -0,0 +1,131 @@ + + */ + #[ORM\OneToMany(mappedBy: 'menu', targetEntity: Client::class)] + private Collection $clients; + + public function __construct() + { + parent::__construct(); + $this->clients = new ArrayCollection(); + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + public function getResolution(): ?string + { + return $this->resolution; + } + + public function setResolution(string $resolution): static + { + $this->resolution = $resolution; + + return $this; + } + + public function getComments(): ?string + { + return $this->comments; + } + + public function setComments(?string $comments): static + { + $this->comments = $comments; + + return $this; + } + + public function getPublicUrl(): ?string + { + return $this->publicUrl; + } + + public function setPublicUrl(?string $publicUrl): static + { + $this->publicUrl = $publicUrl; + + return $this; + } + + public function getPrivateUrl(): ?string + { + return $this->privateUrl; + } + + public function setPrivateUrl(?string $privateUrl): static + { + $this->privateUrl = $privateUrl; + + return $this; + } + + /** + * @return Collection + */ + public function getClients(): Collection + { + return $this->clients; + } + + public function addClient(Client $client): static + { + if (!$this->clients->contains($client)) { + $this->clients->add($client); + $client->setMenu($this); + } + + return $this; + } + + public function removeClient(Client $client): static + { + if ($this->clients->removeElement($client)) { + // set the owning side to null (unless already changed) + if ($client->getMenu() === $this) { + $client->setMenu(null); + } + } + + return $this; + } +} diff --git a/src/Repository/MenuRepository.php b/src/Repository/MenuRepository.php new file mode 100644 index 0000000..b23f67d --- /dev/null +++ b/src/Repository/MenuRepository.php @@ -0,0 +1,18 @@ + + */ +class MenuRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Menu::class); + } +} diff --git a/src/State/Processor/MenuProcessor.php b/src/State/Processor/MenuProcessor.php new file mode 100644 index 0000000..bc4a911 --- /dev/null +++ b/src/State/Processor/MenuProcessor.php @@ -0,0 +1,71 @@ +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * @throws \Exception + */ + private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): MenuOutput + { + if (!($data instanceof MenuInput)) { + throw new \Exception(sprintf('data is not instance of %s', UserGroupInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->menuRepository->findOneByUuid($uriVariables['uuid']); + } + + $userGroup = $data->createOrUpdateEntity($entity); + $this->validator->validate($userGroup); + $this->menuRepository->save($userGroup); + + return new MenuOutput($userGroup); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->menuRepository->findOneByUuid($uriVariables['uuid']); + $this->menuRepository->delete($user); + + return null; + } +} diff --git a/src/State/Provider/MenuProvider.php b/src/State/Provider/MenuProvider.php new file mode 100644 index 0000000..71359bc --- /dev/null +++ b/src/State/Provider/MenuProvider.php @@ -0,0 +1,75 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new MenuOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('Menu not found'); + } + + return new MenuOutput($item); + } + + public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['uuid'])) { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $item !== null ? new MenuInput($item) : null; + } + + return new MenuInput(); + } +}