From 59607a11cb96e963c94f7afcf2ebef19b513a7fc Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sun, 12 Jul 2026 15:50:23 -0500 Subject: [PATCH] feat: seamless auto-continue on Joomla Update after pre-update backup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the full-screen pre-update backup returns to the Joomla Update confirm page (layout=update&is_backed_up=1), inject a small script that ticks Joomla's 'I have taken a backup' checkbox (#joomlaupdate-confirm- backup) and clicks the Install button (.emptystate-btnadd) so the update continues automatically — no second manual click. Injected via onBeforeCompileHead, super-user only, gated on backup_before_update. Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i --- CHANGELOG.md | 1 + .../src/Extension/MokoSuiteBackup.php | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 105fd151..edc76ac1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] ### Fixed +- Pre-update backup on the **Joomla Update** page is now **seamless** (Akeeba-style): after the full-screen backup runs, the plugin auto-ticks Joomla's "I have taken a backup" checkbox and clicks Install, so the update continues automatically instead of stopping for a second manual click. - Pre-update full-screen backup now actually fires on the **Joomla Update** page. The "Install the update" button posts to `option=com_joomlaupdate&layout=update` (Joomla's confirm/updating page) — carrying **only `layout=update`**, no `view`/`task` — so the previous match on `view=update`/`update.install` never triggered. The plugin now intercepts `layout=update` (as well as `view=update` and the legacy `update.install`) and returns the browser there flagged `is_backed_up=1`. ### Added diff --git a/source/packages/plg_system_mokosuitebackup/src/Extension/MokoSuiteBackup.php b/source/packages/plg_system_mokosuitebackup/src/Extension/MokoSuiteBackup.php index ce47e68d..2215b4e6 100644 --- a/source/packages/plg_system_mokosuitebackup/src/Extension/MokoSuiteBackup.php +++ b/source/packages/plg_system_mokosuitebackup/src/Extension/MokoSuiteBackup.php @@ -170,6 +170,25 @@ final class MokoSuiteBackup extends CMSPlugin implements SubscriberInterface $input = $app->getInput(); + // Joomla core update: after the pre-update backup returns to the confirm + // page (layout=update&is_backed_up=1), auto-check Joomla's "I have a + // backup" box and click Install so the update continues seamlessly + // (Akeeba-style) instead of stopping for a second manual click. + if ($input->getCmd('option', '') === 'com_joomlaupdate') { + if ($input->getCmd('layout', '') === 'update' + && (int) ComponentHelper::getParams('com_mokosuitebackup')->get('backup_before_update', 0)) { + $user = $app->getIdentity(); + $doc = $app->getDocument(); + + if ($user && !$user->guest && $user->authorise('core.admin') && $doc instanceof HtmlDocument) { + $doc->getWebAssetManager()->useScript('core'); + $doc->addScriptDeclaration($this->joomlaUpdateAutoContinueScript()); + } + } + + return; + } + if ($input->getCmd('option', '') !== 'com_installer') { return; } @@ -226,6 +245,30 @@ final class MokoSuiteBackup extends CMSPlugin implements SubscriberInterface $doc->addScript(Uri::root(true) . '/media/plg_system_mokosuitebackup/js/installer-backup.js', [], ['defer' => true]); } + /** + * Inline JS for the Joomla Update confirm page. When we return there after + * the pre-update backup (is_backed_up=1), it ticks Joomla's "I have taken a + * backup" checkbox and clicks the Install button (.emptystate-btnadd) so the + * update proceeds automatically — seamless, no second manual click. + */ + private function joomlaUpdateAutoContinueScript(): string + { + return <<<'JS' +(function () { +'use strict'; +if (new URLSearchParams(window.location.search).get('is_backed_up') !== '1') { return; } +var go = function () { + var chk = document.getElementById('joomlaupdate-confirm-backup'); + var wrap = document.getElementById('joomlaupdate-wrapper'); + var btn = (wrap && wrap.querySelector('.emptystate-btnadd')) || document.querySelector('.emptystate-btnadd'); + if (chk) { chk.checked = true; chk.dispatchEvent(new Event('change', { bubbles: true })); } + if (btn) { btn.classList.remove('disabled'); window.setTimeout(function () { btn.click(); }, 400); } +}; +if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', go); } else { go(); } +})(); +JS; + } + /** * Send a Joomla core update through the full-screen backup page BEFORE the * update applies (Akeeba-style), so no backup runs synchronously inside the -- 2.52.0