Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions migrations/Version20260323085126.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20260323085126 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add version link indices';
}

public function up(Schema $schema): void
{
$tables = [
'version_conflict_link',
'version_dev_require_link',
'version_provide_link',
'version_replace_link',
'version_require_link',
'version_suggest_link',
];

foreach ($tables as $table) {
$this->addSql(<<<SQL
ALTER TABLE $table ADD index INT DEFAULT NULL
SQL);
$this->addSql(<<<SQL
UPDATE $table t
SET "index" = sub.row_num - 1
FROM (
SELECT id, ROW_NUMBER() OVER (PARTITION BY version_id ORDER BY id) AS row_num
FROM $table
) sub
WHERE t.id = sub.id
SQL);
$this->addSql(<<<SQL
ALTER TABLE $table ALTER COLUMN index SET NOT NULL
SQL);
}
}

public function down(Schema $schema): void
{
$tables = [
'version_conflict_link',
'version_dev_require_link',
'version_provide_link',
'version_replace_link',
'version_require_link',
'version_suggest_link',
];

foreach ($tables as $table) {
$this->addSql(<<<SQL
ALTER TABLE $table DROP index
SQL);
}
}
}
13 changes: 13 additions & 0 deletions src/Doctrine/Entity/AbstractVersionLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ abstract class AbstractVersionLink

protected Version $version;

#[ORM\Column]
private int $index;

#[ORM\Column(length: 191)]
private string $linkedPackageName;

Expand All @@ -26,6 +29,16 @@ public function getId(): ?int
return $this->id;
}

public function getIndex(): int
{
return $this->index;
}

public function setIndex(int $index): void
{
$this->index = $index;
}

public function getVersion(): Version
{
return $this->version;
Expand Down
6 changes: 6 additions & 0 deletions src/Doctrine/Entity/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,27 @@ class Version extends TrackedEntity implements \Stringable
private ?array $dist = null;

#[ORM\OneToMany(mappedBy: 'version', targetEntity: VersionRequireLink::class, cascade: ['persist', 'detach', 'remove'])]
#[ORM\OrderBy(['index' => 'ASC'])]
private Collection $require;

#[ORM\OneToMany(mappedBy: 'version', targetEntity: VersionDevRequireLink::class, cascade: ['persist', 'detach', 'remove'])]
#[ORM\OrderBy(['index' => 'ASC'])]
private Collection $devRequire;

#[ORM\OneToMany(mappedBy: 'version', targetEntity: VersionConflictLink::class, cascade: ['persist', 'detach', 'remove'])]
#[ORM\OrderBy(['index' => 'ASC'])]
private Collection $conflict;

#[ORM\OneToMany(mappedBy: 'version', targetEntity: VersionProvideLink::class, cascade: ['persist', 'detach', 'remove'])]
#[ORM\OrderBy(['index' => 'ASC'])]
private Collection $provide;

#[ORM\OneToMany(mappedBy: 'version', targetEntity: VersionReplaceLink::class, cascade: ['persist', 'detach', 'remove'])]
#[ORM\OrderBy(['index' => 'ASC'])]
private Collection $replace;

#[ORM\OneToMany(mappedBy: 'version', targetEntity: VersionSuggestLink::class, cascade: ['persist', 'detach', 'remove'])]
#[ORM\OrderBy(['index' => 'ASC'])]
private Collection $suggest;

#[ORM\ManyToMany(targetEntity: Keyword::class, inversedBy: 'versions', cascade: ['persist', 'detach', 'remove'])]
Expand Down
33 changes: 25 additions & 8 deletions src/Package/PackageMetadataResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ private function updateVersion(Package $package, Version $version, CompletePacka
// handle links
foreach (self::SUPPORTED_LINK_TYPES as $linkType => $opts) {
$links = [];
$linkIndex = 0;
foreach ($data->{$opts['method']}() as $link) {
$constraint = $link->getPrettyConstraint();
if (str_contains($constraint, ',') && str_contains($constraint, '@')) {
Expand All @@ -329,52 +330,68 @@ private function updateVersion(Package $package, Version $version, CompletePacka
}, $constraint);
}

$links[$link->getTarget()] = $constraint;
$links[$link->getTarget()] = ['constraint' => $constraint, 'index' => $linkIndex++];
}

/** @var AbstractVersionLink $link */
foreach ($version->{'get' . $linkType}() as $link) {
$linkPackageName = $link->getLinkedPackageName();

// Clear links that have changed/disappeared (for updates)
if (!isset($links[$linkPackageName]) || $links[$linkPackageName] !== $link->getLinkedVersionConstraint()) {
if (!isset($links[$linkPackageName]) || $links[$linkPackageName]['constraint'] !== $link->getLinkedVersionConstraint()) {
$version->{'get' . $linkType}()->removeElement($link);
$em->remove($link);
} else {
// Update index if it changed
if ($link->getIndex() !== $links[$linkPackageName]['index']) {
$link->setIndex($links[$linkPackageName]['index']);
}
// Clear those that are already set
unset($links[$linkPackageName]);
}
}

foreach ($links as $linkPackageName => $linkPackageConstraint) {
foreach ($links as $linkPackageName => $linkData) {
/** @var AbstractVersionLink $link */
$link = new $opts['entity']();
$link->setLinkedPackageName($linkPackageName);
$link->setLinkedVersionConstraint($linkPackageConstraint);
$link->setLinkedVersionConstraint($linkData['constraint']);
$link->setIndex($linkData['index']);
$version->{'add' . $linkType . 'Link'}($link);
$link->setVersion($version);
$em->persist($link);
}
}

// handle suggests
if ($suggests = $data->getSuggests()) {
if ($suggestsData = $data->getSuggests()) {
$suggests = [];
$suggestIndex = 0;
foreach ($suggestsData as $suggestPackageName => $suggestConstraint) {
$suggests[$suggestPackageName] = ['constraint' => $suggestConstraint, 'index' => $suggestIndex++];
}

foreach ($version->getSuggest() as $link) {
$linkPackageName = $link->getLinkedPackageName();
// clear links that have changed/disappeared (for updates)
if (!isset($suggests[$linkPackageName]) || $suggests[$linkPackageName] !== $link->getLinkedVersionConstraint()) {
if (!isset($suggests[$linkPackageName]) || $suggests[$linkPackageName]['constraint'] !== $link->getLinkedVersionConstraint()) {
$version->getSuggest()->removeElement($link);
$em->remove($link);
} else {
// Update index if it changed
if ($link->getIndex() !== $suggests[$linkPackageName]['index']) {
$link->setIndex($suggests[$linkPackageName]['index']);
}
// clear those that are already set
unset($suggests[$linkPackageName]);
}
}

foreach ($suggests as $linkPackageName => $linkPackageConstraint) {
foreach ($suggests as $linkPackageName => $linkData) {
$link = new VersionSuggestLink();
$link->setLinkedPackageName($linkPackageName);
$link->setLinkedVersionConstraint($linkPackageConstraint);
$link->setLinkedVersionConstraint($linkData['constraint']);
$link->setIndex($linkData['index']);
$version->addSuggestLink($link);
$link->setVersion($version);
$em->persist($link);
Expand Down
Loading