diff --git a/migrations/Version20241212214741.php b/migrations/Version20241212214741.php new file mode 100644 index 0000000..a5284a3 --- /dev/null +++ b/migrations/Version20241212214741.php @@ -0,0 +1,39 @@ +addSql('CREATE SEQUENCE domain_status_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE domain_status (id INT NOT NULL, domain_id VARCHAR(255) NOT NULL, date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, add_status TEXT NOT NULL, delete_status TEXT NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_146369D5115F0EE5 ON domain_status (domain_id)'); + $this->addSql('COMMENT ON COLUMN domain_status.date IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN domain_status.add_status IS \'(DC2Type:simple_array)\''); + $this->addSql('COMMENT ON COLUMN domain_status.delete_status IS \'(DC2Type:simple_array)\''); + $this->addSql('ALTER TABLE domain_status ADD CONSTRAINT FK_146369D5115F0EE5 FOREIGN KEY (domain_id) REFERENCES domain (ldh_name) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP SEQUENCE domain_status_id_seq CASCADE'); + $this->addSql('ALTER TABLE domain_status DROP CONSTRAINT FK_146369D5115F0EE5'); + $this->addSql('DROP TABLE domain_status'); + } +} diff --git a/src/Entity/Domain.php b/src/Entity/Domain.php index be30ffe..2089294 100644 --- a/src/Entity/Domain.php +++ b/src/Entity/Domain.php @@ -106,6 +106,12 @@ class Domain #[Groups(['domain:item', 'domain:list'])] private ?bool $deleted; + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: DomainStatus::class, mappedBy: 'domain', orphanRemoval: true)] + private Collection $domainStatuses; + private const IMPORTANT_EVENTS = [EventAction::Deletion->value, EventAction::Expiration->value]; private const IMPORTANT_STATUS = [ 'redemption period', @@ -128,8 +134,8 @@ class Domain $this->nameservers = new ArrayCollection(); $this->createdAt = new \DateTimeImmutable('now'); $this->updatedAt = new \DateTimeImmutable('now'); - $this->deleted = false; + $this->domainStatuses = new ArrayCollection(); } public function getLdhName(): ?string @@ -376,4 +382,34 @@ class Domain || (count(array_intersect($this->getStatus(), ['auto renew period', 'client hold', 'server hold'])) > 0 && $this->getUpdatedAt()->diff(new \DateTimeImmutable())->days >= 1); } + + /** + * @return Collection + */ + public function getDomainStatuses(): Collection + { + return $this->domainStatuses; + } + + public function addDomainStatus(DomainStatus $domainStatus): static + { + if (!$this->domainStatuses->contains($domainStatus)) { + $this->domainStatuses->add($domainStatus); + $domainStatus->setDomain($this); + } + + return $this; + } + + public function removeDomainStatus(DomainStatus $domainStatus): static + { + if ($this->domainStatuses->removeElement($domainStatus)) { + // set the owning side to null (unless already changed) + if ($domainStatus->getDomain() === $this) { + $domainStatus->setDomain(null); + } + } + + return $this; + } } diff --git a/src/Entity/DomainStatus.php b/src/Entity/DomainStatus.php new file mode 100644 index 0000000..e38702f --- /dev/null +++ b/src/Entity/DomainStatus.php @@ -0,0 +1,87 @@ +date = new \DateTimeImmutable('now'); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getDomain(): ?Domain + { + return $this->domain; + } + + public function setDomain(?Domain $domain): static + { + $this->domain = $domain; + + return $this; + } + + public function getDate(): ?\DateTimeImmutable + { + return $this->date; + } + + public function setDate(\DateTimeImmutable $date): static + { + $this->date = $date; + + return $this; + } + + public function getAddStatus(): array + { + return $this->addStatus; + } + + public function setAddStatus(array $addStatus): static + { + $this->addStatus = $addStatus; + + return $this; + } + + public function getDeleteStatus(): array + { + return $this->deleteStatus; + } + + public function setDeleteStatus(array $deleteStatus): static + { + $this->deleteStatus = $deleteStatus; + + return $this; + } +} diff --git a/src/Repository/DomainStatusRepository.php b/src/Repository/DomainStatusRepository.php new file mode 100644 index 0000000..ec3c6ad --- /dev/null +++ b/src/Repository/DomainStatusRepository.php @@ -0,0 +1,43 @@ + + */ +class DomainStatusRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, DomainStatus::class); + } + + // /** + // * @return DomainStatus[] Returns an array of DomainStatus objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('d') + // ->andWhere('d.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('d.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?DomainStatus + // { + // return $this->createQueryBuilder('d') + // ->andWhere('d.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Service/RDAPService.php b/src/Service/RDAPService.php index eda7ab2..ad6f2fe 100644 --- a/src/Service/RDAPService.php +++ b/src/Service/RDAPService.php @@ -7,6 +7,7 @@ use App\Config\TldType; use App\Entity\Domain; use App\Entity\DomainEntity; use App\Entity\DomainEvent; +use App\Entity\DomainStatus; use App\Entity\Entity; use App\Entity\EntityEvent; use App\Entity\Nameserver; @@ -182,7 +183,22 @@ readonly class RDAPService $domain->setTld($tld)->setLdhName($idnDomain)->setDeleted(false); if (array_key_exists('status', $res)) { + $addedStatus = array_diff($res['status'], $domain->getStatus()); + $deletedStatus = array_diff($domain->getStatus(), $res['status']); $domain->setStatus($res['status']); + + if (count($addedStatus) > 0 || count($deletedStatus) > 0) { + $this->em->persist($domain); + $this->em->flush(); + + $domainStatus = (new DomainStatus()) + ->setDomain($domain) + ->setDate($domain->getUpdatedAt()) + ->setAddStatus($addedStatus) + ->setDeleteStatus($deletedStatus); + + $this->em->persist($domainStatus); + } } else { $this->logger->warning('The domain name {idnDomain} has no WHOIS status.', [ 'idnDomain' => $idnDomain,