Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 176 additions & 1 deletion src/helper/Site_Backup_Restore.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ class Site_Backup_Restore {
public $site_data;
private $rclone_config_path;

// Properties for EasyDash callback handling
Comment thread
mrrobot47 marked this conversation as resolved.
private $dash_auth_enabled = false;
private $dash_backup_id;
private $dash_verify_token;
private $dash_api_url;
private $dash_backup_metadata;
private $dash_backup_completed = false;

public function __construct() {
$this->fs = new Filesystem();
}
Expand All @@ -32,13 +40,47 @@ public function backup( $args, $assoc_args = [] ) {
return; // Exit after listing backups
}

// Handle --dash-auth flag for EasyDash integration
$dash_auth = \EE\Utils\get_flag_value( $assoc_args, 'dash-auth' );
Comment thread
mrrobot47 marked this conversation as resolved.

if ( $dash_auth ) {
// Debug: Log the raw dash_auth value received
EE::debug( 'Received --dash-auth value: ' . $dash_auth );

// Parse backup-id:backup-verification-token format
$auth_parts = explode( ':', $dash_auth, 2 );
if ( count( $auth_parts ) !== 2 || empty( $auth_parts[0] ) || empty( $auth_parts[1] ) ) {
EE::error( 'Invalid --dash-auth format. Expected: backup-id:backup-verification-token' );
}
Comment thread
mrrobot47 marked this conversation as resolved.

// Check for ed-api-url configuration
$ed_api_url = get_config_value( 'ed-api-url', '' );
if ( empty( $ed_api_url ) ) {
EE::error( 'ed-api-url is not configured. Please set it in /opt/easyengine/config/config.yml' );
Comment thread
mrrobot47 marked this conversation as resolved.
}

// Store dash auth info in class properties for shutdown handler
$this->dash_auth_enabled = true;
$this->dash_backup_id = $auth_parts[0];
$this->dash_verify_token = $auth_parts[1];
$this->dash_api_url = $ed_api_url;

// Debug: Log parsed values
EE::debug( 'Parsed backup_id: ' . $this->dash_backup_id );
EE::debug( 'Parsed verify_token: ' . $this->dash_verify_token );
Comment thread
mrrobot47 marked this conversation as resolved.
EE::debug( 'API URL: ' . $this->dash_api_url );
Comment thread
mrrobot47 marked this conversation as resolved.

// Register shutdown handler to send failure callback if backup doesn't complete
Comment thread
mrrobot47 marked this conversation as resolved.
register_shutdown_function( [ $this, 'dash_shutdown_handler' ] );
}

$this->pre_backup_check();
$backup_dir = EE_BACKUP_DIR . '/' . $this->site_data['site_url'];

$this->fs->remove( $backup_dir );
$this->fs->mkdir( $backup_dir );

$this->backup_site_details( $backup_dir );
$this->dash_backup_metadata = $this->backup_site_details( $backup_dir );

switch ( $this->site_data['site_type'] ) {
case 'html':
Expand All @@ -56,9 +98,36 @@ public function backup( $args, $assoc_args = [] ) {
$this->fs->remove( $backup_dir );

$this->fs->remove( EE_BACKUP_DIR . '/' . $this->site_data['site_url'] . '.lock' );

// Mark backup as completed and send success callback
$this->dash_backup_completed = true;
if ( $this->dash_auth_enabled ) {
$this->send_dash_success_callback(
$this->dash_api_url,
$this->dash_backup_id,
$this->dash_verify_token,
$this->dash_backup_metadata
);
}

delem_log( 'site backup end' );
}

/**
* Shutdown handler to send failure callback to EasyDash if backup didn't complete.
Comment thread
mrrobot47 marked this conversation as resolved.
* This is called when script terminates (including via EE::error which calls exit).
*/
public function dash_shutdown_handler() {
// Only send failure callback if dash auth was enabled and backup didn't complete
if ( $this->dash_auth_enabled && ! $this->dash_backup_completed ) {
$this->send_dash_failure_callback(
$this->dash_api_url,
$this->dash_backup_id,
$this->dash_verify_token
);
}
}
Comment thread
mrrobot47 marked this conversation as resolved.

public function restore( $args, $assoc_args = [] ) {

delem_log( 'site restore start' );
Expand Down Expand Up @@ -1042,4 +1111,110 @@ private function restore_php_conf( $backup_dir ) {
EE::exec( $restore_command );
}
}

/**
* Send success callback to EasyDash API after successful backup.
*
* @param string $ed_api_url The EasyDash API URL.
* @param string $backup_id The backup ID.
* @param string $verify_token The verification token.
* @param array $backup_metadata The backup metadata.
*/
Comment thread
mrrobot47 marked this conversation as resolved.
private function send_dash_success_callback( $ed_api_url, $backup_id, $verify_token, $backup_metadata ) {
$endpoint = rtrim( $ed_api_url, '/' ) . '/easydash.easydash.doctype.site_backup.site_backup.on_ee_backup_success';

// Debug: Log the values being used for callback
EE::debug( 'Sending success callback with backup_id: ' . $backup_id );
EE::debug( 'Sending success callback with verify_token: ' . $verify_token );

// Build metadata for the API call - always include all fields
$metadata = [
'post_count' => $this->sanitize_count( $backup_metadata['post_count'] ?? 0 ),
'theme_count' => $this->sanitize_count( $backup_metadata['theme_count'] ?? 0 ),
'user_count' => $this->sanitize_count( $backup_metadata['user_count'] ?? 0 ),
'plugin_count' => $this->sanitize_count( $backup_metadata['plugin_count'] ?? 0 ),
'wp_version' => $backup_metadata['wp_version'] ?? '',
'comment_count' => $this->sanitize_count( $backup_metadata['comment_count'] ?? 0 ),
'page_count' => $this->sanitize_count( $backup_metadata['page_count'] ?? 0 ),
'upload_count' => $this->sanitize_count( $backup_metadata['upload_count'] ?? 0 ),
'site_type' => $backup_metadata['site_type'] ?? 'html',
'remote_path' => $backup_metadata['remote_path'] ?? '',
];

$payload = [
'site' => $this->site_data['site_url'],
'backup' => $backup_id,
'verify' => $verify_token,
'metadata' => $metadata,
];

EE::debug( 'Payload being sent: ' . json_encode( $payload ) );
Comment thread
mrrobot47 marked this conversation as resolved.

Comment thread
mrrobot47 marked this conversation as resolved.
$this->send_dash_request( $endpoint, $payload );
}

/**
* Send failure callback to EasyDash API after failed backup.
*
* @param string $ed_api_url The EasyDash API URL.
* @param string $backup_id The backup ID.
* @param string $verify_token The verification token.
*/
Comment thread
mrrobot47 marked this conversation as resolved.
private function send_dash_failure_callback( $ed_api_url, $backup_id, $verify_token ) {
$endpoint = rtrim( $ed_api_url, '/' ) . '/easydash.easydash.doctype.site_backup.site_backup.on_ee_backup_failure';

$payload = [
'site' => $this->site_data['site_url'],
'backup' => $backup_id,
'verify' => $verify_token,
];

$this->send_dash_request( $endpoint, $payload );
}

/**
* Send HTTP request to EasyDash API.
*
* @param string $endpoint The API endpoint URL.
* @param array $payload The request payload.
*/
Comment thread
mrrobot47 marked this conversation as resolved.
private function send_dash_request( $endpoint, $payload ) {
$ch = curl_init( $endpoint );

curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $payload ) );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
] );
curl_setopt( $ch, CURLOPT_TIMEOUT, 30 );
Comment thread
mrrobot47 marked this conversation as resolved.

$response = curl_exec( $ch );
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
$error = curl_error( $ch );

curl_close( $ch );
Comment thread
mrrobot47 marked this conversation as resolved.

if ( $error ) {
EE::warning( 'Failed to send callback to EasyDash: ' . $error );
} elseif ( $http_code >= 400 ) {
EE::warning( 'EasyDash callback returned HTTP ' . $http_code . '. Response: ' . $response );
Comment thread
mrrobot47 marked this conversation as resolved.
} else {
EE::log( 'EasyDash callback sent successfully.' );
EE::debug( 'EasyDash response: ' . $response );
Comment thread
mrrobot47 marked this conversation as resolved.
Comment thread
mrrobot47 marked this conversation as resolved.
}
}

/**
* Sanitize count value for API payload.
*
* @param mixed $value The value to sanitize.
* @return int The sanitized integer value.
*/
private function sanitize_count( $value ) {
if ( $value === '-' || ! is_numeric( $value ) ) {
return 0;
}
return intval( $value );
}
}
3 changes: 3 additions & 0 deletions src/helper/class-ee-site.php
Original file line number Diff line number Diff line change
Expand Up @@ -2485,6 +2485,9 @@ public function sync( $args, $assoc_args ) {
* [--list]
* : List all available backups on remote.
*
* [--dash-auth]
* : Pass dash auth token and backup id. For EasyEngine dash use only.
*
* ## EXAMPLES
*
* # Backup a site
Expand Down
Loading