diff --git a/CHANGELOG.md b/CHANGELOG.md index a366932a..05a7ae91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ 1. [](#bugfix) * Fix for deeply nested sortable fields (at last!) * Restore admin session timeout modal by returning 401 for timed-out AJAX requests + * Honor `system.updates.safe_upgrade` so legacy Grav installs keep the classic updater # v1.10.49.1 ## 09/03/2025 diff --git a/admin.php b/admin.php index 8d04220f..52683621 100644 --- a/admin.php +++ b/admin.php @@ -385,6 +385,11 @@ class AdminPlugin extends Plugin 'direct-install' => [['admin.super'], 'PLUGIN_ADMIN.DIRECT_INSTALL'], ]); + $config = $this->grav['config'] ?? null; + if (!SafeUpgradeManager::configAllowsSafeUpgrade($config)) { + return; + } + try { $manifestFiles = glob(GRAV_ROOT . '/user/data/upgrades/*.json') ?: []; diff --git a/classes/plugin/SafeUpgradeManager.php b/classes/plugin/SafeUpgradeManager.php index 532a043e..fa506fde 100644 --- a/classes/plugin/SafeUpgradeManager.php +++ b/classes/plugin/SafeUpgradeManager.php @@ -14,6 +14,7 @@ namespace Grav\Plugin\Admin; +use Grav\Common\Config\Config; use Grav\Common\Filesystem\Folder; use Grav\Common\GPM\Installer; use Grav\Common\GPM\GPM; @@ -1068,14 +1069,37 @@ class SafeUpgradeManager { try { $config = $this->grav['config'] ?? null; - if ($config === null) { - return true; + return self::configAllowsSafeUpgrade($config); + } catch (Throwable $e) { + return false; + } + } + + /** + * @param Config|null $config + * @return bool + */ + public static function configAllowsSafeUpgrade(?Config $config): bool + { + if ($config === null) { + return false; + } + + $value = $config->get('system.updates.safe_upgrade'); + if ($value === null) { + return false; + } + + if (is_string($value)) { + $filtered = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); + if ($filtered === null) { + return false; } - return (bool)$config->get('system.updates.safe_upgrade', true); - } catch (Throwable $e) { - return true; + return $filtered; } + + return (bool)$value; } /** diff --git a/themes/grav/app/updates/index.js b/themes/grav/app/updates/index.js index 43942fba..e970adff 100644 --- a/themes/grav/app/updates/index.js +++ b/themes/grav/app/updates/index.js @@ -10,12 +10,14 @@ import './update'; import './channel-switcher'; import SafeUpgrade from './safe-upgrade'; +const SAFE_UPGRADE_ENABLED = Number(config.safe_upgrade_enabled || 0) === 1; + export default class Updates { constructor(payload = {}) { this.setPayload(payload); this.task = `task${config.param_sep}`; this.updateURL = ''; - this.safeUpgrade = new SafeUpgrade(this); + this.safeUpgrade = SAFE_UPGRADE_ENABLED ? new SafeUpgrade(this) : null; } setPayload(payload = {}) { diff --git a/themes/grav/js/admin.min.js b/themes/grav/js/admin.min.js index 514c76c5..0d0ff9ef 100644 --- a/themes/grav/js/admin.min.js +++ b/themes/grav/js/admin.min.js @@ -3055,6 +3055,7 @@ function updates_toPrimitive(t, r) { if ("object" != updates_typeof(t) || !t) re +var SAFE_UPGRADE_ENABLED = Number(external_GravAdmin_namespaceObject.config.safe_upgrade_enabled || 0) === 1; var Updates = /*#__PURE__*/function () { function Updates() { var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; @@ -3062,7 +3063,7 @@ var Updates = /*#__PURE__*/function () { this.setPayload(payload); this.task = "task".concat(external_GravAdmin_namespaceObject.config.param_sep); this.updateURL = ''; - this.safeUpgrade = new SafeUpgrade(this); + this.safeUpgrade = SAFE_UPGRADE_ENABLED ? new SafeUpgrade(this) : null; } return updates_createClass(Updates, [{ key: "setPayload", diff --git a/themes/grav/templates/partials/base-root.html.twig b/themes/grav/templates/partials/base-root.html.twig index 970b07e0..6aaf81e6 100644 --- a/themes/grav/templates/partials/base-root.html.twig +++ b/themes/grav/templates/partials/base-root.html.twig @@ -82,7 +82,8 @@ {% endblock %} - {% block modals %} +{% set safe_upgrade_enabled = config.system.updates.safe_upgrade|default(false) %} +{% block modals %} {# Session expired blocking modal #}
@@ -127,6 +128,7 @@
+ {% if safe_upgrade_enabled %}
@@ -146,6 +148,21 @@
+ {% else %} +
+
+

{{ "PLUGIN_ADMIN.MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_TITLE"|t }}

+

+ {{ "PLUGIN_ADMIN.MODAL_UPDATE_GRAV_CONFIRMATION_REQUIRED_DESC"|t }} +

+
+
+ + +
+
+
+ {% endif %} {% endblock %} diff --git a/themes/grav/templates/partials/javascript-config.html.twig b/themes/grav/templates/partials/javascript-config.html.twig index 0d67af2c..77bdaffb 100644 --- a/themes/grav/templates/partials/javascript-config.html.twig +++ b/themes/grav/templates/partials/javascript-config.html.twig @@ -4,6 +4,7 @@ {% set plugins_enabled = config.plugins.admin.notifications.plugins is same as(true) or config.plugins.admin.notifications.plugins == 'true' %} {% set themes_enabled = config.plugins.admin.notifications.themes is same as(true) or config.plugins.admin.notifications.themes == 'true' %} {% set notifications = (feed_enabled or dashboard_enabled or plugins_enabled or themes_enabled) ? 1 : 0 %} +{% set safe_upgrade_enabled = config.system.updates.safe_upgrade|default(false) %} {% switch template_route %} {% case 'dashboard' %} @@ -28,6 +29,7 @@ {% endif %} admin_timeout: '{{ config.plugins.admin.session.timeout ?: 1800 }}', keep_alive_enabled: {{ (config.plugins.admin.session.keep_alive is defined ? config.plugins.admin.session.keep_alive : true) ? 1 : 0 }}, + safe_upgrade_enabled: {{ safe_upgrade_enabled ? 1 : 0 }}, admin_nonce: '{{ admin.getNonce }}', language: '{{ grav.user.language|default('en') }}', pro_enabled: '{{ config.plugins["admin-pro"].enabled }}',