diff --git a/migrations/Version20260323085126.php b/migrations/Version20260323085126.php new file mode 100644 index 0000000..91bdb69 --- /dev/null +++ b/migrations/Version20260323085126.php @@ -0,0 +1,64 @@ +addSql(<<addSql(<<addSql(<<addSql(<<id; } + public function getIndex(): int + { + return $this->index; + } + + public function setIndex(int $index): void + { + $this->index = $index; + } + public function getVersion(): Version { return $this->version; diff --git a/src/Doctrine/Entity/Version.php b/src/Doctrine/Entity/Version.php index 318f6b3..164a60c 100644 --- a/src/Doctrine/Entity/Version.php +++ b/src/Doctrine/Entity/Version.php @@ -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'])] diff --git a/src/Package/PackageMetadataResolver.php b/src/Package/PackageMetadataResolver.php index 7ad02e9..0490dad 100644 --- a/src/Package/PackageMetadataResolver.php +++ b/src/Package/PackageMetadataResolver.php @@ -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, '@')) { @@ -329,7 +330,7 @@ private function updateVersion(Package $package, Version $version, CompletePacka }, $constraint); } - $links[$link->getTarget()] = $constraint; + $links[$link->getTarget()] = ['constraint' => $constraint, 'index' => $linkIndex++]; } /** @var AbstractVersionLink $link */ @@ -337,20 +338,25 @@ private function updateVersion(Package $package, Version $version, CompletePacka $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); @@ -358,23 +364,34 @@ private function updateVersion(Package $package, Version $version, CompletePacka } // 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);