PluginProbe
Media Cloud Sync / trunk
Media Cloud Sync vtrunk
1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 All 34 releases
← All changes | includes/base/service.php +485 -581 1.2.12trunk View file →
@@ -7,15 +7,22 @@
7 7 private static $instance = null;
8 8 private $assets_url;
9 9 private $version;
10 10 private $token;
11 - private $service = false;
11 + private $service = false;
12 + private $providers = [
13 + 's3' => ['class' => 'S3', 'sdk' => 's3'],
14 + 'gcloud' => ['class' => 'GCloud', 'sdk' => 'google'],
15 + 'docean' => ['class' => 'DOcean', 'sdk' => 's3'],
16 + 'cloudflareR2' => ['class' => 'CloudflareR2', 'sdk' => 's3'],
17 + 's3compatible' => ['class' => 'S3Compatible', 'sdk' => 's3'],
18 + ];
12 19
13 20 protected $settings;
14 21
15 22
16 23 /**
17 - * Admin constructor.
24 + * Service constructor.
18 25 * @since 1.0.0
19 26 */
20 27 public function __construct() {
21 28 $this->assets_url = WPMCS_ASSETS_URL;
@@ -24,22 +31,11 @@
24 31
25 32 $this->settings = Utils::get_settings();
26 33
27 34 $current_service = Utils::get_service();
28 - switch ($current_service) {
29 - case 's3':
30 - $this->service = new S3;
31 - break;
32 - case 'gcloud':
33 - $this->service = new GCloud;
34 - break;
35 - case 'docean':
36 - $this->service = new DOcean;
37 - break;
38 - case 's3compatible':
39 - $this->service = new S3Compatible;
40 - break;
41 - default:$this->service = false;
35 +
36 + if($current_service) {
37 + $this->service = $this->get_handler_class($current_service);
42 38 }
43 39 }
44 40
45 41 /**
@@ -52,10 +48,11 @@
52 48 'message' => esc_html__('Something went wrong', 'media-cloud-sync')
53 49 ];
54 50
55 51 $service = isset($data['service'])? $data['service'] : false;
52 + $handler_class = $this->get_handler_class($service);
56 53
57 - if($service == false) {
54 + if($service == false || $handler_class == false) {
58 55 $result = [
59 56 'success' => false,
60 57 'message' => esc_html__('No service selected', 'media-cloud-sync')
61 58 ];
@@ -61,95 +58,237 @@
61 58 ];
62 59 return $result;
63 60 }
64 61
65 - switch($service){
66 - case 's3':
67 - $config = isset($data['config']) ? $data['config'] : [];
68 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
69 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
70 - $region = isset($config['region']) ? $config['region'] : false;
62 + $configSource = isset($data['configSource']) ? $data['configSource'] : 'database';
71 63
72 - if($access_key==false || $secret_key==false || $region==false) {
73 - $result = [
74 - 'success' => false,
75 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
76 - ];
77 - return $result;
64 + if($configSource === 'config') {
65 + // Credentials come from a wp-config.php constant — WPMCS_CONFIG by default, or
66 + // a caller-supplied constant (e.g. Bucket-to-Bucket's destination uses WPMCS_BTB_CONFIG).
67 + $constant = !empty($data['wpConfigConstant']) ? $data['wpConfigConstant'] : 'WPMCS_CONFIG';
68 + if(!Utils::is_wp_config_credentials_defined($constant)) {
69 + return [
70 + 'success' => false,
71 + /* translators: %s: wp-config.php constant name */
72 + 'message' => sprintf(esc_html__('%s is not defined in wp-config.php', 'media-cloud-sync'), $constant)
73 + ];
74 + }
75 +
76 + $config = Utils::get_wp_config_credentials($constant);
77 + $missing = [];
78 + foreach(self::get_required_config_keys($service) as $key) {
79 + if(!isset($config[$key]) || $config[$key] === '') {
80 + $missing[] = $key;
78 81 }
82 + }
83 + if(!empty($missing)) {
84 + return [
85 + 'success' => false,
86 + /* translators: 1: wp-config.php constant name, 2: comma separated list of missing configuration keys */
87 + 'message' => sprintf(esc_html__('%1$s is missing key(s): %2$s', 'media-cloud-sync'), $constant, implode(', ', $missing))
88 + ];
89 + }
90 + } else {
91 + $config = $this->resolve_config($data);
92 + }
79 93
80 - $currentService = new S3;
81 - return $currentService->verifyCredentials($access_key, $secret_key, $region);
82 - break;
83 - case 'gcloud':
84 - $config = isset($data['config']) ? $data['config'] : [];
85 - $config_json = isset($config['config_json']) ? $config['config_json'] : '';
94 + return $handler_class->verifyCredentials($config);
95 + }
86 96
87 - if(!(isset($config_json) && !empty($config_json))) {
88 - $result = [
89 - 'success' => false,
90 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
91 - ];
92 - return $result;
93 - }
94 -
95 - if(!Utils::is_json($config_json)) {
96 - $result = [
97 - 'success' => false,
98 - 'message' => esc_html__('Invalid JSON. Please try again', 'media-cloud-sync')
99 - ];
100 - return $result;
101 - }
97 + /**
98 + * True if any of the given values is empty.
99 + * Shared guard for provider config-validation checks (region/access_key/
100 + * secret_key/bucket_name/etc.) so each provider class doesn't reimplement
101 + * the same empty() chain.
102 + * @since 1.3.11
103 + * @param array $fields
104 + * @return bool
105 + */
106 + public static function has_missing_fields(array $fields) {
107 + foreach ($fields as $field) {
108 + if (empty($field)) {
109 + return true;
110 + }
111 + }
112 + return false;
113 + }
102 114
103 - $currentService = new GCloud;
104 - return $currentService->verifyCredentials($config_json);
105 - break;
106 - case 'docean':
107 - $config = isset($data['config']) ? $data['config'] : [];
108 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
109 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
110 - $region = isset($config['region']) ? $config['region'] : false;
115 + /**
116 + * Resolve the credential config for a wizard request. 'config' pulls credentials from a
117 + * wp-config.php constant instead of the payload; 'existing' reuses the site's currently
118 + * connected primary connection's credentials (e.g. Bucket-to-Bucket's destination form,
119 + * migrating to a different bucket under the same account).
120 + * @since 1.3.11
121 + * @param array $data
122 + * @return array
123 + */
124 + private function resolve_config($data) {
125 + $configSource = isset($data['configSource']) ? $data['configSource'] : 'database';
126 + if($configSource === 'config') {
127 + $constant = !empty($data['wpConfigConstant']) ? $data['wpConfigConstant'] : 'WPMCS_CONFIG';
128 + return Utils::get_wp_config_credentials($constant);
129 + }
130 + if($configSource === 'existing') {
131 + $current = Utils::get_credentials('', []);
132 + return isset($current['config']) && is_array($current['config']) ? $current['config'] : [];
133 + }
134 + return isset($data['config']) ? $data['config'] : [];
135 + }
111 136
112 - if($access_key==false || $secret_key==false || $region==false) {
113 - $result = [
114 - 'success' => false,
115 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
116 - ];
117 - return $result;
118 - }
137 + /**
138 + * Required configuration keys per provider, used to validate the
139 + * WPMCS_CONFIG constant before attempting credential verification.
140 + * @since 1.3.11
141 + * @param string $service
142 + * @return array
143 + */
144 + public static function get_required_config_keys($service) {
145 + $required = [
146 + 's3' => ['access_key', 'secret_key', 'region'],
147 + 'gcloud' => ['config_json'],
148 + 'docean' => ['access_key', 'secret_key', 'region'],
149 + 'cloudflareR2' => ['account_id', 'access_key', 'secret_key'],
150 + 's3compatible' => ['endpoint', 'access_key', 'secret_key'],
151 + ];
152 + return isset($required[$service]) ? $required[$service] : [];
153 + }
119 154
120 - $currentService = new DOcean;
121 - return $currentService->verifyCredentials($access_key, $secret_key, $region);
122 - break;
123 - case 's3compatible':
124 - $config = isset($data['config']) ? $data['config'] : [];
125 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
126 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
127 - $region = isset($config['region']) ? $config['region'] : false;
128 - $endpoint = isset($config['endpoint']) ? $config['endpoint'] : false;
155 + /**
156 + * Persist a connection status result and normalize the response payload.
157 + * @since 1.3.11
158 + * @param string $status_key
159 + * @param array $result
160 + * @return array
161 + */
162 + private function persist_connection_status($status_key, $result) {
163 + $lastChecked = isset($result['lastChecked']) ? $result['lastChecked'] : time();
164 + $success = !empty($result['success']);
165 + $message = isset($result['message']) ? $result['message'] : '';
129 166
130 - if($access_key==false || $secret_key==false || $endpoint==false) {
131 - $result = [
132 - 'success' => false,
133 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
134 - ];
135 - return $result;
136 - }
167 + Utils::set_status($status_key, [
168 + 'status' => $success,
169 + 'message' => $message,
170 + 'lastChecked' => $lastChecked,
171 + ]);
137 172
138 - $currentService = new S3Compatible;
139 - return $currentService->verifyCredentials($endpoint, $access_key, $secret_key, $region);
140 - break;
141 - default:
142 - $result = [
143 - 'success' => false,
144 - 'message' => esc_html__('Invalid service', 'media-cloud-sync')
145 - ];
173 + return [
174 + 'success' => $success,
175 + 'message' => $message,
176 + 'lastChecked' => $lastChecked,
177 + ];
178 + }
179 +
180 + /**
181 + * Verify saved storage credentials and bucket write access.
182 + * @since 1.3.11
183 + * @return array
184 + */
185 + private function run_storage_status_check() {
186 + if(!Utils::is_service_enabled()) {
187 + return $this->persist_connection_status('storageCredentials', [
188 + 'success' => false,
189 + 'message' => Utils::get_service_configuration_error(),
190 + 'lastChecked' => time(),
191 + ]);
146 192 }
147 193
148 - return $result;
194 + $credentials = Utils::get_credentials();
195 + $data = [
196 + 'service' => isset($credentials['service']) ? $credentials['service'] : Utils::get_service(),
197 + 'configSource' => Utils::get_credentials_source(),
198 + 'config' => isset($credentials['config']) ? $credentials['config'] : [],
199 + 'bucketData' => [
200 + 'config' => isset($credentials['bucketConfig']) ? $credentials['bucketConfig'] : [],
201 + ],
202 + ];
203 +
204 + $result = $this->verifyObjectWritePermission($data);
205 +
206 + return $this->persist_connection_status('storageCredentials', $result);
149 207 }
150 208
151 209 /**
210 + * Verify CDN / delivery read access using saved credentials.
211 + * @since 1.3.11
212 + * @return array
213 + */
214 + private function run_cdn_status_check() {
215 + if(!Utils::is_service_enabled()) {
216 + return $this->persist_connection_status('cdnRead', [
217 + 'success' => false,
218 + 'message' => Utils::get_service_configuration_error(),
219 + 'lastChecked' => time(),
220 + ]);
221 + }
222 +
223 + if(!$this->service) {
224 + return $this->persist_connection_status('cdnRead', [
225 + 'success' => false,
226 + 'message' => esc_html__('No service selected', 'media-cloud-sync'),
227 + 'lastChecked' => time(),
228 + ]);
229 + }
230 +
231 + return $this->persist_connection_status('cdnRead', $this->service->verifyObjectReadPermission());
232 + }
233 +
234 + /**
235 + * Run one or more saved-connection status checks.
236 + * @since 1.3.11
237 + * @param string $check storage|cdn|all
238 + * @return array
239 + */
240 + public function verifyStatus($check = 'storage') {
241 + $check = is_string($check) ? strtolower($check) : 'storage';
242 +
243 + if($check === 'write') {
244 + $check = 'storage';
245 + } elseif($check === 'read') {
246 + $check = 'cdn';
247 + }
248 +
249 + if($check === 'all') {
250 + $storage = $this->run_storage_status_check();
251 + $cdn = $this->run_cdn_status_check();
252 +
253 + return [
254 + 'success' => !empty($storage['success']) && !empty($cdn['success']),
255 + 'checks' => [
256 + 'storageCredentials' => $storage,
257 + 'cdnRead' => $cdn,
258 + ],
259 + ];
260 + }
261 +
262 + if($check === 'cdn') {
263 + return $this->run_cdn_status_check();
264 + }
265 +
266 + if($check !== 'storage') {
267 + return [
268 + 'success' => false,
269 + 'message' => esc_html__('Invalid status check type', 'media-cloud-sync'),
270 + ];
271 + }
272 +
273 + return $this->run_storage_status_check();
274 + }
275 +
276 + /**
277 + * @deprecated 1.3.11 Use verifyStatus( 'storage' ).
278 + */
279 + public function verifyWrite() {
280 + return $this->verifyStatus('storage');
281 + }
282 +
283 + /**
284 + * @deprecated 1.3.11 Use verifyStatus( 'cdn' ).
285 + */
286 + public function verifyRead() {
287 + return $this->verifyStatus('cdn');
288 + }
289 +
290 + /**
152 291 * Verify Bucket Exist
153 292 * @since 1.0.0
154 293 */
155 294 public function verifyBucketExist($data) {
@@ -158,10 +297,11 @@
158 297 'message' => esc_html__('Something went wrong', 'media-cloud-sync')
159 298 ];
160 299
161 300 $service = isset($data['service'])? $data['service'] : false;
301 + $handler_class = $this->get_handler_class($service);
162 302
163 - if($service == false) {
303 + if($service == false || $handler_class == false) {
164 304 $result = [
165 305 'success' => false,
166 306 'message' => esc_html__('No service selected', 'media-cloud-sync')
167 307 ];
@@ -167,103 +307,13 @@
167 307 ];
168 308 return $result;
169 309 }
170 310
171 - switch($service){
172 - case 's3':
173 - $result = [
174 - 'success' => false,
175 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
176 - ];
177 - $config = isset($data['config']) ? $data['config'] : [];
178 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
179 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
180 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
181 - $transfer_acceleration = isset($bucketConfig['transfer_acceleration']) ? $bucketConfig['transfer_acceleration'] : false;
182 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
183 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
184 - $region = isset($config['region']) ? $config['region'] : false;
311 + $config = $this->resolve_config($data);
312 + $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
313 + $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
185 314
186 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
187 -
188 - $currentService = new S3;
189 -
190 -
191 - return $currentService->verifyBucketExist($access_key, $secret_key, $region, $bucket, $transfer_acceleration);
192 -
193 - case 'gcloud':
194 - $result = [
195 - 'success' => false,
196 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
197 - ];
198 - $config = isset($data['config']) ? $data['config'] : [];
199 - $config_json = isset($config['config_json']) ? $config['config_json'] : '';
200 -
201 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
202 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
203 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
204 -
205 - if( !(isset($config_json) && !empty($config_json) && $bucket!=false ) ) return $result;
206 -
207 - if(!Utils::is_json($config_json)) {
208 - $result = [
209 - 'success' => false,
210 - 'message' => esc_html__('Invalid config file', 'media-cloud-sync')
211 - ];
212 - return $result;
213 - };
214 -
215 - $currentService = new GCloud;
216 - return $currentService->verifyBucketExist($config_json, $bucket);
217 - break;
218 - case 'docean':
219 - $result = [
220 - 'success' => false,
221 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
222 - ];
223 - $config = isset($data['config']) ? $data['config'] : [];
224 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
225 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
226 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
227 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
228 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
229 - $region = isset($config['region']) ? $config['region'] : false;
230 -
231 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
232 -
233 - $currentService = new DOcean;
234 -
235 -
236 - return $currentService->verifyBucketExist($access_key, $secret_key, $region, $bucket);
237 - break;
238 - case 's3compatible':
239 - $result = [
240 - 'success' => false,
241 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
242 - ];
243 - $config = isset($data['config']) ? $data['config'] : [];
244 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
245 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
246 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
247 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
248 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
249 - $region = isset($config['region']) ? $config['region'] : false;
250 - $endpoint = isset($config['endpoint']) ? $config['endpoint'] : false;
251 -
252 - if( $access_key==false || $secret_key==false || $bucket==false || $endpoint==false ) return $result;
253 -
254 - $currentService = new S3Compatible;
255 -
256 - return $currentService->verifyBucketExist($endpoint, $access_key, $secret_key, $bucket, $region);
257 - break;
258 - default:
259 - $result = [
260 - 'success' => false,
261 - 'message' => esc_html__('Invalid service', 'media-cloud-sync')
262 - ];
263 - }
264 -
265 - return $result;
315 + return $handler_class->verifyBucketExist($config, $bucketConfig);
266 316 }
267 317
268 318 /**
269 319 * Verify Bucket Credentials
@@ -275,10 +325,11 @@
275 325 'message' => esc_html__('Something went wrong', 'media-cloud-sync')
276 326 ];
277 327
278 328 $service = isset($data['service'])? $data['service'] : false;
329 + $handler_class = $this->get_handler_class($service);
279 330
280 - if($service == false) {
331 + if($service == false || $handler_class == false) {
281 332 $result = [
282 333 'success' => false,
283 334 'message' => esc_html__('No service selected', 'media-cloud-sync')
284 335 ];
@@ -283,102 +334,14 @@
283 334 'message' => esc_html__('No service selected', 'media-cloud-sync')
284 335 ];
285 336 return $result;
286 337 }
338 +
339 + $config = $this->resolve_config($data);
340 + $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
341 + $bucketAddNewConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
287 342
288 - switch($service){
289 - case 's3':
290 - $result = [
291 - 'success' => false,
292 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
293 - ];
294 - $config = isset($data['config']) ? $data['config'] : [];
295 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
296 - $bucketAddNewConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
297 - $bucket = isset($bucketAddNewConfig['bucket_name']) ? $bucketAddNewConfig['bucket_name'] : false;
298 - $transfer_acceleration = isset($bucketAddNewConfig['transfer_acceleration']) ? $bucketAddNewConfig['transfer_acceleration'] : false;
299 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
300 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
301 - $region = isset($config['region']) ? $config['region'] : false;
302 -
303 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
304 -
305 - $currentService = new S3;
306 - return $currentService->createBucket($access_key, $secret_key, $region, $bucket, $transfer_acceleration);
307 - case 'gcloud':
308 - $result = [
309 - 'success' => false,
310 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
311 - ];
312 - $config = isset($data['config']) ? $data['config'] : [];
313 - $config_json = isset($config['config_json']) ? $config['config_json'] : '';
314 -
315 - $bucketConfig = isset($data['bucketData']) ? $data['bucketData'] : [];
316 - $bucketAddNewConfig = isset($bucketConfig['addNewConfig']) ? $bucketConfig['addNewConfig'] : [];
317 - $bucket = isset($bucketAddNewConfig['bucket_name']) ? $bucketAddNewConfig['bucket_name'] : false;
318 - $region = isset($bucketAddNewConfig['region']) ? $bucketAddNewConfig['region'] : false;
319 -
320 - if( !(isset($config_json) && !empty($config_json) &&$region!=false && $bucket!=false ) ) return $result;
321 -
322 - if(!Utils::is_json($config_json)) {
323 - $result = [
324 - 'success' => false,
325 - 'message' => esc_html__('Invalid JSON', 'media-cloud-sync')
326 - ];
327 - return $result;
328 - };
329 -
330 - $currentService = new GCloud;
331 - return $currentService->createBucket($config_json, $region, $bucket);
332 - break;
333 - case 'docean':
334 - $result = [
335 - 'success' => false,
336 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
337 - ];
338 -
339 - $config = isset($data['config']) ? $data['config'] : [];
340 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
341 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
342 - $region = isset($config['region']) ? $config['region'] : false;
343 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
344 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
345 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
346 -
347 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
348 -
349 - $currentService = new DOcean;
350 - return $currentService->createBucket($access_key, $secret_key, $region, $bucket);
351 - break;
352 - case 's3compatible':
353 - $result = [
354 - 'success' => false,
355 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
356 - ];
357 -
358 - $config = isset($data['config']) ? $data['config'] : [];
359 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
360 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
361 - $region = isset($config['region']) ? $config['region'] : false;
362 - $endpoint = isset($config['endpoint']) ? $config['endpoint'] : false;
363 -
364 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
365 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
366 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
367 -
368 - if( $access_key==false || $secret_key==false || $bucket==false || $endpoint==false ) return $result;
369 -
370 - $currentService = new S3Compatible;
371 - return $currentService->createBucket($endpoint, $access_key, $secret_key, $bucket, $region);
372 - break;
373 - default:
374 - $result = [
375 - 'success' => false,
376 - 'message' => esc_html__('Invalid service', 'media-cloud-sync')
377 - ];
378 - }
379 -
380 - return $result;
343 + return $handler_class->createBucket( $config, $bucketAddNewConfig );
381 344 }
382 345
383 346 /**
384 347 * Verify Object write permission
@@ -390,10 +353,11 @@
390 353 'message' => esc_html__('Something went wrong', 'media-cloud-sync')
391 354 ];
392 355
393 356 $service = isset($data['service'])? $data['service'] : false;
357 + $handler_class = $this->get_handler_class($service);
394 358
395 - if($service == false) {
359 + if($service == false || $handler_class == false) {
396 360 $result = [
397 361 'success' => false,
398 362 'message' => esc_html__('No service selected', 'media-cloud-sync')
399 363 ];
@@ -399,112 +363,17 @@
399 363 ];
400 364 return $result;
401 365 }
402 366
403 - switch($service){
404 - case 's3':
405 - $result = [
406 - 'success' => false,
407 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
408 - ];
409 - $config = isset($data['config']) ? $data['config'] : [];
410 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
411 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
412 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
413 - } else {
414 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
415 - }
416 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
417 - $transfer_acceleration = isset($bucketConfig['transfer_acceleration']) ? $bucketConfig['transfer_acceleration'] : false;
418 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
419 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
420 - $region = isset($config['region']) ? $config['region'] : false;
421 -
422 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
423 -
424 - $currentService = new S3;
425 - return $currentService->verifyObjectWritePermission($access_key, $secret_key, $region, $bucket, $transfer_acceleration);
426 -
427 - case 'gcloud':
428 - $result = [
429 - 'success' => false,
430 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
431 - ];
432 - $config = isset($data['config']) ? $data['config'] : [];
433 - $config_json = isset($config['config_json']) ? $config['config_json'] : '';
434 -
435 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
436 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
437 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
438 - } else {
439 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
440 - }
441 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
442 -
443 - if( !(isset($config_json) && !empty($config_json) && $bucket!=false ) ) return $result;
444 -
445 - if(!Utils::is_json($config_json)) {
446 - $result = [
447 - 'success' => false,
448 - 'message' => esc_html__('Invalid config json', 'media-cloud-sync')
449 - ];
450 - return $result;
451 - }
452 -
453 - $currentService = new GCloud;
454 - return $currentService->verifyObjectWritePermission($config_json, $bucket);
455 - break;
456 - case 'docean':
457 - $result = [
458 - 'success' => false,
459 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
460 - ];
461 - $config = isset($data['config']) ? $data['config'] : [];
462 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
463 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
464 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
465 - } else {
466 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
467 - }
468 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
469 - $transfer_acceleration = isset($bucketConfig['transfer_acceleration']) ? $bucketConfig['transfer_acceleration'] : false;
470 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
471 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
472 - $region = isset($config['region']) ? $config['region'] : false;
473 -
474 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
475 -
476 - $currentService = new DOcean;
477 - return $currentService->verifyObjectWritePermission($access_key, $secret_key, $region, $bucket);
478 - break;
479 - case 's3compatible':
480 - $result = [
481 - 'success' => false,
482 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
483 - ];
484 - $config = isset($data['config']) ? $data['config'] : [];
485 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
486 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
487 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
488 - } else {
489 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
490 - }
491 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
492 - $transfer_acceleration = isset($bucketConfig['transfer_acceleration']) ? $bucketConfig['transfer_acceleration'] : false;
493 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
494 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
495 - $region = isset($config['region']) ? $config['region'] : false;
496 - $endpoint = isset($config['endpoint']) ? $config['endpoint'] : false;
497 -
498 - if( $access_key==false || $secret_key==false || $endpoint==false || $bucket==false ) return $result;
499 - $currentService = new S3Compatible;
500 - return $currentService->verifyObjectWritePermission($endpoint, $access_key, $secret_key, $bucket, $region);
501 - break;
502 - default:
503 - break;
367 + $config = $this->resolve_config($data);
368 + $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
369 + if(isset($bucketData['addNew']) && $bucketData['addNew']) {
370 + $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
371 + } else {
372 + $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
504 373 }
505 374
506 - return false;
375 + return $handler_class->verifyObjectWritePermission($config, $bucketConfig);
507 376 }
508 377
509 378
510 379 /**
@@ -517,10 +386,11 @@
517 386 'message' => esc_html__('Something went wrong', 'media-cloud-sync')
518 387 ];
519 388
520 389 $service = isset($data['service'])? $data['service'] : false;
390 + $handler_class = $this->get_handler_class($service);
521 391
522 - if($service == false) {
392 + if($service == false || $handler_class == false) {
523 393 $result = [
524 394 'success' => false,
525 395 'message' => esc_html__('No service selected', 'media-cloud-sync')
526 396 ];
@@ -526,122 +396,21 @@
526 396 ];
527 397 return $result;
528 398 }
529 399
530 - switch($service){
531 - case 's3':
532 - $result = [
533 - 'success' => false,
534 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
535 - ];
536 - $config = isset($data['config']) ? $data['config'] : [];
537 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
538 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
539 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
540 - } else {
541 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
542 - }
543 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
544 - $transfer_acceleration = isset($bucketConfig['transfer_acceleration']) ? $bucketConfig['transfer_acceleration'] : false;
545 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
546 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
547 - $region = isset($config['region']) ? $config['region'] : false;
548 -
549 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
550 -
551 - $currentService = new S3;
552 - return $currentService->verifyObjectDeletePermission($access_key, $secret_key, $region, $bucket, $transfer_acceleration);
553 -
554 - case 'gcloud':
555 - $result = [
556 - 'success' => false,
557 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
558 - ];
559 - $config = isset($data['config']) ? $data['config'] : [];
560 - $config_json = isset($config['config_json']) ? $config['config_json'] : '';
561 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
562 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
563 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
564 - } else {
565 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
566 - }
567 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
568 -
569 - if( !(isset($config_json) && !empty($config_json) && $bucket!=false) ) return $result;
570 -
571 - if(!Utils::is_json($config_json)) {
572 - $result = [
573 - 'success' => false,
574 - 'message' => esc_html__('Invalid config json', 'media-cloud-sync')
575 - ];
576 - return $result;
577 - }
578 -
579 - $currentService = new GCloud;
580 - return $currentService->verifyObjectDeletePermission($config_json, $bucket);
581 - break;
582 - case 'docean':
583 - $result = [
584 - 'success' => false,
585 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
586 - ];
587 - $config = isset($data['config']) ? $data['config'] : [];
588 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
589 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
590 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
591 - } else {
592 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
593 - }
594 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
595 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
596 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
597 - $region = isset($config['region']) ? $config['region'] : false;
598 -
599 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
600 -
601 - $currentService = new DOcean;
602 - return $currentService->verifyObjectDeletePermission($access_key, $secret_key, $region, $bucket);
603 - break;
604 - case 's3compatible':
605 - $result = [
606 - 'success' => false,
607 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
608 - ];
609 - $config = isset($data['config']) ? $data['config'] : [];
610 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
611 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
612 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
613 - } else {
614 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
615 - }
616 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
617 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
618 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
619 - $region = isset($config['region']) ? $config['region'] : false;
620 - $endpoint = isset($config['endpoint']) ? $config['endpoint'] : false;
621 -
622 - if( $access_key==false || $secret_key==false || $endpoint==false || $bucket==false ) return $result;
623 -
624 - $currentService = new S3Compatible;
625 - return $currentService->verifyObjectDeletePermission($endpoint, $access_key, $secret_key, $bucket, $region);
626 - break;
627 - default:
628 - break;
400 + $config = $this->resolve_config($data);
401 + $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
402 + if(isset($bucketData['addNew']) && $bucketData['addNew']) {
403 + $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
404 + } else {
405 + $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
629 406 }
630 407
631 - return false;
408 + return $handler_class->verifyObjectDeletePermission( $config, $bucketConfig );
632 409 }
633 410
634 411
635 412 /**
636 - * Verify Object read permission
637 - * @since 1.0.0
638 - */
639 - public function verifyObjectReadPermission($data) {
640 - return $this->service->verifyObjectReadPermission($data);
641 - }
642 -
643 - /**
644 413 * Get Bucket Security Settings
645 414 */
646 415 public function getBucketSecuritySettings($data) {
647 416 $result = [
@@ -649,10 +418,11 @@
649 418 'message' => esc_html__('Something went wrong', 'media-cloud-sync')
650 419 ];
651 420
652 421 $service = isset($data['service'])? $data['service'] : false;
422 + $handler_class = $this->get_handler_class($service);
653 423
654 - if($service == false) {
424 + if($service == false || $handler_class == false) {
655 425 $result = [
656 426 'success' => false,
657 427 'message' => esc_html__('No service selected', 'media-cloud-sync')
658 428 ];
@@ -658,37 +428,25 @@
658 428 ];
659 429 return $result;
660 430 }
661 431
662 - switch($service){
663 - case 's3':
664 - $result = [
665 - 'success' => false,
666 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
667 - ];
668 - $config = isset($data['config']) ? $data['config'] : [];
669 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
670 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
671 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
672 - } else {
673 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
674 - }
675 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
676 - $transfer_acceleration = isset($bucketConfig['transfer_acceleration']) ? $bucketConfig['transfer_acceleration'] : false;
677 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
678 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
679 - $region = isset($config['region']) ? $config['region'] : false;
432 + if(!method_exists($handler_class, 'getBucketSecuritySettings')) {
433 + $result = [
434 + 'success' => false,
435 + 'message' => esc_html__('Service does not have getBucketSecuritySettings method', 'media-cloud-sync')
436 + ];
437 + return $result;
438 + }
680 439
681 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
682 -
683 - $currentService = new S3;
684 - return $currentService->getBucketSecuritySettings($access_key, $secret_key, $region, $bucket, $transfer_acceleration);
685 - break;
686 - default:
687 - break;
440 + $config = $this->resolve_config($data);
441 + $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
442 + if(isset($bucketData['addNew']) && $bucketData['addNew']) {
443 + $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
444 + } else {
445 + $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
688 446 }
689 447
690 - return $result;
448 + return $handler_class->getBucketSecuritySettings( $config, $bucketConfig );
691 449 }
692 450
693 451
694 452 /**
@@ -702,10 +460,11 @@
702 460 'message' => esc_html__('Something went wrong', 'media-cloud-sync')
703 461 ];
704 462
705 463 $service = isset($data['service'])? $data['service'] : false;
464 + $handler_class = $this->get_handler_class($service);
706 465
707 - if($service == false) {
466 + if($service == false || $handler_class == false) {
708 467 $result = [
709 468 'success' => false,
710 469 'message' => esc_html__('No service selected', 'media-cloud-sync')
711 470 ];
@@ -711,39 +470,26 @@
711 470 ];
712 471 return $result;
713 472 }
714 473
715 - switch($service){
716 - case 's3':
717 - $result = [
718 - 'success' => false,
719 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
720 - ];
721 - $config = isset($data['config']) ? $data['config'] : [];
722 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
723 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
724 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
725 - } else {
726 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
727 - }
728 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
729 - $transfer_acceleration = isset($bucketConfig['transfer_acceleration']) ? $bucketConfig['transfer_acceleration'] : false;
730 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
731 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
732 - $region = isset($config['region']) ? $config['region'] : false;
733 - $value = isset($data['value']) ? $data['value'] : false;
474 + if(method_exists($handler_class, 'changePublicAccess') == false) {
475 + $result = [
476 + 'success' => false,
477 + 'message' => esc_html__('Method not supported for this service', 'media-cloud-sync')
478 + ];
479 + return $result;
480 + }
734 481
735 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
736 -
737 - $currentService = new S3;
738 - return $currentService->changePublicAccess($value, $access_key, $secret_key, $region, $bucket, $transfer_acceleration);
739 - break;
740 -
741 - default:
742 - break;
482 + $config = $this->resolve_config($data);
483 + $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
484 + if(isset($bucketData['addNew']) && $bucketData['addNew']) {
485 + $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
486 + } else {
487 + $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
743 488 }
489 + $value = isset($data['value']) ? $data['value'] : false;
744 490
745 - return $result;
491 + return $handler_class->changePublicAccess( $config, $bucketConfig, $value );
746 492 }
747 493
748 494 /**
749 495 * Change bucket ownership
@@ -754,10 +500,11 @@
754 500 'message' => esc_html__('Something went wrong', 'media-cloud-sync')
755 501 ];
756 502
757 503 $service = isset($data['service'])? $data['service'] : false;
504 + $handler_class = $this->get_handler_class($service);
758 505
759 - if($service == false) {
506 + if($service == false || $handler_class == false) {
760 507 $result = [
761 508 'success' => false,
762 509 'message' => esc_html__('No service selected', 'media-cloud-sync')
763 510 ];
@@ -763,48 +510,68 @@
763 510 ];
764 511 return $result;
765 512 }
766 513
767 - switch($service){
768 - case 's3':
769 - $result = [
770 - 'success' => false,
771 - 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
772 - ];
773 - $config = isset($data['config']) ? $data['config'] : [];
774 - $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
775 - if(isset($bucketData['addNew']) && $bucketData['addNew']) {
776 - $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
777 - } else {
778 - $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
779 - }
780 - $bucket = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : false;
781 - $transfer_acceleration = isset($bucketConfig['transfer_acceleration']) ? $bucketConfig['transfer_acceleration'] : false;
782 - $access_key = isset($config['access_key']) ? $config['access_key'] : false;
783 - $secret_key = isset($config['secret_key']) ? $config['secret_key'] : false;
784 - $region = isset($config['region']) ? $config['region'] : false;
785 - $value = isset($data['value']) ? $data['value'] : false;
514 + if(method_exists($handler_class, 'changeObjectOwnership') == false) {
515 + $result = [
516 + 'success' => false,
517 + 'message' => esc_html__('Method not supported for this service', 'media-cloud-sync')
518 + ];
519 + return $result;
520 + }
786 521
787 - if( $access_key==false || $secret_key==false || $region==false || $bucket==false ) return $result;
788 -
789 - $currentService = new S3;
790 - return $currentService->changeObjectOwnership($value, $access_key, $secret_key, $region, $bucket, $transfer_acceleration);
791 - break;
792 -
793 - default:
794 - break;
522 + $config = $this->resolve_config($data);
523 + $bucketData = isset($data['bucketData']) ? $data['bucketData'] : [];
524 + if(isset($bucketData['addNew']) && $bucketData['addNew']) {
525 + $bucketConfig = isset($bucketData['addNewConfig']) ? $bucketData['addNewConfig'] : [];
526 + } else {
527 + $bucketConfig = isset($bucketData['config']) ? $bucketData['config'] : [];
795 528 }
529 + $value = isset($data['value']) ? $data['value'] : false;
796 530
797 - return $result;
531 + return $handler_class->changeObjectOwnership( $config, $bucketConfig, $value );
798 532 }
799 533
534 +
535 + /**
536 + * Generates a URL for a given key in the cloud storage.
537 + *
538 + * @param string $key The key of the object in the cloud storage.
539 + *
540 + * @return string The URL of the object.
541 + */
542 + public function get_url($key) {
543 + if (!$this->service) {
544 + return '';
545 + }
546 + return $this->service->generate_file_url($key);
547 + }
800 548
549 +
801 550 /**
802 - * Get presigned URL
551 + * Checks if a given URL is from a provider.
552 + *
553 + * @param string $url The URL to be checked.
554 + *
555 + * @return bool True if the URL is from a provider, false otherwise.
556 + */
557 + public function is_provider_url($url) {
558 + if (!$this->service) {
559 + return false;
560 + }
561 + return $this->service->is_provider_url($url);
562 + }
563 +
564 +
565 + /**
566 + * Get private URL
803 567 * @since 1.0.0
804 568 */
805 - public function get_presigned_url($path) {
806 - $url_result = $this->service->get_presigned_url($path);
569 + public function get_private_url($path) {
570 + if (!$this->service) {
571 + return false;
572 + }
573 + $url_result = $this->service->get_private_url($path);
807 574 if(isset($url_result['success']) && $url_result['success']) {
808 575 return isset($url_result['file_url']) ? $url_result['file_url'] : false;
809 576 }
810 577 return false;
@@ -810,17 +577,54 @@
810 577 return false;
811 578 }
812 579
813 580
814 - public function uploadSingle($file_path, $source_path, $prefix = '') {
815 - return $this->service->uploadSingle($file_path, $source_path, $prefix);
581 + /**
582 + * Upload a single file to the cloud storage.
583 + *
584 + * @param string $file_path The absolute path to the file on the local server.
585 + * @param string $relative_source_path The relative path to the file on the local server.
586 + * @param string $prefix An optional prefix to add to the cloud storage path.
587 + * @return array The result of the upload operation, including success status and any relevant messages.
588 + */
589 + public function uploadSingle($file_path, $relative_source_path, $prefix = '') {
590 + if (!$this->service) {
591 + return ['success' => false, 'code' => 200, 'message' => esc_html__('No storage service configured', 'media-cloud-sync')];
592 + }
593 + return $this->service->uploadSingle($file_path, $relative_source_path, $prefix);
816 594 }
817 595
818 596
597 + public function deleteSingle($key) {
598 + if (!$this->service) {
599 + return ['success' => false, 'code' => 200, 'message' => esc_html__('No storage service configured', 'media-cloud-sync')];
600 + }
601 + return $this->service->deleteSingle($key);
602 + }
603 +
819 604 /**
605 + * Deletes every version/generation of $key, including delete markers — a plain
606 + * deleteSingle() on a versioned bucket only removes the live copy, leaving older
607 + * versions (and the storage they use) behind. Used where a key is being permanently
608 + * relocated (e.g. moving a folder) and shouldn't leave anything recoverable at the old
609 + * path. Safe to call on a non-versioned bucket too — it's then equivalent to deleteSingle().
610 + * @since 1.3.14
611 + */
612 + public function purge_all_versions($key) {
613 + if (!$this->service || !method_exists($this->service, 'purge_all_versions')) {
614 + return ['success' => false, 'code' => 200, 'message' => esc_html__('No storage service configured', 'media-cloud-sync')];
615 + }
616 + return $this->service->purge_all_versions($key);
617 + }
618 +
619 +
620 + /**
820 621 * Move object to server from cloud
821 622 */
822 623 public function object_to_server($key, $save_path) {
624 + if (!$this->service) {
625 + return false;
626 + }
823 627 $path_parts = pathinfo($save_path);
824 628 if (!file_exists($path_parts['dirname'])) {
825 629 mkdir($path_parts['dirname'], 0755, true);
826 630 }
@@ -827,12 +631,112 @@
827 631 return $this->service->object_to_server($key, $save_path);
828 632 }
829 633
830 634 /**
635 + * Object bytes in memory, no local file — for callers (e.g. zip download) that need
636 + * the content itself rather than a copy on the server's filesystem.
637 + * @since 1.3.13
638 + */
639 + public function get_object_content($key) {
640 + if (!$this->service) {
641 + return false;
642 + }
643 + return $this->service->get_object_content($key);
644 + }
645 +
646 + /**
647 + * Copy an object to a new path in the cloud storage
648 + *
649 + * @param string $key The key of the object to be copied
650 + * @param string $new_path The new path to move the object to
651 + * @return array The result of the copy operation
652 + */
653 + public function copy_to_new_path($key, $new_path) {
654 + if (!$this->service) {
655 + return ['success' => false, 'code' => 200, 'message' => esc_html__('No storage service configured', 'media-cloud-sync')];
656 + }
657 + return $this->service->copy_to_new_path($key, $new_path);
658 + }
659 +
660 + // Cross-bucket server-side copy on the singleton's own (source) connection.
661 + public function copy_to_bucket($key, $new_key, $dest_bucket) {
662 + if (!$this->service || !method_exists($this->service, 'copy_to_bucket')) {
663 + return ['success' => false, 'code' => 200, 'message' => esc_html__('Not supported for this service', 'media-cloud-sync')];
664 + }
665 + return $this->service->copy_to_bucket($key, $new_key, $dest_bucket);
666 + }
667 +
668 + /**
669 + * List objects in the currently configured bucket, one folder level at a time by default.
670 + *
671 + * @param string $prefix The folder path to list within (empty = bucket root).
672 + * @param string|null $continuationToken Provider-issued token for the next page.
673 + * @param int $maxKeys Page size.
674 + * @param string|null $delimiter '/' for folder-level listing, null for flat/recursive.
675 + * @return array {success, code, message, folders, objects, next_token}
676 + */
677 + public function listObjects($prefix = '', $continuationToken = null, $maxKeys = 1000, $delimiter = '/') {
678 + if (!$this->service) {
679 + return ['success' => false, 'code' => 200, 'message' => esc_html__('No storage service configured', 'media-cloud-sync'), 'folders' => [], 'objects' => [], 'next_token' => null];
680 + }
681 + return $this->service->listObjects($prefix, $continuationToken, $maxKeys, $delimiter);
682 + }
683 +
684 + /**
685 + * Get Service Handler
686 + *
687 + * @param string $service
688 + * @param array|null $credentials Optional explicit credentials to bind the handler to,
689 + * instead of the global Utils::get_credentials() default —
690 + * e.g. a migration destination, independent of this
691 + * singleton's own source-bound connection. Not a singleton
692 + * itself — every call constructs a new SDK client; callers
693 + * reusing one connection across many operations should call
694 + * this once and hold onto the returned handler.
695 + */
696 + public function get_handler_class($service, $credentials = null) {
697 + if(isset($this->providers[$service])) {
698 + $provider = $this->providers[$service];
699 + if(!empty($provider['sdk'])) {
700 + self::load_sdk($provider['sdk']);
701 + }
702 + $class = __NAMESPACE__ . '\\' . $provider['class'];
703 + if(class_exists($class)) {
704 + return new $class($credentials);
705 + }
706 + }
707 + return false;
708 + }
709 +
710 + /**
711 + * Lazy load the bundled SDK autoloader for the given service.
712 + * Each SDK is required at most once per request.
713 + *
714 + * @since 1.3.10
715 + */
716 + private static function load_sdk($sdk) {
717 + static $loaded = [];
718 + if (isset($loaded[$sdk])) {
719 + return;
720 + }
721 + if ($sdk === 's3') {
722 + require_once WPMCS_SDK_PATH . 's3/aws-autoloader.php';
723 + } elseif ($sdk === 'google') {
724 + require_once WPMCS_SDK_PATH . 'google/autoload.php';
725 + } else {
726 + return;
727 + }
728 + $loaded[$sdk] = true;
729 + }
730 +
731 + /**
831 732 * Get the service domain
832 733 *
833 734 */
834 735 public function get_domain() {
736 + if (!$this->service) {
737 + return '';
738 + }
835 739 return $this->service->get_domain();
836 740 }
837 741
838 742 /**