Skip to content

Commit 396bd98

Browse files
committed
Read an admin dependency as admin2 on Grav 2
A plugin declaring support for both 1.7 and 2.0 and asking for `admin >= 1.10.x` is saying it needs the admin panel. On Grav 2 that is admin2, so the requirement is met rather than unsatisfiable, and dropping it outright (as the previous commit did) threw away the intent. The version constraint is deliberately not carried over: 1.10.x describes the classic admin's numbering and says nothing about admin2's, so comparing them would be comparing unrelated version lines. Without a constraint the requirement reads "the admin panel is present", which is true on any Grav 2 site that has one, and installable when it is not. Mirrors the `replaced_by` record the compatibility registry already holds for admin. It is repeated in core because dependency resolution must not depend on a network lookup. [getgrav/grav-premium-issues#618]
1 parent 85d4ca6 commit 396bd98

3 files changed

Lines changed: 99 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
1. [](#bugfix)
55
* Installing a package whose dependency is not in the GPM index now says so and carries on, instead of stopping the command with a PHP fatal error. A plugin that still asks for the Grav 1.7 admin plugin was enough to trigger it [getgrav/grav-premium-issues#618](https://github.com/getgrav/grav-premium-issues/issues/618)
6-
* A dependency that cannot be installed on this generation of Grav is now ignored rather than attempted. A plugin that works on both 1.7 and 2.0 has no way to say "the admin plugin, but only on 1.7", so on Grav 2 that requirement is dropped instead of failing the install [getgrav/grav-premium-issues#618](https://github.com/getgrav/grav-premium-issues/issues/618)
6+
* A plugin that asks for the `admin` plugin now has that read as Admin 2 on Grav 2, so a plugin written for both 1.7 and 2.0 installs instead of failing on a dependency that cannot exist there. The version it asks for is not carried over, because it describes the old admin's numbering [getgrav/grav-premium-issues#618](https://github.com/getgrav/grav-premium-issues/issues/618)
7+
* Any other dependency that cannot be installed on this generation of Grav is now left out of the install rather than attempted and failed
78

89
# v2.0.24
910
## 09/03/2026

system/src/Grav/Common/GPM/GPM.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,43 @@ public static function declaresGravCompatibility($compatibility): bool
10831083
* @param string $slug
10841084
* @return bool
10851085
*/
1086+
/**
1087+
* Rewrite dependencies that name the admin panel under the slug the running
1088+
* generation of Grav actually ships.
1089+
*
1090+
* A plugin that supports both 1.7 and 2.0 and asks for `admin >= 1.10.x` is
1091+
* saying "I need the admin panel". On Grav 2 that is `admin2`, so the
1092+
* requirement is met by admin2 rather than being unsatisfiable. The version
1093+
* constraint is deliberately dropped: 1.10.x describes the classic admin's
1094+
* numbering and says nothing about admin2's, so carrying it over would
1095+
* compare two unrelated version lines. Without a constraint the requirement
1096+
* is simply "the admin panel is present", which is true on any Grav 2 site
1097+
* that has one — and installable when it is not
1098+
* (getgrav/grav-premium-issues#618).
1099+
*
1100+
* This mirrors the `replaced_by` record the compatibility registry already
1101+
* holds for `admin`; it is repeated here because dependency resolution must
1102+
* not depend on a network lookup.
1103+
*
1104+
* @param array $dependencies slug => version-constraint
1105+
* @return array
1106+
*/
1107+
protected function remapGenerationDependencies(array $dependencies): array
1108+
{
1109+
if (self::gravGeneration() !== '2.0' || !isset($dependencies['admin'])) {
1110+
return $dependencies;
1111+
}
1112+
1113+
unset($dependencies['admin']);
1114+
1115+
// Already required in its own right, or already there: nothing to add.
1116+
if (!isset($dependencies['admin2']) && !$this->isPluginInstalled('admin2')) {
1117+
$dependencies['admin2'] = '*';
1118+
}
1119+
1120+
return $dependencies;
1121+
}
1122+
10861123
public function dependencyIsInstallable(string $slug): bool
10871124
{
10881125
$package = $this->findPackage($slug, true);
@@ -1112,6 +1149,7 @@ public function dependencyIsInstallable(string $slug): bool
11121149
public function getDependencies($packages)
11131150
{
11141151
$dependencies = $this->calculateMergedDependenciesOfPackages($packages);
1152+
$dependencies = $this->remapGenerationDependencies($dependencies);
11151153
foreach ($dependencies as $dependency_slug => $dependencyVersionWithOperator) {
11161154
$dependency_slug = (string)$dependency_slug;
11171155
if (in_array($dependency_slug, $packages, true)) {

tests/unit/Grav/Common/GPM/GPMTest.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,65 @@ public function testDeclaresGravCompatibility(): void
351351
self::assertSame($isGrav2 ? '2.0' : '1.7', GPM::gravGeneration());
352352
}
353353

354+
/**
355+
* A plugin supporting both generations that asks for `admin` means "the
356+
* admin panel". On Grav 2 that is admin2, so the requirement is met there
357+
* rather than being unsatisfiable, and the classic admin's version
358+
* constraint is dropped because it describes a different version line.
359+
*/
360+
public function testAdminDependencyResolvesToAdmin2OnGrav2(): void
361+
{
362+
if (((int)GRAV_VERSION) < 2) {
363+
self::markTestSkipped('Behaviour is specific to Grav 2.');
364+
}
365+
366+
$this->gpm->data = [
367+
'dual-compat-plugin' => (object)[
368+
'dependencies' => [
369+
['name' => 'admin', 'version' => '>=1.10.49'],
370+
]
371+
],
372+
'admin2' => (object)[],
373+
];
374+
375+
$dependencies = $this->gpm->getDependencies(['dual-compat-plugin']);
376+
377+
self::assertArrayNotHasKey('admin', $dependencies, 'the classic admin slug never survives on Grav 2');
378+
// admin2 is not installed in the test environment, so it is offered.
379+
self::assertSame('install', $dependencies['admin2'] ?? null, 'the requirement is carried over to admin2');
380+
}
381+
382+
/**
383+
* The same requirement is simply satisfied when admin2 is already there,
384+
* which is every real Grav 2 site with an admin.
385+
*/
386+
public function testAdminDependencySatisfiedWhenAdmin2Installed(): void
387+
{
388+
if (((int)GRAV_VERSION) < 2) {
389+
self::markTestSkipped('Behaviour is specific to Grav 2.');
390+
}
391+
392+
$gpm = new class extends GpmStub {
393+
public function isPluginInstalled($slug): bool
394+
{
395+
return $slug === 'admin2';
396+
}
397+
};
398+
$gpm->data = [
399+
'dual-compat-plugin' => (object)[
400+
'dependencies' => [
401+
['name' => 'admin', 'version' => '>=1.10.49'],
402+
]
403+
],
404+
'admin2' => (object)[],
405+
];
406+
407+
$dependencies = $gpm->getDependencies(['dual-compat-plugin']);
408+
409+
self::assertArrayNotHasKey('admin', $dependencies);
410+
self::assertArrayNotHasKey('admin2', $dependencies, 'nothing to do when the admin panel is already installed');
411+
}
412+
354413
/**
355414
* A dependency is uninstallable both when the repository does not serve it
356415
* and when it serves it declaring another generation.

0 commit comments

Comments
 (0)