Skip to content

Instantly share code, notes, and snippets.

@cuongdcdev
Last active August 5, 2020 15:48
Show Gist options
  • Save cuongdcdev/1f1f67e3c65590b92153bf3ad78e3537 to your computer and use it in GitHub Desktop.
Save cuongdcdev/1f1f67e3c65590b92153bf3ad78e3537 to your computer and use it in GitHub Desktop.
<?php
/**
* BackWPup_Destination_Downloader
*
* @since 3.6.0
* @package Inpsyde\BackWPup
*/
use Inpsyde\Restore\Api\Controller\DecryptController;
use Inpsyde\Restore\Api\Module\Decryption\Exception\DecryptException;
/**
* Class BackWPup_Destination_Downloader
*
* @since 3.6.0
* @package Inpsyde\BackWPup
*/
class BackWPup_Destination_Downloader {
const ARCHIVE_ENCRYPT_OPTION = 'archiveencryption';
const CAPABILITY = 'backwpup_backups_download';
const STATE_DOWNLOADING = 'downloading';
const STATE_ERROR = 'error';
const STATE_DONE = 'done';
/**
* @var \BackWpUp_Destination_Downloader_Data
*/
private $data;
/**
* @var \BackWPup_Destination_Downloader_Interface
*/
private $destination;
/**
* Download file via ajax
*/
public static function download_by_ajax() {
$dest = (string) filter_input( INPUT_GET, 'destination', FILTER_SANITIZE_STRING );
if ( ! $dest ) {
return;
}
$job_id = (int) filter_input( INPUT_GET, 'jobid', FILTER_SANITIZE_NUMBER_INT );
if ( ! $job_id ) {
return;
}
$file = (string) filter_input( INPUT_GET, 'file', FILTER_SANITIZE_STRING );
$file_local = (string) filter_input( INPUT_GET, 'local_file', FILTER_SANITIZE_STRING );
if ( ! $file || ! $file_local ) {
return;
}
set_time_limit( 0 );
// Set up eventsource headers
header( 'Content-Type: text/event-stream' );
header( 'Cache-Control: no-cache' );
header( 'X-Accel-Buffering: no' );
header( 'Content-Encoding: none' );
// 2KB padding for IE
echo ':' . str_repeat( ' ', 2048 ) . "\n\n"; // phpcs:ignore
// Ensure we're not buffered.
wp_ob_end_flush_all();
flush();
/** @var \BackWPup_Destinations $dest_class */
$dest_class = BackWPup::get_destination( $dest );
$dest_class->file_download(
$job_id,
trim( sanitize_text_field( $file ) ),
trim( sanitize_text_field( $file_local ) )
);
}
/**
* BackWPup_Downloader constructor
*
* @param \BackWpUp_Destination_Downloader_Data $data
* @param \BackWPup_Destination_Downloader_Interface $destination
*/
public function __construct(
BackWpUp_Destination_Downloader_Data $data,
BackWPup_Destination_Downloader_Interface $destination
) {
$this->data = $data;
$this->destination = $destination;
}
/**
* @return bool
*/
public function download_by_chunks() {
$this->ensure_user_can_download();
$source_file_path = $this->data->source_file_path();
$local_file_path = $this->data->local_file_path();
$size = $this->destination->calculate_size();
$start_byte = 0;
$chunk_size = 512 * 1024;
$end_byte = $start_byte + $chunk_size - 1;
if ( $end_byte >= $size ) {
$end_byte = $size - 1;
}
try {
while ( $end_byte <= $size ) {
$this->destination->download_chunk( $start_byte, $end_byte );
self::send_message(
array(
'state' => self::STATE_DOWNLOADING,
'start_byte' => $start_byte,
'end_byte' => $end_byte,
'size' => $size,
'download_percent' => round( ( $end_byte + 1 ) / $size * 100 ),
'filename' => basename( $source_file_path ),
)
);
if ( $end_byte === $size - 1 ) {
break;
}
$start_byte = $end_byte + 1;
$end_byte = $start_byte + $chunk_size - 1;
if ( $start_byte < $size && $end_byte >= $size ) {
$end_byte = $size - 1;
}
}
if ( BackWPup::is_pro() ) {
$decrypter = \Inpsyde\BackWPup\Pro\Restore\Functions\restore_container( 'decrypter' );
if ( $decrypter->maybe_decrypted( $local_file_path ) ) {
throw new DecryptException( DecryptController::STATE_NEED_DECRYPTION_KEY );
}
}
} catch ( \Exception $e ) {
self::send_message(
array(
'state' => self::STATE_ERROR,
'message' => $e->getMessage(),
),
'log'
);
return false;
}
self::send_message( array(
'state' => self::STATE_DONE,
'message' => esc_html__( 'Your download is being generated &hellip;', 'backwpup' ),
) );
return true;
}
/**
* Ensure user capability
*/
private function ensure_user_can_download() {
if ( ! current_user_can( self::CAPABILITY ) ) {
wp_die();
}
}
/**
* @param $data
* @param string $event
*/
private static function send_message( $data, $event = 'message' ) {
echo "event: {$event}\n";
echo "data: " . wp_json_encode( $data ) . "\n\n";
flush();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment