PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / trunk
MainWP Dashboard: Self-hosted WordPress Management for Agencies vtrunk
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / modules / api-backups / classes / class-api-backups-utility.php

class-api-backups-utility.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies trunk, at modules/api-backups/classes/class-api-backups-utility.php

792 lines 26.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class Api_Backups_Utility
4 *
5 * @package MainWP\Dashboard
6 * @version 5.0
7 */
8
9 namespace MainWP\Dashboard\Module\ApiBackups;
10
11 use MainWP\Dashboard\MainWP_Credential_Render;
12 use MainWP\Dashboard\MainWP_DB;
13 use MainWP\Dashboard\MainWP_Logger;
14 use MainWP\Dashboard\MainWP_System_Utility;
15
16 // Exit if accessed directly.
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21
22 /**
23 * Class Api_Backups_Utility
24 */
25 class Api_Backups_Utility { //phpcs:ignore -- NOSONAR - multi methods.
26
27 /**
28 * Instance value.
29 *
30 * @var static Default null
31 */
32 public static $instance = null;
33
34 /**
35 * Get Instance
36 *
37 * Creates public static instance.
38 *
39 * @static
40 *
41 * @return Api_Backups_Utility
42 */
43 public static function get_instance() {
44 if ( null === static::$instance ) {
45 static::$instance = new self();
46 }
47 return static::$instance;
48 }
49
50 /**
51 * Method __construct.
52 */
53 public function __construct() {
54 // contructor.
55 }
56
57 /**
58 * Method count_child_sites().
59 */
60 public function count_child_sites() {
61 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
62
63 if ( ! empty( $websites ) ) {
64 $sites_count = MainWP_DB::num_rows( $websites );
65 }
66 // Free result set.
67 Api_Backups_Helper::free_result( $websites );
68
69 return $sites_count;
70 }
71
72 /**
73 * Get timestamp.
74 *
75 * @param int $timestamp Holds Timestamp.
76 *
77 * @return float|int Return GMT offset.
78 */
79 public static function get_timestamp( $timestamp = false ) {
80 if ( empty( $timestamp ) ) {
81 $timestamp = time();
82 }
83 $gmtOffset = get_option( 'gmt_offset' );
84
85 return $gmtOffset ? ( $gmtOffset * HOUR_IN_SECONDS ) + $timestamp : $timestamp;
86 }
87
88 /**
89 * Format timestamp.
90 *
91 * @param int $timestamp Holds Timestamp.
92 * @param bool $gmt Whether to set as General mountain time. Default: FALSE.
93 *
94 * @return string Return Timestamp.
95 */
96 public static function format_timestamp( $timestamp, $gmt = false ) {
97 return date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $timestamp, $gmt );
98 }
99
100 /**
101 * Format datestamp.
102 *
103 * @param int $timestamp Holds Timestamp.
104 * @param bool $gmt Whether to set as General mountain time. Default: FALSE.
105 *
106 * @return string Return Timestamp.
107 */
108 public static function format_datestamp( $timestamp, $gmt = false ) {
109 return date_i18n( get_option( 'date_format' ), $timestamp, $gmt );
110 }
111
112 /**
113 * Method map_fields()
114 *
115 * Map Site.
116 *
117 * @param mixed $website Website to map.
118 * @param mixed $keys Keys to map.
119 * @param bool $object_output Output format array|object.
120 *
121 * @return object $outputSite Mapped site.
122 */
123 public static function map_fields( &$website, $keys, $object_output = false ) { //phpcs:ignore -- NOSONAR - complex.
124 $outputSite = array();
125 if ( ! empty( $website ) ) {
126 if ( is_object( $website ) ) {
127 foreach ( $keys as $key ) {
128 if ( property_exists( $website, $key ) ) {
129 $outputSite[ $key ] = $website->$key;
130 }
131 }
132 } elseif ( is_array( $website ) ) {
133 foreach ( $keys as $key ) {
134 $outputSite[ $key ] = $website[ $key ];
135 }
136 }
137 }
138
139 if ( $object_output ) {
140 return (object) $outputSite;
141 } else {
142 return $outputSite;
143 }
144 }
145
146 /**
147 * Method array_sort()
148 *
149 * Sort given array by given flags.
150 *
151 * @param mixed $arr Array to sort.
152 * @param mixed $key Array key.
153 * @param string $sort_flag Flags to sort by. Default = SORT_STRING.
154 */
155 public static function array_sort( &$arr, $key, $sort_flag = SORT_STRING ) {
156 $sorter = array();
157 $ret = array();
158 reset( $arr );
159 foreach ( $arr as $ii => $val ) {
160 $sorter[ $ii ] = $val[ $key ];
161 }
162 asort( $sorter, $sort_flag );
163 foreach ( $sorter as $ii => $val ) {
164 $ret[ $ii ] = $arr[ $ii ];
165 }
166 $arr = $ret;
167 }
168
169 /**
170 * Debugging log info.
171 *
172 * Sets logging for debugging purpose
173 *
174 * @param string $message Log info message.
175 */
176 public static function log_info( $message ) {
177 static::log_debug( $message, 2 );
178 }
179
180 /**
181 * Debugging log.
182 *
183 * Sets logging for debugging purpose.
184 *
185 * @param string $message Log debug message.
186 * @param int $log_color Log color.
187 */
188 public static function log_debug( $message, $log_color = 3 ) {
189 if ( is_array( $message ) || is_object( $message ) ) {
190 $message = print_r( $message, true ); //phpcs:ignore
191 } elseif ( ! is_string( $message ) ) {
192 $message = 'undefined';
193 }
194
195 if ( ! in_array( $log_color, array( 0, 1, 2, 3 ) ) ) {
196 $log_color = 3;
197 }
198 do_action( 'mainwp_log_action', 'API Backups :: ' . $message, MainWP_Logger::API_BACKUPS_LOG_PRIORITY, $log_color );
199 }
200
201 /**
202 *
203 * Method save_lasttime_backup().
204 *
205 * @param int $site_id site id.
206 * @param int $available_backups Available backups.
207 * @param string $backup_api API backups provider.
208 *
209 * @return mixed
210 */
211 public static function save_lasttime_backup( $site_id, $available_backups, $backup_api ) { //phpcs:ignore -- NOSONAR - complex method.
212
213 static::log_debug( 'save backup time :: [available backups=' . ( is_string( $available_backups ) ? $available_backups : 'is not string' ) . ']' );
214
215 if ( empty( $available_backups ) ) {
216 return;
217 }
218
219 if ( is_string( $available_backups ) ) {
220 $available_backups = json_decode( $available_backups );
221 }
222
223 $primaryBackup = MainWP_System_Utility::get_primary_backup();
224
225 $website = Api_Backups_Helper::get_website_by_id( $site_id );
226
227 $backup_method = '';
228 if ( is_array( $website ) && isset( $website['primary_backup_method'] ) ) {
229 if ( '' === $website['primary_backup_method'] || 'global' === $website['primary_backup_method'] ) {
230 $backup_method = $primaryBackup;
231 } else {
232 $backup_method = $website['primary_backup_method'];
233 }
234 }
235
236 if ( 'module-api-backups' !== $backup_method ) {
237 return;
238 }
239
240 $lasttime_backup = 0;
241 if ( 'plesk' === $backup_api ) {
242 $available_backups = is_object( $available_backups ) && ! empty( $available_backups->value ) ? $available_backups->value : array();
243 if ( is_array( $available_backups ) ) {
244 foreach ( $available_backups as $backup ) {
245 if ( is_object( $backup ) && ! empty( $backup->value->createdAt->value ) ) {
246 $backup_time = strtotime( $backup->value->createdAt->value );
247 if ( $backup_time > $lasttime_backup ) {
248 $lasttime_backup = $backup_time;
249 }
250 }
251 }
252 }
253 } elseif ( 'kinsta' === $backup_api ) {
254 $available_backups = is_array( $available_backups ) && ! empty( $available_backups ) ? $available_backups : array();
255 if ( is_array( $available_backups ) ) {
256 foreach ( $available_backups as $backup ) {
257 if ( is_object( $backup ) && ! empty( $backup->created_at ) ) {
258 $milliseconds = $backup->created_at;
259 $epoch = $milliseconds / 1000;
260 $backup_time = strtotime( $epoch );
261 if ( $backup_time > $lasttime_backup ) {
262 $lasttime_backup = $backup_time;
263 }
264 }
265 }
266 }
267 } elseif ( 'cpanel_auto' === $backup_api ) {
268 if ( is_object( $available_backups ) && isset( $available_backups->data ) ) {
269 $available_backups_automatic_list = $available_backups->data;
270 } else {
271 $available_backups_automatic_list = array();
272 }
273
274 if ( is_array( $available_backups_automatic_list ) ) {
275 foreach ( $available_backups_automatic_list as $backup ) {
276 if ( is_object( $backup ) && ! empty( $backup->backupID ) ) {
277 $backup_time = strtotime( $backup->backupID );
278 if ( $backup_time > $lasttime_backup ) {
279 $lasttime_backup = $backup_time;
280 }
281 }
282 }
283 }
284 } elseif ( 'cpanel_manual' === $backup_api ) {
285 $available_backups_manual_list = $available_backups;
286 if ( is_array( $available_backups_manual_list ) ) {
287 foreach ( $available_backups_manual_list as $backup ) {
288 if ( is_object( $backup ) && ! empty( $backup->timestamp ) ) {
289 $backup_time = $backup->timestamp;
290 if ( $backup_time > $lasttime_backup ) {
291 $lasttime_backup = $backup_time;
292 }
293 }
294 }
295 }
296 } elseif ( 'cpanel_wp_toolkit' === $backup_api ) {
297 $available_backups_manual_list = $available_backups;
298 if ( is_array( $available_backups_manual_list ) ) {
299 foreach ( $available_backups_manual_list as $backup ) {
300 if ( is_object( $backup ) && ! empty( $backup->value->createdAt->value ) ) {
301 $backup_time = strtotime( $backup->value->createdAt->value );
302 if ( $backup_time > $lasttime_backup ) {
303 $lasttime_backup = $backup_time;
304 }
305 }
306 }
307 }
308 } elseif ( 'gridpane' === $backup_api ) {
309 if ( isset( $available_backups->automatic ) ) {
310 $available_backups_automatic_list = explode( ',', $available_backups->automatic );
311 } else {
312 $available_backups_automatic_list = array();
313 }
314 if ( isset( $available_backups->manual ) ) {
315 $available_backups_manual_list = explode( ',', $available_backups->manual );
316 } else {
317 $available_backups_manual_list = array();
318 }
319 // to do check date created: $api_response->backups->local.
320
321 if ( is_array( $available_backups_automatic_list ) ) {
322 foreach ( $available_backups_automatic_list as $backup_name ) {
323 $backup_time = substr( $backup_name, 0, 16 ); // get date time string in name.
324 $backup_time = strtotime( $backup_time );
325 if ( $backup_time > $lasttime_backup ) {
326 $lasttime_backup = $backup_time;
327 }
328 }
329 }
330
331 if ( is_array( $available_backups_manual_list ) ) {
332 foreach ( $available_backups_manual_list as $backup_name ) {
333 $backup_time = substr( $backup_name, 0, 16 ); // get date time string in name.
334 $backup_time = strtotime( $backup_time );
335 if ( $backup_time > $lasttime_backup ) {
336 $lasttime_backup = $backup_time;
337 }
338 }
339 }
340 } elseif ( 'cloudways' === $backup_api ) {
341 if ( isset( $available_backups->application_backup_exists ) && true === $available_backups->application_backup_exists ) {
342 $available_backups = $available_backups->backup_dates;
343 } else {
344 $available_backups = array();
345 }
346
347 if ( is_array( $available_backups ) ) {
348 foreach ( $available_backups as $backup ) {
349 $backup_time = strtotime( $backup );
350 if ( $backup_time > $lasttime_backup ) {
351 $lasttime_backup = $backup_time;
352 }
353 }
354 }
355 } elseif ( 'vultr' === $backup_api ) {
356 if ( isset( $available_backups->snapshots ) ) {
357 $available_snapshots_list = $available_backups->snapshots;
358 } else {
359 $available_snapshots_list = array();
360 }
361 if ( isset( $available_backups->backups ) ) {
362 $available_backups_list = $available_backups->backups;
363 } else {
364 $available_backups_list = array();
365 }
366 if ( is_array( $available_snapshots_list ) ) {
367 foreach ( $available_snapshots_list as $backup ) {
368 if ( is_object( $backup ) && ! empty( $backup->date_created ) ) {
369 $backup_time = strtotime( $backup->date_created );
370 if ( $backup_time > $lasttime_backup ) {
371 $lasttime_backup = $backup_time;
372 }
373 }
374 }
375 }
376 if ( is_array( $available_backups_list ) ) {
377 foreach ( $available_backups_list as $backup ) {
378 if ( is_object( $backup ) && ! empty( $backup->date_created ) ) {
379 $backup_time = strtotime( $backup->date_created );
380 if ( $backup_time > $lasttime_backup ) {
381 $lasttime_backup = $backup_time;
382 }
383 }
384 }
385 }
386 } elseif ( 'linode' === $backup_api ) {
387 // Automatic Backups.
388 if ( isset( $available_backups->automatic ) ) {
389 $available_backups_automatic_list = $available_backups->automatic;
390 } else {
391 $available_backups_automatic_list = array();
392 }
393 // Manual Backups.
394 if ( isset( $available_backups->snapshot ) ) {
395 $available_backups_snapshot_list = $available_backups->snapshot;
396 } else {
397 $available_backups_snapshot_list = array();
398 }
399 if ( is_array( $available_backups_automatic_list ) ) {
400 foreach ( $available_backups_automatic_list as $backup ) {
401 if ( is_object( $backup ) && ! empty( $backup->created ) ) {
402 $backup_time = strtotime( $backup->created );
403 if ( $backup_time > $lasttime_backup ) {
404 $lasttime_backup = $backup_time;
405 }
406 }
407 }
408 }
409 if ( is_array( $available_backups_snapshot_list ) ) {
410 foreach ( $available_backups_snapshot_list as $backup ) {
411 if ( is_object( $backup ) && ! empty( $backup->created ) ) {
412 $backup_time = strtotime( $backup->created );
413 if ( $backup_time > $lasttime_backup ) {
414 $lasttime_backup = $backup_time;
415 }
416 }
417 }
418 }
419 } elseif ( 'digitalocean' === $backup_api ) {
420 if ( isset( $available_backups->snapshots ) ) {
421 $available_backups = $available_backups->snapshots;
422 }
423 if ( is_array( $available_backups ) ) {
424 foreach ( $available_backups as $backup ) {
425 if ( is_object( $backup ) && ! empty( $backup->created_at ) ) {
426 $backup_time = strtotime( $backup->created_at );
427 if ( $backup_time > $lasttime_backup ) {
428 $lasttime_backup = $backup_time;
429 }
430 }
431 }
432 }
433 }
434
435 if ( empty( $lasttime_backup ) ) {
436 return;
437 }
438 $lastBackup = MainWP_DB::instance()->get_website_option( $site_id, 'primary_lasttime_backup' );
439
440 if ( ! empty( $lastBackup ) && $lastBackup > $lasttime_backup ) {
441 return;
442 }
443 static::log_debug( 'save backup time :: [site-id=' . $site_id . '] :: [backup time=' . gmdate( 'Y-m-d H:i:s', $lasttime_backup ) . '] :: [api-backups=' . $backup_api . ']' );
444 $site = new \stdClass();
445 $site->id = $site_id;
446 MainWP_DB::instance()->update_website_option( $site, 'primary_lasttime_backup', $lasttime_backup );
447 }
448
449 /**
450 * Show Info Messages
451 *
452 * Check whenther or not to show the MainWP Message.
453 *
454 * @param string $notice_id Notice ID.
455 *
456 * @return bool False if hidden, true to show.
457 */
458 public static function show_mainwp_message( $notice_id ) {
459 $status = get_user_option( 'mainwp_notice_saved_status' );
460 if ( ! is_array( $status ) ) {
461 $status = array();
462 }
463 if ( isset( $status[ $notice_id ] ) ) {
464 return false;
465 }
466 return true;
467 }
468
469
470 /**
471 * Method human_filesize()
472 *
473 * Convert to human readable file size format,
474 * (B|kB|MB|GB|TB|PB|EB|ZB|YB).
475 *
476 * @param mixed $bytes File in bytes.
477 * @param integer $decimals Number of decimals to output.
478 *
479 * @return string Human readable file size.
480 */
481 public static function human_filesize( $bytes, $decimals = 2 ) {
482 $size = array( 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' );
483 $factor = floor( ( strlen( $bytes ) - 1 ) / 3 );
484
485 return sprintf( "%.{$decimals}f", $bytes / pow( 1024, $factor ) ) . @$size[ $factor ]; //phpcs:ignore
486 }
487
488
489 /**
490 * Get Color Code
491 *
492 * Returns CSS class to use correct color for the element.
493 *
494 * @param int $value value.
495 *
496 * @return string CSS class.
497 */
498 public static function color_code( $value ) {
499 $color = '';
500 if ( 5 < $value ) {
501 $color = 'red';
502 } elseif ( 0 < $value && 5 >= $value ) {
503 $color = 'yellow';
504 } else {
505 $color = 'green';
506 }
507 return $color;
508 }
509
510 /**
511 * Method update_option()
512 *
513 * Update option.
514 *
515 * @param mixed $option_name Option name.
516 * @param mixed $option_value Option value.
517 *
518 * @return (boolean) False if value was not updated and true if value was updated.
519 */
520 public static function update_option( $option_name, $option_value ) {
521 $success = add_option( $option_name, $option_value, '', 'no' );
522
523 if ( ! $success ) {
524 $success = update_option( $option_name, $option_value );
525 }
526
527 return $success;
528 }
529
530
531 /**
532 * Method encrypt_api_keys
533 *
534 * @param string $data data.
535 * @param int $siteid site id.
536 * @param string $file_key file key.
537 * @param string $service_name service name.
538 *
539 * Encrypt data.
540 */
541 public function encrypt_api_keys( $data, $siteid = false, $file_key = false, $service_name = '' ) {
542 if ( is_string( $data ) ) {
543
544 $prefix = 'apibackups_';
545
546 if ( ! empty( $siteid ) ) {
547 $prefix = $prefix . intval( $siteid ) . '_';
548 }
549
550 if ( ! empty( $service_name ) && is_string( $service_name ) ) {
551 $prefix = $prefix . $service_name . '_';
552 }
553
554 $result = apply_filters( 'mainwp_encrypt_key_value', false, $data, $prefix, $file_key );
555
556 if ( is_array( $result ) && ! empty( $result['encrypted_val'] ) ) {
557 return $result;
558 }
559 }
560 return $data;
561 }
562
563 /**
564 * Method decrypt_api_keys
565 *
566 * @param mixed $encrypted_data encrypted data.
567 * @param string $def_val default data.
568 */
569 public function decrypt_api_keys( $encrypted_data, $def_val = '' ) {
570 if ( ! empty( $encrypted_data ) && is_array( $encrypted_data ) && ! empty( $encrypted_data['encrypted_val'] ) ) { // old format.
571 $result = apply_filters( 'mainwp_decrypt_key_value', false, $encrypted_data, $def_val );
572 if ( ! empty( $result ) && is_string( $result ) ) {
573 return $result;
574 }
575 }
576 return $def_val;
577 }
578
579 /**
580 * Method get_compatible_site_api_key
581 *
582 * Encrypt data.
583 *
584 * @param string $name name data.
585 * @param string $def_val default data.
586 * @param string $opt_name Option name.
587 */
588 public function get_api_key( $name, $def_val = '', $opt_name = '' ) {
589
590 $names = array(
591 'vultr',
592 'gridpane',
593 'linode',
594 'digitalocean',
595 'cloudways',
596 'cpanel',
597 'plesk',
598 'kinsta',
599 );
600
601 if ( ! in_array( $name, $names ) ) {
602 return $def_val;
603 }
604
605 if ( ! empty( $opt_name ) ) {
606 $encrypted = get_option( 'mainwp_api_backups_' . $name . '_' . (string) $opt_name );
607 } else {
608 $encrypted = get_option( 'mainwp_api_backups_' . $name . '_api_key' );
609 }
610
611 if ( is_array( $encrypted ) && ! empty( $encrypted['file_key'] ) ) {
612 $key = $this->decrypt_api_keys( $encrypted );
613 if ( ! empty( $key ) && is_string( $key ) ) {
614 return $key;
615 }
616 }
617 return $def_val;
618 }
619
620 /**
621 * Method update_compatible_site_api_key
622 *
623 * Encrypt data.
624 *
625 * @param string $name name data.
626 * @param string $value value data.
627 * @param string $opt_name Option name.
628 */
629 public function update_api_key( $name, $value, $opt_name = '' ) {
630
631 $names = array(
632 'vultr',
633 'gridpane',
634 'linode',
635 'digitalocean',
636 'cloudways',
637 'cpanel',
638 'plesk',
639 'kinsta',
640 );
641
642 if ( ! in_array( $name, $names ) ) {
643 return false;
644 }
645
646 // MWP-1543: settings forms render the sentinel ('••••••••') in the
647 // password input when a value is already stored. A submission that
648 // returns the sentinel unchanged means "leave existing value alone";
649 // short-circuit before delete_option / encrypt so no overwrite happens.
650 if ( MainWP_Credential_Render::is_sentinel( $value ) ) {
651 return true;
652 }
653
654 if ( ! empty( $opt_name ) ) {
655 $opt_name = 'mainwp_api_backups_' . $name . '_' . (string) $opt_name;
656 } else {
657 $opt_name = 'mainwp_api_backups_' . $name . '_api_key';
658 }
659
660 $current = get_option( $opt_name );
661 $key_file = '';
662
663 if ( is_array( $current ) && ! empty( $current['file_key'] ) ) {
664 $key_file = $current['file_key'];
665 }
666
667 if ( empty( $value ) ) {
668 delete_option( $opt_name );
669 if ( ! empty( $key_file ) ) {
670 do_action( 'mainwp_delete_key_file', $key_file );
671 }
672 return true;
673 }
674
675 $encrypted = $this->encrypt_api_keys( $value, false, $key_file, $name );
676 if ( is_array( $encrypted ) && ! empty( $encrypted['file_key'] ) ) {
677 return update_option( $opt_name, $encrypted );
678 }
679
680 return false;
681 }
682
683 /**
684 * Method get child site key.
685 *
686 * Encrypt data.
687 *
688 * @param int $website_id name data.
689 * @param string $name name data.
690 * @param string $def_val default data.
691 */
692 public function get_child_api_key( $website_id, $name, $def_val = '' ) {
693
694 $names = array(
695 'vultr',
696 'gridpane',
697 'linode',
698 'digitalocean',
699 'cloudways',
700 'cpanel',
701 'plesk',
702 'kinsta',
703 );
704
705 if ( ! in_array( $name, $names ) ) {
706 return $def_val;
707 }
708
709 $opt_name = 'mainwp_api_backups_' . $name . '_api_key';
710 $opt_encoded = Api_Backups_Helper::get_website_options( $website_id, array( $opt_name ) );
711 if ( array_key_exists( $opt_name, $opt_encoded ) ) {
712 $encrypted = json_decode( $opt_encoded[ $opt_name ], true );
713 } else {
714 $encrypted = '';
715 }
716
717 if ( is_array( $encrypted ) && ! empty( $encrypted['file_key'] ) ) {
718 $key = $this->decrypt_api_keys( $encrypted );
719
720 if ( ! empty( $key ) && is_string( $key ) ) {
721 return $key;
722 }
723 }
724 return $def_val;
725 }
726
727 /**
728 * Method update child api key.
729 *
730 * Encrypt data.
731 *
732 * @param int $website_id name data.
733 * @param string $name name data.
734 * @param string $value value data.
735 */
736 public function update_child_api_key( $website_id, $name, $value ) {
737
738 $names = array(
739 'vultr',
740 'gridpane',
741 'linode',
742 'digitalocean',
743 'cloudways',
744 'cpanel',
745 'plesk',
746 'kinsta',
747 );
748
749 if ( ! in_array( $name, $names ) ) {
750 return false;
751 }
752
753 // MWP-1543: same sentinel short-circuit as update_api_key(); the
754 // per-site Edit Site form renders the sentinel placeholder when a
755 // value already exists, and an unchanged submission must not
756 // overwrite the encrypted option with the sentinel string.
757 if ( MainWP_Credential_Render::is_sentinel( $value ) ) {
758 return true;
759 }
760
761 $opt_name = 'mainwp_api_backups_' . $name . '_api_key';
762 $opt_encoded = Api_Backups_Helper::get_website_options( $website_id, array( $opt_name ) );
763 if ( array_key_exists( $opt_name, $opt_encoded ) ) {
764 $current = json_decode( $opt_encoded[ $opt_name ], true );
765 } else {
766 $current = '';
767 }
768 $key_file = '';
769 if ( is_array( $current ) && ! empty( $current['file_key'] ) ) {
770 $key_file = $current['file_key'];
771 }
772
773 // If post $value is empty, delete option.
774 if ( empty( $value ) ) {
775 // Delete the site serviceapi key.
776 Api_Backups_Helper::update_website_option( $website_id, $opt_name, '' );
777 if ( ! empty( $key_file ) ) {
778 do_action( 'mainwp_delete_key_file', $key_file );
779 }
780 return true;
781 }
782
783 $encrypted = wp_json_encode( $this->encrypt_api_keys( $value, $website_id, $key_file, $name ) );
784
785 if ( ! empty( $encrypted ) ) {
786 return Api_Backups_Helper::update_website_option( $website_id, $opt_name, $encrypted );
787 }
788
789 return false;
790 }
791 }
792