diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 65e3f61..8664f2e 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.43.05 +# VERSION: 01.43.08 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/source/packages/com_mokosuitebackup/mokosuitebackup.xml b/source/packages/com_mokosuitebackup/mokosuitebackup.xml index 5b2f4ea..217a93f 100644 --- a/source/packages/com_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/com_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> MokoSuiteBackup - 01.43.05 + 01.43.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php b/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php index dfb6ffc..9bc481a 100644 --- a/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php +++ b/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php @@ -165,7 +165,38 @@ SCANNER; $php ); - /* Modify the pre-checks to use getSelectedBackupFile() */ + /* Replace the backup archive check with one that scans for ZIPs + (must run BEFORE the blanket file_exists replacement below) */ + $php = str_replace( + <<<'ORIG' + $checks[] = [ + 'label' => 'Backup Archive', + 'value' => file_exists(BACKUP_FILE) ? number_format(filesize(BACKUP_FILE) / 1048576, 2) . ' MB' : 'Not found', + 'ok' => file_exists(BACKUP_FILE), + 'hint' => 'site-backup.zip must be in the same directory as restore.php', + ]; +ORIG, + <<<'REPL' + $availableBackups = scanForBackups(); + $backupCount = count($availableBackups); + $selectedFile = getSelectedBackupFile(); + if ($selectedFile && file_exists($selectedFile)) { + $archiveValue = basename($selectedFile) . ' (' . number_format(filesize($selectedFile) / 1048576, 2) . ' MB)'; + } elseif ($backupCount > 0) { + $archiveValue = $backupCount . ' ZIP file(s) found'; + } else { + $archiveValue = 'No ZIP files found'; + } + $checks[] = [ + 'label' => 'Backup Archive', + 'value' => $archiveValue, + 'ok' => $backupCount > 0, + 'hint' => 'Place one or more backup ZIP files in the same directory as restore.php', + ]; +REPL + ); + + /* Modify remaining pre-checks to use getSelectedBackupFile() */ $php = str_replace( "file_exists(BACKUP_FILE)", "(getSelectedBackupFile() !== '' || file_exists(BACKUP_FILE))", @@ -174,65 +205,83 @@ SCANNER; $html = self::generateFrontend(); - /* Add backup file selector to the frontend before the extract step */ + /* Inject backup file selector into the extract step (panel2) */ $selectorHtml = <<<'SELECTOR' - - - + if (backups.length === 0) { + var alert = document.createElement('div'); + alert.style.cssText = 'padding:12px;background:#fef2f2;border:1px solid #fecaca;border-radius:6px;color:#dc2626;'; + alert.textContent = 'No ZIP files found in this directory. Upload a backup archive first.'; + list.appendChild(alert); + } else if (backups.length === 1) { + hiddenInput.value = backups[0].name; + var found = document.createElement('div'); + found.style.cssText = 'padding:12px;background:#dcfce7;border:1px solid #bbf7d0;border-radius:6px;color:#16a34a;'; + var strong = document.createElement('strong'); + strong.textContent = backups[0].name; + found.appendChild(document.createTextNode('Found: ')); + found.appendChild(strong); + found.appendChild(document.createTextNode(' (' + (backups[0].size / 1048576).toFixed(1) + ' MB)')); + list.appendChild(found); + } else { + var hint = document.createElement('div'); + hint.style.cssText = 'padding:8px 12px;background:#eff6ff;border:1px solid #bfdbfe;border-radius:6px;color:#1d4ed8;margin-bottom:8px;font-size:0.9em;'; + hint.textContent = 'Multiple backup archives found \u2014 select which one to restore:'; + list.appendChild(hint); + backups.forEach(function(b, i) { + var label = document.createElement('label'); + label.style.cssText = 'display:flex;align-items:center;padding:10px 12px;margin:4px 0;border:1px solid #e2e8f0;border-radius:6px;cursor:pointer;transition:background 0.15s;'; + label.onmouseover = function() { this.style.background = '#f8fafc'; }; + label.onmouseout = function() { this.style.background = ''; }; + var radio = document.createElement('input'); + radio.type = 'radio'; + radio.name = 'backup_choice'; + radio.value = b.name; + radio.style.marginRight = '10px'; + if (i === 0) { radio.checked = true; hiddenInput.value = b.name; } + radio.addEventListener('change', function() { hiddenInput.value = this.value; }); + label.appendChild(radio); + var info = document.createElement('div'); + var nameStrong = document.createElement('strong'); + nameStrong.textContent = b.name; + info.appendChild(nameStrong); + var meta = document.createElement('div'); + meta.style.cssText = 'font-size:0.85em;color:#64748b;margin-top:2px;'; + meta.textContent = (b.size / 1048576).toFixed(1) + ' MB \u2014 ' + b.date; + info.appendChild(meta); + label.appendChild(info); + list.appendChild(label); + }); + } + })(); + SELECTOR; - /* Insert the selector before the extract step in the HTML */ + /* Insert the selector into the extract panel */ $html = str_replace( - '', - $selectorHtml . "\n", + '

Extract site-backup.zip into the current directory.

', + '

Select a backup archive and extract it into the current directory.

' . "\n" . $selectorHtml, + $html + ); + + /* Pass selected backup file to the extract action */ + $html = str_replace( + "const r = await post('extract', pw ? { archive_password: pw } : {});", + "var extraParams = {};\n" . + " if (pw) extraParams.archive_password = pw;\n" . + " var sel = document.getElementById('mr-backup-file');\n" . + " if (sel && sel.value) extraParams.backup_file = sel.value;\n" . + " const r = await post('extract', extraParams);", $html ); @@ -462,15 +511,31 @@ function actionPreflight(): array 'hint' => 'Informational', ]; + $joomlaExists = file_exists(RESTORE_DIR . '/configuration.php') + || file_exists(RESTORE_DIR . '/libraries/src/Version.php'); + $checks[] = [ + 'label' => 'Existing Installation', + 'value' => $joomlaExists ? 'Joomla detected' : 'Clean directory', + 'ok' => true, + 'warn' => $joomlaExists, + 'hint' => $joomlaExists + ? 'WARNING: A Joomla installation already exists in this directory. Restoring will overwrite it.' + : 'No existing installation found — safe to proceed', + ]; + $allOk = true; + $warnings = []; foreach ($checks as $c) { if (!$c['ok']) { $allOk = false; } + if (!empty($c['warn'])) { + $warnings[] = $c['hint']; + } } - return ['success' => $allOk, 'checks' => $checks]; + return ['success' => $allOk, 'checks' => $checks, 'warnings' => $warnings]; } function actionExtract(array $data): array @@ -1425,6 +1490,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica N .mr-checks li:last-child{border-bottom:none} .mr-check-icon{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:0.75rem;font-weight:700;flex-shrink:0} .mr-check-ok{background:#dcfce7;color:#16a34a} +.mr-check-warn{background:#fef9c3;color:#a16207} .mr-check-fail{background:#fef2f2;color:#dc2626} .mr-check-info{background:#e0f2fe;color:#0284c7} .mr-check-label{flex:1;font-weight:500} @@ -1877,8 +1943,10 @@ async function runPreflight() { r.checks.forEach(function(c) { const li = document.createElement('li'); const icon = document.createElement('span'); - icon.className = 'mr-check-icon ' + (c.ok ? 'mr-check-ok' : 'mr-check-fail'); - icon.textContent = c.ok ? '\u2713' : '\u2717'; + var iconClass = c.ok ? 'mr-check-ok' : 'mr-check-fail'; + if (c.warn) iconClass = 'mr-check-warn'; + icon.className = 'mr-check-icon ' + iconClass; + icon.textContent = c.warn ? '\u26a0' : (c.ok ? '\u2713' : '\u2717'); const label = document.createElement('span'); label.className = 'mr-check-label'; @@ -1891,9 +1959,16 @@ async function runPreflight() { li.appendChild(icon); li.appendChild(label); li.appendChild(val); + if (c.warn && c.hint) { + var hint = document.createElement('div'); + hint.style.cssText = 'font-size:0.85em;color:#a16207;margin-top:4px;padding:4px 8px;background:#fef9c3;border-radius:4px;'; + hint.textContent = c.hint; + li.appendChild(hint); + } list.appendChild(li); - log(' ' + (c.ok ? 'OK' : 'FAIL') + ': ' + c.label + ' = ' + c.value); + var logPrefix = c.warn ? 'WARN' : (c.ok ? 'OK' : 'FAIL'); + log(' ' + logPrefix + ': ' + c.label + ' = ' + c.value); }); setBtnLoading(btn, false); diff --git a/source/packages/mod_mokosuitebackup_cpanel/mod_mokosuitebackup_cpanel.xml b/source/packages/mod_mokosuitebackup_cpanel/mod_mokosuitebackup_cpanel.xml index 821773c..fe20917 100644 --- a/source/packages/mod_mokosuitebackup_cpanel/mod_mokosuitebackup_cpanel.xml +++ b/source/packages/mod_mokosuitebackup_cpanel/mod_mokosuitebackup_cpanel.xml @@ -8,7 +8,7 @@ --> mod_mokosuitebackup_cpanel - 01.43.05 + 01.43.08 2026-06-23 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml index 9f08d49..1c131db 100644 --- a/source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Action Log - MokoSuiteBackup - 01.43.05 + 01.43.08 2026-06-04 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml index bae25c6..fc09026 100644 --- a/source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Console - MokoSuiteBackup - 01.43.05 + 01.43.08 2026-06-04 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml index 16377e2..acf0cbf 100644 --- a/source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Content - MokoSuiteBackup - 01.43.05 + 01.43.08 2026-06-04 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml index be95174..78d053d 100644 --- a/source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml @@ -1,7 +1,7 @@ Quick Icon - MokoSuiteBackup - 01.43.05 + 01.43.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml index 8deac60..1410d45 100644 --- a/source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> System - MokoSuiteBackup - 01.43.05 + 01.43.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml index 4a1e430..daf5785 100644 --- a/source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Task - MokoSuiteBackup - 01.43.05 + 01.43.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml b/source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml index 781fa27..0ff493d 100644 --- a/source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> Web Services - MokoSuiteBackup - 01.43.05 + 01.43.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/pkg_mokosuitebackup.xml b/source/pkg_mokosuitebackup.xml index af4a767..9c8f12f 100644 --- a/source/pkg_mokosuitebackup.xml +++ b/source/pkg_mokosuitebackup.xml @@ -8,7 +8,7 @@ Package - MokoSuiteBackup mokosuitebackup - 01.43.05 + 01.43.08 2026-06-02 Moko Consulting hello@mokoconsulting.tech