From 7ff5c87884189d2b6c4c17ab1f71e5914f65a407 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Wed, 12 Feb 2025 17:14:39 +0100 Subject: [PATCH] refs #1472. Changes in images and imageRepo --- config/api_platform/Image.yaml | 61 ------ config/api_platform/ImageImageRepository.yaml | 92 +++++++++ config/services.yaml | 5 + config/services/api_platform.yaml | 14 +- migrations/Version20250211073126.php | 35 ++++ migrations/Version20250211073801.php | 35 ++++ migrations/Version20250211081319.php | 33 ++++ migrations/Version20250211081406.php | 33 ++++ migrations/Version20250211103630.php | 31 +++ migrations/Version20250211105319.php | 31 +++ migrations/Version20250211162339.php | 31 +++ migrations/Version20250211164155.php | 33 ++++ src/Controller/DeployImageAction.php | 4 +- src/Controller/OgAgent/CreateImageAction.php | 13 +- src/Controller/OgAgent/DeployImageAction.php | 7 +- .../OgAgent/Webhook/ClientsController.php | 43 ++-- .../Image/CreateAuxFilesAction.php | 21 +- .../Image/DeletePermanentAction.php | 11 +- .../OgRepository/Image/DeleteTrashAction.php | 23 ++- .../OgRepository/Image/DeployImageAction.php | 3 +- .../OgRepository/Image/GetAction.php | 22 +-- .../OgRepository/Image/RecoverAction.php | 11 +- .../OgRepository/Image/TransferAction.php | 6 +- src/Controller/OgRepository/StatusAction.php | 2 +- .../Webhook/ResponseController.php | 13 +- src/Dto/Input/DeleteImageInput.php | 13 ++ src/Dto/Input/DeployImageInput.php | 27 ++- src/Dto/Input/ImageImageRepositoryInput.php | 44 +++++ src/Dto/Input/ImageInput.php | 39 ++-- src/Dto/Output/ImageImageRepositoryOutput.php | 49 +++++ src/Dto/Output/ImageOutput.php | 40 +--- src/Dto/Output/ImageRepositoryOutput.php | 8 +- src/Dto/Output/MenuOutput.php | 2 +- src/Entity/Image.php | 187 +++++------------- src/Entity/ImageImageRepository.php | 90 +++++++++ src/Entity/ImageRepository.php | 36 +++- src/Factory/ImageFactory.php | 2 - .../ImageImageRepositoryRepository.php | 18 ++ .../ImageImageRepositoryProcessor.php | 68 +++++++ src/State/Processor/ImageProcessor.php | 2 + .../Provider/ImageImageRepositoryProvider.php | 56 ++++++ .../Provider/ImageRepositoryProvider.php | 22 ++- 42 files changed, 947 insertions(+), 369 deletions(-) create mode 100644 config/api_platform/ImageImageRepository.yaml create mode 100644 migrations/Version20250211073126.php create mode 100644 migrations/Version20250211073801.php create mode 100644 migrations/Version20250211081319.php create mode 100644 migrations/Version20250211081406.php create mode 100644 migrations/Version20250211103630.php create mode 100644 migrations/Version20250211105319.php create mode 100644 migrations/Version20250211162339.php create mode 100644 migrations/Version20250211164155.php create mode 100644 src/Dto/Input/DeleteImageInput.php create mode 100644 src/Dto/Input/ImageImageRepositoryInput.php create mode 100644 src/Dto/Output/ImageImageRepositoryOutput.php create mode 100644 src/Entity/ImageImageRepository.php create mode 100644 src/Repository/ImageImageRepositoryRepository.php create mode 100644 src/State/Processor/ImageImageRepositoryProcessor.php create mode 100644 src/State/Provider/ImageImageRepositoryProvider.php diff --git a/config/api_platform/Image.yaml b/config/api_platform/Image.yaml index 589ac13..86e3c04 100644 --- a/config/api_platform/Image.yaml +++ b/config/api_platform/Image.yaml @@ -27,67 +27,6 @@ resources: ApiPlatform\Metadata\Post: ~ ApiPlatform\Metadata\Delete: ~ - get_image_ogrepository: - shortName: OgRepository Server - description: Get image in OgRepository - class: ApiPlatform\Metadata\Get - method: GET - input: false - uriTemplate: /images/server/{uuid}/get - controller: App\Controller\OgRepository\Image\GetAction - - create_aux_files_image_ogrepository: - shortName: OgRepository Server - class: ApiPlatform\Metadata\Post - method: POST - input: false - uriTemplate: /images/server/{uuid}/create-aux-files - controller: App\Controller\OgRepository\Image\CreateAuxFilesAction - - deploy_image_ogrepository: - shortName: OgRepository Server - class: ApiPlatform\Metadata\Post - method: POST - input: App\Dto\Input\DeployImageInput - uriTemplate: /images/{uuid}/deploy-image - controller: App\Controller\DeployImageAction - - trash_delete_image_ogrepository: - shortName: OgRepository Server - description: Delete Image in OgRepository - class: ApiPlatform\Metadata\Post - method: POST - input: false - uriTemplate: /images/server/{uuid}/delete-trash - controller: App\Controller\OgRepository\Image\DeleteTrashAction - - permanent_delete_image_ogrepository: - shortName: OgRepository Server - description: Delete Image in OgRepository - class: ApiPlatform\Metadata\Post - method: POST - input: false - uriTemplate: /images/server/{uuid}/delete-permanent - controller: App\Controller\OgRepository\Image\DeletePermanentAction - - recover_image_ogrepository: - shortName: OgRepository Server - description: Recover Image in OgRepository - class: ApiPlatform\Metadata\Post - method: POST - input: false - uriTemplate: /images/server/{uuid}/recover - controller: App\Controller\OgRepository\Image\RecoverAction - - transfer_image_ogrepository: - shortName: OgRepository Server - description: Export Image in OgRepository - class: ApiPlatform\Metadata\Post - method: POST - input: App\Dto\Input\ExportImportImageRepositoryInput - uriTemplate: /images/{uuid}/transfer-image - controller: App\Controller\OgRepository\Image\TransferAction - properties: App\Entity\Image: id: diff --git a/config/api_platform/ImageImageRepository.yaml b/config/api_platform/ImageImageRepository.yaml new file mode 100644 index 0000000..1d77384 --- /dev/null +++ b/config/api_platform/ImageImageRepository.yaml @@ -0,0 +1,92 @@ +resources: + App\Entity\ImageImageRepository: + processor: App\State\Processor\ImageImageRepositoryProcessor + input: App\Dto\Input\ImageImageRepositoryInput + output: App\Dto\Output\ImageImageRepositoryOutput + normalizationContext: + groups: ['default', 'image-image-repository:read'] + denormalizationContext: + groups: ['image-image-repository:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\ImageImageRepositoryProvider + filters: + - 'api_platform.filter.image_image_repository.order' + - 'api_platform.filter.image_image_repository.search' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\ImageImageRepositoryProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\ImageImageRepositoryProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\ImageImageRepositoryProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + + get_image_ogrepository: + shortName: OgRepository Server + description: Get image in OgRepository + class: ApiPlatform\Metadata\Get + method: GET + input: false + uriTemplate: /image-image-repositories/server/{uuid}/get + controller: App\Controller\OgRepository\Image\GetAction + + create_aux_files_image_ogrepository: + shortName: OgRepository Server + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /image-image-repositories/server/{uuid}/create-aux-files + controller: App\Controller\OgRepository\Image\CreateAuxFilesAction + + deploy_image_ogrepository: + shortName: OgRepository Server + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\DeployImageInput + uriTemplate: /image-image-repositories/{uuid}/deploy-image + controller: App\Controller\DeployImageAction + + trash_delete_image_ogrepository: + shortName: OgRepository Server + description: Delete Image in OgRepository + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /image-image-repositories/server/{uuid}/delete-trash + controller: App\Controller\OgRepository\Image\DeleteTrashAction + + permanent_delete_image_ogrepository: + shortName: OgRepository Server + description: Delete Image in OgRepository + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /image-image-repositories/server/{uuid}/delete-permanent + controller: App\Controller\OgRepository\Image\DeletePermanentAction + + recover_image_ogrepository: + shortName: OgRepository Server + description: Recover Image in OgRepository + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /image-image-repositories/server/{uuid}/recover + controller: App\Controller\OgRepository\Image\RecoverAction + + transfer_image_ogrepository: + shortName: OgRepository Server + description: Export Image in OgRepository + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\ExportImportImageRepositoryInput + uriTemplate: /image-image-repositories/{uuid}/transfer-image + controller: App\Controller\OgRepository\Image\TransferAction + +properties: + App\Entity\ImageImageRepository: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index 0987229..fbf0dc6 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -151,3 +151,8 @@ services: bind: $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\ImageImageRepositoryProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' diff --git a/config/services/api_platform.yaml b/config/services/api_platform.yaml index 5a6cad1..2240693 100644 --- a/config/services/api_platform.yaml +++ b/config/services/api_platform.yaml @@ -191,7 +191,19 @@ services: api_platform.filter.repository.search: parent: 'api_platform.doctrine.orm.search_filter' - arguments: [ { 'id': 'exact', 'name': 'partial'} ] + arguments: [ { 'id': 'exact', 'name': 'partial', 'ip': 'partial', 'status': 'exact'} ] + tags: [ 'api_platform.filter' ] + + api_platform.filter.image_image_repository.order: + parent: 'api_platform.doctrine.orm.order_filter' + arguments: + $properties: { 'id': ~, 'name': ~ } + $orderParameterName: 'order' + tags: [ 'api_platform.filter' ] + + api_platform.filter.image_image_repository.search: + parent: 'api_platform.doctrine.orm.search_filter' + arguments: [ { 'id': 'exact', 'name': 'partial', 'ip': 'partial', 'status': 'exact', 'repository.id': 'exact'} ] tags: [ 'api_platform.filter' ] repository.not_equal_filter: diff --git a/migrations/Version20250211073126.php b/migrations/Version20250211073126.php new file mode 100644 index 0000000..dc6963a --- /dev/null +++ b/migrations/Version20250211073126.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE image_image_repository DROP FOREIGN KEY FK_B785133714C736FC'); + $this->addSql('ALTER TABLE image_image_repository DROP FOREIGN KEY FK_B78513373DA5256D'); + $this->addSql('DROP TABLE image_image_repository'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TABLE image_image_repository (image_id INT NOT NULL, image_repository_id INT NOT NULL, INDEX IDX_B78513373DA5256D (image_id), INDEX IDX_B785133714C736FC (image_repository_id), PRIMARY KEY(image_id, image_repository_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); + $this->addSql('ALTER TABLE image_image_repository ADD CONSTRAINT FK_B785133714C736FC FOREIGN KEY (image_repository_id) REFERENCES image_repository (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE image_image_repository ADD CONSTRAINT FK_B78513373DA5256D FOREIGN KEY (image_id) REFERENCES image (id) ON DELETE CASCADE'); + } +} diff --git a/migrations/Version20250211073801.php b/migrations/Version20250211073801.php new file mode 100644 index 0000000..05ff24c --- /dev/null +++ b/migrations/Version20250211073801.php @@ -0,0 +1,35 @@ +addSql('CREATE TABLE image_image_repository (id INT AUTO_INCREMENT NOT NULL, image_id INT DEFAULT NULL, repository_id INT 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, status VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_B7851337D17F50A6 (uuid), INDEX IDX_B78513373DA5256D (image_id), INDEX IDX_B785133750C9D4F7 (repository_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE image_image_repository ADD CONSTRAINT FK_B78513373DA5256D FOREIGN KEY (image_id) REFERENCES image (id)'); + $this->addSql('ALTER TABLE image_image_repository ADD CONSTRAINT FK_B785133750C9D4F7 FOREIGN KEY (repository_id) REFERENCES image_repository (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image_image_repository DROP FOREIGN KEY FK_B78513373DA5256D'); + $this->addSql('ALTER TABLE image_image_repository DROP FOREIGN KEY FK_B785133750C9D4F7'); + $this->addSql('DROP TABLE image_image_repository'); + } +} diff --git a/migrations/Version20250211081319.php b/migrations/Version20250211081319.php new file mode 100644 index 0000000..d0d0cc8 --- /dev/null +++ b/migrations/Version20250211081319.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE image_image_repository DROP FOREIGN KEY FK_B785133750C9D4F7'); + $this->addSql('ALTER TABLE image_image_repository ADD CONSTRAINT FK_B785133750C9D4F7 FOREIGN KEY (repository_id) REFERENCES image_image_repository (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image_image_repository DROP FOREIGN KEY FK_B785133750C9D4F7'); + $this->addSql('ALTER TABLE image_image_repository ADD CONSTRAINT FK_B785133750C9D4F7 FOREIGN KEY (repository_id) REFERENCES image_repository (id)'); + } +} diff --git a/migrations/Version20250211081406.php b/migrations/Version20250211081406.php new file mode 100644 index 0000000..cfc8c19 --- /dev/null +++ b/migrations/Version20250211081406.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE image_image_repository DROP FOREIGN KEY FK_B785133750C9D4F7'); + $this->addSql('ALTER TABLE image_image_repository ADD CONSTRAINT FK_B785133750C9D4F7 FOREIGN KEY (repository_id) REFERENCES image_repository (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image_image_repository DROP FOREIGN KEY FK_B785133750C9D4F7'); + $this->addSql('ALTER TABLE image_image_repository ADD CONSTRAINT FK_B785133750C9D4F7 FOREIGN KEY (repository_id) REFERENCES image_image_repository (id)'); + } +} diff --git a/migrations/Version20250211103630.php b/migrations/Version20250211103630.php new file mode 100644 index 0000000..9ebe71c --- /dev/null +++ b/migrations/Version20250211103630.php @@ -0,0 +1,31 @@ +addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_IMAGE_REPOSITORY ON image_image_repository (image_id, repository_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP INDEX UNIQ_IDENTIFIER_IMAGE_REPOSITORY ON image_image_repository'); + } +} diff --git a/migrations/Version20250211105319.php b/migrations/Version20250211105319.php new file mode 100644 index 0000000..7f0f7fe --- /dev/null +++ b/migrations/Version20250211105319.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE image_image_repository CHANGE image_id image_id INT NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image_image_repository CHANGE image_id image_id INT DEFAULT NULL'); + } +} diff --git a/migrations/Version20250211162339.php b/migrations/Version20250211162339.php new file mode 100644 index 0000000..8d6053e --- /dev/null +++ b/migrations/Version20250211162339.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE image DROP path, DROP type, DROP revision, DROP info, DROP size, DROP status'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image ADD path VARCHAR(255) DEFAULT NULL, ADD type VARCHAR(255) DEFAULT NULL, ADD revision VARCHAR(255) DEFAULT NULL, ADD info VARCHAR(255) DEFAULT NULL, ADD size INT DEFAULT NULL, ADD status VARCHAR(255) NOT NULL'); + } +} diff --git a/migrations/Version20250211164155.php b/migrations/Version20250211164155.php new file mode 100644 index 0000000..27b81ea --- /dev/null +++ b/migrations/Version20250211164155.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE image DROP created, DROP image_fullsum'); + $this->addSql('ALTER TABLE image_image_repository ADD created TINYINT(1) DEFAULT NULL, ADD image_fullsum VARCHAR(255) DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image_image_repository DROP created, DROP image_fullsum'); + $this->addSql('ALTER TABLE image ADD created TINYINT(1) DEFAULT NULL, ADD image_fullsum VARCHAR(255) DEFAULT NULL'); + } +} diff --git a/src/Controller/DeployImageAction.php b/src/Controller/DeployImageAction.php index a48beec..a586835 100644 --- a/src/Controller/DeployImageAction.php +++ b/src/Controller/DeployImageAction.php @@ -8,6 +8,7 @@ use ApiPlatform\Validator\ValidatorInterface; use App\Dto\Input\DeployImageInput; use App\Entity\Command; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Entity\OrganizationalUnit; use App\Entity\Partition; use App\Model\CommandTypes; @@ -42,7 +43,7 @@ class DeployImageAction extends AbstractController * @throws ClientExceptionInterface * @throws ServerExceptionInterface */ - public function __invoke(DeployImageInput $input, Image $image): JsonResponse + public function __invoke(DeployImageInput $input, ImageImageRepository $image): JsonResponse { $this->validator->validate($input); @@ -68,7 +69,6 @@ class DeployImageAction extends AbstractController case DeployMethodTypes::MULTICAST_UFTP_DIRECT: case DeployMethodTypes::MULTICAST_UDPCAST: case DeployMethodTypes::MULTICAST_UDPCAST_DIRECT: - case DeployMethodTypes::MULTICAST: foreach ($input->clients as $client) { $inputData = [ 'method' => $input->method, diff --git a/src/Controller/OgAgent/CreateImageAction.php b/src/Controller/OgAgent/CreateImageAction.php index a1ad041..55c87a7 100644 --- a/src/Controller/OgAgent/CreateImageAction.php +++ b/src/Controller/OgAgent/CreateImageAction.php @@ -7,6 +7,7 @@ namespace App\Controller\OgAgent; use App\Entity\Client; use App\Entity\Command; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Entity\Trace; use App\Model\ClientStatus; use App\Model\CommandTypes; @@ -55,11 +56,18 @@ class CreateImageAction extends AbstractController $repository = $image->getClient()->getRepository(); + $imageImageRepository = new ImageImageRepository(); + $imageImageRepository->setImage($image); + $imageImageRepository->setRepository($repository); + $imageImageRepository->setStatus(ImageStatus::IN_PROGRESS); + + $this->entityManager->persist($imageImageRepository); + $data = [ 'dsk' => (string) $partitionInfo['numDisk'], 'par' => (string) $partitionInfo['numPartition'], 'cpt' => null, - 'idi' => $image->getUuid(), + 'idi' => $imageImageRepository->getUuid(), 'nci' => $image->getName(), 'ipr' => $repository->getIp(), 'nfn' => 'CrearImagen', @@ -102,9 +110,6 @@ class CreateImageAction extends AbstractController $jobId = json_decode($response->getContent(), true)['job_id']; - $image->setStatus(ImageStatus::IN_PROGRESS); - $this->entityManager->persist($image); - $client = $image->getClient(); $client->setStatus(ClientStatus::BUSY); $this->entityManager->persist($client); diff --git a/src/Controller/OgAgent/DeployImageAction.php b/src/Controller/OgAgent/DeployImageAction.php index a94028b..2a19984 100644 --- a/src/Controller/OgAgent/DeployImageAction.php +++ b/src/Controller/OgAgent/DeployImageAction.php @@ -8,6 +8,7 @@ use App\Dto\Input\DeployImageInput; use App\Entity\Client; use App\Entity\Command; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Entity\Partition; use App\Entity\Trace; use App\Model\ClientStatus; @@ -38,8 +39,10 @@ class DeployImageAction extends AbstractController { } - public function __invoke(Image $image, DeployImageInput $input, Client $client, string $method) + public function __invoke(ImageImageRepository $imageImageRepository, DeployImageInput $input, Client $client, string $method) { + $image = $imageImageRepository->getImage(); + if (!$image->getClient()->getIp()) { throw new ValidatorException('IP is required'); } @@ -69,7 +72,7 @@ class DeployImageAction extends AbstractController default => throw new ValidatorException('Invalid method'), }; - $repository = $client->getRepository(); + $repository = $imageImageRepository->getRepository(); $data = [ 'dsk' => (string) $input->diskNumber, diff --git a/src/Controller/OgAgent/Webhook/ClientsController.php b/src/Controller/OgAgent/Webhook/ClientsController.php index 3a779b4..c6c9573 100644 --- a/src/Controller/OgAgent/Webhook/ClientsController.php +++ b/src/Controller/OgAgent/Webhook/ClientsController.php @@ -4,6 +4,7 @@ namespace App\Controller\OgAgent\Webhook; use App\Controller\OgRepository\Image\CreateAuxFilesAction; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Entity\OperativeSystem; use App\Entity\Partition; use App\Entity\Software; @@ -65,9 +66,10 @@ class ClientsController extends AbstractController if ($data['nfn'] === 'RESPUESTA_CrearImagen') { $trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]); - $image = $this->entityManager->getRepository(Image::class)->findOneBy(['uuid' => $data['idi']]); + /** @var ImageImageRepository $imageImageRepository */ + $imageImageRepository = $this->entityManager->getRepository(ImageImageRepository::class)->findOneBy(['uuid' => $data['idi']]); - if (!$image) { + if (!$imageImageRepository) { $this->logger->error('Image not found', $data); return new JsonResponse(['message' => 'Image not found'], Response::HTTP_NOT_FOUND); } @@ -80,37 +82,41 @@ class ClientsController extends AbstractController if ($data['res'] === 1) { $trace->setStatus(TraceStatus::SUCCESS); $trace->setFinishedAt(new \DateTime()); - $image->setStatus(ImageStatus::AUX_FILES_PENDING); - $image->setCreated(true); - $this->logger->info('Start partition creation. ', ['image' => (string) $image->getUuid()]); + + $imageImageRepository->setStatus(ImageStatus::AUX_FILES_PENDING); + $imageImageRepository->setCreated(true); + + $this->entityManager->persist($imageImageRepository); + + $this->logger->info('Start partition creation. ', ['image' => (string) $imageImageRepository->getUuid()]); if (isset($data['cfg'])) { - $this->createPartitionService->__invoke($data, $image->getClient()); + $this->createPartitionService->__invoke($data, $imageImageRepository->getImage()->getClient()); } - $this->logger->info('Starting software profile creation. ', ['image' => (string) $image->getUuid()]); - $this->createSoftwareProfile($data['inv_sft'], $image); - $this->logger->info('Start aux files ogrepo API ', ['image' => (string) $image->getUuid()]); + $this->logger->info('Starting software profile creation. ', ['image' => (string) $imageImageRepository->getUuid()]); + $this->createSoftwareProfile($data['inv_sft'], $imageImageRepository); + $this->logger->info('Start aux files ogrepo API ', ['image' => (string) $imageImageRepository->getUuid()]); try { - $this->createAuxFilesAction->__invoke($image); + $this->createAuxFilesAction->__invoke($imageImageRepository); } catch (\Exception $e) { - $this->logger->error('Error creating aux files', ['image' => (string) $image->getUuid(), 'error' => $e->getMessage()]); + $this->logger->error('Error creating aux files', ['image' => (string) $imageImageRepository->getUuid(), 'error' => $e->getMessage()]); } - $this->logger->info('End aux files ogrepo API ', ['image' => (string) $image->getUuid()]); + $this->logger->info('End aux files ogrepo API ', ['image' => (string) $imageImageRepository->getUuid()]); } else { $trace->setStatus(TraceStatus::FAILED); $trace->setFinishedAt(new \DateTime()); $trace->setOutput($data['der']); - $image->setCreated(false); - $image->setStatus(ImageStatus::FAILED); + $imageImageRepository->setCreated(false); + $imageImageRepository->setStatus(ImageStatus::FAILED); $this->logger->error('Image updated failed', $data); } - $this->entityManager->persist($image); + $this->entityManager->persist($imageImageRepository); $client = $trace->getClient(); $client->setStatus(ClientStatus::OG_LIVE); $this->entityManager->persist($client); $this->entityManager->persist($trace); $this->entityManager->flush(); - $this->logger->info('Image updated. Success.', ['image' => (string) $image->getUuid()]); + $this->logger->info('Image updated. Success.', ['image' => (string) $imageImageRepository->getUuid()]); } if ($data['nfn'] === 'RESPUESTA_RestaurarImagen'|| $data['nfn'] === 'RESPUESTA_Configurar') { @@ -139,7 +145,7 @@ class ClientsController extends AbstractController return new JsonResponse(data: 'Webhook finished', status: Response::HTTP_OK); } - public function createSoftwareProfile(string $base64Data, Image $image): void + public function createSoftwareProfile(string $base64Data, ImageImageRepository $imageImageRepository): void { $decodedData = base64_decode($base64Data); $this->logger->info('Software profile decoded', ['data' => '']); @@ -156,6 +162,8 @@ class ClientsController extends AbstractController $this->entityManager->persist($softwareEntity); } + $image = $imageImageRepository->getImage(); + $softwareProfile = new SoftwareProfile(); $softwareProfile->setDescription('Perfil software: ' . $image->getClient()->getName()); $softwareProfile->setOrganizationalUnit($image->getClient()->getOrganizationalUnit()); @@ -167,6 +175,7 @@ class ClientsController extends AbstractController $image->setSoftwareProfile($softwareProfile); $this->entityManager->persist($image); + $this->entityManager->persist($imageImageRepository); $this->entityManager->persist($softwareProfile); $this->entityManager->flush(); } diff --git a/src/Controller/OgRepository/Image/CreateAuxFilesAction.php b/src/Controller/OgRepository/Image/CreateAuxFilesAction.php index 33e081c..2f927a1 100644 --- a/src/Controller/OgRepository/Image/CreateAuxFilesAction.php +++ b/src/Controller/OgRepository/Image/CreateAuxFilesAction.php @@ -5,6 +5,7 @@ namespace App\Controller\OgRepository\Image; use App\Controller\OgRepository\AbstractOgRepositoryController; use App\Entity\Command; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Model\CommandTypes; use App\Model\ImageStatus; use App\Model\TraceStatus; @@ -28,34 +29,36 @@ class CreateAuxFilesAction extends AbstractOgRepositoryController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Image $data): JsonResponse + public function __invoke(ImageImageRepository $data): JsonResponse { - if (!$data->getName()) { + $image = $data->getImage(); + + if (!$image->getName()) { throw new ValidatorException('Name is required'); } $params = [ 'json' => [ - 'image' => $data->getName().'.img' + 'image' => $image->getName().'.img' ] ]; - $this->logger->info('Creating aux files', ['image' => $data->getName()]); + $this->logger->info('Creating aux files', ['image' => $image->getName()]); - $repository = $data->getClient()->getRepository(); + $repository = $image->getClient()->getRepository(); $content = $this->createRequest('POST', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/torrentsum', $params); $inputData = [ - 'imageName' => $data->getName(), + 'imageName' => $image->getName(), 'imageUuid' => $data->getUuid(), ]; - $this->createService->__invoke($data->getClient(), CommandTypes::CREATE_IMAGE_AUX_FILE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData); + $this->createService->__invoke($image->getClient(), CommandTypes::CREATE_IMAGE_AUX_FILE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData); - $this->logger->info('Aux files created successfully', ['image' => $data->getName()]); + $this->logger->info('Aux files created successfully', ['image' => $image->getName()]); - $data->setStatus(ImageStatus::IN_PROGRESS); + $data->setStatus(ImageStatus::AUX_FILES_PENDING); $this->entityManager->persist($data); $this->entityManager->flush(); diff --git a/src/Controller/OgRepository/Image/DeletePermanentAction.php b/src/Controller/OgRepository/Image/DeletePermanentAction.php index 4342249..869f4f5 100644 --- a/src/Controller/OgRepository/Image/DeletePermanentAction.php +++ b/src/Controller/OgRepository/Image/DeletePermanentAction.php @@ -4,6 +4,7 @@ namespace App\Controller\OgRepository\Image; use App\Controller\OgRepository\AbstractOgRepositoryController; use App\Entity\Image; +use App\Entity\ImageImageRepository; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Attribute\AsController; @@ -23,19 +24,21 @@ class DeletePermanentAction extends AbstractOgRepositoryController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Image $data, HttpClientInterface $httpClient): JsonResponse + public function __invoke(ImageImageRepository $data, HttpClientInterface $httpClient): JsonResponse { if (!$data->getImageFullsum()) { throw new ValidatorException('Fullsum is required'); } - $this->logger->info('Deleting image', ['image' => $data->getName()]); + $image = $data->getImage(); - $repository = $data->getClient()->getRepository(); + $this->logger->info('Deleting image', ['image' => $image->getName()]); + + $repository = $image->getClient()->getRepository(); $content = $this->createRequest( 'DELETE', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/'.$data->getImageFullsum().'?method=permanent'); - $this->logger->info('Image deleted', ['image' => $data->getName()]); + $this->logger->info('Image deleted', ['image' => $image->getName()]); $this->entityManager->remove($data); $this->entityManager->flush(); diff --git a/src/Controller/OgRepository/Image/DeleteTrashAction.php b/src/Controller/OgRepository/Image/DeleteTrashAction.php index f0f439f..4a370af 100644 --- a/src/Controller/OgRepository/Image/DeleteTrashAction.php +++ b/src/Controller/OgRepository/Image/DeleteTrashAction.php @@ -3,7 +3,10 @@ namespace App\Controller\OgRepository\Image; use App\Controller\OgRepository\AbstractOgRepositoryController; +use App\Dto\Input\DeleteImageInput; use App\Entity\Image; +use App\Entity\ImageImageRepository; +use App\Entity\ImageRepository; use App\Model\ImageStatus; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; @@ -13,7 +16,6 @@ use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface; use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; -use Symfony\Contracts\HttpClient\HttpClientInterface; #[AsController] class DeleteTrashAction extends AbstractOgRepositoryController @@ -24,22 +26,25 @@ class DeleteTrashAction extends AbstractOgRepositoryController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Image $data, HttpClientInterface $httpClient): JsonResponse + public function __invoke(ImageImageRepository $imageImageRepository): JsonResponse { - if (!$data->getImageFullsum()) { + $repository = $imageImageRepository->getRepository(); + $image = $imageImageRepository->getImage(); + + if (!$imageImageRepository->getImageFullsum()) { throw new ValidatorException('Fullsum is required'); } - $this->logger->info('Deleting image', ['image' => $data->getName()]); + $this->logger->info('Deleting image', ['image' => $image->getName()]); - $repository = $data->getClient()->getRepository(); + $repository = $image->getClient()->getRepository(); - $content = $this->createRequest('DELETE', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/'.$data->getImageFullsum().'?method=trash'); + $content = $this->createRequest('DELETE', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/'.$imageImageRepository->getImageFullsum().'?method=trash'); - $this->logger->info('Image deleted', ['image' => $data->getName()]); + $this->logger->info('Image deleted', ['image' => $image->getName()]); - $data->setStatus(ImageStatus::TRASH); - $this->entityManager->persist($data); + $imageImageRepository->setStatus(ImageStatus::TRASH); + $this->entityManager->persist($image); $this->entityManager->flush(); return new JsonResponse(data: $content, status: Response::HTTP_OK); diff --git a/src/Controller/OgRepository/Image/DeployImageAction.php b/src/Controller/OgRepository/Image/DeployImageAction.php index 03e30d1..600163f 100644 --- a/src/Controller/OgRepository/Image/DeployImageAction.php +++ b/src/Controller/OgRepository/Image/DeployImageAction.php @@ -7,6 +7,7 @@ use App\Dto\Input\DeployImageInput; use App\Entity\Client; use App\Entity\Command; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Model\CommandTypes; use App\Model\DeployImageTypes; use App\Model\DeployMethodTypes; @@ -29,7 +30,7 @@ class DeployImageAction extends AbstractOgRepositoryController * @throws ClientExceptionInterface * @throws TransportExceptionInterface */ - public function __invoke(DeployImageInput $input, Image $data, Client $client, HttpClientInterface $httpClient): JsonResponse + public function __invoke(DeployImageInput $input, ImageImageRepository $data, Client $client, HttpClientInterface $httpClient): JsonResponse { $params = [ 'json' => [ diff --git a/src/Controller/OgRepository/Image/GetAction.php b/src/Controller/OgRepository/Image/GetAction.php index 9f6c67d..fbd3626 100644 --- a/src/Controller/OgRepository/Image/GetAction.php +++ b/src/Controller/OgRepository/Image/GetAction.php @@ -4,6 +4,7 @@ namespace App\Controller\OgRepository\Image; use App\Controller\OgRepository\AbstractOgRepositoryController; use App\Entity\Image; +use App\Entity\ImageImageRepository; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Attribute\AsController; @@ -23,30 +24,13 @@ class GetAction extends AbstractOgRepositoryController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Image $data): JsonResponse + public function __invoke(ImageImageRepository $data): JsonResponse { if (!$data->getImageFullsum()) { throw new ValidatorException('Fullsum is required'); } - $content = []; - - foreach ($data->getRepositories() as $repository) { - try { - $response = $this->createRequest('GET', 'http://' . $repository->getIp() . ':8006/ogrepository/v1/images/' . $data->getImageFullsum()); - $content[] = [ - 'repository' => $repository->getIp(), - 'data' => $response - ]; - } catch (\Exception $e) { - $this->logger->error(sprintf('Error en repositorio %s: %s', $repository->getIp(), $e->getMessage())); - $content[] = [ - 'repository' => $repository->getIp(), - 'error' => $e->getMessage(), - 'details' => $e->getMessage() - ]; - } - } + $content = $this->createRequest('GET', 'http://'.$data->getRepository()->getIp().':8006/ogrepository/v1/images/'.$data->getImageFullsum()); return new JsonResponse(data: $content, status: Response::HTTP_OK); } diff --git a/src/Controller/OgRepository/Image/RecoverAction.php b/src/Controller/OgRepository/Image/RecoverAction.php index 5fe0bfc..123aa65 100644 --- a/src/Controller/OgRepository/Image/RecoverAction.php +++ b/src/Controller/OgRepository/Image/RecoverAction.php @@ -5,6 +5,7 @@ namespace App\Controller\OgRepository\Image; use App\Controller\OgRepository\AbstractOgRepositoryController; use App\Dto\Input\DeployImageInput; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Model\CommandTypes; use App\Model\ImageStatus; use App\Model\TraceStatus; @@ -27,25 +28,27 @@ class RecoverAction extends AbstractOgRepositoryController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Image $data, HttpClientInterface $httpClient): JsonResponse + public function __invoke(ImageImageRepository $data, HttpClientInterface $httpClient): JsonResponse { if (!$data->getImageFullsum()) { throw new ValidatorException('Fullsum is required'); } + $image = $data->getImage(); + $params = [ 'json' => [ 'ID_img' => $data->getImageFullsum() ] ]; - $this->logger->info('Recovering image', ['image' => $data->getName()]); + $this->logger->info('Recovering image', ['image' => $image->getName()]); - $repository = $data->getClient()->getRepository(); + $repository = $image->getClient()->getRepository(); $content = $this->createRequest('POST', 'http://'.$repository->getIp().':8006/ogrepository/v1/trash/images', $params); - $this->logger->info('Image recovered successfully', ['image' => $data->getName()]); + $this->logger->info('Image recovered successfully', ['image' => $image->getName()]); $data->setStatus(ImageStatus::SUCCESS); $this->entityManager->persist($data); diff --git a/src/Controller/OgRepository/Image/TransferAction.php b/src/Controller/OgRepository/Image/TransferAction.php index 95a3af0..6a3b3c1 100644 --- a/src/Controller/OgRepository/Image/TransferAction.php +++ b/src/Controller/OgRepository/Image/TransferAction.php @@ -5,6 +5,7 @@ namespace App\Controller\OgRepository\Image; use App\Controller\OgRepository\AbstractOgRepositoryController; use App\Dto\Input\ExportImportImageRepositoryInput; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Entity\ImageRepository; use App\Model\CommandTypes; use App\Model\ImageStatus; @@ -27,13 +28,14 @@ class TransferAction extends AbstractOgRepositoryController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(ExportImportImageRepositoryInput $input, Image $image): JsonResponse + public function __invoke(ExportImportImageRepositoryInput $input, ImageImageRepository $imageImageRepository): JsonResponse { $repositories = $input->repositories; foreach ($repositories as $repositoryEntity) { /** @var ImageRepository $repository */ $repository = $repositoryEntity->getEntity(); + $image = $imageImageRepository->getImage(); if (!$image->getImageFullsum()) { throw new ValidatorException('Fullsum is required'); @@ -63,7 +65,7 @@ class TransferAction extends AbstractOgRepositoryController $this->createService->__invoke($image->getClient(), CommandTypes::TRANSFER_IMAGE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData); - $image->setStatus(ImageStatus::TRANSFERRING); + $imageImageRepository->setStatus(ImageStatus::TRANSFERRING); $this->entityManager->persist($image); $this->entityManager->flush(); } diff --git a/src/Controller/OgRepository/StatusAction.php b/src/Controller/OgRepository/StatusAction.php index 74c2654..18945b4 100644 --- a/src/Controller/OgRepository/StatusAction.php +++ b/src/Controller/OgRepository/StatusAction.php @@ -21,7 +21,7 @@ class StatusAction extends AbstractOgRepositoryController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(ImageRepository $data, HttpClientInterface $httpClient): JsonResponse + public function __invoke(ImageRepository $data): JsonResponse { $content = $this->createRequest('GET', 'http://'.$data->getIp(). ':8006/ogrepository/v1/status'); diff --git a/src/Controller/OgRepository/Webhook/ResponseController.php b/src/Controller/OgRepository/Webhook/ResponseController.php index 3539d4d..beeaf92 100644 --- a/src/Controller/OgRepository/Webhook/ResponseController.php +++ b/src/Controller/OgRepository/Webhook/ResponseController.php @@ -4,6 +4,7 @@ namespace App\Controller\OgRepository\Webhook; use App\Controller\OgRepository\AbstractOgRepositoryController; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Entity\ImageRepository; use App\Entity\Trace; use App\Model\CommandTypes; @@ -60,21 +61,21 @@ class ResponseController extends AbstractOgRepositoryController $trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]); $imageUuid = $trace->getInput()['imageUuid']; - $image = $this->entityManager->getRepository(Image::class)->findOneBy(['uuid' => $imageUuid]); + /* @var ImageImageRepository $imageImageRepository */ + $imageImageRepository = $this->entityManager->getRepository(ImageImageRepository::class)->findOneBy(['uuid' => $imageUuid]); - if ($image === null) { + if ($imageImageRepository === null) { $this->updateTraceStatus($trace, TraceStatus::FAILED, 'Image not found'); return; } - $image->setImageFullsum($data['image_id']); - $image->setStatus(ImageStatus::SUCCESS); - $this->entityManager->persist($image); + $imageImageRepository->setImageFullsum($data['image_id']); + $imageImageRepository->setStatus(ImageStatus::SUCCESS); + $this->entityManager->persist($imageImageRepository); $this->updateTraceStatus($trace, TraceStatus::SUCCESS); } - /** * @throws TransportExceptionInterface * @throws ServerExceptionInterface diff --git a/src/Dto/Input/DeleteImageInput.php b/src/Dto/Input/DeleteImageInput.php new file mode 100644 index 0000000..29590f2 --- /dev/null +++ b/src/Dto/Input/DeleteImageInput.php @@ -0,0 +1,13 @@ +imageRepository = new ImageRepositoryOutput($imageImageRepository->getRepository()); + $this->status = $imageImageRepository->getStatus(); + } + + public function createOrUpdateEntity(?ImageImageRepository $imageImageRepository = null): ImageImageRepository + { + if (!$imageImageRepository) { + $imageImageRepository = new ImageImageRepository(); + } + + $imageImageRepository->setRepository($this->imageRepository); + $imageImageRepository->setStatus($this->status); + + return $imageImageRepository; + } +} diff --git a/src/Dto/Input/ImageInput.php b/src/Dto/Input/ImageInput.php index e2ac465..35e8fcf 100644 --- a/src/Dto/Input/ImageInput.php +++ b/src/Dto/Input/ImageInput.php @@ -4,12 +4,14 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\ClientOutput; +use App\Dto\Output\ImageImageRepositoryOutput; use App\Dto\Output\ImageRepositoryOutput; use App\Dto\Output\OrganizationalUnitOutput; use App\Dto\Output\PartitionOutput; use App\Dto\Output\RemoteCalendarRuleOutput; use App\Dto\Output\SoftwareProfileOutput; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Entity\OrganizationalUnit; use App\Entity\Partition; use App\Model\ImageStatus; @@ -31,18 +33,10 @@ final class ImageInput #[ApiProperty(description: 'The comments of the image', example: "Image 1 comments")] public ?string $comments = null; - #[Groups(['image:write'])] - #[ApiProperty(description: 'The type of the image', example: "Server")] - public ?string $type = null; - #[Groups(['image:write'])] #[ApiProperty(description: 'The type of the image', example: "Server")] public ?string $source = 'input'; - #[Groups(['image:write'])] - #[ApiProperty(description: 'The status of the image', example: "PENDING")] - public ?string $status = ImageStatus::PENDING; - #[Groups(['image:write'])] #[ApiProperty(description: 'The software profile of the image')] public ?SoftwareProfileOutput $softwareProfile = null; @@ -74,7 +68,6 @@ final class ImageInput #[ApiProperty(description: 'The global property of the image')] public ?bool $isGlobal = false; - public function __construct(?Image $image = null) { if (!$image) { @@ -84,25 +77,21 @@ final class ImageInput $this->name = $image->getName(); $this->description = $image->getDescription(); $this->comments = $image->getComments(); - $this->type = $image->getType(); $this->remotePc = $image->isRemotePc(); $this->isGlobal = $image->isGlobal(); - $this->status = $image->getStatus(); if ($image->getSoftwareProfile()) { $this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile()); } - if ($image->getRepositories()) { - foreach ($image->getRepositories() as $repository) { - $this->imageRepositories[] = new ImageRepositoryOutput($repository); - } - } - if ($image->getClient()) { $this->client = new ClientOutput($image->getClient()); } + if ($image->getImageImageRepositories()) { + $this->imageRepositories = array_map(fn($imageImageRepository) => new ImageImageRepositoryOutput($imageImageRepository), $image->getImageImageRepositories()->toArray()); + } + if ($image->getParent()) { $this->parent = new self($image->getParent()); } @@ -112,13 +101,11 @@ final class ImageInput { if (!$image) { $image = new Image(); - $image->setStatus(ImageStatus::PENDING); } $image->setName($this->name); $image->setDescription($this->description); $image->setComments($this->comments); - $image->setType($this->type); if ($this->softwareProfile) { $image->setSoftwareProfile($this->softwareProfile->getEntity()); @@ -129,15 +116,17 @@ final class ImageInput } if ($this->imageRepositories) { - foreach ($this->imageRepositories as $repository) { - $repositoriesToAdd[] = $repository->getEntity(); + foreach ($this->imageRepositories as $imageRepository) { + $aux = new ImageImageRepository(); + $aux->setImage($image); + $aux->setRepository($imageRepository->getEntity()); + $aux->setStatus(''); + if (!$image->containsImageImageRepository($aux)) { + $image->addImageImageRepository($aux); + } } - } else { - $repositoriesToAdd[] = $image->getClient()?->getRepository(); } - $image->setRepositories( $repositoriesToAdd ?? [] ); - $image->setRemotePc($this->remotePc); $image->setIsGlobal($this->isGlobal); $image->setCreated(false); diff --git a/src/Dto/Output/ImageImageRepositoryOutput.php b/src/Dto/Output/ImageImageRepositoryOutput.php new file mode 100644 index 0000000..a7b3830 --- /dev/null +++ b/src/Dto/Output/ImageImageRepositoryOutput.php @@ -0,0 +1,49 @@ +getImage()) { + $this->image = new ImageOutput($imageImageRepository->getImage()); + } + } + + if ($imageImageRepository->getRepository()) { + $this->imageRepository = new ImageRepositoryOutput($imageImageRepository->getRepository()); + } + + $this->status = $imageImageRepository->getStatus(); + $this->imageFullsum = $imageImageRepository->getImageFullsum(); + $this->createdAt = $imageImageRepository->getCreatedAt(); + $this->createdBy = $imageImageRepository->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/ImageOutput.php b/src/Dto/Output/ImageOutput.php index 6d51e60..085ec55 100644 --- a/src/Dto/Output/ImageOutput.php +++ b/src/Dto/Output/ImageOutput.php @@ -4,6 +4,7 @@ namespace App\Dto\Output; use ApiPlatform\Metadata\Get; use App\Entity\Image; +use App\Entity\ImageImageRepository; use App\Entity\ImageRepository; use App\Entity\Software; use Symfony\Component\Serializer\Annotation\Groups; @@ -11,7 +12,7 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'Image')] final class ImageOutput extends AbstractOutput { - #[Groups(['image:read'])] + #[Groups(['image:read', 'image-image-repository:read'])] public ?string $name = ''; #[Groups(['image:read'])] @@ -20,30 +21,12 @@ final class ImageOutput extends AbstractOutput #[Groups(['image:read'])] public ?string $comments = ''; - #[Groups(['image:read'])] - public ?string $type = null; - - #[Groups(['image:read'])] - public ?string $path = ''; - - #[Groups(['image:read'])] - public ?string $revision = ''; - - #[Groups(['image:read'])] - public ?string $info = ''; - - #[Groups(['image:read'])] - public ?int $size = null; - #[Groups(['image:read'])] public ?bool $remotePc = null; #[Groups(['image:read'])] public ?bool $isGlobal = null; - #[Groups(['image:read'])] - public ?bool $created = null; - #[Groups(['image:read'])] public ?SoftwareProfileOutput $softwareProfile = null; @@ -56,12 +39,6 @@ final class ImageOutput extends AbstractOutput #[Groups(['image:read'])] public ?array $partitionInfo = null; - #[Groups(['image:read'])] - public ?string $imageFullsum = ''; - - #[Groups(['image:read'])] - public ?string $status = null; - #[Groups(['image:read'])] public \DateTime $createdAt; @@ -75,24 +52,15 @@ final class ImageOutput extends AbstractOutput $this->name = $image->getName(); $this->description = $image->getDescription(); $this->comments = $image->getComments(); - $this->type = $image->getType(); - $this->path = $image->getPath(); - $this->revision = $image->getRevision(); - $this->info = $image->getInfo(); - $this->size = $image->getSize(); - $this->imageFullsum = $image->getImageFullsum(); - $this->status = $image->getStatus(); $this->softwareProfile = $image->getSoftwareProfile() ? new SoftwareProfileOutput($image->getSoftwareProfile()) : null; - $this->imageRepositories = $image->getRepositories()->map( - fn(ImageRepository $image) => new ImageRepositoryOutput($image) + $this->imageRepositories = $image->getImageImageRepositories()->map( + fn(ImageImageRepository $image) => new ImageImageRepositoryOutput($image) )->toArray(); - $this->partitionInfo = json_decode($image->getPartitionInfo(), true); $this->remotePc = $image->isRemotePc(); $this->isGlobal = $image->isGlobal(); - $this->created = $image->isCreated(); $this->createdAt = $image->getCreatedAt(); $this->createdBy = $image->getCreatedBy(); } diff --git a/src/Dto/Output/ImageRepositoryOutput.php b/src/Dto/Output/ImageRepositoryOutput.php index 5ee94fa..6d3fdb7 100644 --- a/src/Dto/Output/ImageRepositoryOutput.php +++ b/src/Dto/Output/ImageRepositoryOutput.php @@ -9,7 +9,7 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'ImageRepository')] class ImageRepositoryOutput extends AbstractOutput { - #[Groups(['repository:read', 'image:read', 'client:read', "organizational-unit:read"])] + #[Groups(['repository:read', 'image:read', 'client:read', "organizational-unit:read", "image-image-repository:read"])] public ?string $name = ''; #[Groups(['repository:read'])] @@ -18,19 +18,23 @@ class ImageRepositoryOutput extends AbstractOutput #[Groups(['repository:read'])] public ?string $comments = ''; + #[Groups(['repository:read'])] + public ?bool $status = true; + #[Groups(['repository:read'])] public \DateTime $createdAt; #[Groups(['repository:read'])] public ?string $createdBy = null; - public function __construct(ImageRepository $imageRepository) + public function __construct(ImageRepository $imageRepository, bool $status = true) { parent::__construct($imageRepository); $this->name = $imageRepository->getName(); $this->ip = $imageRepository->getIp(); $this->comments = $imageRepository->getComments(); + $this->status = $status; $this->createdAt = $imageRepository->getCreatedAt(); $this->createdBy = $imageRepository->getCreatedBy(); } diff --git a/src/Dto/Output/MenuOutput.php b/src/Dto/Output/MenuOutput.php index e9bc6fa..1a81def 100644 --- a/src/Dto/Output/MenuOutput.php +++ b/src/Dto/Output/MenuOutput.php @@ -34,7 +34,7 @@ final class MenuOutput extends AbstractOutput #[Groups(['menu:read'])] public ?string $createdBy = null; -public function __construct(Menu $menu) + public function __construct(Menu $menu) { parent::__construct($menu); diff --git a/src/Entity/Image.php b/src/Entity/Image.php index c8a326b..3ba195e 100644 --- a/src/Entity/Image.php +++ b/src/Entity/Image.php @@ -21,21 +21,6 @@ class Image extends AbstractEntity #[ORM\Column(length: 255, nullable: true)] private ?string $comments = null; - #[ORM\Column(length: 255, nullable: true)] - private ?string $path = null; - - #[ORM\Column(length: 255, nullable: true)] - private ?string $type = null; - - #[ORM\Column(length: 255, nullable: true)] - private ?string $revision = null; - - #[ORM\Column(length: 255, nullable: true)] - private ?string $info = null; - - #[ORM\Column(length: 255, nullable: true)] - private ?int $size = null; - #[ORM\ManyToOne] #[ORM\JoinColumn(nullable: true)] private ?SoftwareProfile $softwareProfile = null; @@ -43,12 +28,6 @@ class Image extends AbstractEntity #[ORM\Column] private ?bool $remotePc = null; - /** - * @var Collection - */ - #[ORM\ManyToMany(targetEntity: \App\Entity\ImageRepository::class, inversedBy: 'images')] - private Collection $repositories; - #[ORM\Column(length: 255, nullable: true)] private ?string $partitionInfo = null; @@ -58,24 +37,19 @@ class Image extends AbstractEntity #[ORM\ManyToOne] private ?Client $client = null; - #[ORM\Column(nullable: true)] - private ?bool $created = null; - - #[ORM\Column(length: 255, nullable: true)] - private ?string $imageFullsum = null; - - #[ORM\Column(length: 255)] - private ?string $status = null; - #[ORM\Column] private ?bool $isGlobal = null; + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'image', targetEntity: ImageImageRepository::class, cascade: ['persist'], orphanRemoval: true)] + private Collection $imageImageRepositories; public function __construct() { parent::__construct(); - - $this->repositories = new ArrayCollection(); + $this->imageImageRepositories = new ArrayCollection(); } public function getDescription(): ?string @@ -102,66 +76,6 @@ class Image extends AbstractEntity return $this; } - public function getPath(): ?string - { - return $this->path; - } - - public function setPath(?string $path): static - { - $this->path = $path; - - return $this; - } - - public function getType(): ?string - { - return $this->type; - } - - public function setType(?string $type): static - { - $this->type = $type; - - return $this; - } - - public function getRevision(): ?string - { - return $this->revision; - } - - public function setRevision(?string $revision): static - { - $this->revision = $revision; - - return $this; - } - - public function getInfo(): ?string - { - return $this->info; - } - - public function setInfo(?string $info): static - { - $this->info = $info; - - return $this; - } - - public function getSize(): ?int - { - return $this->size; - } - - public function setSize(?int $size): static - { - $this->size = $size; - - return $this; - } - public function getSoftwareProfile(): ?SoftwareProfile { return $this->softwareProfile; @@ -186,39 +100,6 @@ class Image extends AbstractEntity return $this; } - public function getRepositories(): ?Collection - { - return $this->repositories; - } - - public function setRepositories(array $repositories): static - { - $this->repositories->clear(); - - foreach ($repositories as $repository){ - $this->addRepository($repository); - } - - return $this; - } - - public function addRepository(\App\Entity\ImageRepository $repository): static - { - if (!$this->repositories->contains($repository)) { - $this->repositories->add($repository); - //$repository->addImage($this); - } - - return $this; - } - - public function removeRepository(?\App\Entity\ImageRepository $repository): static - { - $this->repositories->removeElement($repository); - - return $this; - } - public function getPartitionInfo(): ?string { return $this->partitionInfo; @@ -279,18 +160,6 @@ class Image extends AbstractEntity return $this; } - public function getStatus(): ?string - { - return $this->status; - } - - public function setStatus(string $status): static - { - $this->status = $status; - - return $this; - } - public function isGlobal(): ?bool { return $this->isGlobal; @@ -302,4 +171,48 @@ class Image extends AbstractEntity return $this; } + + /** + * @return Collection + */ + public function getImageImageRepositories(): Collection + { + return $this->imageImageRepositories; + } + + public function addImageImageRepository(ImageImageRepository $imageImageRepository): static + { + if (!$this->imageImageRepositories->contains($imageImageRepository)) { + $this->imageImageRepositories->add($imageImageRepository); + $imageImageRepository->setImage($this); + } + + return $this; + } + + public function removeImageImageRepository(ImageImageRepository $imageImageRepository): static + { + if ($this->imageImageRepositories->removeElement($imageImageRepository)) { + // set the owning side to null (unless already changed) + if ($imageImageRepository->getImage() === $this) { + $imageImageRepository->setImage(null); + } + } + + return $this; + } + + public function containsImageImageRepository(ImageImageRepository $imageImageRepository): bool + { + foreach ($this->imageImageRepositories as $existing) { + if ( + $existing->getImage()->getId() === $imageImageRepository->getImage()->getId() && + $existing->getRepository()->getId() === $imageImageRepository->getRepository()->getId() + ) { + return true; + } + } + + return false; + } } diff --git a/src/Entity/ImageImageRepository.php b/src/Entity/ImageImageRepository.php new file mode 100644 index 0000000..169df79 --- /dev/null +++ b/src/Entity/ImageImageRepository.php @@ -0,0 +1,90 @@ +image; + } + + public function setImage(?Image $image): static + { + $this->image = $image; + + return $this; + } + + public function getRepository(): ?ImageRepository + { + return $this->repository; + } + + public function setRepository(?ImageRepository $repository): static + { + $this->repository = $repository; + + return $this; + } + + public function getStatus(): ?string + { + return $this->status; + } + + public function setStatus(string $status): static + { + $this->status = $status; + + return $this; + } + + public function getCreated(): ?bool + { + return $this->created; + } + + public function setCreated(?bool $created): static + { + $this->created = $created; + + return $this; + } + + public function getImageFullsum(): ?string + { + return $this->imageFullsum; + } + + public function setImageFullsum(?string $imageFullsum): static + { + $this->imageFullsum = $imageFullsum; + + return $this; + } +} diff --git a/src/Entity/ImageRepository.php b/src/Entity/ImageRepository.php index 3641cdf..1dc49fe 100644 --- a/src/Entity/ImageRepository.php +++ b/src/Entity/ImageRepository.php @@ -19,15 +19,15 @@ class ImageRepository extends AbstractEntity private ?string $comments = null; /** - * @var Collection + * @var Collection */ - #[ORM\ManyToMany(targetEntity: Image::class, mappedBy: 'repositories')] - private Collection $images; + #[ORM\OneToMany(mappedBy: 'repository', targetEntity: ImageImageRepository::class)] + private Collection $imageImageRepositories; public function __construct() { parent::__construct(); - $this->images = new ArrayCollection(); + $this->imageImageRepositories = new ArrayCollection(); } public function getIp(): ?string @@ -55,10 +55,32 @@ class ImageRepository extends AbstractEntity } /** - * @return Collection + * @return Collection */ - public function getImages(): Collection + public function getImageImageRepositories(): Collection { - return $this->images; + return $this->imageImageRepositories; + } + + public function addImageImageRepository(ImageImageRepository $imageImageRepository): static + { + if (!$this->imageImageRepositories->contains($imageImageRepository)) { + $this->imageImageRepositories->add($imageImageRepository); + $imageImageRepository->setRepository($this); + } + + return $this; + } + + public function removeImageImageRepository(ImageImageRepository $imageImageRepository): static + { + if ($this->imageImageRepositories->removeElement($imageImageRepository)) { + // set the owning side to null (unless already changed) + if ($imageImageRepository->getRepository() === $this) { + $imageImageRepository->setRepository(null); + } + } + + return $this; } } diff --git a/src/Factory/ImageFactory.php b/src/Factory/ImageFactory.php index f490b4a..392f6e9 100644 --- a/src/Factory/ImageFactory.php +++ b/src/Factory/ImageFactory.php @@ -35,9 +35,7 @@ final class ImageFactory extends ModelFactory return [ 'createdAt' => self::faker()->dateTime(), 'name' => self::faker()->text(255), - 'status' => self::faker()->randomElement(['IN_PROGRESS', 'FINISHED', 'ERROR']), 'softwareProfile' => SoftwareProfileFactory::new(), - 'repositories' => ImageRepositoryFactory::createMany(5), 'updatedAt' => self::faker()->dateTime(), 'remotePc' => self::faker()->boolean(), 'isGlobal' => self::faker()->boolean(), diff --git a/src/Repository/ImageImageRepositoryRepository.php b/src/Repository/ImageImageRepositoryRepository.php new file mode 100644 index 0000000..a72dc6b --- /dev/null +++ b/src/Repository/ImageImageRepositoryRepository.php @@ -0,0 +1,18 @@ + + */ +class ImageImageRepositoryRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, ImageImageRepository::class); + } +} diff --git a/src/State/Processor/ImageImageRepositoryProcessor.php b/src/State/Processor/ImageImageRepositoryProcessor.php new file mode 100644 index 0000000..d4fed62 --- /dev/null +++ b/src/State/Processor/ImageImageRepositoryProcessor.php @@ -0,0 +1,68 @@ +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 = []): ImageImageRepositoryOutput + { + if (!($data instanceof ImageImageRepositoryInput)) { + throw new \Exception(sprintf('data is not instance of %s', ImageImageRepositoryInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->imageRepository->findOneByUuid($uriVariables['uuid']); + } + + $image = $data->createOrUpdateEntity($entity); + $this->validator->validate($image); + $this->imageRepository->save($image); + + return new ImageImageRepositoryOutput($image); + } + + 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/Processor/ImageProcessor.php b/src/State/Processor/ImageProcessor.php index 8d79868..ccb203d 100644 --- a/src/State/Processor/ImageProcessor.php +++ b/src/State/Processor/ImageProcessor.php @@ -11,7 +11,9 @@ use ApiPlatform\State\ProcessorInterface; use ApiPlatform\Validator\ValidatorInterface; use App\Controller\OgAgent\CreateImageAction; use App\Dto\Input\ImageInput; +use App\Dto\Input\ImageRepositoryInput; use App\Dto\Output\ImageOutput; +use App\Entity\ImageImageRepository; use App\Repository\ImageRepository; readonly class ImageProcessor implements ProcessorInterface diff --git a/src/State/Provider/ImageImageRepositoryProvider.php b/src/State/Provider/ImageImageRepositoryProvider.php new file mode 100644 index 0000000..9c47ca3 --- /dev/null +++ b/src/State/Provider/ImageImageRepositoryProvider.php @@ -0,0 +1,56 @@ +provideCollection($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 ImageImageRepositoryOutput($item, $context); + } + + 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('ImageImageRepository not found'); + } + + return new ImageImageRepositoryOutput($item); + } +} diff --git a/src/State/Provider/ImageRepositoryProvider.php b/src/State/Provider/ImageRepositoryProvider.php index 4230b45..5e45ff1 100644 --- a/src/State/Provider/ImageRepositoryProvider.php +++ b/src/State/Provider/ImageRepositoryProvider.php @@ -9,17 +9,23 @@ use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Put; use ApiPlatform\State\Pagination\TraversablePaginator; use ApiPlatform\State\ProviderInterface; +use App\Controller\OgRepository\StatusAction; 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; +use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; readonly class ImageRepositoryProvider implements ProviderInterface { public function __construct( - private ProviderInterface $collectionProvider, - private ProviderInterface $itemProvider + private ProviderInterface $collectionProvider, + private ProviderInterface $itemProvider, + private StatusAction $statusAction ) { } @@ -37,13 +43,23 @@ readonly class ImageRepositoryProvider implements ProviderInterface } } + /** + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + * @throws RedirectionExceptionInterface + * @throws ClientExceptionInterface + */ 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); + $statusResponse = $this->statusAction->__invoke($item); + $content = json_decode($statusResponse->getContent(), true); + $status = !isset($content['error']); + + $items[] = new ImageRepositoryOutput($item, $status); } return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems());