PluginProbe
Media Cloud Sync / 1.3.10
Media Cloud Sync v1.3.10
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
media-cloud-sync / includes / base / services / gcloud.php

gcloud.php in Media Cloud Sync 1.3.10, at includes/base/services/gcloud.php

978 lines 37.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Dudlewebs\WPMCS;
3
4 defined('ABSPATH') || exit;
5
6 // Libraries
7 use Dudlewebs\WPMCS\GCP\Google\Cloud\Storage\StorageClient;
8 use Dudlewebs\WPMCS\GCP\Google\Cloud\Core\Exception\ServiceException;
9
10 use Exception;
11
12 class GCloud {
13 private $assets_url;
14 private $version;
15 private $token;
16
17 protected $config;
18 protected $bucketConfig;
19 protected $settings;
20 protected $credentials;
21 protected $bucket_name;
22 protected $bucket; // Object
23 protected $cdnConfig;
24
25 public $service = 'gcloud';
26 public $gcloudClient = false;
27
28 /**
29 * Admin constructor.
30 * @since 1.0.0
31 */
32 public function __construct() {
33 $this->assets_url = WPMCS_ASSETS_URL;
34 $this->version = WPMCS_VERSION;
35 $this->token = WPMCS_TOKEN;
36
37 // Initialize setup
38 $this->init();
39 }
40
41 /**
42 * Initialise Client
43 */
44 public function init() {
45 $this->settings = Utils::get_settings();
46 $this->credentials = Utils::get_credentials();
47 $this->config = isset($this->credentials['config']) && !empty($this->credentials['config'])
48 ? $this->credentials['config']
49 : [];
50 $this->bucketConfig = isset($this->credentials['bucketConfig']) && !empty($this->credentials['bucketConfig'])
51 ? $this->credentials['bucketConfig']
52 : [];
53 $this->bucket_name = isset($this->bucketConfig['bucket_name']) && !empty($this->bucketConfig['bucket_name'])
54 ? $this->bucketConfig['bucket_name']
55 : '';
56 $this->cdnConfig = isset($this->credentials['cdn']) && !empty($this->credentials['cdn'])
57 ? $this->credentials['cdn']
58 : [];
59
60 if (
61 isset($this->config['config_json']) && !empty($this->config['config_json']) &&
62 isset($this->bucket_name) && !empty($this->bucket_name)
63 ) {
64 if(Utils::is_json($this->config['config_json'])){
65 // Set google client
66 $keyArray = json_decode($this->config['config_json'], true);
67
68 if (is_array($keyArray)) {
69 $this->gcloudClient = new StorageClient([
70 'keyFile' => $keyArray,
71 ]);
72 $this->bucket = $this->gcloudClient->bucket($this->bucket_name);
73 } else {
74 // Handle JSON decode failure
75 throw new \Exception('Invalid JSON provided for GCloud credentials.');
76 }
77 } else {
78 add_action('admin_notices', function (){
79 echo wp_kses_post(sprintf( "<div class='error'><p><strong>%s: </strong><br>Google Cloud Storage configuration is invalid.
80 It may break the media url's as well as media uploads.<br>
81 <a href='%s'>Re-configure</a> plugin to fix the issue.
82 </p></div>",
83 esc_html__('Media Cloud Sync', 'media-cloud-sync'),
84 admin_url('admin.php?page='.$this->token . '-admin-ui#/configure')
85 ));
86 });
87
88 }
89 }
90 }
91
92 /**
93 * Verify Credentials
94 * @since 1.0.0
95 * @return boolean
96 */
97 public function verifyCredentials( $config = [] ){
98 $config_json = isset($config['config_json']) ? $config['config_json'] : '';
99 if (!empty($config_json)) {
100 if(!Utils::is_json($config_json)){
101 return [
102 'success' => false,
103 'code' => 200,
104 'message' => esc_html__('Invalid JSON configuration, please try again', 'media-cloud-sync'),
105 ];
106 }
107
108 try {
109 $config_array = json_decode($config_json, true);
110 if (is_array($config_array)) {
111 $googleClient = new StorageClient([
112 'keyFile' => $config_array
113 ]);
114 } else {
115 return [
116 'success' => false,
117 'code' => 200,
118 'message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'),
119 ];
120 }
121
122
123
124 try {
125 $bucket = $googleClient->bucket($this->token . '_dummy-bucket-for-auth-check');
126 $exists = $bucket->exists(); // Triggers the API call
127
128 // If we reach here, the credentials are valid
129 $result = [
130 'success' => true,
131 'code' => 200,
132 'message' => esc_html__('Credentials are valid', 'media-cloud-sync'),
133 ];
134 } catch (ServiceException $e) {
135 $statusCode = $e->getCode();
136
137 $validErrors = [200, 403, 404];
138
139 if (in_array($statusCode, $validErrors)) {
140 // If we reach here, the credentials are valid
141 $result = [
142 'success' => true,
143 'code' => 200,
144 'message' => esc_html__('Credentials are valid', 'media-cloud-sync'),
145 ];
146 }
147 }
148
149 if($result['success'] == false) {
150 return $result;
151 }
152
153
154 try {
155 $buckets = $googleClient->buckets();
156 $newBucketFormat = [];
157 if(isset($buckets) && !empty($buckets)){
158 foreach($buckets as $bucket) {
159 $name = $bucket->name();
160 if(!empty($name)) {
161 // Fetch the bucket's metadata
162 $bucketInfo = $bucket->info();
163 $newBucketFormat[] = ['Name' => $name, 'CreationDate' => $bucketInfo['timeCreated']];
164 }
165 }
166 }
167 $result['buckets_data']['buckets'] = $newBucketFormat;
168 $result['buckets_data']['message'] = esc_html__('Buckets listed successfully', 'media-cloud-sync');
169 $result['buckets_data']['status'] = true;
170 } catch (Exception $e) {
171 $result ['buckets_data']['buckets'] = [];
172 $result ['buckets_data']['message'] = esc_html__('Unable to list buckets, Please check the bucket listing permission', 'media-cloud-sync');
173 $result ['buckets_data']['status'] = false;
174 }
175 return $result;
176 } catch (Exception $ex) {
177 return array('message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false);
178 }
179 }
180 return array('message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'), 'code' => 200, 'success' => false);
181 }
182
183
184 /**
185 * Verify Bucket Exists
186 * @since 1.0.0
187 * @return boolean
188 */
189 public function verifyBucketExist( $config = [], $bucketConfig = [] ){
190 $config_json = isset($config['config_json']) ? $config['config_json'] : '';
191 $bucket_name = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : '';
192 if ( empty($config_json) || empty($bucket_name) ) {
193 return ['message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'), 'code' => 200, 'success' => false];
194 }
195
196 if ( !Utils::is_json( $config_json ) ) {
197 return ['message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'), 'code' => 200, 'success' => false];
198 }
199
200 try {
201 $config_array = json_decode($config_json, true);
202 if (is_array($config_array)) {
203 $googleClient = new StorageClient([
204 'keyFile' => $config_array
205 ]);
206 } else {
207 return [
208 'success' => false,
209 'code' => 200,
210 'message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'),
211 ];
212 }
213
214 try {
215 $bucket = $googleClient->bucket($bucket_name);
216
217 if ($bucket->exists()) {
218 return [
219 'message' => esc_html__('Bucket exists', 'media-cloud-sync'),
220 'code' => 200,
221 'success' => true,
222 ];
223 } else {
224 return [
225 'message' => esc_html__('Bucket does not exist', 'media-cloud-sync'),
226 'code' => 200,
227 'success' => false,
228 ];
229 }
230 } catch (ServiceException $e) {
231 return [
232 'message' => esc_html__('Bucket does not exist or credentials are invalid: ', 'media-cloud-sync') . $e->getMessage(),
233 'code' => 200,
234 'success' => false,
235 ];
236 }
237
238
239 if($bucket_found) {
240 return array('message' => esc_html__('Bucket exist', 'media-cloud-sync'), 'code' => 200, 'success' => true);
241 } else {
242 return array('message' => esc_html__("Bucket choosen does not exist / does not have read permission", 'media-cloud-sync'), 'code' => 200, 'success' => false);
243 }
244 } catch (Exception $ex) {
245 return ['message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false];
246 }
247 }
248
249
250 /**
251 * Create Bucket
252 * @since 1.0.0
253 * @return boolean
254 */
255 public function createBucket( $config = [], $bucketConfig = [] ){
256 $config_json = isset($config['config_json']) ? $config['config_json'] : '';
257 $region = isset($bucketConfig['region']) ? $bucketConfig['region'] : '';
258 $bucket_name = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : '';
259 if ( empty($config_json) || empty($region) || empty($bucket_name) ) {
260 return ['message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'), 'code' => 200, 'success' => false];
261 }
262
263 if ( !Utils::is_json( $config_json ) ) {
264 return ['message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'), 'code' => 200, 'success' => false];
265 }
266
267 try {
268 $config_array = json_decode($config_json, true);
269 if (is_array($config_array)) {
270 $googleClient = new StorageClient([
271 'keyFile' => $config_array
272 ]);
273 } else {
274 return [
275 'success' => false,
276 'code' => 200,
277 'message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'),
278 ];
279 }
280
281 // Create Bucket
282 $bucket = $googleClient->createBucket($bucket_name, [
283 'location' => $region,
284 'iamConfiguration' => [
285 'uniformBucketLevelAccess' => [
286 'enabled' => true
287 ]
288 ]
289 ]);
290
291 // Fetch the bucket's IAM
292 try {
293 $iam = $bucket->iam();
294
295 $policy = $iam->policy();
296
297 // Add allUsers as a Storage Object Viewer
298 $policy['bindings'][] = [
299 'role' => 'roles/storage.objectViewer',
300 'members' => ['allUsers'],
301 ];
302
303 // Set the updated policy
304 $iam->setPolicy($policy);
305
306 } catch (ServiceException $e) {
307 return [
308 'message' => esc_html__('Bucket created successfully. But failed to set IAM policy.', 'media-cloud-sync'),
309 'data' => [
310 'Name' => $bucket_name,
311 'CreationDate' => date('Y-m-d\TH:i:s\Z'),
312 ],
313 'code' => 200,
314 'success' => true,
315 ];
316 } catch (Exception $e) {
317 return [
318 'message' => esc_html__('Bucket created successfully. But failed to set IAM policy.', 'media-cloud-sync'),
319 'data' => [
320 'Name' => $bucket_name,
321 'CreationDate' => date('Y-m-d\TH:i:s\Z'),
322 ],
323 'code' => 200,
324 'success' => true,
325 ];
326 }
327
328 return [
329 'message' => esc_html__('Bucket created successfully.', 'media-cloud-sync'),
330 'data' => [
331 'Name' => $bucket_name,
332 'CreationDate' => date('Y-m-d\TH:i:s\Z'),
333 ],
334 'code' => 200,
335 'success' => true,
336 ];
337
338 } catch (Exception $ex) {
339 return ['message' => $e->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false];
340 }
341 }
342
343 /**
344 * Check Bucket Write Permission
345 * @since 1.0.0
346 */
347 public function verifyObjectWritePermission( $config = [], $bucketConfig = [] ) {
348 $config_json = isset($config['config_json']) ? $config['config_json'] : '';
349 $bucket_name = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : '';
350 if ( empty($config_json) || empty($bucket_name) ) {
351 return ['message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'), 'code' => 200, 'success' => false];
352 }
353
354 if ( !Utils::is_json( $config_json ) ) {
355 return ['message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'), 'code' => 200, 'success' => false];
356 }
357
358 try {
359 $config_array = json_decode($config_json, true);
360 if (is_array($config_array)) {
361 $googleClient = new StorageClient([
362 'keyFile' => $config_array
363 ]);
364 } else {
365 return [
366 'success' => false,
367 'code' => 200,
368 'message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'),
369 ];
370 }
371 $bucket = $googleClient->bucket($bucket_name);
372 if ($bucket->exists()) {
373 $bucket_found = true;
374 } else {
375 return ['message' => esc_html__('No Buckets found', 'media-cloud-sync'), 'code' => 200, 'success' => false];
376 }
377 if ($bucket_found) {
378 $object_key = Utils::generate_object_key($this->token . '_dummy-object-for-bucket-permission-check', '');
379
380 // Prepare a temporary file with content to check write permission
381 $stream = fopen('php://temp', 'r+');
382 fwrite($stream, 'This is a test object to check write permission.');
383 rewind($stream);
384
385 // Upload the object to the bucket
386 $object = $bucket->upload(
387 $stream,
388 [
389 'name' => $object_key,
390 ]
391 );
392 if(is_resource($stream)) {
393 fclose($stream);
394 }
395
396 if ($object->exists()) {
397 return ['message' => esc_html__('Bucket write permission verified successfully', 'media-cloud-sync'), 'code' => 200, 'success' => true];
398 } else {
399 return ['message' => esc_html__('Bucket write permission not verified', 'media-cloud-sync'), 'code' => 200, 'success' => false];
400 }
401 }
402 } catch (Exception $ex) {
403 return ['message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false];
404 }
405 }
406
407 /**
408 * Check Bucket Delete Permission
409 * @since 1.0.0
410 */
411 public function verifyObjectDeletePermission( $config = [], $bucketConfig = [] ) {
412 $config_json = isset($config['config_json']) ? $config['config_json'] : '';
413 $bucket_name = isset($bucketConfig['bucket_name']) ? $bucketConfig['bucket_name'] : '';
414
415 if ( empty($config_json) || empty($bucket_name) ) {
416 return ['message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'), 'code' => 200, 'success' => false];
417 }
418 if( !Utils::is_json( $config_json ) ) {
419 return ['message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'), 'code' => 200, 'success' => false];
420 }
421
422 try {
423 $config_array = json_decode($config_json, true);
424 if (is_array($config_array)) {
425 $googleClient = new StorageClient([
426 'keyFile' => $config_array
427 ]);
428 } else {
429 return [
430 'success' => false,
431 'code' => 200,
432 'message' => esc_html__('JSON Configuration is invalid', 'media-cloud-sync'),
433 ];
434 }
435
436 $bucket = $googleClient->bucket($bucket_name);
437 try {
438 $object_key = Utils::generate_object_key($this->token . '_dummy-object-for-bucket-permission-check', '');
439
440 // Try fetching a dummy object to test access
441 $object = $bucket->object($object_key);
442 if ($object->exists()) {
443 $object->delete();
444 if (!$object->exists()) {
445 return [
446 'message' => esc_html__('Bucket exists', 'media-cloud-sync'),
447 'code' => 200,
448 'success' => true,
449 ];
450 } else {
451 return [
452 'message' => esc_html__('You do not have permission to delete object', 'media-cloud-sync'),
453 'code' => 200,
454 'success' => false,
455 ];
456 }
457 } else {
458 return [
459 'message' => esc_html__('Object does not exist', 'media-cloud-sync'),
460 'code' => 200,
461 'success' => false,
462 ];
463 }
464 } catch (Exception $ex) {
465 return [
466 'message' => esc_html__('Object does not exist or credentials are invalid: ', 'media-cloud-sync') . $e->getMessage(),
467 'code' => 200,
468 'success' => false,
469 ];
470 }
471
472 } catch (Exception $ex) {
473 return ['message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false];
474 }
475 }
476
477 /**
478 * Check Bucket Read Permission
479 * @since 1.2.4
480 */
481 public function verifyObjectReadPermission() {
482 $result = [
483 'status' => false,
484 'message' => '',
485 'lastChecked' => time(),
486 ];
487 if (empty($this->gcloudClient) || empty($this->bucket_name)) {
488 $result['message'] = esc_html__('Please check the authorization details', 'media-cloud-sync');
489 Utils::set_status('cdnRead', $result);
490 return [
491 'message' => $result['message'],
492 'code' => 200,
493 'success' => false,
494 'lastChecked' => $result['lastChecked'],
495 ];
496 }
497
498 try {
499 $object_key = Utils::generate_object_key($this->token . '_dummy-object-for-bucket-permission-check', '');
500
501 // Check if the object was created successfully
502 if (!$this->exists($object_key)) {
503 // Create a dummy object to check write permission
504 $stream = fopen('php://temp', 'r+');
505 fwrite($stream, 'This is a test object to check read permission.');
506 rewind($stream);
507 $this->bucket->upload(
508 $stream,
509 [
510 'name' => $object_key,
511 ]
512 );
513 if (is_resource($stream)) {
514 fclose($stream);
515 }
516 // Re-check if the object was created successfully
517 if (!$this->exists($object_key)) {
518 $result['status'] = false;
519 $result['message'] = esc_html__('Failed to create an object for read permission check, please check service configuration', 'media-cloud-sync');
520 Utils::set_status('cdnRead', $result);
521 return [
522 'message' => $result['message'],
523 'code' => 200,
524 'success' => false,
525 'lastChecked' => $result['lastChecked'],
526 ];
527 }
528 }
529
530 $url = $this->generate_file_url($object_key);
531 $cdn_url = Cdn::may_generate_cdn_url($url, $object_key);
532
533 $headers = @get_headers($cdn_url);
534 if (strpos($headers[0], '200') !== false) {
535 $result['status'] = true;
536 $result['message'] = esc_html__('Objects are accessible to Read', 'media-cloud-sync');
537 } else if (strpos($headers[0], '403') !== false) {
538 $result['status'] = false;
539 if($this->cdnConfig['service'] == $this->service) {
540 $result['message'] = esc_html__('Access Denied. Please check your bucket policy. Public Read Access is required.', 'media-cloud-sync');
541 } else {
542 $result['message'] = esc_html__('Access Denied. Please check your bucket policy', 'media-cloud-sync');
543 }
544 $result['message'] = esc_html__('Access Denied. Please check your bucket policy', 'media-cloud-sync');
545 } else if (strpos($headers[0], '404') !== false) {
546 $result['status'] = false;
547 $result['message'] = esc_html__('Object not found. Please check your bucket policy', 'media-cloud-sync');
548 } else if (strpos($headers[0], '500') !== false) {
549 $result['status'] = false;
550 $result['message'] = esc_html__('Internal Server error. Please check your bucket policy', 'media-cloud-sync');
551 } else {
552 $result['status'] = false;
553 $result['message'] = esc_html__('Objects are not accessible to read', 'media-cloud-sync');
554 }
555 Utils::set_status('cdnRead', $result);
556 $this->deleteSingle($object_key);
557 return [
558 'message' => $result['message'],
559 'code' => 200,
560 'success' => $result['status'],
561 'lastChecked' => $result['lastChecked'],
562 ];
563 } catch (ServiceException $ex) {
564 $result['message'] = $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync');
565 Utils::set_status('cdnRead', $result);
566 return ['message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false, 'lastChecked' => time()];
567 } catch (Exception $ex) {
568 $result['message'] = $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync');
569 Utils::set_status('cdnRead', $result);
570 return ['message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false, 'lastChecked' => time()];
571 }
572 }
573
574 /**
575 * isConfigured Function To Identify the congfigurations are correct
576 * @since 1.0.0
577 */
578 public function isConfigured(){
579 if ($this->gcloudClient) {
580 try {
581 $bucket = $this->gcloudClient->bucket($this->token . '_dummy-bucket-for-auth-check');
582 $exists = $bucket->exists(); // Triggers the API call
583 return false;
584 } catch (ServiceException $e) {
585 $statusCode = $e->getCode();
586
587 $validErrors = [200, 403, 404];
588
589 if (in_array($statusCode, $validErrors)) {
590 // If we reach here, the credentials are valid
591 return true;
592 } else {
593 // If we reach here, the credentials are not valid
594 return false;
595 }
596 }
597 }
598 return false;
599 }
600
601 /**
602 * Make Object Private
603 * @since 1.0.0
604 *
605 */
606 public function toPrivate($key) {
607 if(!$key) return false;
608
609 try {
610 $object = $this->bucket->object($key);
611 if ($object->exists()) {
612 $object->update(['acl' => []], ['predefinedAcl' => 'private']);
613 return true;
614 }
615 } catch (ServiceException $e) {
616 // Handle exception if needed
617 return false;
618 } catch (Exception $e) {
619 // Handle other exceptions if needed
620 return false;
621 }
622 return false;
623 }
624
625
626 /**
627 * Make Object Public
628 * @since 1.0.0
629 *
630 */
631 public function toPublic($key) {
632 if(!$key) return false;
633
634 try {
635 $object = $this->bucket->object($key);
636 if ($object->exists()) {
637 $object->update(['acl' => []], ['predefinedAcl' => 'publicRead']);
638 return true;
639 }
640 return false;
641 } catch (ServiceException $e) {
642 // Handle exception if needed
643 return false;
644 } catch (Exception $e) {
645 // Handle other exceptions if needed
646 return false;
647 }
648 }
649
650
651 /**
652 * Check the object exist
653 * @since 1.1.8
654 */
655 public function exists($key, $bucket = null) {
656 if(!$key) return false;
657
658 try {
659 $bucket = $bucket ?? $this->bucket;
660 $object = $bucket->object($key);
661 if ($object->exists()) {
662 return true;
663 } else {
664 return false;
665 }
666 } catch (ServiceException $e) {
667 // Handle exception if needed
668 return false;
669 } catch (Exception $e) {
670 // Handle other exceptions if needed
671 return false;
672 }
673
674 return false;
675 }
676
677
678 /**
679 * Upload Single
680 * @since 1.0.0
681 * @return boolean
682 */
683 public function uploadSingle($absolute_source_path, $relative_source_path, $prefix=''){
684 $result = array();
685 if (
686 isset($absolute_source_path) && !empty($absolute_source_path) &&
687 isset($relative_source_path) && !empty($relative_source_path)
688 ) {
689 $file_name = wp_basename( $relative_source_path );
690 if ($file_name) {
691 $upload_path = Utils::generate_object_key($relative_source_path, $prefix);
692
693 // Decide Multipart upload or normal put object
694 if (filesize($absolute_source_path) <= Schema::getConstant('GCLOUD_MULTIPART_MIN_FILE_SIZE')) {
695 // Upload a publicly accessible file. The file size and type are determined by the SDK.
696 try {
697 $handle = fopen($absolute_source_path, 'rb');
698 $upload = $this->bucket->upload(
699 $handle, [ 'name' => $upload_path ]
700 );
701 if (is_resource($handle)) {
702 fclose($handle);
703 }
704
705 if ($upload->exists()) {
706 $result = array(
707 'success' => true,
708 'code' => 200,
709 'file_url' => $this->generate_file_url($upload_path),
710 'key' => $upload_path,
711 'message' => esc_html__('File Uploaded Successfully', 'media-cloud-sync'),
712 );
713 } else {
714 $result = array(
715 'success' => false,
716 'code' => 200,
717 'message' => esc_html__('Object not found at server.', 'media-cloud-sync'),
718 );
719 }
720 } catch (Exception $e) {
721 $result = array(
722 'success' => false,
723 'code' => 200,
724 'message' => $e->getMessage(),
725 );
726 }
727 } else {
728 try {
729 $handle = fopen($absolute_source_path, 'rb');
730 $upload = $this->bucket->upload(
731 $handle,
732 [
733 'name' => $upload_path,
734 'chunkSize' => 262144 * 2,
735 ]
736 );
737 if (is_resource($handle)) {
738 fclose($handle);
739 }
740
741 if ($upload->exists()) {
742 $result = array(
743 'success' => true,
744 'code' => 200,
745 'file_url' => $this->generate_file_url($upload_path),
746 'key' => $upload_path,
747 'message' => esc_html__('File Uploaded Successfully', 'media-cloud-sync'),
748 );
749 } else {
750 $result = array(
751 'success' => false,
752 'code' => 200,
753 'message' => esc_html__('Something happened while uploading to server', 'media-cloud-sync'),
754 );
755 }
756 } catch (Exception $e) {
757 $result = array(
758 'success' => false,
759 'code' => 200,
760 'message' => $e->getMessage(),
761 );
762 }
763 }
764 } else {
765 $result = array(
766 'success' => false,
767 'code' => 200,
768 'message' => esc_html__('Check the file you are trying to upload. Please try again', 'media-cloud-sync'),
769 );
770 }
771 } else {
772 $result = array(
773 'success' => false,
774 'code' => 200,
775 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'),
776 );
777 }
778 return $result;
779 }
780
781
782 /**
783 * Save object to server
784 * @since 1.0.0
785 */
786 public function object_to_server($key, $save_path){
787 try {
788 $object = $this->bucket->object($key);
789 if ($object->exists()) {
790 $object->downloadToFile($save_path);
791 if (file_exists($save_path)) {
792 return true;
793 }
794 }
795 } catch (Exception $e) {
796 return false;
797 }
798 return false;
799 }
800
801
802 /**
803 * Copy an object to a new path in Google Cloud Storage
804 *
805 * @param string $key Original object key (path in bucket)
806 * @param string $new_path Destination object key
807 * @return bool True if object was copied successfully, false otherwise
808 * @since 1.3.4
809 */
810 public function copy_to_new_path($key, $new_path) {
811 try {
812 // Get the source object
813 $sourceObject = $this->bucket->object($key);
814 if (!$sourceObject->exists()) {
815 return [
816 'message' => esc_html__('Original file not found' , 'media-cloud-sync'),
817 'code' => 200,
818 'success' => false
819 ];
820 }
821
822 // Step 1: Copy to new path
823 $destinationObject = $this->bucket->object($new_path);
824 if (!$destinationObject->exists()) {
825 $sourceObject->copy($this->bucket, ['name' => $new_path]);
826 $destinationObject = $this->bucket->object($new_path);
827 }
828
829 // Step 2: Verify new object exists
830 if ($destinationObject->exists()) {
831 return [
832 'success' => true,
833 'code' => 200,
834 'message' => esc_html__('File copied successfully', 'media-cloud-sync')
835 ];
836 }
837 } catch (ServiceException $e) {
838 return [
839 'success' => false,
840 'code' => 200,
841 'message' => $e->getMessage()
842 ];
843 } catch (\Exception $e) {
844 return [
845 'success' => false,
846 'code' => 200,
847 'message' => $e->getMessage()
848 ];
849 }
850 return [
851 'success' => false,
852 'code' => 200,
853 'message' => esc_html__('File not copied', 'media-cloud-sync')
854 ];
855 }
856
857
858 /**
859 * Delete Single
860 * @since 1.0.0
861 * @return boolean
862 */
863 public function deleteSingle($key){
864 $result = array();
865 if (isset($key) && !empty($key)) {
866 try {
867 $object = $this->bucket->object($key);
868 $object->delete();
869
870 if (!$object->exists()) {
871 $result = array(
872 'success' => true,
873 'code' => 200,
874 'message' => esc_html__('Deleted Successfully', 'media-cloud-sync'),
875 );
876 } else {
877 $result = array(
878 'success' => false,
879 'code' => 200,
880 'message' => esc_html__('File not deleted', 'media-cloud-sync'),
881 );
882 }
883 } catch (Exception $e) {
884 $result = array(
885 'success' => false,
886 'code' => 200,
887 'message' => $e->getMessage(),
888 );
889 }
890 } else {
891 $result = array(
892 'success' => false,
893 'code' => 200,
894 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'),
895 );
896 }
897 return $result;
898 }
899
900
901 /**
902 * get private URL
903 * @since 1.0.0
904 * @return boolean
905 */
906 public function get_private_url($key) {
907 $result = array();
908 if (isset($key) && !empty($key)) {
909 try {
910 $object = $this->bucket->object($key);
911
912 $expires = isset($this->settings['private_url_expire']) ? $this->settings['private_url_expire'] : 20;
913
914 $privateUrl = $object->signedUrl(new \DateTime(sprintf('+%s minutes', $expires)));
915
916 if ($privateUrl) {
917 $result = array(
918 'success' => true,
919 'code' => 200,
920 'file_url' => $privateUrl,
921 'message' => esc_html__('Got Private URL Successfully', 'media-cloud-sync'),
922 );
923 } else {
924 $result = array(
925 'success' => false,
926 'code' => 200,
927 'message' => esc_html__('Error getting private URL', 'media-cloud-sync'),
928 );
929 }
930 } catch (Exception $e) {
931 $result = array(
932 'success' => false,
933 'code' => 200,
934 'message' => $e->getMessage(),
935 );
936 }
937 } else {
938 $result = array(
939 'success' => false,
940 'code' => 200,
941 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'),
942 );
943 }
944 return $result;
945 }
946
947
948 /**
949 * Generate file URL
950 */
951 public function generate_file_url($key){
952 $domain = $this->get_domain();
953
954 return apply_filters('wpmcs_generate_google_file_url',
955 $domain . '/' . $this->bucket_name . '/' . $key,
956 $domain, $key,
957 $this->bucket_name
958 );
959 }
960
961 /**
962 * Is provider URL
963 * @since 1.3.6
964 */
965 public function is_provider_url($url) {
966 $domain = $this->get_domain();
967 return (strpos($url, $domain . '/' . $this->bucket_name . '/') !== false);
968 }
969
970 /**
971 * Get domain URL
972 */
973 public function get_domain() {
974 $url_base = 'https://storage.googleapis.com';
975
976 return $url_base;
977 }
978 }