Skip to content

Commit 33c92e7

Browse files
committed
Add package link pages for providers and implementations
1 parent 7e409e5 commit 33c92e7

7 files changed

Lines changed: 145 additions & 1 deletion

File tree

src/Controller/Dashboard/DashboardPackagesInfoController.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public function info(string $packageName, ?string $packageVersion = null): Respo
4141
}
4242

4343
$dependentCount = $this->entityManager->getRepository(Dependent::class)->count(['dependentPackageName' => $package->getName()]);
44+
$implementationCount = $this->entityManager->getRepository(Provider::class)->count(['providedPackageName' => $package->getName(), 'implementation' => true]);
45+
$providerCount = $this->entityManager->getRepository(Provider::class)->count(['providedPackageName' => $package->getName(), 'implementation' => false]);
4446
$suggesterCount = $this->entityManager->getRepository(Suggester::class)->count(['suggestedPackageName' => $package->getName()]);
4547

4648
return $this->render('dashboard/packages/package_info.html.twig', [
@@ -49,6 +51,8 @@ public function info(string $packageName, ?string $packageVersion = null): Respo
4951
'version' => $version,
5052

5153
'dependentCount' => $dependentCount,
54+
'implementationCount' => $implementationCount,
55+
'providerCount' => $providerCount,
5256
'suggesterCount' => $suggesterCount,
5357
]);
5458
}
@@ -92,6 +96,56 @@ public function dependents(Request $request, string $packageName): Response
9296
]);
9397
}
9498

99+
#[Route('/dashboard/packages/implementations/{packageName}', name: 'dashboard_packages_implementations', requirements: ['packageName' => '[a-z0-9_.-]+/[a-z0-9_.-]+'])]
100+
#[IsGrantedAccess]
101+
public function implementations(Request $request, string $packageName): Response
102+
{
103+
$package = $this->packageRepository->findOneBy(['name' => $packageName]);
104+
105+
$providerRepository = $this->entityManager->getRepository(Provider::class);
106+
$queryBuilder = $providerRepository->createQueryBuilder('provider');
107+
$queryBuilder
108+
->leftJoin('provider.package', 'package')
109+
->andWhere('provider.providedPackageName = :packageName')
110+
->andWhere('provider.implementation = true')
111+
->setParameter('packageName', $package->getName())
112+
->addOrderBy('package.name', 'ASC');
113+
114+
$paginator = PackagePaginator::fromRequest($request, $queryBuilder, $this->container->get('router'));
115+
$providers = $paginator->getResults();
116+
117+
return $this->render('dashboard/packages/package_implementations.html.twig', [
118+
'package' => $package,
119+
'providers' => $providers,
120+
'paginator' => $paginator,
121+
]);
122+
}
123+
124+
#[Route('/dashboard/packages/providers/{packageName}', name: 'dashboard_packages_providers', requirements: ['packageName' => '[a-z0-9_.-]+/[a-z0-9_.-]+'])]
125+
#[IsGrantedAccess]
126+
public function providers(Request $request, string $packageName): Response
127+
{
128+
$package = $this->packageRepository->findOneBy(['name' => $packageName]);
129+
130+
$providerRepository = $this->entityManager->getRepository(Provider::class);
131+
$queryBuilder = $providerRepository->createQueryBuilder('provider');
132+
$queryBuilder
133+
->leftJoin('provider.package', 'package')
134+
->andWhere('provider.providedPackageName = :packageName')
135+
->andWhere('provider.implementation = false')
136+
->setParameter('packageName', $package->getName())
137+
->addOrderBy('package.name', 'ASC');
138+
139+
$paginator = PackagePaginator::fromRequest($request, $queryBuilder, $this->container->get('router'));
140+
$providers = $paginator->getResults();
141+
142+
return $this->render('dashboard/packages/package_providers.html.twig', [
143+
'package' => $package,
144+
'providers' => $providers,
145+
'paginator' => $paginator,
146+
]);
147+
}
148+
95149
#[Route('/dashboard/packages/suggesters/{packageName}', name: 'dashboard_packages_suggesters', requirements: ['packageName' => '[a-z0-9_.-]+/[a-z0-9_.-]+'])]
96150
#[IsGrantedAccess]
97151
public function suggesters(Request $request, string $packageName): Response

src/Doctrine/Entity/ProvideLink.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,14 @@ class ProvideLink extends AbstractPackageLink
1010
#[ORM\ManyToOne(targetEntity: Version::class, inversedBy: 'provide')]
1111
#[ORM\JoinColumn(nullable: false)]
1212
protected Version $version;
13+
14+
public function isImplementation(): bool
15+
{
16+
return str_ends_with($this->getLinkedPackageName(), '-implementation');
17+
}
18+
19+
public function getImplementedPackageName(): string
20+
{
21+
return substr($this->getLinkedPackageName(), 0, -15);
22+
}
1323
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% extends 'dashboard/packages/package_base.html.twig' %}
2+
3+
{% block page_title %}{{ package.name }} <small>{{ 'Implementations'|trans }}</small>{% endblock %}
4+
5+
{% block page_content %}
6+
{% include 'dashboard/packages/_package_header.html.twig' with {currentPage: 'implementations'} %}
7+
8+
{% include 'dashboard/packages/_package_list.html.twig' with {packages: providers|map(provider => provider.package)} %}
9+
{% endblock %}

templates/dashboard/packages/package_info.html.twig

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
<div><a href="{{ packageDependentsUrl }}">{{ 'Dependents'|trans }}</a>: {{ dependentCount }}</div>
5050
{% set packageSuggestersUrl = path('dashboard_packages_suggesters', {packageName: package.name}) %}
5151
<div><a href="{{ packageSuggestersUrl }}">{{ 'Suggesters'|trans }}</a>: {{ suggesterCount }}</div>
52+
{% set packageImplementationsUrl = path('dashboard_packages_implementations', {packageName: package.name}) %}
53+
<div><a href="{{ packageImplementationsUrl }}">{{ 'Implementations'|trans }}</a>: {{ implementationCount }}</div>
54+
{% set packageProvidersUrl = path('dashboard_packages_providers', {packageName: package.name}) %}
55+
<div><a href="{{ packageProvidersUrl }}">{{ 'Providers'|trans }}</a>: {{ providerCount }}</div>
5256
{% if version.license %}
5357
<div>License: {{ version.license|join(', ') }}</div>
5458
{% else %}
@@ -68,7 +72,7 @@
6872
<div class="row border-bottom pb-3 mb-3">
6973
{{ _self.linkBlock("requires", version.require) }}
7074
{{ _self.linkBlock("requires (dev)", version.devRequire) }}
71-
{{ _self.linkBlock("provides", version.provide) }}
75+
{{ _self.provideBlock("provides", version.provide) }}
7276
{{ _self.linkBlock("suggests", version.suggest) }}
7377
{{ _self.linkBlock("conflicts", version.conflict) }}
7478
{{ _self.linkBlock("replaces", version.replace) }}
@@ -98,3 +102,23 @@
98102
</ul>
99103
</div>
100104
{% endmacro %}
105+
106+
{% macro provideBlock(title, links) %}
107+
<div class="col-md-6 col-lg-4">
108+
<div class="h5">{{ title }}</div>
109+
110+
<ul>
111+
{% for link in links %}
112+
{% if link.linkedPackageName is existing_package %}
113+
<li><a href="{{ path('dashboard_packages_info', {packageName: link.linkedPackageName}) }}">{{ link.linkedPackageName }}</a>: {{ link.linkedVersionConstraint }}</li>
114+
{% elseif link.implementation and link.implementedPackageName is existing_package %}
115+
<li><a href="{{ path('dashboard_packages_info', {packageName: link.implementedPackageName}) }}">{{ link.linkedPackageName }}</a>: {{ link.linkedVersionConstraint }}</li>
116+
{% else %}
117+
<li>{{ link.linkedPackageName }}: {{ link.linkedVersionConstraint }}</li>
118+
{% endif %}
119+
{% else %}
120+
<li>None</li>
121+
{% endfor %}
122+
</ul>
123+
</div>
124+
{% endmacro %}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% extends 'dashboard/packages/package_base.html.twig' %}
2+
3+
{% block page_title %}{{ package.name }} <small>{{ 'Providers'|trans }}</small>{% endblock %}
4+
5+
{% block page_content %}
6+
{% include 'dashboard/packages/_package_header.html.twig' with {currentPage: 'providers'} %}
7+
8+
{% include 'dashboard/packages/_package_list.html.twig' with {packages: providers|map(provider => provider.package)} %}
9+
{% endblock %}

tests/FunctionalTests/Controller/Dashboard/DashboardPackagesInfoControllerTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,42 @@ public function testDependents(): void
3030
$this->assertAnySelectorTextSame('h1 small', 'Dependents');
3131
}
3232

33+
public function testImplementations(): void
34+
{
35+
$client = static::createClient();
36+
37+
/** @var UserRepository $userRepository */
38+
$userRepository = $client->getContainer()->get(UserRepository::class);
39+
40+
/** @var User $user */
41+
$user = $userRepository->findOneByUsername('user');
42+
$client->loginUser($user);
43+
44+
$client->request('GET', '/?routeName=dashboard_packages_implementations&routeParams[packageName]=psr/log');
45+
46+
$this->assertResponseStatusCodeSame(200);
47+
48+
$this->assertAnySelectorTextSame('h1 small', 'Implementations');
49+
}
50+
51+
public function testProviders(): void
52+
{
53+
$client = static::createClient();
54+
55+
/** @var UserRepository $userRepository */
56+
$userRepository = $client->getContainer()->get(UserRepository::class);
57+
58+
/** @var User $user */
59+
$user = $userRepository->findOneByUsername('user');
60+
$client->loginUser($user);
61+
62+
$client->request('GET', '/?routeName=dashboard_packages_providers&routeParams[packageName]=psr/log');
63+
64+
$this->assertResponseStatusCodeSame(200);
65+
66+
$this->assertAnySelectorTextSame('h1 small', 'Providers');
67+
}
68+
3369
public function testSuggesters(): void
3470
{
3571
$client = static::createClient();

translations/messages.en.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ Credits: Credits
44
Dashboard: Dashboard
55
Dependents: Dependents
66
Documentation: Documentation
7+
Implementations: Implementations
78
Info: Info
89
Packages: Packages
910
Personal: Personal
11+
Providers: Providers
1012
Sign out: Sign out
1113
Statistics: Statistics
1214
Suggesters: Suggesters

0 commit comments

Comments
 (0)