PluginProbe
Media Cloud Sync / 1.4.2
Media Cloud Sync v1.4.2
1.4.2 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 All 36 releases
media-cloud-sync / includes / base / services / service.php

service.php in Media Cloud Sync 1.4.2, at includes/base/services/service.php

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