From edee27994bd36d363abf6bebe3cfae6dec9541a2 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Tue, 29 Oct 2024 16:57:30 +0100 Subject: [PATCH] refs #1081. API ImageRepository. Edit Image API with this --- config/api_platform/ImageRepository.yaml | 20 ++--- config/api_platform/Partition.yaml | 2 + config/api_platform/SoftwareProfile.yaml | 2 +- config/services.yaml | 5 ++ src/Dto/Input/ImageInput.php | 10 +++ src/Dto/Input/ImageRepositoryInput.php | 82 ++++++------------- src/Dto/Input/PartitionInput.php | 5 +- src/Dto/Output/ImageOutput.php | 4 + src/Dto/Output/ImageRepositoryOutput.php | 32 +++++++- src/Dto/Output/OrganizationalUnitOutput.php | 2 +- src/Repository/ImageRepository.php | 16 +++- src/Repository/ImageRepositoryRepository.php | 18 ++++ .../Processor/ImageRepositoryProcessor.php | 66 ++++++++++++++- .../Provider/ImageRepositoryProvider.php | 71 +++++++++++++++- 14 files changed, 251 insertions(+), 84 deletions(-) create mode 100644 src/Repository/ImageRepositoryRepository.php diff --git a/config/api_platform/ImageRepository.yaml b/config/api_platform/ImageRepository.yaml index 35d8d13..e6cb84c 100644 --- a/config/api_platform/ImageRepository.yaml +++ b/config/api_platform/ImageRepository.yaml @@ -1,31 +1,29 @@ resources: - App\Entity\Repository: - processor: App\State\Processor\RepositoryProcessor - input: App\Dto\Input\RepositoryInput - output: App\Dto\Output\RepositoryOutput - orderBy: - RepositoryNumber: 'ASC' + App\Entity\ImageRepository: + processor: App\State\Processor\ImageRepositoryProcessor + input: App\Dto\Input\ImageRepositoryInput + output: App\Dto\Output\ImageRepositoryOutput normalizationContext: groups: ['default', 'repository:read'] denormalizationContext: groups: ['repository:write'] operations: ApiPlatform\Metadata\GetCollection: - provider: App\State\Provider\RepositoryProvider + provider: App\State\Provider\ImageRepositoryProvider filters: - 'api_platform.filter.repository.order' - 'api_platform.filter.repository.search' ApiPlatform\Metadata\Get: - provider: App\State\Provider\RepositoryProvider + provider: App\State\Provider\ImageRepositoryProvider ApiPlatform\Metadata\Put: - provider: App\State\Provider\RepositoryProvider + provider: App\State\Provider\ImageRepositoryProvider ApiPlatform\Metadata\Patch: - provider: App\State\Provider\RepositoryProvider + provider: App\State\Provider\ImageRepositoryProvider ApiPlatform\Metadata\Post: ~ ApiPlatform\Metadata\Delete: ~ properties: - App\Entity\Repository: + App\Entity\ImageRepository: id: identifier: false uuid: diff --git a/config/api_platform/Partition.yaml b/config/api_platform/Partition.yaml index 7d09114..3103413 100644 --- a/config/api_platform/Partition.yaml +++ b/config/api_platform/Partition.yaml @@ -3,6 +3,8 @@ resources: processor: App\State\Processor\PartitionProcessor input: App\Dto\Input\PartitionInput output: App\Dto\Output\PartitionOutput + orderBy: + partitionNumber: 'ASC' normalizationContext: groups: ['default', 'partition:read'] denormalizationContext: diff --git a/config/api_platform/SoftwareProfile.yaml b/config/api_platform/SoftwareProfile.yaml index 899cad8..ff08333 100644 --- a/config/api_platform/SoftwareProfile.yaml +++ b/config/api_platform/SoftwareProfile.yaml @@ -17,7 +17,7 @@ resources: ApiPlatform\Metadata\Get: provider: App\State\Provider\SoftwareProfileProvider normalizationContext: - groups: ['software-profile:item:get', 'software-profile:read:collection:short'] + groups: ['software-profile:read', 'software-profile:item:get', 'software-profile:read:collection:short'] ApiPlatform\Metadata\Put: provider: App\State\Provider\SoftwareProfileProvider ApiPlatform\Metadata\Patch: diff --git a/config/services.yaml b/config/services.yaml index 294e4b8..62e58a2 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -152,3 +152,8 @@ services: bind: $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\ImageRepositoryProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' diff --git a/src/Dto/Input/ImageInput.php b/src/Dto/Input/ImageInput.php index c1b2e84..b994e9e 100644 --- a/src/Dto/Input/ImageInput.php +++ b/src/Dto/Input/ImageInput.php @@ -4,6 +4,7 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\ClientOutput; +use App\Dto\Output\ImageRepositoryOutput; use App\Dto\Output\OrganizationalUnitOutput; use App\Dto\Output\SoftwareProfileOutput; use App\Entity\Image; @@ -50,6 +51,10 @@ final class ImageInput #[ApiProperty(description: 'The software profile of the image')] public ?SoftwareProfileOutput $softwareProfile = null; + #[Groups(['image:write'])] + #[ApiProperty(description: 'The image repository of the image')] + public ?ImageRepositoryOutput $imageRepository = null; + #[Groups(['image:write'])] public ?bool $remotePc = false; @@ -72,6 +77,10 @@ final class ImageInput if ($image->getSoftwareProfile()) { $this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile()); } + + if ($image->getRepository()) { + $this->imageRepository = new ImageRepositoryOutput($image->getRepository()); + } } public function createOrUpdateEntity(?Image $image = null): Image @@ -89,6 +98,7 @@ final class ImageInput $image->setInfo($this->info); $image->setSize($this->size); $image->setSoftwareProfile($this->softwareProfile->getEntity()); + $image->setRepository($this->imageRepository->getEntity()); $image->setRemotePc($this->remotePc); return $image; diff --git a/src/Dto/Input/ImageRepositoryInput.php b/src/Dto/Input/ImageRepositoryInput.php index a7b4166..e2ea309 100644 --- a/src/Dto/Input/ImageRepositoryInput.php +++ b/src/Dto/Input/ImageRepositoryInput.php @@ -8,81 +8,49 @@ use App\Dto\Output\ImageOutput; use App\Dto\Output\OperativeSystemOutput; use App\Dto\Output\OrganizationalUnitOutput; use App\Entity\HardwareProfile; +use App\Entity\ImageRepository; use App\Entity\Menu; use App\Entity\Partition; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -final class RepositoryInput +final class ImageRepositoryInput { - #[Groups(['partition:write'])] - #[ApiProperty(description: 'The disk number of the partition', example: 1)] - public ?int $diskNumber = null; + #[Groups(['repository:write'])] + #[ApiProperty(description: 'The name of the repository', example: "Repository 1")] + public ?string $name = null; - #[Groups(['partition:write'])] - #[ApiProperty(description: 'The number of the partition', example: 1)] - public ?int $partitionNumber = null; - - #[Groups(['partition:write'])] - #[ApiProperty(description: 'The code of the partition', example: "code")] - public ?string $partitionCode = null; - - #[Assert\NotNull()] - #[Groups(['partition:write'])] - #[ApiProperty(description: 'The size of the partition', example: 100)] - public ?int $size = null; + #[Groups(['repository:write'])] + #[ApiProperty(description: 'The IP of the repository', example: "")] + public ?string $ip = null; - public function __construct(?Repository $partition = null) + #[Groups(['repository:write'])] + #[ApiProperty(description: 'The comments of the repository', example: "Repository 1 comments")] + public ?string $comments = null; + + + public function __construct(?ImageRepository $repository = null) { - if (!$partition) { + if (!$repository) { return; } - $this->diskNumber = $partition->getDiskNumber(); - $this->partitionNumber = $partition->getPartitionNumber(); - $this->partitionCode = $partition->getPartitionCode(); - $this->size = $partition->getSize(); - $this->cacheContent = $partition->getCacheContent(); - $this->filesystem = $partition->getFilesystem(); - - if ($partition->getOperativeSystem()) { - $this->operativeSystem = new OperativeSystemOutput($partition->getOperativeSystem()); - } - - if ($partition->getClient()) { - $this->client = new ClientOutput($partition->getClient()); - } - $this->memoryUsage = $partition->getMemoryUsage(); - - if ($partition->getImage()) { - $this->image = new ImageOutput($partition->getImage()); - } + $this->name = $repository->getName(); + $this->ip = $repository->getIp(); + $this->comments = $repository->getComments(); } - public function createOrUpdateEntity(?Partition $partition = null): Partition + public function createOrUpdateEntity(?ImageRepository $repository = null): ImageRepository { - if (!$partition) { - $partition = new Partition(); + if (!$repository) { + $repository = new ImageRepository(); } - $partition->setDiskNumber($this->diskNumber); - $partition->setPartitionNumber($this->partitionNumber); - $partition->setPartitionCode($this->partitionCode); - $partition->setSize($this->size * 1024); - $partition->setCacheContent($this->cacheContent); - $partition->setFilesystem($this->filesystem); + $repository->setName($this->name); + $repository->setIp($this->ip); + $repository->setComments($this->comments); - if ($this->operativeSystem) { - $partition->setOperativeSystem($this->operativeSystem->getEntity()); - } - $partition->setClient($this->client->getEntity()); - $partition->setMemoryUsage($this->memoryUsage * 100); - - if ($this->image) { - $partition->setImage($this->image->getEntity()); - } - - return $partition; + return $repository; } } \ No newline at end of file diff --git a/src/Dto/Input/PartitionInput.php b/src/Dto/Input/PartitionInput.php index 2e7d366..635149f 100644 --- a/src/Dto/Input/PartitionInput.php +++ b/src/Dto/Input/PartitionInput.php @@ -101,10 +101,7 @@ final class PartitionInput $partition->setOperativeSystem($this->operativeSystem->getEntity()); } $partition->setClient($this->client->getEntity()); - - if ($this->memoryUsage) { - $partition->setMemoryUsage($this->memoryUsage * 100); - } + $partition->setMemoryUsage($this->memoryUsage * 100); if ($this->image) { $partition->setImage($this->image->getEntity()); diff --git a/src/Dto/Output/ImageOutput.php b/src/Dto/Output/ImageOutput.php index fe91429..6569676 100644 --- a/src/Dto/Output/ImageOutput.php +++ b/src/Dto/Output/ImageOutput.php @@ -39,6 +39,9 @@ final class ImageOutput extends AbstractOutput #[Groups(['image:read'])] public ?SoftwareProfileOutput $softwareProfile = null; + #[Groups(['image:read'])] + public ?ImageRepositoryOutput $imageRepository = null; + #[Groups(['image:read'])] public \DateTime $createdAt; @@ -58,6 +61,7 @@ final class ImageOutput extends AbstractOutput $this->info = $image->getInfo(); $this->size = $image->getSize(); $this->softwareProfile = $image->getSoftwareProfile() ? new SoftwareProfileOutput($image->getSoftwareProfile()) : null; + $this->imageRepository = $image->getRepository() ? new ImageRepositoryOutput($image->getRepository()) : null; $this->remotePc = $image->isRemotePc(); $this->createdAt = $image->getCreatedAt(); $this->createdBy = $image->getCreatedBy(); diff --git a/src/Dto/Output/ImageRepositoryOutput.php b/src/Dto/Output/ImageRepositoryOutput.php index 1ede3f3..a940da1 100644 --- a/src/Dto/Output/ImageRepositoryOutput.php +++ b/src/Dto/Output/ImageRepositoryOutput.php @@ -2,7 +2,37 @@ namespace App\Dto\Output; -class ImageRepositoryOutput +use ApiPlatform\Metadata\Get; +use App\Entity\ImageRepository; +use Symfony\Component\Serializer\Annotation\Groups; + +#[Get(shortName: 'ImageRepository')] +class ImageRepositoryOutput extends AbstractOutput { + #[Groups(['repository:read', 'image:read'])] + public ?string $name = ''; + + #[Groups(['repository:read'])] + public ?string $ip = ''; + + #[Groups(['repository:read'])] + public ?string $comments = ''; + + #[Groups(['repository:read'])] + public \DateTime $createdAt; + + #[Groups(['repository:read'])] + public ?string $createdBy = null; + + public function __construct(ImageRepository $imageRepository) + { + parent::__construct($imageRepository); + + $this->name = $imageRepository->getName(); + $this->ip = $imageRepository->getIp(); + $this->comments = $imageRepository->getComments(); + $this->createdAt = $imageRepository->getCreatedAt(); + $this->createdBy = $imageRepository->getCreatedBy(); + } } \ No newline at end of file diff --git a/src/Dto/Output/OrganizationalUnitOutput.php b/src/Dto/Output/OrganizationalUnitOutput.php index 9d9ca7c..f1daa30 100644 --- a/src/Dto/Output/OrganizationalUnitOutput.php +++ b/src/Dto/Output/OrganizationalUnitOutput.php @@ -11,7 +11,7 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'OrganizationalUnit')] final class OrganizationalUnitOutput extends AbstractOutput { - #[Groups(['organizational-unit:read', "client:read", "user:read", 'organizational-unit:read:collection:short'])] + #[Groups(['organizational-unit:read', "client:read", "user:read", 'organizational-unit:read:collection:short', 'software-profile:read'])] public string $name; #[Groups(['organizational-unit:read'])] diff --git a/src/Repository/ImageRepository.php b/src/Repository/ImageRepository.php index 3e6ea6c..b20b95b 100644 --- a/src/Repository/ImageRepository.php +++ b/src/Repository/ImageRepository.php @@ -2,7 +2,17 @@ namespace App\Repository; -class ImageRepository -{ +use App\Entity\Image; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\Persistence\ManagerRegistry; -} \ No newline at end of file +/** + * @extends ServiceEntityRepository + */ +class ImageRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Image::class); + } +} diff --git a/src/Repository/ImageRepositoryRepository.php b/src/Repository/ImageRepositoryRepository.php new file mode 100644 index 0000000..ba83114 --- /dev/null +++ b/src/Repository/ImageRepositoryRepository.php @@ -0,0 +1,18 @@ + + */ +class ImageRepositoryRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, ImageRepository::class); + } +} diff --git a/src/State/Processor/ImageRepositoryProcessor.php b/src/State/Processor/ImageRepositoryProcessor.php index a3afb03..a107ce7 100644 --- a/src/State/Processor/ImageRepositoryProcessor.php +++ b/src/State/Processor/ImageRepositoryProcessor.php @@ -2,7 +2,67 @@ namespace App\State\Processor; -class ImageRepositoryProcessor -{ +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Operation; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use ApiPlatform\Metadata\Put; +use ApiPlatform\State\ProcessorInterface; +use ApiPlatform\Validator\ValidatorInterface; +use App\Dto\Input\ImageRepositoryInput; +use App\Dto\Output\ImageRepositoryOutput; +use App\Repository\ImageRepositoryRepository; -} \ No newline at end of file +readonly class ImageRepositoryProcessor implements ProcessorInterface +{ + public function __construct( + private ImageRepositoryRepository $imageRepository, + private ValidatorInterface $validator + ) + { + } + + /** + * @throws \Exception + */ + public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): ImageRepositoryOutput|null + { + switch ($operation){ + case $operation instanceof Post: + case $operation instanceof Put: + case $operation instanceof Patch: + return $this->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 = []): ImageRepositoryOutput + { + if (!($data instanceof ImageRepositoryInput)) { + throw new \Exception(sprintf('data is not instance of %s', ImageRepositoryInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->imageRepository->findOneByUuid($uriVariables['uuid']); + } + + $repository = $data->createOrUpdateEntity($entity); + $this->validator->validate($repository); + $this->imageRepository->save($repository); + + return new ImageRepositoryOutput($repository); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->imageRepository->findOneByUuid($uriVariables['uuid']); + $this->imageRepository->delete($user); + + return null; + } +} diff --git a/src/State/Provider/ImageRepositoryProvider.php b/src/State/Provider/ImageRepositoryProvider.php index 8ae18b3..4230b45 100644 --- a/src/State/Provider/ImageRepositoryProvider.php +++ b/src/State/Provider/ImageRepositoryProvider.php @@ -2,7 +2,72 @@ namespace App\State\Provider; -class ImageRepositoryProvider -{ +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Operation; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Put; +use ApiPlatform\State\Pagination\TraversablePaginator; +use ApiPlatform\State\ProviderInterface; +use App\Dto\Input\ImageInput; +use App\Dto\Input\ImageRepositoryInput; +use App\Dto\Output\ImageOutput; +use App\Dto\Output\ImageRepositoryOutput; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -} \ No newline at end of file +readonly class ImageRepositoryProvider implements ProviderInterface +{ + public function __construct( + private ProviderInterface $collectionProvider, + private ProviderInterface $itemProvider + ) + { + } + + public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + switch ($operation){ + case $operation instanceof GetCollection: + return $this->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 ImageRepositoryOutput($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('Image not found'); + } + + return new ImageRepositoryOutput($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 ImageRepositoryInput($item) : null; + } + + return new ImageRepositoryInput(); + } +}