PluginProbe
Media Cloud Sync / 1.1.1
Media Cloud Sync v1.1.1
1.4.1 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 All 35 releases
media-cloud-sync / includes / base / services / docean.php

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

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