PluginProbe
WP Database Backup – Unlimited Database & Files Backup by Backup for WP / 7.7
WP Database Backup – Unlimited Database & Files Backup by Backup for WP v7.7
7.13 7.12 trunk 1.1 2.1.1 5.9 6.0 6.1 6.10 6.11 6.12 6.12.1 6.2 6.3 6.4 6.5 6.5.1 6.6 6.7 6.8 6.9 7.0 7.0.1 7.1 7.10 All 34 releases
wp-database-backup / includes / admin / Destination / Backblaze / class-wpdatabasebackupbb.php

class-wpdatabasebackupbb.php in WP Database Backup – Unlimited Database & Files Backup by Backup for WP 7.7, at includes/admin/Destination/Backblaze/class-wpdatabasebackupbb.php

299 lines 11.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Destination BlackBlaze.
4 *
5 * @package wpdbbkp
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly.
10 }
11
12
13
14
15 add_action( 'wp_db_backup_completed', array( 'WPDatabaseBackupBB', 'wp_db_backup_completed' ) );
16
17 /**
18 * WPDatabaseBackupBB Class.
19 *
20 * @class WPDatabaseBackupBB
21 */
22 class WPDatabaseBackupBB {
23
24 // Function to upload files to Backblaze B2
25 public static function upload_backup_to_backblaze($file_path, $file_name) {
26 global $wp_filesystem;
27
28 if (!function_exists('WP_Filesystem')) {
29 require_once(ABSPATH . '/wp-admin/includes/file.php');
30 }
31 WP_Filesystem();
32
33 $s3_token = get_transient('b2_authorization_token');
34 $api_url = get_transient('b2_api_url');
35 $bucket_id = get_option('wpdb_dest_bb_s3_bucket') ?: '';
36
37 if (!$s3_token) {
38 $key_id = get_option('wpdb_dest_bb_s3_bucket_key') ?: '';
39 $app_key = get_option('wpdb_dest_bb_s3_bucket_secret') ?: '';
40 $b2_authorize_url = "https://api.backblazeb2.com/b2api/v2/b2_authorize_account";
41 $credentials = base64_encode($key_id . ":" . $app_key);
42
43 // Authorize account
44 $response = wp_remote_get($b2_authorize_url, array(
45 'headers' => array('Authorization' => 'Basic ' . $credentials),
46 'timeout' => 60
47 ));
48
49 if (is_wp_error($response)) {
50 return array('success' => false, 'message' => esc_html__('Authorization request failed: ', 'wpdbbkp') . $response->get_error_message());
51 }
52
53 $body = wp_remote_retrieve_body($response);
54 $data = json_decode($body);
55
56 if (empty($data->authorizationToken)) {
57 return array('success' => false, 'message' => esc_html__('Failed to authorize with Backblaze.', 'wpdbbkp'));
58 }
59
60 $auth_token = $data->authorizationToken;
61 set_transient('b2_authorization_token', $auth_token, 1 * HOUR_IN_SECONDS);
62 set_transient('b2_api_url', $data->apiUrl, 1 * HOUR_IN_SECONDS);
63 } else {
64 $auth_token = $s3_token;
65 }
66
67 // Handle large files via multipart upload
68 $file_size = filesize($file_path);
69 $max_part_size = 100 * 1024 * 1024; // 50MB max part size
70 $is_large_file = $file_size > $max_part_size;
71
72 if ($is_large_file) {
73 return self::handle_large_file_upload($file_path, $file_name, $auth_token, $bucket_id, $max_part_size);
74 }
75
76 // If it's not a large file, proceed with single file upload
77 return self::upload_single_file($file_path, $file_name, $auth_token, $bucket_id);
78 }
79
80 // Function to handle large file multipart upload
81 public static function handle_large_file_upload($file_path, $file_name, $auth_token, $bucket_id, $max_part_size) {
82 global $wp_filesystem;
83 if (!function_exists('WP_Filesystem')) {
84 require_once(ABSPATH . '/wp-admin/includes/file.php');
85 }
86 WP_Filesystem();
87
88 if (!$wp_filesystem->exists($file_path)) {
89 return array('success' => false, 'message' => esc_html__('File does not exist: ', 'wpdbbkp') . $file_path);
90 }
91
92 $root_path = str_replace('\\', '/', ABSPATH); // Normalize to forward slashes for consistency
93 $file_name = str_replace($root_path, '', $file_name);
94 $file_name = ltrim($file_name, '/'); // Ensure there is no leading slash
95 $file_name = 'wpdbbkp/' . $file_name;
96
97 // Start large file upload
98 $start_large_file_url = get_transient('b2_api_url') . '/b2api/v2/b2_start_large_file';
99 $response = wp_remote_post($start_large_file_url, array(
100 'body' => wp_json_encode(array(
101 'bucketId' => $bucket_id,
102 'fileName' => $file_name,
103 'contentType' => 'b2/x-auto'
104 )),
105 'headers' => array(
106 'Authorization' => $auth_token,
107 'Content-Type' => 'application/json'
108 ),
109 'timeout' => 60
110 ));
111 if (is_wp_error($response)) {
112 return array('success' => false, 'message' => esc_html__('Failed to start large file upload: ', 'wpdbbkp') . $response->get_error_message());
113 }
114
115 $data = json_decode(wp_remote_retrieve_body($response));
116 $file_id = $data->fileId;
117
118 $file_size = filesize($file_path);
119 $part_size = 100 * 1024 * 1024; // 100MB per part
120 $num_parts = ceil($file_size / $part_size); // Calculate the number of parts
121
122 $handle = fopen($file_path, 'rb'); //phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen --required for large files
123 $part_sha1_array = array();
124
125 for ($i = 0; $i < $num_parts; $i++) {
126 // Get a new upload part URL for each part
127 $get_upload_part_url = get_transient('b2_api_url') . '/b2api/v2/b2_get_upload_part_url';
128 $response_2 = wp_remote_post($get_upload_part_url, array(
129 'body' => wp_json_encode(array(
130 'fileId' => $file_id
131 )),
132 'headers' => array(
133 'Authorization' => $auth_token,
134 'Content-Type' => 'application/json'
135 ),
136 'timeout' => 60
137 ));
138
139 if (is_wp_error($response_2)) {
140 fclose($handle); //phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose --required for large files
141 return array('success' => false, 'message' => esc_html__('Failed to get upload part URL: ', 'wpdbbkp') . $response_2->get_error_message());
142 }
143
144 $data_2 = json_decode(wp_remote_retrieve_body($response_2));
145 $upload_part_url = $data_2->uploadUrl;
146 $upload_part_auth_token = $data_2->authorizationToken;
147
148 // Read the part from the file
149 $file_part = fread($handle, $part_size); //phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread --required for large files
150 if ($file_part === false) {
151 fclose($handle); //phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose --required for large files
152 return array('success' => false, 'message' => esc_html__('Failed to read part ', 'wpdbbkp') . $i . ' from file.');
153 }
154
155 $sha1_of_part = sha1($file_part);
156 $part_sha1_array[] = $sha1_of_part;
157
158 // Upload each part to Backblaze
159 $response = wp_remote_post($upload_part_url, array(
160 'body' => $file_part,
161 'headers' => array(
162 'Authorization' => $upload_part_auth_token,
163 'X-Bz-Part-Number' => ($i + 1),
164 'X-Bz-Content-Sha1' => $sha1_of_part,
165 'Content-Length' => strlen($file_part)
166 ),
167 'timeout' => 1800 // 15-minute timeout for large file uploads
168 ));
169
170 if (is_wp_error($response)) {
171 fclose($handle); //phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose --required for large files
172 return array('success' => false, 'message' => esc_html__('Upload request failed for part ', 'wpdbbkp') . $i . ': ' . $response->get_error_message());
173 }
174
175 // Check response code
176 $response_code = wp_remote_retrieve_response_code($response);
177 if ($response_code != 200) {
178 fclose($handle); //phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose --required for large files
179 return array('success' => false, 'message' => esc_html__('Failed to upload part ', 'wpdbbkp') . $i);
180 }
181 }
182
183 fclose($handle); //phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose --required for large files
184
185 // Finalize large file upload
186 $finish_large_file_url = get_transient('b2_api_url') . '/b2api/v2/b2_finish_large_file';
187 $response = wp_remote_post($finish_large_file_url, array(
188 'body' => wp_json_encode(array(
189 'fileId' => $file_id,
190 'partSha1Array' => $part_sha1_array
191 )),
192 'headers' => array(
193 'Authorization' => $auth_token,
194 'Content-Type' => 'application/json'
195 ),
196 'timeout' => 60
197 ));
198
199 if (is_wp_error($response)) {
200 return array('success' => false, 'message' => esc_html__('Failed to finalize large file upload: ', 'wpdbbkp') . $response->get_error_message());
201 }
202
203 return array('success' => true, 'message' => 'Large file ' . $file_name . esc_html__(' uploaded successfully to Backblaze.', 'wpdbbkp'));
204 }
205
206
207 public static function upload_single_file($file_path, $file_name, $auth_token, $bucket_id) {
208 global $wp_filesystem;
209 $root_path = str_replace('\\', '/', ABSPATH); // Normalize to forward slashes for consistency
210 $file_name = str_replace($root_path, '', $file_name);
211 $file_name = ltrim($file_name, '/'); // Ensure there is no leading slash
212 $file_name = 'wpdbbkp/'.$file_name;
213 // Get upload URL
214 $upload_url = get_transient('b2_api_url') . '/b2api/v2/b2_get_upload_url';
215 $response = wp_remote_post($upload_url, array(
216 'body' => wp_json_encode(array('bucketId' => $bucket_id)),
217 'headers' => array(
218 'Authorization' => $auth_token,
219 'Content-Type' => 'application/json'
220 ),
221 'timeout' => 60
222 ));
223
224 if (is_wp_error($response)) {
225 return array('success' => false, 'message' => esc_html__('Failed to get upload URL: ', 'wpdbbkp') . $response->get_error_message());
226 }
227
228 $body = wp_remote_retrieve_body($response);
229 $data = json_decode($body);
230 if (empty($data->uploadUrl)) {
231 return array('success' => false, 'message' => esc_html__('Failed to get upload URL from Backblaze.', 'wpdbbkp'));
232 }
233
234 $upload_url = $data->uploadUrl;
235 $upload_auth_token = $data->authorizationToken;
236
237 // Check if file exists
238 if (!$wp_filesystem->exists($file_path)) {
239 return array('success' => false, 'message' => esc_html__('File does not exist: ', 'wpdbbkp') . $file_path);
240 }
241
242 $file_contents = $wp_filesystem->get_contents($file_path);
243 if ($file_contents === false) {
244 return array('success' => false, 'message' => esc_html__('Failed to read file: ', 'wpdbbkp') . $file_path);
245 }
246
247 $sha1_of_file_data = sha1($file_contents);
248
249 // Upload the file
250 $response = wp_remote_post($upload_url, array(
251 'body' => $file_contents,
252 'headers' => array(
253 'Authorization' => $upload_auth_token,
254 'X-Bz-File-Name' => $file_name,
255 'Content-Type' => 'b2/x-auto',
256 'X-Bz-Content-Sha1' => $sha1_of_file_data
257 ),
258 'timeout' => 900
259 ));
260
261 if (is_wp_error($response)) {
262 return array('success' => false, 'message' => esc_html__('Upload request failed: ', 'wpdbbkp') . $response->get_error_message());
263 }
264
265 $response_code = wp_remote_retrieve_response_code($response);
266 if ($response_code != 200) {
267 $response_body = wp_remote_retrieve_body($response);
268 return array('success' => false, 'message' => esc_html__('Failed to upload ', 'wpdbbkp') . $file_name . '. Response: ' . $response_body);
269 }
270
271 return array('success' => true, 'message' => 'File ' . $file_name . esc_html__(' uploaded successfully to Backblaze.', 'wpdbbkp'));
272 }
273
274
275 /**
276 * Run after complete backup.
277 *
278 * @param array $args - backup details.
279 */
280
281 public static function wp_db_backup_completed( &$args ) {
282 $destination_s3 = get_option( 'wp_db_backup_destination_bb' );
283 if ( isset( $destination_s3 ) && 1 == $destination_s3 && get_option( 'wpdb_dest_bb_s3_bucket_host' ) && get_option( 'wpdb_dest_bb_s3_bucket' ) && get_option( 'wpdb_dest_bb_s3_bucket_key' ) && get_option( 'wpdb_dest_bb_s3_bucket_secret' ) ) {
284
285 try {
286
287 $ret = WPDatabaseBackupBB::upload_backup_to_backblaze($args[1], $args[1]);
288 $args[2] = $args[2] .$ret['message'];
289 if ($ret['success']) {
290 $args[4] .= 'Backblaze, ';
291 }
292 } catch ( Exception $e ) {
293 $args[2] = $args[2] . "<br>".esc_html__("Failed to upload Database Backup on s3 bucket", 'wpdbbkp');
294 }
295 }
296 }
297
298 }
299