From d6cbc4ab892bc350fd6b0ace194fb2c6ec218d3e Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 17 Aug 2026 02:37:34 +0000 Subject: [PATCH 1/2] fix(extension manager): let flarum/core survive the update-check filter The update check skips any package that is not an installed extension. flarum/core is not one, so it was dropped on every run, even though surfacing a new major of it is the stated purpose of the first composer outdated call, and both LastUpdateCheck::getNewMajorVersion() and the admin frontend read a flarum/core entry back out of that list. --- .../src/Command/CheckForUpdatesHandler.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/extensions/package-manager/src/Command/CheckForUpdatesHandler.php b/extensions/package-manager/src/Command/CheckForUpdatesHandler.php index e5dda3ed36..0ba88dd3ab 100755 --- a/extensions/package-manager/src/Command/CheckForUpdatesHandler.php +++ b/extensions/package-manager/src/Command/CheckForUpdatesHandler.php @@ -76,8 +76,13 @@ public function handle(CheckForUpdates $command): array $composerJson = $this->composerJson->get(); foreach ($installed as $mainPackageUpdate) { - // Skip if not an extension - if (! $this->extensions->getExtension(Extension::nameToId($mainPackageUpdate['name']))) { + $isCore = $mainPackageUpdate['name'] === 'flarum/core'; + + // Skip if not an extension. flarum/core is not one, but surfacing a new + // major of it is the stated purpose of the first command above, and both + // LastUpdateCheck::getNewMajorVersion() and the admin frontend read the + // flarum/core entry back out of this list, so it has to survive the loop. + if (! $isCore && ! $this->extensions->getExtension(Extension::nameToId($mainPackageUpdate['name']))) { continue; } From a7ff69a02edf24b7d232a7cae66637771df91fba Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 17 Aug 2026 02:37:34 +0000 Subject: [PATCH 2/2] fix(extension manager): relax the iterated package, not the wildcard ComposerJson::require('*', '*') tested Extension::nameToId($packageName), which in the wildcard branch is always the literal '*'. That never resolves to an extension, so every iteration continued and no constraint was ever relaxed, while nameToId() emitted a warning per require entry. Test $p, the package being iterated, and skip platform requirements that have no vendor segment. --- .../package-manager/src/Composer/ComposerJson.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/extensions/package-manager/src/Composer/ComposerJson.php b/extensions/package-manager/src/Composer/ComposerJson.php index ee0f9b9168..18dcb96bfe 100644 --- a/extensions/package-manager/src/Composer/ComposerJson.php +++ b/extensions/package-manager/src/Composer/ComposerJson.php @@ -38,8 +38,15 @@ public function require(string $packageName, string $version): void continue; } - // Only extensions can all be set to * versioning. - if (! $this->extensions->getExtension(Extension::nameToId($packageName))) { + // Platform requirements such as `php` or `ext-*` have no vendor + // segment, so they cannot be turned into an extension id. + if (! str_contains($p, '/')) { + continue; + } + + // Only extensions can all be set to * versioning. This has to test the + // package being iterated, not the wildcard that was passed in. + if (! $this->extensions->getExtension(Extension::nameToId($p))) { continue; }