Skip to content

Commit 0826a7e

Browse files
committed
Add route to pin/unpin revisions of package versions
1 parent 2d65c81 commit 0826a7e

4 files changed

Lines changed: 103 additions & 11 deletions

File tree

src/Controller/Dashboard/DashboardPackagesInfoController.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\HttpFoundation\Request;
1818
use Symfony\Component\HttpFoundation\Response;
1919
use Symfony\Component\Routing\Attribute\Route;
20+
use Symfony\Component\Security\Http\Attribute\IsGranted;
2021

2122
class DashboardPackagesInfoController extends AbstractController
2223
{
@@ -90,7 +91,7 @@ public function versionMetadataList(
9091
#[MapPackage] Package $package,
9192
#[MapPackage] Version $version,
9293
): Response {
93-
$metadataCollection = $this->metadataRepository->getMetadataCollectionForVersion($version);
94+
$metadataCollection = $this->metadataRepository->findAllMetadataForVersion($version);
9495

9596
return $this->render('dashboard/packages/package_version_revisions.html.twig', [
9697
'package' => $package,
@@ -100,6 +101,46 @@ public function versionMetadataList(
100101
]);
101102
}
102103

104+
#[Route('/packages/{package}/pin-metadata/{version}', name: 'dashboard_packages_version_pin', requirements: ['package' => MapPackage::PACKAGE_REGEX, 'version' => '.*'], methods: ['POST'])]
105+
#[IsGranted('ROLE_ADMIN')]
106+
public function pinMetadata(
107+
Request $request,
108+
#[MapPackage] Package $package,
109+
#[MapPackage] Version $version,
110+
): Response {
111+
$action = (string) $request->request->get('action');
112+
113+
if (!$this->isCsrfTokenValid($action . '-revision-' . $version->getId(), (string) $request->request->get('_token'))) {
114+
throw $this->createAccessDeniedException();
115+
}
116+
117+
if ('pin' === $action) {
118+
$revision = $request->request->getInt('revision');
119+
if (null === $metadata = $this->metadataRepository->findMetadataForVersion($version, $revision)) {
120+
throw $this->createNotFoundException('The revision does not exist.');
121+
}
122+
123+
$version->setCurrentMetadata($metadata);
124+
$version->setPinned(true);
125+
} elseif ('unpin' === $action) {
126+
if (null === $latestMetadata = $this->metadataRepository->findLatestMetadataForVersion($version)) {
127+
throw $this->createNotFoundException('No metadata available for this version.');
128+
}
129+
130+
$version->setCurrentMetadata($latestMetadata);
131+
$version->setPinned(false);
132+
} else {
133+
throw $this->createNotFoundException('Invalid action.');
134+
}
135+
136+
$this->entityManager->flush();
137+
138+
return $this->redirectToRoute('dashboard_packages_version_info', [
139+
'package' => $package->getName(),
140+
'version' => $version->getName(),
141+
]);
142+
}
143+
103144
#[Route('/packages/{package}/versions', name: 'dashboard_packages_versions', requirements: ['package' => MapPackage::PACKAGE_REGEX])]
104145
#[IsGrantedAccess]
105146
public function versions(#[MapPackage] Package $package): Response

src/Doctrine/Repository/MetadataRepository.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,26 @@ public function getMetadataCountForVersion(Version $version): int
4848
return $this->count(['version' => $version]);
4949
}
5050

51-
public function getMetadataCollectionForVersion(Version $version): array
51+
public function findMetadataForVersion(Version $version, int $revision): ?Metadata
52+
{
53+
return $this->findOneBy(
54+
criteria: ['version' => $version, 'revision' => $revision],
55+
);
56+
}
57+
58+
public function findLatestMetadataForVersion(Version $version): ?Metadata
59+
{
60+
return $this->findOneBy(
61+
criteria: ['version' => $version],
62+
orderBy: ['revision' => Order::Descending->value],
63+
);
64+
}
65+
66+
public function findAllMetadataForVersion(Version $version): array
5267
{
5368
return $this->findBy(
54-
['version' => $version],
55-
['revision' => Order::Descending->value],
69+
criteria: ['version' => $version],
70+
orderBy: ['revision' => Order::Descending->value],
5671
);
5772
}
5873

templates/dashboard/packages/package_info.html.twig

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,29 @@
120120
'%version%': "<strong>#{version.name|escape}</strong>",
121121
})|raw }}
122122
</p>
123-
{% if not metadata.isCurrentMetadata %}
124-
<p class="text-warning">
125-
<strong>
126-
{{ "You're viewing an inactive revision of this package"|trans }}
127-
</strong>
128-
</p>
123+
{% if not metadata.isCurrentMetadata or version.pinned %}
124+
<div class="mb-3">
125+
{% if not metadata.isCurrentMetadata %}
126+
<div class="d-flex align-items-center">
127+
<span class="fa-solid fa-fw fa-code-branch text-warning me-1" aria-hidden="true"></span>
128+
<strong>
129+
{{ "You're viewing an inactive revision of this package"|trans }}
130+
</strong>
131+
</div>
132+
{% endif %}
133+
{% if version.pinned %}
134+
<div class="d-flex align-items-center">
135+
<span class="fa-solid fa-fw fa-thumbtack text-warning me-1" aria-hidden="true"></span>
136+
<strong>
137+
{{ 'This version is pinned. Future updates will not change the active metadata until it is unpinned.'|trans }}
138+
</strong>
139+
</div>
140+
{% endif %}
141+
</div>
129142
{% endif %}
130143
<div class="btn-toolbar gap-1">
131144
<a class="btn btn-sm btn-secondary" href="{{ path('dashboard_packages_version_metadata_list', {package: package.name, version: version.name}) }}">
132-
<span class="fa-solid fa-list me-1" aria-hidden="true"></span>
145+
<span class="fa-solid fa-hexagon-nodes me-1" aria-hidden="true"></span>
133146
<span class="btn-label">{{ 'Revisions'|trans }}</span>
134147
</a>
135148
{% if not metadata.isCurrentMetadata %}
@@ -138,6 +151,26 @@
138151
<span class="btn-label">{{ 'Current revision'|trans }}</span>
139152
</a>
140153
{% endif %}
154+
{% if version.pinned and metadata.isCurrentMetadata %}
155+
<form method="post" action="{{ path('dashboard_packages_version_pin', {package: package.name, version: version.name}) }}">
156+
<input type="hidden" name="_token" value="{{ csrf_token('unpin-revision-' ~ version.id) }}">
157+
<input type="hidden" name="action" value="unpin">
158+
<button type="submit" class="btn btn-sm btn-secondary">
159+
<span class="fa-solid fa-thumbtack-slash me-1" aria-hidden="true"></span>
160+
<span class="btn-label">{{ 'Unpin revision'|trans }}</span>
161+
</button>
162+
</form>
163+
{% elseif not version.pinned %}
164+
<form method="post" action="{{ path('dashboard_packages_version_pin', {package: package.name, version: version.name}) }}">
165+
<input type="hidden" name="_token" value="{{ csrf_token('pin-revision-' ~ version.id) }}">
166+
<input type="hidden" name="action" value="pin">
167+
<input type="hidden" name="revision" value="{{ metadata.revision }}">
168+
<button type="submit" class="btn btn-sm btn-secondary">
169+
<span class="fa-solid fa-thumbtack me-1" aria-hidden="true"></span>
170+
<span class="btn-label">{{ 'Pin revision'|trans }}</span>
171+
</button>
172+
</form>
173+
{% endif %}
141174
</div>
142175
</div>
143176
{% endif %}

translations/messages.en.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,12 @@ Suggests: Suggests
7676
Current revision: Current revision
7777
Indexed on %date%: Indexed on %date%
7878
Multiple revisions found for version %version% of package %package%: Multiple revisions found for version %version% of package %package%.
79+
Pin revision: Pin revision
7980
Revision: Revision
8081
Revisions: Revisions
8182
This version has multiple revisions: This version has multiple revisions
83+
This version is pinned. Future updates will not change the active metadata until it is unpinned.: This version is pinned. Future updates will not change the active metadata until it is unpinned.
84+
Unpin revision: Unpin revision
8285
You're viewing an inactive revision of this package: You're viewing an inactive revision of this package.
8386

8487
# Package labels (Statistics)

0 commit comments

Comments
 (0)