Skip to content

Commit 65e7455

Browse files
committed
Save local distributions in the database
Signed-off-by: Tim Goudriaan <tim@codedmonkey.com>
1 parent 757e0bd commit 65e7455

7 files changed

Lines changed: 348 additions & 69 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
final class Version20251110105944 extends AbstractMigration
11+
{
12+
public function getDescription(): string
13+
{
14+
return 'Create distribution table';
15+
}
16+
17+
public function up(Schema $schema): void
18+
{
19+
$this->addSql(<<<'SQL'
20+
CREATE TABLE distribution (created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, last_modified_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, reference VARCHAR(255) NOT NULL, type VARCHAR(255) NOT NULL, released_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, resolved_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, source TEXT DEFAULT NULL, version_id INT NOT NULL, PRIMARY KEY(id))
21+
SQL);
22+
$this->addSql(<<<'SQL'
23+
CREATE UNIQUE INDEX UNIQ_A44837814BBC2705AEA349138CDE5729 ON distribution (version_id, reference, type)
24+
SQL);
25+
$this->addSql(<<<'SQL'
26+
CREATE INDEX IDX_A44837814BBC2705 ON distribution (version_id)
27+
SQL);
28+
$this->addSql(<<<'SQL'
29+
ALTER TABLE distribution ADD CONSTRAINT FK_A44837814BBC2705 FOREIGN KEY (version_id) REFERENCES version (id) NOT DEFERRABLE INITIALLY IMMEDIATE
30+
SQL);
31+
}
32+
33+
public function down(Schema $schema): void
34+
{
35+
$this->addSql(<<<'SQL'
36+
ALTER TABLE distribution DROP CONSTRAINT FK_A44837814BBC2705
37+
SQL);
38+
$this->addSql(<<<'SQL'
39+
DROP TABLE distribution
40+
SQL);
41+
}
42+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
namespace CodedMonkey\Dirigent\Doctrine\Entity;
4+
5+
use CodedMonkey\Dirigent\Doctrine\Repository\DistributionRepository;
6+
use Doctrine\DBAL\Types\Types;
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
#[ORM\Entity(repositoryClass: DistributionRepository::class)]
10+
#[ORM\UniqueConstraint(columns: ['version_id', 'reference', 'type'])]
11+
class Distribution extends TrackedEntity
12+
{
13+
#[ORM\Column, ORM\GeneratedValue, ORM\Id]
14+
private ?int $id = null;
15+
16+
#[ORM\ManyToOne(inversedBy: 'distributions')]
17+
#[ORM\JoinColumn(nullable: false)]
18+
private ?Version $version = null;
19+
20+
#[ORM\Column]
21+
private ?string $reference = null;
22+
23+
#[ORM\Column]
24+
private ?string $type = null;
25+
26+
#[ORM\Column]
27+
private \DateTimeImmutable $releasedAt;
28+
29+
#[ORM\Column]
30+
private \DateTimeImmutable $resolvedAt;
31+
32+
/**
33+
* Source URL.
34+
*
35+
* Contains the source URL if the distribution is mirrored.
36+
*/
37+
#[ORM\Column(type: Types::TEXT, nullable: true)]
38+
private ?string $source = null;
39+
40+
public function getId(): ?int
41+
{
42+
return $this->id;
43+
}
44+
45+
public function getVersion(): ?Version
46+
{
47+
return $this->version;
48+
}
49+
50+
public function setVersion(Version $version): void
51+
{
52+
$this->version = $version;
53+
}
54+
55+
public function getReference(): string
56+
{
57+
return $this->reference;
58+
}
59+
60+
public function setReference(string $reference): void
61+
{
62+
$this->reference = $reference;
63+
}
64+
65+
public function getType(): string
66+
{
67+
return $this->type;
68+
}
69+
70+
public function setType(string $type): void
71+
{
72+
$this->type = $type;
73+
}
74+
75+
public function getReleasedAt(): \DateTimeImmutable
76+
{
77+
return $this->releasedAt;
78+
}
79+
80+
public function setReleasedAt(\DateTimeImmutable $releasedAt): void
81+
{
82+
$this->releasedAt = $releasedAt;
83+
}
84+
85+
public function getResolvedAt(): \DateTimeImmutable
86+
{
87+
return $this->resolvedAt;
88+
}
89+
90+
public function setResolvedAt(): void
91+
{
92+
$this->resolvedAt = new \DateTimeImmutable();
93+
}
94+
95+
public function getSource(): ?string
96+
{
97+
return $this->source;
98+
}
99+
100+
public function setSource(?string $source): void
101+
{
102+
$this->source = $source;
103+
}
104+
}

src/Doctrine/Entity/Version.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ class Version extends TrackedEntity
114114
#[ORM\ManyToOne(targetEntity: Package::class, inversedBy: 'versions')]
115115
private ?Package $package = null;
116116

117+
#[ORM\OneToMany(targetEntity: Distribution::class, mappedBy: 'version')]
118+
private Collection $distributions;
119+
117120
#[ORM\OneToOne(mappedBy: 'version', cascade: ['persist', 'detach', 'remove'])]
118121
private VersionInstallations $installations;
119122

@@ -132,6 +135,7 @@ public function __construct()
132135
$this->replace = new ArrayCollection();
133136
$this->suggest = new ArrayCollection();
134137
$this->keywords = new ArrayCollection();
138+
$this->distributions = new ArrayCollection();
135139
$this->installations = new VersionInstallations($this);
136140
}
137141

@@ -480,6 +484,14 @@ public function setPackage(Package $package): void
480484
$this->package = $package;
481485
}
482486

487+
/**
488+
* @return Collection<int, Distribution>
489+
*/
490+
public function getDistributions(): Collection
491+
{
492+
return $this->distributions;
493+
}
494+
483495
public function getInstallations(): VersionInstallations
484496
{
485497
return $this->installations;

src/Doctrine/EventListener/PackageListener.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,33 @@
44

55
use CodedMonkey\Dirigent\Doctrine\Entity\Package;
66
use CodedMonkey\Dirigent\Doctrine\Repository\PackageRepository;
7+
use CodedMonkey\Dirigent\Package\PackageDistributionResolver;
78
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
9+
use Doctrine\ORM\Event\PostUpdateEventArgs;
810
use Doctrine\ORM\Event\PreRemoveEventArgs;
911
use Doctrine\ORM\Events;
1012

13+
#[AsEntityListener(Events::postUpdate, entity: Package::class)]
1114
#[AsEntityListener(Events::preRemove, entity: Package::class)]
12-
class PackageListener
15+
readonly class PackageListener
1316
{
17+
public function __construct(
18+
private PackageDistributionResolver $distributionResolver,
19+
) {
20+
}
21+
22+
public function postUpdate(Package $package, PostUpdateEventArgs $event): void
23+
{
24+
$changedFields = $event->getObjectManager()->getUnitOfWork()->getEntityChangeSet($package);
25+
26+
// Only resolve the distributions if distribution strategy has changed to automatic
27+
if (isset($changedFields['distributionStrategy']) && $package->getDistributionStrategy()->isAutomatic()) {
28+
foreach ($package->getVersions() as $version) {
29+
$this->distributionResolver->schedule($version);
30+
}
31+
}
32+
}
33+
1434
public function preRemove(Package $package, PreRemoveEventArgs $event): void
1535
{
1636
/** @var PackageRepository $repository */

src/Doctrine/EventListener/VersionListener.php

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,31 @@
33
namespace CodedMonkey\Dirigent\Doctrine\EventListener;
44

55
use CodedMonkey\Dirigent\Doctrine\Entity\Version;
6-
use CodedMonkey\Dirigent\Message\ResolveDistribution;
6+
use CodedMonkey\Dirigent\Package\PackageDistributionResolver;
77
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
88
use Doctrine\ORM\Event\PostUpdateEventArgs;
99
use Doctrine\ORM\Events;
10-
use Symfony\Component\DependencyInjection\Attribute\Autowire;
11-
use Symfony\Component\Messenger\Envelope;
12-
use Symfony\Component\Messenger\MessageBusInterface;
13-
use Symfony\Component\Messenger\Stamp\TransportNamesStamp;
1410

1511
#[AsEntityListener(Events::postPersist, entity: Version::class)]
1612
#[AsEntityListener(Events::postUpdate, entity: Version::class)]
1713
readonly class VersionListener
1814
{
1915
public function __construct(
20-
private MessageBusInterface $messenger,
21-
#[Autowire(param: 'dirigent.distributions.enabled')]
22-
private bool $distributionsEnabled,
23-
#[Autowire(param: 'dirigent.distributions.dev_versions')]
24-
private bool $resolveDevDistributions,
16+
private PackageDistributionResolver $distributionResolver,
2517
) {
2618
}
2719

2820
public function postPersist(Version $version): void
2921
{
30-
$this->resolveDistribution($version);
22+
$this->distributionResolver->schedule($version);
3123
}
3224

3325
public function postUpdate(Version $version, PostUpdateEventArgs $event): void
3426
{
3527
// Only resolve the distribution if the source has changed
3628
$changedFields = $event->getObjectManager()->getUnitOfWork()->getEntityChangeSet($version);
3729
if (isset($changedFields['source'])) {
38-
$this->resolveDistribution($version);
39-
}
40-
}
41-
42-
private function resolveDistribution(Version $version): void
43-
{
44-
if (
45-
!$this->distributionsEnabled
46-
|| ($version->isDevelopment() && !$this->resolveDevDistributions)
47-
) {
48-
return;
49-
}
50-
51-
if ($version->getPackage()->getDistributionStrategy()->isAutomatic()) {
52-
$message = Envelope::wrap(new ResolveDistribution($version->getId()))
53-
->with(new TransportNamesStamp('async'));
54-
$this->messenger->dispatch($message);
30+
$this->distributionResolver->schedule($version);
5531
}
5632
}
5733
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
namespace CodedMonkey\Dirigent\Doctrine\Repository;
4+
5+
use CodedMonkey\Dirigent\Doctrine\Entity\Distribution;
6+
use CodedMonkey\Dirigent\Doctrine\Entity\Package;
7+
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
8+
use Doctrine\Persistence\ManagerRegistry;
9+
10+
/**
11+
* @extends ServiceEntityRepository<Distribution>
12+
*
13+
* @method Distribution|null find($id, $lockMode = null, $lockVersion = null)
14+
* @method Distribution[] findAll()
15+
* @method Distribution[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
16+
* @method Distribution|null findOneBy(array $criteria, array $orderBy = null)
17+
*/
18+
class DistributionRepository extends ServiceEntityRepository
19+
{
20+
public function __construct(ManagerRegistry $registry)
21+
{
22+
parent::__construct($registry, Distribution::class);
23+
}
24+
25+
public function save(Distribution $entity, bool $flush = false): void
26+
{
27+
$this->getEntityManager()->persist($entity);
28+
29+
if ($flush) {
30+
$this->getEntityManager()->flush();
31+
}
32+
}
33+
34+
public function remove(Distribution $entity, bool $flush = false): void
35+
{
36+
$this->getEntityManager()->remove($entity);
37+
38+
if ($flush) {
39+
$this->getEntityManager()->flush();
40+
}
41+
}
42+
43+
/**
44+
* @return Distribution[]
45+
*/
46+
public function findByPackage(Package $package): array
47+
{
48+
return $this->createQueryBuilder('distribution')
49+
->leftJoin('distribution.version', 'version')
50+
->leftJoin('version.package', 'package')
51+
->andWhere('package.id = :package')
52+
->setParameter('package', $package->getId())
53+
->getQuery()
54+
->getResult();
55+
}
56+
}

0 commit comments

Comments
 (0)