Drops the per-profile remote_storage column and all legacy FTP/SFTP/S3/
Google Drive credential columns. Remote destinations are now sourced
exclusively from #__mokosuitebackup_remotes (multi-remote), which is
created at install time — so the backward-compat fallback branches in
BackupEngine, SteppedBackupEngine and loadRemoteDestinations are removed.
- sql: drop 26 legacy columns (install.mysql.sql + 02.52.25.sql migration)
- forms/profile.xml: remove legacy remote fields and ftp/gdrive/s3 fieldsets
- tmpl/profile/edit.php: drop legacy UI, add save-first prompt, use
getOrCreateInstance for the modal, read item.params (was item.config)
- PreflightCheck: validate credentials from the remotes table; curl
warning now applies to ntfy only
- SteppedSession: drop remoteStorage property
- language: add backup-record delete-count strings
- script.php: simplify postflight license-key prompt
Previously a successful backup with a failed remote upload was marked
as "complete", hiding the upload failure. Now these records get a
"warning" status with a yellow badge so operators can see at a glance
which backups didn't reach their remote destination.
Warning-status records are treated as usable backups throughout:
- Downloadable, browsable, and restorable (the archive is intact)
- Counted in dashboard stats, storage totals, and success streaks
- Included in purge operations and differential base lookups
- Shown with yellow "warning" badge in list, detail, and cpanel module
- Filterable via the status dropdown on Backup Records
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
PreflightCheck now auto-cancels "running" backup records that have
exceeded 30 minutes, treating them as stalled. Partial archive files
are cleaned up. The auto-cancelled records are surfaced as warnings
so the user knows what happened.
Records younger than 30 minutes are assumed to be legitimately running
and still block new backups for the same profile.
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
Backups stuck in "running" status block all future backups for the same
profile via the preflight check. Previously the only fix was a manual
DB update.
Adds a toolbar button and AJAX endpoint to cancel stalled backups:
- New ACL permission: mokosuitebackup.backup.cancel
- BackupsController::cancelStalled() for toolbar (multi-select)
- AjaxController::cancelBackup() for AJAX/API use
- Sets status to "fail", cleans up partial archive files
- Updated preflight error message to mention the cancel action
- Language keys for en-GB and en-US
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
Every action handler now logs entry, key parameters, outcomes, and
failures to PHP error_log. Security file creation logs directory
permissions, PHP user, and the specific error when file_put_contents
fails. Database import logs SQL file size, statement counts, and
individual errors. Cleanup logs each file removal success/failure.
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
The security file was only written inside the code-generation block
(first page load). If the file was deleted or failed to write, it
was never recreated because the session already held the code. Now
file writing is a separate check that runs whenever verification is
pending and the file is missing.
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
Remote uploaders (SFTP, FTP, S3, Google Drive) expect type-prefixed
property names (sftp_host, ftp_port, etc.) but createUploaderFromParams
passes unprefixed keys from the remotes table params JSON. Add prefix
mapping in createUploaderFromParams to bridge the naming gap.
Rename .mokorestore-security.php to mokorestore-security.php (no leading
dot) so the file is visible in file managers and not blocked by web
server dotfile rules. Also clean it up in actionCleanup.
Closes#13
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
The ordering column was unused in the profiles UI — profiles sort by ID.
Drops the column via migration, removes all references from model,
config query, importer, and install SQL.
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
CI version_bump was creating duplicate <version> lines in all
sub-extension manifests. Also AjaxController still referenced the old
`config` column and removed `keep_local` column on the remotes table.
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
The CI version_bump wrote 't' instead of a tab before <version> in
pkg_mokosuitebackup.xml, and appended a duplicate <version> line in
mokosuitebackup.xml instead of replacing the existing one.
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
- Add MokoSuiteClient as git submodule under source/packages/
- Add pkg_mokosuiteclient entry to pkg_mokosuitebackup.xml
- Fix duplicate <version> tag in package manifest
- install.mysql.sql: rename `config` → `params` and drop `keep_local` from remotes
table to match update file 01.41.00 and RemoteTable.php code (fixes Joomla
database maintenance "one problem")
- install.mysql.sql: fix idx_enabled index to use composite (profile_id, enabled)
- install.mysql.sql: add restore_script_name column to profiles table
- 01.43.22.sql: ALTER TABLE to add restore_script_name for existing installs
- DashboardModel: order profile dropdown by ID instead of ordering column
- SteppedBackupEngine: add stack trace logging around MokoRestore standalone
generation to debug str_replace FATAL on SFTP profiles
- SshKeyField: detect base64-encoded keys from DB so the "Key loaded"
badge displays correctly after initial upload
- Add COM_MOKOJOOMBACKUP_BACKUPS_N_ITEMS_DELETED language keys for
Joomla's AdminController delete feedback message