PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
6.2.2 6.2.1 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 All 155 releases
mainwp / modules / api-backups / classes / class-api-backups-3rd-party.php

class-api-backups-3rd-party.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.2.2, at modules/api-backups/classes/class-api-backups-3rd-party.php

5,479 lines 267.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Module API Backups 3rd Party class.
4 *
5 * @package MainWP\Dashboard
6 * @version 5.0
7 */
8
9 namespace MainWP\Dashboard\Module\ApiBackups;
10
11 use WP_Error;
12 use MainWP\Dashboard\MainWP_DB;
13 use MainWP\Dashboard\MainWP_Extensions_Handler;
14 use MainWP\Dashboard\MainWP_Site_Open;
15
16 // Exit if accessed directly.
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 /**
22 * Class Api_Backups_3rd_Party
23 *
24 * This class is responsible for handling the 3rd party API requests for each available backup provider.
25 *
26 * @package MainWP\Dashboard
27 *
28 * @version 5.0
29 */
30 class Api_Backups_3rd_Party { //phpcs:ignore -- NOSONAR - multi methods.
31
32 // phpcs:disable WordPress.DB.RestrictedFunctions, Generic.Metrics.CyclomaticComplexity, WordPress.WP.AlternativeFunctions, WordPress.PHP.NoSilencedErrors -- Using cURL functions.
33
34 const CLOUDWAYS_API_URL = 'https://api.cloudways.com/api/v2';
35
36 /**
37 * Public static variable to hold the single instance of the class.
38 *
39 * @var mixed Default null
40 */
41 protected static $instance = null;
42
43
44 /**
45 * Public static variable to hold the saved access token value.
46 *
47 * @var mixed Default null
48 */
49 protected static $access_token = null;
50
51 /**
52 * Public static variable.
53 */
54 const OPERATION = '/operation/'; // to clean code.
55
56 /**
57 * Public static variable.
58 */
59 const SNAPSHOTS = '/snapshots/'; // to clean code.
60
61 /**
62 * Public static variable.
63 */
64 const INSTANCES = '/instances/'; // to clean code.
65
66 /**
67 * Public static variable.
68 */
69 const DROPLETS = '/droplets/'; // to clean code.
70
71 /**
72 * Method instance()
73 *
74 * Create a public static instance.
75 *
76 * @static
77 * @return Api_Backups_3rd_Party
78 */
79 public static function instance() {
80 if ( null === static::$instance ) {
81 static::$instance = new self();
82 }
83 return static::$instance;
84 }
85
86
87 /**
88 * Method get_class_name()
89 *
90 * Get class name.
91 *
92 * @return string __CLASS__ Class name.
93 */
94 public static function get_class_name() {
95 return __CLASS__;
96 }
97
98 /**
99 * Api_Backups_3rd_Party Constructor.
100 *
101 * Runs each time the class is called.
102 */
103 public function __construct() {
104 // Initiate admin_init() function.
105 add_action( 'admin_init', array( &$this, 'admin_init' ) );
106 }
107
108 /**
109 * Admin init.
110 */
111 public function admin_init() {
112 // Admin Init.
113 }
114
115 /**
116 * Init ajax actions.
117 */
118 public function init_ajax_actions() {
119 // Cloudways Ajax.
120 do_action( 'mainwp_ajax_add_action', 'cloudways_action_backup', array( &$this, 'ajax_cloudways_action_backup' ) );
121 do_action( 'mainwp_ajax_add_action', 'cloudways_action_individual_backup', array( &$this, 'ajax_cloudways_action_individual_backup' ) );
122 do_action( 'mainwp_ajax_add_action', 'cloudways_action_update_ids', array( &$this, 'ajax_cloudways_action_update_ids' ) );
123 do_action( 'mainwp_ajax_add_action', 'cloudways_action_refresh_available_backups', array( &$this, 'cloudways_action_refresh_available_backups' ) );
124 do_action( 'mainwp_ajax_add_action', 'cloudways_action_restore_backup', array( &$this, 'cloudways_action_restore_backup' ) );
125 do_action( 'mainwp_ajax_add_action', 'cloudways_action_delete_backup', array( &$this, 'cloudways_action_delete_backup' ) );
126
127 // GridPane Ajax.
128 do_action( 'mainwp_ajax_add_action', 'gridpane_action_create_backup', array( &$this, 'ajax_gridpane_action_create_backup' ) );
129 do_action( 'mainwp_ajax_add_action', 'gridpane_action_individual_create_backup', array( &$this, 'ajax_gridpane_action_individual_create_backup' ) );
130 do_action( 'mainwp_ajax_add_action', 'gridpane_action_update_ids', array( &$this, 'ajax_gridpane_action_update_ids' ) );
131 do_action( 'mainwp_ajax_add_action', 'gridpane_action_refresh_available_backups', array( &$this, 'gridpane_action_refresh_available_backups' ) );
132 do_action( 'mainwp_ajax_add_action', 'gridpane_action_restore_backup', array( &$this, 'gridpane_action_restore_backup' ) );
133 do_action( 'mainwp_ajax_add_action', 'gridpane_action_delete_backup', array( &$this, 'gridpane_action_delete_backup' ) );
134
135 // Vultr Ajax.
136 do_action( 'mainwp_ajax_add_action', 'vultr_action_create_snapshot', array( &$this, 'ajax_vultr_action_create_snapshot' ) );
137 do_action( 'mainwp_ajax_add_action', 'vultr_action_individual_create_snapshot', array( &$this, 'ajax_vultr_action_individual_create_snapshot' ) );
138 do_action( 'mainwp_ajax_add_action', 'vultr_action_refresh_available_backups', array( &$this, 'vultr_action_refresh_available_backups' ) );
139 do_action( 'mainwp_ajax_add_action', 'vultr_action_restore_backup', array( &$this, 'ajax_vultr_action_restore_backup' ) );
140 do_action( 'mainwp_ajax_add_action', 'vultr_action_delete_backup', array( &$this, 'vultr_action_delete_backup' ) );
141
142 // Linode Ajax.
143 do_action( 'mainwp_ajax_add_action', 'linode_action_create_backup', array( &$this, 'ajax_linode_action_create_backup' ) );
144 do_action( 'mainwp_ajax_add_action', 'linode_action_individual_create_backup', array( &$this, 'ajax_linode_action_individual_create_backup' ) );
145 do_action( 'mainwp_ajax_add_action', 'linode_action_refresh_available_backups', array( &$this, 'linode_action_refresh_available_backups' ) );
146 do_action( 'mainwp_ajax_add_action', 'linode_action_restore_backup', array( &$this, 'linode_action_restore_backup' ) );
147 do_action( 'mainwp_ajax_add_action', 'linode_action_cancel_backups', array( &$this, 'linode_action_cancel_backups' ) );
148
149 // DigitalOcean Ajax.
150 do_action( 'mainwp_ajax_add_action', 'digitalocean_action_create_backup', array( &$this, 'ajax_digitalocean_action_create_backup' ) );
151 do_action( 'mainwp_ajax_add_action', 'digitalocean_action_individual_create_backup', array( &$this, 'ajax_digitalocean_action_individual_create_backup' ) );
152 do_action( 'mainwp_ajax_add_action', 'digitalocean_action_refresh_available_backups', array( &$this, 'digitalocean_action_refresh_available_backups' ) );
153 do_action( 'mainwp_ajax_add_action', 'digitalocean_action_restore_backup', array( &$this, 'digitalocean_action_restore_backup' ) );
154 do_action( 'mainwp_ajax_add_action', 'digitalocean_action_delete_backup', array( &$this, 'digitalocean_action_delete_backup' ) );
155
156 // cPanel Ajax.
157 do_action( 'mainwp_ajax_add_action', 'cpanel_action_refresh_available_backups', array( &$this, 'ajax_cpanel_action_refresh_available_backups' ) );
158 do_action( 'mainwp_ajax_add_action', 'cpanel_action_create_manual_backup', array( &$this, 'ajax_cpanel_action_create_manual_backup' ) );
159 do_action( 'mainwp_ajax_add_action', 'cpanel_action_create_wptk_backup', array( &$this, 'ajax_cpanel_action_create_wptk_backup' ) );
160 do_action( 'mainwp_ajax_add_action', 'cpanel_action_restore_wptk_backup', array( &$this, 'ajax_cpanel_action_restore_wptk_backup' ) );
161 do_action( 'mainwp_ajax_add_action', 'cpanel_action_delete_wptk_backup', array( &$this, 'ajax_cpanel_action_delete_wptk_backup' ) );
162 do_action( 'mainwp_ajax_add_action', 'cpanel_action_restore_backup', array( &$this, 'ajax_cpanel_action_restore_backup' ) );
163 do_action( 'mainwp_ajax_add_action', 'cpanel_action_restore_database_backup', array( &$this, 'ajax_cpanel_action_restore_database_backup' ) );
164 do_action( 'mainwp_ajax_add_action', 'cpanel_action_restore_manual_backup', array( &$this, 'ajax_cpanel_action_restore_manual_backup' ) );
165 do_action( 'mainwp_ajax_add_action', 'cpanel_action_create_database_backup', array( &$this, 'ajax_cpanel_action_create_database_backup' ) );
166 do_action( 'mainwp_ajax_add_action', 'cpanel_action_create_full_backup', array( &$this, 'ajax_cpanel_action_create_full_backup' ) );
167
168 // Plesk Ajax.
169 do_action( 'mainwp_ajax_add_action', 'plesk_action_refresh_available_backups', array( &$this, 'ajax_plesk_action_refresh_available_backups' ) );
170 do_action( 'mainwp_ajax_add_action', 'plesk_action_create_backup', array( &$this, 'ajax_plesk_action_create_backup' ) );
171 do_action( 'mainwp_ajax_add_action', 'plesk_action_restore_backup', array( &$this, 'ajax_plesk_action_restore_backup' ) );
172 do_action( 'mainwp_ajax_add_action', 'plesk_action_delete_backup', array( &$this, 'ajax_plesk_action_delete_backup' ) );
173
174 // Kinsta Ajax.
175 do_action( 'mainwp_ajax_add_action', 'kinsta_action_refresh_available_backups', array( &$this, 'ajax_kinsta_action_refresh_available_backups' ) );
176 do_action( 'mainwp_ajax_add_action', 'kinsta_action_create_backup', array( &$this, 'ajax_kinsta_action_create_backup' ) );
177 do_action( 'mainwp_ajax_add_action', 'kinsta_action_restore_backup', array( &$this, 'ajax_kinsta_action_restore_backup' ) );
178 do_action( 'mainwp_ajax_add_action', 'kinsta_action_delete_backup', array( &$this, 'ajax_kinsta_action_delete_backup' ) );
179
180 // Backup selected sites.
181 do_action( 'mainwp_ajax_add_action', 'action_backup_selected_sites', array( &$this, 'action_backup_selected_sites' ) );
182
183 // Fire off Cloudways & Gridpane ID auto lookup on site addition.
184 add_action( 'mainwp_added_new_site', array( &$this, 'hook_added_new_site' ), 10, 2 );
185 }
186
187
188 /**
189 * Hook after new site added.
190 *
191 * @param int $id Site id just added.
192 * @param object $website Site data just added.
193 *
194 * @return void
195 */
196 public function hook_added_new_site( $id, $website ) {
197 unset( $id );
198 $success = $this->fetch_cloudways_settings_for_site( $website );
199 if ( ! $success ) {
200 $this->fetch_gridpane_settings_for_site( $website );
201 }
202 }
203
204
205 /**
206 * Hook after new site added.
207 *
208 * @param object $website Site data just added.
209 *
210 * @return bool result.
211 */
212 public function fetch_cloudways_settings_for_site( $website ) {
213
214 if ( empty( $website ) || empty( $website->id ) || empty( $website->url ) ) {
215 return false;
216 }
217
218 $url = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', $website->url ) );
219
220 // Fetch Cloudways Server List.
221 $server_list = static::fetch_cloudways_server_list();
222
223 /**
224 * Search $server_list for Child Site app ID & server ID.
225 *
226 * Loop through each Server/App & check if app cname / fqdn name matches any Child Site domain name.
227 * if so, save the server & app ID to that Child Site's options table.
228 */
229 if ( ! is_array( $server_list ) ) {
230 return false;
231 }
232
233 $found_child_site_id = $website->id;
234
235 foreach ( $server_list as $server ) {
236 foreach ( $server->apps as $app ) {
237 if ( $app->cname === $url || $app->app_fqdn === $url ) { // Check if app fqdn name matches any Child Site domain name, if so, save the server & app ID to that Child Site's options table.
238 $this->update_3rd_party_cloudways_data( $found_child_site_id, $app );
239 return true;
240 }
241 }
242 }
243
244 return false;
245 }
246
247 /**
248 * Method update_3rd_party_data().
249 *
250 * @param int $site_id site id.
251 * @param object $app app data.
252 *
253 * @return void
254 */
255 public function update_3rd_party_cloudways_data( $site_id, $app ) {
256 Api_Backups_Helper::update_website_option( $site_id, 'mainwp_3rd_party_app_id', $app->id );
257 Api_Backups_Helper::update_website_option( $site_id, 'mainwp_3rd_party_instance_id', $app->server_id );
258 Api_Backups_Helper::update_website_option( $site_id, 'mainwp_3rd_party_api', 'Cloudways' );
259 }
260
261
262 /**
263 * Hook after new site added.
264 *
265 * @param object $website Site data just added.
266 *
267 * @return bool result.
268 */
269 public function fetch_gridpane_settings_for_site( $website ) {
270
271 if ( empty( $website ) || empty( $website->id ) || empty( $website->url ) ) {
272 return false;
273 }
274
275 $url = rawurlencode( $website->url );
276 $strip_protocall = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $url ) ) );
277 $clean_url = preg_replace( '/^www\./', '', $strip_protocall );
278
279 // Get Sites list.
280 $gridpane_list = static::gridpane_get_sites_list( 200 );
281
282 // Check for Child Site IP @ each instance. Add to Child Site Options Table.
283 if ( is_array( $gridpane_list ) ) {
284 foreach ( $gridpane_list as $gpane_site ) {
285 if ( $gpane_site->url === $clean_url ) {
286 // Grab Site options then update Child Site options.
287 Api_Backups_Helper::update_website_option( $website->id, 'mainwp_3rd_party_instance_id', $gpane_site->id );
288 Api_Backups_Helper::update_website_option( $website->id, 'mainwp_3rd_party_api', 'GridPane' );
289 return true;
290 }
291 }
292 }
293 return false;
294 }
295
296
297 /**
298 * Global backup page Action notification handler.
299 *
300 * @return void
301 */
302 public static function action_notifications() {
303 if ( isset( $_GET['backup'] ) && ( 'true' === $_GET['backup'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
304 echo '<div class="ui message green"><i class="icon close"></i> ' . esc_html__( 'All Backups have been created.', 'mainwp' ) . '</div>';
305 } elseif ( isset( $_GET['backup'] ) && ( 'false' === $_GET['backup'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
306 echo '<div class="ui message red"><i class="icon close"></i> ' . esc_html__( 'There was an issue with creating your backup.', 'mainwp' ) . '</div>';
307 }
308 }
309
310 /**
311 * Render the main api backups page.
312 *
313 * @return void
314 */
315 public static function render_mainwp_backups_page() {
316 ?>
317 <div class="mainwp-sub-header">
318 <div class="ui grid">
319 <div class="ui two column row">
320 <div class="middle aligned column ui">
321 <button id="action_backup_selected_sites" class="ui green mini button disabled"><?php esc_html_e( 'Backup Selected Sites', 'mainwp' ); ?></button>
322 </div>
323 <div class="right aligned middle aligned column">
324 <a href="admin.php?page=SettingsApiBackups" class="ui mini green basic button"><?php esc_html_e( 'Manage API Backups Settings', 'mainwp' ); ?></a>
325 </div>
326 </div>
327 </div>
328 </div>
329 <div class="ui padded segment" id="mainwp-3rd-party-api-backups">
330 <?php static::action_notifications(); ?>
331 <?php static::render_api_backups_table( '3rd-party-api-backups' ); ?>
332 </div>
333 <?php
334 }
335
336
337 /**
338 * Render the global 3rd party api backups table.
339 *
340 * @return void
341 */
342 public static function render_api_backups_table() { //phpcs:ignore -- NOSONAR - complex.
343
344 // Get all Child Sites aloud by user role.
345 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
346
347 ?>
348 <?php // Render action notifications. I get replaced by JS. ?>
349 <div id="mainwp-api-backups-message-zone" class="ui message" style="display: none;">
350 <i class="icon close"></i>
351 <div class="content">
352 <div class="message"></div>
353 </div>
354 </div>
355 <table id="mainwp-3rd-party-backups-table" class="ui mainwp-api-backup-table table" style="width:100%">
356 <thead>
357 <tr>
358 <th scope="col" class="no-sort collapsing check-column">
359 <span class="ui checkbox">
360 <label for="cb-select-all-top"></label>
361 <input id="cb-select-all-top" type="checkbox"/>
362 </span>
363 </th>
364 <th scope="col"><?php esc_html_e( 'Site', 'mainwp' ); ?></th>
365 <th scope="col"><?php esc_html_e( 'API Provider', 'mainwp' ); ?></th>
366 <th scope="col"><?php esc_html_e( 'Last Manual Backup Date', 'mainwp' ); ?></th>
367 <th scope="col" class="no-sort collapsing"></th>
368 </tr>
369 </thead>
370 <tbody>
371 <?php while ( $websites && ( $website = Api_Backups_Helper::fetch_object( $websites ) ) ) { ?>
372 <?php
373 /**
374 * Grab Child Site data needed to display Table.
375 */
376
377 // Grab API Provider.
378 $api_provider_array = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_api' ) );
379 $api_provider = ( isset( $api_provider_array['mainwp_3rd_party_api'] ) && '' !== $api_provider_array['mainwp_3rd_party_api'] ) ? $api_provider_array['mainwp_3rd_party_api'] : 'None';
380 $api_provider_options = strtolower( $api_provider );
381
382 // Check for Plesk and change to WP-Toolkit.
383 if ( 'Plesk' === $api_provider ) {
384 $api_provider = 'Plesk (WP Toolkit)';
385 }
386
387 // Grab Last Backup date UTC.
388 $last_backup_array = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $api_provider_options . '_last_backup' ) );
389 $last_backup_UTC = isset( $last_backup_array[ 'mainwp_3rd_party_' . $api_provider_options . '_last_backup' ] ) ? $last_backup_array[ 'mainwp_3rd_party_' . $api_provider_options . '_last_backup' ] : '';
390
391 // If found Convert UTC into chosen WP DateTime formats or return "Awaiting first backup".
392 if ( '' === $last_backup_UTC ) {
393 $last_backup = esc_html__( 'Awaiting first backup', 'mainwp' );
394 } else {
395 $last_backup = Api_Backups_Utility::format_timestamp( $last_backup_UTC );
396 }
397
398 ?>
399 <tr website-id="<?php echo intval( $website->id ); ?>" provider-name="<?php echo esc_attr( $api_provider ); ?>">
400 <td class="check-column">
401 <?php if ( 'None' !== $api_provider ) : ?>
402 <span class="ui checkbox">
403 <label for="table-checkbox"></label>
404 <input id="table-checkbox" type="checkbox" value="<?php echo intval( $website->id ); ?>" status="queue" >
405 </span>
406 <?php else : ?>
407 <span class="ui disabled checkbox">
408 <label for="table-checkbox"></label>
409 </span>
410 <?php endif; ?>
411 </td>
412 <td>
413 <div>
414 <a href="<?php MainWP_Site_Open::get_open_site_admin_link( $website->id, true ); //phpcs:ignore -- ok. ?>" target="_blank">
415 <i class="sign in alternate icon"></i>
416 </a>
417 <a href="admin.php?page=ManageSitesApiBackups&id=<?php echo intval( $website->id ); ?>"><?php echo esc_html( $website->name ); ?></a> <span class="running"></span>
418 </div>
419 <span class="ui small text">
420 <a href="<?php echo esc_url( $website->url ); ?>" target="_blank" class="ui grey text"><?php echo esc_url( $website->url ); ?></a>
421 </span>
422 </td>
423 <td><?php echo esc_html( $api_provider ); ?></td>
424 <td class="last-backup-date" ><?php echo ( $last_backup ) ? esc_html( $last_backup ) : esc_html__( 'Awaiting first backup', 'mainwp' ); ?></td>
425 <td class="collapsing not-selectable">
426 <i class="ui notched circle loading icon" style="display:none;"></i>
427 <div class="ui right pointing dropdown" style="z-index: 999">
428 <a href="javascript:void(0)"><i class="ellipsis vertical icon"></i></a>
429 <div class="menu">
430 <?php if ( 'cPanel' === $api_provider ) : ?>
431 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $api_provider_options ); ?>_action_full_backup item"
432 website_id="<?php echo intval( $website->id ); ?>" href="javascript:void(0)">
433 <?php esc_html_e( 'Backup', 'mainwp' ); ?>
434 </a>
435 <?php elseif ( 'None' !== $api_provider && 'cPanel' !== $api_provider ) : ?>
436 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $api_provider_options ); ?>_action_backup item"
437 website_id="<?php echo intval( $website->id ); ?>" href="javascript:void(0)">
438 <?php esc_html_e( 'Backup', 'mainwp' ); ?>
439 </a>
440 <?php endif; ?>
441 <a class="item" href="admin.php?page=ManageSitesApiBackups&id=<?php echo intval( $website->id ); ?>"><?php esc_html_e( 'Manage Backups', 'mainwp' ); ?></a>
442 </div>
443 </div>
444 </td>
445 </tr>
446 <?php
447 }
448 Api_Backups_Helper::free_result( $websites );
449 ?>
450 </tbody>
451 </table>
452 <script type="text/javascript">
453 let responsive = true;
454 if ( jQuery( window ).width() > 1140 ) {
455 responsive = false;
456 }
457 jQuery( document ).ready( function() {
458 jQuery( '.mainwp-api-backup-table' ).DataTable( {
459 "stateSave": true,
460 "stateDuration": 0,
461 "colReorder" : {columns:":not(.check-column):not(:last-child)"},
462 "responsive": responsive,
463 "scrollX": true,
464 "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
465 "columnDefs": [ { "targets": 'no-sort', "orderable": false } ],
466 "order": [ [ 1, "asc" ] ],
467 "language": { "emptyTable": "No backups found." },
468 "drawCallback": function( settings ) {
469 setTimeout(() => {
470 jQuery('#mainwp-3rd-party-backups-table .ui.checkbox').checkbox();
471 jQuery('.mainwp-api-backup-table .ui.dropdown').dropdown();
472 mainwp_datatable_fix_menu_overflow('#mainwp-3rd-party-backups-table');
473 }, 1000);
474 },
475 select: {
476 items: 'row',
477 style: 'multi+shift',
478 selector: 'tr>td:not(.not-selectable)'
479 }
480 }).on('select', function (e, dt, type, indexes) {
481 if( 'row' == type ){
482 dt.rows(indexes)
483 .nodes()
484 .to$().find('td.check-column .ui.checkbox' ).checkbox('set checked');
485 }
486 }).on('deselect', function (e, dt, type, indexes) {
487 if( 'row' == type ){
488 dt.rows(indexes)
489 .nodes()
490 .to$().find('td.check-column .ui.checkbox' ).checkbox('set unchecked');
491 }
492 }).on( 'columns-reordered', function () {
493 setTimeout(() => {
494 jQuery( '#mainwp-3rd-party-backups-table .ui.dropdown' ).dropdown();
495 jQuery( '#mainwp-3rd-party-backups-table .ui.checkbox' ).checkbox();
496 mainwp_datatable_fix_menu_overflow('#mainwp-3rd-party-backups-table');
497 mainwp_table_check_columns_init(); // ajax: to fix checkbox all.
498 }, 1000);
499 });
500 } );
501 </script>
502 <?php
503 }
504
505 /**
506 * Render the Individual 3rd Party API Backup Page.
507 *
508 * @param mixed $website The Child Site Object.
509 */
510 public function render_api_backups_site( $website ) { //phpcs:ignore -- NOSONAR - complex function.
511
512 $available_backups = array();
513
514 if ( empty( $website ) ) {
515 return;
516 }
517
518 $website_id = $website['id'];
519
520 /**
521 * Grab Child Site data needed to display Table.
522 */
523
524 // Grab backup api name.
525 $site_api_name = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_api' ) );
526 $backup_api = isset( $site_api_name['mainwp_3rd_party_api'] ) ? strtolower( $site_api_name['mainwp_3rd_party_api'] ) : null;
527
528 // Grab Child Sites available backups from DB to display in table.
529 $site_available_backups = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_available_backups' ) );
530
531 // Check if valid JSON or not. If not, then it's a string - do not decode it.
532 if ( isset( $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ] ) && ! empty( $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ] ) ) {
533 json_decode( $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ] );
534 if ( json_last_error() === JSON_ERROR_NONE ) {
535 // JSON is valid.
536 $available_backups = json_decode( $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ] );
537 } else {
538 // JSON is invalid treat it as a string.
539 $available_backups = $site_available_backups[ 'mainwp_3rd_party_' . $backup_api . '_available_backups' ];
540 }
541 } else {
542 $available_backups = array();
543 }
544
545 if ( empty( $backup_api ) ) {
546 $title = esc_html__( 'No API Backup Solution has been chosen.', 'mainwp' );
547 /* translators: %1$s: Link to API Backups Settings page, %2$s: Link to Child Site Settings page */
548 $msg_format = __( 'Please double check that you have set the API Key on the %1$s page and have set the Instance ID on the %2$s page.', 'mainwp' );
549 $message = sprintf(
550 $msg_format,
551 '<a href="' . esc_url( admin_url( 'admin.php?page=SettingsApiBackups' ) ) . '">' . esc_html__( 'API Backups Settings', 'mainwp' ) . '</a>',
552 '<a href="' . esc_url( admin_url( 'admin.php?page=managesites&id=' . intval( $website_id ) ) ) . '">' . esc_html__( 'Child Site &rarr; Settings page', 'mainwp' ) . '</a>'
553 );
554 $icon = '<em data-emoji=":closed_lock_with_key:" class="big"></em>';
555 \MainWP\Dashboard\MainWP_UI::render_empty_page_placeholder( $title, $message, $icon );
556 } else {
557 $columns = 'one';
558 if ( 'cpanel' === $backup_api || 'plesk' === $backup_api ) {
559 $columns = 'two';
560 }
561 ?>
562 <div class="mainwp-actions-bar">
563 <div class="ui grid">
564 <div class="ui <?php echo esc_html( $columns ); ?> column row">
565 <div class="middle aligned column ui">
566 <?php if ( 'cpanel' === $backup_api ) : ?>
567 <div id="mainwp_api_cpanel_backup_tabs" class="ui top attached tabular menu">
568 <div class="active item" data-tab="cpanel-native"><i class="fitted cpanel big icon"></i></div>
569 <div class="item" data-tab="cpanel-wp-toolkit"><i class="fitted wordpress big icon"></i></div><?php //phpcs:ignore -- skip wordpress.?>
570 </div>
571 <?php endif; ?>
572 </div>
573 <div class="right aligned middle aligned column">
574 <?php if ( 'cpanel' === $backup_api ) : ?>
575 <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_create_full_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini green button"><?php esc_html_e( 'Backup Files &amp; Database', 'mainwp' ); ?></button>
576 <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_create_wptk_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini green button hidden"><?php esc_html_e( 'Backup Now', 'mainwp' ); ?></button>
577 <?php else : ?>
578 <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_individual_create_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini green button"><?php esc_html_e( 'Backup Now', 'mainwp' ); ?></button>
579 <?php endif; ?>
580 <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_refresh_available_backups" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini green button"><?php esc_html_e( 'Refresh Available Backups', 'mainwp' ); ?></button>
581
582 <?php // Render DigitalOcean specific action buttons. ?>
583 <?php
584 if ( 'digitalocean' === $backup_api ) {
585 // Grab Linode instance id.
586 $digitalocean_droplet_id = Api_Backups_Helper::get_website_options(
587 $website,
588 array(
589 'mainwp_3rd_party_instance_id',
590 )
591 );
592 $droplet_id = isset( $digitalocean_droplet_id['mainwp_3rd_party_instance_id'] ) ? $digitalocean_droplet_id['mainwp_3rd_party_instance_id'] : null;
593 ?>
594 <a href="https://cloud.digitalocean.com/droplets/<?php echo esc_attr( $droplet_id ); ?>/snapshots" target="_blank" class="ui mini button">
595 <i class="external icon"></i>
596 <?php esc_html_e( 'View on DigitalOcean', 'mainwp' ); ?>
597 </a>
598 <?php } ?>
599 <?php // Render Linode specific action buttons. ?>
600 <?php
601 if ( 'linode' === $backup_api ) {
602 // Grab Linode instance id.
603 $linode_instance_id = Api_Backups_Helper::get_website_options(
604 $website,
605 array(
606 'mainwp_3rd_party_instance_id',
607 )
608 );
609 $instance_id = isset( $linode_instance_id['mainwp_3rd_party_instance_id'] ) ? $linode_instance_id['mainwp_3rd_party_instance_id'] : null;
610 ?>
611 <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_cancel_backups" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini button"><?php esc_html_e( 'Disable & Remove Backups on This Linode', 'mainwp' ); ?></button>
612 <a href="https://cloud.linode.com/linodes/<?php echo esc_attr( $instance_id ); ?>/backup" target="_blank" class="ui mini button">
613 <i class="external icon"></i>
614 <?php esc_html_e( 'View on Akamai (Linode)', 'mainwp' ); ?>
615 </a>
616 <?php } ?>
617 <?php // Render Cloudways specific action buttons. ?>
618 <?php
619 if ( 'cloudways' === $backup_api ) {
620 // Grab Cloudways app id.
621 $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_app_id' ) );
622 $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
623 ?>
624 <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui mini button"><?php esc_html_e( 'Delete 24hr Restore Point', 'mainwp' ); ?></button>
625 <a href="https://platform.cloudways.com/apps/<?php echo esc_attr( $app_id ); ?>/restore" target="_blank" class="ui mini button">
626 <i class="external icon"></i>
627 <?php esc_html_e( 'View on Cloudways', 'mainwp' ); ?>
628 </a>
629 <?php } ?>
630 <?php // Render Vultr specific action buttons. ?>
631 <?php
632 if ( 'vultr' === $backup_api ) {
633 // Grab Vultr Instance id.
634 $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_instance_id' ) );
635 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
636 ?>
637 <a href="https://my.vultr.com/subs/?id=<?php echo esc_attr( $instance_id ); ?>#subssnapshots" target="_blank" class="ui mini button">
638 <i class="external icon"></i>
639 <?php esc_html_e( 'View on Vultr', 'mainwp' ); ?>
640 </a>
641 <?php } ?>
642 <?php // Render GridPane specific action buttons. ?>
643 <?php if ( 'gridpane' === $backup_api ) { ?>
644 <a href="https://my.gridpane.com/sites" target="_blank" class="ui mini button">
645 <i class="external icon"></i>
646 <?php esc_html_e( 'View on GridPane', 'mainwp' ); ?>
647 </a>
648 <?php } ?>
649 </div>
650 </div>
651 </div>
652 </div>
653 <div class="ui padded segment">
654
655 <?php // Render action notifications. I get replaced by JS. ?>
656 <div id="mainwp-api-backups-message-zone" class="ui message" style="display: none;">
657 <i class="icon close"></i>
658 <div class="content">
659 <div class="message"></div>
660 </div>
661 </div>
662
663 <?php // Render info notifications. ?>
664 <?php // Render Linode info notifications. ?>
665 <?php if ( 'linode' === $backup_api ) { ?>
666 <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message1' ) ) : ?>
667 <div class="ui info message">
668 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message1"></i>
669 <div><?php esc_html_e( 'Three backup slots are executed and rotated automatically: a daily backup, a 2-7 day old backup, and an 8-14 day old backup. You will need to enable backups on your Akamai (Linode) Instance in order to use this feature.', 'mainwp' ); ?></div>
670 </div>
671 <div class="ui info message">
672 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message1"></i>
673 <div><?php esc_html_e( 'Please note that when you click the Disable & Remove Backups button it cancels the Backup service on the given Linode. Deletes all of this Linode\'s existing backups forever.', 'mainwp' ); ?></div>
674 </div>
675 <?php endif; ?>
676 <?php } ?>
677 <?php if ( 'cloudways' === $backup_api ) { ?>
678 <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message2' ) ) : ?>
679 <div class="ui info message">
680 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message2"></i>
681 <div><?php esc_html_e( ' This page allows you to back up and restore your currently available Cloudways backups.', 'mainwp' ); ?></div>
682 </div>
683 <div class="ui info message">
684 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message2"></i>
685 <p><?php esc_html_e( 'Please note that Cloudways does not allow you to delete individual backups.', 'mainwp' ); ?></p>
686 <p><?php esc_html_e( 'A local copy of your application will be saved automatically before you restore your application using the restore feature.', 'mainwp' ); ?></p>
687 <p><?php esc_html_e( 'To use the restore feature again, you will have to either delete this local copy by clicking the Delete 24hr Restore Point button or roll your application back to the state it was before you restored it via the Cloudways Account UI.', 'mainwp' ); ?></p>
688 <p><?php esc_html_e( 'This local copy is kept for the first 24 hours, after which it is automatically removed.', 'mainwp' ); ?></p>
689 </div>
690 <?php endif; ?>
691 <?php } ?>
692 <?php if ( 'digitalocean' === $backup_api ) { ?>
693 <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message3' ) ) : ?>
694 <div class="ui info message">
695 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message3"></i>
696 <div><?php esc_html_e( ' This page allows you to back up and restore your currently available DigitalOcean backups.', 'mainwp' ); ?></div>
697 </div>
698 <?php endif; ?>
699 <?php } ?>
700 <?php if ( 'gridpane' === $backup_api ) { ?>
701 <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message4' ) ) : ?>
702 <div class="ui info message">
703 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message4"></i>
704 <div><?php esc_html_e( ' This page allows you to back up and restore your currently available GridPane backups.', 'mainwp' ); ?></div>
705 </div>
706 <?php endif; ?>
707 <?php } ?>
708 <?php if ( 'vultr' === $backup_api ) { ?>
709 <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-common-message5' ) ) : ?>
710 <div class="ui info message">
711 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-common-message5"></i>
712 <div><?php esc_html_e( ' This page allows you to back up and restore your currently available Vultr backups.', 'mainwp' ); ?></div>
713 </div>
714 <?php endif; ?>
715 <?php } ?>
716 <?php // Display Kinsta Table. ?>
717 <?php
718 if ( 'kinsta' === $backup_api ) {
719
720 if ( is_object( $available_backups ) ) {
721 $available_backups = $available_backups->environment->backups;
722 } else {
723 $available_backups = array();
724 }
725
726 ?>
727 <?php if ( Api_Backups_Utility::show_mainwp_message( 'mainwp-module-api-backups-info-message' ) ) : ?>
728 <div class="ui info message">
729 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-module-api-backups-info-message"></i>
730 <div><?php esc_html_e( 'You can create up to 5 manual backups. Each manual backup will be stored for 14 days.', 'mainwp' ); ?></div>
731 </div>
732 <?php
733 endif;
734 $el_id_wp_1 = $website['id'];
735 ?>
736 <table id="mainwp-siteid-<?php echo intval( $el_id_wp_1 ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%">
737 <thead>
738 <tr>
739 <th scope="col"><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
740 <th scope="col"><?php esc_html_e( 'Note', 'mainwp' ); ?></th>
741 <th scope="col"><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
742 <th scope="col"><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
743 <th scope="col" class="no-sort collapsing"></th>
744 <th scope="col" class="no-sort collapsing"></th>
745 </tr>
746 </thead>
747 <tbody>
748 <?php foreach ( $available_backups as $backup ) { ?>
749 <?php
750 // Convert Kinsta backup date to human readable format.
751 $backup_date = Api_Backups_Utility::format_timestamp( intval( $backup->created_at / 1000 ) );
752 ?>
753 <tr>
754 <td class="collapsing"><?php echo esc_html( $backup->name ); ?></td>
755 <td class="collapsing"><?php echo esc_html( $backup->note ); ?></td>
756 <td class="collapsing"><?php echo esc_html( $backup->type ); ?></td>
757 <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
758 <td></td>
759 <td class="collapsing right aligned">
760 <button id="kinsta_restore_button" class="ui circular icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup item"
761 website_id="<?php echo intval( $website['id'] ); ?>"
762 backup_id="<?php echo intval( $backup->id ); ?>"
763 data-tooltip="<?php esc_attr_e( 'Restore Backup', 'mainwp' ); ?>"
764 data-inverted=""
765 data-position="top center">
766 <i class="undo icon"></i>
767 </button>
768 <button id="kinsta_delete_button" class="ui circular icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup item"
769 website_id="<?php echo intval( $website['id'] ); ?>"
770 backup_id="<?php echo intval( $backup->id ); ?>"
771 data-tooltip="<?php esc_attr_e( 'Delete Backup', 'mainwp' ); ?>"
772 data-inverted=""
773 data-position="top center">
774 <i class="trash icon"></i>
775 </button>
776 </td>
777 </tr>
778 <?php } ?>
779 </tbody>
780 <tfoot>
781 <tr>
782 <th scope="col"><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
783 <th scope="col"><?php esc_html_e( 'Environment', 'mainwp' ); ?></th>
784 <th scope="col"><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
785 <th scope="col"><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
786 <th scope="col" class="no-sort collapsing"></th>
787 <th scope="col" class="no-sort collapsing"></th>
788 </tr>
789 </tfoot>
790 </table>
791 <div class="ui divider hidden"></div>
792 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
793 <thead>
794 <tr>
795 <th scope="col" colspan="3">
796 <div class="ui equal width grid">
797 <div class="left aligned middle aligned column">
798 <?php esc_html_e( 'Downloadable Backups', 'mainwp' ); ?>
799 </div>
800 </div>
801 </th>
802 </tr>
803 <tr>
804 <th scope="col"><?php esc_html_e( 'Created', 'mainwp' ); ?></th>
805 <th scope="col"><?php esc_html_e( 'Expiry', 'mainwp' ); ?></th>
806 <th scope="col" class="no-sort collapsing"></th>
807 </tr>
808 </thead>
809 <tbody>
810 <?php
811 // Grab Downloadable Backups.
812 $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_kinsta_downloadable_backups' ) );
813 $downloadable_backups = isset( $site_options['mainwp_3rd_party_kinsta_downloadable_backups'] ) ? $site_options['mainwp_3rd_party_kinsta_downloadable_backups'] : '';
814 $downloadable_backups = json_decode( $downloadable_backups );
815 ?>
816 <?php if ( is_object( $downloadable_backups ) ) { ?>
817 <?php foreach ( $downloadable_backups->environment->downloadable_backups as $backup ) { ?>
818 <?php
819
820 // Convert Kinsta backup dates to human readable format.
821 $created_date = Api_Backups_Utility::format_timestamp( intval( $backup->created_at / 1000 ) );
822 $expiry_date = Api_Backups_Utility::format_timestamp( intval( $backup->expires_at / 1000 ) );
823
824 // Check if backup is expired, disable row including download button.
825 if ( intval( $backup->expires_at / 1000 ) > time() ) {
826
827 ?>
828
829 <tr>
830 <td class="collapsing"><?php echo esc_html( $created_date ); ?></td>
831 <td class="collapsing"><?php echo esc_html( $expiry_date ); ?></td>
832 <td>
833 <a class="kinsta_download" href="<?php echo esc_attr( $backup->download_link ); ?>" target="_blank">
834 <button class="ui right labeled icon button">
835 <i class="right download icon"></i>
836 <?php echo esc_html__( 'Download', 'mainwp' ); ?>
837 </button>
838 </a>
839 </td>
840 </tr>
841 <?php } else { ?>
842 <tr class="disabled">
843 <td class="collapsing"><?php echo esc_html( $created_date ); ?></td>
844 <td class="collapsing"><?php echo esc_html( $expiry_date ); ?></td>
845 <td>
846 <a class="kinsta_download" href="<?php echo esc_attr( $backup->download_link ); ?>" target="_blank">
847 <button class="ui right labeled icon button disabled">
848 <i class="right download icon"></i>
849 <?php echo esc_html__( 'Download', 'mainwp' ); ?>
850 </button>
851 </a>
852 </td>
853 </tr>
854 <?php } ?>
855 <?php } ?>
856 <?php } ?>
857 </tbody>
858 <tfoot>
859 <tr>
860 <th scope="col"><?php esc_html_e( 'Created', 'mainwp' ); ?></th>
861 <th scope="col"><?php esc_html_e( 'Expiry', 'mainwp' ); ?></th>
862 <th scope="col" class="no-sort collapsing"></th>
863 </tr>
864 </tfoot>
865 </table>
866 <?php } ?>
867 <?php // Display Plesk Table. ?>
868 <?php
869 if ( 'plesk' === $backup_api ) {
870 // Grab available cPanel Automatic Backups or set to empty array.
871 if ( is_object( $available_backups ) && isset( $available_backups->value ) ) {
872 $available_backups = $available_backups->value;
873 } else {
874 $available_backups = array();
875 }
876 ?>
877 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
878 <thead>
879 <tr>
880 <th scope="col"><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
881 <th scope="col"><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
882 <th scope="col" class="no-sort collapsing"></th>
883 <th scope="col" class="no-sort collapsing"></th>
884 </tr>
885 </thead>
886 <tbody>
887 <?php foreach ( $available_backups as $backup ) { ?>
888 <?php
889 $backup_date = gmdate( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $backup->value->createdAt->value ) );
890
891 $opts = Api_Backups_Helper::get_website_options(
892 $website['id'],
893 array(
894 'mainwp_plesk_installation_id', // Plesk installation id.
895 )
896 );
897
898 if ( is_array( $opts ) ) {
899 $installation_id = $opts['mainwp_plesk_installation_id'] ?? '';
900 }
901 ?>
902 <tr>
903 <td class="collapsing"><?php echo esc_html( $backup->value->fileName->value ); ?></td>
904 <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
905 <td></td>
906 <td class="collapsing right aligned">
907 <button id="plesk_restore_button" class="ui circular mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup item"
908 installation_id="<?php echo intval( $installation_id ); ?>"
909 website_id="<?php echo intval( $website['id'] ); ?>"
910 backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
911 data-tooltip="<?php esc_attr_e( 'Restore Backup', 'mainwp' ); ?>"
912 data-inverted=""
913 data-position="top center">
914 <i class="undo icon"></i>
915 </button>
916 <?php
917 /**
918 * Grab installation domain & build path to download.
919 * Eg.: /var/www/vhosts/example.com/wordpress-backups/
920 */
921 $installation_domain = static::get_plesk_home_dir();
922 $dirdl = '/var/www/vhosts/' . $installation_domain . '/wordpress-backups/';
923 ?>
924
925 <a id="plesk_download_button" class="ui circular mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_downlaod_backup item"
926 installation_id="<?php echo intval( $installation_id ); ?>"
927 website_id="<?php echo intval( $website['id'] ); ?>"
928 backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
929 href="<?php MainWP_Site_Open::get_open_site_admin_link( $website['id'], true ); //phpcs:ignore -- ok. ?>&dirdl=<?php echo esc_attr( rawurlencode( $dirdl ) ); ?>&filedl=<?php echo esc_attr( rawurlencode( $backup->value->fileName->value ) ); ?>"
930 data-tooltip="<?php esc_attr_e( 'Download Backup', 'mainwp' ); ?>"
931 data-inverted=""
932 data-position="top center"
933 target="_blank">
934 <i class="download icon"></i>
935 </a>
936 <button id="plesk_delete_button" class="ui circular mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup item"
937 installation_id="<?php echo intval( $installation_id ); ?>"
938 website_id="<?php echo intval( $website['id'] ); ?>"
939 backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
940 data-tooltip="<?php esc_attr_e( 'Delete Backup', 'mainwp' ); ?>"
941 data-inverted=""
942 data-position="top center">
943 <i class="trash icon"></i>
944 </button>
945 </td>
946 </tr>
947 <?php } ?>
948 </tbody>
949 <tfoot>
950 <tr>
951 <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
952 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
953 <th scope="col" class="no-sort collapsing"></th>
954 <th scope="col" class="no-sort collapsing"></th>
955 </tr>
956 </tfoot>
957 </table>
958 <?php } ?>
959 <?php // Display cPanel Table. ?>
960 <?php
961 if ( 'cpanel' === $backup_api ) {
962
963 // Grab available cPanel Automatic Backups or set to empty array.
964 if ( is_object( $available_backups ) && isset( $available_backups->data ) ) {
965 $available_backups_automatic_list = $available_backups->data;
966 } else {
967 $available_backups_automatic_list = array();
968 }
969
970 // Grab available cPanel Manual Backups.
971 $available_backups_manual_list = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ) );
972
973 // Check if valid JSON or not. If not, then it's a string - do not decode it.
974 if ( isset( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] ) && ! empty( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] ) ) {
975 json_decode( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] );
976 if ( json_last_error() === JSON_ERROR_NONE ) {
977 // JSON is valid.
978 $available_backups_manual_list = json_decode( $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ] );
979 } else {
980 // JSON is invalid treat it as a string.
981 $available_backups_manual_list = $available_backups_manual_list[ 'mainwp_3rd_party_' . $backup_api . '_manual_backups' ];
982 }
983 } else {
984 $available_backups_manual_list = array();
985 }
986
987 // Grab available cPanel Manual Database Backups.
988 $mainwp_3rd_party_cpanel_manual_database_backups = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ) );
989
990 // Check if valid JSON or not. If not, then it's a string - do not decode it.
991 if ( isset( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] ) && ! empty( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] ) ) {
992 json_decode( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] );
993 if ( json_last_error() === JSON_ERROR_NONE ) {
994 // JSON is valid.
995 $available_manual_database_backups = json_decode( $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ] );
996 } else {
997 // JSON is invalid treat it as a string.
998 $available_manual_database_backups = $mainwp_3rd_party_cpanel_manual_database_backups[ 'mainwp_3rd_party_' . $backup_api . '_manual_database_backups' ];
999 }
1000 } else {
1001 $available_manual_database_backups = array();
1002 }
1003 ?>
1004 <div class="ui bottom attached active tab" data-tab="cpanel-native">
1005 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1006 <thead>
1007 <tr>
1008 <th scope="col" colspan="4">
1009 <?php esc_html_e( 'Automatic Host Backups', 'mainwp' ); ?>
1010 </th>
1011 </tr>
1012 <tr>
1013 <th scope="col"><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1014 <th scope="col"><?php esc_html_e( 'Backup Type', 'mainwp' ); ?></th>
1015 <th scope="col"><?php esc_html_e( 'Site Path', 'mainwp' ); ?></th>
1016 <th scope="col" class="no-sort collapsing"></th>
1017 </tr>
1018 </thead>
1019 <tbody>
1020 <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
1021 <tr>
1022 <td><?php echo esc_html( $backup->backupID ); ?></td>
1023 <td><?php echo esc_html( ucfirst( $backup->backupType ) ); ?></td>
1024 <td><?php echo esc_html( $backup->path ); ?></td>
1025 <td>
1026 <a id="cpanel_automatic_backup_button" class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup item"
1027 website_id="<?php echo intval( $website['id'] ); ?>"
1028 backup_type="<?php echo esc_attr( 'automatic' ); ?>"
1029 backup_path="<?php echo esc_attr( $backup->path ); ?>"
1030 backup_name="<?php echo esc_attr( $backup->backupID ); ?>"
1031 href="javascript:void(0)">
1032 <button class="ui right labeled icon button">
1033 <i class="right undo icon"></i>
1034 <?php esc_html_e( 'Restore', 'mainwp' ); ?>
1035 </button>
1036 </a>
1037 </td>
1038 </tr>
1039 <?php } ?>
1040 </tbody>
1041 <tfoot>
1042 <tr>
1043 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1044 <th scope="col" ><?php esc_html_e( 'Backup Type', 'mainwp' ); ?></th>
1045 <th scope="col" ><?php esc_html_e( 'Site Path', 'mainwp' ); ?></th>
1046 <th scope="col" class="no-sort collapsing"></th>
1047 </tr>
1048 </tfoot>
1049 </table>
1050 <div class="ui divider hidden"></div>
1051 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1052 <thead>
1053 <tr>
1054 <th scope="col" colspan="3">
1055 <div class="ui equal width grid">
1056 <div class="left aligned middle aligned column">
1057 <?php esc_html_e( 'Manual Account Backups', 'mainwp' ); ?>
1058 </div>
1059 <div class="right aligned middle aligned column">
1060 <?php
1061 $el_id_cp_api = $backup_api;
1062 ?>
1063 <button id="mainwp_3rd_party_api_<?php echo esc_attr( $el_id_cp_api ); ?>_action_individual_create_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui primary elastic green button"><?php esc_html_e( 'Backup', 'mainwp' ); ?></button>
1064 </div>
1065 </div>
1066 </th>
1067 </tr>
1068 <tr>
1069 <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1070 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1071 <th scope="col" class="no-sort collapsing"></th>
1072 </tr>
1073 </thead>
1074 <tbody>
1075 <?php foreach ( $available_backups_manual_list as $backup ) { ?>
1076 <?php
1077 $my_unix_timestamp = $backup->timestamp;
1078 $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
1079 ?>
1080 <tr>
1081 <td class="collapsing"><?php echo esc_html( $backup->file_name ); ?></td>
1082 <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
1083 <td>
1084 <?php
1085 $file_path = $backup->absolute_dir . '/';
1086 ?>
1087 <a class="open_newwindow_wpadmin" href="<?php MainWP_Site_Open::get_open_site_admin_link( $website['id'], true ); //phpcs:ignore -- ok. ?>&dirdl=<?php echo esc_attr( rawurlencode( $file_path ) ); ?>&filedl=<?php echo esc_attr( rawurlencode( $backup->file_name ) ); ?>" target="_blank">
1088 <button class="ui right labeled icon button">
1089 <i class="right download icon"></i>
1090 <?php echo esc_html__( 'Download', 'mainwp' ); ?>
1091 </button>
1092 </a>
1093 </td>
1094 </tr>
1095 <?php } ?>
1096 </tbody>
1097 <tfoot>
1098 <tr>
1099 <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1100 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1101 <th scope="col" class="no-sort collapsing"></th>
1102 </tr>
1103 </tfoot>
1104 </table>
1105 <div class="ui divider hidden"></div>
1106 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1107 <thead>
1108 <tr>
1109 <th scope="col" colspan="3">
1110 <div class="ui equal width grid">
1111 <div class="left aligned middle aligned column">
1112 <?php esc_html_e( 'Manual Database Backups', 'mainwp' ); ?>
1113 </div>
1114 <div class="right aligned middle aligned column">
1115 <button id="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_create_database_backup" website_id="<?php echo intval( $website['id'] ); ?>" class="ui primary elastic green button"><?php esc_html_e( 'Backup', 'mainwp' ); ?></button>
1116 </div>
1117 </div>
1118 </th>
1119 </tr>
1120 <tr>
1121 <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1122 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1123 <th scope="col" class="no-sort collapsing"></th>
1124 </tr>
1125 </thead>
1126 <tbody>
1127 <?php foreach ( $available_manual_database_backups as $backup ) { ?>
1128 <?php
1129 $my_unix_timestamp = $backup->timestamp;
1130 $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
1131 ?>
1132 <tr>
1133 <td class="collapsing"><?php echo esc_html( $backup->file_name ); ?></td>
1134 <td class="collapsing"><?php echo esc_html( $backup_date ); ?></td>
1135 <td>
1136 <a id="database_backup_button" class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_database_backup item"
1137 website_id="<?php echo intval( $website['id'] ); ?>"
1138 backup_path="<?php echo esc_attr( $backup->absolute_dir ); ?>"
1139 backup_name="<?php echo esc_attr( $backup->file_name ); ?>"
1140 href="javascript:void(0)">
1141 <button class="ui right labeled icon button">
1142 <i class="right undo icon"></i>
1143 <?php esc_html_e( 'Restore', 'mainwp' ); ?>
1144 </button>
1145 </a>
1146 </td>
1147 </tr>
1148 <?php } ?>
1149 </tbody>
1150 <tfoot>
1151 <tr>
1152 <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1153 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1154 <th scope="col" class="no-sort collapsing"></th>
1155 </tr>
1156 </tfoot>
1157 </table>
1158 </div>
1159 <div class="ui bottom attached tab" data-tab="cpanel-wp-toolkit">
1160 <?php
1161 $available_wptk_backups = array();
1162 /**
1163 * Grab WP-Toolkit status & available backups.
1164 */
1165 $mainwp_enable_wp_toolkit = '0'; // Default to false.
1166
1167 if ( is_array( $website ) && key_exists( 'id', $website ) ) {
1168 // Grab given website options.
1169 $opts = Api_Backups_Helper::get_website_options(
1170 $website['id'],
1171 array(
1172 'mainwp_enable_wp_toolkit', // WP-Toolkit status.
1173 'mainwp_3rd_party_cpanel_wp_toolkit_backups', // WP-Toolkit backups.
1174 )
1175 );
1176
1177 if ( is_array( $opts ) ) {
1178 // Grab WP-Toolkit status.
1179 $mainwp_enable_wp_toolkit = $opts['mainwp_enable_wp_toolkit'] ?? '0';
1180
1181 // Grab WP-Toolkit backups.
1182 $cpanel_wp_toolkit_backups = ! empty( $opts['mainwp_3rd_party_cpanel_wp_toolkit_backups'] ) ? json_decode( $opts['mainwp_3rd_party_cpanel_wp_toolkit_backups'] ) : false;
1183 $available_wptk_backups = is_object( $cpanel_wp_toolkit_backups ) && ! empty( $cpanel_wp_toolkit_backups->value ) ? $cpanel_wp_toolkit_backups->value : false;
1184 }
1185 }
1186 ?>
1187 <?php if ( $mainwp_enable_wp_toolkit ) : // Display WP-Toolkit Table if enabled. ?>
1188 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-wptk-table" class="ui mainwp-api-backup-table table" style="width:100%">
1189 <thead>
1190 <tr>
1191 <th scope="col" colspan="4">
1192 <?php esc_html_e( 'WP Toolkit Backups', 'mainwp' ); ?>
1193 </th>
1194 </tr>
1195 <tr>
1196 <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1197 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1198 <th scope="col" class="no-sort collapsing"></th>
1199 <th scope="col" class="no-sort collapsing"></th>
1200 </tr>
1201 </thead>
1202 <tbody>
1203 <?php
1204 if ( ! is_array( $available_wptk_backups ) ) {
1205 $available_wptk_backups = array();
1206 }
1207 foreach ( $available_wptk_backups as $backup ) {
1208 ?>
1209 <?php
1210 $my_unix_timestamp = strtotime( $backup->value->createdAt->value );
1211 $backup_date = get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $my_unix_timestamp ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
1212 ?>
1213 <tr>
1214 <td class=""><?php echo esc_html( $backup->value->fileName->value ); ?></td>
1215 <td class=""><?php echo esc_html( $backup_date ); ?></td>
1216 <td></td>
1217 <td class="right aligned">
1218 <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_wptk_backup item"
1219 website_id="<?php echo intval( $website['id'] ); ?>"
1220 backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
1221 data-tooltip="<?php esc_attr_e( 'Restore Backup', 'mainwp' ); ?>"
1222 data-inverted=""
1223 data-position="top center">
1224 <i class="undo icon"></i>
1225 </button>
1226 <?php
1227 /**
1228 * Grab home directory & build download directory.
1229 * Eg.: /home/cpanel_username/wordpress-backups/
1230 */
1231 $home_dir = static::cpanel_action_get_home_directory();
1232 $dirdl = $home_dir . '/wordpress-backups/';
1233 ?>
1234 <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_download_wptk_backup item"
1235 website_id="<?php echo intval( $website['id'] ); ?>"
1236 backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
1237 href="<?php MainWP_Site_Open::get_open_site_admin_link( $website['id'], true ); //phpcs:ignore -- ok. ?>&dirdl=<?php echo esc_attr( rawurlencode( $dirdl ) ); ?>&filedl=<?php echo esc_attr( rawurlencode( $backup->value->fileName->value ) ); ?>"
1238 data-tooltip="<?php esc_attr_e( 'Download Backup', 'mainwp' ); ?>"
1239 data-inverted=""
1240 data-position="top center">
1241 <i class="download icon"></i>
1242 </button>
1243 <button class="ui mini icon button mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_wptk_backup item"
1244 website_id="<?php echo intval( $website['id'] ); ?>"
1245 backup_name="<?php echo esc_attr( $backup->value->fileName->value ); ?>"
1246 data-tooltip="<?php esc_attr_e( 'Delete Backup', 'mainwp' ); ?>"
1247 data-inverted=""
1248 data-position="top center">
1249 <i class="trash icon"></i>
1250 </button>
1251 </td>
1252 </tr>
1253 <?php } ?>
1254 </tbody>
1255 <tfoot>
1256 <tr>
1257 <th scope="col" ><?php esc_html_e( 'Backup Name', 'mainwp' ); ?></th>
1258 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1259 <th scope="col" class="no-sort collapsing"></th>
1260 <th scope="col" class="no-sort collapsing"></th>
1261 </tr>
1262 </tfoot>
1263 </table>
1264 <?php else : // Display message if WP-Toolkit is not enabled. ?>
1265 <?php
1266 $title = esc_html__( 'The WP-Toolkit API has not been enabled.', 'mainwp' );
1267 $message = esc_html__( 'Please double check that you have set the cPanel API Key on the API Backups Settings page and have enabled the WP Toolkit API on the Child Site -> Edit page.', 'mainwp' );
1268 $icon = '<em data-emoji=":closed_lock_with_key:" class="big"></em>';
1269 \MainWP\Dashboard\MainWP_UI::render_empty_page_placeholder( $title, $message, $icon );
1270 ?>
1271 <?php endif; ?>
1272 </div>
1273 <?php } ?>
1274 <?php // Display GridPane Table. ?>
1275 <?php
1276 if ( 'gridpane' === $backup_api ) {
1277 if ( isset( $available_backups->automatic ) ) {
1278 $available_backups_automatic_list = explode( ',', $available_backups->automatic );
1279 } else {
1280 $available_backups_automatic_list = array();
1281 }
1282 if ( isset( $available_backups->manual ) ) {
1283 $available_backups_manual_list = explode( ',', $available_backups->manual );
1284 } else {
1285 $available_backups_manual_list = array();
1286 }
1287 ?>
1288 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1289 <thead>
1290 <tr>
1291 <th scope="col" ><?php esc_html_e( 'GridPane Backup Name', 'mainwp' ); ?></th>
1292 <th scope="col" ><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
1293 <th scope="col" class="no-sort collapsing"></th>
1294 <th scope="col" class="no-sort collapsing"></th>
1295 </tr>
1296 </thead>
1297 <tbody>
1298 <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
1299 <tr>
1300 <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup ); ?></td>
1301 <td><?php esc_html_e( 'Automatic', 'mainwp' ); ?></td>
1302 <td></td>
1303 <td class="collapsing right aligned">
1304 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1305 website_id="<?php echo intval( $website['id'] ); ?>"
1306 backup_type="<?php echo esc_attr( 'automatic' ); ?>"
1307 backup_name="<?php echo esc_attr( $backup ); ?>"
1308 href="javascript:void(0)">
1309 <i class="undo icon"></i>
1310 </a>
1311 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1312 website_id="<?php echo intval( $website['id'] ); ?>"
1313 backup_type="<?php echo esc_attr( 'automatic' ); ?>"
1314 backup_name="<?php echo esc_attr( $backup ); ?>"
1315 href="javascript:void(0)">
1316 <i class="trash icon"></i>
1317 </a>
1318 </td>
1319 </tr>
1320 <?php } ?>
1321 <?php foreach ( $available_backups_manual_list as $backup ) { ?>
1322 <tr>
1323 <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup ); ?></td>
1324 <td><?php esc_html_e( 'Manual', 'mainwp' ); ?></td>
1325 <td></td>
1326 <td class="collapsing right aligned">
1327 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1328 website_id="<?php echo intval( $website['id'] ); ?>"
1329 backup_type="<?php echo esc_attr( 'manual' ); ?>"
1330 backup_name="<?php echo esc_attr( $backup ); ?>"
1331 href="javascript:void(0)">
1332 <i class="undo icon"></i>
1333 </a>
1334 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1335 website_id="<?php echo intval( $website['id'] ); ?>"
1336 backup_type="<?php echo esc_attr( 'manual' ); ?>"
1337 backup_name="<?php echo esc_attr( $backup ); ?>"
1338 href="javascript:void(0)">
1339 <i class="trash icon"></i>
1340 </a>
1341 </td>
1342 </tr>
1343 <?php } ?>
1344 </tbody>
1345 <tfoot>
1346 <tr>
1347 <th scope="col" ><?php esc_html_e( 'GridPane Backup Name', 'mainwp' ); ?></th>
1348 <th scope="col" ><?php esc_html_e( 'Type', 'mainwp' ); ?></th>
1349 <th scope="col" class="no-sort collapsing"></th>
1350 <th scope="col" class="no-sort collapsing"></th>
1351 </tr>
1352 </tfoot>
1353 </table>
1354 <?php } ?>
1355 <?php // Display Cloudways Table. ?>
1356 <?php
1357 if ( 'cloudways' === $backup_api ) {
1358
1359 // Check if backups are available.
1360 if ( isset( $available_backups->application_backup_exists ) && true === $available_backups->application_backup_exists ) {
1361 $available_backups = $available_backups->backup_dates;
1362 } else {
1363 $available_backups = array();
1364 }
1365
1366 ?>
1367 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1368 <thead>
1369 <tr>
1370 <th scope="col" ><?php esc_html_e( 'Cloudways Backup Type', 'mainwp' ); ?></th>
1371 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1372 <th scope="col" class="no-sort collapsing"></th>
1373 <th scope="col" class="no-sort collapsing"></th>
1374 </tr>
1375 </thead>
1376 <tbody>
1377 <?php foreach ( $available_backups as $backup ) { ?>
1378 <tr>
1379 <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php esc_html_e( 'Application Backup', 'mainwp' ); ?></td>
1380 <td><?php echo esc_html( gmdate( 'm-d-Y ( h:i:s )', strtotime( $backup ) ) ); ?></td>
1381 <td></td>
1382 <td>
1383 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button" website_id="<?php echo intval( $website['id'] ); ?>" backup_date="<?php echo esc_attr( $backup ); ?>" href="javascript:void(0)"><i class="undo icon"></i></a>
1384 </td>
1385 </tr>
1386 <?php } ?>
1387 </tbody>
1388 <tfoot>
1389 <tr>
1390 <th scope="col" ><?php esc_html_e( 'Cloudways Backup Type', 'mainwp' ); ?></th>
1391 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1392 <th scope="col" class="no-sort collapsing"></th>
1393 <th scope="col" class="no-sort collapsing"></th>
1394 </tr>
1395 </tfoot>
1396 </table>
1397 <?php } ?>
1398 <?php // Display Vultr Table. ?>
1399 <?php
1400 if ( 'vultr' === $backup_api ) {
1401 if ( isset( $available_backups->snapshots ) ) {
1402 $available_snapshots_list = $available_backups->snapshots;
1403 } else {
1404 $available_snapshots_list = array();
1405 }
1406 if ( isset( $available_backups->backups ) ) {
1407 $available_backups_list = $available_backups->backups;
1408 } else {
1409 $available_backups_list = array();
1410 }
1411 ?>
1412 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1413 <thead>
1414 <tr>
1415 <th scope="col" ><?php esc_html_e( 'Vultr Backup Label', 'mainwp' ); ?></th>
1416 <th scope="col" ><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1417 <th scope="col" ><?php esc_html_e( 'Compressed Size', 'mainwp' ); ?></th>
1418 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1419 <th scope="col" ><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1420 <th scope="col" class="no-sort collapsing"></th>
1421 <th scope="col" class="no-sort collapsing"></th>
1422 </tr>
1423 </thead>
1424 <tbody>
1425 <?php
1426 foreach ( $available_snapshots_list as $backup ) {
1427 if ( empty( $backup ) || ! is_object( $backup ) || empty( $backup->date_created ) ) {
1428 continue;
1429 }
1430 ?>
1431 <tr>
1432 <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->description ); ?></td>
1433 <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->size ) ); ?></td>
1434 <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->compressed_size ) ); ?></td>
1435 <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->date_created ) ) ); ?></td>
1436 <td><?php echo esc_html( $backup->status ); ?></td>
1437 <td></td>
1438 <td class="collapsing right aligned">
1439 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button" website_id="<?php echo intval( $website['id'] ); ?>" snapshot_id="<?php echo esc_attr( $backup->id ); ?>" href="javascript:void(0)"><i class="undo icon"></i></a>
1440 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button" website_id="<?php echo intval( $website['id'] ); ?>" snapshot_id="<?php echo esc_attr( $backup->id ); ?>" href="javascript:void(0)"><i class="trash icon"></i></a>
1441 </td>
1442 </tr>
1443 <?php } ?>
1444 <?php
1445 foreach ( $available_backups_list as $backup ) {
1446 if ( empty( $backup ) || ! is_object( $backup ) || empty( $backup->date_created ) ) {
1447 continue;
1448 }
1449 ?>
1450 <tr>
1451 <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->description ); ?></td>
1452 <td><?php echo esc_html( Api_Backups_Utility::human_filesize( $backup->size ) ); ?></td>
1453 <td><?php esc_html_e( 'N/A', 'mainwp' ); ?></td>
1454 <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->date_created ) ) ); ?></td>
1455 <td><?php echo esc_html( $backup->status ); ?></td>
1456 <td></td>
1457 <td class="collapsing right aligned">
1458 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1459 website_id="<?php echo intval( $website['id'] ); ?>"
1460 snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1461 href="javascript:void(0)">
1462 <i class="undo icon"></i>
1463 </a>
1464 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1465 website_id="<?php echo intval( $website['id'] ); ?>"
1466 snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1467 href="javascript:void(0)">
1468 <i class="trash icon"></i>
1469 </a>
1470 </td>
1471 </tr>
1472 <?php } ?>
1473 </tbody>
1474 <tfoot>
1475 <tr>
1476 <th scope="col" ><?php esc_html_e( 'Vultr Backup Label', 'mainwp' ); ?></th>
1477 <th scope="col" ><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1478 <th scope="col" ><?php esc_html_e( 'Compressed Size', 'mainwp' ); ?></th>
1479 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1480 <th scope="col" ><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1481 <th scope="col" class="no-sort collapsing"></th>
1482 <th scope="col" class="no-sort collapsing"></th>
1483 </tr>
1484 </tfoot>
1485 </table>
1486 <?php } ?>
1487 <?php // Display Linode Table. ?>
1488 <?php
1489 if ( 'linode' === $backup_api ) {
1490
1491 // Automatic Backups.
1492 if ( isset( $available_backups->automatic ) ) {
1493 $available_backups_automatic_list = $available_backups->automatic;
1494 } else {
1495 $available_backups_automatic_list = array();
1496 }
1497
1498 // Manual Backups.
1499 if ( isset( $available_backups->snapshot ) ) {
1500 $available_backups_snapshot_list = $available_backups->snapshot;
1501 } else {
1502 $available_backups_snapshot_list = array();
1503 }
1504 ?>
1505 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1506 <thead>
1507 <tr>
1508 <th scope="col" ><?php esc_html_e( 'Akamai (Linode) Backup Type', 'mainwp' ); ?></th>
1509 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1510 <th scope="col" ><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1511 <th scope="col" class="no-sort collapsing"></th>
1512 <th scope="col" class="no-sort collapsing"></th>
1513 <th scope="col" class="no-sort collapsing"></th>
1514 </tr>
1515 </thead>
1516 <tbody>
1517 <?php foreach ( $available_backups_automatic_list as $backup ) { ?>
1518 <tr>
1519 <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->type ); ?></td>
1520 <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created ) ) ); ?></td>
1521 <td class="operation_status"><?php echo esc_html( $backup->status ); ?></td>
1522 <td></td>
1523 <td></td>
1524 <td>
1525 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1526 website_id="<?php echo intval( $website['id'] ); ?>"
1527 backup_type="<?php echo esc_attr( $backup->type ); ?>"
1528 backup_id="<?php echo esc_attr( $backup->id ); ?>"
1529 href="javascript:void(0)">
1530 <i class="undo icon"></i>
1531 </a>
1532 </td>
1533 </tr>
1534 <?php } ?>
1535 <?php foreach ( $available_backups_snapshot_list as $backup ) { ?>
1536 <?php if ( null !== $backup ) { ?>
1537 <tr>
1538 <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->type ); ?></td>
1539 <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created ) ) ); ?></td>
1540 <td><?php echo esc_html( $backup->status ); ?></td>
1541 <td></td>
1542 <td></td>
1543 <td>
1544
1545 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1546 website_id="<?php echo intval( $website['id'] ); ?>"
1547 backup_type="<?php echo esc_attr( $backup->type ); ?>"
1548 backup_id="<?php echo esc_attr( $backup->id ); ?>"
1549 href="javascript:void(0)">
1550 <i class="undo icon"></i>
1551 </a>
1552 </td>
1553 </tr>
1554 <?php } ?>
1555 <?php } ?>
1556 </tbody>
1557 <tfoot>
1558 <tr>
1559 <th scope="col" ><?php esc_html_e( 'Akamai (Linode) Backup Type', 'mainwp' ); ?></th>
1560 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1561 <th scope="col" ><?php esc_html_e( 'Status', 'mainwp' ); ?></th>
1562 <th scope="col" class="no-sort collapsing"></th>
1563 <th scope="col" class="no-sort collapsing"></th>
1564 <th scope="col" class="no-sort collapsing"></th>
1565 </tr>
1566 </tfoot>
1567 </table>
1568 <?php } ?>
1569 <?php // Display DigitalOcean Table. ?>
1570 <?php
1571 if ( 'digitalocean' === $backup_api ) {
1572 if ( isset( $available_backups->snapshots ) ) {
1573 $available_backups = $available_backups->snapshots;
1574 }
1575 if ( ! is_array( $available_backups ) ) {
1576 $available_backups = array();
1577 }
1578 ?>
1579 <table id="mainwp-siteid-<?php echo intval( $website['id'] ); ?>-table" class="ui mainwp-api-backup-table table" style="width:100%"> <?php // NOSONAR - id ok. ?>
1580 <thead>
1581 <tr>
1582 <th scope="col" ><?php esc_html_e( 'DigitalOcean Backup Label', 'mainwp' ); ?></th>
1583 <th scope="col" ><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1584 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1585 <th scope="col" class="no-sort collapsing"></th>
1586 <th scope="col" class="no-sort collapsing"></th>
1587 </tr>
1588 </thead>
1589 <tbody>
1590 <?php foreach ( $available_backups as $backup ) { ?>
1591 <tr>
1592 <td><i class="ui notched circle loading icon" style="display:none;"></i> <?php echo esc_html( $backup->name ); ?></td>
1593 <td><?php echo intval( $backup->size_gigabytes ); ?>GB</td>
1594 <td><?php echo esc_html( Api_Backups_Utility::format_timestamp( strtotime( $backup->created_at ) ) ); ?></td>
1595 <td></td>
1596 <td class="collapsing right aligned">
1597 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_restore_backup ui mini icon button"
1598 website_id="<?php echo intval( $website['id'] ); ?>"
1599 snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1600 href="javascript:void(0)">
1601 <i class="undo icon"></i>
1602 </a>
1603 <a class="mainwp_3rd_party_api_<?php echo esc_attr( $backup_api ); ?>_action_delete_backup ui mini icon button"
1604 website_id="<?php echo intval( $website['id'] ); ?>"
1605 snapshot_id="<?php echo esc_attr( $backup->id ); ?>"
1606 href="javascript:void(0)">
1607 <i class="trash icon"></i>
1608 </a>
1609 </td>
1610 </tr>
1611 <?php } ?>
1612 </tbody>
1613 <tfoot>
1614 <tr>
1615 <th scope="col" ><?php esc_html_e( 'DigitalOcean Backup Label', 'mainwp' ); ?></th>
1616 <th scope="col" ><?php esc_html_e( 'Size', 'mainwp' ); ?></th>
1617 <th scope="col" ><?php esc_html_e( 'Date Created', 'mainwp' ); ?></th>
1618 <th scope="col" class="no-sort collapsing"></th>
1619 <th scope="col" class="no-sort collapsing"></th>
1620 </tr>
1621 </tfoot>
1622 </table>
1623 <?php } ?>
1624
1625 </div>
1626 <script type="text/javascript">
1627 let responsive = true;
1628 if ( jQuery( window ).width() > 1140 ) {
1629 responsive = false;
1630 }
1631 jQuery( document ).ready( function() {
1632
1633 jQuery( '.mainwp-api-backup-table' ).DataTable( {
1634 "stateSave": true,
1635 "stateDuration": 0,
1636 "colReorder" : {columns:":not(.check-column):not(:last-child)"},
1637 "responsive": responsive,
1638 "scrollX": false,
1639 "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
1640 "columnDefs": [ { "targets": 'no-sort', "orderable": false } ],
1641 "order": [ [ 1, "asc" ] ],
1642 "language": { "emptyTable": "No backups found." },
1643 "drawCallback": function( settings ) {
1644 setTimeout(() => {
1645 jQuery('.mainwp-api-backup-table .ui.checkbox').checkbox();
1646 jQuery('.mainwp-api-backup-table .ui.dropdown').dropdown();
1647 mainwp_datatable_fix_menu_overflow('.mainwp-api-backup-table', -55, 10 );
1648 }, 1000);
1649 }
1650 } ).on( 'columns-reordered', function () {
1651 setTimeout(() => {
1652 jQuery( '.mainwp-api-backup-table .ui.dropdown' ).dropdown();
1653 jQuery( '.mainwp-api-backup-table .ui.checkbox' ).checkbox();
1654 mainwp_datatable_fix_menu_overflow('.mainwp-api-backup-table', -55, 10 );
1655 mainwp_table_check_columns_init(); // ajax: to fix checkbox all.
1656 }, 1000);
1657 });
1658 } );
1659 </script>
1660 <?php
1661 } // END if.
1662 }
1663
1664 /**
1665 * Fetch Cloudways oAuth Access Token.
1666 *
1667 * Fetch the Cloudways oAuth access token from the given API credentials.
1668 *
1669 * @return mixed Return Cloudways Access Token.
1670 */
1671 public static function get_saved_v2_access_token() {
1672 if ( null === static::$access_token ) {
1673 static::$access_token = self::get_cloudways_access_token();
1674 }
1675 return static::$access_token;
1676 }
1677 /**
1678 * Fetch Cloudways oAuth Access Token.
1679 *
1680 * Fetch the Cloudways oAuth access token from the given API credentials.
1681 *
1682 * @return mixed Return Cloudways Access Token.
1683 */
1684 public static function is_access_token_v2() {
1685 return ! empty( self::get_saved_v2_access_token() );
1686 }
1687
1688 /*********************************************************************************
1689 * Cloudways API Methods.
1690 **********************************************************************************/
1691
1692 /**
1693 * Call Cloudways API, Authenticate & perform given method.
1694 *
1695 * Use this function to contact CW API
1696 * We use OAuth, an open standard for authorization. Here are the steps involved:
1697 * 1. Get your API Key from here: https://platform.cloudways.com/api
1698 * 2. Enter in your account email address and API Key below.
1699 *
1700 * @param string $method GET|POST|PUT|DELETE.
1701 * @param string $url relative URL for the call.
1702 * @param array $post Optional post data for the call.
1703 * @return object|false Output from CW API.
1704 */
1705 public static function call_cloudways_api_v2( $method, $url, $post = array() ) {
1706
1707 $access_token = self::get_saved_v2_access_token();
1708
1709 $ch = curl_init();
1710
1711 curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $method );
1712 curl_setopt( $ch, CURLOPT_URL, self::CLOUDWAYS_API_URL . $url );
1713 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
1714
1715 curl_setopt(
1716 $ch,
1717 CURLOPT_HTTPHEADER,
1718 array(
1719 'Authorization: Bearer ' . $access_token,
1720 'Accept: application/json',
1721 )
1722 );
1723
1724 // Set Post Parameters.
1725 $encoded = '';
1726 if ( count( $post ) ) {
1727 foreach ( $post as $name => $value ) {
1728 $encoded .= rawurlencode( $name ) . '=' . rawurlencode( $value ) . '&';
1729 }
1730
1731 $encoded = substr( $encoded, 0, strlen( $encoded ) - 1 );
1732
1733 curl_setopt( $ch, CURLOPT_POSTFIELDS, $encoded );
1734 curl_setopt( $ch, CURLOPT_POST, 1 );
1735 }
1736
1737 $output = curl_exec( $ch );
1738 $httpcode = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
1739
1740 curl_close( $ch );
1741
1742 if ( 200 !== $httpcode ) {
1743 return false;
1744 }
1745
1746 return json_decode( $output );
1747 }
1748
1749 /**
1750 * Call Cloudways API, Authenticate & perform given method.
1751 *
1752 * Use this function to contact CW API
1753 * We use OAuth, an open standard for authorization. Here are the steps involved:
1754 * 1. Get your API Key from here: https://platform.cloudways.com/api
1755 * 2. Enter in your account email address and API Key below.
1756 *
1757 * @param string $method GET|POST|PUT|DELETE.
1758 * @param string $url relative URL for the call.
1759 * @param string $accessToken Access token generated using OAuth Call.
1760 * @param array $post Optional post data for the call.
1761 * @return object|false Output from CW API.
1762 */
1763 public static function call_cloudways_api( $method, $url, $accessToken, $post = array() ) {
1764 $baseURL = 'https://api.cloudways.com/api/v1';
1765
1766 $ch = curl_init();
1767 curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $method );
1768 curl_setopt( $ch, CURLOPT_URL, $baseURL . $url );
1769 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
1770
1771 // Set Authorization Header.
1772 if ( $accessToken ) {
1773 curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Authorization: Bearer ' . $accessToken ) );
1774 }
1775
1776 // Set Post Parameters.
1777 $encoded = '';
1778 if ( count( $post ) ) {
1779 foreach ( $post as $name => $value ) {
1780 $encoded .= rawurlencode( $name ) . '=' . rawurlencode( $value ) . '&';
1781 }
1782 $encoded = substr( $encoded, 0, strlen( $encoded ) - 1 );
1783
1784 curl_setopt( $ch, CURLOPT_POSTFIELDS, $encoded );
1785 curl_setopt( $ch, CURLOPT_POST, 1 );
1786 }
1787
1788 $output = curl_exec( $ch );
1789
1790 $httpcode = (string) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
1791
1792 curl_close( $ch );
1793
1794 if ( '200' !== $httpcode ) {
1795 return false;
1796 }
1797
1798 return json_decode( $output );
1799 }
1800
1801 /**
1802 * Fetch Cloudways oAuth Access Token.
1803 *
1804 * Fetch the Cloudways oAuth access token from the given API credentials.
1805 *
1806 * @return mixed Return Cloudways Access Token.
1807 */
1808 public static function fetch_cloudways_access_token() {
1809 $account_email = get_option( 'mainwp_cloudways_api_account_email' );
1810 $api_key = static::get_cloudways_api_key();
1811
1812 // Fetch Access Token.
1813 $tokenResponse = static::call_cloudways_api(
1814 'POST',
1815 '/oauth/access_token',
1816 null,
1817 array(
1818 'email' => $account_email,
1819 'api_key' => $api_key,
1820 )
1821 );
1822 if ( empty( $tokenResponse ) ) {
1823 return '';
1824 }
1825 return $tokenResponse->access_token;
1826 }
1827
1828 /**
1829 * Fetch all available servers.
1830 *
1831 * @return mixed Returns available list of servers.
1832 */
1833 public static function fetch_cloudways_server_list() { //phpcs:ignore -- NOSONAR - complex.
1834
1835 if ( static::is_access_token_v2() ) {
1836 $serverList = (array) static::call_cloudways_api_v2( 'GET', '/server' );
1837 } else {
1838 // Grab access token.
1839 $accessToken = static::fetch_cloudways_access_token();
1840
1841 // Fetch Server List.
1842 $serverList = (array) static::call_cloudways_api( 'GET', '/server', $accessToken );
1843 }
1844
1845 if ( ! array_key_exists( 'servers', $serverList ) ) {
1846 return;
1847 }
1848 // Return the server list.
1849 return $serverList['servers'];
1850 }
1851
1852
1853 /**
1854 * Ajax.
1855 * Save the server & app ID to that Child Site's options table.
1856 *
1857 * Compare connected Child Sites against connected Cloudways account.
1858 * Automatically check for Child Sites domain name in server list & save.
1859 * that app's Server ID & App ID to that Child Site's options table.
1860 */
1861 public function ajax_cloudways_action_update_ids() {
1862 Api_Backups_Helper::security_nonce( 'cloudways_action_update_ids' );
1863 static::cloudways_action_update_ids();
1864 }
1865
1866 /**
1867 * Save the server & app ID to that Child Site's options table.
1868 *
1869 * Compare connected Child Sites against connected Cloudways account.
1870 * Automatically check for Child Sites domain name in server list & save.
1871 * that app's Server ID & App ID to that Child Site's options table.
1872 */
1873 public static function cloudways_action_update_ids() {
1874 // Fetch Child Site domains.
1875 $child_sites = array();
1876 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
1877
1878 foreach ( $websites as $website ) {
1879 $child_sites[ $website['id'] ] = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $website['url'] ) ) );
1880 }
1881
1882 // Fetch Cloudways Server List.
1883 $server_list = static::fetch_cloudways_server_list();
1884
1885 /**
1886 * Search $server_list for Child Site app ID & server ID.
1887 *
1888 * Loop through each Server/App & check if app cname / fqdn name matches any Child Site domain name.
1889 * if so, save the server & app ID to that Child Site's options table.
1890 */
1891 if ( ! is_array( $server_list ) ) {
1892 return;
1893 }
1894 foreach ( $server_list as $server ) {
1895 foreach ( $server->apps as $app ) {
1896 if ( in_array( $app->cname, $child_sites ) ) {
1897 $found_child_site_id = array_search( $app->cname, $child_sites );
1898 // Update Child Site options table.
1899 Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_app_id', $app->id );
1900 Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_instance_id', $app->server_id );
1901 Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_api', 'Cloudways' );
1902 } elseif ( in_array( $app->app_fqdn, $child_sites ) ) { // Check if app fqdn name matches any Child Site domain name, if so, save the server & app ID to that Child Site's options table.
1903 $found_child_site_id = array_search( $app->app_fqdn, $child_sites );
1904 // Update Child Site options table.
1905 Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_app_id', $app->id );
1906 Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_instance_id', $app->server_id );
1907 Api_Backups_Helper::update_website_option( $found_child_site_id, 'mainwp_3rd_party_api', 'Cloudways' );
1908 }
1909 }
1910 }
1911 }
1912
1913
1914 /**
1915 * Cloudways: action backup.
1916 *
1917 * Perform a backup on the selected Cloudways server.
1918 *
1919 * @return void
1920 */
1921 public function ajax_cloudways_action_individual_backup() {
1922 Api_Backups_Helper::security_nonce( 'cloudways_action_individual_backup' );
1923 static::cloudways_action_backup();
1924 }
1925
1926 /**
1927 * Cloudways: action backup.
1928 *
1929 * Perform a backup on the selected Cloudways server.
1930 *
1931 * @return void
1932 */
1933 public function ajax_cloudways_action_backup() {
1934 Api_Backups_Helper::security_nonce( 'cloudways_action_backup' );
1935 static::cloudways_action_create_backup();
1936 }
1937
1938 /**
1939 * Cloudways: action backup.
1940 *
1941 * Perform a backup on the selected Cloudways server.
1942 *
1943 * @param int $website_id Website ID.
1944 * @param bool $ret_val Return output or not.
1945 *
1946 * @return mixed
1947 */
1948 public static function cloudways_action_create_backup( $website_id = '', $ret_val = false ) {
1949
1950 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
1951
1952 // Grab this from websites.
1953 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_app_id' ) );
1954 $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
1955 $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
1956
1957 $data = array(
1958 'server_id' => $server_id,
1959 'app_id' => $app_id,
1960 );
1961
1962 $accessToken = '';
1963
1964 if ( static::is_access_token_v2() ) {
1965 $api_response = (array) static::call_cloudways_api_v2( 'POST', '/app/manage/takeBackup', $data );
1966 } else {
1967
1968 // Grab Cloudways access token.
1969 $accessToken = static::fetch_cloudways_access_token();
1970
1971 // Send Payload & create backup.
1972 $api_response = (array) static::call_cloudways_api( 'POST', '/app/manage/takeBackup', $accessToken, $data );
1973 }
1974
1975 $success = true;
1976
1977 if ( true !== $api_response['status'] ) {
1978 $success = false;
1979 } else {
1980 if ( static::is_access_token_v2() ) {
1981 // Save current backup operation.
1982 $backup_operation = (array) static::call_cloudways_api_v2( 'GET', static::OPERATION . $api_response['operation_id'] );
1983 } else {
1984 // Save current backup operation.
1985 $backup_operation = (array) static::call_cloudways_api( 'GET', static::OPERATION . $api_response['operation_id'], $accessToken );
1986 }
1987
1988 $backup_operation = wp_json_encode( $backup_operation['operation'] );
1989 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_backup_operation', $backup_operation );
1990
1991 // Save Timestamp.
1992 $local_time = current_datetime();
1993 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
1994 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_last_backup', $current_time );
1995 // Poll operations endpoint for backup status.
1996 // static::cloudways_action_poll_backup_operation( $website_id );.
1997 }
1998
1999 if ( $ret_val ) {
2000 return $api_response;
2001 }
2002
2003 if ( ! $success ) {
2004 wp_die( 'false' );
2005 } else {
2006 // Return success.
2007 wp_send_json( 'true' );
2008 // Poll operations endpoint for backup status.
2009 // static::cloudways_action_poll_backup_operation( $website_id );.
2010 }
2011 }
2012
2013 /**
2014 * Cloudways: action poll backup operation.
2015 *
2016 * Poll the Cloudways operations endpoint for backup status.
2017 *
2018 * @param int $website_id Website ID.
2019 *
2020 * @return void
2021 */
2022 public static function cloudways_action_poll_backup_operation( $website_id ) {
2023
2024 global $wp;
2025
2026 // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
2027 $site_options = Api_Backups_Helper::get_website_options(
2028 $website_id,
2029 array(
2030 'mainwp_3rd_party_cloudways_backup_operation',
2031 )
2032 );
2033
2034 // Current backup operation.
2035 $backup_operation = isset( $site_options['mainwp_3rd_party_cloudways_backup_operation'] ) ? $site_options['mainwp_3rd_party_cloudways_backup_operation'] : null;
2036 $operation_id = json_decode( $backup_operation, true )['id'];
2037
2038 if ( static::is_access_token_v2() ) {
2039 // Send Payload & list backups. https://api.cloudways.com/api/v1/operation/{id}.
2040 $operation_polling = static::call_cloudways_api_v2( 'GET', static::OPERATION . $operation_id );
2041 } else {
2042
2043 // Grab Cloudways access token.
2044 $accessToken = static::fetch_cloudways_access_token();
2045
2046 // Send Payload & list backups. https://api.cloudways.com/api/v1/operation/{id}.
2047 $operation_polling = static::call_cloudways_api( 'GET', static::OPERATION . $operation_id, $accessToken );
2048 }
2049 $backup_polling_response = $operation_polling->operation;
2050
2051 // If backup has not been completed yet, sleep for 30 seconds and check again.
2052 // If backup has been completed, save the backup operation results.
2053 if ( true !== $backup_polling_response->is_completed ) {
2054 sleep( 30 );
2055 static::cloudways_action_poll_backup_operation( $website_id );
2056 } else {
2057 // Save current backup operation.
2058 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_backup_operation', wp_json_encode( $backup_polling_response ) );
2059
2060 // Refresh the page.
2061 wp_safe_redirect( get_permalink( home_url( $wp->request ) ) );
2062 }
2063 // Return success.
2064 wp_send_json( 'true' );
2065 }
2066
2067 /**
2068 * Cloudways: action refresh available backups.
2069 *
2070 * Save backups to DB for the selected Cloudways server.
2071 *
2072 * @return void
2073 */
2074 public static function cloudways_action_refresh_available_backups() {
2075
2076 Api_Backups_Helper::security_nonce( 'cloudways_action_refresh_available_backups' );
2077
2078 // Grab website_id & backup_api name from Ajax post.
2079 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2080 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2081 } else {
2082 // Grab $_GET['data'] from url if not Ajax call.
2083 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2084 }
2085
2086
2087 // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
2088 $site_options = Api_Backups_Helper::get_website_options(
2089 $website_id,
2090 array(
2091 'mainwp_3rd_party_instance_id',
2092 'mainwp_3rd_party_app_id',
2093 )
2094 );
2095 $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2096 $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
2097
2098 if ( static::is_access_token_v2() ) {
2099 // Grab Backup operation from API.
2100 $backup_operation = static::call_cloudways_api_v2( 'GET', '/app/manage/backup?server_id=' . $server_id . '&app_id=' . $app_id );
2101 } else {
2102 // Grab Cloudways access token.
2103 $accessToken = static::fetch_cloudways_access_token();
2104 // Grab Backup operation from API.
2105 $backup_operation = static::call_cloudways_api( 'GET', '/app/manage/backup?server_id=' . $server_id . '&app_id=' . $app_id, $accessToken );
2106 }
2107
2108 $operation_id = $backup_operation->operation_id;
2109
2110 sleep( 3 ); // REQUIRED! Wait 3 seconds for cURL connection to be closed before opening a new one.
2111
2112 if ( static::is_access_token_v2() ) {
2113 $operation_polling = static::call_cloudways_api_v2( 'GET', static::OPERATION . $operation_id );
2114 } else {
2115 // Send Payload & list backups. https://api.cloudways.com/api/v1/operation/{id}.
2116 $operation_polling = static::call_cloudways_api( 'GET', static::OPERATION . $operation_id, $accessToken );
2117 }
2118
2119 $operation = $operation_polling->operation;
2120
2121 // Save backup operation.
2122 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cloudways_available_backups', $operation->parameters );
2123
2124 Api_Backups_Utility::save_lasttime_backup( $website_id, $operation->parameters, 'cloudways' );
2125
2126 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2127 if ( 1 !== (int) $operation->is_completed ) {
2128 wp_die( 'false' );
2129 } else {
2130 // Return success.
2131 wp_send_json( 'true' );
2132 }
2133 }
2134 }
2135
2136 /**
2137 * Cloudways: action restore backup.
2138 *
2139 * Restore a backup on the selected Cloudways server.
2140 *
2141 * @return void
2142 */
2143 public function cloudways_action_restore_backup() {
2144
2145 Api_Backups_Helper::security_nonce( 'cloudways_action_restore_backup' );
2146
2147 // Grab website_id & backup_date name from Ajax post.
2148 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2149 $backup_date = isset( $_POST['backup_date'] ) ? wp_unslash( $_POST['backup_date'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2150
2151 // Grab needed site options from WP_MAINWP_WP_OPTIONS table.
2152 $site_options = Api_Backups_Helper::get_website_options(
2153 $website_id,
2154 array(
2155 'mainwp_3rd_party_instance_id',
2156 'mainwp_3rd_party_app_id',
2157 )
2158 );
2159 $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2160 $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
2161
2162 // Payload to send to Cloudways API.
2163 $data = array(
2164 'server_id' => $server_id,
2165 'app_id' => $app_id,
2166 'time' => $backup_date,
2167 'type' => 'complete',
2168 );
2169
2170 if ( static::is_access_token_v2() ) {
2171 $api_response = static::call_cloudways_api_v2( 'POST', '/app/manage/restore', $data );
2172 } else {
2173 // Grab Cloudways access token.
2174 $accessToken = static::fetch_cloudways_access_token();
2175
2176 // Send Payload & create backup.
2177 $api_response = static::call_cloudways_api( 'POST', '/app/manage/restore', $accessToken, $data );
2178 }
2179
2180 // Handle API response.
2181 if ( 1 !== (int) $api_response->status ) {
2182 wp_die( 'false' );
2183 } else {
2184 wp_send_json( 'true' );
2185 }
2186 }
2187
2188 /**
2189 * Cloudways: action delete backup.
2190 *
2191 * Delete a backup on the selected Cloudways server.
2192 *
2193 * @return void
2194 */
2195 public function cloudways_action_delete_backup() {
2196
2197 Api_Backups_Helper::security_nonce( 'cloudways_action_delete_backup' );
2198
2199 // Grab website_id from Ajax post.
2200 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2201
2202 // Grab this from websites.
2203 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_app_id' ) );
2204 $server_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2205 $app_id = isset( $site_options['mainwp_3rd_party_app_id'] ) ? $site_options['mainwp_3rd_party_app_id'] : null;
2206
2207 $data = array(
2208 'server_id' => $server_id,
2209 'app_id' => $app_id,
2210 );
2211
2212 // Grab Cloudways access token.
2213 $accessToken = static::fetch_cloudways_access_token();
2214
2215 // Send Payload & create backup.
2216 $api_response = static::call_cloudways_api( 'DELETE', '/app/manage/backup', $accessToken, $data );
2217
2218 if ( 1 !== (int) $api_response->status ) {
2219 wp_die( 'false' );
2220 } else {
2221 wp_send_json( 'true' );
2222 }
2223 }
2224
2225 /*********************************************************************************
2226 * Vultr API Methods.
2227 **********************************************************************************/
2228
2229 /**
2230 * Call Vultr API, Authenticate & perform given method.
2231 *
2232 * Use this function to contact Vultr API
2233 * We use OAuth, an open standard for authorization. Here are the steps involved:
2234 * 1. Get your API Key from here: https://platform.cloudways.com/api
2235 * 2. Enter in your account email address and API Key below.
2236 *
2237 * @param string $method GET|POST|PUT|DELETE.
2238 * @param string $url relative URL for the call.
2239 * @param string $accessToken Access token generated using OAuth Call.
2240 * @param string $data Json encoded array - Optional post data for the call.
2241 * @param bool $die_error die when error.
2242 *
2243 * @return array Response from Vultr API.
2244 */
2245 public static function call_vultr_api( $method, $url, $accessToken, $data = null, $die_error = true ) {
2246
2247 $baseurl = 'https://api.vultr.com/v2';
2248
2249 $curl = curl_init( $baseurl . $url );
2250 curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $method );
2251 curl_setopt( $curl, CURLOPT_URL, $baseurl . $url );
2252 curl_setopt( $curl, CURLOPT_POST, true );
2253 curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
2254
2255 $headers = array(
2256 "Authorization: Bearer $accessToken",
2257 'Content-Type: application/json',
2258 );
2259 curl_setopt( $curl, CURLOPT_HTTPHEADER, $headers );
2260 curl_setopt( $curl, CURLOPT_POSTFIELDS, $data );
2261
2262 $ssl_verifyhost = ( false === get_option( 'mainwp_sslVerifyCertificate' ) ) || ( 1 === (int) get_option( 'mainwp_sslVerifyCertificate' ) );
2263
2264 if ( $ssl_verifyhost ) {
2265 curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, 2 );
2266 curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, true );
2267 } else {
2268 // for debug only!
2269 curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, false ); // NOSONAR.
2270 curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false ); // NOSONAR.
2271 }
2272
2273 $resp = curl_exec( $curl );
2274
2275 $response = array();
2276 // Basic Error reporting. ( should wrap in try catch MainWP Exceptions call during code refactoring ).
2277 $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
2278 if ( ( '201' !== $httpCode ) && ( '200' !== $httpCode ) && ( '202' !== $httpCode ) && ( '204' !== $httpCode ) ) {
2279 $decode_resp = json_decode( $resp );
2280 $error = $decode_resp->error;
2281 if ( $die_error ) { // die when error.
2282 if ( isset( $_POST['bulk_backups'] ) && ! empty( $_POST['bulk_backups'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing
2283 wp_send_json( array( 'error' => 'Code: ' . esc_html( $httpCode ) . ' - ' . esc_html( $error ) ) ); // to fix for backup selected sites (bulk).
2284 } else {
2285 die( 'Code: ' . esc_html( $httpCode ) . ' - ' . esc_html( $error ) );
2286 }
2287 } else {
2288 $response['response'] = $decode_resp;
2289 $response['status'] = false;
2290 }
2291 } else {
2292 $response['response'] = json_decode( $resp );
2293 $response['status'] = true;
2294
2295 }
2296 curl_close( $curl );
2297 // Return Response.
2298 return $response;
2299 }
2300
2301
2302
2303 /**
2304 * Ajax.
2305 * Vultr: action create snapshot.
2306 *
2307 * Create a snapshot on the selected Vultr server.
2308 *
2309 * This function is also called before any update. During this time a backup will be.
2310 * Created but no updates will be made this time around. A new update will need to be manually triggered.
2311 *
2312 * @return void
2313 */
2314 public function ajax_vultr_action_individual_create_snapshot() {
2315 Api_Backups_Helper::security_nonce( 'vultr_action_individual_create_snapshot' );
2316 static::vultr_action_create_snapshot();
2317 }
2318
2319 /**
2320 * Ajax.
2321 * Vultr: action create snapshot.
2322 *
2323 * Create a snapshot on the selected Vultr server.
2324 *
2325 * This function is also called before any update. During this time a backup will be.
2326 * Created but no updates will be made this time around. A new update will need to be manually triggered.
2327 *
2328 * @return void
2329 */
2330 public function ajax_vultr_action_create_snapshot() {
2331 Api_Backups_Helper::security_nonce( 'vultr_action_create_snapshot' );
2332 static::vultr_action_create_snapshot();
2333 }
2334
2335 /**
2336 * Method get_vultr_api_key().
2337 */
2338 public static function get_vultr_api_key() {
2339 return Api_Backups_Utility::get_instance()->get_api_key( 'vultr' );
2340 }
2341
2342 /**
2343 * Method get_gridpane_api_key().
2344 */
2345 public static function get_gridpane_api_key() {
2346 return Api_Backups_Utility::get_instance()->get_api_key( 'gridpane' );
2347 }
2348
2349 /**
2350 * Method get_linode_api_key().
2351 */
2352 public static function get_linode_api_key() {
2353 return Api_Backups_Utility::get_instance()->get_api_key( 'linode' );
2354 }
2355
2356 /**
2357 * Method get_digitalocean_api_key().
2358 */
2359 public static function get_digitalocean_api_key() {
2360 return Api_Backups_Utility::get_instance()->get_api_key( 'digitalocean' );
2361 }
2362
2363 /**
2364 * Method get_cloudways_api_key().
2365 */
2366 public static function get_cloudways_api_key() {
2367 return Api_Backups_Utility::get_instance()->get_api_key( 'cloudways' );
2368 }
2369
2370 /**
2371 * Method get_cloudways_access_token().
2372 */
2373 public static function get_cloudways_access_token() {
2374 return Api_Backups_Utility::get_instance()->get_api_key( 'cloudways', '', 'access_token' );
2375 }
2376
2377
2378 /**
2379 * Method get_cpanel_account_password().
2380 */
2381 public static function get_cpanel_account_password() {
2382 return Api_Backups_Utility::get_instance()->get_api_key( 'cpanel' );
2383 }
2384
2385 /**
2386 * Method get_plesk_api_key().
2387 */
2388 public static function get_plesk_api_key() {
2389 return Api_Backups_Utility::get_instance()->get_api_key( 'plesk' );
2390 }
2391
2392 /**
2393 * Method get_kinsta_api_key().
2394 */
2395 public static function get_kinsta_api_key() {
2396 return Api_Backups_Utility::get_instance()->get_api_key( 'kinsta' );
2397 }
2398
2399 /**
2400 * Vultr: action create snapshot.
2401 *
2402 * Create a snapshot on the selected Vultr server.
2403 *
2404 * This function is also called before any update. During this time a backup will be
2405 * created but no updates will be made this time around. A new update will need to be manually triggered.
2406 *
2407 * @param int $website_id website id.
2408 * @param string $backup_api backup api.
2409 *
2410 * @return mixed result.
2411 */
2412 public static function vultr_action_create_snapshot( $website_id = '', $backup_api = '' ) {
2413
2414 // Grab $_POST data if set else use args.
2415 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : intval( $website_id ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2416 $backup_api = isset( $_POST['backup_api'] ) ? wp_unslash( $_POST['backup_api'] ) : $backup_api; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2417
2418 // Grab Site options.
2419 $website = Api_Backups_Helper::get_website_by_id( $website_id );
2420
2421 // Grab this from websites ( Static atm ).
2422 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_vultr_snapshot_list' ) );
2423 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2424 $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? $site_options['mainwp_3rd_party_vultr_snapshot_list'] : null;
2425
2426 // Grab Vultr Access token.
2427 $accessToken = static::get_vultr_api_key();
2428
2429 // Remove http://, www., and slash(/) from the URL.
2430 $url = ! empty( $website['url'] ) ? rawurlencode( $website['url'] ) : '';
2431 $clean_url = preg_replace( '#^[^:/.]*[:/]+#i', '', preg_replace( '{/$}', '', urldecode( $url ) ) );
2432
2433 // Build payload data.
2434 $snapshot_data = array(
2435 'instance_id' => $instance_id,
2436 'description' => 'MainWP API Backups -' . $clean_url,
2437 );
2438 $snapshot_data = wp_json_encode( $snapshot_data );
2439
2440 // Send Payload & create backup.
2441 $snapshot_response = static::call_vultr_api( 'POST', '/snapshots', $accessToken, $snapshot_data );
2442 $snapshot_id = $snapshot_response['response']->snapshot->id;
2443
2444 $snapshot_list = json_decode( $snapshot_list );
2445 $snapshot_list[] = $snapshot_id;
2446 $snapshot_list = wp_json_encode( $snapshot_list );
2447
2448 $success = true;
2449 // Store Last Backup timestamp.
2450 if ( empty( $snapshot_response ) ) {
2451 $success = false;
2452 } else {
2453 $local_time = current_datetime();
2454 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
2455 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_' . $backup_api . '_last_backup', $current_time );
2456 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_snapshot_list', $snapshot_list );
2457 }
2458
2459 if ( $ret_val ) {
2460 return $snapshot_response;
2461 }
2462
2463 if ( $success ) {
2464 // Return Response.
2465 if ( ! empty( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2466 wp_send_json( 'true' ); // Equivalent to die() - but for ajax.
2467 } else {
2468 return true;
2469 }
2470 } elseif ( ! empty( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2471 $error = new WP_Error( '400', __( 'There was an issue with creating your backup.', 'mainwp' ) );
2472 wp_send_json_error( $error );
2473 } else {
2474 return false;
2475 }
2476 }
2477
2478 /**
2479 * Vultr: action refresh available backups.
2480 *
2481 * Save backups to DB for the selected Vultr server.
2482 *
2483 * @return void
2484 */
2485 public function vultr_action_refresh_available_backups() { //phpcs:ignore -- NOSONAR - complex.
2486 Api_Backups_Helper::security_nonce( 'vultr_action_refresh_available_backups' );
2487
2488 // Grab website_id & backup_api name from Ajax post.
2489 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2490 // Grab $_POST data.
2491 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2492 } else {
2493 // Grab $_GET data from url if not Ajax call.
2494 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2495 }
2496
2497 // Grab this from websites ( Static atm ).
2498 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id', 'mainwp_3rd_party_vultr_snapshot_list' ) );
2499 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2500 $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? json_decode( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) : null;
2501
2502 // Grab Vultr Access token.
2503 $accessToken = static::get_vultr_api_key();
2504
2505 $success = false;
2506 $die_error = false;
2507
2508 // Build available backups array.
2509 $available_backups = array();
2510 foreach ( $snapshot_list as $snapshot ) {
2511 $api_response = static::call_vultr_api( 'GET', static::SNAPSHOTS . $snapshot, $accessToken, null, $die_error );
2512 $snapshot = $api_response['response'];
2513 $available_backups['snapshots'] = $snapshot;
2514 if ( is_array( $api_response ) && ! empty( $api_response['status'] ) ) {
2515 $success = true;
2516 }
2517 }
2518 $automatic_backups = static::call_vultr_api( 'GET', '/backups?instance_id=' . $instance_id, $accessToken, null, $die_error );
2519 $automatic_backups = $automatic_backups['response']->backups;
2520 $available_backups['backups'] = $automatic_backups;
2521 $available_backups = wp_json_encode( $available_backups );
2522
2523 if ( ! $success && ! empty( $automatic_backups['status'] ) ) {
2524 $success = true;
2525 }
2526
2527 // Grab Site options then update Child Site options.
2528 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_available_backups', $available_backups, $die_error );
2529
2530 if ( $success ) {
2531 Api_Backups_Utility::save_lasttime_backup( $website_id, $available_backups, 'vultr' );
2532 }
2533
2534 // Return AJAX.
2535 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2536 // Store Available backups.
2537 if ( $success ) {
2538 wp_send_json( 'true' );
2539 } else {
2540 wp_send_json_error( $api_response );
2541 }
2542 }
2543 }
2544
2545 /**
2546 * Vultr: action restore backup.
2547 *
2548 * Restore backup on the selected Vultr server.
2549 *
2550 * @return void
2551 */
2552 public function ajax_vultr_action_restore_backup() {
2553 Api_Backups_Helper::security_nonce( 'vultr_action_restore_backup' );
2554 static::vultr_action_restore_backup();
2555 }
2556
2557 /**
2558 * Vultr: action restore backup.
2559 *
2560 * Restore backup on the selected Vultr server.
2561 *
2562 * @return void
2563 */
2564 public function vultr_action_restore_backup() {
2565 // Grab $_POST data.
2566 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2567 $snapshot_id = isset( $_POST['snapshot_id'] ) ? wp_unslash( $_POST['snapshot_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2568
2569 // Grab backup info from websites.
2570 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2571 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2572
2573 // Grab Access token.
2574 $accessToken = static::get_vultr_api_key();
2575 // Set which Backup to restore to.
2576 $backup_data = array(
2577 'snapshot_id' => $snapshot_id,
2578 );
2579 $backup_data = wp_json_encode( $backup_data );
2580
2581 // Send Payload & list backups. backups/restore/1038'.
2582 $api_response = (object) static::call_vultr_api( 'POST', static::INSTANCES . $instance_id . '/restore', $accessToken, $backup_data );
2583
2584 // Return AJAX.
2585 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2586 if ( 1 !== (int) $api_response->status ) {
2587 wp_send_json_error( $api_response );
2588 } else {
2589 wp_send_json( 'true' );
2590 }
2591 }
2592 }
2593
2594 /**
2595 * Vultr: action delete backup.
2596 *
2597 * Delete a backup on the selected Vultr server.
2598 *
2599 * @return void
2600 */
2601 public function vultr_action_delete_backup() {
2602
2603 Api_Backups_Helper::security_nonce( 'vultr_action_delete_backup' );
2604
2605 // Grab $_GET['data'] from url if not Ajax call.
2606 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2607 $snapshot_id = isset( $_POST['snapshot_id'] ) ? wp_unslash( $_POST['snapshot_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2608 // $snapshot_id acecab84-7404-4193-bc9f-88e29956362f;
2609
2610 // Grab Vultr Access token.
2611 $accessToken = static::get_vultr_api_key();
2612
2613 // Send Payload & delete backup.
2614 $api_response = (object) static::call_vultr_api( 'DELETE', static::SNAPSHOTS . $snapshot_id, $accessToken );
2615
2616 // Remove backup from snapshot list.
2617 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_vultr_snapshot_list' ) );
2618 $snapshot_list = isset( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) ? json_decode( $site_options['mainwp_3rd_party_vultr_snapshot_list'] ) : null;
2619
2620 $key = array_search( $snapshot_id, $snapshot_list );
2621 if ( false !== $key ) {
2622 unset( $snapshot_list[ $key ] );
2623 }
2624 $snapshot_list = wp_json_encode( $snapshot_list );
2625
2626 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_vultr_snapshot_list', $snapshot_list );
2627 // die.
2628 // Return AJAX.
2629 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2630 // Return Ajax response.
2631 if ( 1 !== (int) $api_response->status ) {
2632 wp_send_json_error( 'false' );
2633
2634 } else {
2635 wp_send_json( 'true' );
2636 }
2637 }
2638 }
2639
2640 /*********************************************************************************
2641 * GridPane API Methods.
2642 **********************************************************************************/
2643
2644 /**
2645 * Call GridPane API, Authenticate & perform given method.
2646 *
2647 * Use this function to contact GridPane API
2648 * We use OAuth, an open standard for authorization. Here are the steps involved:
2649 * 1. Get your API Key from here: https://platform.cloudways.com/api
2650 * 2. Enter in your account email address and API Key below.
2651 *
2652 * @param string $method GET|POST|PUT|DELETE.
2653 * @param string $url relative URL for the call.
2654 * @param string $accessToken Access token generated using OAuth Call.
2655 * @param mixed $backup_data Json encoded array - Optional post data for the call.
2656 *
2657 * @return string Output from GridPane API.
2658 */
2659 public static function call_gridpane_api( $method, $url, $accessToken, $backup_data = array() ) {
2660
2661 $baseurl = 'https://my.gridpane.com/oauth/api/v1';
2662 $curl = curl_init();
2663 curl_setopt_array(
2664 $curl,
2665 array(
2666 CURLOPT_URL => $baseurl . $url,
2667 CURLOPT_RETURNTRANSFER => true,
2668 CURLOPT_ENCODING => '',
2669 CURLOPT_MAXREDIRS => 10,
2670 CURLOPT_TIMEOUT => 0,
2671 CURLOPT_FOLLOWLOCATION => true,
2672 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
2673 CURLOPT_CUSTOMREQUEST => $method,
2674 CURLOPT_POSTFIELDS => $backup_data,
2675 CURLOPT_HTTPHEADER => array(
2676 "Authorization: Bearer $accessToken",
2677 'Content-Type: application/json',
2678 ),
2679 )
2680 );
2681 $response = curl_exec( $curl );
2682 curl_close( $curl );
2683 return $response;
2684 }
2685
2686 /**
2687 * Get GridPane Site List.
2688 *
2689 * Request for all sites for current user token.
2690 *
2691 * @param int $sites_count sites count.
2692 * @return object|bool Return Sites Object.
2693 */
2694 public static function gridpane_get_sites_list( $sites_count ) {
2695
2696 // Grab Vultr Access token.
2697 $accessToken = static::get_gridpane_api_key();
2698
2699 // Grab Sites List.
2700 $grid_response = (array) static::call_gridpane_api( 'GET', '/site?per_page=' . $sites_count, $accessToken );
2701 Api_Backups_Utility::log_debug( 'GridPane API get sites :: [response=' . ( is_array( $grid_response ) ? print_r( $grid_response, true ) : 'INVALID' ). '] :: ' . $accessToken ); // phpcs:ignore -- NOSONAR - for debugging.
2702 $grid_response_decoded = json_decode( $grid_response[0] );
2703 if ( is_object( $grid_response_decoded ) && property_exists( $grid_response_decoded, 'data' ) ) {
2704 return $grid_response_decoded->data;
2705 }
2706 return false;
2707 }
2708
2709 /**
2710 * Get GridPane Site List.
2711 *
2712 * Request for all sites for current user token.
2713 *
2714 * @return object|bool Return Sites Object.
2715 */
2716 public static function gridpane_get_domain_list() {
2717
2718 // Grab Vultr Access token.
2719 $accessToken = static::get_gridpane_api_key();
2720
2721 // Grab Sites List.
2722 $grid_response = (array) static::call_gridpane_api( 'GET', '/domain', $accessToken );
2723 $grid_response_decoded = json_decode( $grid_response[0] );
2724 if ( is_object( $grid_response_decoded ) && property_exists( $grid_response_decoded, 'data' ) ) {
2725 return $grid_response_decoded->data;
2726 }
2727 return false;
2728 }
2729
2730 /**
2731 * Ajax.
2732 * Assign Server:Apps to Child Sites options table.
2733 *
2734 * Compare connected Child Sites against connected GridPane account.
2735 * Automatically check for Child Sites domain name in server list & save
2736 * that app's Server ID & App ID to that Child Site's options table.
2737 *
2738 * @return void True|False Return True on success & False on failure
2739 */
2740 public function ajax_gridpane_action_update_ids() {
2741 Api_Backups_Helper::security_nonce( 'gridpane_action_update_ids' );
2742 static::gridpane_action_update_ids();
2743 }
2744
2745 /**
2746 * Assign Server:Apps to Child Sites options table.
2747 *
2748 * Compare connected Child Sites against connected GridPane account.
2749 * Automatically check for Child Sites domain name in server list & save
2750 * that app's Server ID & App ID to that Child Site's options table.
2751 *
2752 * @return void True|False Return True on success & False on failure
2753 */
2754 public static function gridpane_action_update_ids() { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR - complexity.
2755
2756 // Get child_sites list from MainWP.
2757 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_wp_for_current_user() );
2758
2759 // Build an array of websites by URL.
2760 $websites_by_urls = array();
2761 if ( $websites ) {
2762 while ( $websites && ( $website = Api_Backups_Helper::fetch_object( $websites ) ) ) {
2763 $clean_url = Api_Backups_Helper::clean_url( $website->url );
2764 $websites_by_urls[ $clean_url ] = $website->id;
2765 }
2766 MainWP_DB::data_seek( $websites, 0 );
2767 }
2768
2769 // Get GP Sites list.
2770 $sites_list = static::gridpane_get_sites_list( 99999 ); // 99999 to pull all sites. High number at least for now.
2771
2772 $logs_updated_sites = array();
2773
2774 // Loop through Child Sites.
2775 while ( $websites && ( $website = Api_Backups_Helper::fetch_object( $websites ) ) ) {
2776
2777 // Grab non-stagingChild Site ID.
2778 $website_id = $website->id;
2779
2780 // Remove http(s)://, www., and trailing slash(/) from the URL.
2781 $clean_url = Api_Backups_Helper::clean_url( $website->url );
2782
2783 /**
2784 * Check if the URLs of Child Sites match with those of GridPane Sites.
2785 * If they do, add the GridPane Site ID and the provider name 'GridPane'
2786 * to the Child Site options table.
2787 */
2788 if ( is_array( $sites_list ) ) {
2789 foreach ( $sites_list as $site ) {
2790
2791 // If the URL of the Child Site matches the URL of the GridPane Site.
2792 if ( $site->url === $clean_url ) {
2793
2794 // GridPane Site found here....
2795
2796 // Grab GridPane Site ID.
2797 $gp_site_id = $site->id;
2798
2799 // Update Production Child Site options.
2800 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_instance_id', $gp_site_id );
2801 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_api', 'GridPane' );
2802 $logs_updated_sites[ $clean_url ] = $gp_site_id;
2803 // Check if the site is a staging site.
2804 if ( ! empty( $site->staging_site_built_at ) && isset( $websites_by_urls[ 'staging.' . $site->url ] ) ) {
2805 $staging_child_site_id = $websites_by_urls[ 'staging.' . $site->url ];
2806
2807 $logs_updated_sites[ 'staging.' . $site->url ] = $gp_site_id + 1;
2808
2809 // Update Staging Child Site options.
2810 Api_Backups_Helper::update_website_option( $staging_child_site_id, 'mainwp_3rd_party_instance_id', $gp_site_id + 1 );
2811 Api_Backups_Helper::update_website_option( $staging_child_site_id, 'mainwp_3rd_party_api', 'GridPane' );
2812 }
2813 break;
2814 }
2815 }
2816 }
2817 }
2818 Api_Backups_Utility::log_debug( 'Updated GridPane API Sites :: [total=' . count( $logs_updated_sites ) . '] :: [' . print_r( $logs_updated_sites, true ) . ']' ); // phpcs:ignore -- NOSONAR - for debugging.
2819
2820 $logs_sites_lists = array();
2821 if ( is_array( $sites_list ) ) {
2822 foreach ( $sites_list as $site ) {
2823 $logs_sites_lists[ $site->url ] = $site->id;
2824 }
2825 }
2826 Api_Backups_Utility::log_debug( 'GridPane Sites Lists:: [total=' . count( $logs_sites_lists ) . '] :: [' . print_r( $logs_sites_lists, true ) . ']' ); // phpcs:ignore -- NOSONAR - for debugging.
2827
2828 Api_Backups_Helper::free_result( $websites );
2829 }
2830
2831 /**
2832 * Ajax.
2833 * GridPane: action create backup.
2834 *
2835 * Create a backup on the selected GridPane server.
2836 *
2837 * @return void
2838 */
2839 public function ajax_gridpane_action_individual_create_backup() {
2840 Api_Backups_Helper::security_nonce( 'gridpane_action_individual_create_backup' );
2841 static::gridpane_action_create_backup();
2842 }
2843
2844 /**
2845 * Ajax.
2846 * GridPane: action create backup.
2847 *
2848 * Create a backup on the selected GridPane server.
2849 *
2850 * @return void
2851 */
2852 public function ajax_gridpane_action_create_backup() {
2853 Api_Backups_Helper::security_nonce( 'gridpane_action_create_backup' );
2854 static::gridpane_action_create_backup();
2855 }
2856
2857 /**
2858 * GridPane: action create backup.
2859 *
2860 * @param int $website_id Website ID.
2861 * @param bool $ret_val Return output or not.
2862 *
2863 * @return mixed
2864 */
2865 public static function gridpane_action_create_backup( $website_id = '', $ret_val = false ) {
2866
2867 // Grab $_POST data.
2868 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : intval( $website_id ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2869
2870 // Grab this from websites.
2871 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2872 $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2873
2874 // Grab Gridpane Access token.
2875 $accessToken = static::get_gridpane_api_key();
2876
2877 // Set Backup `type` & `tag`.
2878 $backup_data = array(
2879 'type' => 'local',
2880 'tag' => 'MainWP-API-Backups',
2881 );
2882 $backup_data = wp_json_encode( $backup_data );
2883
2884 // Send Payload & create backup.
2885 $backup_response = static::call_gridpane_api( 'POST', '/backups/' . $site_id, $accessToken, $backup_data );
2886 $backup_status = json_decode( $backup_response );
2887
2888 $success = false;
2889 $error = false;
2890 // Store Last Backup timestamp.
2891 if ( $backup_status && ! empty( $backup_status->success ) ) {
2892 $success = true;
2893 $local_time = current_datetime();
2894 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
2895 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_gridpane_last_backup', $current_time );
2896 } else {
2897 $error = new WP_Error( $backup_status->error->code, $backup_status->error->message );
2898 }
2899
2900 if ( $ret_val ) {
2901 return $backup_status;
2902 }
2903
2904 if ( $success ) {
2905 wp_send_json( 'true' );
2906 } else {
2907 if ( empty( $error ) ) {
2908 $error = esc_html__( 'Undefined error. Please try again.', 'mainwp' );
2909 }
2910 wp_send_json_error( $error );
2911 }
2912 }
2913
2914 /**
2915 * GridPane: action refresh available backups.
2916 *
2917 * Save backups to DB for the selected GridPane server.
2918 *
2919 * @return void
2920 */
2921 public function gridpane_action_refresh_available_backups() {
2922
2923 Api_Backups_Helper::security_nonce( 'gridpane_action_refresh_available_backups' );
2924
2925 // Grab website_id & backup_api name from Ajax post.
2926 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2927 // Grab $_POST data.
2928 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2929 } else {
2930 // Grab $_GET['data'] from url if not Ajax call.
2931 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2932 }
2933
2934 // Grab IDs from websites.
2935 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2936 $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2937
2938 // Grab Gridpane Access token.
2939 $accessToken = static::get_gridpane_api_key();
2940
2941 // Refresh backups.
2942 static::call_gridpane_api( 'GET', '/backups/refresh/' . $site_id, $accessToken );
2943
2944 // Send Payload & grab backup list.
2945 $api_response = json_decode( static::call_gridpane_api( 'GET', '/backups/original/' . $site_id, $accessToken ) );
2946
2947 $available_backups = '';
2948 if ( $api_response && ! empty( $api_response->backups ) && ! empty( $api_response->backups->local ) ) {
2949 $available_backups = wp_json_encode( $api_response->backups->local );
2950 }
2951
2952 // Update Child Site option with available backup list.
2953 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_gridpane_available_backups', $available_backups );
2954
2955 Api_Backups_Utility::save_lasttime_backup( $website_id, $available_backups, 'gridpane' );
2956
2957 // Return AJAX.
2958 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2959 if ( true !== $api_response->success ) {
2960 wp_send_json_error( 'No Backups Found' );
2961
2962 } else {
2963 wp_send_json( 'true' );
2964 }
2965 }
2966 }
2967
2968 /**
2969 * GridPane: action restore backup.
2970 *
2971 * Restore selected backup for the selected GridPane server.
2972 *
2973 * @return void
2974 */
2975 public function gridpane_action_restore_backup() {
2976
2977 Api_Backups_Helper::security_nonce( 'gridpane_action_restore_backup' );
2978
2979 // Grab $_POST data.
2980 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
2981 $backup_type = isset( $_POST['backup_type'] ) ? wp_unslash( $_POST['backup_type'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2982 $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2983
2984 // Grab backup info from websites.
2985 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
2986 $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
2987
2988 // Grab Gridpane Access token.
2989 $accessToken = static::get_gridpane_api_key();
2990
2991 // Set which Backup to restore to.
2992 $backup_data = array(
2993 'backup_source' => 'local',
2994 'source_type' => 'original',
2995 'backup_type' => $backup_type,
2996 'backup' => $backup_name,
2997 );
2998 $backup_data = wp_json_encode( $backup_data );
2999
3000 // Send Payload & list backups. backups/restore/1038'.
3001 $api_response = json_decode( static::call_gridpane_api( 'POST', '/backups/restore/' . $site_id, $accessToken, $backup_data ) );
3002
3003 // Return AJAX.
3004 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3005 if ( '1' !== (string) $api_response->success ) {
3006 wp_send_json_error( 'false' );
3007
3008 }
3009 wp_send_json( 'true' );
3010 }
3011 }
3012
3013 /**
3014 * GridPane: action delete backup.
3015 *
3016 * Delete backup for the selected GridPane server.
3017 *
3018 * @return void
3019 */
3020 public function gridpane_action_delete_backup() {
3021
3022 Api_Backups_Helper::security_nonce( 'gridpane_action_delete_backup' );
3023
3024 // Grab $_POST data.
3025 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3026 $backup_type = isset( $_POST['backup_type'] ) ? wp_unslash( $_POST['backup_type'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3027 $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3028
3029 // Grab backup info from websites.
3030 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3031 $site_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3032
3033 // Grab Gridpane Access token.
3034 $accessToken = static::get_gridpane_api_key();
3035
3036 // Set which Backup to restore to.
3037 $backup_data = array(
3038 'backup_source' => 'local',
3039 'backup_type' => $backup_type,
3040 'backup' => $backup_name,
3041 );
3042 $backup_data = wp_json_encode( $backup_data );
3043
3044 // Send Payload & delete backup.
3045 $api_response = json_decode( static::call_gridpane_api( 'PUT', '/backups/purge/' . $site_id, $accessToken, $backup_data ) );
3046
3047 // Return AJAX.
3048 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3049 if ( '1' !== (string) $api_response->success ) {
3050 wp_send_json_error( 'false' );
3051 }
3052 wp_send_json( 'true' );
3053 }
3054 }
3055
3056
3057 /*********************************************************************************
3058 * Linode API Methods.
3059 **********************************************************************************/
3060
3061 /**
3062 * Call Linode API, Authenticate & perform given method.
3063 *
3064 * Use this function to contact Linode API
3065 * We use OAuth, an open standard for authorization. Here are the steps involved:
3066 * 1. Get your API Key from here: https://platform.cloudways.com/api
3067 * 2. Enter in your account email address and API Key below.
3068 *
3069 * @param string $method GET|POST|PUT|DELETE.
3070 * @param string $url relative URL for the call.
3071 * @param string $accessToken Access token generated using OAuth Call.
3072 * @param mixed $backup_data Json encoded array - Optional post data for the call.
3073 * @return string Output from GridPane API.
3074 */
3075 public static function call_linode_api( $method, $url, $accessToken, $backup_data = array() ) {
3076
3077 $baseurl = 'https://api.linode.com/v4/linode';
3078 $curl = curl_init();
3079 curl_setopt_array(
3080 $curl,
3081 array(
3082 CURLOPT_URL => $baseurl . $url,
3083 CURLOPT_RETURNTRANSFER => true,
3084 CURLOPT_ENCODING => '',
3085 CURLOPT_MAXREDIRS => 10,
3086 CURLOPT_TIMEOUT => 0,
3087 CURLOPT_FOLLOWLOCATION => true,
3088 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3089 CURLOPT_CUSTOMREQUEST => $method,
3090 CURLOPT_POSTFIELDS => $backup_data,
3091 CURLOPT_HTTPHEADER => array(
3092 "Authorization: Bearer $accessToken",
3093 'Content-Type: application/json',
3094 ),
3095 )
3096 );
3097
3098 $response = curl_exec( $curl );
3099
3100 curl_close( $curl );
3101 return $response;
3102 }
3103
3104 /**
3105 * Linode: action create backup.
3106 *
3107 * Create backup for the selected Linode server.
3108 *
3109 * @return void
3110 */
3111 public function ajax_linode_action_individual_create_backup() {
3112 Api_Backups_Helper::security_nonce( 'linode_action_individual_create_backup' );
3113 static::linode_action_create_backup();
3114 die();
3115 }
3116
3117 /**
3118 * Linode: action create backup.
3119 *
3120 * Create backup for the selected Linode server.
3121 *
3122 * @return void
3123 */
3124 public function ajax_linode_action_create_backup() {
3125 Api_Backups_Helper::security_nonce( 'linode_action_create_backup' );
3126 static::linode_action_create_backup();
3127 die();
3128 }
3129
3130 /**
3131 * Linode: action create backup.
3132 *
3133 * Create backup for the selected Linode server.
3134 *
3135 * @param int $website_id Website ID.
3136 * @param bool $ret_val Return output or not.
3137 *
3138 * @return mixed
3139 */
3140 public static function linode_action_create_backup( $website_id = '', $ret_val = false ) {
3141
3142 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3143
3144 // Grab IDs from websites.
3145 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3146 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3147
3148 // Grab Linode Access token.
3149 $accessToken = static::get_linode_api_key();
3150
3151 // Send Payload & create backup.
3152 $linode_response = (array) static::call_linode_api( 'POST', static::INSTANCES . $instance_id . '/backups', $accessToken );
3153 $linode_response = json_decode( $linode_response[0] );
3154
3155 // Handle response.
3156 if ( ! isset( $linode_response->errors ) ) {
3157 $local_time = current_datetime();
3158 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
3159 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_last_backup', $current_time );
3160 }
3161
3162 if ( $ret_val ) {
3163 return $linode_response;
3164 }
3165
3166 // Handle response.
3167 if ( isset( $linode_response->errors ) ) {
3168 $error = new WP_Error( '400', $linode_response->errors['0']->reason );
3169 // Return AJAX.
3170 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3171 wp_send_json_error( $error );
3172
3173 }
3174 } elseif ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3175 wp_send_json( 'true' ); // Return AJAX.
3176 }
3177 die();
3178 }
3179
3180 /**
3181 * Linode: action Refresh available backups.
3182 *
3183 * Save backups to DB for the selected Linode server.
3184 *
3185 * @return void
3186 */
3187 public function linode_action_refresh_available_backups() {
3188 Api_Backups_Helper::security_nonce( 'linode_action_refresh_available_backups' );
3189 // Grab website_id & backup_api name from Ajax post.
3190 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3191 // Grab $_POST data.
3192 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3193 } else {
3194 // Grab $_GET['data'] from url if not Ajax call.
3195 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3196 }
3197
3198 // Grab Child Site options.
3199 // Grab IDs from websites.
3200 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3201 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3202
3203 // Grab Vultr Access token.
3204 $accessToken = static::get_linode_api_key();
3205
3206 // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups.
3207 $api_response = (object) static::call_linode_api( 'GET', static::INSTANCES . $instance_id . '/backups', $accessToken );
3208 $all_backups = $api_response->scalar;
3209
3210 // Grab Site options then update Child Site options.
3211 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_available_backups', $all_backups );
3212
3213 Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'linode' );
3214
3215 // Return AJAX.
3216 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3217 // Store Available backups.
3218 if ( ! $all_backups ) {
3219 wp_send_json_error( $api_response );
3220 } else {
3221 wp_send_json( 'true' );
3222 }
3223 }
3224 }
3225
3226 /**
3227 * Linode: action Restore backup.
3228 *
3229 * Restore backup for the selected Linode server.
3230 *
3231 * @return void
3232 */
3233 public function linode_action_restore_backup() {
3234
3235 Api_Backups_Helper::security_nonce( 'linode_action_restore_backup' );
3236
3237 // Grab $_POST data.
3238 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3239 $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3240
3241 // Grab IDs from websites.
3242 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3243 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3244
3245 // Grab Linode Access token.
3246 $accessToken = static::get_linode_api_key();
3247
3248 // Set which Backup to restore to.
3249 $backup_data = array(
3250 'instance_id' => $instance_id,
3251 'overwrite' => true,
3252 );
3253 $backup_data = wp_json_encode( $backup_data );
3254
3255 // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups/{backupId}/restore.
3256 $restore_response = (array) static::call_linode_api( 'POST', static::INSTANCES . $instance_id . '/backups/' . $backup_id . '/restore', $accessToken, $backup_data );
3257 $restore_response = (array) json_decode( $restore_response['0'] );
3258
3259 sleep( 20 );
3260 static::linode_action_linode_status( $website_id );
3261 }
3262
3263 /**
3264 * Linode: action Linode status.
3265 *
3266 * Check linode status to know when to reboot server.
3267 *
3268 * @param int $website_id Child Site ID.
3269 *
3270 * @return void
3271 */
3272 public static function linode_action_linode_status( $website_id ) {
3273
3274 // Grab IDs from websites.
3275 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3276 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3277
3278 // Grab Linode Access token.
3279 $accessToken = static::get_linode_api_key();
3280
3281 // Send Payload & grab instance status. https://api.linode.com/v4/linode/instances/{linodeId}.
3282 $linode_instance_response = (array) static::call_linode_api( 'GET', static::INSTANCES . $instance_id, $accessToken );
3283 $linode_instance_response = json_decode( $linode_instance_response['0'] );
3284 $linode_instance_status = $linode_instance_response->status;
3285
3286 // Check if linode status is 'offline'.
3287 // Check linode status to know when to reboot server.
3288 switch ( $linode_instance_status ) {
3289 case 'running':
3290 case 'restoring':
3291 case 'Linode Busy.':
3292 // Re-Check status.
3293 sleep( 1 );
3294 static::linode_action_linode_status( $website_id );
3295 break;
3296 case 'offline':
3297 // Starting server.
3298 static::linode_action_linode_start( $instance_id );
3299 break;
3300 default:
3301 break;
3302 }
3303 }
3304
3305 /**
3306 * Linode: action Linode start.
3307 *
3308 * @param int $instance_id Linode Instance ID.
3309 *
3310 * @return void
3311 */
3312 public static function linode_action_linode_start( $instance_id ) {
3313 sleep( 10 );
3314 // Grab Linode Access token.
3315 $accessToken = static::get_linode_api_key();
3316
3317 // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/boot.
3318 $linode_boot_response = (array) static::call_linode_api( 'POST', static::INSTANCES . $instance_id . '/boot', $accessToken );
3319 $linode_boot_response = (array) json_decode( $linode_boot_response['0'] );
3320
3321 wp_send_json( 'true' );
3322 }
3323
3324 /**
3325 * Linode: action cancel backups.
3326 *
3327 * Cancel all backups for a Linode Instance.
3328 *
3329 * @return void
3330 */
3331 public function linode_action_cancel_backups() {
3332
3333 Api_Backups_Helper::security_nonce( 'linode_action_cancel_backups' );
3334
3335 // Grab $_POST data.
3336 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3337
3338 // Grab IDs from websites.
3339 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3340 $instance_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3341
3342 // Grab Vultr Access token.
3343 $accessToken = static::get_linode_api_key();
3344
3345 // Send Payload & create backup. https://api.linode.com/v4/linode/instances/{linodeId}/backups/cancel.
3346 $api_response = (object) static::call_linode_api( 'POST', static::INSTANCES . $instance_id . '/backups/cancel', $accessToken );
3347
3348 // Return AJAX.
3349 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3350 // Store Available backups.
3351 if ( ! $api_response ) {
3352 wp_send_json_error( 'false' );
3353
3354 } else {
3355 $all_backups = array();
3356 // Grab Site options then update Child Site options.
3357 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_linode_available_backups', $all_backups );
3358 }
3359 wp_send_json( 'true' );
3360 }
3361 }
3362
3363 /*********************************************************************************
3364 * DigitalOcean API Methods.
3365 **********************************************************************************/
3366
3367 /**
3368 * Call DigitalOcean API, Authenticate & perform given method.
3369 *
3370 * @param string $method GET|POST|PUT|DELETE.
3371 * @param string $url relative URL for the call.
3372 * @param string $accessToken Access token generated using OAuth Call.
3373 * @param mixed $backup_data Json encoded array - Optional post data for the call.
3374 * @return array Output from DigitalOcean API.
3375 */
3376 public static function call_digitalocean_api( $method, $url, $accessToken, $backup_data = array() ) {
3377
3378 $baseurl = 'https://api.digitalocean.com/v2';
3379
3380 $curl = curl_init();
3381 curl_setopt_array(
3382 $curl,
3383 array(
3384 CURLOPT_URL => $baseurl . $url,
3385 CURLOPT_RETURNTRANSFER => true,
3386 CURLOPT_ENCODING => '',
3387 CURLOPT_MAXREDIRS => 10,
3388 CURLOPT_TIMEOUT => 0,
3389 CURLOPT_FOLLOWLOCATION => true,
3390 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3391 CURLOPT_CUSTOMREQUEST => $method,
3392 CURLOPT_POSTFIELDS => $backup_data,
3393 CURLOPT_HTTPHEADER => array(
3394 "Authorization: Bearer $accessToken",
3395 'Content-Type: application/json',
3396 ),
3397 )
3398 );
3399
3400 $resp = curl_exec( $curl );
3401
3402 $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
3403 $response['httpCode'] = $httpCode;
3404 $response['response'] = $resp;
3405 if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
3406 $response['status'] = 'false';
3407 } else {
3408 $response['status'] = 'true';
3409
3410 }
3411 curl_close( $curl );
3412 return $response;
3413 }
3414
3415
3416 /**
3417 * DigitalOcean: Action create backup.
3418 *
3419 * Create a backup of the droplet.
3420 *
3421 * @return void
3422 */
3423 public function ajax_digitalocean_action_create_backup() {
3424 Api_Backups_Helper::security_nonce( 'digitalocean_action_create_backup' );
3425 static::digitalocean_action_create_backup();
3426 }
3427
3428 /**
3429 * DigitalOcean: Action create backup.
3430 *
3431 * Create a backup of the droplet.
3432 *
3433 * @return void
3434 */
3435 public function ajax_digitalocean_action_individual_create_backup() {
3436 Api_Backups_Helper::security_nonce( 'digitalocean_action_individual_create_backup' );
3437 static::digitalocean_action_create_backup();
3438 }
3439
3440 /**
3441 * DigitalOcean: Action create backup.
3442 *
3443 * Create a backup of the droplet.
3444 *
3445 * @param int $website_id Website ID.
3446 * @param bool $ret_val Return output or not.
3447 *
3448 * @return mixed
3449 */
3450 public static function digitalocean_action_create_backup( $website_id = '', $ret_val = false ) {
3451
3452 // Grab $_POST data.
3453 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : $website_id; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3454
3455 // Grab Child Site options.
3456 $website = Api_Backups_Helper::get_website_by_id( $website_id );
3457
3458 // Grab IDs from websites.
3459 $site_options = Api_Backups_Helper::get_website_options( $website, array( 'mainwp_3rd_party_instance_id' ) );
3460 $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3461
3462 // Grab Access token.
3463 $accessToken = static::get_digitalocean_api_key();
3464
3465 // Set backup type and name.
3466 $backup_data = array(
3467 'type' => 'snapshot',
3468 'name' => 'MainWP API Backups - ' . $website['name'],
3469 );
3470 $backup_data = wp_json_encode( $backup_data );
3471
3472 // Send Payload & create backup.
3473 $api_response = static::call_digitalocean_api( 'POST', static::DROPLETS . $droplet_id . '/actions', $accessToken, $backup_data );
3474
3475 $success = true;
3476
3477 // Store Last Backup timestamp.
3478 if ( 'true' === $api_response['status'] ) {
3479 $local_time = current_datetime();
3480 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
3481 Api_Backups_Helper::update_website_option( $website, 'mainwp_3rd_party_digitalocean_last_backup', $current_time );
3482 } else {
3483 $success = false;
3484 }
3485
3486 if ( $ret_val ) {
3487 return $api_response;
3488 }
3489
3490 // Return AJAX.
3491 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3492 // Store Last Backup timestamp.
3493 if ( $success ) {
3494 wp_send_json( 'true' );
3495 } else {
3496 wp_die( 'false' );
3497 }
3498 }
3499 }
3500
3501 /**
3502 *
3503 * DigitalOcean: Action refresh available backups.
3504 *
3505 * Save backups to DB for the selected DigitalOcean server.
3506 *
3507 * @return void
3508 */
3509 public function digitalocean_action_refresh_available_backups() {
3510
3511 Api_Backups_Helper::security_nonce( 'digitalocean_action_refresh_available_backups' );
3512
3513 // Grab website_id & backup_api name from Ajax post.
3514 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3515 // Grab $_POST data.
3516 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3517 } else {
3518 // Grab $_GET['data'] from url if not Ajax call.
3519 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3520 // $backup_api is pulled from the DB below if not Ajax call.
3521 }
3522
3523 // Grab IDs from websites.
3524 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3525 $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3526
3527 // Grab Vultr Access token.
3528 $accessToken = static::get_digitalocean_api_key();
3529
3530 // Send Payload & create backup.
3531 $api_response = static::call_digitalocean_api( 'GET', static::DROPLETS . $droplet_id . '/snapshots', $accessToken );
3532 $all_backups = $api_response['response'];
3533
3534 // Grab Site options then update Child Site options.
3535 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_digitalocean_available_backups', $all_backups );
3536 Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'digitalocean' );
3537
3538 // Return AJAX.
3539 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3540 // Store Last Backup timestamp.
3541 if ( 'true' === $api_response['status'] ) {
3542 wp_send_json( 'true' );
3543 } else {
3544 wp_die( 'false' );
3545 }
3546 }
3547 }
3548
3549 /**
3550 * DigitalOcean: Action restore backup.
3551 *
3552 * Restore a backup of the droplet.
3553 *
3554 * @return void
3555 */
3556 public function digitalocean_action_restore_backup() {
3557
3558 Api_Backups_Helper::security_nonce( 'digitalocean_action_restore_backup' );
3559
3560 // Grab $_POST data.
3561 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3562 $snapshot_id = isset( $_POST['snapshot_id'] ) ? wp_unslash( $_POST['snapshot_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3563
3564 // Grab IDs from websites.
3565 $site_options = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_3rd_party_instance_id' ) );
3566 $droplet_id = isset( $site_options['mainwp_3rd_party_instance_id'] ) ? $site_options['mainwp_3rd_party_instance_id'] : null;
3567
3568 // Grab Access token.
3569 $accessToken = static::get_digitalocean_api_key();
3570
3571 // Set backup type and name.
3572 $backup_data = array(
3573 'type' => 'restore',
3574 'image' => $snapshot_id,
3575 );
3576 $backup_data = wp_json_encode( $backup_data );
3577
3578 // Send Payload & create backup.
3579 $api_response = static::call_digitalocean_api( 'POST', static::DROPLETS . $droplet_id . '/actions', $accessToken, $backup_data );
3580
3581 // Return AJAX.
3582 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3583 // Store Last Backup timestamp.
3584 if ( 'true' === $api_response['status'] && '201' === $api_response['httpCode'] ) {
3585 wp_send_json( 'true' );
3586 } else {
3587 wp_die( 'false' );
3588 }
3589 }
3590 }
3591
3592 /**
3593 * DigitalOcean: Action delete backup.
3594 *
3595 * Delete a backup of the droplet.
3596 *
3597 * @return void
3598 */
3599 public static function digitalocean_action_delete_backup() {
3600
3601 Api_Backups_Helper::security_nonce( 'digitalocean_action_delete_backup' );
3602
3603 // Grab $_POST data.
3604 $snapshot_id = isset( $_POST['snapshot_id'] ) ? wp_unslash( $_POST['snapshot_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3605
3606 // Grab Access token.
3607 $accessToken = static::get_digitalocean_api_key();
3608
3609 // Send Payload.
3610 $api_response = static::call_digitalocean_api( 'DELETE', static::SNAPSHOTS . $snapshot_id, $accessToken );
3611
3612 // Return AJAX.
3613 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3614 if ( '' !== $api_response['response'] && '204' === $api_response['httpCode'] ) {
3615 wp_send_json_error( 'false' );
3616 }
3617 wp_send_json( 'true' );
3618 }
3619 }
3620
3621 /*********************************************************************************
3622 * Plesk API Methods.
3623 **********************************************************************************/
3624 /**
3625 * Call Plesk API, Authenticate & perform given method.
3626 *
3627 * @param string $method GET|POST|PUT|DELETE.
3628 * @param string $url API endpoint for the call.
3629 * @param string $baseurl Base url.
3630 * @param string $api_key Plesk API Key.
3631 * @param mixed $backup_data Json encoded array - Optional post data for the call.
3632 * @return array Output from cPanel API.
3633 */
3634 public static function call_plesk_api( $method, $url, $baseurl, $api_key, $backup_data = array() ) {
3635
3636 // To fix double slash issue in url if exists. If url starts with / and baseurl ends with /, then remove the last slash from baseurl.
3637 if ( '/' === substr( $url, 0, 1 ) && '/' === substr( $baseurl, -1 ) ) {
3638 $baseurl = rtrim( $baseurl, '/' );
3639 }
3640
3641 $full_url = $baseurl . $url;
3642
3643 $curl = curl_init();
3644
3645 $api_Key = $api_key;
3646 curl_setopt_array(
3647 $curl,
3648 array(
3649 CURLOPT_URL => $full_url,
3650 CURLOPT_RETURNTRANSFER => true,
3651 CURLOPT_ENCODING => '',
3652 CURLOPT_MAXREDIRS => 10,
3653 CURLOPT_TIMEOUT => 0,
3654 CURLOPT_FOLLOWLOCATION => true,
3655 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
3656 CURLOPT_CUSTOMREQUEST => $method,
3657 CURLOPT_POSTFIELDS => $backup_data,
3658 CURLOPT_HTTPHEADER => array(
3659 'Accept: */*', // DO NOT REMOVE THIS LINE! Plesk API will DELETE ALL BACKUPS if this is not included!
3660 'Content-Type: application/json',
3661 "X-API-Key: $api_Key",
3662 ),
3663 )
3664 );
3665
3666 $resp = curl_exec( $curl );
3667
3668 $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
3669
3670 $response['httpCode'] = $httpCode;
3671 $response['response'] = $resp;
3672
3673 if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
3674 $response['status'] = 'false';
3675 } else {
3676 $response['status'] = 'true';
3677 }
3678 curl_close( $curl );
3679 return $response;
3680 }
3681
3682 /**
3683 *
3684 * Plesk: Grab Home Directory.
3685 *
3686 * Grab needed home directory for downloading backups.
3687 *
3688 * @return string|bool
3689 */
3690 public static function get_plesk_home_dir() {
3691 // Authenticate plesk account.
3692 $plesk_authentication_credentials = static::get_plesk_authentication_credentials();
3693 $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3694 $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3695 $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3696
3697 $api_response = static::call_plesk_api( 'GET', '/api/modules/wp-toolkit/v1/installations?installationsIds%5B%5D=' . $plesk_installation_id, $plesk_baseurl, $plesk_api_key );
3698
3699 $response_decoded = ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3700 return is_array( $response_decoded ) && ! empty( $response_decoded[0] ) && ! empty( $response_decoded['0']->domain->name ) ? $response_decoded['0']->domain->name : false;
3701 }
3702
3703 /**
3704 *
3705 * Plesk: Authentication.
3706 *
3707 * Grab needed authentication credentials for Plesk API - either from global settings or individual settings.
3708 *
3709 * @param int $website_id Website ID.
3710 *
3711 * @return array
3712 */
3713 public static function get_plesk_authentication_credentials( $website_id = null ) { //phpcs:ignore -- NOSONAR - complex.
3714
3715 $plesk_authentication_credentials = array();
3716 // Grab website_id & from Ajax post if $website_id is not set.
3717 if ( empty( $website_id ) ) {
3718 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3719 if ( isset( $_POST['website_id'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3720 // Grab $_POST data.
3721 $website_id = intval( $_POST['website_id'] ); //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3722 } else {
3723 // Grab $_GET['data'] from url.
3724 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3725 }
3726 } else {
3727 // Grab $_GET['data'] from url.
3728 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3729 }
3730 }
3731
3732 // Global / Individual check.
3733 $global_individual_check = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_plesk_individual' ) );
3734 $mainwp_enable_plesk_individual = isset( $global_individual_check['mainwp_enable_plesk_individual'] ) ? $global_individual_check['mainwp_enable_plesk_individual'] : '0';
3735
3736 if ( 'on' === $mainwp_enable_plesk_individual ) {
3737 // Grab cPanel baseurl, username & password.
3738 $baseurl = Api_Backups_Helper::get_website_options( $website_id, array( 'plesk_api_url' ) );
3739 $plesk_baseurl = isset( $baseurl['plesk_api_url'] ) ? $baseurl['plesk_api_url'] : null;
3740
3741 // Grab Plesk password.
3742 $plesk_api_key = Api_Backups_Utility::get_instance()->get_child_api_key( $website_id, 'plesk' );
3743
3744 // Grab Plesk Installation ID.
3745 $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_plesk_installation_id' ) );
3746 $plesk_installation_id = isset( $site_path['mainwp_plesk_installation_id'] ) ? $site_path['mainwp_plesk_installation_id'] : null;
3747
3748 } elseif ( '0' === $mainwp_enable_plesk_individual ) {
3749 // Grab Plesk baseurl, username & password.
3750 $plesk_baseurl = ( false === get_option( 'mainwp_plesk_api_url' ) ) ? null : get_option( 'mainwp_plesk_api_url' );
3751
3752 // Grab Plesk password.
3753 $plesk_api_key = static::get_plesk_api_key();
3754
3755 // Grab Plesk Installation ID.
3756 $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_plesk_installation_id' ) );
3757 $plesk_installation_id = isset( $site_path['mainwp_plesk_installation_id'] ) ? $site_path['mainwp_plesk_installation_id'] : null;
3758 }
3759
3760 // Build array.
3761 $plesk_authentication_credentials[] = array(
3762 'plesk_baseurl' => $plesk_baseurl,
3763 'plesk_api_key' => $plesk_api_key,
3764 'plesk_installation_id' => $plesk_installation_id,
3765 'website_id' => $website_id,
3766 );
3767
3768 return $plesk_authentication_credentials;
3769 }
3770
3771 /**
3772 * Plesk: action refresh available backups.
3773 *
3774 * Refresh available backups for the selected server.
3775 *
3776 * @return void
3777 */
3778 public function ajax_plesk_action_refresh_available_backups() {
3779 Api_Backups_Helper::security_nonce( 'plesk_action_refresh_available_backups' );
3780 static::plesk_action_refresh_available_backups();
3781 die();
3782 }
3783
3784 /**
3785 * Plesk: action create backup.
3786 *
3787 * Create backup for the selected server.
3788 *
3789 * @return void
3790 */
3791 public function ajax_plesk_action_create_backup() {
3792 Api_Backups_Helper::security_nonce( 'plesk_action_create_backup' );
3793 static::plesk_action_create_backup();
3794 die();
3795 }
3796
3797 /**
3798 * Plesk: action restore backup.
3799 *
3800 * Create backup for the selected server.
3801 *
3802 * @return void
3803 */
3804 public function ajax_plesk_action_restore_backup() {
3805 Api_Backups_Helper::security_nonce( 'plesk_action_restore_backup' );
3806 static::plesk_action_restore_backup();
3807 die();
3808 }
3809
3810 /**
3811 * Plesk: action delete backup.
3812 *
3813 * Delete backup for the selected server.
3814 *
3815 * @return void
3816 */
3817 public function ajax_plesk_action_delete_backup() {
3818 Api_Backups_Helper::security_nonce( 'plesk_action_delete_backup' );
3819 static::plesk_action_delete_backup();
3820 die();
3821 }
3822
3823 /**
3824 *
3825 * Plesk: Action refresh available backups.
3826 *
3827 * Save backups to DB for the selected server.
3828 *
3829 * @return void
3830 */
3831 public static function plesk_action_refresh_available_backups() {
3832
3833 // Authenticate plesk account.
3834 $plesk_authentication_credentials = static::get_plesk_authentication_credentials();
3835 $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3836 $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3837 $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3838 $website_id = $plesk_authentication_credentials[0]['website_id'];
3839
3840 // Grab backup meta.
3841 $api_response = static::call_plesk_api( 'GET', '/api/modules/wp-toolkit/v1/installations/' . $plesk_installation_id . '/backups/meta', $plesk_baseurl, $plesk_api_key );
3842
3843 $all_backups = $api_response['response'];
3844 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_plesk_available_backups', $all_backups );
3845 Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'plesk' );
3846
3847 // Return AJAX.
3848 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3849 // Store Last Backup timestamp.
3850 if ( 'true' === $api_response['status'] ) {
3851 wp_send_json( 'true' );
3852 } else {
3853 wp_die( 'false' );
3854 }
3855 }
3856 }
3857
3858 /**
3859 *
3860 * Plesk: Action create manual backup.
3861 *
3862 * Create a Plesk Backup.
3863 *
3864 * @param bool $ret_val Return output or not.
3865 * @param int $website_id Website ID.
3866 *
3867 * @return mixed
3868 */
3869 public static function plesk_action_create_backup( $ret_val = false, $website_id = null ) { //phpcs:ignore -- NOSONAR - complex.
3870
3871 // Authenticate plesk account.
3872 $plesk_authentication_credentials = static::get_plesk_authentication_credentials( $website_id );
3873 $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3874 $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3875 $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3876 $website_id = $plesk_authentication_credentials[0]['website_id'];
3877
3878 $backup_data = array(
3879 'installationId' => $plesk_installation_id,
3880 );
3881 $backup_data = wp_json_encode( $backup_data );
3882
3883 // Send Payload & create backup. https://{your_plesk_url}/api/modules/wp-toolkit/v1/features/backups/creator.
3884 $api_response = static::call_plesk_api( 'POST', '/api/modules/wp-toolkit/v1/features/backups/creator', $plesk_baseurl, $plesk_api_key, $backup_data );
3885
3886 $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3887 $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
3888
3889 $success = false;
3890 if ( is_array( $api_response ) && isset( $api_response['status'] ) && 'true' === $api_response['status'] ) {
3891 $success = true;
3892 }
3893
3894 if ( empty( $errors ) ) {
3895 // Save Timestamp.
3896 $local_time = current_datetime();
3897 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
3898 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_plesk_last_backup', $current_time );
3899 }
3900
3901 if ( $ret_val ) {
3902 return $api_response;
3903 }
3904
3905 // Return AJAX.
3906 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3907 // Store Last Backup timestamp.
3908 if ( $success ) {
3909 wp_send_json( 'true' );
3910 } else {
3911 if ( empty( $errors ) ) {
3912 $errors = esc_html__( 'Undefined error. Please try again.', 'mainwp' );
3913 }
3914 wp_die( esc_html( $errors ) );
3915 }
3916 }
3917 }
3918
3919 /**
3920 *
3921 * Plesk: Action restore backup.
3922 *
3923 * Restore Plesk Backup.
3924 */
3925 public static function plesk_action_restore_backup() {
3926
3927 // Grab website_id & backup_api name from Ajax post.
3928 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3929 // Grab $_POST data.
3930 $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3931 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3932 }
3933
3934 // Authenticate plesk account.
3935 $plesk_authentication_credentials = static::get_plesk_authentication_credentials( $website_id );
3936 $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3937 $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3938 $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3939
3940 $backup_data = array(
3941 'installationId' => $plesk_installation_id,
3942 'fileName' => $backup_name,
3943 'clobber' => 'false',
3944 'dropAllDatabaseTables' => 'false',
3945 );
3946
3947 $backup_data = wp_json_encode( $backup_data );
3948
3949 // Send Payload & create backup. https://{your_plesk_url}/api/modules/wp-toolkit/v1/features/backups/restorer.
3950 $api_response = static::call_plesk_api( 'POST', '/api/modules/wp-toolkit/v1/features/backups/restorer', $plesk_baseurl, $plesk_api_key, $backup_data );
3951
3952 $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
3953 $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
3954
3955 // Return AJAX.
3956 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3957 // Store Last Backup timestamp.
3958 if ( empty( $errors ) ) {
3959 wp_send_json( 'true' );
3960 } else {
3961 wp_die( esc_html( $errors ) );
3962 }
3963 }
3964 }
3965
3966 /**
3967 *
3968 * Plesk: Action delete backup.
3969 *
3970 * Delete Plesk Backup.
3971 */
3972 public static function plesk_action_delete_backup() {
3973
3974 // Grab website_id & backup_api name from Ajax post.
3975 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
3976 // Grab $_POST data.
3977 $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
3978 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
3979 }
3980
3981 // Authenticate plesk account.
3982 $plesk_authentication_credentials = static::get_plesk_authentication_credentials( $website_id );
3983 $plesk_baseurl = $plesk_authentication_credentials[0]['plesk_baseurl'];
3984 $plesk_api_key = $plesk_authentication_credentials[0]['plesk_api_key'];
3985 $plesk_installation_id = $plesk_authentication_credentials[0]['plesk_installation_id'];
3986
3987 $backup_data = wp_json_encode(
3988 array(
3989 'delete' => true,
3990 )
3991 );
3992
3993 /**
3994 * Payload for deleting a backup.
3995 * plesk_baseurl must include the port number.
3996 * https://{plesk_baseurl:8443}/api/modules/wp-toolkit/v1/installations/{plesk_installation_id}/backups?files%5B%5D={backup_name}
3997 * Backup Name Example ( must be urlencoded ): sweet-lovelace.104-207-132-143.plesk.page_site-1__2024-01-12T16_37_25%2B0000.zip
3998 */
3999
4000 $payload = '/api/modules/wp-toolkit/v1/installations/' . $plesk_installation_id . '/backups?files%5B%5D=' . rawurlencode( $backup_name );
4001
4002 // Send Payload & create backup.
4003 $api_response = static::call_plesk_api( 'DELETE', $payload, $plesk_baseurl, $plesk_api_key, $backup_data );
4004
4005 $response_decoded = ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
4006 $errors = ! empty( $response_decoded ) && ! empty( $response_decoded->task->errors ) ? $response_decoded->task->errors : '';
4007
4008 // Return AJAX.
4009 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4010 // Store Last Backup timestamp.
4011 if ( empty( $errors ) && '204' === (string) $api_response['httpCode'] && 'true' === (string) $api_response['status'] ) {
4012 wp_send_json( 'true' );
4013 } else {
4014 wp_die( esc_html( $errors ) );
4015 }
4016 }
4017 }
4018
4019 /*********************************************************************************
4020 * CPanel API Methods.
4021 **********************************************************************************/
4022 /**
4023 * Call cPanel API, Authenticate & perform given method.
4024 *
4025 * @param string $method GET|POST|PUT|DELETE.
4026 * @param string $url API endpoint for the call.
4027 * @param string $baseurl Baseurl.
4028 * @param string $username cPanel account username.
4029 * @param string $password cPanel account password.
4030 * @param mixed $backup_data Json encoded array - Optional post data for the call.
4031 * @return array Output from cPanel API.
4032 */
4033 public static function call_cpanel_api( $method, $url, $baseurl, $username, $password, $backup_data = array() ) {
4034
4035 // base64encode cPanel Username & Password.
4036 $base64encoded = base64_encode( $username . ':' . $password ); //phpcs:ignore -- base64 encode.
4037 $curl = curl_init();
4038
4039 curl_setopt_array(
4040 $curl,
4041 array(
4042 CURLOPT_URL => $baseurl . $url,
4043 CURLOPT_RETURNTRANSFER => true,
4044 CURLOPT_ENCODING => '',
4045 CURLOPT_MAXREDIRS => 10,
4046 CURLOPT_TIMEOUT => 0,
4047 CURLOPT_FOLLOWLOCATION => true,
4048 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
4049 CURLOPT_CUSTOMREQUEST => $method,
4050 CURLOPT_POSTFIELDS => $backup_data,
4051 CURLOPT_HTTPHEADER => array(
4052 'Content-Type: text/plain',
4053 "Authorization: Basic $base64encoded",
4054 ),
4055 )
4056 );
4057
4058 $resp = curl_exec( $curl );
4059
4060 $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
4061 $response['httpCode'] = $httpCode;
4062 $response['response'] = $resp;
4063 if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
4064 $response['status'] = 'false';
4065 } else {
4066 $response['status'] = 'true';
4067 }
4068 curl_close( $curl );
4069 return $response;
4070 }
4071
4072 /*********************************************************************************
4073 * CPanel API Methods.
4074 **********************************************************************************/
4075 /**
4076 * Call cPanel API, Authenticate & perform given method.
4077 *
4078 * @param string $method GET|POST|PUT|DELETE.
4079 * @param string $url API endpoint for the call.
4080 * @param string $baseurl base url.
4081 * @param string $username cPanel account username.
4082 * @param string $password cPanel account password.
4083 * @param mixed $backup_data Json encoded array - Optional post data for the call.
4084 * @return array Output from cPanel API.
4085 */
4086 public static function call_cpanel_api_json( $method, $url, $baseurl, $username, $password, $backup_data = array() ) {
4087
4088 // base64encode cPanel Username & Password.
4089 $base64encoded = base64_encode( $username . ':' . $password ); //phpcs:ignore -- base64 encode.
4090 $curl = curl_init();
4091
4092 curl_setopt_array(
4093 $curl,
4094 array(
4095 CURLOPT_URL => $baseurl . $url,
4096 CURLOPT_RETURNTRANSFER => true,
4097 CURLOPT_ENCODING => '',
4098 CURLOPT_MAXREDIRS => 10,
4099 CURLOPT_TIMEOUT => 0,
4100 CURLOPT_FOLLOWLOCATION => true,
4101 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
4102 CURLOPT_CUSTOMREQUEST => $method,
4103 CURLOPT_POSTFIELDS => $backup_data,
4104 CURLOPT_HTTPHEADER => array(
4105 'Accept: */*', // DO NOT REMOVE THIS LINE! Plesk API will DELETE ALL BACKUPS if this is not included!
4106 'Content-Type: application/json',
4107 "Authorization: Basic $base64encoded",
4108 ),
4109 )
4110 );
4111
4112 $resp = curl_exec( $curl );
4113
4114 $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
4115 $response['httpCode'] = $httpCode;
4116 $response['response'] = $resp;
4117 if ( '201' !== $httpCode && '200' !== $httpCode && '204' !== $httpCode ) {
4118 $response['status'] = 'false';
4119 } else {
4120 $response['status'] = 'true';
4121 }
4122 curl_close( $curl );
4123 return $response;
4124 }
4125
4126 /**
4127 *
4128 * CPanel: Authentication.
4129 *
4130 * Grab needed authentication credentials for cPanel API - either from global settings or individual settings.
4131 *
4132 * @param int $website_id Website ID.
4133 *
4134 * @return array
4135 */
4136 public static function get_cpanel_authentication_credentials( $website_id = '' ) { //phpcs:ignore -- NOSONAR - complex.
4137
4138 $cpanel_authentication_credentials = array();
4139
4140 // Grab website_id & from Ajax post if $website_id is not set.
4141 if ( empty( $website_id ) ) {
4142 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4143 // Grab $_POST data.
4144 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4145 } else {
4146 // Grab $_GET['data'] from url if not Ajax call.
4147 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4148 }
4149 }
4150
4151 // Global / Individual check.
4152 $global_individual_check = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_cpanel_individual' ) );
4153 $mainwp_enable_cpanel_individual = isset( $global_individual_check['mainwp_enable_cpanel_individual'] ) ? $global_individual_check['mainwp_enable_cpanel_individual'] : '0';
4154
4155 if ( 'on' === $mainwp_enable_cpanel_individual ) {
4156 // Grab cPanel baseurl, username & password.
4157 $baseurl = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_api_url' ) );
4158 $cpanel_baseurl = isset( $baseurl['cpanel_api_url'] ) ? $baseurl['cpanel_api_url'] : null;
4159
4160 // Grab cPanel username.
4161 $username = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_account_username' ) );
4162 $cpanel_username = isset( $username['cpanel_account_username'] ) ? $username['cpanel_account_username'] : null;
4163
4164 // Grab cPanel password.
4165 $cpanel_password = Api_Backups_Utility::get_instance()->get_child_api_key( $website_id, 'cpanel' );
4166
4167 // Grab cPanel site path.
4168 $site_path = Api_Backups_Helper::get_website_options( $website_id, array( 'cpanel_site_path' ) );
4169 $cpanel_site_path = isset( $site_path['cpanel_site_path'] ) ? $site_path['cpanel_site_path'] : null;
4170
4171 } elseif ( '0' === $mainwp_enable_cpanel_individual ) {
4172 // Grab cPanel baseurl, username & password.
4173 $cpanel_baseurl = get_option( 'mainwp_cpanel_url' ); // Fixing when mergeing ???.
4174 // Grab cPanel username.
4175 $cpanel_username = get_option( 'mainwp_cpanel_account_username' ); // Fixing when mergeing ???.
4176 // Grab cPanel password.
4177 $cpanel_password = static::get_cpanel_account_password();
4178
4179 // Grab cPanel site path.
4180 $cpanel_site_path = ( false === get_option( 'mainwp_cpanel_site_path' ) ) ? null : get_option( 'mainwp_cpanel_site_path' );
4181 }
4182
4183 // Build array.
4184 $cpanel_authentication_credentials[] = array(
4185 'cpanel_baseurl' => $cpanel_baseurl,
4186 'cpanel_username' => $cpanel_username,
4187 'cpanel_password' => $cpanel_password,
4188 'cpanel_site_path' => $cpanel_site_path,
4189 'website_id' => $website_id,
4190 );
4191
4192 return $cpanel_authentication_credentials;
4193 }
4194
4195 /**
4196 *
4197 * CPanel: Action get cPanel Home Directory.
4198 *
4199 * Grab cPanel Home Directory for manual backup links.
4200 *
4201 * @return string
4202 */
4203 public static function cpanel_action_get_home_directory() {
4204
4205 // Authenticate cPanel account.
4206 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4207 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4208 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4209 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4210
4211 // Send Payload.
4212 $api_response = static::call_cpanel_api( 'GET', '/execute/Variables/get_user_information', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4213 $api_response_decoded = json_decode( $api_response['response'] );
4214
4215 if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data->home ) ) {
4216 $cpanel_home_directory = $api_response_decoded->data->home;
4217 } else {
4218 $cpanel_home_directory = '';
4219 }
4220
4221 return $cpanel_home_directory;
4222 }
4223
4224 /**
4225 * Get cPanel manual account backups.
4226 *
4227 * @return false|string cPanel account backups
4228 */
4229 public static function get_cpanel_manual_account_backups() {
4230
4231 // Define array for Manual Backups.
4232 $manual_backups = array();
4233
4234 // Authenticate cPanel account.
4235 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4236 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4237 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4238 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4239
4240 // Send Payload.
4241 $api_response = static::call_cpanel_api( 'GET', '/execute/Fileman/list_files?dir=/&include_mime=1&types=file', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4242 $api_response_decoded = json_decode( $api_response['response'] );
4243
4244 // Build list.
4245 if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data ) ) {
4246 $files = $api_response_decoded->data;
4247 foreach ( $files as $file ) {
4248 if ( 'application/x-gzip' === $file->rawmimetype ) {
4249 $manual_backups[] = array(
4250 'file_name' => $file->file,
4251 'absolute_dir' => $file->absdir,
4252 'timestamp' => $file->ctime,
4253 );
4254 }
4255 }
4256 } else {
4257 $manual_backups = array();
4258 }
4259
4260 // return array of Manual Backups.
4261 return wp_json_encode( $manual_backups );
4262 }
4263
4264 /**
4265 * Get cPanel manual database backups.
4266 *
4267 * Create manual database backup via mysqldump.
4268 * Backups will be stored within `/uploads/mainwp/api_db_backups` directory.
4269 *
4270 * @param int $website_id Website ID.
4271 *
4272 * @return false|string cPanel account backups
4273 */
4274 public static function get_cpanel_manual_database_backups( $website_id = '' ) {
4275
4276 unset( $website_id );
4277
4278 // Define array for Manual Backups.
4279 $manual_backups = array();
4280
4281 // Authenticate cPanel account.
4282 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4283 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4284 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4285 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4286
4287 // Grab cPanel site path.
4288 $cpanel_db_backups_path = $cpanel_authentication_credentials[0]['cpanel_site_path'] . '/wp-content/uploads/mainwp/api_db_backups';
4289
4290 // Send Payload.
4291 $api_response = static::call_cpanel_api( 'GET', '/execute/Fileman/list_files?dir=' . $cpanel_db_backups_path . '&include_mime=1&types=file', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4292 $api_response_decoded = json_decode( $api_response['response'] );
4293
4294 // Build list.
4295 if ( is_object( $api_response_decoded ) && isset( $api_response_decoded->data ) ) {
4296 $files = $api_response_decoded->data;
4297 foreach ( $files as $file ) {
4298 if ( 'application/x-gzip' === $file->rawmimetype ) {
4299 $manual_backups[] = array(
4300 'file_name' => $file->file,
4301 'absolute_dir' => $file->absdir,
4302 'timestamp' => $file->ctime,
4303 );
4304 }
4305 }
4306 } else {
4307 $manual_backups = array();
4308 }
4309
4310 // return array of Manual Backups.
4311 return wp_json_encode( $manual_backups );
4312 }
4313
4314 /**
4315 *
4316 * Method get_3rdparty_installation_path().
4317 *
4318 * @param string $what what to get path.
4319 *
4320 * @return string api path.
4321 */
4322 public static function get_3rdparty_installation_path( $what = '' ) {
4323 $path = '/3rdparty/wpt/index.php/v1/installations/';
4324 if ( 'with_sort' === $what ) {
4325 $path .= '?sortBy=title&sortOrder=asc';
4326 }
4327 return $path;
4328 }
4329
4330 /**
4331 *
4332 * CPanel: Action refresh available WP-Toolit backups.
4333 *
4334 * Save backups to DB for the selected server.
4335 *
4336 * @param int $website_id Website id.
4337 *
4338 * @return array
4339 */
4340 public function get_cpanel_wp_toolkit_backups( $website_id ) {
4341
4342 // Grab Child Site options array.
4343 $website = Api_Backups_Helper::get_website_by_id( $website_id );
4344
4345 // Grab website url & trim trailing slash.
4346 $website_url = trim( $website['url'], '/' );
4347
4348 // Authenticate cPanel account.
4349 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4350 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4351 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4352 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4353
4354 $wp_toolkit_installation_id = '';
4355
4356 // Grab list of WP Toolkit installations.
4357 $wp_toolkit_installation_list = static::call_cpanel_api( 'GET', $this->get_3rdparty_installation_path( 'with_sort' ), $cpanel_baseurl, $cpanel_username, $cpanel_password );
4358 $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4359
4360 // Search for website url in list of WP Toolkit installations & grab Site ID.
4361 if ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4362 foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4363 if ( $site->url === $website_url ) {
4364 $wp_toolkit_installation_id = $site->id;
4365 }
4366 }
4367 }
4368
4369 // Grab backup meta for found Site ID.
4370 $wp_toolkit_backups = static::call_cpanel_api( 'GET', static::get_3rdparty_installation_path() . $wp_toolkit_installation_id . '/backups/meta', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4371 if ( 'true' === $wp_toolkit_backups['status'] ) {
4372 return $wp_toolkit_backups['response'];
4373 } else {
4374 return array();
4375 }
4376 }
4377
4378 /**
4379 * CPanel: action restore backup.
4380 *
4381 * Restore cPanel backup for the selected cPanel server.
4382 *
4383 * @return void
4384 */
4385 public function ajax_cpanel_action_restore_backup() {
4386 Api_Backups_Helper::security_nonce( 'cpanel_action_restore_backup' );
4387 static::cpanel_action_restore_backup();
4388 die();
4389 }
4390
4391 /**
4392 * CPanel: action restore database backup.
4393 *
4394 * Restore cPanel backup for the selected cPanel server.
4395 *
4396 * @return void
4397 */
4398 public function ajax_cpanel_action_restore_database_backup() {
4399 Api_Backups_Helper::security_nonce( 'cpanel_action_restore_database_backup' );
4400 static::cpanel_action_restore_database_backup();
4401 die();
4402 }
4403
4404 /**
4405 * CPanel: action restore manual backup.
4406 *
4407 * Restore cPanel backup for the selected cPanel server.
4408 *
4409 * @return void
4410 */
4411 public function ajax_cpanel_action_restore_manual_backup() {
4412 Api_Backups_Helper::security_nonce( 'cpanel_action_restore_manual_backup' );
4413 static::cpanel_action_restore_manual_backup();
4414 die();
4415 }
4416
4417 /**
4418 * CPanel: action refresh available backups.
4419 *
4420 * Refresh available backups for the selected cPanel server.
4421 *
4422 * @return void
4423 */
4424 public function ajax_cpanel_action_refresh_available_backups() {
4425 Api_Backups_Helper::security_nonce( 'cpanel_action_refresh_available_backups' );
4426 static::cpanel_action_refresh_available_backups();
4427 die();
4428 }
4429
4430 /**
4431 * CPanel: action create backup.
4432 *
4433 * Create backup for the selected cPanel server.
4434 *
4435 * @return void
4436 */
4437 public function ajax_cpanel_action_create_manual_backup() {
4438 Api_Backups_Helper::security_nonce( 'cpanel_action_create_manual_backup' );
4439 static::cpanel_action_create_manual_backup();
4440 die();
4441 }
4442
4443 /**
4444 * CPanel: action create WP-Toolkit backup.
4445 *
4446 * Create backup for the selected cPanel server.
4447 *
4448 * @return void
4449 */
4450 public function ajax_cpanel_action_create_wptk_backup() {
4451 Api_Backups_Helper::security_nonce( 'cpanel_action_create_wptk_backup' );
4452 static::cpanel_action_create_wptk_backup();
4453 die();
4454 }
4455
4456 /**
4457 * CPanel: action create WP-Toolkit backup.
4458 *
4459 * Create backup for the selected cPanel server.
4460 *
4461 * @return void
4462 */
4463 public function ajax_cpanel_action_restore_wptk_backup() {
4464 Api_Backups_Helper::security_nonce( 'cpanel_action_restore_wptk_backup' );
4465 static::cpanel_action_restore_wptk_backup();
4466 die();
4467 }
4468
4469 /**
4470 * CPanel: action delete WP-Toolkit backup.
4471 *
4472 * Create backup for the selected cPanel server.
4473 *
4474 * @return void
4475 */
4476 public function ajax_cpanel_action_delete_wptk_backup() {
4477 Api_Backups_Helper::security_nonce( 'cpanel_action_delete_wptk_backup' );
4478 static::cpanel_action_delete_wptk_backup();
4479 die();
4480 }
4481
4482 /**
4483 * CPanel: action create full backup.
4484 *
4485 * Create backup for the selected cPanel server.
4486 *
4487 * @return void
4488 */
4489 public static function ajax_cpanel_action_create_full_backup() { //phpcs:ignore -- NOSONAR - complex.
4490 Api_Backups_Helper::security_nonce( 'cpanel_action_create_full_backup' );
4491
4492 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4493 // Grab Child Site ID from $_POST data.
4494 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4495
4496 $opts = Api_Backups_Helper::get_website_options(
4497 $website_id,
4498 array(
4499 'mainwp_enable_wp_toolkit',
4500 )
4501 );
4502
4503 $mainwp_enable_wp_toolkit = '';
4504
4505 if ( is_array( $opts ) ) {
4506 $mainwp_enable_wp_toolkit = $opts['mainwp_enable_wp_toolkit'] ?? '0';
4507 }
4508
4509 // Create file backup.
4510 $file_backup_response = static::cpanel_action_create_manual_backup( true );
4511 $response_decoded = json_decode( $file_backup_response['response'] );
4512 $errors = $response_decoded->errors['0'];
4513
4514 // If no errors with file backup, create database backup.
4515 if ( empty( $errors ) ) {
4516
4517 // If no errors, create database backup.
4518 $database_backup_response = static::ajax_cpanel_action_create_database_backup( true, $website_id );
4519
4520 // If no errors, & WP-Toolikit is enabled create WP-Toolkit backup or return true.
4521 if ( 'GOOD' === $database_backup_response['result'] ) {
4522 // If WP Toolkit is enabled, create WP Toolkit backup.
4523 if ( 'on' === $mainwp_enable_wp_toolkit ) {
4524 $cpanel_wptk_backup_response = static::cpanel_action_create_wptk_backup( true );
4525 if ( '201' !== $cpanel_wptk_backup_response['httpCode'] && '200' !== $cpanel_wptk_backup_response['httpCode'] && '204' !== $cpanel_wptk_backup_response['httpCode'] ) {
4526 wp_die( 'There was an issue while creating the Database backup. Please check logs and try again.' );
4527 } else {
4528 // Return true for WP-Toolkit backup.
4529 wp_send_json( 'true' );
4530 }
4531 } else {
4532 // Return true for cPanel backup.
4533 wp_send_json( 'true' );
4534 }
4535 } else {
4536 // Return error for cPanel database backup.
4537 wp_die( 'There was an issue while creating the Cpanel Database backup. Please check logs and try again.' );
4538 }
4539 } else {
4540 // If cpanel file backup errors, return false.
4541 wp_die( esc_html( $errors ) );
4542 }
4543 }
4544 }
4545
4546 /**
4547 * CPanel: action create database backup.
4548 *
4549 * Create database backup for the selected cPanel server.
4550 *
4551 * @param bool $ret_val Return output or not.
4552 * @param int $website_id Website ID.
4553 *
4554 * @return mixed
4555 */
4556 public static function ajax_cpanel_action_create_database_backup( $ret_val = false, $website_id = null ) {
4557
4558 // Grab website_id & from Ajax post if $website_id is not set.
4559 if ( empty( $website_id ) ) {
4560
4561 // Check nonce.
4562 Api_Backups_Helper::security_nonce( 'cpanel_action_create_database_backup' );
4563
4564 // Grab $_POST data.
4565 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4566
4567 }
4568
4569 $post_data = array( 'mwp_action' => 'cpanel_mysqldump' );
4570
4571 $information = MainWP_Extensions_Handler::fetch_url_authed( $website_id, 'api_backups_mysqldump', $post_data );
4572
4573 if ( $ret_val ) {
4574 return $information;
4575 }
4576
4577 // Return AJAX.
4578 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4579 // Store Last Backup timestamp.
4580 if ( 'GOOD' === $information['result'] ) {
4581 wp_send_json( 'true' );
4582 } else {
4583 wp_die( 'There was an issue while creating the database backup. Please check logs and try again.' );
4584 }
4585 }
4586 }
4587
4588 /**
4589 *
4590 * CPanel: Action create manual backup.
4591 *
4592 * Create a cPanel Manual Backup.
4593 *
4594 * @param bool $ret_val Return output or not.
4595 * @param int $website_id Website ID.
4596 *
4597 * @return mixed
4598 */
4599 public static function cpanel_action_create_manual_backup( $ret_val = false, $website_id = null ) {
4600
4601 // Authenticate cPanel account.
4602 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials( $website_id );
4603 $website_id = $cpanel_authentication_credentials[0]['website_id'];
4604
4605 // Send Payload & create backup.
4606 $api_response = static::call_cpanel_api( 'GET', '/execute/Backup/fullbackup_to_homedir', $cpanel_authentication_credentials[0]['cpanel_baseurl'], $cpanel_authentication_credentials[0]['cpanel_username'], $cpanel_authentication_credentials[0]['cpanel_password'] );
4607 $response_decoded = is_array( $api_response ) && ! empty( $api_response['response'] ) ? json_decode( $api_response['response'] ) : '';
4608 $errors = ! empty( $response_decoded ) && is_object( $response_decoded ) && ! empty( $response_decoded->errors ) ? $response_decoded->errors['0'] : '';
4609
4610 if ( empty( $errors ) ) {
4611 // Save Timestamp.
4612 $local_time = current_datetime();
4613 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
4614 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_last_backup', $current_time );
4615 }
4616
4617 if ( $ret_val ) {
4618 return $api_response;
4619 }
4620
4621 // Return AJAX.
4622 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4623 // Store Last Backup timestamp.
4624 if ( empty( $errors ) ) {
4625 wp_send_json( 'true' );
4626 } else {
4627 wp_die( esc_html( $errors ) );
4628 }
4629 }
4630 }
4631
4632 /**
4633 *
4634 * CPanel: Action create WP-Toolkit backup.
4635 *
4636 * Create a cPanel Manual Backup.
4637 *
4638 * @param bool $ret_val Return output or not.
4639 *
4640 * @return array|void
4641 */
4642 public static function cpanel_action_create_wptk_backup( $ret_val = false ) { //phpcs:ignore -- NOSONAR - complex.
4643
4644 // Authenticate cPanel account.
4645 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4646 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4647 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4648 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4649 $website_id = $cpanel_authentication_credentials[0]['website_id'];
4650
4651 // Grab Child Site options array.
4652 $website = Api_Backups_Helper::get_website_by_id( $website_id );
4653
4654 // Grab website url & trim trailing slash.
4655 $website_url = trim( $website['url'], '/' );
4656
4657 // Grab list of WP Toolkit installations.
4658 $wp_toolkit_installation_list = static::call_cpanel_api( 'GET', static::get_3rdparty_installation_path( 'with_sort' ), $cpanel_baseurl, $cpanel_username, $cpanel_password );
4659 $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4660
4661 if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4662 $error = $wp_toolkit_installation_list_decoded->meta->message;
4663 wp_die( esc_html( $error ) );
4664 } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4665 foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4666 if ( $site->url === $website_url ) {
4667 $wp_toolkit_installation_id = $site->id;
4668 }
4669 }
4670 } else {
4671 $wp_toolkit_installation_id = '';
4672 }
4673
4674 // Prepare Backup Payload.
4675 $backup_data = array(
4676 'installationId' => $wp_toolkit_installation_id,
4677 );
4678 $backup_data = wp_json_encode( $backup_data );
4679
4680 // Grab list of WP Toolkit installations.
4681 $wp_toolkit_backup_response = static::call_cpanel_api_json( 'POST', '/3rdparty/wpt/index.php/v1/features/backups/creator', $cpanel_baseurl, $cpanel_username, $cpanel_password, $backup_data );
4682 $wp_toolkit_backup_response_decoded = is_array( $wp_toolkit_backup_response ) && ! empty( $wp_toolkit_backup_response['response'] ) ? json_decode( $wp_toolkit_backup_response['response'] ) : '';
4683
4684 $errors = '';
4685 if ( '201' !== $wp_toolkit_backup_response['httpCode'] && '200' !== $wp_toolkit_backup_response['httpCode'] && '204' !== $wp_toolkit_backup_response['httpCode'] ) {
4686 $errors = ! empty( $wp_toolkit_backup_response_decoded ) && ! empty( $wp_toolkit_backup_response_decoded->meta->message ) ? $wp_toolkit_backup_response_decoded->meta->message : '';
4687 } else {
4688 // Save Timestamp.
4689 $local_time = current_datetime();
4690 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
4691 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_last_backup', $current_time );
4692 }
4693
4694 if ( $ret_val ) {
4695 return $wp_toolkit_backup_response;
4696 }
4697
4698 // Return AJAX.
4699 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4700 // Store Last Backup timestamp.
4701 if ( empty( $errors ) ) {
4702 wp_send_json( 'true' );
4703 } else {
4704 wp_die( esc_html( $errors ) );
4705 }
4706 }
4707 }
4708
4709 /**
4710 *
4711 * CPanel: Action create WP-Toolkit backup.
4712 *
4713 * Create a cPanel Manual Backup.
4714 *
4715 * @param bool $ret_val Return output or not.
4716 *
4717 * @return array|void
4718 */
4719 public static function cpanel_action_restore_wptk_backup( $ret_val = false ) {
4720
4721 // Authenticate cPanel account.
4722 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4723 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4724 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4725 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4726 $website_id = $cpanel_authentication_credentials[0]['website_id'];
4727
4728 // Grab Child Site options array.
4729 $website = Api_Backups_Helper::get_website_by_id( $website_id );
4730
4731 // Grab website url & trim trailing slash.
4732 $website_url = trim( $website['url'], '/' );
4733
4734 // Grab list of WP Toolkit installations.
4735 $wp_toolkit_installation_list = static::call_cpanel_api( 'GET', static::get_3rdparty_installation_path( 'with_sort' ), $cpanel_baseurl, $cpanel_username, $cpanel_password );
4736 $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4737
4738 if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4739 $error = $wp_toolkit_installation_list_decoded->meta->message;
4740 wp_die( esc_html( $error ) );
4741 } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4742 foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4743 if ( $site->url === $website_url ) {
4744 $wp_toolkit_installation_id = $site->id;
4745 }
4746 }
4747 } else {
4748 $wp_toolkit_installation_id = '';
4749 }
4750
4751 // Prepare Backup Payload.
4752 $backup_data = array(
4753 'installationId' => $wp_toolkit_installation_id,
4754 'fileName' => isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : '', //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4755 'clobber' => false,
4756 'dropAllDatabaseTables' => false,
4757
4758 );
4759 $backup_data = wp_json_encode( $backup_data );
4760
4761 // Grab list of WP Toolkit installations.
4762 $wp_toolkit_backup_response = static::call_cpanel_api_json( 'POST', '/3rdparty/wpt/index.php/v1/features/backups/restorer', $cpanel_baseurl, $cpanel_username, $cpanel_password, $backup_data );
4763 $wp_toolkit_backup_response_decoded = json_decode( $wp_toolkit_backup_response['response'] );
4764
4765 if ( '201' !== $wp_toolkit_backup_response['httpCode'] && '200' !== $wp_toolkit_backup_response['httpCode'] && '204' !== $wp_toolkit_backup_response['httpCode'] ) {
4766 $error = $wp_toolkit_backup_response_decoded->meta->message;
4767 wp_die( esc_html( $error ) );
4768 } else {
4769 wp_send_json( 'true' );
4770 }
4771
4772 if ( $ret_val ) {
4773 return $wp_toolkit_backup_response;
4774 }
4775 }
4776
4777 /**
4778 *
4779 * Plesk: Action delete backup.
4780 *
4781 * Delete Plesk Backup.
4782 *
4783 * @return void
4784 */
4785 public static function cpanel_action_delete_wptk_backup() { //phpcs:ignore -- NOSONAR - complex.
4786
4787 // Grab website_id & backup_api name from Ajax post.
4788 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4789 // Grab $_POST data.
4790 $backup_name = isset( $_POST['backup_name'] ) ? wp_unslash( $_POST['backup_name'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4791 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended
4792 }
4793
4794 // Authenticate cPanel account.
4795 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4796 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4797 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4798 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4799
4800 // Grab Child Site options array.
4801 $website = Api_Backups_Helper::get_website_by_id( $website_id );
4802
4803 // Grab website url & trim trailing slash.
4804 $website_url = trim( $website['url'], '/' );
4805
4806 $wp_toolkit_installation_id = '';
4807
4808 // Grab list of WP Toolkit installations.
4809 $wp_toolkit_installation_list = static::call_cpanel_api( 'GET', static::get_3rdparty_installation_path( 'with_sort' ), $cpanel_baseurl, $cpanel_username, $cpanel_password );
4810 $wp_toolkit_installation_list_decoded = json_decode( $wp_toolkit_installation_list['response'] );
4811
4812 if ( '201' !== $wp_toolkit_installation_list['httpCode'] && '200' !== $wp_toolkit_installation_list['httpCode'] && '204' !== $wp_toolkit_installation_list['httpCode'] ) {
4813 $error = $wp_toolkit_installation_list_decoded->meta->message;
4814 wp_die( esc_html( $error ) );
4815 } elseif ( is_array( $wp_toolkit_installation_list_decoded ) ) {
4816 foreach ( $wp_toolkit_installation_list_decoded as $site ) {
4817 if ( $site->url === $website_url ) {
4818 $wp_toolkit_installation_id = $site->id;
4819 }
4820 }
4821 }
4822
4823 $backup_data = wp_json_encode(
4824 array(
4825 'delete' => true,
4826 )
4827 );
4828
4829 /**
4830 * Payload for deleting a backup.
4831 * plesk_baseurl must include the port number.
4832 * https://{plesk_baseurl:8443}/api/modules/wp-toolkit/v1/installations/{plesk_installation_id}/backups?files%5B%5D={backup_name}
4833 * Backup Name Example ( must be urlencoded ): sweet-lovelace.104-207-132-143.plesk.page_site-1__2024-01-12T16_37_25%2B0000.zip
4834 *
4835 * /v1/installations/{installationId}/backups
4836 */
4837 $payload = static::get_3rdparty_installation_path() . $wp_toolkit_installation_id . '/backups?files%5B%5D=' . rawurlencode( $backup_name );
4838
4839 // Send Payload & create backup.
4840 $api_response = static::call_cpanel_api_json( 'DELETE', $payload, $cpanel_baseurl, $cpanel_username, $cpanel_password, $backup_data );
4841 $response_decoded = json_decode( $api_response['response'] );
4842 $errors = $response_decoded->task->errors;
4843
4844 // Return AJAX.
4845 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4846 // Store Last Backup timestamp.
4847 if ( empty( $errors ) && '204' === (string) $api_response['httpCode'] && 'true' === (string) $api_response['status'] ) {
4848 wp_send_json( 'true' );
4849 } else {
4850 wp_die( esc_html( $errors ) );
4851 }
4852 }
4853 }
4854
4855 /**
4856 *
4857 * CPanel: Action refresh available backups.
4858 *
4859 * Save backups to DB for the selected cPanel server.
4860 *
4861 * @return void
4862 */
4863 public function cpanel_action_refresh_available_backups() {
4864
4865 // Authenticate cPanel account.
4866 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4867 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4868 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4869 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4870 $cpanel_site_path = $cpanel_authentication_credentials[0]['cpanel_site_path'];
4871 $website_id = $cpanel_authentication_credentials[0]['website_id'];
4872
4873 // Grab automatic WHM backups.
4874 $api_response = static::call_cpanel_api( 'GET', '/execute/Restore/query_file_info?path=' . $cpanel_site_path . '&exists=1', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4875 $all_backups = $api_response['response'];
4876
4877 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_available_backups', $all_backups );
4878 Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'cpanel_auto' );
4879
4880 // Grab manual account backups.
4881 $manual_backups = static::get_cpanel_manual_account_backups();
4882 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_manual_backups', $manual_backups );
4883
4884 Api_Backups_Utility::save_lasttime_backup( $website_id, $manual_backups, 'cpanel_manual' );
4885
4886 // Grab manual DB backups.
4887 $database_backups = static::get_cpanel_manual_database_backups( $website_id );
4888 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_manual_database_backups', $database_backups );
4889
4890 // Grab WP-Toolkit backups.
4891 $wp_toolkit_enabled = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_wp_toolkit' ) );
4892 $wp_toolkit_enabled = isset( $wp_toolkit_enabled['mainwp_enable_wp_toolkit'] ) ? strtolower( $wp_toolkit_enabled['mainwp_enable_wp_toolkit'] ) : 0;
4893 if ( $wp_toolkit_enabled ) {
4894 $wp_toolkit_backups = static::get_cpanel_wp_toolkit_backups( $website_id );
4895 if ( $wp_toolkit_backups ) {
4896 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_cpanel_wp_toolkit_backups', $wp_toolkit_backups );
4897 Api_Backups_Utility::save_lasttime_backup( $website_id, $wp_toolkit_backups, 'cpanel_wp_toolkit' );
4898 }
4899 }
4900
4901 // Return AJAX.
4902 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4903 // Store Last Backup timestamp.
4904 if ( 'true' === $api_response['status'] ) {
4905 wp_send_json( 'true' );
4906 } else {
4907 wp_die( 'false' );
4908 }
4909 }
4910 }
4911
4912 /**
4913 *
4914 * CPanel: Action restore selected backup.
4915 *
4916 * @return void
4917 */
4918 public function cpanel_action_restore_backup() {
4919
4920 Api_Backups_Helper::security_nonce( 'cpanel_action_restore_backup' );
4921
4922 // Authenticate cPanel account.
4923 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4924 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4925 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4926 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4927 $cpanel_site_path = $cpanel_authentication_credentials[0]['cpanel_site_path'];
4928
4929 // Grab website_id & backup_api name from Ajax post.
4930 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4931 // Grab $_POST data.
4932 $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4933 }
4934
4935 // Send Payload & create backup.
4936 $api_response = static::call_cpanel_api( 'GET', '/execute/Restore/restore_file?backupID=' . $backup_id . '&path=' . $cpanel_site_path . '&overwrite=1', $cpanel_baseurl, $cpanel_username, $cpanel_password );
4937
4938 // Return AJAX.
4939 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4940 // Store Last Backup timestamp.
4941 if ( '200' === (string) $api_response['httpCode'] ) {
4942 wp_send_json( 'true' );
4943 } else {
4944 wp_die( 'false' );
4945 }
4946 }
4947 }
4948
4949 /**
4950 *
4951 * CPanel: Action restore selected database backup.
4952 *
4953 * @return void
4954 */
4955 public function cpanel_action_restore_database_backup() {
4956
4957 // Authenticate cPanel account.
4958 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4959
4960 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4961 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4962 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
4963
4964 // Grab website_id & backup_api name from Ajax post.
4965 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4966 // Grab $_POST data.
4967 $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4968 $backup_path = isset( $_POST['backup_path'] ) ? wp_unslash( $_POST['backup_path'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
4969 }
4970
4971 $backup_full_path = $backup_path . '/' . $backup_id;
4972
4973 // Send Payload & create backup. https://{host}:{port}/execute/Backup/restore_databases?backup=database_file_name.sql.gz.
4974 $api_response = static::call_cpanel_api( 'POST', '/execute/Backup/restore_databases?backup=' . $backup_full_path, $cpanel_baseurl, $cpanel_username, $cpanel_password );
4975 // Return AJAX.
4976 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
4977 // Store Last Backup timestamp.
4978 if ( '200' === (string) $api_response['httpCode'] ) {
4979 wp_send_json( 'true' );
4980 } else {
4981 wp_die( 'false' );
4982 }
4983 }
4984 }
4985
4986 /**
4987 *
4988 * CPanel: Action restore selected manual backup.
4989 *
4990 * @return void
4991 */
4992 public function cpanel_action_restore_manual_backup() {
4993
4994 // Authenticate cPanel account.
4995 $cpanel_authentication_credentials = static::get_cpanel_authentication_credentials();
4996
4997 $cpanel_baseurl = $cpanel_authentication_credentials[0]['cpanel_baseurl'];
4998 $cpanel_username = $cpanel_authentication_credentials[0]['cpanel_username'];
4999 $cpanel_password = $cpanel_authentication_credentials[0]['cpanel_password'];
5000
5001 // Grab website_id & backup_api name from Ajax post.
5002 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5003 // Grab $_POST data.
5004 $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
5005 $backup_path = isset( $_POST['backup_path'] ) ? wp_unslash( $_POST['backup_path'] ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
5006 }
5007
5008 /**
5009 * Output example for api call.:
5010 * Endpoint: /execute/Backup/restore_files
5011 * Backup file: backup-1.4.2024_17-45-59_cpanel-user.tar.gz
5012 * Backup directory: /home/{cpanel-user}
5013 * Backup full path: /home/{cpanel-user}/backup-1.4.2024_17-45-59_cpanel-user.tar.gz
5014 *
5015 * Https://{host}:{port}/execute/Backup/restore_files?backup=/home/{cpanel-user}/backup-1.4.2024_17-45-59_cpanel-user.tar.gz&directory=/home/{cpanel-user}.
5016 */
5017 $backup_full_path = $backup_path . '/' . $backup_id;
5018 $directory = $backup_path;
5019
5020 // Send Payload & create backup.
5021 $api_response = static::call_cpanel_api( 'POST', '/execute/Backup/restore_files?backup=' . $backup_full_path . '&directory=' . $directory, $cpanel_baseurl, $cpanel_username, $cpanel_password );
5022 $response_decoded = json_decode( $api_response['response'] );
5023 $errors = $response_decoded->errors['0'];
5024
5025 // Return AJAX.
5026 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5027 // Store Last Backup timestamp.
5028 if ( '200' === (string) $api_response['httpCode'] && empty( $errors ) ) {
5029 wp_send_json( 'true' );
5030 } else {
5031 wp_die( 'false' );
5032 }
5033 }
5034 }
5035
5036 /*********************************************************************************
5037 * Kinsta API Methods.
5038 **********************************************************************************/
5039
5040 /**
5041 * Kinsta: action refresh available backups.
5042 *
5043 * Refresh available backups for the selected server.
5044 *
5045 * @return void
5046 */
5047 public function ajax_kinsta_action_refresh_available_backups() {
5048 Api_Backups_Helper::security_nonce( 'kinsta_action_refresh_available_backups' );
5049 static::kinsta_action_refresh_available_backups();
5050 die();
5051 }
5052
5053 /**
5054 * Kinsta: action create backup.
5055 *
5056 * Create backup for the selected server.
5057 *
5058 * @return void
5059 */
5060 public function ajax_kinsta_action_create_backup() {
5061 Api_Backups_Helper::security_nonce( 'kinsta_action_create_backup' );
5062 static::kinsta_action_create_backup();
5063 die();
5064 }
5065
5066 /**
5067 * Kinsta: action delete backup.
5068 *
5069 * Create backup for the selected server.
5070 *
5071 * @return void
5072 */
5073 public function ajax_kinsta_action_delete_backup() {
5074 Api_Backups_Helper::security_nonce( 'kinsta_action_delete_backup' );
5075 static::kinsta_action_delete_backup();
5076 die();
5077 }
5078
5079 /**
5080 * Kinsta: action restore backup.
5081 *
5082 * Restore backup for the selected server.
5083 *
5084 * @return void
5085 */
5086 public function ajax_kinsta_action_restore_backup() {
5087 Api_Backups_Helper::security_nonce( 'kinsta_action_restore_backup' );
5088 static::kinsta_action_restore_backup(); // ajax call.
5089 die();
5090 }
5091
5092 /**
5093 *
5094 * Kinsta: Authentication.
5095 *
5096 * Grab needed authentication credentials for Kinsta API - either from global settings or individual settings.
5097 *
5098 * @param int $website_id Website ID.
5099 *
5100 * @return array
5101 */
5102 public static function get_kinsta_authentication_credentials( $website_id = null ) { //phpcs:ignore -- NOSONAR - complex.
5103
5104 $kinsta_authentication_credentials = array();
5105
5106 // Grab website_id & from Ajax post if $website_id is not set.
5107 if ( empty( $website_id ) ) {
5108 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5109 // Grab : $_POST['data'] submit values.
5110 $website_id = isset( $_POST['website_id'] ) ? intval( $_POST['website_id'] ) : 0; //phpcs:ignore -- nonce verified.
5111 } else {
5112 // Grab : $_GET['data'] from url if not Ajax call.
5113 $website_id = isset( $_GET['id'] ) ? intval( $_GET['id'] ) : 0; //phpcs:ignore -- nonce verified.
5114 }
5115 }
5116
5117 // Global / Individual check.
5118 $global_individual_check = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_enable_kinsta_individual' ) );
5119 $mainwp_enable_kinsta_individual = isset( $global_individual_check['mainwp_enable_kinsta_individual'] ) ? $global_individual_check['mainwp_enable_kinsta_individual'] : '0';
5120
5121 if ( 'on' === $mainwp_enable_kinsta_individual ) {
5122 // Grab cPanel baseurl, username & password.
5123 $kinsta_baseurl = 'https://api.kinsta.com/v2';
5124
5125 // Grab Kinsta password.
5126 $kinsta_api_key = Api_Backups_Utility::get_instance()->get_child_api_key( $website_id, 'kinsta' );
5127
5128 // Grab Kinsta Account Email.
5129 $account_email = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_kinsta_account_email' ) );
5130 $kinsta_account_email = isset( $account_email['mainwp_kinsta_account_email'] ) ? $account_email['mainwp_kinsta_account_email'] : null;
5131
5132 // Grab Kinsta Company ID.
5133 $company_id = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_kinsta_company_id' ) );
5134 $kinsta_company_id = isset( $company_id['mainwp_kinsta_company_id'] ) ? $company_id['mainwp_kinsta_company_id'] : null;
5135
5136 // Grab Kinsta Environment ID.
5137 $environment_id = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_kinsta_environment_id' ) );
5138 $kinsta_environment_id = isset( $environment_id['mainwp_kinsta_environment_id'] ) ? $environment_id['mainwp_kinsta_environment_id'] : null;
5139
5140 } elseif ( '0' === $mainwp_enable_kinsta_individual ) {
5141 // Grab Kinsta baseurl, username & password.
5142 $kinsta_baseurl = 'https://api.kinsta.com/v2';
5143
5144 // Grab Kinsta password.
5145 $kinsta_api_key = static::get_kinsta_api_key();
5146
5147 // Grab Kinsta Account Email.
5148 $kinsta_account_email = get_option( 'mainwp_kinsta_api_account_email' );
5149
5150 // Grab Kinsta Company ID.
5151 $kinsta_company_id = get_option( 'mainwp_kinsta_company_id' );
5152
5153 // Grab Kinsta Environment ID.
5154 $environment_id = Api_Backups_Helper::get_website_options( $website_id, array( 'mainwp_kinsta_environment_id' ) );
5155 $kinsta_environment_id = isset( $environment_id['mainwp_kinsta_environment_id'] ) ? $environment_id['mainwp_kinsta_environment_id'] : null;
5156 }
5157
5158 // Build array.
5159 $kinsta_authentication_credentials[] = array(
5160 'kinsta_baseurl' => $kinsta_baseurl,
5161 'kinsta_api_key' => $kinsta_api_key,
5162 'kinsta_environment_id' => $kinsta_environment_id,
5163 'website_id' => $website_id,
5164 'kinsta_company_id' => $kinsta_company_id,
5165 'kinsta_company_email' => $kinsta_account_email,
5166 );
5167
5168 return $kinsta_authentication_credentials;
5169 }
5170
5171 /**
5172 * Call Kinsta API, Authenticate & perform given method.
5173 *
5174 * @param string $method GET|POST|PUT|DELETE.
5175 * @param string $url API endpoint for the call.
5176 * @param string $baseurl baseurl.
5177 * @param string $api_key Kinsta API Key.
5178 * @param string $action action.
5179 * @param string $backup_data action.
5180 *
5181 * @return array Output from cPanel API.
5182 */
5183 public static function call_kinsta_api( $method, $url, $baseurl, $api_key, $action = '', $backup_data = array() ) {
5184
5185 $curl = curl_init();
5186
5187 $api_Key = $api_key;
5188 curl_setopt_array(
5189 $curl,
5190 array(
5191 CURLOPT_URL => $baseurl . $url,
5192 CURLOPT_RETURNTRANSFER => true,
5193 CURLOPT_ENCODING => '',
5194 CURLOPT_MAXREDIRS => 10,
5195 CURLOPT_TIMEOUT => 0,
5196 CURLOPT_FOLLOWLOCATION => true,
5197 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
5198 CURLOPT_CUSTOMREQUEST => $method,
5199 CURLOPT_POSTFIELDS => $backup_data,
5200 CURLOPT_HTTPHEADER => array(
5201 'Content-Type: application/json',
5202 "Authorization: Bearer $api_Key",
5203 ),
5204 )
5205 );
5206
5207 $resp = curl_exec( $curl );
5208 $httpCode = (string) curl_getinfo( $curl, CURLINFO_HTTP_CODE );
5209
5210 $response['httpCode'] = $httpCode;
5211 $response['response'] = $resp;
5212
5213 if ( '202' !== $httpCode && '200' !== $httpCode ) {
5214 $response['status'] = 'false';
5215 } else {
5216 $response['status'] = 'true';
5217 }
5218
5219 // Log API call.
5220 $payload = "[Status] $httpCode :: [Action] $action :: [EndPoint] $baseurl$url";
5221 $payload_response = "[Status] $httpCode :: [Action] $action :: [Response] $resp";
5222 Api_Backups_Utility::log_debug( $payload );
5223 Api_Backups_Utility::log_debug( $payload_response );
5224
5225 curl_close( $curl );
5226 return $response;
5227 }
5228
5229 /**
5230 *
5231 * Kinsta: Action get User ID.
5232 *
5233 * Get the User Id from the given Company ID & Email address.
5234 *
5235 * @return array
5236 */
5237 public static function kinsta_action_get_user_id() {
5238
5239 // Authenticate kinsta account.
5240 $kinsta_authentication_credentials = static::get_kinsta_authentication_credentials();
5241 $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5242 $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5243 $kinsta_company_id = $kinsta_authentication_credentials[0]['kinsta_company_id'];
5244 $kinsta_company_email = $kinsta_authentication_credentials[0]['kinsta_company_email'];
5245
5246 $payload_url = '/company/' . $kinsta_company_id . '/users';
5247
5248 // Send Payload.
5249 $api_response = static::call_kinsta_api( 'GET', $payload_url, $kinsta_baseurl, $kinsta_api_key, '' );
5250
5251 // Decode Response.
5252 $response = json_decode( $api_response['response'] );
5253 $company = $response->company;
5254 $company_users = $company->users;
5255
5256 // Grab correct user ID.
5257 foreach ( $company_users as $user ) {
5258 if ( $kinsta_company_email === $user->user->email ) {
5259 $user_id = $user->user->id;
5260 }
5261 }
5262
5263 // Return user id.
5264 return $user_id;
5265 }
5266
5267 /**
5268 *
5269 * Kinsta: Action refresh available backups.
5270 *
5271 * Save backups to DB for the selected server.
5272 *
5273 * @param array $credentials Kinsta credentials.
5274 * @param bool $return_result Return or not.
5275 *
5276 * @return mixed
5277 */
5278 public static function kinsta_action_refresh_available_backups( $credentials = array(), $return_result = false ) {
5279
5280 // Authenticate kinsta account.
5281 $kinsta_authentication_credentials = empty( $credentials ) || ! is_array( $credentials ) ? static::get_kinsta_authentication_credentials() : $credentials;
5282 $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5283 $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5284 $kinsta_env_id = $kinsta_authentication_credentials[0]['kinsta_environment_id'];
5285 $website_id = $kinsta_authentication_credentials[0]['website_id'];
5286 $downloadable_backups = '';
5287
5288 $action = 'kinsta_action_refresh_available_backups';
5289
5290 // Grab backup meta.
5291 $api_response = static::call_kinsta_api( 'GET', '/sites/environments/' . $kinsta_env_id . '/backups', $kinsta_baseurl, $kinsta_api_key, $action );
5292
5293 $success = false;
5294
5295 if ( 'true' === $api_response['status'] ) {
5296 $all_backups = $api_response['response'];
5297 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_kinsta_available_backups', $all_backups );
5298 Api_Backups_Utility::save_lasttime_backup( $website_id, $all_backups, 'kinsta' );
5299
5300 $action = 'kinsta_action_refresh_available_backups_downloadable';
5301
5302 $downloadable_backups = static::call_kinsta_api( 'GET', '/sites/environments/' . $kinsta_env_id . '/downloadable-backups', $kinsta_baseurl, $kinsta_api_key, $action );
5303 $success = true;
5304 } else {
5305 Api_Backups_Utility::log_debug( 'Kinsta API Error: ' . $api_response['response'] );
5306 }
5307 if ( $downloadable_backups ) {
5308 if ( 'true' === $downloadable_backups['status'] ) {
5309 $downloadable_backups = $downloadable_backups['response'];
5310 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_kinsta_downloadable_backups', $downloadable_backups );
5311 }
5312 } else {
5313 Api_Backups_Utility::log_debug( 'Kinsta API Error: There was an issue while refreshing available backups.' );
5314 }
5315
5316 if ( $return_result ) {
5317 return $success;
5318 }
5319
5320 // Return AJAX.
5321 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5322 // Store Last Backup timestamp.
5323 if ( 'true' === $api_response['status'] ) {
5324 wp_send_json( 'true' );
5325 } else {
5326 wp_die( 'false' );
5327 }
5328 }
5329 }
5330
5331 /**
5332 *
5333 * Kinsta: Action create manual backup.
5334 *
5335 * Create a Plesk Backup.
5336 *
5337 * @param bool $resturn_values resturn values.
5338 * @param int $site_id website id.
5339 *
5340 * @return mixed result.
5341 */
5342 public static function kinsta_action_create_backup( $resturn_values = false, $site_id = null ) {
5343
5344 // Authenticate kinsta account.
5345 $kinsta_authentication_credentials = static::get_kinsta_authentication_credentials( $site_id );
5346 $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5347 $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5348 $kinsta_env_id = $kinsta_authentication_credentials[0]['kinsta_environment_id'];
5349 $website_id = $kinsta_authentication_credentials[0]['website_id'];
5350
5351 // Grab Child Site options.
5352 $website = Api_Backups_Helper::get_website_by_id( $website_id );
5353
5354 // Prepare Backup Payload.
5355 $backup_data = array(
5356 'tag' => 'MainWP API Backups - ' . $website['name'],
5357 );
5358 $backup_data = wp_json_encode( $backup_data );
5359
5360 // Send Payload & create backup.
5361 $api_response = static::call_kinsta_api( 'POST', '/sites/environments/' . $kinsta_env_id . '/manual-backups', $kinsta_baseurl, $kinsta_api_key, $backup_data );
5362
5363 if ( is_array( $api_response ) && isset( $api_response['status'] ) && 'true' === $api_response['status'] ) {
5364 // Save Timestamp.
5365 $local_time = current_datetime();
5366 $current_time = $local_time->getTimestamp() + $local_time->getOffset();
5367 Api_Backups_Helper::update_website_option( $website_id, 'mainwp_3rd_party_kinsta_last_backup', $current_time );
5368 }
5369
5370 if ( $resturn_values ) {
5371 return $api_response;
5372 }
5373
5374 // Return AJAX.
5375 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5376 // Store Last Backup timestamp.
5377 if ( 'true' === $api_response['status'] ) {
5378 wp_send_json( 'true' );
5379 } else {
5380 wp_die( 'false' );
5381 }
5382 }
5383 }
5384
5385 /**
5386 *
5387 * Kinsta: Action create manual backup.
5388 *
5389 * Create a Plesk Backup.
5390 *
5391 * @param bool $return_values return values.
5392 *
5393 * @return array
5394 */
5395 public static function kinsta_action_delete_backup( $return_values = false ) {
5396
5397 $backup_id = isset( $_POST['backup_id'] ) ? wp_unslash( $_POST['backup_id'] ) : ''; //phpcs:ignore -- nonce verified.
5398
5399 // Authenticate kinsta account.
5400 $kinsta_authentication_credentials = static::get_kinsta_authentication_credentials();
5401 $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5402 $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5403
5404 $payload_url = '/sites/environments/backups/' . $backup_id;
5405
5406 // Send Payload & create backup.
5407 $api_response = static::call_kinsta_api( 'DELETE', $payload_url, $kinsta_baseurl, $kinsta_api_key, '' );
5408
5409 if ( is_array( $api_response ) && isset( $api_response['status'] ) && 'true' === $api_response['status'] ) {
5410 static::kinsta_action_refresh_available_backups( $kinsta_authentication_credentials, true );
5411 }
5412
5413 if ( $return_values ) {
5414 return $api_response;
5415 }
5416
5417 // Return AJAX.
5418 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5419 // Store Last Backup timestamp.
5420 if ( 'true' === $api_response['status'] ) {
5421 wp_send_json( 'true' );
5422 } else {
5423 wp_die( 'false' );
5424 }
5425 }
5426 }
5427
5428 /**
5429 *
5430 * Kinsta: Action restore manual backup.
5431 *
5432 * Restore a selected Backup.
5433 *
5434 * @param bool $return_values return or not.
5435 *
5436 * @return array
5437 */
5438 public static function kinsta_action_restore_backup( $return_values = false ) {
5439
5440 $backup_id = isset( $_POST['backup_id'] ) ? intval( $_POST['backup_id'] ) : 0; //phpcs:ignore -- nonce verified.
5441
5442 // Authenticate kinsta account.
5443 $kinsta_authentication_credentials = static::get_kinsta_authentication_credentials();
5444 $kinsta_baseurl = $kinsta_authentication_credentials[0]['kinsta_baseurl'];
5445 $kinsta_api_key = $kinsta_authentication_credentials[0]['kinsta_api_key'];
5446 $kinsta_env_id = $kinsta_authentication_credentials[0]['kinsta_environment_id'];
5447
5448 $company_user_id = static::kinsta_action_get_user_id();
5449
5450 $payload_url = '/sites/environments/' . $kinsta_env_id . '/backups/restore';
5451
5452 // Prepare Backup Payload.
5453 $backup_data = array(
5454 'backup_id' => $backup_id,
5455 'notified_user_id' => $company_user_id,
5456 );
5457 $backup_data = wp_json_encode( $backup_data );
5458
5459 // Send Payload & create backup.
5460 $api_response = static::call_kinsta_api( 'POST', $payload_url, $kinsta_baseurl, $kinsta_api_key, '', $backup_data );
5461
5462 if ( $return_values ) {
5463 return $api_response;
5464 }
5465
5466 // Return AJAX.
5467 if ( is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
5468 // Store Last Backup timestamp.
5469 if ( 'true' === $api_response['status'] ) {
5470 wp_send_json( 'true' );
5471 } else {
5472 wp_die( 'false' );
5473 }
5474 }
5475 }
5476
5477 // END class MainWP_3rdParty_Backup.
5478 }
5479