PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
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.11, at includes/base/services/gcloud.php

973 lines 37.2 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 return [
490 'message' => $result['message'],
491 'code' => 200,
492 'success' => false,
493 'lastChecked' => $result['lastChecked'],
494 ];
495 }
496
497 try {
498 $object_key = Utils::generate_object_key($this->token . '_dummy-object-for-bucket-permission-check', '');
499
500 // Check if the object was created successfully
501 if (!$this->exists($object_key)) {
502 // Create a dummy object to check write permission
503 $stream = fopen('php://temp', 'r+');
504 fwrite($stream, 'This is a test object to check read permission.');
505 rewind($stream);
506 $this->bucket->upload(
507 $stream,
508 [
509 'name' => $object_key,
510 ]
511 );
512 if (is_resource($stream)) {
513 fclose($stream);
514 }
515 // Re-check if the object was created successfully
516 if (!$this->exists($object_key)) {
517 $result['status'] = false;
518 $result['message'] = esc_html__('Failed to create an object for read permission check, please check service configuration', 'media-cloud-sync');
519 return [
520 'message' => $result['message'],
521 'code' => 200,
522 'success' => false,
523 'lastChecked' => $result['lastChecked'],
524 ];
525 }
526 }
527
528 $url = $this->generate_file_url($object_key);
529 $cdn_url = Cdn::may_generate_cdn_url($url, $object_key);
530
531 $headers = @get_headers($cdn_url);
532 if (strpos($headers[0], '200') !== false) {
533 $result['status'] = true;
534 $result['message'] = esc_html__('Objects are accessible to Read', 'media-cloud-sync');
535 } else if (strpos($headers[0], '403') !== false) {
536 $result['status'] = false;
537 if($this->cdnConfig['service'] == $this->service) {
538 $result['message'] = esc_html__('Access Denied. Please check your bucket policy. Public Read Access is required.', 'media-cloud-sync');
539 } else {
540 $result['message'] = esc_html__('Access Denied. Please check your bucket policy', 'media-cloud-sync');
541 }
542 $result['message'] = esc_html__('Access Denied. Please check your bucket policy', 'media-cloud-sync');
543 } else if (strpos($headers[0], '404') !== false) {
544 $result['status'] = false;
545 $result['message'] = esc_html__('Object not found. Please check your bucket policy', 'media-cloud-sync');
546 } else if (strpos($headers[0], '500') !== false) {
547 $result['status'] = false;
548 $result['message'] = esc_html__('Internal Server error. Please check your bucket policy', 'media-cloud-sync');
549 } else {
550 $result['status'] = false;
551 $result['message'] = esc_html__('Objects are not accessible to read', 'media-cloud-sync');
552 }
553 $this->deleteSingle($object_key);
554 return [
555 'message' => $result['message'],
556 'code' => 200,
557 'success' => $result['status'],
558 'lastChecked' => $result['lastChecked'],
559 ];
560 } catch (ServiceException $ex) {
561 $result['message'] = $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync');
562 return ['message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false, 'lastChecked' => time()];
563 } catch (Exception $ex) {
564 $result['message'] = $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync');
565 return ['message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false, 'lastChecked' => time()];
566 }
567 }
568
569 /**
570 * isConfigured Function To Identify the congfigurations are correct
571 * @since 1.0.0
572 */
573 public function isConfigured(){
574 if ($this->gcloudClient) {
575 try {
576 $bucket = $this->gcloudClient->bucket($this->token . '_dummy-bucket-for-auth-check');
577 $exists = $bucket->exists(); // Triggers the API call
578 return false;
579 } catch (ServiceException $e) {
580 $statusCode = $e->getCode();
581
582 $validErrors = [200, 403, 404];
583
584 if (in_array($statusCode, $validErrors)) {
585 // If we reach here, the credentials are valid
586 return true;
587 } else {
588 // If we reach here, the credentials are not valid
589 return false;
590 }
591 }
592 }
593 return false;
594 }
595
596 /**
597 * Make Object Private
598 * @since 1.0.0
599 *
600 */
601 public function toPrivate($key) {
602 if(!$key) return false;
603
604 try {
605 $object = $this->bucket->object($key);
606 if ($object->exists()) {
607 $object->update(['acl' => []], ['predefinedAcl' => 'private']);
608 return true;
609 }
610 } catch (ServiceException $e) {
611 // Handle exception if needed
612 return false;
613 } catch (Exception $e) {
614 // Handle other exceptions if needed
615 return false;
616 }
617 return false;
618 }
619
620
621 /**
622 * Make Object Public
623 * @since 1.0.0
624 *
625 */
626 public function toPublic($key) {
627 if(!$key) return false;
628
629 try {
630 $object = $this->bucket->object($key);
631 if ($object->exists()) {
632 $object->update(['acl' => []], ['predefinedAcl' => 'publicRead']);
633 return true;
634 }
635 return false;
636 } catch (ServiceException $e) {
637 // Handle exception if needed
638 return false;
639 } catch (Exception $e) {
640 // Handle other exceptions if needed
641 return false;
642 }
643 }
644
645
646 /**
647 * Check the object exist
648 * @since 1.1.8
649 */
650 public function exists($key, $bucket = null) {
651 if(!$key) return false;
652
653 try {
654 $bucket = $bucket ?? $this->bucket;
655 $object = $bucket->object($key);
656 if ($object->exists()) {
657 return true;
658 } else {
659 return false;
660 }
661 } catch (ServiceException $e) {
662 // Handle exception if needed
663 return false;
664 } catch (Exception $e) {
665 // Handle other exceptions if needed
666 return false;
667 }
668
669 return false;
670 }
671
672
673 /**
674 * Upload Single
675 * @since 1.0.0
676 * @return boolean
677 */
678 public function uploadSingle($absolute_source_path, $relative_source_path, $prefix=''){
679 $result = array();
680 if (
681 isset($absolute_source_path) && !empty($absolute_source_path) &&
682 isset($relative_source_path) && !empty($relative_source_path)
683 ) {
684 $file_name = wp_basename( $relative_source_path );
685 if ($file_name) {
686 $upload_path = Utils::generate_object_key($relative_source_path, $prefix);
687
688 // Decide Multipart upload or normal put object
689 if (filesize($absolute_source_path) <= Schema::getConstant('GCLOUD_MULTIPART_MIN_FILE_SIZE')) {
690 // Upload a publicly accessible file. The file size and type are determined by the SDK.
691 try {
692 $handle = fopen($absolute_source_path, 'rb');
693 $upload = $this->bucket->upload(
694 $handle, [ 'name' => $upload_path ]
695 );
696 if (is_resource($handle)) {
697 fclose($handle);
698 }
699
700 if ($upload->exists()) {
701 $result = array(
702 'success' => true,
703 'code' => 200,
704 'file_url' => $this->generate_file_url($upload_path),
705 'key' => $upload_path,
706 'message' => esc_html__('File Uploaded Successfully', 'media-cloud-sync'),
707 );
708 } else {
709 $result = array(
710 'success' => false,
711 'code' => 200,
712 'message' => esc_html__('Object not found at server.', 'media-cloud-sync'),
713 );
714 }
715 } catch (Exception $e) {
716 $result = array(
717 'success' => false,
718 'code' => 200,
719 'message' => $e->getMessage(),
720 );
721 }
722 } else {
723 try {
724 $handle = fopen($absolute_source_path, 'rb');
725 $upload = $this->bucket->upload(
726 $handle,
727 [
728 'name' => $upload_path,
729 'chunkSize' => 262144 * 2,
730 ]
731 );
732 if (is_resource($handle)) {
733 fclose($handle);
734 }
735
736 if ($upload->exists()) {
737 $result = array(
738 'success' => true,
739 'code' => 200,
740 'file_url' => $this->generate_file_url($upload_path),
741 'key' => $upload_path,
742 'message' => esc_html__('File Uploaded Successfully', 'media-cloud-sync'),
743 );
744 } else {
745 $result = array(
746 'success' => false,
747 'code' => 200,
748 'message' => esc_html__('Something happened while uploading to server', 'media-cloud-sync'),
749 );
750 }
751 } catch (Exception $e) {
752 $result = array(
753 'success' => false,
754 'code' => 200,
755 'message' => $e->getMessage(),
756 );
757 }
758 }
759 } else {
760 $result = array(
761 'success' => false,
762 'code' => 200,
763 'message' => esc_html__('Check the file you are trying to upload. Please try again', 'media-cloud-sync'),
764 );
765 }
766 } else {
767 $result = array(
768 'success' => false,
769 'code' => 200,
770 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'),
771 );
772 }
773 return $result;
774 }
775
776
777 /**
778 * Save object to server
779 * @since 1.0.0
780 */
781 public function object_to_server($key, $save_path){
782 try {
783 $object = $this->bucket->object($key);
784 if ($object->exists()) {
785 $object->downloadToFile($save_path);
786 if (file_exists($save_path)) {
787 return true;
788 }
789 }
790 } catch (Exception $e) {
791 return false;
792 }
793 return false;
794 }
795
796
797 /**
798 * Copy an object to a new path in Google Cloud Storage
799 *
800 * @param string $key Original object key (path in bucket)
801 * @param string $new_path Destination object key
802 * @return bool True if object was copied successfully, false otherwise
803 * @since 1.3.4
804 */
805 public function copy_to_new_path($key, $new_path) {
806 try {
807 // Get the source object
808 $sourceObject = $this->bucket->object($key);
809 if (!$sourceObject->exists()) {
810 return [
811 'message' => esc_html__('Original file not found' , 'media-cloud-sync'),
812 'code' => 200,
813 'success' => false
814 ];
815 }
816
817 // Step 1: Copy to new path
818 $destinationObject = $this->bucket->object($new_path);
819 if (!$destinationObject->exists()) {
820 $sourceObject->copy($this->bucket, ['name' => $new_path]);
821 $destinationObject = $this->bucket->object($new_path);
822 }
823
824 // Step 2: Verify new object exists
825 if ($destinationObject->exists()) {
826 return [
827 'success' => true,
828 'code' => 200,
829 'message' => esc_html__('File copied successfully', 'media-cloud-sync')
830 ];
831 }
832 } catch (ServiceException $e) {
833 return [
834 'success' => false,
835 'code' => 200,
836 'message' => $e->getMessage()
837 ];
838 } catch (\Exception $e) {
839 return [
840 'success' => false,
841 'code' => 200,
842 'message' => $e->getMessage()
843 ];
844 }
845 return [
846 'success' => false,
847 'code' => 200,
848 'message' => esc_html__('File not copied', 'media-cloud-sync')
849 ];
850 }
851
852
853 /**
854 * Delete Single
855 * @since 1.0.0
856 * @return boolean
857 */
858 public function deleteSingle($key){
859 $result = array();
860 if (isset($key) && !empty($key)) {
861 try {
862 $object = $this->bucket->object($key);
863 $object->delete();
864
865 if (!$object->exists()) {
866 $result = array(
867 'success' => true,
868 'code' => 200,
869 'message' => esc_html__('Deleted Successfully', 'media-cloud-sync'),
870 );
871 } else {
872 $result = array(
873 'success' => false,
874 'code' => 200,
875 'message' => esc_html__('File not deleted', 'media-cloud-sync'),
876 );
877 }
878 } catch (Exception $e) {
879 $result = array(
880 'success' => false,
881 'code' => 200,
882 'message' => $e->getMessage(),
883 );
884 }
885 } else {
886 $result = array(
887 'success' => false,
888 'code' => 200,
889 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'),
890 );
891 }
892 return $result;
893 }
894
895
896 /**
897 * get private URL
898 * @since 1.0.0
899 * @return boolean
900 */
901 public function get_private_url($key) {
902 $result = array();
903 if (isset($key) && !empty($key)) {
904 try {
905 $object = $this->bucket->object($key);
906
907 $expires = isset($this->settings['private_url_expire']) ? $this->settings['private_url_expire'] : 20;
908
909 $privateUrl = $object->signedUrl(new \DateTime(sprintf('+%s minutes', $expires)));
910
911 if ($privateUrl) {
912 $result = array(
913 'success' => true,
914 'code' => 200,
915 'file_url' => $privateUrl,
916 'message' => esc_html__('Got Private URL Successfully', 'media-cloud-sync'),
917 );
918 } else {
919 $result = array(
920 'success' => false,
921 'code' => 200,
922 'message' => esc_html__('Error getting private URL', 'media-cloud-sync'),
923 );
924 }
925 } catch (Exception $e) {
926 $result = array(
927 'success' => false,
928 'code' => 200,
929 'message' => $e->getMessage(),
930 );
931 }
932 } else {
933 $result = array(
934 'success' => false,
935 'code' => 200,
936 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'),
937 );
938 }
939 return $result;
940 }
941
942
943 /**
944 * Generate file URL
945 */
946 public function generate_file_url($key){
947 $domain = $this->get_domain();
948
949 return apply_filters('wpmcs_generate_google_file_url',
950 $domain . '/' . $this->bucket_name . '/' . $key,
951 $domain, $key,
952 $this->bucket_name
953 );
954 }
955
956 /**
957 * Is provider URL
958 * @since 1.3.6
959 */
960 public function is_provider_url($url) {
961 $domain = $this->get_domain();
962 return (strpos($url, $domain . '/' . $this->bucket_name . '/') !== false);
963 }
964
965 /**
966 * Get domain URL
967 */
968 public function get_domain() {
969 $url_base = 'https://storage.googleapis.com';
970
971 return $url_base;
972 }
973 }