Skip to content

Commit 388c08c

Browse files
committed
Add package link pages for dependents and suggesters
1 parent 8d0bb90 commit 388c08c

10 files changed

Lines changed: 179 additions & 56 deletions

File tree

src/Controller/Dashboard/DashboardPackagesController.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
namespace CodedMonkey\Dirigent\Controller\Dashboard;
44

55
use CodedMonkey\Dirigent\Attribute\IsGrantedAccess;
6+
use CodedMonkey\Dirigent\Doctrine\Entity\Dependent;
67
use CodedMonkey\Dirigent\Doctrine\Entity\Package;
78
use CodedMonkey\Dirigent\Doctrine\Entity\PackageFetchStrategy;
9+
use CodedMonkey\Dirigent\Doctrine\Entity\Suggester;
810
use CodedMonkey\Dirigent\Doctrine\Repository\PackageRepository;
911
use CodedMonkey\Dirigent\EasyAdmin\PackagePaginator;
1012
use CodedMonkey\Dirigent\Form\PackageAddMirroringFormType;
@@ -74,10 +76,16 @@ public function info(string $packageName, ?string $packageVersion = null): Respo
7476
$version = $package->getLatestVersion();
7577
}
7678

79+
$dependentCount = $this->entityManager->getRepository(Dependent::class)->count(['dependentPackageName' => $package->getName()]);
80+
$suggesterCount = $this->entityManager->getRepository(Suggester::class)->count(['suggestedPackageName' => $package->getName()]);
81+
7782
return $this->render('dashboard/packages/package_info.html.twig', [
7883
'package' => $package,
7984
'latestVersion' => $latestVersion,
8085
'version' => $version,
86+
87+
'dependentCount' => $dependentCount,
88+
'suggesterCount' => $suggesterCount,
8189
]);
8290
}
8391

@@ -96,6 +104,58 @@ public function versions(string $packageName): Response
96104
]);
97105
}
98106

107+
#[Route('/dashboard/packages/dependents/{packageName}', name: 'dashboard_packages_dependents', requirements: ['packageName' => '[a-z0-9_.-]+/[a-z0-9_.-]+'])]
108+
#[IsGrantedAccess]
109+
public function dependents(Request $request, string $packageName): Response
110+
{
111+
$package = $this->packageRepository->findOneBy(['name' => $packageName]);
112+
113+
$dependentRepository = $this->entityManager->getRepository(Dependent::class);
114+
$queryBuilder = $dependentRepository->createQueryBuilder('dependent');
115+
$queryBuilder
116+
->leftJoin('dependent.package', 'package')
117+
->andWhere('dependent.dependentPackageName = :packageName')
118+
->setParameter('packageName', $package->getName())
119+
->addOrderBy('package.name', 'ASC');
120+
121+
$paginatorDto = new PaginatorDto(20, 3, 1, true, null);
122+
$paginatorDto->setPageNumber($request->query->getInt('page', 1));
123+
$paginator = (new PackagePaginator($this->adminUrlGenerator))->paginate($paginatorDto, $queryBuilder);
124+
$dependents = $paginator->getResults();
125+
126+
return $this->render('dashboard/packages/package_dependents.html.twig', [
127+
'package' => $package,
128+
'dependents' => $dependents,
129+
'paginator' => $paginator,
130+
]);
131+
}
132+
133+
#[Route('/dashboard/packages/suggesters/{packageName}', name: 'dashboard_packages_suggesters', requirements: ['packageName' => '[a-z0-9_.-]+/[a-z0-9_.-]+'])]
134+
#[IsGrantedAccess]
135+
public function suggesters(Request $request, string $packageName): Response
136+
{
137+
$package = $this->packageRepository->findOneBy(['name' => $packageName]);
138+
139+
$suggesterRepository = $this->entityManager->getRepository(Suggester::class);
140+
$queryBuilder = $suggesterRepository->createQueryBuilder('suggester');
141+
$queryBuilder
142+
->leftJoin('suggester.package', 'package')
143+
->andWhere('suggester.suggestedPackageName = :packageName')
144+
->setParameter('packageName', $package->getName())
145+
->addOrderBy('package.name', 'ASC');
146+
147+
$paginatorDto = new PaginatorDto(20, 3, 1, true, null);
148+
$paginatorDto->setPageNumber($request->query->getInt('page', 1));
149+
$paginator = (new PackagePaginator($this->adminUrlGenerator))->paginate($paginatorDto, $queryBuilder);
150+
$suggesters = $paginator->getResults();
151+
152+
return $this->render('dashboard/packages/package_suggesters.html.twig', [
153+
'package' => $package,
154+
'suggesters' => $suggesters,
155+
'paginator' => $paginator,
156+
]);
157+
}
158+
99159
#[Route('/dashboard/packages/statistics/{packageName}', name: 'dashboard_packages_statistics', requirements: ['packageName' => '[a-z0-9_.-]+/[a-z0-9_.-]+'])]
100160
#[IsGrantedAccess]
101161
public function statistics(string $packageName): Response

src/EasyAdmin/PackagePaginator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function paginate(PaginatorDto $paginatorDto, QueryBuilder $queryBuilder)
4040
->setMaxResults($this->pageSize)
4141
->getQuery();
4242

43-
$paginator = new Paginator($query, $paginatorDto->fetchJoinCollection());
43+
$paginator = new Paginator($query, false);
4444

4545
$this->results = $paginator->getIterator();
4646
$this->numResults = $paginator->count();
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<div class="d-grid gap-3">
2+
{% for package in packages %}
3+
<div class="card">
4+
<div class="card-body py-2">
5+
{% set packageInfoUrl = dashboard_path('dashboard_packages_info', {packageName: package.name}) %}
6+
<a href="{{ packageInfoUrl }}"><h5 class="card-title">{{ package.name }}</h5></a>
7+
{% if package.mirrorRegistry %}
8+
<p class="card-text mb-1 text-body-secondary">Mirrored from {{ package.mirrorRegistry.name }}</p>
9+
{% endif %}
10+
<p class="card-text">{{ package.description ?? '<em>No description provided.</em>' }}</p>
11+
</div>
12+
</div>
13+
{% else %}
14+
<table class="table datagrid datagrid-empty">
15+
<tbody>
16+
{% for i in 1..14 %}
17+
<tr class="empty-row">
18+
<td><span></span></td>
19+
<td><span></span></td>
20+
<td><span></span></td>
21+
<td><span></span></td>
22+
<td><span></span></td>
23+
<td><span></span></td>
24+
</tr>
25+
26+
{% if 3 == loop.index %}
27+
<tr class="no-results">
28+
<td colspan="100">
29+
{{ t('datagrid.no_results', ea.i18n.translationParameters, 'EasyAdminBundle')|trans }}
30+
</td>
31+
</tr>
32+
{% endif %}
33+
{% endfor %}
34+
</tbody>
35+
</table>
36+
{% endfor %}
37+
</div>
38+
39+
{% if packages|length %}
40+
<div class="content-panel-footer without-padding without-border">
41+
{% block paginator %}
42+
{{ include(ea.templatePath('crud/paginator')) }}
43+
{% endblock paginator %}
44+
</div>
45+
{% endif %}

templates/dashboard/packages/list.html.twig

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -25,49 +25,5 @@
2525
{% endblock %}
2626

2727
{% block page_content %}
28-
<div class="d-grid gap-3">
29-
{% for package in packages %}
30-
<div class="card">
31-
<div class="card-body py-2">
32-
{% set packageInfoUrl = dashboard_path('dashboard_packages_info', {packageName: package.name}) %}
33-
<a href="{{ packageInfoUrl }}"><h5 class="card-title">{{ package.name }}</h5></a>
34-
{% if package.mirrorRegistry %}
35-
<p class="card-text mb-1 text-body-secondary">Mirrored from {{ package.mirrorRegistry.name }}</p>
36-
{% endif %}
37-
<p class="card-text">{{ package.description ?? '<em>No description provided.</em>' }}</p>
38-
</div>
39-
</div>
40-
{% else %}
41-
<table class="table datagrid datagrid-empty">
42-
<tbody>
43-
{% for i in 1..14 %}
44-
<tr class="empty-row">
45-
<td><span></span></td>
46-
<td><span></span></td>
47-
<td><span></span></td>
48-
<td><span></span></td>
49-
<td><span></span></td>
50-
<td><span></span></td>
51-
</tr>
52-
53-
{% if 3 == loop.index %}
54-
<tr class="no-results">
55-
<td colspan="100">
56-
{{ t('datagrid.no_results', ea.i18n.translationParameters, 'EasyAdminBundle')|trans }}
57-
</td>
58-
</tr>
59-
{% endif %}
60-
{% endfor %}
61-
</tbody>
62-
</table>
63-
{% endfor %}
64-
</div>
65-
66-
{% if packages|length %}
67-
<div class="content-panel-footer without-padding without-border">
68-
{% block paginator %}
69-
{{ include(ea.templatePath('crud/paginator')) }}
70-
{% endblock paginator %}
71-
</div>
72-
{% endif %}
28+
{% include 'dashboard/packages/_package_list.html.twig' %}
7329
{% endblock %}
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>{{ 'Dependents'|trans }}</small>{% endblock %}
4+
5+
{% block page_content %}
6+
{% include 'dashboard/packages/package_header.html.twig' with {currentPage: 'dependents'} %}
7+
8+
{% include 'dashboard/packages/_package_list.html.twig' with {packages: dependents|map(dependent => dependent.package)} %}
9+
{% endblock %}

templates/dashboard/packages/package_header.html.twig

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
<a {% if currentPage == 'versions' %}class="nav-link active" aria-current="page"{% else %}class="nav-link text-primary"{% endif%} href="{{ packageVersionsUrl }}">{{ 'Versions'|trans }}</a>
1111
</li>
1212
<li class="nav-item">
13-
<span class="nav-link disabled">{{ 'Dependants'|trans }}</span>
13+
{% set packageDependentsUrl = dashboard_path('dashboard_packages_dependents', {packageName: package.name}) %}
14+
<a {% if currentPage == 'dependents' %}class="nav-link active" aria-current="page"{% else %}class="nav-link text-primary"{% endif%} href="{{ packageDependentsUrl }}">{{ 'Dependents'|trans }}</a>
1415
</li>
1516
<li class="nav-item">
16-
{% set packageVersionsUrl = dashboard_path('dashboard_packages_statistics', {packageName: package.name}) %}
17-
<a {% if currentPage == 'statistics' %}class="nav-link active" aria-current="page"{% else %}class="nav-link text-primary"{% endif%} href="{{ packageVersionsUrl }}">{{ 'Statistics'|trans }}</a>
17+
{% set packageStatisticsUrl = dashboard_path('dashboard_packages_statistics', {packageName: package.name}) %}
18+
<a {% if currentPage == 'statistics' %}class="nav-link active" aria-current="page"{% else %}class="nav-link text-primary"{% endif%} href="{{ packageStatisticsUrl }}">{{ 'Statistics'|trans }}</a>
1819
</li>
1920
</ul>

templates/dashboard/packages/package_info.html.twig

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
<div><a href="{{ version.source.url }}">Source</a></div>
4646
{% endif %}
4747
<div>Installs: {{ package.installations.total }}</div>
48+
{% set packageDependentsUrl = dashboard_path('dashboard_packages_dependents', {packageName: package.name}) %}
49+
<div><a href="{{ packageDependentsUrl }}">{{ 'Dependents'|trans }}</a>: {{ dependentCount }}</div>
50+
{% set packageSuggestersUrl = dashboard_path('dashboard_packages_suggesters', {packageName: package.name}) %}
51+
<div><a href="{{ packageSuggestersUrl }}">{{ 'Suggesters'|trans }}</a>: {{ suggesterCount }}</div>
4852
{% if version.license %}
4953
<div>License: {{ version.license|join(', ') }}</div>
5054
{% else %}
@@ -83,10 +87,10 @@
8387

8488
<ul>
8589
{% for link in links %}
86-
{% if link.packageName is existing_package %}
87-
<li><a href="{{ dashboard_path('dashboard_packages_info', {packageName: link.packageName}) }}">{{ link.packageName }}</a>: {{ link.packageVersion }}</li>
90+
{% if link.linkedPackageName is existing_package %}
91+
<li><a href="{{ dashboard_path('dashboard_packages_info', {packageName: link.linkedPackageName}) }}">{{ link.linkedPackageName }}</a>: {{ link.linkedVersionConstraint }}</li>
8892
{% else %}
89-
<li>{{ link.packageName }}: {{ link.packageVersion }}</li>
93+
<li>{{ link.linkedPackageName }}: {{ link.linkedVersionConstraint }}</li>
9094
{% endif %}
9195
{% else %}
9296
<li>None</li>
@@ -101,10 +105,10 @@
101105

102106
<ul>
103107
{% for link in links %}
104-
{% if link.packageName is existing_package %}
105-
<li><a href="{{ dashboard_path('dashboard_packages_info', {packageName: link.packageName}) }}">{{ link.packageName }}</a>: {{ link.packageVersion }}</li>
108+
{% if link.linkedPackageName is existing_package %}
109+
<li><a href="{{ dashboard_path('dashboard_packages_info', {packageName: link.linkedPackageName}) }}">{{ link.linkedPackageName }}</a>: {{ link.linkedVersionConstraint }}</li>
106110
{% else %}
107-
<li>{{ link.packageName }}: {{ link.packageVersion }}</li>
111+
<li>{{ link.linkedPackageName }}: {{ link.linkedVersionConstraint }}</li>
108112
{% endif %}
109113
{% else %}
110114
<li>None</li>
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>{{ 'Suggesters'|trans }}</small>{% endblock %}
4+
5+
{% block page_content %}
6+
{% include 'dashboard/packages/package_header.html.twig' %}
7+
8+
{% include 'dashboard/packages/_package_list.html.twig' with {packages: suggesters|map(suggester => suggester.package)} %}
9+
{% endblock %}

tests/FunctionalTests/DashboardPackagesControllerTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,52 @@
22

33
namespace CodedMonkey\Dirigent\Tests\FunctionalTests;
44

5+
use CodedMonkey\Dirigent\Doctrine\Entity\User;
56
use CodedMonkey\Dirigent\Doctrine\Repository\PackageRepository;
67
use CodedMonkey\Dirigent\Doctrine\Repository\RegistryRepository;
8+
use CodedMonkey\Dirigent\Doctrine\Repository\UserRepository;
79
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
810

911
class DashboardPackagesControllerTest extends WebTestCase
1012
{
1113
use WebTestCaseTrait;
1214

15+
public function testDependents(): void
16+
{
17+
$client = static::createClient();
18+
19+
/** @var UserRepository $userRepository */
20+
$userRepository = $client->getContainer()->get(UserRepository::class);
21+
22+
/** @var User $user */
23+
$user = $userRepository->findOneByUsername('user');
24+
$client->loginUser($user);
25+
26+
$client->request('GET', '/?routeName=dashboard_packages_dependents&routeParams[packageName]=psr/log');
27+
28+
$this->assertResponseStatusCodeSame(200);
29+
30+
$this->assertAnySelectorTextSame('h1 small', 'Dependents');
31+
}
32+
33+
public function testSuggesters(): 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_suggesters&routeParams[packageName]=psr/log');
45+
46+
$this->assertResponseStatusCodeSame(200);
47+
48+
$this->assertAnySelectorTextSame('h1 small', 'Suggesters');
49+
}
50+
1351
public function testStatistics(): void
1452
{
1553
$client = static::createClient();

translations/messages.en.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ Account: Account
22
Administration: Administration
33
Credits: Credits
44
Dashboard: Dashboard
5-
Dependants: Dependants
5+
Dependents: Dependents
66
Documentation: Documentation
77
Info: Info
88
Packages: Packages
99
Personal: Personal
1010
Sign out: Sign out
1111
Statistics: Statistics
12+
Suggesters: Suggesters
1213
Usage: Usage
1314

1415
Access token: Access token

0 commit comments

Comments
 (0)