The mod_quickicon helper array_merge()s a defaults array into each icon a
plugin returns; if a plugin's DB query throws or it returns a malformed
(unwrapped) icon, the whole admin dashboard can 500 with an array_merge
TypeError. The current handler is structurally correct (icons are wrapped
in a list, matching core plg_quickicon_joomlaupdate), so this hardens it:
- Extract the query/state logic into buildStatusIcon().
- Wrap it in try/catch — on any Throwable, log and contribute no icon
instead of bubbling into the dashboard render.
- Document why the [$icon] list-wrapping is load-bearing.
Closes#297.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
RestoreEngine ignored DatabaseImporter::hasErrors(), so the non-stepped
restore always reported success even when SQL statements failed. It now
logs the failures and returns a warning ("database may be incomplete").
DatabaseImporter's splitter is also quote/backtick/escape-aware so a ; or
newline inside a value no longer splits a statement, and comments are only
skipped between statements — matching the stepped-engine fix (#291).
Closes#188.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
typeLabels[TYPE] referenced an undefined uppercase variable; the forEach
parameter is lowercase `type`, so every type label rendered as the raw
type string instead of its translated label.
Closes#170.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
Replaces the old public ntfy.sh default in the runtime defaults: profile
form default/hint, NotificationSender fallbacks, the ntfy_server column
default in install.mysql.sql, and the en-GB field description. ntfy.sh is
still documented as the public alternative.
Closes#166.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
Stepped restore silently swallowed every failed SQL statement and always
reported "Restore complete", so a half-imported database looked fine.
- SteppedRestoreEngine::stepDatabase() now records a failure count + first
few messages (recordSqlError) instead of only error_log(), and the
completion step returns the count with a warning; the modal shows
"Restore Complete (with warnings)" and does NOT auto-return.
- New quote/backtick/escape-aware isCompleteStatement() replaces the naive
"line ends with ;" terminator, so a ; or newline inside a string value no
longer splits a statement mid-value.
- Comment/blank lines are only skipped BETWEEN statements, never inside an
accumulating multi-line statement.
Relates to #188 (DatabaseImporter) and the standalone MokoRestore splitter;
tracked in #291.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
The stepped-restore Cancel button (added with the progress-modal controls)
stopped the client loop and reloaded, but left the server-side restore
session, *.restore.json state, and the extracted staging directory behind
with no reaper — so cancelled/abandoned restores leaked disk indefinitely.
- SteppedRestoreEngine::cancel() mirrors the failure-cleanup path (delete
staging dir + restore state + session).
- AjaxController::restoreCancel() exposes it (token + restore ACL gated).
- Restore modal Cancel now calls ajax.restoreCancel with the session id
before leaving (session id tracked in restoreSessionId).
- SteppedSession::cleanupOldSessions() also reaps orphaned
mokosuitebackup-restore-* staging dirs >24h (backstop for browser-close).
Found by an audit of the restore path against recent changes; the schema
(retired sftp_*/VARCHAR include_mokorestore) and PHP 8.3 changes were
confirmed to NOT affect restore.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
The generated restore.php wizard used a light "Joomla-styled" blue theme.
Restyled its stylesheet to the full-black MokoSuite look that matches the
runbackup / backup-progress screens: black background + big header, dark
panels/cards, dark form inputs with readable contrast, MokoSuite blue/green
accents, dark step-bar/checks/alerts/progress/log, and all inline help-box
styles converted from light to the dark palette. No logic changes.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
Restore-progress modal now matches the backup modal: auto-continue
checkbox, terminal buttons (Retry restore / Back to backups), and a
double-confirm Cancel. Restore's cancel warns that stopping mid-flight
may leave the site partially restored (no server rollback), and there is
no "view record" button (restore has no new record). startSteppedRestore
split into a re-runnable runSteppedRestore() so Retry works. Title via
safe DOM (no innerHTML).
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
Brings the full-screen runbackup screen's controls onto the black
backup-progress modal in the backups view:
- "Automatically return to the list when finished" checkbox (default on);
unchecked leaves the completion screen up with buttons.
- Cancel button while running (double confirm) — stops the step loop and
cancels the record via ajax.cancelBackup.
- Terminal buttons: View backup record + Back to backups on success;
Retry + Back to backups on failure.
Title icon/text updated via safe DOM (no innerHTML). Restore modal
unchanged in this pass.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
Back-fills dev with the fuller rebrand that shipped on main in the
dev->main release (#282): MokoGitea->MokoGIT, GITEA_ORG->GIT_ORG,
mokogit-actions[bot], and the corrected .mokogit/CLAUDE.md path. dev's
earlier partial rename (#279) is superseded so dev and main no longer
diverge on CI config.
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i