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 / api.php

api.php in Media Cloud Sync 1.3.11, at includes/api.php

582 lines 16.7 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 use WP_REST_Response;
5
6 defined('ABSPATH') || exit;
7
8 class Api {
9 private static $instance = null;
10 private $token;
11 private $version;
12 private $assets_url;
13
14 /**
15 * Constructor
16 * @since 1.0.0
17 */
18
19 public function __construct() {
20 $this->assets_url = WPMCS_ASSETS_URL;
21 $this->version = WPMCS_VERSION;
22 $this->token = WPMCS_TOKEN;
23
24 add_action( 'rest_api_init', array( $this, 'register_routes' ) );
25 }
26
27
28 /**
29 * Register API routes
30 */
31
32 public function register_routes() {
33 $this->add_route( '/verifyCredentials', 'verifyCredentials', 'POST' );
34 $this->add_route( '/bucket/checkExist', 'verifyBucketExist', 'POST' );
35 $this->add_route( '/bucket/addNew', 'createBucket', 'POST' );
36 $this->add_route( '/permissions/status', 'verifyStatus', 'POST' );
37 $this->add_route( '/permissions/write', 'verifyWrite', 'POST' );
38 $this->add_route( '/permissions/delete', 'verifyObjectDelete', 'POST' );
39 $this->add_route( '/permissions/read', 'verifyRead', 'POST' );
40
41 $this->add_route( '/security/get_security', 'getBucketSecuritySettings', 'POST' );
42 $this->add_route( '/security/block_public_access', 'changePublicAccess', 'POST' );
43 $this->add_route( '/security/object_ownership_enforce', 'changeObjectOwnership', 'POST' );
44
45 $this->add_route( '/getSettings', 'getSettings' );
46 $this->add_route( '/saveConfig', 'saveConfig', 'POST' );
47 $this->add_route( '/refreshCounts', 'refreshCounts', 'POST' );
48 $this->add_route( '/getErrorLogs', 'getErrorLogs', 'POST' );
49
50 // Upgrade Database Routes
51 $this->add_route( '/upgrade/status', 'getUpgradeStatus' );
52 $this->add_route( '/upgrade/start', 'startUpgrade', 'POST' );
53
54 // Sync Routes
55 $this->add_route( '/sync/status', 'getStatus' );
56 $this->add_route( '/sync/start', 'startSync', 'POST' );
57 $this->add_route( '/sync/pause', 'pauseSync', 'POST' );
58 $this->add_route( '/sync/resume', 'resumeSync', 'POST' );
59 $this->add_route( '/sync/stop', 'stopSync', 'POST' );
60
61 $this->add_route( '/sync/retrySingle', 'retrySingle', 'POST' );
62 }
63
64 /**
65 * Verify the Service Credentials
66 */
67 public function verifyCredentials( $data ) {
68 return new WP_REST_Response( Service::instance()->verifyCredentials($data->get_params()), 200 );
69 }
70
71 /**
72 * Verify the Bucket exist
73 */
74 public function verifyBucketExist( $data ) {
75 return new WP_REST_Response( Service::instance()->verifyBucketExist($data->get_params()), 200 );
76 }
77
78 /**
79 * Create the bucket
80 */
81 public function createBucket( $data ) {
82 return new WP_REST_Response( Service::instance()->createBucket($data->get_params()), 200 );
83 }
84
85 /**
86 * Saved connection status checks (storage, CDN).
87 * @since 1.3.11
88 */
89 public function verifyStatus( $data ) {
90 $params = $data->get_params();
91 $check = isset( $params['check'] ) ? sanitize_text_field( $params['check'] ) : 'storage';
92 return new WP_REST_Response( Service::instance()->verifyStatus( $check ), 200 );
93 }
94
95 /**
96 * Verify bucket write permission (configure wizard) or saved storage status (legacy route).
97 * @since 1.3.11
98 */
99 public function verifyWrite( $data ) {
100 $params = $data->get_params();
101 if ( !empty( $params['service'] ) ) {
102 return new WP_REST_Response( Service::instance()->verifyObjectWritePermission( $params ), 200 );
103 }
104 return new WP_REST_Response( Service::instance()->verifyStatus( 'storage' ), 200 );
105 }
106
107 /**
108 * Verify the Bucket delete Permission
109 */
110 public function verifyObjectDelete( $data ) {
111 return new WP_REST_Response( Service::instance()->verifyObjectDeletePermission($data->get_params()), 200 );
112 }
113
114 /**
115 * Verify delivery read access (legacy route).
116 * @since 1.3.11
117 */
118 public function verifyRead( $data ) {
119 return new WP_REST_Response( Service::instance()->verifyStatus( 'cdn' ), 200 );
120 }
121
122 /**
123 * Get the Security Settings
124 */
125 public function getBucketSecuritySettings( $data ) {
126 return new WP_REST_Response( Service::instance()->getBucketSecuritySettings($data->get_params()), 200 );
127 }
128
129
130 /**
131 * Change the Public Access
132 */
133 public function changePublicAccess( $data ) {
134 return new WP_REST_Response( Service::instance()->changePublicAccess($data->get_params()), 200 );
135 }
136
137
138 /**
139 * Change the Object Ownership
140 */
141 public function changeObjectOwnership( $data ) {
142 return new WP_REST_Response( Service::instance()->changeObjectOwnership($data->get_params()), 200 );
143 }
144
145 /**
146 * Get Settings
147 */
148 public function getSettings( ) {
149 // Fetch and update media counts for make sure they are up to date
150 Counter::fetch_and_update();
151
152 $data = [
153 'credentials' => Utils::get_credentials( '', [], true ),
154 'serviceEnabled' => Utils::is_service_enabled(),
155 'serviceError' => Utils::get_service_configuration_error(),
156 'common' => [
157 'version' => defined('WPMCS_PRO_VERSION') ? WPMCS_PRO_VERSION : WPMCS_VERSION,
158 'counts' => [
159 'all' => Counter::get_count(),
160 'categorized' => $this->getSortedMediaCounts()
161 ],
162 'status' => Utils::get_status('', false),
163 'settings' => Utils::get_settings(),
164 ],
165 'sync' => Sync::instance()->get_status(),
166 'license' => defined('WPMCS_PRO_VERSION') ? Utils::get_safe_license_data() : [],
167 ];
168
169 return new WP_REST_Response( $data, 200 );
170 }
171
172 /**
173 * Save the Configurations
174 */
175 public function saveConfig( $data ) {
176 $saveData = $data->get_params();
177 $result = [
178 'success' => false,
179 'message' => esc_html__('Something went wrong. Invalid data recieved', 'media-cloud-sync')
180 ];
181
182 $action = isset($saveData['action']) ? $saveData['action'] : false;
183 if($action === false) return new WP_REST_Response( $result, 200 );
184
185 $service = isset($saveData['service']) ? $saveData['service'] : false;
186 $serviceLabel = isset($saveData['serviceLabel']) ? $saveData['serviceLabel'] : '';
187 $cdn = isset($saveData['cdn']) ? $saveData['cdn'] : [];
188 $config = isset($saveData['config']) ? $saveData['config'] : false;
189 $configSource = isset($saveData['configSource']) ? $saveData['configSource'] : 'database';
190 $bucketConfig = isset($saveData['bucketConfig']) ? $saveData['bucketConfig'] : [];
191 $security = isset($saveData['security']) ? $saveData['security'] : [];
192 $settings = isset($saveData['settings']) ? $saveData['settings'] : [];
193
194 $serviceOk = true;
195 $settingsOk = true;
196
197 if( $action === 'cdn' ){
198 $existing = Utils::get_credentials();
199 $existing['cdn'] = $cdn;
200
201 $updated = Utils::update_option('credentials', $existing, Schema::getConstant('GLOBAL_SETTINGS_KEY'));
202 $updatedSettings = Utils::update_option('settings', $settings, Schema::getConstant('GLOBAL_SETTINGS_KEY'));
203
204 if(!$updated) $serviceOk = false;
205 }
206
207
208 if($action === 'all' || $action === 'service'){
209 // In 'config' source mode the credentials live in the WPMCS_CONFIG constant,
210 // so an empty config payload is expected and must not block the save.
211 if ( $service === false || ($configSource !== 'config' && empty($config)) || empty($bucketConfig)) return new WP_REST_Response( $result, 200 );
212
213 $updated = Utils::update_option(
214 'credentials',
215 [
216 'service' => $service,
217 'serviceLabel' => $serviceLabel,
218 'cdn' => $cdn,
219 'config' => $configSource === 'config' ? [] : $config,
220 'configSource' => $configSource,
221 'bucketConfig' => $bucketConfig,
222 'security' => $security
223 ],
224 Schema::getConstant('GLOBAL_SETTINGS_KEY')
225 );
226 if(!$updated) $serviceOk = false;
227
228 if($serviceOk) {
229 Utils::set_status('cdnRead', [
230 'status' => false,
231 'message' => '',
232 'lastChecked' => null
233 ]);
234 Utils::set_status('storageCredentials', [
235 'status' => false,
236 'message' => '',
237 'lastChecked' => null
238 ]);
239 }
240 }
241
242 if(($action === 'all' || $action === 'settings')) {
243 $updatedSettings = Utils::update_option('settings', $settings, Schema::getConstant('GLOBAL_SETTINGS_KEY'));
244 if(!$updatedSettings) $settingsOk = false;
245 }
246
247 // Clear plugin caches and refresh counts after any configuration save.
248 if(in_array($action, ['all', 'service', 'settings', 'cdn'], true)) {
249 if($action === 'all' || $action === 'service' || $action === 'settings') {
250 Integration::instance()->clear_all_meta(false);
251 }
252
253 if($action === 'all' || $action === 'settings') {
254 Utils::clear_all_content_meta(false, false);
255 }
256
257 Cache::flush_object_cache();
258 Counter::instance()->fetch_and_update();
259 }
260
261
262 if($serviceOk && $settingsOk) {
263 $result = [
264 'success' => true,
265 'message' => esc_html__('Configuration saved successfully', 'media-cloud-sync')
266 ];
267 }
268
269 return new WP_REST_Response( $result, 200 );
270 }
271
272
273 /**
274 * Refresh the Media Counts
275 *
276 */
277 public function refreshCounts( ) {
278 Cache::flush_object_cache();
279 Integration::instance()->clear_all_meta();
280 Counter::instance()->fetch_and_update();
281
282 $result = [
283 'success' => true,
284 'counts' => [
285 'all' => Counter::get_count(),
286 'categorized' => $this->getSortedMediaCounts()
287 ],
288 'message' => esc_html__('Media counts refreshed successfully', 'media-cloud-sync')
289 ];
290 return new WP_REST_Response( $result, 200 );
291 }
292
293
294 /**
295 * Start Upgrade
296 * @since 1.3.6
297 */
298 public function startUpgrade( $request ) {
299 $result = Upgrade::instance()->start_upgrade();
300 return new WP_REST_Response( $result, 200 );
301 }
302
303
304 /**
305 * Get Upgrade Status
306 * @since 1.3.6
307 */ public function getUpgradeStatus( $request ) {
308 $result = Upgrade::instance()->get_progress();
309 return new WP_REST_Response( $result, 200 );
310 }
311
312
313 /**
314 * Get Media Error Logs
315 * @since 1.2.13
316 */
317 public function getErrorLogs( $request ) {
318 $params = $request->get_params();
319 $type = isset($params['type']) ? $params['type'] : 'all';
320 $page = isset($params['page']) ? $params['page'] : null;
321 $per_page = isset($params['per_page']) ? $params['per_page'] : null;
322
323 if($type !== 'all') {
324 $logs = Logger::instance()->get_logs_by_type($type, $page, $per_page);
325 } else {
326 $logs = Logger::instance()->get_all_logs($page, $per_page);
327 }
328
329 $result = [
330 'success' => true,
331 'logs' => $logs,
332 'message' => esc_html__('Error logs fetched successfully', 'media-cloud-sync')
333 ];
334 return new WP_REST_Response( $result, 200 );
335 }
336
337
338 /**
339 * Get Status
340 * @since 1.2.13
341 */
342 public function getStatus( $request ) {
343 // Fetch and update media counts for make sure they are up to date
344 $action = isset($request->get_params()['action']) ? $request->get_params()['action'] : 'all';
345 $status = Sync::instance()->get_status();
346
347 if($action !== 'all') {
348 $status = isset($status[$action]) ? $status[$action] : [];
349 }
350
351 $result = [
352 'success' => true,
353 'status' => $status,
354 'counts' => [
355 'all' => Counter::get_count(),
356 'categorized' => $this->getSortedMediaCounts()
357 ],
358 'message' => esc_html__('Status fetched successfully', 'media-cloud-sync')
359 ];
360
361 return new WP_REST_Response( $result, 200 );
362 }
363
364
365 /**
366 * Start Sync
367 * @since 1.2.13
368 */
369 public function startSync( $data ) {
370 $action = isset($data->get_params()['action']) ? $data->get_params()['action'] : '';
371 if(empty($action)) {
372 $result = [
373 'success' => false,
374 'message' => esc_html__('Invalid action', 'media-cloud-sync')
375 ];
376 return new WP_REST_Response( $result, 200 );
377 }
378 if(!Utils::is_service_enabled()) {
379 $result = [
380 'success' => false,
381 'message' => Utils::get_service_configuration_error() ?: esc_html__('Storage is not configured correctly.', 'media-cloud-sync')
382 ];
383 return new WP_REST_Response( $result, 200 );
384 }
385 $status = Sync::instance()->start($action);
386
387 $result = [
388 'success' => true,
389 'status' => $status,
390 'message' => esc_html__('Sync started successfully', 'media-cloud-sync')
391 ];
392 return new WP_REST_Response( $result, 200 );
393 }
394
395
396 /**
397 * Pause Sync
398 * @since 1.2.13
399 */
400 public function pauseSync( $data ) {
401 $action = isset($data->get_params()['action']) ? $data->get_params()['action'] : '';
402 if(empty($action)) {
403 $result = [
404 'success' => false,
405 'message' => esc_html__('Invalid action', 'media-cloud-sync')
406 ];
407 return new WP_REST_Response( $result, 200 );
408 }
409 $status = Sync::instance()->pause($action);
410
411 $result = [
412 'success' => true,
413 'status' => $status,
414 'message' => esc_html__('Sync paused successfully', 'media-cloud-sync')
415 ];
416 return new WP_REST_Response( $result, 200 );
417 }
418
419
420 /**
421 * Resume Sync
422 * @since 1.2.13
423 */
424 public function resumeSync( $data ) {
425 $action = isset($data->get_params()['action']) ? $data->get_params()['action'] : '';
426 if(empty($action)) {
427 $result = [
428 'success' => false,
429 'message' => esc_html__('Invalid action', 'media-cloud-sync')
430 ];
431 return new WP_REST_Response( $result, 200 );
432 }
433 $status = Sync::instance()->resume($action);
434
435 $result = [
436 'success' => true,
437 'status' => $status,
438 'message' => esc_html__('Sync resumed successfully', 'media-cloud-sync')
439 ];
440 return new WP_REST_Response( $result, 200 );
441 }
442
443
444 /**
445 * Stop Sync
446 * @since 1.2.13
447 */
448 public function stopSync( $data ) {
449 $action = isset($data->get_params()['action']) ? $data->get_params()['action'] : '';
450 if(empty($action)) {
451 $result = [
452 'success' => false,
453 'message' => esc_html__('Invalid action', 'media-cloud-sync')
454 ];
455 return new WP_REST_Response( $result, 200 );
456 }
457 $status = Sync::instance()->stop($action);
458
459 $result = [
460 'success' => true,
461 'status' => $status,
462 'counts' => [
463 'all' => Counter::get_count(),
464 'categorized' => $this->getSortedMediaCounts()
465 ],
466 'message' => esc_html__('Sync stopped successfully', 'media-cloud-sync')
467 ];
468 return new WP_REST_Response( $result, 200 );
469 }
470
471
472 /**
473 * Retry a Media Sync Error
474 */
475 public function retrySingle( $data ) {
476 $params = $data->get_params();
477 $id = isset($params['id']) ? $params['id'] : '';
478 $source_type = isset($params['source_type']) ? $params['source_type'] : 'media_library';
479 $type = isset($params['type']) ? $params['type'] : '';
480 $status = false;
481 if(empty($id) || empty($source_type) || empty($type)) {
482 $result = [
483 'success' => false,
484 'message' => esc_html__('Invalid parameters', 'media-cloud-sync')
485 ];
486 return new WP_REST_Response( $result, 200 );
487 }
488 // Retry Sync
489 $handler = Sync::instance()->get_class_by_action($type);
490 if($handler) {
491 $handler->retry_single($id, $source_type);
492 }
493
494 $status = Utils::is_empty(Logger::instance()->get_log($type, $id, $source_type)) ? true : false;
495
496 $result = [
497 'success' => $status,
498 'message' => $status ? esc_html__('Media synced successfully', 'media-cloud-sync') : esc_html__('Media sync failed', 'media-cloud-sync')
499 ];
500 return new WP_REST_Response( $result, 200 );
501 }
502
503
504 /**
505 * Get Sorted Media Counts
506 * Sorts media counts by source type
507 * @since 1.2.13
508 */
509 private function getSortedMediaCounts() {
510 $sorted_counts = [];
511 $detailed_counts = Counter::get_count( 'all', false );
512 if(!empty($detailed_counts)) {
513 $source_labels = Integration::$source_labels;
514 if(!empty($source_labels)) {
515 $prefixes = array_keys($source_labels);
516 foreach($detailed_counts as $source_type => $counts) {
517 $found_prefix = false;
518 foreach($prefixes as $prefix) {
519 $found_prefix = strpos($source_type, $prefix) === 0 ? $prefix : false;;
520 if($found_prefix !== false) break;
521 }
522
523 if($found_prefix !== false) {
524 $sorted_counts[$found_prefix] = [
525 'label' => $source_labels[$found_prefix],
526 'uploaded' => isset($sorted_counts[$found_prefix]['data']['uploaded'])
527 ? $sorted_counts[$found_prefix]['data']['uploaded'] + $counts['uploaded']
528 : $counts['uploaded'],
529 'total' => isset($sorted_counts[$found_prefix]['data']['total'])
530 ? $sorted_counts[$found_prefix]['data']['total'] + $counts['total']
531 : $counts['total']
532 ];
533 }
534 }
535 }
536 }
537
538 return $sorted_counts;
539 }
540
541
542 /**
543 * Helper function to create Adding Route
544 * @since 1.0.0
545 */
546 private function add_route( $slug, $callBack, $method = 'GET' ) {
547 register_rest_route(
548 $this->token . '/v1',
549 $slug,
550 array(
551 'methods' => $method,
552 'callback' => array( $this, $callBack ),
553 'permission_callback' => array( $this, 'getPermission' ),
554 ) );
555 }
556
557 /**
558 * Permission Callback
559 **/
560 public function getPermission() {
561 if ( current_user_can( 'manage_options' ) ) {
562 return true;
563 } else {
564 return false;
565 }
566 }
567
568 /**
569 * Ensures only one instance of Class is loaded or can be loaded.
570 *
571 * @return Api Class instance
572 * @since 1.0.0
573 * @static
574 */
575 public static function instance(){
576 if (is_null(self::$instance)) {
577 self::$instance = new self();
578 }
579 return self::$instance;
580 }
581 }
582