Skip to content

Commit 80b68f2

Browse files
alamiraultakondas
andauthored
Show when package is deprecated (#567)
* Show when package is deprecated * ClearMetadataCacheCommandTest avoid using same temporary folder that other tests Co-authored-by: Arkadiusz Kondas <[email protected]>
1 parent 98f4174 commit 80b68f2

File tree

13 files changed

+186
-7
lines changed

13 files changed

+186
-7
lines changed

src/Entity/Organization/Package.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ class Package
132132
*/
133133
private int $keepLastReleases = 0;
134134

135+
/**
136+
* @ORM\Column(type="text", nullable=true)
137+
*/
138+
private ?string $replacementPackage = null;
139+
135140
/**
136141
* @param mixed[] $metadata
137142
*/
@@ -381,4 +386,14 @@ public function update(string $url, int $keepLastReleases): void
381386
$this->keepLastReleases = $keepLastReleases;
382387
$this->repositoryUrl = $url;
383388
}
389+
390+
public function getReplacementPackage(): ?string
391+
{
392+
return $this->replacementPackage;
393+
}
394+
395+
public function setReplacementPackage(?string $replacementPackage): void
396+
{
397+
$this->replacementPackage = $replacementPackage;
398+
}
384399
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Buddy\Repman\Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
final class Version20220220163835 extends AbstractMigration
11+
{
12+
public function getDescription(): string
13+
{
14+
return 'Add replacement_package on package table';
15+
}
16+
17+
public function up(Schema $schema): void
18+
{
19+
$this->addSql('ALTER TABLE organization_package ADD replacement_package TEXT DEFAULT NULL');
20+
}
21+
22+
public function down(Schema $schema): void
23+
{
24+
$this->addSql('ALTER TABLE organization_package DROP replacement_package');
25+
}
26+
}

src/Query/User/Model/PackageDetails.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ final class PackageDetails
1818
private ?string $lastSyncError;
1919
private int $keepLastReleases;
2020
private ?string $readme;
21+
private ?string $replacementPackage;
2122

2223
public function __construct(
2324
string $id,
@@ -30,7 +31,8 @@ public function __construct(
3031
?string $lastSyncError = null,
3132
?ScanResult $scanResult = null,
3233
int $keepLastReleases = 0,
33-
?string $readme = null
34+
?string $readme = null,
35+
?string $replacementPackage = null
3436
) {
3537
$this->id = $id;
3638
$this->organizationId = $organizationId;
@@ -43,6 +45,7 @@ public function __construct(
4345
$this->scanResult = $scanResult ?? null;
4446
$this->keepLastReleases = $keepLastReleases;
4547
$this->readme = $readme;
48+
$this->replacementPackage = $replacementPackage;
4649
}
4750

4851
public function id(): string
@@ -99,4 +102,14 @@ public function isSynchronizedSuccessfully(): bool
99102
{
100103
return $this->name() !== null && $this->lastSyncError() === null;
101104
}
105+
106+
public function isAbandoned(): bool
107+
{
108+
return !is_null($this->replacementPackage);
109+
}
110+
111+
public function getReplacementPackage(): ?string
112+
{
113+
return $this->replacementPackage;
114+
}
102115
}

src/Query/User/PackageQuery/DbalPackageQuery.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ public function getDetailsById(string $id): Option
190190
last_scan_status,
191191
last_scan_result,
192192
keep_last_releases,
193-
readme
193+
readme,
194+
replacement_package
194195
FROM "organization_package"
195196
WHERE id = :id', [
196197
'id' => $id,
@@ -455,6 +456,7 @@ private function hydratePackageDetails(array $data): PackageDetails
455456
$scanResult,
456457
$data['keep_last_releases'] ?? 0,
457458
$data['readme'] ?? null,
459+
$data['replacement_package'] ?? null,
458460
);
459461
}
460462

src/Service/PackageSynchronizer/ComposerPackageSynchronizer.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Buddy\Repman\Service\PackageSynchronizer;
66

77
use Buddy\Repman\Entity\Organization\Package;
8+
use Buddy\Repman\Entity\Organization\Package\Abandoned;
89
use Buddy\Repman\Entity\Organization\Package\Link;
910
use Buddy\Repman\Entity\Organization\Package\Version;
1011
use Buddy\Repman\Repository\PackageRepository;
@@ -175,6 +176,13 @@ public function synchronize(Package $package): void
175176
$package->addLink(new Link(Uuid::uuid4(), $package, 'suggests', $linkName, $linkDescription));
176177
$encounteredLinks['suggests-'.$linkName] = true;
177178
}
179+
180+
// Is abandoned ?
181+
if ($latest instanceof CompletePackage && $latest->isAbandoned()) {
182+
$package->setReplacementPackage($latest->getReplacementPackage() ?? '');
183+
} else {
184+
$package->setReplacementPackage(null);
185+
}
178186
}
179187

180188
$package->addOrUpdateVersion(

templates/organization/package/details.html.twig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@
1616
{% block content %}
1717

1818
{% if package.name %}
19+
{% if package.isAbandoned %}
20+
<div class="row">
21+
<div class="col-12">
22+
<div class="alert alert-danger">
23+
{% if package.replacementPackage is not empty %}
24+
This package is <b>abandoned</b> and no longer maintained. The author suggests using the <b>{{ package.replacementPackage }}</b> package instead.
25+
{% else %}
26+
This package is <b>abandoned</b> and no longer maintained. No replacement package was suggested.
27+
{% endif %}
28+
</div>
29+
</div>
30+
</div>
31+
{% endif %}
1932
<div class="row">
2033
<div class="col-3">
2134
<h4>Package name</h4>

tests/Doubles/FakePackageSynchronizer.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ final class FakePackageSynchronizer implements PackageSynchronizer
1919
private \DateTimeImmutable $latestReleaseDate;
2020
private ?string $error = null;
2121
private ?string $readme = null;
22+
private ?string $replacementPackage = null;
2223

2324
/**
2425
* @var Version[]
@@ -39,7 +40,7 @@ public function __construct()
3940
* @param Version[] $versions
4041
* @param LinkModel[] $links
4142
*/
42-
public function setData(string $name, string $description, string $latestReleasedVersion, \DateTimeImmutable $latestReleaseDate, array $versions = [], array $links = [], ?string $readme = null): void
43+
public function setData(string $name, string $description, string $latestReleasedVersion, \DateTimeImmutable $latestReleaseDate, array $versions = [], array $links = [], ?string $readme = null, ?string $replacementPackage = null): void
4344
{
4445
$this->name = $name;
4546
$this->description = $description;
@@ -49,6 +50,7 @@ public function setData(string $name, string $description, string $latestRelease
4950
$this->versions = $versions;
5051
$this->links = $links;
5152
$this->readme = $readme;
53+
$this->replacementPackage = $replacementPackage;
5254
}
5355

5456
public function setError(string $error): void
@@ -65,6 +67,7 @@ public function synchronize(Package $package): void
6567
}
6668

6769
$package->setReadme($this->readme);
70+
$package->setReplacementPackage($this->replacementPackage);
6871
$encounteredVersions = [];
6972
foreach ($this->versions as $version) {
7073
$package->addOrUpdateVersion($version);

tests/Functional/Command/ClearMetadataCacheCommandTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class ClearMetadataCacheCommandTest extends FunctionalTestCase
1515
{
1616
public function testClearMetadataCache(): void
1717
{
18-
$basePath = \sys_get_temp_dir().'/'.'repman';
18+
$basePath = \sys_get_temp_dir().'/'.'repman/clear-metadata';
1919

2020
$ignoredFiles = [
2121
$basePath.'/dist/.svn/foo/packages.json',
@@ -50,7 +50,7 @@ public function testClearMetadataCache(): void
5050

5151
public function testNoMetadataFilesFound(): void
5252
{
53-
$basePath = \sys_get_temp_dir().'/'.'repman';
53+
$basePath = \sys_get_temp_dir().'/'.'repman/clear-metadata';
5454

5555
$command = new ClearMetadataCacheCommand(new Filesystem(new Local($basePath)));
5656
$commandTester = new CommandTester($command);

tests/Functional/Controller/OrganizationControllerTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ public function testPackageDetails(): void
515515
self::assertStringContainsString('depends:buddy-works/buddy', $this->lastResponseBody());
516516

517517
self::assertStringContainsString('This is a readme', $this->lastResponseBody());
518+
self::assertStringNotContainsString('This package is <b>abandoned</b>', $this->lastResponseBody());
518519

519520
$this->client->request('GET', $this->urlTo('organization_package_details', [
520521
'organization' => 'buddy',
@@ -524,6 +525,40 @@ public function testPackageDetails(): void
524525
self::assertTrue($this->client->getResponse()->isNotFound());
525526
}
526527

528+
/**
529+
* @dataProvider getAbandonedReplacements
530+
*/
531+
public function testPackageDetailsAbandoned(string $replacementPackage, string $expectedMessage): void
532+
{
533+
$buddyId = $this->fixtures->createOrganization('buddy', $this->userId);
534+
$packageId = $this->fixtures->addPackage($buddyId, 'https://buddy.com');
535+
$this->fixtures->syncPackageWithData($packageId, 'buddy-works/buddy', 'Test', '1.1.1', new \DateTimeImmutable(), [], [], null, $replacementPackage);
536+
537+
$this->client->request('GET', $this->urlTo('organization_package_details', [
538+
'organization' => 'buddy',
539+
'package' => $packageId,
540+
]));
541+
542+
self::assertTrue($this->client->getResponse()->isOk());
543+
self::assertStringContainsString($expectedMessage, $this->lastResponseBody());
544+
}
545+
546+
/**
547+
* @return \Generator<array<mixed>>
548+
*/
549+
public function getAbandonedReplacements(): \Generator
550+
{
551+
yield 'Abandoned without replacement package' => [
552+
'',
553+
'This package is <b>abandoned</b> and no longer maintained. No replacement package was suggested.',
554+
];
555+
556+
yield 'Abandoned with replacement package' => [
557+
'foo/bar',
558+
'This package is <b>abandoned</b> and no longer maintained. The author suggests using the <b>foo/bar</b> package instead.',
559+
];
560+
}
561+
527562
public function testPackageStats(): void
528563
{
529564
$buddyId = $this->fixtures->createOrganization('buddy', $this->userId);

tests/Integration/FixturesManager.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,9 @@ public function syncPackageWithError(string $packageId, string $error): void
203203
* @param Version[] $versions
204204
* @param Link[] $links
205205
*/
206-
public function syncPackageWithData(string $packageId, string $name, string $description, string $latestReleasedVersion, \DateTimeImmutable $latestReleaseDate, array $versions = [], array $links = [], ?string $readme = null): void
206+
public function syncPackageWithData(string $packageId, string $name, string $description, string $latestReleasedVersion, \DateTimeImmutable $latestReleaseDate, array $versions = [], array $links = [], ?string $readme = null, ?string $replacementPackage = null): void
207207
{
208-
$this->container->get(PackageSynchronizer::class)->setData($name, $description, $latestReleasedVersion, $latestReleaseDate, $versions, $links, $readme);
208+
$this->container->get(PackageSynchronizer::class)->setData($name, $description, $latestReleasedVersion, $latestReleaseDate, $versions, $links, $readme, $replacementPackage);
209209
$this->dispatchMessage(new SynchronizePackage($packageId));
210210
$this->container->get(EntityManagerInterface::class)->flush();
211211
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "foo/foo",
3+
"description": "Abandoned package",
4+
"type": "library",
5+
"require": {
6+
},
7+
"require-dev": {
8+
},
9+
"license": "MIT",
10+
"abandoned": "foo/bar"
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "foo/foo",
3+
"description": "Abandoned package",
4+
"type": "library",
5+
"require": {
6+
},
7+
"require-dev": {
8+
},
9+
"license": "MIT",
10+
"abandoned": true
11+
}

tests/Unit/Service/PackageSynchronizer/ComposerPackageSynchronizerTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,48 @@ public function testSynchronizePackageWithLimitedNumberOfVersions(): void
227227
self::assertEquals(['1.1.1', '1.2.0'], $versionStrings);
228228
}
229229

230+
public function testSynchronizePackageAbandonedWithReplacementPackage(): void
231+
{
232+
// prepare package in path without git
233+
$resPath = $this->resourcesDir.'path/abandoned-replacement-package/composer.json';
234+
$tmpPath = sys_get_temp_dir().'/repman/path/abandoned-replacement-package/composer.json';
235+
if (!is_dir(dirname($tmpPath))) {
236+
mkdir(dirname($tmpPath), 0777, true);
237+
}
238+
copy($resPath, $tmpPath);
239+
240+
$package = PackageMother::withOrganization('path', dirname($tmpPath), 'buddy');
241+
242+
/* @phpstan-ignore-next-line */
243+
$this->downloader->addContent(dirname($tmpPath), file_get_contents($tmpPath));
244+
$this->synchronizer->synchronize($package);
245+
246+
self::assertEquals('foo/bar', $this->getProperty($package, 'replacementPackage'));
247+
@unlink($this->baseDir.'/buddy/p/some/package.json');
248+
@unlink($tmpPath);
249+
}
250+
251+
public function testSynchronizePackageAbandonedWithoutReplacementPackage(): void
252+
{
253+
// prepare package in path without git
254+
$resPath = $this->resourcesDir.'path/abandoned-without-replacement-package/composer.json';
255+
$tmpPath = sys_get_temp_dir().'/repman/path/abandoned-without-replacement-package/composer.json';
256+
if (!is_dir(dirname($tmpPath))) {
257+
mkdir(dirname($tmpPath), 0777, true);
258+
}
259+
copy($resPath, $tmpPath);
260+
261+
$package = PackageMother::withOrganization('path', dirname($tmpPath), 'buddy');
262+
263+
/* @phpstan-ignore-next-line */
264+
$this->downloader->addContent(dirname($tmpPath), file_get_contents($tmpPath));
265+
$this->synchronizer->synchronize($package);
266+
267+
self::assertEquals('', $this->getProperty($package, 'replacementPackage'));
268+
@unlink($this->baseDir.'/buddy/p/some/package.json');
269+
@unlink($tmpPath);
270+
}
271+
230272
/**
231273
* @return mixed
232274
*/

0 commit comments

Comments
 (0)