Skip to content

Commit 279192e

Browse files
committed
Report a missing GPM dependency instead of fatalling
GPM::findPackage() returns false when nothing in the index matches, and InstallCommand::installDependencies() passed that straight into processPackage(?Package $package) — a TypeError, so `bin/gpm install` died on an uncatchable fatal. processPackage() already had the "Package not found on the GPM!" branch for exactly this case; the type declaration just meant it could never run. Any plugin still declaring the Grav 1.7 `admin` plugin as a dependency triggered it on Grav 2, where no `admin` package exists in the index. Two siblings read a property straight off that same false: the uninstall dependency walk before packageExists(), and calculateMergedDependenciesOfPackage(). Reported by @onetrev [getgrav/grav-premium-issues#618]
1 parent 7b2b35f commit 279192e

6 files changed

Lines changed: 39 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
# v2.0.24
2+
## 09/03/2026
3+
4+
1. [](#bugfix)
5+
* 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+
7+
# v2.0.24
8+
## 09/03/2026
9+
10+
1. [](#bugfix)
11+
* A JSON request whose body is a bare scalar (`"text"`, `12345`, `true`) sent with `Content-Type: application/json` no longer answers a 500 from the request pipeline before any route runs. It is treated as an empty body, so a plugin's webhook or API route gets to answer it, log it and refuse it itself. With `errors.display` on, the old failure also printed a stack trace with server paths to whoever sent it
12+
113
# v2.0.23
214
## 09/02/2026
315

system/defines.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
// Some standard defines
1111
define("GRAV", true);
12-
define("GRAV_VERSION", "2.0.23");
12+
define("GRAV_VERSION", "2.0.24");
1313
define("GRAV_SCHEMA", "1.8.0_2026-06-09_0");
1414
define("GRAV_TESTING", false);
1515

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,10 @@ private function calculateMergedDependenciesOfPackage($packageName, $dependencie
12251225
{
12261226
$packageData = $this->findPackage($packageName);
12271227

1228-
if (empty($packageData->dependencies)) {
1228+
// findPackage() returns false when the index has no such package, and
1229+
// reading a property off that is a PHP 8 warning before empty() ever
1230+
// sees it.
1231+
if (!$packageData || empty($packageData->dependencies)) {
12291232
return $dependencies;
12301233
}
12311234

system/src/Grav/Common/Processors/RequestProcessor.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
3939
$header = $request->getHeaderLine('Content-Type');
4040
$type = trim(strstr($header, ';', true) ?: $header);
4141
if ($type === 'application/json') {
42-
$request = $request->withParsedBody(json_decode($request->getBody()->getContents(), true));
42+
// withParsedBody() accepts an array, an object or null. A JSON scalar
43+
// ("a string", 12345, true) decodes to none of those, and handing it
44+
// over threw an InvalidArgumentException that answered the request
45+
// with a 500 before any route ran. A scalar is not a body a handler
46+
// can read, so it is treated as no body at all.
47+
$decoded = json_decode($request->getBody()->getContents(), true);
48+
$request = $request->withParsedBody(is_array($decoded) ? $decoded : null);
4349
}
4450

4551
$uri = $request->getUri();

system/src/Grav/Console/Gpm/InstallCommand.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,14 @@ public function installDependencies(array $dependencies, string $type, string $m
334334

335335
if ($answer) {
336336
foreach ($packages as $dependencyName => $dependencyVersion) {
337-
$package = $this->gpm->findPackage($dependencyName);
337+
// findPackage() returns false, not null, when nothing in the
338+
// index matches — and processPackage() is typed ?Package, so
339+
// passing that straight through was a TypeError rather than
340+
// the "Package not found on the GPM!" message it already
341+
// knows how to print. A plugin asking for a dependency that
342+
// does not exist on this Grav version (the 1.7 `admin`
343+
// plugin, say) must report it, not fatal.
344+
$package = $this->gpm->findPackage($dependencyName) ?: null;
338345
$this->processPackage($package, $type === 'update');
339346
}
340347
$io->newLine();

system/src/Grav/Console/Gpm/UninstallCommand.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ private function uninstallPackage($slug, $package, $is_dependency = false): bool
204204

205205
$dependencyPackage = $this->gpm->findPackage($dependency);
206206

207+
// Same false-not-null return as the install path: a dependency
208+
// missing from the index would otherwise reach packageExists()
209+
// and have its `package_type` read off a bool.
210+
if (!$dependencyPackage) {
211+
continue;
212+
}
213+
207214
$dependency_exists = $this->packageExists($dependency, $dependencyPackage);
208215

209216
if ($dependency_exists == Installer::EXISTS) {

0 commit comments

Comments
 (0)