diff --git a/config/api_platform/Software.yaml b/config/api_platform/Software.yaml new file mode 100644 index 0000000..4e34a66 --- /dev/null +++ b/config/api_platform/Software.yaml @@ -0,0 +1,31 @@ +resources: + App\Entity\Software: + processor: App\State\Processor\SoftwareProcessor + input: App\Dto\Input\SoftwareInput + output: App\Dto\Output\SoftwareOutput + normalizationContext: + groups: ['default', 'software:read'] + denormalizationContext: + groups: ['software:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\SoftwareProvider + filters: + - 'api_platform.filter.software.order' + - 'api_platform.filter.software.search' + + ApiPlatform\Metadata\Get: + provider: App\State\Provider\SoftwareProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\SoftwareProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\SoftwareProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + +properties: + App\Entity\Software: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/SoftwareProfile.yaml b/config/api_platform/SoftwareProfile.yaml new file mode 100644 index 0000000..f5c544c --- /dev/null +++ b/config/api_platform/SoftwareProfile.yaml @@ -0,0 +1,30 @@ +resources: + App\Entity\SoftwareProfile: + processor: App\State\Processor\SoftwareProfileProcessor + input: App\Dto\Input\SoftwareProfileInput + output: App\Dto\Output\SoftwareProfileOutput + normalizationContext: + groups: ['default', 'software-profile:read'] + denormalizationContext: + groups: ['software-profile:write'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\SoftwareProfileProvider + filters: + - 'api_platform.filter.software.order' + - 'api_platform.filter.software.search' + ApiPlatform\Metadata\Get: + provider: App\State\Provider\SoftwareProfileProvider + ApiPlatform\Metadata\Put: + provider: App\State\Provider\SoftwareProfileProvider + ApiPlatform\Metadata\Patch: + provider: App\State\Provider\SoftwareProfileProvider + ApiPlatform\Metadata\Post: ~ + ApiPlatform\Metadata\Delete: ~ + +properties: + App\Entity\SoftwareProfile: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index e9086eb..6b82216 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -69,6 +69,16 @@ services: $itemProvider: '@api_platform.doctrine.orm.state.item_provider' App\State\Provider\HardwareTypeProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\SoftwareProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\SoftwareProfileProvider: 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/Version20240702132742.php b/migrations/Version20240702132742.php new file mode 100644 index 0000000..91069d5 --- /dev/null +++ b/migrations/Version20240702132742.php @@ -0,0 +1,41 @@ +addSql('CREATE TABLE software (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, description VARCHAR(255) DEFAULT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_77D068CFD17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE software_profile (id INT AUTO_INCREMENT NOT NULL, organizational_unit_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, description VARCHAR(255) DEFAULT NULL, comments VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_B70C3C9BD17F50A6 (uuid), INDEX IDX_B70C3C9BFB84408A (organizational_unit_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE software_profile_software (software_profile_id INT NOT NULL, software_id INT NOT NULL, INDEX IDX_3DDFEC7ED42A742 (software_profile_id), INDEX IDX_3DDFEC7D7452741 (software_id), PRIMARY KEY(software_profile_id, software_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE software_profile ADD CONSTRAINT FK_B70C3C9BFB84408A FOREIGN KEY (organizational_unit_id) REFERENCES organizational_unit (id)'); + $this->addSql('ALTER TABLE software_profile_software ADD CONSTRAINT FK_3DDFEC7ED42A742 FOREIGN KEY (software_profile_id) REFERENCES software_profile (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE software_profile_software ADD CONSTRAINT FK_3DDFEC7D7452741 FOREIGN KEY (software_id) REFERENCES software (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE software_profile DROP FOREIGN KEY FK_B70C3C9BFB84408A'); + $this->addSql('ALTER TABLE software_profile_software DROP FOREIGN KEY FK_3DDFEC7ED42A742'); + $this->addSql('ALTER TABLE software_profile_software DROP FOREIGN KEY FK_3DDFEC7D7452741'); + $this->addSql('DROP TABLE software'); + $this->addSql('DROP TABLE software_profile'); + $this->addSql('DROP TABLE software_profile_software'); + } +} diff --git a/src/Dto/Input/SoftwareInput.php b/src/Dto/Input/SoftwareInput.php new file mode 100644 index 0000000..624a94c --- /dev/null +++ b/src/Dto/Input/SoftwareInput.php @@ -0,0 +1,42 @@ +name = $software->getName(); + $this->description = $software->getDescription(); + } + + public function createOrUpdateEntity(?Software $software = null): Software + { + if (!$software) { + $software = new Software(); + } + + $software->setName($this->name); + $software->setDescription($this->description); + + return $software; + } +} \ No newline at end of file diff --git a/src/Dto/Input/SoftwareProfileInput.php b/src/Dto/Input/SoftwareProfileInput.php new file mode 100644 index 0000000..c803d82 --- /dev/null +++ b/src/Dto/Input/SoftwareProfileInput.php @@ -0,0 +1,51 @@ +description = $softwareProfile->getDescription(); + $this->comments = $softwareProfile->getComments(); + if($softwareProfile->getOrganizationalUnit()) { + $this->organizationalUnit = new OrganizationalUnitOutput($softwareProfile->getOrganizationalUnit()); + } + } + + public function createOrUpdateEntity(?SoftwareProfile $softwareProfile = null): SoftwareProfile + { + if (!$softwareProfile) { + $softwareProfile = new SoftwareProfile(); + } + + $softwareProfile->setDescription($this->description); + $softwareProfile->setComments($this->comments); + if ($this->organizationalUnit) { + $softwareProfile->setOrganizationalUnit($this->organizationalUnit->getEntity()); + } + + return $softwareProfile; + } +} \ No newline at end of file diff --git a/src/Dto/Output/SoftwareOutput.php b/src/Dto/Output/SoftwareOutput.php new file mode 100644 index 0000000..07a4fee --- /dev/null +++ b/src/Dto/Output/SoftwareOutput.php @@ -0,0 +1,34 @@ +name = $software->getName(); + $this->description = $software->getDescription(); + $this->createdAt = $software->getCreatedAt(); + $this->createdBy = $software->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Dto/Output/SoftwareProfileOutput.php b/src/Dto/Output/SoftwareProfileOutput.php new file mode 100644 index 0000000..5dc21e0 --- /dev/null +++ b/src/Dto/Output/SoftwareProfileOutput.php @@ -0,0 +1,49 @@ +description = $softwareProfile->getDescription(); + $this->comments = $softwareProfile->getComments(); + if($softwareProfile->getOrganizationalUnit()) { + $this->organizationalUnit = new OrganizationalUnitOutput($softwareProfile->getOrganizationalUnit()); + } + + $this->softwareCollection = $softwareProfile->getSoftwareCollection()->map( + fn(Software $hardware) => new SoftwareOutput($hardware) + )->toArray(); + + $this->createdAt = $softwareProfile->getCreatedAt(); + $this->createdBy = $softwareProfile->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Entity/OrganizationalUnit.php b/src/Entity/OrganizationalUnit.php index 136cf16..469a9f5 100644 --- a/src/Entity/OrganizationalUnit.php +++ b/src/Entity/OrganizationalUnit.php @@ -78,12 +78,19 @@ class OrganizationalUnit extends AbstractEntity #[ORM\Column(nullable: true)] private ?int $capacity = null; + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'organizationalUnit', targetEntity: SoftwareProfile::class)] + private Collection $softwareProfiles; + public function __construct() { parent::__construct(); $this->organizationalUnits = new ArrayCollection(); $this->users = new ArrayCollection(); $this->clients = new ArrayCollection(); + $this->softwareProfiles = new ArrayCollection(); } public function getDescription(): ?string @@ -331,4 +338,34 @@ class OrganizationalUnit extends AbstractEntity $childUnit->updateNetworkSettingsRecursively($networkSettings); } } + + /** + * @return Collection + */ + public function getSoftwareProfiles(): Collection + { + return $this->softwareProfiles; + } + + public function addSoftwareProfile(SoftwareProfile $softwareProfile): static + { + if (!$this->softwareProfiles->contains($softwareProfile)) { + $this->softwareProfiles->add($softwareProfile); + $softwareProfile->setOrganizationalUnit($this); + } + + return $this; + } + + public function removeSoftwareProfile(SoftwareProfile $softwareProfile): static + { + if ($this->softwareProfiles->removeElement($softwareProfile)) { + // set the owning side to null (unless already changed) + if ($softwareProfile->getOrganizationalUnit() === $this) { + $softwareProfile->setOrganizationalUnit(null); + } + } + + return $this; + } } diff --git a/src/Entity/Software.php b/src/Entity/Software.php new file mode 100644 index 0000000..1723483 --- /dev/null +++ b/src/Entity/Software.php @@ -0,0 +1,69 @@ + + */ + #[ORM\ManyToMany(targetEntity: SoftwareProfile::class, mappedBy: 'softwareCollection')] + private Collection $softwareProfiles; + + public function __construct() + { + parent::__construct(); + $this->softwareProfiles = new ArrayCollection(); + } + + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): static + { + $this->description = $description; + + return $this; + } + + /** + * @return Collection + */ + public function getSoftwareProfiles(): Collection + { + return $this->softwareProfiles; + } + + public function addSoftwareProfile(SoftwareProfile $softwareProfile): static + { + if (!$this->softwareProfiles->contains($softwareProfile)) { + $this->softwareProfiles->add($softwareProfile); + $softwareProfile->addSoftwareCollection($this); + } + + return $this; + } + + public function removeSoftwareProfile(SoftwareProfile $softwareProfile): static + { + if ($this->softwareProfiles->removeElement($softwareProfile)) { + $softwareProfile->removeSoftwareCollection($this); + } + + return $this; + } +} diff --git a/src/Entity/SoftwareProfile.php b/src/Entity/SoftwareProfile.php new file mode 100644 index 0000000..bc0f968 --- /dev/null +++ b/src/Entity/SoftwareProfile.php @@ -0,0 +1,100 @@ + + */ + #[ORM\ManyToMany(targetEntity: Software::class, inversedBy: 'softwareProfiles')] + private Collection $softwareCollection; + + public function __construct() + { + parent::__construct(); + + $this->softwareCollection = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): static + { + $this->description = $description; + + return $this; + } + + public function getComments(): ?string + { + return $this->comments; + } + + public function setComments(?string $comments): static + { + $this->comments = $comments; + + return $this; + } + + public function getOrganizationalUnit(): ?OrganizationalUnit + { + return $this->organizationalUnit; + } + + public function setOrganizationalUnit(?OrganizationalUnit $organizationalUnit): static + { + $this->organizationalUnit = $organizationalUnit; + + return $this; + } + + /** + * @return Collection + */ + public function getSoftwareCollection(): Collection + { + return $this->softwareCollection; + } + + public function addSoftwareCollection(Software $softwareCollection): static + { + if (!$this->softwareCollection->contains($softwareCollection)) { + $this->softwareCollection->add($softwareCollection); + } + + return $this; + } + + public function removeSoftwareCollection(Software $softwareCollection): static + { + $this->softwareCollection->removeElement($softwareCollection); + + return $this; + } +} diff --git a/src/Model/SoftwareTypes.php b/src/Model/SoftwareTypes.php new file mode 100644 index 0000000..afe552a --- /dev/null +++ b/src/Model/SoftwareTypes.php @@ -0,0 +1,31 @@ + 'Sistema Operativo', + self::FILE => 'Fichero', + self::APPLICATION => 'Aplicación', + ]; + + public static function getSoftwareTypes(): array + { + return self::SOFTWARE_TYPES; + } + + public static function getSoftwareType(string $software): ?string + { + return self::SOFTWARE_TYPES[$software] ?? null; + } + + public static function getSoftwareTypeKeys(): array + { + return array_keys(self::SOFTWARE_TYPES); + } +} \ No newline at end of file diff --git a/src/Repository/SoftwareProfileRepository.php b/src/Repository/SoftwareProfileRepository.php new file mode 100644 index 0000000..72fded4 --- /dev/null +++ b/src/Repository/SoftwareProfileRepository.php @@ -0,0 +1,18 @@ + + */ +class SoftwareProfileRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, SoftwareProfile::class); + } +} diff --git a/src/Repository/SoftwareRepository.php b/src/Repository/SoftwareRepository.php new file mode 100644 index 0000000..9b7f49f --- /dev/null +++ b/src/Repository/SoftwareRepository.php @@ -0,0 +1,18 @@ + + */ +class SoftwareRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Software::class); + } +} diff --git a/src/State/Processor/SoftwareProcessor.php b/src/State/Processor/SoftwareProcessor.php new file mode 100644 index 0000000..3730595 --- /dev/null +++ b/src/State/Processor/SoftwareProcessor.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 = []): SoftwareOutput + { + if (!($data instanceof SoftwareInput)) { + throw new \Exception(sprintf('data is not instance of %s', SoftwareInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->softwareRepository->findOneByUuid($uriVariables['uuid']); + } + + $software = $data->createOrUpdateEntity($entity); + $this->validator->validate($software); + $this->softwareRepository->save($software); + + return new SoftwareOutput($software); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->softwareRepository->findOneByUuid($uriVariables['uuid']); + $this->softwareRepository->delete($user); + + return null; + } +} diff --git a/src/State/Processor/SoftwareProfileProcessor.php b/src/State/Processor/SoftwareProfileProcessor.php new file mode 100644 index 0000000..7368d4d --- /dev/null +++ b/src/State/Processor/SoftwareProfileProcessor.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 = []): SoftwareProfileOutput + { + if (!($data instanceof SoftwareProfileInput)) { + throw new \Exception(sprintf('data is not instance of %s', SoftwareProfileInput::class)); + } + + $entity = null; + if (isset($uriVariables['uuid'])) { + $entity = $this->softwareProfileRepository->findOneByUuid($uriVariables['uuid']); + } + + $softwareProfile = $data->createOrUpdateEntity($entity); + $this->validator->validate($softwareProfile); + $this->softwareProfileRepository->save($softwareProfile); + + return new SoftwareProfileOutput($softwareProfile); + } + + private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null + { + $user = $this->softwareProfileRepository->findOneByUuid($uriVariables['uuid']); + $this->softwareProfileRepository->delete($user); + + return null; + } +} diff --git a/src/State/Provider/SoftwareProfileProvider.php b/src/State/Provider/SoftwareProfileProvider.php new file mode 100644 index 0000000..94f9aed --- /dev/null +++ b/src/State/Provider/SoftwareProfileProvider.php @@ -0,0 +1,71 @@ +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 SoftwareProfileInput($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('Software profile not found'); + } + + return new SoftwareProfileOutput($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 SoftwareProfileInput($item) : null; + } + + return new SoftwareProfileInput(); + } +} diff --git a/src/State/Provider/SoftwareProvider.php b/src/State/Provider/SoftwareProvider.php new file mode 100644 index 0000000..9459b09 --- /dev/null +++ b/src/State/Provider/SoftwareProvider.php @@ -0,0 +1,71 @@ +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 SoftwareOutput($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('Software not found'); + } + + return new SoftwareOutput($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 SoftwareInput($item) : null; + } + + return new SoftwareInput(); + } +}