Changeset 3375223
- Timestamp:
- 10/08/2025 03:30:54 PM (4 months ago)
- Location:
- hejbit-decentralised-backup/trunk
- Files:
-
- 6 edited
-
HDB.php (modified) (20 diffs)
-
inc/CreateDB.php (modified) (3 diffs)
-
inc/CreateZip.php (modified) (2 diffs)
-
inc/MergeChunk.php (modified) (1 diff)
-
inc/SendChunk.php (modified) (2 diffs)
-
readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
hejbit-decentralised-backup/trunk/HDB.php
r3330068 r3375223 8 8 * Tested up to: 6.7.2 9 9 * Requires PHP: 7.3 10 * Version: 1.0. 610 * Version: 1.0.7 11 11 * Author: Hejbit, Joaosraposo 12 12 * License: AGPLv3 … … 40 40 $nameTable = $wpdb->prefix . 'hejbit_saveInProgress'; 41 41 // Query for creating the table 42 $sql = "CREATE TABLE IF NOT EXISTS $nameTable (42 $sql1 = "CREATE TABLE IF NOT EXISTS $nameTable ( 43 43 id_zip int(11) NOT NULL auto_increment, 44 44 name text DEFAULT NULL, … … 50 50 )$charset_collate;"; 51 51 52 // Create logs table 53 $logsTable = $wpdb->prefix . 'hejbit_logs'; 54 $sql2 = "CREATE TABLE IF NOT EXISTS $logsTable ( 55 id int(11) NOT NULL auto_increment, 56 backup_id int(11) DEFAULT NULL, 57 timestamp datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 58 log_level varchar(20) DEFAULT 'INFO', 59 step varchar(50) DEFAULT NULL, 60 message text, 61 details longtext, 62 PRIMARY KEY (id), 63 KEY backup_id_idx (backup_id), 64 KEY timestamp_idx (timestamp) 65 )$charset_collate;"; 66 52 67 // Fetches the doc to modify the DB 53 68 require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); 54 69 55 70 // Applies the queries 56 dbDelta($sql); 71 dbDelta($sql1); 72 dbDelta($sql2); 73 57 74 } 58 75 … … 63 80 //Deletion of the cron jobs 64 81 if (wp_next_scheduled('hejbit_Save')) { 65 66 82 wp_clear_scheduled_hook('hejbit_Save'); 67 83 }; 68 84 69 85 if (wp_next_scheduled('hejbit_Save', array('next'))) { 70 71 86 wp_clear_scheduled_hook('hejbit_Save', array('next')); 72 87 }; … … 74 89 // Delete the tables 75 90 global $wpdb; 76 $nameTable = 'hejbit_saveInProgress'; 77 $table_name = $wpdb->prefix . $nameTable; 78 79 // Sanitize the table name and execute the query 80 $wpdb->query("DROP TABLE IF EXISTS `{$table_name}`"); 91 $tables = array('hejbit_saveInProgress', 'hejbit_logs'); 92 93 foreach ($tables as $table) { 94 $table_name = $wpdb->prefix . $table; 95 $wpdb->query("DROP TABLE IF EXISTS `{$table_name}`"); 96 } 81 97 82 98 // Deletion of the options … … 112 128 if (empty($rows->id_zip)) { 113 129 130 // Log new backup start 131 self::log('Starting new backup process', 'INFO', 'INIT'); 132 114 133 // Creation of a new backup 115 134 $tableName = $wpdb->prefix . 'hejbit_saveInProgress'; … … 122 141 $wpdb->insert($tableName, $inProgress); 123 142 } else { 143 // Log resume 144 self::log('Resuming backup process', 'INFO', 'RESUME', array( 145 'status' => $rows->status, 146 'fileNumber' => $rows->fileNumber 147 )); 124 148 125 149 $inProgress = array( … … 130 154 }; 131 155 132 // Resumption based on the backup status 156 // Resumption based on the backup status (add logging for each case) 133 157 switch ($inProgress['status']) { 134 158 135 159 136 160 case "0": 161 self::log('Starting database export', 'INFO', 'CREATE_DB'); 137 162 // Export of the DB 138 163 include plugin_dir_path(__FILE__) . 'inc/CreateDB.php'; … … 143 168 144 169 case "1": 170 self::log('Starting ZIP creation', 'INFO', 'CREATE_ZIP'); 145 171 // Creation of the Zip 146 172 include plugin_dir_path(__FILE__) . 'inc/CreateZip.php'; … … 150 176 151 177 case "2": 178 self::log('Merging backup files', 'INFO', 'MERGE_ZIP'); 152 179 // Merging the files to be backed up 153 180 include plugin_dir_path(__FILE__) . 'inc/MergeZip.php'; … … 157 184 158 185 case "3": 186 self::log('Preparing to send to NextCloud', 'INFO', 'SEND_CHUNK'); 159 187 160 188 $nc_status = hejbit_save_to_nextcloud::is_NextCloud_good(); 161 189 $hejbit_folder = hejbit_save_to_nextcloud::is_Folder_hejbit(); 162 190 163 164 191 if (!$nc_status) { 192 self::log('NextCloud connection failed', 'ERROR', 'SEND_CHUNK'); 193 } 194 if (!$hejbit_folder) { 195 self::log('Invalid HejBit folder', 'ERROR', 'SEND_CHUNK'); 196 } 165 197 166 198 // If the connection with NextCloud is correct and folder is hejbit … … 240 272 241 273 case "4": 274 self::log('Merging chunks on NextCloud', 'INFO', 'MERGE_CHUNK'); 242 275 243 276 // If the connection with NextCloud is correct … … 307 340 }; 308 341 342 // Clean old logs (keep last 30 days by default) 343 $logs_retention = get_option('hejbit_logs_retention', 30); 344 hejbit_save_to_nextcloud::clean_logs($logs_retention); 309 345 310 346 // Starting the backup - THIS SHOULD ALWAYS HAPPEN … … 594 630 return (int)$memoryLimit; 595 631 } 632 633 // Logging method 634 static function log($message, $level = 'INFO', $step = null, $details = null) { 635 global $wpdb; 636 637 // Get current backup ID 638 $backup_id = null; 639 $current_backup = $wpdb->get_row( 640 $wpdb->prepare( 641 "SELECT id_zip FROM {$wpdb->prefix}hejbit_saveInProgress WHERE finish = %d", 642 0 643 ) 644 ); 645 646 if ($current_backup) { 647 $backup_id = $current_backup->id_zip; 648 } 649 650 // Insert log entry 651 $wpdb->insert( 652 $wpdb->prefix . 'hejbit_logs', 653 array( 654 'backup_id' => $backup_id, 655 'log_level' => $level, 656 'step' => $step, 657 'message' => $message, 658 'details' => $details ? json_encode($details) : null 659 ), 660 array('%d', '%s', '%s', '%s', '%s') 661 ); 662 } 663 664 // Get logs for display 665 static function get_logs($backup_id = null, $limit = 100, $offset = 0) { 666 global $wpdb; 667 668 $where = ''; 669 $prepare_values = array(); 670 671 if ($backup_id !== null) { 672 $where = "WHERE backup_id = %d"; 673 $prepare_values[] = $backup_id; 674 } 675 676 $prepare_values[] = $limit; 677 $prepare_values[] = $offset; 678 679 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 680 return $wpdb->get_results( 681 $wpdb->prepare( 682 "SELECT l.*, s.name as backup_name 683 FROM {$wpdb->prefix}hejbit_logs l 684 LEFT JOIN {$wpdb->prefix}hejbit_saveInProgress s ON l.backup_id = s.id_zip 685 {$where} 686 ORDER BY l.timestamp DESC 687 LIMIT %d OFFSET %d", 688 $prepare_values 689 ) 690 ); 691 } 692 693 // Clean old logs 694 static function clean_logs($days_to_keep = 30) { 695 global $wpdb; 696 697 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 698 $deleted = $wpdb->query( 699 $wpdb->prepare( 700 "DELETE FROM {$wpdb->prefix}hejbit_logs 701 WHERE timestamp < DATE_SUB(NOW(), INTERVAL %d DAY)", 702 $days_to_keep 703 ) 704 ); 705 return $deleted; 706 } 596 707 }; 708 709 // phpcs:enable WordPress.DB 597 710 598 711 // Admin view … … 629 742 // Menu creation 630 743 add_menu_page('HejBit Decentralised Backup', 'HejBit Decentralised Backup', 'manage_options', 'hejbit_nextcloud'); 744 631 745 // Adds a 'Backup' sub-menu 632 746 add_submenu_page('hejbit_nextcloud', 'Backup', 'Backup', 'manage_options', 'hejbit_decentralised-backup', 'hejbit_savetonextcloud_param'); 747 748 // Add logs sub-menu 749 add_submenu_page('hejbit_nextcloud', 'Logs', 'Logs', 'manage_options', 'hejbit_logs', 'hejbit_logs_page'); 633 750 634 751 // The method 'add_menu_page()' also creates a 'HejBit Decentralised Backup' sub-menu, so we delete it … … 832 949 }); 833 950 834 835 951 function hejbit_get_all_saves() 836 952 { … … 842 958 843 959 // Execute the query to retrieve all backups 960 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 844 961 $allSaves = $wpdb->get_results( 845 962 "SELECT * FROM {$wpdb->prefix}hejbit_saveInProgress" … … 901 1018 function hejbit_savetonextcloud_param() 902 1019 { ?> 1020 <script> 1021 document.addEventListener('DOMContentLoaded', function() { 1022 var btn = document.getElementById('hejbit-test-nextcloud'); 1023 if (btn) { 1024 btn.addEventListener('click', function() { 1025 var resultDiv = document.getElementById('hejbit-nextcloud-result'); 1026 resultDiv.innerHTML = 'Testing connection...'; 1027 fetch(ajaxurl, { 1028 method: 'POST', 1029 headers: {'Content-Type': 'application/x-www-form-urlencoded'}, 1030 body: 'action=hejbit_test_nextcloud' 1031 }) 1032 .then(response => response.json()) 1033 .then(data => { 1034 if (data.success) { 1035 resultDiv.innerHTML = '✅ Connection established.<br>' + 1036 (data.hejbit_folder ? '✅ Hejbit folder exists.' : '❌ Hejbit folder does NOT exist.'); 1037 } else { 1038 resultDiv.innerHTML = '❌ Connection failed: ' + data.message; 1039 } 1040 }) 1041 .catch(() => { 1042 resultDiv.innerHTML = '❌ Error testing connection.'; 1043 }); 1044 }); 1045 } 1046 }); 1047 </script> 903 1048 904 1049 <div class="wrap"> … … 960 1105 961 1106 <tr valign="top"> 962 <th scope="row" style="width:350px;">Remote Backup Folder ( /Hejbit/WordpressBackups/ )</th> 963 <td><input type="text" name="hejbit_folder_dlwcloud" value="<?php if (!empty(get_option('hejbit_folder_dlwcloud'))) { 964 echo 965 esc_html(get_option('hejbit_folder_dlwcloud')); 966 } else { 967 echo ""; 968 }; ?>" required /></td> 1107 <th scope="row" style="width:350px;">Remote Backup Folder ( /Hejbit/WordpressBackups/ ) 1108 <p> 1109 Save the schedule first to use this button. 1110 </p> 1111 </th> 1112 <td style="display: flex; align-items: center; gap: 10px;"> 1113 <input type="text" name="hejbit_folder_dlwcloud" value="<?php echo esc_html(get_option('hejbit_folder_dlwcloud', '')); ?>" required /> 1114 <button type="button" id="hejbit-test-nextcloud" class="button">Test Nextcloud Connection</button> 1115 <div id="hejbit-nextcloud-result" style="margin-left:10px;"></div> 1116 </td> 969 1117 </tr> 970 1118 971 1119 <tr valign="top"> 972 1120 <th scope="row" style="width:350px;">Notification email separated by ;</th> … … 1027 1175 </div> 1028 1176 <?php settings_errors('hejbit'); 1029 }; ?> 1177 }; 1178 1179 //Handler AJAX for testing Nextcloud connection (button) 1180 add_action('wp_ajax_hejbit_test_nextcloud', function() { 1181 if (!current_user_can('manage_options')) { 1182 wp_send_json(array('success' => false, 'message' => 'Permission denied.')); 1183 } 1184 $nc_status = hejbit_save_to_nextcloud::is_NextCloud_good(); 1185 if (!$nc_status) { 1186 wp_send_json(array('success' => false, 'message' => 'Could not connect to Nextcloud.')); 1187 } 1188 $hejbit_folder = hejbit_save_to_nextcloud::is_Folder_hejbit(); 1189 if ($hejbit_folder) { 1190 wp_send_json(array( 1191 'success' => true, 1192 'hejbit_folder' => true 1193 )); 1194 } else { 1195 wp_send_json(array( 1196 'success' => true, 1197 'hejbit_folder' => false 1198 )); 1199 } 1200 }); 1201 1202 // Logs page 1203 function hejbit_logs_page() { 1204 // Handle log cleanup if requested 1205 if ( 1206 isset($_POST['clear_old_logs']) && 1207 isset($_POST['hejbit_logs_nonce']) && 1208 wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['hejbit_logs_nonce'])), 'hejbit_clear_logs') 1209 ) { 1210 $days = isset($_POST['days_to_keep']) ? intval($_POST['days_to_keep']) : 30; 1211 $deleted = hejbit_save_to_nextcloud::clean_logs($days); 1212 echo '<div class="notice notice-success"><p>' . sprintf('Deleted %d old log entries.', esc_html($deleted)) . '</p></div>'; 1213 } 1214 1215 // Pagination 1216 $page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1; 1217 $per_page = 50; 1218 $offset = ($page - 1) * $per_page; 1219 1220 // Get logs 1221 $logs = hejbit_save_to_nextcloud::get_logs(null, $per_page, $offset); 1222 1223 // Get total count for pagination 1224 global $wpdb; 1225 // Try to get cached value first 1226 $cache_key = 'hejbit_total_logs_count'; 1227 $total_logs = wp_cache_get($cache_key, 'hejbit_logs'); 1228 if (false === $total_logs) { 1229 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 1230 $total_logs = $wpdb->get_var( 1231 "SELECT COUNT(*) FROM {$wpdb->prefix}hejbit_logs" 1232 ); 1233 wp_cache_set($cache_key, $total_logs, 'hejbit_logs', 300); // Cache for 5 minutes 1234 } 1235 1236 $total_pages = ceil($total_logs / $per_page); 1237 ?> 1238 1239 <div class="wrap"> 1240 <h1>HejBit Backup Logs</h1> 1241 1242 <div style="margin: 20px 0;"> 1243 <form method="post" style="display: inline;"> 1244 <?php wp_nonce_field('hejbit_clear_logs', 'hejbit_logs_nonce'); ?> 1245 <label>Keep logs for: <input type="number" name="days_to_keep" value="30" min="1" max="365" style="width: 60px;"> days</label> 1246 <input type="submit" name="clear_old_logs" class="button" value="Clean Old Logs"> 1247 <input type="button" class="button" value="Refresh" onclick="location.reload();"> 1248 </form> 1249 </div> 1250 1251 <div style="margin-bottom: 20px; padding: 10px; background: #f8f8f8; border: 1px solid #eee;"> 1252 <strong>Backup Status Codes:</strong> 1253 <ul style="margin: 8px 0 0 20px;"> 1254 <li><strong>0</strong>: Start of backup (database export)</li> 1255 <li><strong>1</strong>: ZIP creation (zipping files)</li> 1256 <li><strong>2</strong>: Merge ZIP (merging backup files)</li> 1257 <li><strong>3</strong>: Send chunks to NextCloud (uploading backup)</li> 1258 <li><strong>4</strong>: Merge chunks on NextCloud (finalizing backup)</li> 1259 </ul> 1260 </div> 1261 1262 <table class="wp-list-table widefat fixed striped"> 1263 <thead> 1264 <tr> 1265 <th style="width: 150px;">Timestamp</th> 1266 <th style="width: 80px;">Level</th> 1267 <th style="width: 100px;">Step</th> 1268 <th>Message</th> 1269 <th style="width: 150px;">Backup</th> 1270 </tr> 1271 </thead> 1272 <tbody> 1273 <?php if (empty($logs)): ?> 1274 <tr> 1275 <td colspan="5">No logs found.</td> 1276 </tr> 1277 <?php else: ?> 1278 <?php foreach ($logs as $log): ?> 1279 <tr class="log-<?php echo esc_attr(strtolower($log->log_level)); ?>"> 1280 <td><?php echo esc_html($log->timestamp); ?></td> 1281 <td> 1282 <span style=" 1283 padding: 2px 8px; 1284 border-radius: 3px; 1285 color: white; 1286 background-color: <?php 1287 echo $log->log_level === 'ERROR' ? '#dc3232' : 1288 ($log->log_level === 'WARNING' ? '#ffb900' : 1289 ($log->log_level === 'SUCCESS' ? '#46b450' : '#0073aa')); 1290 ?>;"> 1291 <?php echo esc_html($log->log_level); ?> 1292 </span> 1293 </td> 1294 <td><?php echo esc_html($log->step ?: '-'); ?></td> 1295 <td> 1296 <?php echo esc_html($log->message); ?> 1297 <?php if ($log->details): ?> 1298 <?php $details = json_decode($log->details, true); ?> 1299 <?php if ($details): ?> 1300 <div style="margin-top: 5px; font-size: 12px; color: #666;"> 1301 <?php foreach ($details as $key => $value): ?> 1302 <strong><?php echo esc_html($key); ?>:</strong> <?php echo esc_html($value); ?><br> 1303 <?php endforeach; ?> 1304 </div> 1305 <?php endif; ?> 1306 <?php endif; ?> 1307 </td> 1308 <td><?php echo esc_html($log->backup_name ?: 'Current'); ?></td> 1309 </tr> 1310 <?php endforeach; ?> 1311 <?php endif; ?> 1312 </tbody> 1313 </table> 1314 1315 <?php if ($total_pages > 1): ?> 1316 <div class="tablenav bottom"> 1317 <div class="tablenav-pages"> 1318 <?php 1319 $pagination_links = paginate_links(array( 1320 'base' => add_query_arg('paged', '%#%'), 1321 'format' => '', 1322 'prev_text' => '«', 1323 'next_text' => '»', 1324 'total' => $total_pages, 1325 'current' => $page 1326 )); 1327 if ($pagination_links) { 1328 echo wp_kses_post($pagination_links); 1329 } 1330 ?> 1331 </div> 1332 </div> 1333 <?php endif; ?> 1334 </div> 1335 1336 <style> 1337 .log-error { background-color: #ffebe8 !important; } 1338 .log-warning { background-color: #fff8e5 !important; } 1339 .log-success { background-color: #edfaef !important; } 1340 </style> 1341 <?php 1342 } 1343 ?> -
hejbit-decentralised-backup/trunk/inc/CreateDB.php
r3320542 r3375223 12 12 exit(); 13 13 } 14 15 // Log start of database backup 16 hejbit_save_to_nextcloud::log('Creating database backup', 'INFO', 'CREATE_DB'); 14 17 15 18 // Load the WordPress filesystem … … 86 89 87 90 // Retrieve the table creation script 88 $createTable = $wpdb->get_row( "SHOW CREATE TABLE `" . esc_sql($table) . "`", ARRAY_N);91 $createTable = $wpdb->get_row($wpdb->prepare("SHOW CREATE TABLE `%s`", $table), ARRAY_N); 89 92 $wp_filesystem->put_contents($dbfile, $createTable[1] . ";\n\n", FS_CHMOD_FILE | FILE_APPEND); 90 93 … … 144 147 $wpdb->update($wpdb->prefix . 'hejbit_saveInProgress', $datafinish, $wherefinish); 145 148 149 // Log completion 150 hejbit_save_to_nextcloud::log('Database backup completed successfully', 'SUCCESS', 'CREATE_DB', array( 151 'databases' => count($OA_SQL) 152 )); 153 146 154 // Launch the next step 147 155 wp_schedule_single_event(time(), 'hejbit_SaveInProgress'); -
hejbit-decentralised-backup/trunk/inc/CreateZip.php
r3320542 r3375223 12 12 exit(); 13 13 } 14 15 // Log start of ZIP creation 16 hejbit_save_to_nextcloud::log('Creating ZIP archive', 'INFO', 'CREATE_ZIP', array( 17 'fileNumber' => $inProgress['fileNumber'] 18 )); 14 19 15 20 // Listing of files to back up with exclusion of cache folders … … 76 81 $zip->addFile($filePath, "wordpress/wp-content/" . $relativePath); 77 82 } catch (Exception $e) { 78 // Exception handling 83 // Log the error for logs window 84 hejbit_save_to_nextcloud::log('Failed to add file to ZIP', 'WARNING', 'CREATE_ZIP', array( 85 'file' => $relativePath, 86 'error' => $e->getMessage() 87 )); 79 88 80 89 // Build the error file path in the same location as the original file -
hejbit-decentralised-backup/trunk/inc/MergeChunk.php
r3320542 r3375223 109 109 $wpdb->update($wpdb->prefix . 'hejbit_saveInProgress', $datafinish, $wherefinish); 110 110 111 // Log successful completion 112 hejbit_save_to_nextcloud::log('Backup completed successfully', 'SUCCESS', 'MERGE_CHUNK', array( 113 'filename' => $finalName . '.zip', 114 'destination' => get_option('hejbit_folder_dlwcloud') 115 )); 116 111 117 $info = "Your site backup is complete and decentralized on your Hejbit folder!"; 112 118 $this->sendInfo("SUCCESS", $info); -
hejbit-decentralised-backup/trunk/inc/SendChunk.php
r3330068 r3375223 65 65 ); 66 66 67 if ($thisChunk === false) { 68 hejbit_save_to_nextcloud::log('Failed to read file chunk', 'ERROR', 'SEND_CHUNK'); 69 return; 70 } 71 67 72 // While the file is not completely read 68 73 if (!empty($thisChunk)) { 74 75 // Log chunk send 76 hejbit_save_to_nextcloud::log('Sending chunk to NextCloud', 'INFO', 'SEND_CHUNK', array( 77 'chunk_start' => $inProgress['fileNumber'], 78 'chunk_size' => strlen($thisChunk), 79 'total_size' => $file_size 80 )); 81 69 82 // Get ACTUAL bytes read (critical fix) 70 83 $actual_bytes_read = strlen($thisChunk); … … 99 112 ); 100 113 114 // Check response 115 if (is_wp_error($resSendChunk)) { 116 hejbit_save_to_nextcloud::log('Failed to send chunk', 'ERROR', 'SEND_CHUNK', array( 117 'error' => $resSendChunk->get_error_message() 118 )); 119 } else { 120 $response_code = wp_remote_retrieve_response_code($resSendChunk); 121 if ($response_code >= 200 && $response_code < 300) { 122 hejbit_save_to_nextcloud::log('Chunk sent successfully', 'INFO', 'SEND_CHUNK'); 123 } else { 124 hejbit_save_to_nextcloud::log('Chunk send failed with HTTP error', 'ERROR', 'SEND_CHUNK', array( 125 'http_code' => $response_code 126 )); 127 } 128 129 } 130 101 131 // Update the database with ACTUAL bytes read (critical fix) 102 132 $data = array("fileNumber" => ($inProgress['fileNumber'] + $actual_bytes_read)); -
hejbit-decentralised-backup/trunk/readme.txt
r3330068 r3375223 3 3 Contributors: joaosraposo, app.hejbit.com , metaprovide.org 4 4 Tested up to: 6.8 5 Stable tag: 1.0. 65 Stable tag: 1.0.7 6 6 Requires PHP: 7.3 7 7 License: AGPLv3 … … 20 20 21 21 WARNING: Automatic restoration of backups is not yet possible. It must be done manually by replacing the files on the hosting and restoring the database(DB). 22 23 **New in version 1.0.7:** 24 - Comprehensive logging system accessible via HejBit Decentralised Backup > Logs submenu to monitor all backup operations 25 - Test NextCloud Connection button to verify your setup before running backups 22 26 23 27 == Required Third-Party Services == … … 98 102 - Set the number of backups to keep (up to 10) 99 103 - Enable automatic update blocking: the core, plugins and themes being tagged to be updated automatically, will only be updated after a scheduled backup in order to prevent it from being polluted by a faulty plugin. Manual updates are still possible. 104 105 = Testing Your Connection = 106 107 Before running your first backup, fill in all the fields, click **Save Schedule**, and use the **Test NextCloud Connection** button next to the Remote Backup Folder field to verify: 108 - Your NextCloud credentials and URL are correct 109 - The connection to your NextCloud instance is established 110 - Your specified folder is a valid HejBit folder 111 112 The test will show: 113 - ✅ Connection established - if NextCloud connection is successful 114 - ✅ Hejbit folder exists - if the folder is properly configured for HejBit 115 - ❌ Connection failed: Could not connect to Nextcloud - if the URL or credentials are incorrect 116 - ❌ Hejbit folder does NOT exist - if the Remote Backup Folder path is invalid, missing, or a regular folder. 117 118 = Monitoring Backups = 119 120 The plugin includes a comprehensive logging system accessible via **HejBit Decentralised Backup > Logs**: 121 122 **Log Features:** 123 - Real-time backup progress tracking 124 - Color-coded log levels: INFO (blue), SUCCESS (green), WARNING (yellow), ERROR (red) 125 - Detailed status codes showing backup stages: 126 * 0: Database export 127 * 1: ZIP creation (file compression) 128 * 2: ZIP merging 129 * 3: Upload to NextCloud (chunk sending) 130 * 4: Finalizing backup on NextCloud 131 - Timestamp for each operation 132 - Associated backup names for easy identification 133 134 **Log Management:** 135 - Clean old logs by specifying retention period (default: 30 days) 136 - Refresh button to update log display 137 - Pagination for easy navigation through historical logs 138 139 This feature helps you: 140 - Monitor backup progress in real-time 141 - Quickly identify and troubleshoot any backup failures 142 - Maintain a history of all backup operations 143 - Ensure your backups are completing successfully 144 100 145 101 146 = Process Duration =
Note: See TracChangeset
for help on using the changeset viewer.