8.7 KiB
8.7 KiB
Changelog
[Unreleased]
[02.63.00] --- 2026-07-13
[02.62.00] --- 2026-07-13
[02.61.00] --- 2026-07-13
[02.60.00] --- 2026-07-12
[02.59.00] --- 2026-07-12
Fixed
- Pre-update backup now fires for every extension update/uninstall, not just the first one in a 10-minute window. A coarse 600-second session throttle (armed after any pre-action backup — even after updating MokoSuiteBackup itself or a core Joomla update) was disabling the client-side interceptor and the server-side fallback for all extensions for 10 minutes, so distinct updates silently went un-backed-up (looked like "only the backup extension triggers it"). Replaced with one backup per Update action: a single batch/click still backs up once (deduped per-request), the client re-fire is skipped via a one-shot action-keyed flag (consumed once), and the core-update path uses its own dedicated key so it no longer suppresses extension backups.
- 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 onlylayout=update, noview/task— so the previous match onview=update/update.installnever triggered. The plugin now interceptslayout=update(as well asview=updateand the legacyupdate.install) and returns the browser there flaggedis_backed_up=1.
Added
- Snapshot transfer + master→slave injection (#237): download a content snapshot as a portable
.msbsnapfile (zip ofmanifest.json+snapshot.json+ a sha256 integrity check); import one on another site via a new Import button on the Snapshots page (materialises a local snapshot record you can then restore); and a direct injection API —POST /api/index.php/v1/mokosuitebackup/snapshot/inject— so a master site can push a snapshot straight into a slave's Web Services API. Two conflict modes ship now: overwrite (replace matching items by ID — master wins) and create (skip existing, add only new), selectable per inject call or defaulted in Options → Snapshot Transfer. A receiving site must opt in via the new Allow Snapshot Injection setting. A third duplicate mode inserts everything as brand-new records with remapped IDs (articles, categories, modules — plus their tags, custom-field values and featured flags) using Joomla's Table API so assets/UCM/nested-sets stay valid; each item is inserted defensively (a bad item is skipped and logged, never fatal). - Full-screen backup now also fronts extension updates and uninstalls (Extensions → Update / Manage), not just core Joomla updates. Because
com_installer'supdate.update/manage.removeare POST actions (CSRF token + a checkedcid[]list) that a server-side redirect can't cleanly resume, this is done client-side: the toolbar Update/Uninstall click is intercepted, the selection is captured, the full-screen backup runs, and on return the original selection is restored and the real POST form is re-submitted. Gated bybackup_before_update/backup_before_uninstall, super-user only, and deduped to one backup per Update action. - Manual "Backup Now" completion now offers a View backup record button (links straight to the record that was just created). It appears only for manual backups — the pre-update / pre-uninstall flow hands control back to Joomla instead.
- Full-screen backup screen (
view=runbackup) for both pre-update and manual backups, modelled on Akeeba's Backup-on-Update — replaces the earlier popup-modal approach. Clicking Joomla's Install the update now redirects (server-side, Akeeba-style) to a dedicated full-page backup screen that runs the stepped backup with a real progress bar and then automatically continues the update via a validatedreturnurl(flaggedis_backed_up=1so the backup isn't repeated). Crucially, no backup runs synchronously inside the update request — which is what white-screened large sites. The dashboard Backup Now now opens the same full-screen screen instead of an inline modal. (#196) - Retention now prunes remote copies too: when a backup is pruned by age/count, its archive is deleted from every enabled remote destination (SFTP / FTP / S3 / Google Drive), not just the local copy. Each uploader gained an idempotent
delete()method (already-absent file = success), and removal is best-effort — a failing destination is logged but never blocks local pruning. The shared standalonerestore.phpis intentionally left in place (every backup overwrites it, so newer backups still depend on it). (#229)
Changed
- Consolidated backup plumbing into shared helpers (#230):
- New
RemoteUploaderFactoryreplaces thecreateUploaderFromParams()copy that was duplicated inBackupEngineandSteppedBackupEngine. RetentionManageris now the single retention authority — it takes the globalmax_age_days/max_backupsfallback and gainedpruneOrphans(); the system plugin's hourly cleanup delegates to it and its duplicatedeleteBackupRecord()logic is removed.- The backend controller, Web Services API controller, and legacy
cli/mokosuitebackup.phpnow run backups through the sharedBackupRunner(gaining the normalized complete/warning/fail status) instead of instantiatingBackupEnginedirectly.
- New
Fixed
- Package installer is now honest about success: the postflight no longer prints "installed successfully" / next-steps when the install actually failed or only partially completed. Joomla logs a failed child extension but still runs the package postflight, so the postflight now (a) verifies every bundled child declared in the manifest actually registered in
#__extensions(matched by element + type, and folder/group for plugins) and (b) verifies the component's schema tables — derived dynamically from the installedinstall.mysql.sql— actually exist. If anything is missing it enqueues an error listing what's missing and stops before the success message. Fail-open: any manifest/DB/IO glitch is treated as "nothing missing" so a transient error never turns a good install into a false failure. Unconditional housekeeping (e.g. download-key restore) still runs regardless. - Pre-update full-screen backup screen now actually triggers on Joomla 6 (and 4/5). The redirect matched only the legacy
update.installtask, which Joomla 4/5/6 don't use — they server-side-redirect to the updating pageview=update, which then extracts the downloaded package from JavaScript. The plugin now intercepts theview=updatepage load (the last point before any files change) and returns the browser there flaggedis_backed_up=1so the extraction proceeds after the backup. (update.finaliseis intentionally not intercepted — by then the files are already extracted.) - Pre-update/uninstall backup no longer white-screens the update on large sites. The synchronous backup that runs inside the extension update/uninstall request now raises
max_execution_time/memory_limit(andignore_user_abort) like the web-cron path, so it can't exhaust the request's default limits mid-backup. (Core Joomla updates additionally get a full-screen backup screen — see below.) - Archive names for CLI/console-triggered backups no longer come out as
joomla.invalid_…. The[HOST]placeholder took$_SERVER['HTTP_HOST']verbatim, but Joomla's console fills that with the reserved sentinel hostjoomla.invalid; the resolver now treats that (like empty/localhost) as unusable and falls back to the configuredlive_sitehost, then the system hostname. (Set the site's live_site to get the exact domain in CLI-built names.) - Standalone restore script generation no longer aborts backups with
str_replace() expects at least 3 arguments, 2 given.MokoRestore::generateStandaloneScript()had astr_replace()call (the "Backup Archive" pre-check rewrite) that was missing its$phpsubject argument, so every standalone-mode backup fatally errored while "Generating standalone restore.php…" — the archive still finalized and uploaded, but norestore.phpwas ever produced (the true root cause behind #226). (#226) - Remote upload: the standalone restore script upload is no longer silent — its result is now checked and logged, and a failed restore-script upload marks the backup as
warning(previously the result was discarded, so a missing restore script on the remote went unreported while the archive still showed success). (#226)