From 4c324ef4b8f94e7fb84abccbaa70916aac3572de Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 9 Nov 2025 15:50:42 +0000 Subject: [PATCH] =?UTF-8?q?don=E2=80=99t=20error=20when=20trying=20to=20fo?= =?UTF-8?q?rce=20=E2=80=94safe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andy Miller --- system/install.php | 25 +++++++++++++++++++ .../Grav/Console/Gpm/SelfupgradeCommand.php | 14 ++++++++--- system/src/Grav/Installer/Install.php | 8 ++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/system/install.php b/system/install.php index 8cdc8b53c..37ada646b 100644 --- a/system/install.php +++ b/system/install.php @@ -10,6 +10,31 @@ if (!defined('GRAV_ROOT')) { die(); } +// Check if Install class is already loaded (from an older Grav version) +// This happens when upgrading from older versions where the OLD Install class +// was loaded via autoloader before extracting the update package (e.g., via Install::forceSafeUpgrade()) +if (class_exists('Grav\\Installer\\Install', false)) { + // OLD Install class is already loaded. We cannot load the NEW one due to PHP limitations. + // However, we can work around this by: + // 1. Using a different class name for the NEW installer + // 2. Or, accepting that the OLD Install class will run but ensuring it can still upgrade properly + + // For now, use the OLD Install class but set its location to this extracted package + // so it processes files from here + $install = Grav\Installer\Install::instance(); + + // Use reflection to update the location property to point to this package + $reflection = new \ReflectionClass($install); + if ($reflection->hasProperty('location')) { + $locationProp = $reflection->getProperty('location'); + $locationProp->setAccessible(true); + $locationProp->setValue($install, __DIR__ . '/..'); + } + + return $install; +} + +// Normal case: Install class not yet loaded, load the NEW one require_once __DIR__ . '/src/Grav/Installer/Install.php'; return Grav\Installer\Install::instance(); diff --git a/system/src/Grav/Console/Gpm/SelfupgradeCommand.php b/system/src/Grav/Console/Gpm/SelfupgradeCommand.php index 17c11216e..e9272cb86 100644 --- a/system/src/Grav/Console/Gpm/SelfupgradeCommand.php +++ b/system/src/Grav/Console/Gpm/SelfupgradeCommand.php @@ -132,14 +132,17 @@ class SelfupgradeCommand extends GpmCommand if ($forceSafe || $forceLegacy) { $forcedMode = $forceSafe ? true : false; - Install::forceSafeUpgrade($forcedMode); + // NOTE: Do not call Install::forceSafeUpgrade() here as it would load the old Install class + // before the upgrade package is extracted, causing a class redeclaration error. + // Instead, we set the config and also use an environment variable as a fallback. + putenv('GRAV_FORCE_SAFE_UPGRADE=' . ($forcedMode ? '1' : '0')); try { $grav = Grav::instance(); if ($grav && isset($grav['config'])) { $grav['config']->set('system.updates.safe_upgrade', $forcedMode); } } catch (\Throwable $e) { - // Ignore container bootstrap failures; mode override still applies. + // Ignore container bootstrap failures; mode override still applies via env var. } if ($forceSafe) { @@ -344,7 +347,12 @@ class SelfupgradeCommand extends GpmCommand return $error; } finally { if (null !== $forcedMode) { - Install::forceSafeUpgrade(null); + // Clean up environment variable + putenv('GRAV_FORCE_SAFE_UPGRADE'); + // Only call Install::forceSafeUpgrade if Install class has been loaded + if (class_exists(\Grav\Installer\Install::class, false)) { + Install::forceSafeUpgrade(null); + } } } } diff --git a/system/src/Grav/Installer/Install.php b/system/src/Grav/Installer/Install.php index d34c6b9bf..0c88f515d 100644 --- a/system/src/Grav/Installer/Install.php +++ b/system/src/Grav/Installer/Install.php @@ -471,10 +471,18 @@ ERR; require_once $serviceFile; } + // Check static override first if (null !== self::$forceSafeUpgrade) { return self::$forceSafeUpgrade; } + // Check environment variable set by SelfupgradeCommand (avoids early class loading) + $envValue = getenv('GRAV_FORCE_SAFE_UPGRADE'); + if (false !== $envValue && '' !== $envValue) { + return $envValue === '1'; + } + + // Check Grav config try { $grav = Grav::instance(); if ($grav && isset($grav['config'])) {