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

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

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