diff --git a/source/packages/com_mokosuitebackup/src/Engine/BackupEngine.php b/source/packages/com_mokosuitebackup/src/Engine/BackupEngine.php index 5531d45..626073c 100644 --- a/source/packages/com_mokosuitebackup/src/Engine/BackupEngine.php +++ b/source/packages/com_mokosuitebackup/src/Engine/BackupEngine.php @@ -305,15 +305,19 @@ class BackupEngine $this->log('FATAL: ' . $e->getMessage()); $update = (object) [ - 'id' => $recordId, - 'status' => 'fail', - 'description' => $description ?: '', - 'backup_type' => $profile->backup_type ?? 'full', - 'origin' => $origin, - 'archivename' => $archiveName, - 'backupstart' => $now ?? date('Y-m-d H:i:s'), - 'backupend' => date('Y-m-d H:i:s'), - 'log' => implode("\n", $this->log), + 'id' => $recordId, + 'status' => 'fail', + 'description' => $description ?: '', + 'backup_type' => $profile->backup_type ?? 'full', + 'origin' => $origin, + 'archivename' => $archiveName, + 'backupstart' => $now ?? date('Y-m-d H:i:s'), + 'backupend' => date('Y-m-d H:i:s'), + 'total_size' => 0, + 'files_count' => 0, + 'tables_count' => 0, + 'remote_filename' => '', + 'log' => implode("\n", $this->log), ]; $db->updateObject('#__mokosuitebackup_records', $update, 'id'); @@ -487,6 +491,7 @@ class BackupEngine $name = $zip->getNameIndex($i); if ($name === false) { + $this->log('WARNING: Could not read file at index ' . $i . ' during encryption — file may remain unencrypted'); continue; } diff --git a/source/packages/com_mokosuitebackup/src/Engine/NotificationSender.php b/source/packages/com_mokosuitebackup/src/Engine/NotificationSender.php index 26467af..a5631fd 100644 --- a/source/packages/com_mokosuitebackup/src/Engine/NotificationSender.php +++ b/source/packages/com_mokosuitebackup/src/Engine/NotificationSender.php @@ -169,6 +169,12 @@ class NotificationSender return false; } + if (!function_exists('curl_init')) { + error_log('MokoSuiteBackup: ntfy notifications require ext-curl'); + + return false; + } + try { $config = Factory::getApplication()->getConfig(); $siteName = $config->get('sitename', 'Joomla Site'); @@ -219,7 +225,7 @@ class NotificationSender } if ($httpCode < 200 || $httpCode >= 300) { - error_log('MokoSuiteBackup: ntfy returned HTTP ' . $httpCode . ': ' . $response); + error_log('MokoSuiteBackup: ntfy returned HTTP ' . $httpCode . ': ' . substr((string) $response, 0, 200)); return false; } diff --git a/source/packages/plg_system_mokosuitebackup/src/Extension/MokoSuiteBackup.php b/source/packages/plg_system_mokosuitebackup/src/Extension/MokoSuiteBackup.php index 0844548..e3d00c8 100644 --- a/source/packages/plg_system_mokosuitebackup/src/Extension/MokoSuiteBackup.php +++ b/source/packages/plg_system_mokosuitebackup/src/Extension/MokoSuiteBackup.php @@ -138,6 +138,15 @@ final class MokoSuiteBackup extends CMSPlugin implements SubscriberInterface * A profile value of 0 means "use the global default". */ private function cleanupOldBackups(): void + { + try { + $this->doCleanup(); + } catch (\Throwable $e) { + error_log('MokoSuiteBackup: cleanupOldBackups() failed: ' . $e->getMessage()); + } + } + + private function doCleanup(): void { $db = Factory::getDbo(); $globalMaxAge = (int) ComponentHelper::getParams('com_mokosuitebackup')->get('max_age_days', 30); @@ -219,10 +228,11 @@ final class MokoSuiteBackup extends CMSPlugin implements SubscriberInterface { if (!empty($record->absolute_path) && is_file($record->absolute_path)) { if (!@unlink($record->absolute_path)) { - return; // Don't delete DB record if file can't be removed + error_log('MokoSuiteBackup: Could not delete backup file (id=' . $record->id . '): ' . $record->absolute_path); + + return; } - // Also remove the log file if it exists alongside the archive $logPath = preg_replace('/\.(zip|tar\.gz)$/i', '.log', $record->absolute_path); if (is_file($logPath)) { @@ -230,12 +240,16 @@ final class MokoSuiteBackup extends CMSPlugin implements SubscriberInterface } } - $db->setQuery( - $db->getQuery(true) - ->delete($db->quoteName('#__mokosuitebackup_records')) - ->where($db->quoteName('id') . ' = ' . (int) $record->id) - ); - $db->execute(); + try { + $db->setQuery( + $db->getQuery(true) + ->delete($db->quoteName('#__mokosuitebackup_records')) + ->where($db->quoteName('id') . ' = ' . (int) $record->id) + ); + $db->execute(); + } catch (\Exception $e) { + error_log('MokoSuiteBackup: Could not delete backup record ' . $record->id . ': ' . $e->getMessage()); + } } /** @@ -291,7 +305,7 @@ final class MokoSuiteBackup extends CMSPlugin implements SubscriberInterface 'warning' ); } - } catch (\Exception $e) { + } catch (\Throwable $e) { error_log('MokoSuiteBackup: ' . $description . ' failed: ' . $e->getMessage()); Factory::getApplication()->enqueueMessage( 'MokoSuiteBackup: ' . $description . ' failed — ' . $e->getMessage(),