PluginProbe
Media Cloud Sync / 1.0.2
Media Cloud Sync v1.0.2
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 / docean.php

docean.php in Media Cloud Sync 1.0.2, at includes/base/services/docean.php

714 lines 27.6 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\s3\Aws\S3\S3Client;
8 use Dudlewebs\WPMCS\s3\Aws\Exception\AwsException;
9 use Dudlewebs\WPMCS\s3\Aws\S3\Exception\S3Exception;
10 use Dudlewebs\WPMCS\s3\Aws\S3\MultipartUploader;
11 use Dudlewebs\WPMCS\s3\Aws\Exception\MultipartUploadException;
12 use Exception;
13
14 class DOcean {
15 private $assets_url;
16 private $version;
17 private $token;
18
19 protected $config;
20 protected $bucketConfig;
21 protected $settings;
22 protected $credentials;
23 protected $bucket_name;
24
25 public $service = 'docean';
26 public $DOClient = 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
57 if (
58 isset($this->config['region']) && !empty($this->config['region']) &&
59 isset($this->config['access_key']) && !empty($this->config['access_key']) &&
60 isset($this->config['secret_key']) && !empty($this->config['secret_key'])
61 ) {
62 $endpoint = $this->get_domain();
63
64 $this->DOClient = new S3Client([
65 'version' => '2006-03-01',
66 'region' => $this->config['region'],
67 'endpoint' => $endpoint, // DigitalOcean Spaces requires a custom endpoint
68 'use_accelerate_endpoint' => isset($this->bucketConfig['transfer_acceleration'])
69 ? $this->bucketConfig['transfer_acceleration'] : false,
70 'use_path_style_endpoint' => true, // DigitalOcean Spaces often requires path-style endpoints
71 'use_aws_shared_config_files' => false,
72 'credentials' => [
73 'key' => $this->config['access_key'],
74 'secret' => $this->config['secret_key'],
75 ],
76 ]);
77 }
78
79 }
80
81
82 /**
83 * Verify Credentials
84 * @since 1.0.0
85 * @return boolean
86 */
87 public function verifyCredentials($access_key, $secret_key, $region){
88 if (
89 isset($region) && !empty($region) &&
90 isset($access_key) && !empty($access_key) &&
91 isset($secret_key) && !empty($secret_key)
92 ) {
93 try {
94 $endpoint = $this->get_domain($region);
95
96 $DOClient = new S3Client([
97 'version' => '2006-03-01',
98 'region' => $region,
99 'endpoint' => $endpoint,
100 'use_path_style_endpoint' => true, // Required for DigitalOcean Spaces
101 'use_aws_shared_config_files' => false,
102 'credentials' => [
103 'key' => $access_key,
104 'secret' => $secret_key,
105 ],
106 ]);
107
108 //Listing all Digital Ocean Buckets
109 $buckets = $DOClient->listBuckets();
110
111 $newBucketFormat = [];
112 if(isset($buckets['Buckets']) && !empty($buckets['Buckets'])){
113 foreach($buckets['Buckets'] as $bucket) {
114 if(isset($bucket['Name'])) {
115 $newBucketFormat[] = ['Name' => $bucket['Name'], 'CreationDate' => $bucket['CreationDate']];
116 }
117 }
118 }
119
120 return array( 'message' => esc_html__('Credentials are valid', 'media-cloud-sync'), 'buckets' => $newBucketFormat, 'code' => 200, 'success' => true);
121 }
122 catch (S3Exception $ex) {
123 return array('message' => $ex->getAwsErrorMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false);
124 } catch (Exception $ex) {
125 return array('message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false);
126 }
127 }
128 return array('message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'), 'code' => 200, 'success' => false);
129 }
130
131 /**
132 * Verify Bucket
133 * @since 1.0.0
134 * @return boolean
135 */
136 public function verifyBucket($access_key, $secret_key, $region, $bucket_name, $transfer_acceleration=false){
137 if (
138 isset($region) && !empty($region) &&
139 isset($access_key) && !empty($access_key) &&
140 isset($secret_key) && !empty($secret_key) &&
141 isset($bucket_name) && !empty($bucket_name)
142 ) {
143 try {
144 $endpoint = $this->get_domain($region);
145
146 $DOClient = new S3Client([
147 'version' => '2006-03-01',
148 'region' => $region,
149 'endpoint' => $endpoint,
150 'use_path_style_endpoint' => true, // Required for DigitalOcean Spaces
151 'use_accelerate_endpoint' => $transfer_acceleration, // Transfer acceleration for DigitalOcean Spaces
152 'use_aws_shared_config_files' => false,
153 'credentials' => [
154 'key' => $access_key,
155 'secret' => $secret_key,
156 ],
157 ]);
158
159 //Listing all Digital Ocean Buckets
160 $buckets = $DOClient->listBuckets();
161 $bucket_found = false;
162 $region_correct = false;
163 if ($buckets) {
164 foreach ($buckets['Buckets'] as $bucket) {
165 if ($bucket['Name']==$bucket_name) {
166 $bucket_found = true;
167 }
168 }
169 } else {
170 return array('message' => esc_html__('No matching bucket found', 'media-cloud-sync'), 'code' => 200, 'success' => false);
171 }
172 if ($bucket_found) {
173 $upload_dir = wp_upload_dir();
174 $file_dir = $upload_dir['basedir'] . '/' . Schema::getConstant('UPLOADS') . '/';
175
176 if (!is_dir($file_dir)) {
177 do_action( $this->token.'_create_plugin_dir' );
178 }
179
180 $fileName = $this->token."_verify.txt";
181 $localFile = $file_dir.$this->token."-local-verify.txt";
182
183 $verify_file = fopen($file_dir.$fileName, "w");
184 $txt = "We are verifying input/output operations in Digital Ocean\n";
185 fwrite($verify_file, $txt);
186 fclose($verify_file);
187
188 $upload = $DOClient->putObject([
189 'Bucket' => $bucket_name,
190 'Key' => $fileName,
191 'Body' => fopen($file_dir.$fileName, "r"),
192 'ACL' => 'public-read', // make file 'public'
193 ]);
194
195 @unlink($file_dir.$fileName);
196 if ($upload->get('ObjectURL')) {
197 try {
198 $getObject = $DOClient->GetObject([
199 'Bucket' => $bucket_name,
200 'Key' => $fileName,
201 'SaveAs' => $localFile
202 ]);
203
204 if (file_exists($localFile)) {
205 @unlink($localFile);
206 $DOClient->deleteObject([
207 'Bucket' => $bucket_name,
208 'Key' => $fileName,
209 ]);
210
211 if (!$DOClient->doesObjectExist($bucket_name, $fileName)) {
212 return array('message' => esc_html__('Configuration for Digital Ocean has verified successfully', 'media-cloud-sync'), 'code' => 200, 'success' => true);
213 } else {
214 return array('message' => esc_html__('Bucket has permission issues on deleting the object from bucket, Please check ACL permission as well as policies', 'media-cloud-sync'), 'code' => 200, 'success' => false);
215 }
216 } else {
217 return array('message' => esc_html__('Bucket has permission issues on getting the object from bucket, Please check ACL permission as well as policies', 'media-cloud-sync'), 'code' => 200, 'success' => false);
218 }
219 } catch (S3Exception $ex) {
220 return array('message' => $ex->getAwsErrorMessage(), 'code' => $ex->getAwsErrorCode(), 'success' => false);
221 }
222 } else {
223 return array('message' => esc_html__('Bucket has permission issues on putting object in to bucket, Please check ACL permission as well as policies', 'media-cloud-sync'), 'code' => 200, 'success' => false);
224 }
225 } else {
226 return array('message' => esc_html__('Bucket Name is incorrect', 'media-cloud-sync'), 'code' => 200, 'success' => false);
227 }
228 }
229 catch (S3Exception $ex) {
230 return array('message' => $ex->getAwsErrorMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false);
231 } catch (Exception $ex) {
232 return array('message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false);
233 }
234 }
235 return array('message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'), 'code' => 200, 'success' => false);
236 }
237
238 /**
239 * Create Bucket
240 * @since 1.0.0
241 * @return boolean
242 */
243 public function createBucket($access_key, $secret_key, $region, $bucket_name, $transfer_acceleration = false){
244 if (empty($region) || empty($access_key) || empty($secret_key) || empty($bucket_name)) {
245 return ['message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync'), 'code' => 200, 'success' => false];
246 }
247
248 try {
249 $endpoint = $this->get_domain($region);
250
251 $DOClient = new S3Client([
252 'version' => '2006-03-01',
253 'region' => $region,
254 'endpoint' => $endpoint,
255 'use_path_style_endpoint' => true, // Required for DigitalOcean Spaces
256 'use_aws_shared_config_files' => false,
257 'credentials' => [
258 'key' => $access_key,
259 'secret' => $secret_key,
260 ],
261 ]);
262
263 // Create Bucket
264 $DOClient->createBucket(['Bucket' => $bucket_name]);
265 try {
266 $this->enablBucketPublicAccess($bucket_name, $DOClient);
267 $this->putBucketPolicy($bucket_name, $DOClient);
268 $this->changeBucketOwnership($bucket_name, $DOClient);
269 try {
270
271 $this->changeTransferAccilaration($bucket_name, $DOClient, $transfer_acceleration);
272
273 return [
274 'message' => esc_html__('Bucket created successfully. Choose bucket from list to select the bucket.', 'media-cloud-sync'),
275 'data' => [
276 'Name' => $bucket_name,
277 'CreationDate' => date('Y-m-d\TH:i:s\Z'),
278 ],
279 'code' => 200,
280 'success' => true,
281 ];
282 } catch (AwsException $ex) {
283 return ['message' => esc_html__('Bucket created and made public. But the following error happened while setting the transfer accilaration,', 'media-cloud-sync') . ' ' . $ex->getAwsErrorMessage(), 'code' => 200, 'success' => false];
284 }
285 } catch (AwsException $ex) {
286 return ['message' => esc_html__('Bucket created. But the following error happened while setting the public access,', 'media-cloud-sync') . ' ' . $ex->getAwsErrorMessage(), 'code' => 200, 'success' => false];
287 }
288 } catch (AwsException $ex) {
289 return ['message' => $ex->getAwsErrorMessage(), 'code' => 200, 'success' => false];
290 } catch (S3Exception $ex) {
291 return ['message' => $ex->getAwsErrorMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false];
292 } catch (Exception $ex) {
293 return ['message' => $ex->getMessage() ?? esc_html__('Please check the authorization details', 'media-cloud-sync'), 'code' => 200, 'success' => false];
294 }
295 }
296 /**
297 * Make Public Access Block Settings Enable
298 * @since 1.0.0
299 */
300
301 private function enablBucketPublicAccess($bucket, $DOClient = false) {
302 if($DOClient == false) {
303 $DOClient = $this->DOClient;
304 }
305
306 if(empty($bucket)) return false;
307
308 $DOClient->putPublicAccessBlock([
309 'Bucket' => $bucket,
310 'PublicAccessBlockConfiguration' => [
311 'BlockPublicPolicy' => false,
312 'BlockPublicAcls' => false,
313 'IgnorePublicAcls' => false,
314 'RestrictPublicBuckets' => false,
315 ]
316 ]);
317
318 return true;
319 }
320
321 /**
322 * Add Bucket Policy
323 */
324 private function putBucketPolicy($bucket, $DOClient = false) {
325 if($DOClient == false) {
326 $DOClient = $this->DOClient;
327 }
328
329 if(empty($bucket)) return false;
330
331 $policy = '{
332 "Version": "2012-10-17",
333 "Statement": [
334 {
335 "Effect": "Allow",
336 "Principal": "*",
337 "Action": [
338 "s3:DeleteObjectTagging",
339 "s3:ListBucketMultipartUploads",
340 "s3:DeleteObjectVersion",
341 "s3:ListBucket",
342 "s3:DeleteObjectVersionTagging",
343 "s3:GetBucketAcl",
344 "s3:ListMultipartUploadParts",
345 "s3:PutObject",
346 "s3:GetObjectAcl",
347 "s3:GetObject",
348 "s3:AbortMultipartUpload",
349 "s3:DeleteObject",
350 "s3:GetBucketLocation",
351 "s3:PutObjectAcl",
352 "s3:putBucketOwnershipControls",
353 "s3:putBucketPolicy"
354 ],
355 "Resource": [
356 "arn:aws:s3:::' . $bucket . '/*",
357 "arn:aws:s3:::' . $bucket . '"
358 ]
359 }
360 ]
361 }';
362
363 // Add bucket policy
364 $DOClient->putBucketPolicy(['Bucket' => $bucket, 'Policy' => $policy]);
365
366 return true;
367 }
368
369 /**
370 * Add Bucket Ownership
371 */
372 private function changeBucketOwnership($bucket, $DOClient = false, $ownership = 'BucketOwnerPreferred') {
373 if($DOClient == false) {
374 $DOClient = $this->DOClient;
375 }
376
377 if(empty($bucket)) return false;
378
379 // Change object ownership ACL enabled
380 $DOClient->putBucketOwnershipControls([
381 'Bucket' => $bucket,
382 'OwnershipControls' => [
383 'Rules' => [['ObjectOwnership' => $ownership]],
384 ],
385 ]);
386
387 return true;
388 }
389
390 /**
391 * Change transfer accilaration
392 */
393 private function changeTransferAccilaration($bucket, $DOClient = false, $enable=false, $force = false) {
394 if($DOClient == false) {
395 $DOClient = $this->DOClient;
396 }
397
398 if(empty($bucket)) return false;
399 if(!$force && !$enable) return true;
400
401 $DOClient->putBucketAccelerateConfiguration([
402 'Bucket' => $bucket,
403 'AccelerateConfiguration' => [
404 'Status' => $enable ? 'Enabled' : 'Suspended'
405 ]
406 ]);
407
408 return true;
409 }
410
411 /**
412 * isConfigured Function To Identify the congfigurations are correct
413 * @since 1.0.0
414 */
415 public function isConfigured(){
416 if ($this->DOClient) {
417 try {
418 $buckets = $DOClient->listBuckets();
419 if(!empty($buckets)){
420 foreach($buckets as $bucket) {
421 if ($bucket['Name']==$this->bucket_name) {
422 return true;
423 }
424 }
425 }
426 return false;
427 } catch (AwsException $ex) {
428 return false;
429 }
430 }
431 return false;
432 }
433
434 /**
435 * Make Object Private
436 * @since 1.0.0
437 *
438 */
439 public function toPrivate($key) {
440 if(!$key) return false;
441 try {
442 $this->DOClient->putObjectAcl([
443 'Bucket' => $this->bucket_name,
444 'Key' => $key,
445 'ACL' => 'private'
446 ]);
447 return true;
448 } catch (AwsException $ex) {
449 return false;
450 }
451 return false;
452 }
453
454
455
456 /**
457 * Make Object Public
458 * @since 1.0.0
459 *
460 */
461 public function toPublic($key) {
462 if(!$key) return false;
463 try {
464 $this->DOClient->putObjectAcl([
465 'Bucket' => $this->bucket_name,
466 'Key' => $key,
467 'ACL' => 'public-read'
468 ]);
469 return true;
470 } catch (AwsException $ex) {
471 return false;
472 }
473 return false;
474 }
475
476
477
478 /**
479 * Check the object exist
480 * @since 1.1.8
481 */
482 public function exists($key) {
483 if(!$key) return false;
484
485 if($this->DOClient->doesObjectExist($this->bucket_name, $key)) {
486 return true;
487 }
488
489 return false;
490 }
491
492 /**
493 * Upload Single
494 * @since 1.0.0
495 * @return boolean
496 */
497 public function uploadSingle($media_absolute_path, $media_path, $prefix='') {
498 $result = array();
499 if (
500 isset($media_absolute_path) && !empty($media_absolute_path) &&
501 isset($media_path) && !empty($media_path)
502 ) {
503 $file_name = wp_basename( $media_path );
504 if ($file_name) {
505 $upload_path = Utils::generate_object_key($file_name, $prefix);
506
507 // Decide Multipart upload or normal put object
508 if (filesize($media_absolute_path) <= Schema::getConstant('DOCEAN_MULTIPART_MIN_FILE_SIZE')) {
509 // Upload a publicly accessible file. The file size and type are determined by the SDK.
510 try {
511 $upload = $this->DOClient->putObject([
512 'Bucket' => $this->bucket_name,
513 'Key' => $upload_path,
514 'Body' => fopen($media_absolute_path, 'r'),
515 'ACL' => 'public-read', // make file 'public'
516 ]);
517
518 $result = array(
519 'success' => true,
520 'code' => 200,
521 'file_url' => $upload->get('ObjectURL'),
522 'key' => $upload_path,
523 'message' => esc_html__('File Uploaded Successfully', 'media-cloud-sync')
524 );
525 } catch (AwsException $e) {
526 $result = array(
527 'success' => false,
528 'code' => 200,
529 'message' => $e->getMessage()
530 );
531 }
532 } else {
533 $multiUploader = new MultipartUploader($this->DOClient, $media_absolute_path, [
534 'bucket' => $this->bucket_name,
535 'key' => $upload_path,
536 'acl' => 'public-read', // make file 'public'
537 ]);
538
539 try {
540 do {
541 try {
542 $uploaded = $multiUploader->upload();
543 } catch (MultipartUploadException $e) {
544 $multiUploader = new MultipartUploader($this->DOClient, $media_absolute_path, [
545 'state' => $e->getState(),
546 ]);
547 }
548 } while (!isset($uploaded));
549
550 if (isset($uploaded['ObjectURL']) && !empty($uploaded['ObjectURL'])) {
551 $result = array(
552 'success' => true,
553 'code' => 200,
554 'file_url' => urldecode($uploaded['ObjectURL']),
555 'key' => $upload_path,
556 'message' => esc_html__('File Uploaded Successfully', 'media-cloud-sync')
557 );
558 } else {
559 $result = array(
560 'success' => false,
561 'code' => 200,
562 'message' => esc_html__('Something happened while uploading to server', 'media-cloud-sync')
563 );
564 }
565 } catch (MultipartUploadException $e) {
566 $result = array(
567 'success' => false,
568 'code' => 200,
569 'message' => $e->getMessage()
570 );
571 }
572 }
573 } else {
574 $result = array(
575 'success' => false,
576 'code' => 200,
577 'message' => esc_html__('Check the file you are trying to upload. Please try again', 'media-cloud-sync')
578 );
579 }
580 } else {
581 $result = array(
582 'success' => false,
583 'code' => 200,
584 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
585 );
586 }
587 return $result;
588 }
589
590 /**
591 * Save object to server
592 * @since 1.0.0
593 */
594 public function object_to_server($key, $save_path) {
595 try {
596 $getObject = $this->DOClient->GetObject([
597 'Bucket' => $this->bucket_name,
598 'Key' => $key,
599 'SaveAs' => $save_path
600 ]);
601 if (file_exists($save_path)) {
602 return true;
603 }
604 } catch (AwsException $e) {
605 return false;
606 }
607 return false;
608 }
609
610
611 /**
612 * Delete Single
613 * @since 1.0.0
614 * @return boolean
615 */
616 public function deleteSingle($key) {
617 $result = array();
618 if (isset($key) && !empty($key)) {
619 try {
620 $this->DOClient->deleteObject([
621 'Bucket' => $this->bucket_name,
622 'Key' => $key
623 ]);
624
625 if (!$this->DOClient->doesObjectExist($this->bucket_name, $key)) {
626 $result = array(
627 'success' => true,
628 'code' => 200,
629 'message' => esc_html__('Deleted Successfully', 'media-cloud-sync')
630 );
631 } else {
632 $result = array(
633 'success' => false,
634 'code' => 200,
635 'message' => esc_html__('File not deleted', 'media-cloud-sync')
636 );
637 }
638 } catch (AwsException $e) {
639 $result = array(
640 'success' => false,
641 'code' => 200,
642 'message' => $e->getMessage()
643 );
644 }
645 } else {
646 $result = array(
647 'success' => false,
648 'code' => 200,
649 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
650 );
651 }
652 return $result;
653 }
654
655 /**
656 * get presigned URL
657 * @since 1.0.0
658 * @return boolean
659 */
660 public function get_presigned_url($key) {
661 $result = array();
662 if (isset($key) && !empty($key)) {
663 try {
664 $cmd = $this->DOClient->getCommand('GetObject', [
665 'Bucket' => $this->bucket_name,
666 'Key' => $key
667 ]);
668
669 $expires = isset($this->settings['presigned_expire']) ? $this->settings['presigned_expire'] : 20;
670
671 $request = $this->DOClient->createPresignedRequest($cmd, sprintf('+%s minutes', $expires));
672
673 if ($presignedUrl = (string)$request->getUri()) {
674 $result = array(
675 'success' => true,
676 'code' => 200,
677 'file_url' => $presignedUrl,
678 'message' => esc_html__('Got Presigned URL Successfully', 'media-cloud-sync')
679 );
680 } else {
681 $result = array(
682 'success' => false,
683 'code' => 200,
684 'message' => esc_html__('Error getting presigned URL', 'media-cloud-sync')
685 );
686 }
687 } catch (AwsException $e) {
688 $result = array(
689 'success' => false,
690 'code' => 200,
691 'message' => $e->getMessage()
692 );
693 }
694 } else {
695 $result = array(
696 'success' => false,
697 'code' => 200,
698 'message' => esc_html__('Insufficient Data. Please try again', 'media-cloud-sync')
699 );
700 }
701 return $result;
702 }
703
704 /**
705 * Get domain URL
706 */
707 public function get_domain($region = '') {
708 if(empty($region)) {
709 $region = isset($this->config['region']) ? $this->config['region'] : '';
710 }
711 return "https://{$region}.digitaloceanspaces.com";
712 }
713
714 }