@@ -65,16 +65,16 @@ public function backup( $args, $assoc_args = [] ) {
6565 // Debug: Log the raw dash_auth value received
6666 EE ::debug ( 'Received --dash-auth value: ' . $ dash_auth );
6767
68- // Parse backup-id:backup-verification-token format
69- $ auth_parts = explode ( ': ' , $ dash_auth , 2 );
70- if ( count ( $ auth_parts ) !== 2 || empty ( $ auth_parts [0 ] ) || empty ( $ auth_parts [1 ] ) ) {
71- $ this ->capture_error (
72- 'Invalid --dash-auth format. Expected: backup-id:backup-verification-token ' ,
73- self ::ERROR_TYPE_VALIDATION ,
74- 1001
75- );
76- EE ::error ( 'Invalid --dash-auth format. Expected: backup-id:backup-verification-token ' );
77- }
68+ // Parse backup-id:backup-verification-token format
69+ $ auth_parts = explode ( ': ' , $ dash_auth , 2 );
70+ if ( count ( $ auth_parts ) !== 2 || empty ( $ auth_parts [0 ] ) || empty ( $ auth_parts [1 ] ) ) {
71+ $ this ->capture_error (
72+ 'Invalid --dash-auth format. Expected: backup-id:backup-verification-token ' ,
73+ self ::ERROR_TYPE_VALIDATION ,
74+ 1001
75+ );
76+ EE ::error ( 'Invalid --dash-auth format. Expected: backup-id:backup-verification-token ' );
77+ }
7878
7979 // Check for ed-api-url configuration
8080 $ ed_api_url = get_config_value ( 'ed-api-url ' , '' );
@@ -117,7 +117,7 @@ public function backup( $args, $assoc_args = [] ) {
117117 $ this ->capture_error (
118118 sprintf ( 'Backup is not supported for site type: %s ' , $ this ->site_data ['site_type ' ] ),
119119 self ::ERROR_TYPE_VALIDATION ,
120- 1003
120+ 1002
121121 );
122122 EE ::error ( 'Backup is not supported for this site type. ' );
123123 }
@@ -152,7 +152,7 @@ public function backup( $args, $assoc_args = [] ) {
152152 /**
153153 * Shutdown handler to send failure callback to EasyDash if backup didn't complete.
154154 * This is called when script terminates (including via EE::error which calls exit).
155- *
155+ *
156156 * Automatically captures fatal errors and interrupted processes if no error was
157157 * explicitly captured during backup execution.
158158 */
@@ -165,7 +165,13 @@ public function dash_shutdown_handler() {
165165 $ last_error = error_get_last ();
166166
167167 // Check if this was a fatal PHP error
168- if ( $ last_error && in_array ( $ last_error ['type ' ], [ E_ERROR , E_PARSE , E_CORE_ERROR , E_COMPILE_ERROR , E_USER_ERROR ] ) ) {
168+ if ( $ last_error && in_array ( $ last_error ['type ' ], [
169+ E_ERROR ,
170+ E_PARSE ,
171+ E_CORE_ERROR ,
172+ E_COMPILE_ERROR ,
173+ E_USER_ERROR
174+ ] ) ) {
169175 $ this ->capture_error (
170176 sprintf (
171177 'PHP Fatal Error: %s in %s:%d ' ,
@@ -174,14 +180,14 @@ public function dash_shutdown_handler() {
174180 $ last_error ['line ' ]
175181 ),
176182 self ::ERROR_TYPE_FATAL ,
177- $ last_error [ ' type ' ]
183+ 5001
178184 );
179185 } else {
180186 // Script was killed, interrupted, or failed unexpectedly
181187 $ this ->capture_error (
182188 'Backup process was interrupted or killed unexpectedly ' ,
183189 self ::ERROR_TYPE_INTERRUPTED ,
184- 0
190+ 6000
185191 );
186192 }
187193 }
@@ -200,7 +206,7 @@ public function dash_shutdown_handler() {
200206 *
201207 * @param string $message Error message describing what went wrong.
202208 * @param string $type Error type category (use ERROR_TYPE_* constants).
203- * @param int $code Error code for additional context (optional).
209+ * @param int $code Error code for additional context (optional).
204210 */
205211 private function capture_error ( $ message , $ type = self ::ERROR_TYPE_UNKNOWN , $ code = 0 ) {
206212 // Only capture the first error (root cause)
@@ -425,7 +431,17 @@ private function backup_site_dir( $backup_dir ) {
425431 $ backup_file = $ backup_dir . '/ ' . $ this ->site_data ['site_url ' ] . '.zip ' ;
426432 $ backup_command = sprintf ( 'cd %s && 7z a -mx=1 %s . ' , $ site_dir , $ backup_file );
427433
428- EE ::exec ( $ backup_command );
434+ $ result = EE ::exec ( $ backup_command );
435+
436+ // Check if archive was created successfully
437+ if ( ! $ result || ! $ this ->fs ->exists ( $ backup_file ) ) {
438+ $ this ->capture_error (
439+ 'Failed to create site backup archive ' ,
440+ self ::ERROR_TYPE_FILESYSTEM ,
441+ 3002
442+ );
443+ EE ::error ( 'Failed to create backup archive. Please check disk space and file permissions. ' );
444+ }
429445
430446 return $ backup_file ;
431447 }
@@ -454,7 +470,16 @@ private function backup_wp_content_dir( $backup_dir ) {
454470 }
455471
456472 $ backup_command = sprintf ( 'cd %s && 7z a -mx=1 %s wp-config.php ' , $ site_dir . '/../ ' , $ backup_file );
457- EE ::exec ( $ backup_command );
473+ $ result = EE ::exec ( $ backup_command );
474+
475+ if ( ! $ result ) {
476+ $ this ->capture_error (
477+ 'Failed to create WordPress content backup archive ' ,
478+ self ::ERROR_TYPE_FILESYSTEM ,
479+ 3002
480+ );
481+ EE ::error ( 'Failed to create backup archive. Please check disk space and file permissions. ' );
482+ }
458483
459484 // meta.json path
460485 $ meta_file = $ backup_dir . '/meta.json ' ;
@@ -472,6 +497,16 @@ private function backup_wp_content_dir( $backup_dir ) {
472497 EE ::exec ( $ backup_command );
473498 }
474499
500+ // Final check that backup file was created successfully
501+ if ( ! $ this ->fs ->exists ( $ backup_file ) ) {
502+ $ this ->capture_error (
503+ 'Failed to create WordPress content backup archive ' ,
504+ self ::ERROR_TYPE_FILESYSTEM ,
505+ 3002
506+ );
507+ EE ::error ( 'Failed to create backup archive. Please check disk space and file permissions. ' );
508+ }
509+
475510 return $ backup_file ;
476511 }
477512
@@ -482,7 +517,16 @@ private function backup_nginx_conf( $backup_dir ) {
482517 $ backup_file = $ backup_dir . '/conf.zip ' ;
483518 $ backup_command = sprintf ( 'cd %s && 7z a -mx=1 %s nginx ' , $ conf_dir , $ backup_file );
484519
485- EE ::exec ( $ backup_command );
520+ $ result = EE ::exec ( $ backup_command );
521+
522+ if ( ! $ result ) {
523+ $ this ->capture_error (
524+ 'Failed to create nginx configuration backup archive ' ,
525+ self ::ERROR_TYPE_FILESYSTEM ,
526+ 3002
527+ );
528+ EE ::error ( 'Failed to create nginx configuration backup archive. Please check disk space and file permissions. ' );
529+ }
486530 }
487531
488532 private function backup_php_conf ( $ backup_dir ) {
@@ -492,7 +536,16 @@ private function backup_php_conf( $backup_dir ) {
492536 $ backup_file = $ backup_dir . '/conf.zip ' ;
493537 $ backup_command = sprintf ( 'cd %s && 7z u -mx=1 %s php ' , $ conf_dir , $ backup_file );
494538
495- EE ::exec ( $ backup_command );
539+ $ result = EE ::exec ( $ backup_command );
540+
541+ if ( ! $ result ) {
542+ $ this ->capture_error (
543+ 'Failed to create PHP configuration backup archive ' ,
544+ self ::ERROR_TYPE_FILESYSTEM ,
545+ 3002
546+ );
547+ EE ::error ( 'Failed to create PHP configuration backup archive. Please check disk space and file permissions. ' );
548+ }
496549 }
497550
498551 private function backup_html ( $ backup_dir ) {
@@ -541,10 +594,31 @@ private function backup_db( $backup_dir ) {
541594 $ options = [ 'skip-tty ' => true ];
542595
543596 EE ::run_command ( $ args , $ assoc_args , $ options );
544- EE ::exec ( sprintf ( 'mv %s %s ' , EE_ROOT_DIR . '/sites/ ' . $ this ->site_data ['site_url ' ] . '/app/htdocs/ ' . $ sql_filename , $ sql_file ) );
597+
598+ $ sql_dump_path = EE_ROOT_DIR . '/sites/ ' . $ this ->site_data ['site_url ' ] . '/app/htdocs/ ' . $ sql_filename ;
599+
600+ // Check if database dump was created successfully
601+ if ( ! $ this ->fs ->exists ( $ sql_dump_path ) ) {
602+ $ this ->capture_error (
603+ sprintf ( 'Database backup failed for database: %s ' , $ db_name ),
604+ self ::ERROR_TYPE_DATABASE ,
605+ 4002
606+ );
607+ EE ::error ( 'Database backup failed. Please check database credentials and connectivity. ' );
608+ }
609+
610+ EE ::exec ( sprintf ( 'mv %s %s ' , $ sql_dump_path , $ sql_file ) );
545611 $ backup_command = sprintf ( 'cd %s && 7z u -mx=1 %s sql ' , $ backup_dir , $ backup_file );
546612
547- EE ::exec ( $ backup_command );
613+ $ result = EE ::exec ( $ backup_command );
614+ if ( ! $ result ) {
615+ $ this ->capture_error (
616+ 'Failed to compress database backup into archive ' ,
617+ self ::ERROR_TYPE_FILESYSTEM ,
618+ 3002
619+ );
620+ EE ::error ( 'Failed to compress database backup. Please check disk space. ' );
621+ }
548622 $ this ->fs ->remove ( $ backup_dir . '/sql ' );
549623 }
550624
@@ -751,16 +825,17 @@ private function pre_backup_restore_checks() {
751825 $ command = 'rclone listremotes ' ;
752826 $ output = EE ::launch ( $ command );
753827
754- $ rclone_path = get_config_value ( 'rclone-path ' , 'easyengine:easyengine ' );
755- $ rclone_path = explode ( ': ' , $ rclone_path )[0 ] . ': ' ;
828+ $ rclone_path = get_config_value ( 'rclone-path ' , 'easyengine:easyengine ' );
829+ $ rclone_backend = explode ( ': ' , $ rclone_path )[0 ];
830+ $ rclone_path = $ rclone_backend . ': ' ;
756831
757832 if ( strpos ( $ output ->stdout , $ rclone_path ) === false ) {
758833 $ this ->capture_error (
759- 'rclone backend easyengine does not exist ' ,
834+ sprintf ( 'rclone backend "%s" is not configured. Please create it using `rclone config` ' , $ rclone_backend ) ,
760835 self ::ERROR_TYPE_CONFIG ,
761836 2002
762837 );
763- EE ::error ( 'rclone backend easyengine does not exist. Please create it using `rclone config` ' );
838+ EE ::error ( sprintf ( 'rclone backend "%s" does not exist. Please create it using `rclone config` ' , $ rclone_backend ) );
764839 }
765840
766841 $ this ->check_and_install ( 'zip ' , 'zip ' );
@@ -1217,7 +1292,7 @@ private function cleanup_old_backups() {
12171292 // Check if we have more backups than allowed
12181293 if ( count ( $ backups ) > ( $ no_of_backups + 1 ) ) {
12191294 $ backups_to_delete = array_slice ( $ backups , $ no_of_backups );
1220-
1295+
12211296 EE ::log ( sprintf ( 'Cleaning up old backups. Keeping %d most recent backups. ' , $ no_of_backups ) );
12221297 foreach ( $ backups_to_delete as $ backup ) {
12231298 EE ::log ( 'Deleting old backup: ' . $ backup );
@@ -1241,6 +1316,7 @@ private function cleanup_old_backups() {
12411316 private function rollback_failed_backup () {
12421317 if ( empty ( $ this ->dash_new_backup_path ) ) {
12431318 EE ::warning ( 'Cannot rollback backup: backup path not found. ' );
1319+
12441320 return ;
12451321 }
12461322
@@ -1305,10 +1381,11 @@ private function restore_php_conf( $backup_dir ) {
13051381 /**
13061382 * Send success callback to EasyDash API after successful backup.
13071383 *
1308- * @param string $ed_api_url The EasyDash API URL.
1309- * @param string $backup_id The backup ID.
1310- * @param string $verify_token The verification token.
1311- * @param array $backup_metadata The backup metadata.
1384+ * @param string $ed_api_url The EasyDash API URL.
1385+ * @param string $backup_id The backup ID.
1386+ * @param string $verify_token The verification token.
1387+ * @param array $backup_metadata The backup metadata.
1388+ *
13121389 * @return bool True if API request succeeded, false otherwise.
13131390 */
13141391 private function send_dash_success_callback ( $ ed_api_url , $ backup_id , $ verify_token , $ backup_metadata ) {
@@ -1365,10 +1442,10 @@ private function send_dash_failure_callback( $ed_api_url, $backup_id, $verify_to
13651442 ];
13661443
13671444 EE ::debug ( 'Sending failure callback with error details: ' . json_encode ( [
1368- 'error_message ' => $ payload ['error_message ' ],
1369- 'error_type ' => $ payload ['error_type ' ],
1370- 'error_code ' => $ payload ['error_code ' ],
1371- ] ) );
1445+ 'error_message ' => $ payload ['error_message ' ],
1446+ 'error_type ' => $ payload ['error_type ' ],
1447+ 'error_code ' => $ payload ['error_code ' ],
1448+ ] ) );
13721449
13731450 $ this ->send_dash_request ( $ endpoint , $ payload );
13741451 }
@@ -1377,14 +1454,15 @@ private function send_dash_failure_callback( $ed_api_url, $backup_id, $verify_to
13771454 * Send HTTP request to EasyEngine Dashboard API with retry logic for 5xx errors and connection errors.
13781455 *
13791456 * @param string $endpoint The API endpoint URL.
1380- * @param array $payload The request payload.
1457+ * @param array $payload The request payload.
1458+ *
13811459 * @return bool True if request succeeded, false otherwise.
13821460 */
13831461 private function send_dash_request ( $ endpoint , $ payload ) {
1384- $ max_retries = 3 ;
1385- $ retry_delay = 300 ; // 5 minutes in seconds
1462+ $ max_retries = 3 ;
1463+ $ retry_delay = 300 ; // 5 minutes in seconds
13861464 $ max_attempts = $ max_retries + 1 ; // 1 initial attempt + 3 retries = 4 total
1387- $ attempt = 1 ;
1465+ $ attempt = 1 ;
13881466
13891467 while ( $ attempt <= $ max_attempts ) {
13901468 $ ch = curl_init ( $ endpoint );
@@ -1397,9 +1475,9 @@ private function send_dash_request( $endpoint, $payload ) {
13971475 ] );
13981476 curl_setopt ( $ ch , CURLOPT_TIMEOUT , 30 );
13991477
1400- $ response = curl_exec ( $ ch );
1478+ $ response = curl_exec ( $ ch );
14011479 $ http_code = curl_getinfo ( $ ch , CURLINFO_HTTP_CODE );
1402- $ error = curl_error ( $ ch );
1480+ $ error = curl_error ( $ ch );
14031481
14041482 curl_close ( $ ch );
14051483
@@ -1410,13 +1488,14 @@ private function send_dash_request( $endpoint, $payload ) {
14101488 if ( ! $ error && $ http_code >= 200 && $ http_code < 300 ) {
14111489 EE ::log ( 'EasyEngine Dashboard callback sent successfully. ' );
14121490 EE ::debug ( 'EasyEngine Dashboard response: ' . $ response_text );
1491+
14131492 return true ; // Success
14141493 }
14151494
14161495 // Determine if this is a retryable error
1417- $ is_5xx_error = $ http_code >= 500 && $ http_code < 600 ;
1496+ $ is_5xx_error = $ http_code >= 500 && $ http_code < 600 ;
14181497 $ is_connection_error = ! empty ( $ error ) || $ http_code === 0 ;
1419- $ should_retry = ( $ is_5xx_error || $ is_connection_error ) && $ attempt < $ max_attempts ;
1498+ $ should_retry = ( $ is_5xx_error || $ is_connection_error ) && $ attempt < $ max_attempts ;
14201499
14211500 if ( $ should_retry ) {
14221501 // Retry on 5xx errors or connection errors
@@ -1470,6 +1549,7 @@ private function send_dash_request( $endpoint, $payload ) {
14701549 // 4xx or other HTTP error codes that shouldn't be retried
14711550 EE ::warning ( 'EasyEngine Dashboard callback returned HTTP ' . $ http_code . '. Response: ' . $ response_text );
14721551 }
1552+
14731553 return false ; // Failure
14741554 }
14751555 }
@@ -1481,12 +1561,14 @@ private function send_dash_request( $endpoint, $payload ) {
14811561 * Sanitize count value for API payload.
14821562 *
14831563 * @param mixed $value The value to sanitize.
1564+ *
14841565 * @return int The sanitized integer value.
14851566 */
14861567 private function sanitize_count ( $ value ) {
14871568 if ( $ value === '- ' || ! is_numeric ( $ value ) ) {
14881569 return 0 ;
14891570 }
1571+
14901572 return intval ( $ value );
14911573 }
14921574}
0 commit comments